Я хочу использовать функции переполнения, сравнения совпадений и захвата таймера общего назначения на ST2M32F103REY Cortex M3 одновременно. CC1 сконфигурирован как сравнение, и CC3 сконфигурирован как захват. Обработчик IRQ выглядит следующим образом:Атомный доступ к периферийным регистрам ARM
void TIM3_IRQHandler(void) {
if(TIM3->SR & TIM_SR_UIF){
TIM3->SR &= ~TIM_SR_UIF;
// do something on overflow
}
if(TIM3->SR & TIM_SR_CC1IF) {
TIM3->SR &= ~TIM_SR_CC1IF;
// do something on compare match
}
if(TIM3->SR & TIM_SR_CC3IF) {
TIM3->SR &= ~TIM_SR_CC3IF;
// do something on capture
}
}
В принципе, он работает хорошо, но иногда он пропускает часть. Моя теория заключается в том, что это происходит потому, что операции сброса флагов IRQ, например, TIM3->SR &= ~TIM_SR_UIF
, не является атомарным *, поэтому может случиться так, что, например, TIM_SR_CC1IF, возникающий между загрузкой и хранением, перезаписывается.
* Разборка команды выглядит следующим образом
8012e02: 8a13 ldrh r3, [r2, #16]
8012e06: f023 0301 bic.w r3, r3, #1
8012e0a: 041b lsls r3, r3, #16
8012e0c: 0c1b lsrs r3, r3, #16
8012e0e: 8213 strh r3, [r2, #16]
- ли это правдоподобно? Может ли содержимое регистра TIM3-> SR меняться во время выполнения обработчика IRQ?
- Есть ли возможность сделать атомное чтение и запись в регистр TIM3-> SR?
- Есть ли другое подходящее решение?
Кстати, There is similar question, но это касается защиты доступа несколькими процессами или ядрами, а не защиты одновременного доступа к программному и аппаратным средствам.
Весьма вероятно, что последовательность не является атомарной. Почему бы вам просто отключить прерывания во время чтения-изменения-записи периферийного регистра? – EOF
На самом деле не существует одновременных прерываний, так как мы находимся в обработчике IRQ (учитывая, что нет более высоких приоритетов), поэтому нет проблем с одновременной записью программного обеспечения в регистр. Однако регистр SR также записывается аппаратными средствами, поэтому я бы сказал, что прерывание прерывания не помогло бы. – koalo