Hi! I try porting FreeRTOS kernel on NXP LPC3250.
I use arm-none-eabi-gcc. I took arm7 lpc23xx port for gcc as base. Then I compared assembler parts whith iar at91sam9xe port. They are the same.
Now, my LPC use only one interrupt - TIMER0_MATCH. All other are disabled. So I installed the vPortTick function as ARM IRQ handler. (I do not need a IRQ dispather because, there is no other interupts.) Then I installed vPortYieldProcessor function as SWI handler.
But this works unstable. Led blinks whith different periods. Sometimes stops and after some time starts again.
I think that it is a result of execution timer0 handler over swi. Can anyone explain, how should handlers priorities be defined for correctly work?
Handlers are:
void vPortYieldProcessor( void )
{
/* Within an IRQ ISR the link register has an offset from the true return
address, but an SWI ISR does not. Add the offset manually so the same
ISR return code can be used in both cases. */
__asm volatile ( "ADD LR, LR, #4" );
/* Perform the context switch. First save the context of the current task. */
portSAVE_CONTEXT();
/* Find the highest priority task that is ready to run. */
__asm volatile ( "bl vTaskSwitchContext" );
/* Restore the context of the new task. */
portRESTORE_CONTEXT();
}
void vTickISR( void ) __attribute__((naked));
void vTickISR( void )
{
extern INT_32 portTickTimerId;
/* Save the context of the interrupted task. */
portSAVE_CONTEXT();
/* Increment the RTOS tick count, then look for the highest priority
task that is ready to run. */
__asm volatile
(
" bl xTaskIncrementTick \t\n" \
" cmp r0, #0 \t\n" \
" beq SkipContextSwitch \t\n" \
" bl vTaskSwitchContext \t\n" \
"SkipContextSwitch: \t\n"
);
/* Ready for the next interrupt. */
timer_ioctl(portTickTimerId, TMR_CLEAR_INTS, 1);
/* Restore the context of the new task. */
portRESTORE_CONTEXT();
}
Is you vPortYieldProcessor() also a naked function? If not, it needs
to be.
The call to timer_ioctl() needs to be in assembly too.
portTickTimerId in register r0, TMR_CLEAR_INTS in r1 and 1 in r2. It
might just be simpler to write the code inline using assembly, or have a
function that takes no parameters that calls
timer_ioctl(portTickTimerId, TMR_CLEAR_INTS, 1) so you can simply bl to
that function rather than load the registers and bl to timer_ioctl.
If I run tasks delayed by for() cycle - it works correctly. If I run tasks delayed by vTaskDelay or vTaskDelayUntil functions - it works bad. I see folowing behavior: two times it switch well, but then task1’s led stops. After few secconds (5-10) lights again, then turns off again after random period. Task2’s led blinks stable with 500ms period. This behavior looks like the same as a problem in my first post.