I'm using a USB stack (libusb_stm32) on an STM32F103 for learning. In this stack, when data arrives from the host PC, a callback in the USB ISR** runs a function of mine to put the data into my queue. In this function of mine I have disabled interrupts, but I do NOT think I need to. Is this a correct assumption?
What surprises me here, is that old_primask is 0. Maybe I'm confused, but I expected in an ISR it would be 1. It does become 1 once __disable_irq() runs.
void Enqueue_Callback(uint8_t bytefromhost) { uint32_t old_primask; // don't need? VECTACTIVE is 0x24 old_primask = __get_PRIMASK(); // don't need? old primask was 0x0000 0000 __disable_irq(); // don't need? primask becomes 0x0000 0001 myenqueue(bytefromhost); // I have shared vars in here (counter). __set_PRIMASK( old_primask ); // don't need? }
On the flip side I believe that I DO need to disable interrupts so that the USB interrupt can't interfere with my dequeueing. Is that correct? Here is that side:
bool Dequeue(uint8_t *ch_ptr) { uint32_t old_primask; // VECTACTIVE is 0x00 old_primask = __get_PRIMASK(); // old primask is 0x0000 0000 __disable_irq(); // becomes 0x0000 0001 if( thereisdata() ) // <pseudocode> { mydequeue(ch_ptr); // I have shared vars in here (count). __set_PRIMASK( old_primask ); return 0; } __set_PRIMASK( old_primask ); return 1; }
** I verified that the callback happens at ISR level using this:
// Q. How to safely detect if a function is called from an ISR? // A. You need to test the VECTACTIVE field of the Interrupt Control State Register. inline bool isInterrupt(void) { return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0 ; }
Thank you. I am trying to "flatten out" my project interrupt-wise as I am just learning, so I DON"T want interrupts being interrupted. I will remove the disable code from my callback invoked in the "handler level" USB ISR.
Is the method to disable interrupts globally in my main line ("thread level") Dequeue() OK?
Yes. This should disable any interrupt that has a user definable priority level.
Thank you.