Вылетает в 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
}
{
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
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
#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);
}
{
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 ?