У меня есть такой код: (очень упрощенный код)
// This is code for Microchip 8-bit microcontroller, XC8 compiler (GCC based)
#define TIMER_COUNT 8;
volatile uint16_t timer_values[TIMER_COUNT];
volatile uint16_t timer_max_values[TIMER_COUNT];
// executes every 100ms
void timer1_interrupt_handler()
{
for (uint8_t i = 0; i < TIMER_COUNT ; i++){
timer_values[i];
}
}
void main(){
// (...) some initialization, peripherial and interrupt handler setup
while(1){
for (uint8_t i = 0; i < TIMER_COUNT ; i++) {
// what if interrupt happens in the middle of comparison?
if (timer_values[i] >= timer_max_values[i])
{
timer_values[i] = 0; // reset timer
executeTimerElapsedAction(i);
}
}
}
}
Проблема в том, что это 8-битный микроконтроллер, и когда прерывание происходит в середине неатомарной операции с 16-битной переменной:
timer_values[i] >= timer_max_values[i]
или это:
timer_values[i] = 0;
возможно, что половина uint16_t будет переписана обработчиком прерываний, и все испорчено.
Это не ОСРВ, поэтому у меня нет встроенных блокировок.
Что я могу сделать? Как сделать замок с нуля?
Я думал о создании "критической секции", подобной этой:
GlobalInterruptsDisable(); // enter critical section
if (timer_values[i] >= timer_max_values[i])
{
timer_values[i] = 0; // reset timer
GlobalInterruptsEnable(); // exit critical section
executeTimerElapsedAction(i);
}
но Боюсь, что пока что я пропущу некоторые прерывания (я использую 2 таймера, 2 прерывания UART и прерывания I2C), и что-то еще может испортиться.
Дополнительный вопрос:
Если я отключу прерывания примерно на 20-30 тактов процессора, а затем некоторые данные поступят в UART - я пропущу эти данные, или обработчик прерываний будет выполняться позже после включения прерываний?