LPC3250 porting

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. I try to run simple blink task ~~~ static BOOL8 blink2 = TRUE; void task1(void *) { while(true) { if (blink2) cpldsetbits(ECPLDLeds, CPLDLED0); else cpldclearbits(ECPLDLeds, CPLDLED0); blink2 = (~blink2) & 0x1; vTaskDelay(500 / portTICKPERIOD_MS); } } ~~~ 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   tn" 
    "   cmp r0, #0              tn" 
    "   beq SkipContextSwitch   tn" 
    "   bl vTaskSwitchContext   tn" 
    "SkipContextSwitch:         tn"
);

/* Ready for the next interrupt. */
timer_ioctl(portTickTimerId, TMR_CLEAR_INTS, 1);

/* Restore the context of the new task. */
portRESTORE_CONTEXT();
} ~~~

LPC3250 porting

A couple of notes: 1) Is you vPortYieldProcessor() also a naked function? If not, it needs to be. 2) The call to timerioctl() needs to be in assembly too. portTickTimerId in register r0, TMRCLEARINTS 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 timerioctl(portTickTimerId, TMRCLEARINTS, 1) so you can simply bl to that function rather than load the registers and bl to timer_ioctl.

LPC3250 porting

Hi George! I already ported FreeRTOS for a custom LPC3240 board: https://interactive.freertos.org/hc/en-us/community/posts/210027446-LPC32xx-ARM9-with-FPU-support-using-GCC best regards, thomas

LPC3250 porting

Thank you, Thomas. I imported your port files to my project. Аnd had tryed to run following: ~~~ void task1(void *) { BOOL_8 blink1 = TRUE; TickType_t xLastWakeTime; const TickType_t xFrequency = 500; xLastWakeTime = xTaskGetTickCount(); while(true) { if (blink1) cpld_set_bits(ECPLDLeds, CPLD_LED_1); else cpld_clear_bits(ECPLDLeds, CPLD_LED_1); blink1 = (~blink1) & 0x1; // for (volatile int i=0; i < 8000000; ++i); // vTaskDelay(500 / portTICK_PERIOD_MS); vTaskDelayUntil( &xLastWakeTime, xFrequency ); } } void task2(void *) { BOOL_8 blink2 = FALSE; TickType_t xLastWakeTime; const TickType_t xFrequency = 500; xLastWakeTime = xTaskGetTickCount(); while(true) { if (blink2) cpld_set_bits(ECPLDLeds, CPLD_LED_2); else cpld_clear_bits(ECPLDLeds, CPLD_LED_2); blink2 = (~blink2) & 0x1; // for (volatile int i=0; i < 8000000; ++i); // vTaskDelay(500 / portTICK_PERIOD_MS); vTaskDelayUntil( &xLastWakeTime, xFrequency ); } } extern “C” int centry() { bool blink5 = true; isensboard_init();
BaseType_t result = xTaskCreate(
    task1,
    "task1",
    configMINIMAL_STACK_SIZE,
    NULL,
    tskIDLE_PRIORITY + 1,
    &task1Handle
);
(void)result;

BaseType_t result2 = xTaskCreate(
    task2,
    "task2",
    configMINIMAL_STACK_SIZE,
    NULL,
    tskIDLE_PRIORITY + 1,
    &task2Handle
);
(void)result2;

vTaskStartScheduler();

while(true) {
    if (blink5)
        cpld_set_bits(ECPLDLeds, CPLD_LED_0);
    else
        cpld_clear_bits(ECPLDLeds, CPLD_LED_0);
    blink5 = !blink5;
    for (volatile int i=0; i < 16000000; ++i);
}
return 0;
} ~~~ 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.