grv 0 14 января, 2016 Опубликовано 14 января, 2016 (изменено) · Жалоба Есть довольно увесистый проект stm32f207+freertos 8.0.1+Keil 4.6 Вылетает в bus fault. Причем только после того как начинаю включать вложенные прерывания. Пока все прерывания сидят в приоритете 15(Тик ртоса и мои таймера/уарты) работает нормально. Как только любому из моих прерываний даю приоритет 14(вывел на джампер GPIOE->IDR & Key_K1) либо всем, сразу валится в эксепшин, причем не сразу а через 5-10 мин как "звезды станут в ряд" Дошел до следующего, в процедуре xPortPendSVHandler в pxCurrentTCB после переключения контекста попадает NULL, далее подтягивается с нулевого адреса начальное значение стека MSP вместо стека задачи, и при попытке восстановить стек задачи с адреса 0x20020000 валится в BUS FAULT (это я спецом под стек выделил все оставшееся ОЗУ, до этого валилось в USAGE FAULT когда восстанавливало стек из неиспользуемого места ОЗУ) __asm void xPortPendSVHandler( void ) { extern uxCriticalNesting; extern pxCurrentTCB; extern vTaskSwitchContext; PRESERVE8 mrs r0, psp isb ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */ ldr r2, [r3] stmdb r0!, {r4-r11} /* Save the remaining registers. */ str r0, [r2] /* Save the new top of stack into the first member of the TCB. */ stmdb sp!, {r3, r14} mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY msr basepri, r0 bl vTaskSwitchContext mov r0, #0 msr basepri, r0 ldmia sp!, {r3, r14} ldr r1, [r3] ; ***************my start cmp R1,#0 bne l22 nop;-------------------------------------------------------- Здесь поставил бреакпоинт nop l22 ; ***************my finish ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ ;----------------Вылетает при следующей команде ; R0=0x20020000 - следующий адрес за внутренним ОЗУ ldmia r0!, {r4-r11} /* Pop the registers and the critical nesting count. */ msr psp, r0 isb bx r14 nop } Настройка прерываний При старте до старта ртоса RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); // 4 preeptive 4 subpriority #define configKERNEL_INTERRUPT_PRIORITY 255 #define configMAX_SYSCALL_INTERRUPT_PRIORITY 191 /* equivalent to 0xb0, or priority 11. */ #define configLIBRARY_KERNEL_INTERRUPT_PRIORITY 15 Конфигурация таймера(ов) Используются как внешние прерывания по уровню. void Tim9_IT_init (void) { TIM_TimeBaseInitTypeDef timStruct; TIM_ICInitTypeDef timicStruct; NVIC_InitTypeDef nvicStructure; // Alternative function GPIOE->AFR[0] &= ~(GPIO_AFRL_AFRL6 ); GPIOE->AFR[0] |= ((GPIO_AFRL_AFRL6 & 0x33333333) ); // PE6 - AF3 GPIOE->MODER&=~GPIO_MODER_MODER6; GPIOE->MODER|=GPIO_MODER_MODER6_1; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9, ENABLE); timStruct.TIM_Prescaler=0; timStruct.TIM_CounterMode=TIM_CounterMode_Up; timStruct.TIM_Period=10; timStruct.TIM_ClockDivision=TIM_CKD_DIV1; timStruct.TIM_RepetitionCounter=0; // doesn't matter TIM_TimeBaseInit(TIM9, &timStruct); // Gated mode //timicStruct.TIM_Channel=TIM_Channel_1; timicStruct.TIM_Channel=TIM_Channel_2; timicStruct.TIM_ICPolarity=TIM_ICPolarity_Falling; timicStruct.TIM_ICSelection=TIM_ICSelection_DirectTI; timicStruct.TIM_ICPrescaler=TIM_ICPSC_DIV1; timicStruct.TIM_ICFilter=0; TIM_ICInit(TIM9,&timicStruct); //TIM_SelectInputTrigger(TIM9,TIM_TS_TI1FP1); TIM_SelectInputTrigger(TIM9,TIM_TS_TI2FP2); TIM_SelectSlaveMode(TIM9,TIM_SlaveMode_Gated); //5. Enable the corresponding interrupt using the function TIM_ITConfig(TIMx, TIM_IT_Update) // TIM_ClearITPendingBit(TIM4,TIM_IT_Update); // TIM_ITConfig(TIM4, TIM_IT_Update,ENABLE); // interrupt //4. Enable the NVIC if you need to generate the update interrupt. nvicStructure.NVIC_IRQChannel = TIM1_BRK_TIM9_IRQn; if (GPIOE->IDR & Key_K1) { nvicStructure.NVIC_IRQChannelPreemptionPriority = 15; } else { nvicStructure.NVIC_IRQChannelPreemptionPriority = 14; } nvicStructure.NVIC_IRQChannelSubPriority = 0; nvicStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&nvicStructure); //6. Call the TIM_Cmd(ENABLE) function to enable the TIM counter. TIM_Cmd(TIM9,ENABLE); } Стеки задач с запасом где то минимум на 50 байт (видно по статистике когда нет вложенных прерываний, проект живет сутками) Стек MSP вообще сейчас вся оставшаяся память - 7кб Куча стартапа - 1кб, но я так понимаю она используется только при либовских Malloc которую я не использую. Вместо них я использую ртосовскую, там где то свободных 10кб. Собственно вопрос , что теперь с этим делать и куда рыть ? Каким образом в pxCurrentTCB может попасть 0 ? В моем понимании если даже все мои задачи в ожидании , должна крутиться Idle ? Изменено 14 января, 2016 пользователем grv Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SMaster 0 15 января, 2016 Опубликовано 15 января, 2016 · Жалоба Я думаю, что с этим у вас все правильно, но все же на всякий случай: все обработчики прерываний, вызывающие API-шные функции операционки, используют специализированные функции с окончанием FromISR()? Все такие функции имеют приоритет 11 и выше (численно)? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
grv 0 21 января, 2016 Опубликовано 21 января, 2016 (изменено) · Жалоба Я думаю, что с этим у вас все правильно, но все же на всякий случай: все обработчики прерываний, вызывающие API-шные функции операционки, используют специализированные функции с окончанием FromISR()? Все такие функции имеют приоритет 11 и выше (численно)? Вроде разобрался. Ситуация конечно плачевная, суть в следующем: Грабли таятся в Trace. При определении в настойках USE_PRIMASK_CS 0 в прерываниях в теле функций типа xSemaphoreGiveFromISR() используются макросы portENTER_CRITICAL/ portEXIT_CRITICAL чего делать категорически нельзя. Этими макросами трейс защищает свою критическую секцию. Но при выходе из portEXIT_CRITICAL мы гарантированно имеем BASEPRI=0, и в далее идущую часть критического кода xSemaphoreGiveFromISR врезается высокоприоритетное прерывание что у меня приводило к повреждениям списков задач и далее вылетало в BUSFAULT. Когда не было вложенных прерываний естественно все классно работало. #if ((SELECTED_PORT == PORT_ARM_CortexM) && (USE_PRIMASK_CS == 1)) #define TRACE_SR_ALLOC_CRITICAL_SECTION() int __irq_status; #define TRACE_ENTER_CRITICAL_SECTION() { __irq_status = prvTraceGetIRQMask(); prvTraceDisableIRQ(); } #define TRACE_EXIT_CRITICAL_SECTION() { prvTraceSetIRQMask(__irq_status); } #define trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY trcCRITICAL_SECTION_BEGIN #define trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY trcCRITICAL_SECTION_END #else #define TRACE_ENTER_CRITICAL_SECTION() portENTER_CRITICAL() #define TRACE_EXIT_CRITICAL_SECTION() portEXIT_CRITICAL() #define trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY() recorder_busy++; #define trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY() recorder_busy--; #endif Ставить USE_PRIMASK_CS 1 это с пушки по воробьям, теряется тогда идея "всегда разрешенных прерываний" приоритетом выше MAXSYSCALL Пока поставил так (изменил вариант для USE_PRIMASK_CS 1), грабли ушли: #if ((SELECTED_PORT == PORT_ARM_CortexM) && (USE_PRIMASK_CS == 1)) #define TRACE_SR_ALLOC_CRITICAL_SECTION() int __irq_status; //#define TRACE_ENTER_CRITICAL_SECTION() { __irq_status = prvTraceGetIRQMask(); prvTraceDisableIRQ(); } #define TRACE_ENTER_CRITICAL_SECTION() { __irq_status = portSET_INTERRUPT_MASK_FROM_ISR(); } //#define TRACE_EXIT_CRITICAL_SECTION() { prvTraceSetIRQMask(__irq_status); } #define TRACE_EXIT_CRITICAL_SECTION() { portCLEAR_INTERRUPT_MASK_FROM_ISR(__irq_status); } #define trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY trcCRITICAL_SECTION_BEGIN #define trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY trcCRITICAL_SECTION_END #else #define TRACE_ENTER_CRITICAL_SECTION() portENTER_CRITICAL() #define TRACE_EXIT_CRITICAL_SECTION() portEXIT_CRITICAL() #define trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY() recorder_busy++; #define trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY() recorder_busy--; #endif Одно хорошо, за неделю ковыряний нашел у себя небольшую тележку багов по-меньше и перешел на advanced level в части понимания как FREERTOS все-таки работает Изменено 21 января, 2016 пользователем grv Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Andrey75 0 18 октября, 2016 Опубликовано 18 октября, 2016 · Жалоба Здравствуйте У меня похоже такая же проблема. FreeRTOS 9.0. Если прерывания идут друг за другом, то всё работает. Как только появляется вложенное прерывание то происходит вылет. Иногда не вылет но теряются семафоры. В общем не предсказуемое поведение программы. Только R0 у меня если я правлиьно понял был равен 0x1. Пробовал назначать всем прерываниям один уровень, чтобы небыло вложенных . Но на отложенных прерываниях тоже самое. Включал отключал трассировку - не влияет. Хотел спросить. В каих файлах эти строки? Или они в 9 вресии этот участок кода изменили? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Andrey75 0 18 октября, 2016 Опубликовано 18 октября, 2016 · Жалоба Прошу прощения. У меня оказалась совсем другая и банальная ошибка. Каким то чудом закоментировал NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 ); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться