LPC2212 port – problems with mutex
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;
}
LPC2212 port – problems with mutex
I cannot see anything wrong. Did you try running the tasks defined in FreeRTOSdemocommonminimalgenqtest.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?
LPC2212 port – problems with mutex
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
LPC2212 port – problems with mutex
I mean i am going to compare with LPC2106 port (LPC2209 port doesn exist )
LPC2212 port – problems with mutex
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.
LPC2212 port – problems with mutex
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;
}
..
}