Add memory barrier, optimal interrupt on-off
Disabling an ISR on ARM has 3 instructions of latency. A Memory barrier is REQUIRED to ensure proper and predictable disabling. Memory barriers are expensive, so avoid disabling if already disabled (See https://mcuoneclipse.com/2015/10/16/nvic-disabling-interrupts-on-arm-cortex-m-and-the-need-for-a-memory-barrier-instruction/)
This commit is contained in:
@ -143,6 +143,11 @@ FORCE_INLINE static void HAL_timer_disable_interrupt(const uint8_t timer_num) {
|
||||
case 0: NVIC_DisableIRQ(TIMER0_IRQn); // Disable interrupt handler
|
||||
case 1: NVIC_DisableIRQ(TIMER1_IRQn); // Disable interrupt handler
|
||||
}
|
||||
|
||||
// We NEED memory barriers to ensure Interrupts are actually disabled!
|
||||
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
|
||||
__DSB();
|
||||
__ISB();
|
||||
}
|
||||
|
||||
// This function is missing from CMSIS
|
||||
|
@ -258,6 +258,11 @@ bool LPC1768_PWM_attach_pin(pin_t pin, uint32_t min /* = 1 */, uint32_t max /* =
|
||||
// OK to update the active table because the
|
||||
// ISR doesn't use any of the changed items
|
||||
|
||||
// We NEED memory barriers to ensure Interrupts are actually disabled!
|
||||
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
if (ISR_table_update) //use work table if that's the newest
|
||||
temp_table = work_table;
|
||||
else
|
||||
@ -342,6 +347,11 @@ bool LPC1768_PWM_detach_pin(pin_t pin) {
|
||||
//// interrupt controlled PWM code
|
||||
NVIC_DisableIRQ(HAL_PWM_TIMER_IRQn);
|
||||
|
||||
// We NEED memory barriers to ensure Interrupts are actually disabled!
|
||||
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
if (ISR_table_update) {
|
||||
ISR_table_update = false; // don't update yet - have another update to do
|
||||
NVIC_EnableIRQ(HAL_PWM_TIMER_IRQn); // re-enable PWM interrupts
|
||||
@ -428,6 +438,12 @@ bool LPC1768_PWM_write(pin_t pin, uint32_t value) {
|
||||
|
||||
//// interrupt controlled PWM code
|
||||
NVIC_DisableIRQ(HAL_PWM_TIMER_IRQn);
|
||||
|
||||
// We NEED memory barriers to ensure Interrupts are actually disabled!
|
||||
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
if (!ISR_table_update) // use the most up to date table
|
||||
COPY_ACTIVE_TABLE; // copy active table into work table
|
||||
|
||||
@ -456,6 +472,11 @@ bool useable_hardware_PWM(pin_t pin) {
|
||||
|
||||
NVIC_DisableIRQ(HAL_PWM_TIMER_IRQn);
|
||||
|
||||
// We NEED memory barriers to ensure Interrupts are actually disabled!
|
||||
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
bool return_flag = false;
|
||||
for (uint8_t i = 0; i < NUM_ISR_PWMS; i++) // see if it's already setup
|
||||
if (active_table[i].pin == pin) return_flag = true;
|
||||
|
Reference in New Issue
Block a user