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 ; }
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.