LPC2212 port - problems with mutex

verretj wrote on Wednesday, November 19, 2008:

Hello,

I have ported FreeRTOS on LPC2212 and now I am currently testing the mutex functionnality of FreeRTOS.
So  I simply created two tasks and a mutex. Each Task writes either 1 or 2 in a common buffer which is the shared resource guarded by the mutex. When I try to run it I get a data abort error, does anyone have an idea about this ?
I have checked that the creation of both task and of the mutex goes well and that heap and stack is sufficient (I do not return from vTaskStartScheduler and highwatermarks are different from zero)
I have also checked configuration
#define configQUEUE_REGISTRY_SIZE    5
#define configUSE_MUTEXES            1
The problem is related to the mutex since without it I have got no problems.
But  I cannot see what I have done wrong.

void Task1 (void * pvParameters)
{
    int ret;
    unsigned portBASE_TYPE uxHighWaterMark1;

    /* Inspect our own high water mark on entering the task. */
    uxHighWaterMark1 = uxTaskGetStackHighWaterMark( NULL );
   
    for( ;; )
    {
        /*attendre mutex et le prendre dès qu’il est disponible*/
        ret = xSemaphoreTake( mutex, portMAX_DELAY );
        if (ret == pdFALSE)
        {
            return;
        }
        /*ecrire 1 dans le buffer*/
       
        /*buffer non plein*/
        if ( i < SIZE_BUF-1 )
        {
            buf[i] = 1;
            i++;
            buf[i] = 1;
            i++;           
        }
        else
        {
            i = 0;
        }
       
        /* Inspect our own high water mark on entering the task. */
        uxHighWaterMark1 = uxTaskGetStackHighWaterMark( NULL );
       
        /*liberer  mutex*/
        ret = xSemaphoreGive( mutex );
        if (ret == pdFALSE)
        {
            /*Erreur lors de la liberation du mutex*/
            return;
        }
    }
   
}

int main(int argc, char *argv[])
{
    int ret = -1;
    unsigned int Value =0;
    xTaskHandle xHandle1;
    xTaskHandle xHandle2;
   
    /* Configure la PLL */
    PLL_Config();
   
    /*initialisation buffer et mutex */
    i = 0;   
   
    /*Creation du semaphore*/
    mutex = xSemaphoreCreateMutex ();
    if( mutex == NULL )
    {
        /*Erreur lors de la creation du mutex*/
        return -1;
    }
   
    /*cree les taches */
    ret = xTaskCreate( Task1, "TASK1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, &xHandle1 );
    if(ret!= pdPASS)
    {
        return -1;
    }
    ret = -1;
    ret = xTaskCreate( Task2, "TASK2", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, &xHandle2 );
    if(ret!= pdPASS)
    {
        return -1;
    }
   
    /*demarre le scheduler*/
    vTaskStartScheduler();
    return 0;  
}

davedoors wrote on Wednesday, November 19, 2008:

I cannot see anything wrong. Did you try running the tasks defined in FreeRTOS\demo\common\minimal\genqtest.c? They use a mutex.

What changes did you have to make to port the code to the LPC2212? Where did you get the startup code from?

verretj wrote on Wednesday, November 19, 2008:

I use my own startup code, and made several modifications so thait I start in supervisor mode and the swi branch to vPortYieldProcessor.
I am going to compare it to the one from LPC2209 and see if anything misses. Here is my startup code if you have the courage to go through it.

/* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs */
        .equ    Mode_USR,       0x10
        .equ    Mode_FIQ,       0x11
        .equ    Mode_IRQ,       0x12
        .equ    Mode_SVC,       0x13
        .equ    Mode_ABT,       0x17
        .equ    Mode_UND,       0x1B
        .equ    Mode_SYS,       0x1F    /* only available on ARM Arch >= v4 */

        .equ    I_Bit,          0x80    /* when I bit is set, IRQ is disabled */
        .equ    F_Bit,          0x40    /* when F bit is set, FIQ is disabled */

/* — Stack Sizes ----------------------- */
        .equ    Top_Stack,      0x40004000
        .equ    UND_Stack_Size, 0x00000004
        .equ    ABT_Stack_Size, 0x00000004
        .equ    FIQ_Stack_Size, 0x00000004
        .equ    IRQ_Stack_Size, 0x00000400
        .equ    USR_Stack_Size, 0x00000004
        .equ    SYS_Stack_Size, 0x00000004
        .equ    SVC_Stack_Size, 0x00000400

/* — Peripheral’s registers ------------ */
        .equ    VICIntEnClr,    0xFFFFF014
        .equ    VICVectAddr,    0xFFFFF030
       
       
        .text
        .arm

        .global _start
        .global cksum_size      /* at 0x00000040 */
        .global cksum_expected  /* at 0x00000044 */
_start:

/* Exception Vectors (mapped to address 0) */

Vectors:        LDR     PC, Reset_Addr        
                LDR     PC, Undef_Addr
                LDR     PC, SWI_Addr
                LDR     PC, PAbt_Addr
                LDR     PC, DAbt_Addr
                .word   0xB9205F80             /* Program signature (LPC21xx) */
                LDR     PC, [PC, #-0x0FF0]     /* Vector from VicVectAddr reg */
                LDR     PC, FIQ_Addr

Reset_Addr:     .word   Reset_Handler
Undef_Addr:     .word   Undef_Handler
SWI_Addr:       .word   SWI_Handler
PAbt_Addr:      .word   PAbt_Handler
DAbt_Addr:      .word   DAbt_Handler
                .word   0                      /* not used */
IRQ_Addr:       .word   IRQ_Handler            /* not used */
FIQ_Addr:       .word   FIQ_Handler

cksum_size:     .word   0xDEADBEEF             /* needed for S04_01A_cksum_maker.exe */
cksum_expected: .word   0xCAFEFACE             /* and S04_01A firmware for test #1   */

/* Dummy handlers */
Undef_Handler:  B       Undef_Handler
SWI_Handler:    B       vPortYieldProcessor
PAbt_Handler:   B       PAbt_Handler
DAbt_Handler:   B       DAbt_Handler
IRQ_Handler:    B       IRQ_Handler            /* not used */
FIQ_Handler:    B       FIQ_Handler

Reset_Handler: 
/* — First initialize the VIC (Vectored Interrupt Controller) ----------- */
                LDR     R0, =VICIntEnClr
                MOV     R1, #0xFFFFFFFF
                STR     R1, [R0]       

                LDR     R0, =VICVectAddr
                MOV     R1, #0xFF
                STR     R1, [R0] 

               
/* — Setup Stack for each mode ----------------------------------------- */

                LDR     R0, =Top_Stack

/* Enter Undefined instruction mode and set up the UND stack pointer */
                MSR     CPSR_c, #Mode_UND | I_Bit | F_Bit
                MOV     SP, R0
                SUB     R0, R0, #UND_Stack_Size

/* Enter ABT mode and set up the ABT stack pointer */
                MSR     CPSR_c, #Mode_ABT | I_Bit | F_Bit
                MOV     SP, R0
                SUB     R0, R0, #ABT_Stack_Size

/* Enter FIQ mode and set up the FIQ stack pointer */
                MSR     CPSR_c, #Mode_FIQ | I_Bit | F_Bit
                MOV     SP, R0
                SUB     R0, R0, #FIQ_Stack_Size

/* Enter IRQ mode and set up the IRQ stack pointer */
                MSR     CPSR_c, #Mode_IRQ | I_Bit | F_Bit
                MOV     SP, R0
                SUB     R0, R0, #IRQ_Stack_Size

/* Enter SYS mode and set up the SYS stack pointer */
                MSR     CPSR_c, #Mode_SYS | I_Bit | F_Bit
                MOV     SP, R0
                SUB     R0, R0, #SYS_Stack_Size

/* Enter SVC mode and set up the SVC stack pointer (we stay in SVC mode with interrupts enabled) */
                MSR     CPSR_c, #Mode_SVC | I_Bit | F_Bit
                MOV     SP, R0
                SUB     R0, R0, #SVC_Stack_Size

/* Enter User mode then set up its stack */
/*                MSR     CPSR_c, #Mode_USR
                MOV     SP, R0
                SUB     R0, R0, #USR_Stack_Size

# Setup a default Stack Limit (when compiled with "-mapcs-stack-check")
                SUB     SL, SP, #USR_Stack_Size*/
/* Start in supervisor mode(needed by Free RTOS) */               
            /*    MSR   CPSR_c, #Mode_SVC|I_Bit|F_Bit*/

# — Relocate .data section (copy from ROM to RAM) -------------------------
                LDR     R1, =_etext
                LDR     R2, =_data
                LDR     R3, =_edata
Loop_Rel:       CMP     R2, R3
                LDRLO   R0, [R1], #4
                STRLO   R0, [R2], #4
                BLO     Loop_Rel

# — Clear .bss section (Zero Init) ----------------------------------------
                MOV     R0, #0
                LDR     R1, =__bss_start__
                LDR     R2, =__bss_end__
Loop_ZI:        CMP     R1, R2
                STRLO   R0, [R1], #4
                BLO     Loop_ZI

# — Enter C code ----------------------------------------------------------
                BL      main
main_exited:    B       main_exited

        .end

verretj wrote on Wednesday, November 19, 2008:

I mean i am going to compare with LPC2106 port (LPC2209 port doesn exist )

davedoors wrote on Wednesday, November 19, 2008:

That looks fine too. You are vectoring directly to the interrupt source, which is how the LPC2106 demo does it.

Which debugger are you using? It would be good to step through the code to find exactly where it goes wrong.

verretj wrote on Wednesday, November 19, 2008:

I inspired myself, from the genqtest.c and changed my code so that mutex is passed as parameter when tasks are created in main (before I had set up the mutex as a global variable so i thought maybe this could cause problems) . I debug with openice

Now, when i step trough the first task I encounter no problems mutex is transmitted, taken and released without signaling any error, and the guarded data is written correctly.

But when i step through the second i dont get the mutex and so get blocked when trying to take it.

It’s like the mutex had not been released still ther is no error signaled until i get into data abort handler.

I do not understand what happens. Here is my code task 1 is same as task2 but without delay.

void Task2(void * pvParameters)
{

    /*recuperation du mutex*/
    xSemaphoreHandle mutex = ( xSemaphoreHandle ) pvParameters;

    for( ;; )
    {
        /**/
        ret = xSemaphoreTake( mutex, portMAX_DELAY );
        if (ret == pdFALSE)
        {
            return;
        }

     /*liberer  mutex*/
        ret = xSemaphoreGive( mutex );
        if (ret == pdFALSE)
        {
            /*Erreur lors de la liberation du mutex*/
            return;
        }
        /*tempo 100ms */
        vTaskDelay( xDelay );
    }

int main(int argc, char *argv[])
{
    …
    mutex = NULL;
   
    /*Creation du semaphore*/
    mutex = xSemaphoreCreateMutex ();
    if( mutex == NULL )
    {
        /*Erreur lors de la creation du mutex*/
        return -1;
    }
   
    /*cree les taches */
    ret = xTaskCreate( Task1, "TASK1", configMINIMAL_STACK_SIZE, (void *)mutex, tskIDLE_PRIORITY + 1, &xHandle1 );
    if(ret!= pdPASS)
    {
        return -1;
    }
    ret = -1;
    ret = xTaskCreate( Task2, "TASK2", 2*configMINIMAL_STACK_SIZE,(void *) mutex, tskIDLE_PRIORITY + 2, &xHandle2 );
    if(ret!= pdPASS)
    {
        return -1;
    }

}