2016-06-28 2 views
1

У меня есть этот код, который работает под KEIL, но не под GCC, и я не знаю, почему это происходит. Он тестирует некоторые функциональные возможности RTX OS.Почему моя программа не вводит режим обработчика в GCC?

Handler:

void GenWait_IRQHandler (void) { 

    switch (ISR_ExNum) { 
    case 0: Stat_Isr = osDelay (10); break; 
    #if (osFeatureWait) 
    case 1: Stat_Isr = osWait (10); break; 
    #endif 
    } 
} 

Приведенный выше код вводится путем установки отложенного IRQ от основной:

... 
ISR_ExNum = 0; /* Test: osDelay */ 
NVIC_SetPendingIRQ((IRQn_Type)SWI_HANDLER); 
ASSERT_TRUE (Stat_Isr == osErrorISR); 
... 

Проблема заключается в том, что это ASSERT_TRUE() терпит неудачу, потому что Stat_Isr не равна osErrorISR, которые она должна быть поскольку в режиме обработчика не разрешается звонить osDelay():

osStatus osDelay (uint32_t millisec) { 
    if (__get_IPSR() != 0U) { 
    return osErrorISR;       // Not allowed in ISR 
    } 
    return __svcDelay(millisec); 
} 

Как я уже говорил, при компиляции под KEIL он отлично работает, но при компиляции под GCC он терпит неудачу. Похоже, что IPSR не обновляется при вводе обработчика, и osDelay() не знает, что он должен возвращать ошибку. Любая идея, почему это происходит?

SWI_Handler - это программный обработчик, и я звоню в GenWait_IRQHandler().

EDIT:

Это реализация доступна из KEIL пакетов в качестве проверки RTX, я просто пытаюсь заставить его работать на чипе, я работаю с. Поэтому он должен работать, даже если я вызываю функции из ISR.

Кроме того, как я написал в комментарии:

(от www.keil.com):

обслуживания прерываний (ISR) можно назвать некоторые функции CMSIS-RTOS. Когда функция CMSIS-RTOS не может быть вызвана из контекста ISR, она отклоняет вызов.

И потом:

Функции, которые не могут быть вызваны из ISR проверяемая статуса прерывания и возврата, в случае, если они вызываются из контекста ISR, код состояния osErrorISR. В некоторых реализациях это условие может быть захвачено с использованием вектора HARD FAULT.

EDIT2:

Снижение оптимизации от -O3 до -O1 фиксированной ISSE, но я до сих пор не знаю, почему она была оптимизирована, как это и как я могу легко предотвратить компилятор от делать это. Я знаю, что самый простой ответ - добавить пару «volatile», но это не так просто в этом случае, я думаю.

+3

Вы уверены, что безопасно вызывать функции OS в обработчике прерываний? – EOF

+0

Я уверен, что это так, как я ожидаю, что он вернет ошибку. –

+1

Ищите различия в сборке, сгенерированной компиляторами. Являются ли 'ISR_ExNum' и' Stat_Isr' объявленными как изменчивые? Оптимизация компилятора отключена для обеих цепочек инструментов? – kkrambo

ответ

1

Спасибо @kkrambo за правильный след. Проблема заключалась в заказе инструкций. Добавление летучих веществ в Stat_Isr не было достаточно, но с добавлением барьера памяти сделал эту работу для меня:

... 
ISR_ExNum = 0; /* Test: osDelay */ 
NVIC_SetPendingIRQ((IRQn_Type)SWI_HANDLER); 
__DMB(); 
ASSERT_TRUE (Stat_Isr == osErrorISR); 
... 

Это случилось потому, что код оптимализация сделал ISR называться после ASSERT_TRUE (Stat_Isr == osErrorISR);. Я думаю, теперь это ясно.

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