2016-12-19 3 views
1

Я хочу использовать функции переполнения, сравнения совпадений и захвата таймера общего назначения на 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, но это касается защиты доступа несколькими процессами или ядрами, а не защиты одновременного доступа к программному и аппаратным средствам.

+0

Весьма вероятно, что последовательность не является атомарной. Почему бы вам просто отключить прерывания во время чтения-изменения-записи периферийного регистра? – EOF

+0

На самом деле не существует одновременных прерываний, так как мы находимся в обработчике IRQ (учитывая, что нет более высоких приоритетов), поэтому нет проблем с одновременной записью программного обеспечения в регистр. Однако регистр SR также записывается аппаратными средствами, поэтому я бы сказал, что прерывание прерывания не помогло бы. – koalo

ответ

2

Раздел 15.4.5 из reference manual (CD00171190) утверждает, что все биты в TIMx->SR работы в rc_w0 режиме (или зарезервированы).

Согласно programming manual (PM0056):

чтения/ясно (rc_w0): Программное обеспечение может читать, а также ясно, что этот бит записью 0. Запись «1» не оказывает никакого влияния на значение бита.

Это означает, что вы можете упростить свой код, чтобы полностью избежать цикла чтения-изменения-записи, а вместо этого просто используйте TIM3->SR = ~TIM_SR_UIF.

Многие заметки приложения используют чтение-изменение-запись для очистки прерываний, например, примеры от Keil, но это необязательно и потенциально опасно, как вы уже испытали. В примечании к применению ST DM00236305 (раздел 1.3.2) используется только операция записи.

Однако следует отметить, что при работе с NVIC, регистр используется для сброса является rc_w1.

+0

Это действительно работает, и ошибка, похоже, исчезла! Большое спасибо! – koalo

Смежные вопросы