Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Real time embedded FreeRTOS mailing list 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT Training




Loading

STM32 crash in list.c

Posted by Sam T on January 18, 2011
Dear all,

Thank you very much for reading my post. I have some issues with a custom board based on a STM32 (Cortex M3).

I use FreeRTOS v6.1.0 with CodeSourcery's GCC and Eclipse.

In my design, I communicate with a GPRS device through an USART port. The crash occurs when receiving a packet from the GPRS device, after a few minutes running.

When a data arrives on the USART, the DMA copies it to a buffer, and an interrupt is generated. In the ISR, I just give a semaphore, which unblocks an other task.

I paid attention to the special remarks for CM3 users. Here is the init of the NVIC:


NVIC_InitStructure.NVIC_IRQChannel = UART_Gprs_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 15;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);


In FreeRTOSconfig.h, is set to 255, which on the STM32 means 15. The interrupt priority is the same as the kernel interrupt priority. I tried to put it 1 above (set it to 14), but no change.

When the crash occurs, the code loops forever in list.c, in vListInsert(...), in the for(...) loop. By putting some traces, I was able to find that the code crashes either at the end of the ISR, either at the task side that waits for the semaphore.

Here is the ISR code :

void USART3_IRQHandler(void)
{
long xHigherPriorityTaskWoken = pdFALSE;
debug_flag = 51;
//Don't need to clear the bit, 'cause the DMA controller normally does it
USART_ITConfig(UART_Gprs, USART_IT_RXNE, DISABLE);//Disable interrupt
xSemaphoreGiveFromISR(xGprsRxSemaphore, &xHigherPriorityTaskWoken);

if (xHigherPriorityTaskWoken == pdTRUE)
{
debug_hpw = 1;
debug_flag = 52;
}
else
{
debug_hpw = 0;
debug_flag = 55;
}

portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );

}


I also noticed that if I don't put the portEND_SWITCHING_ISR(...) in this ISR, the crash does not occur.

Here is the code at the task side:

debug_flag = 53;
xSemaphoreTake(xGprsRxSemaphore, ( portTickType ) 200 / portTICK_RATE_MS );

debug_flag = 54;

dma_cnt = DMA_GetCurrDataCounter(UART_Gprs_Rx_DMA_Channel);

while( (gprsRxBuffIndex !=
(UART_BUFFER_SIZE - dma_cnt) ) && (data_cnt < maxLength))
{
buffer[*length] = gprsRxBuffer[gprsRxBuffIndex++];

*length = (*length) + 1;
data_cnt++;

if (gprsRxBuffIndex > UART_BUFFER_SIZE-1)
{
gprsRxBuffIndex = 0;
}
}

USART_ITConfig(UART_Gprs, USART_IT_RXNE, ENABLE);


Could someone give me a few hints to debug my code and try to find what's going on ?

Thank you a lot in advance and best regards,

Sam

RE: STM32 crash in list.c

Posted by Richard on January 19, 2011
“Thank you very much for reading my post.”


...and thank you for doing some research before posting, and providing good information in your post.

Do you set the interrupt priority grouping anywhere? On an STM32, this is normally done with the following line of code:
NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );

Regards.

RE: STM32 crash in list.c

Posted by Sam T on January 19, 2011
Dear Richard,

You are absolutely right, this step is missing, and it never crashed again since I made this change. Thank you very much for your help, and thank you as well for FreeRTOS !

Best regards,

Sam

RE: STM32 crash in list.c

Posted by Tobias Groll on June 19, 2011
I have the same probleme. My code looks very the same like here shown but I'm waiting for receiving CAN messages so I use the interrupt for can. I have changed the priority group and have checked my settings for the interrupt. But the I get the same error, my programm stays in the for loop in list.c
I use libopenstm32.

This is my code:

Initialisation:

SCB_AIRCR = scb_aircrTemp | SCB_AIRCR_VECTKEY | (SCB_AIRCR_PRIGROUP_GROUP16_NOSUB << SCB_AIRCR_PRIGROUP_LSB);
/* NVIC setup. */
nvic_enable_irq(NVIC_USB_LP_CAN_RX0_IRQ);
//set priority, configMAX_SYSCALL_INTERRUPT_PRIORITY is the highest priority interrupts can have which calls freertos functions
nvic_set_priority(NVIC_USB_LP_CAN_RX0_IRQ, configKERNEL_INTERRUPT_PRIORITY - 32);

/* Reset CAN. */
can_reset(CAN1);

/* CAN cell init. */
if (can_init(CAN1,
false, /* TTCM: Time triggered comm mode? */
false, /* ABOM: Automatic bus-off management? */
false, /* AWUM: Automatic wakeup mode? */
false, /* NART: No automatic retransmission? */
false, /* RFLM: Receive FIFO locked mode? */
false, /* TXFP: Transmit FIFO priority? */
CAN_BTR_SJW_1TQ,
CAN_BTR_TS1_5TQ,
CAN_BTR_TS2_2TQ,
4)) /* BRP+1: Baud rate prescaler */
{

/* Die because we failed to initialize. */
while (1)
__asm__("nop");
}

/* CAN filter 0 init. */
can_filter_id_mask_32bit_init(CAN1,
0, /* Filter ID */
0, /* CAN ID */
0, /* CAN ID mask */
0, /* FIFO assignment (here: FIFO0) */
true); /* Enable the filter. */


Code of the waiting task:


while(1)
{
//enable interrupt
can_enable_irq(CAN1, CAN_IER_FMPIE0);
//wait till new can data received
xSemaphoreTake(xSemaphoreWaitingForCanReceive, LONG_TIME);
//gets the number of waiting can packages from the FMP0 in the CAN receive Register of FIFO0
waitingCanPackages = CAN_RF0R(CAN1) & CAN_RF0R_FMP0_MASK;
while(waitingCanPackages > 0){
gpio_clear(GPIOC, GPIO12);
//gets can packages until the FIFO queue is empty
for(;waitingCanPackages > 0;waitingCanPackages--){
ticksSinceBooted = xTaskGetTickCount();
//read data from can
readCan(&sensorDataLength, sensorData, &canId);
//reduce can data to required digits
writeCanId = (uint16_t)canId;
//puts canId to the array
arCanId = (uint8_t*)&writeCanId;

//calculate the data to write
//header 1 Byte
fileData[fileDataLength] = 0xCA;
//timestamp 4 Byte
memcpy(& (fileData[fileDataLength + 1]), (uint8_t*)&ticksSinceBooted, 4 * sizeof(uint8_t));
//can Id 2 Byte
fileData[fileDataLength + 5] = arCanId[0];
fileData[fileDataLength + 6] = arCanId[1];
//data length 1 Byte
fileData[fileDataLength + 7] = sensorDataLength;
//data 0 - 8 Byte (sensorDataLength)
memcpy(&(fileData[fileDataLength + 8]), sensorData, sensorDataLength * sizeof(uint8_t));

//calculate the full length of the data to write
fileDataLength += (8 + sensorDataLength);
}
//write the data on the card
//writeFat(fileDataLength, fileData);
//reset the length of the data that will be written
fileDataLength = 0;
gpio_set(GPIOC, GPIO12);
//check if more can packages are waiting
waitingCanPackages = CAN_RF0R(CAN1) & CAN_RF0R_FMP0_MASK;
}
}


Interrupt Handler:


void usb_lp_can_rx0_isr(void)
{
long xHigherPriorityTaskWoken = pdFALSE;
//disable interrupt
can_disable_irq(CAN1, CAN_IER_FMPIE0);
//unlock Log Task
xSemaphoreGiveFromISR(xSemaphoreWaitingForCanReceive,&xHigherPriorityTaskWoken);
/* If xHigherPriorityTaskWoken was set to true you
we should yield. The actual macro used here is
port specific. */
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}



Thanks for your Help

RE: STM32 crash in list.c

Posted by Dave on June 19, 2011
What number is configKERNEL_INTERRUPT_PRIORITY - 32 giving you? That does not look right.
Are you calling NVIC_PriorityGroupConfig() anywhere?

RE: STM32 crash in list.c

Posted by Tobias Groll on June 19, 2011
This is the Priority Group Configuration:

SCB_AIRCR = scb_aircrTemp | SCB_AIRCR_VECTKEY | (SCB_AIRCR_PRIGROUP_GROUP16_NOSUB << SCB_AIRCR_PRIGROUP_LSB);

scb_aircrTemp contains the value of the register before editing without VECTKEY
SCB_AIRCR_VECTKEY is the key you need to edit the register
SCB_AIRCR_PRIGROUP_GROUP16_NOSUB contains the value for no subriority bits
and SCB_AIRCR_PRIGROUP_LSB contains the position of the group priority bits

libopenstm32 does not contain a function to do this.

configKERNEL_INTERRUPT_PRIORITY is set to 255 for the lowest priority, I've tried it with -32 for a priority that is a littel higher but lower as the max Syscall priority. I have tried it with 255 without -32 to but that's the same effect.


RE: STM32 crash in list.c

Posted by Dave on June 19, 2011
“This is the Priority Group Configuration:

SCB_AIRCR = scb_aircrTemp | SCB_AIRCR_VECTKEY | (SCB_AIRCR_PRIGROUP_GROUP16_NOSUB << SCB_AIRCR_PRIGROUP_LSB);”


I don't understand that at all, but am sure it is not configuring the priority grouping in the interrupt controller. Read post 2 in this thread.


“configKERNEL_INTERRUPT_PRIORITY is set to 255 for the lowest priority, I've tried it with -32 for a priority that is a littel higher but lower as the max Syscall priority. I have tried it with 255 without -32 to but that's the same effect.”


Read point 3 here http://www.freertos.org/FAQHelp.html and check how nvic_set_priority() is expecting the priority to be specified. I am 99% sure it is not expecting a value above 15, in which case, you are not using the function correctly. I would also set the priority before enabling the interrupt, you have it the other way around.

I recommend reading the Cortex-M NVIC reference manual to understand how to set the NVIC up.

RE: STM32 crash in list.c

Posted by Tobias Groll on June 19, 2011
I don't use the stm32 stdperipheral lib, I use libopenstm32.
The NVIC_PriorityGroupConfig function of stm32 std lib does exactly the same as my line for setting the priority group.

In stm32 stdperipheral lib, the highest priority you can set is 15. But in libopenstm32 you set the priority to the value how it is set in the register and thats an 8bit value, so the highest number you can set is 255 and that's the lowest interrupt priority

RE: STM32 crash in list.c

Posted by Tobias Groll on June 21, 2011
I have reread the stm32 manual und rechecked my register settings, by read out the registers and I think I've setted them right.

But I think there is an other reason for my problem.

I have a second task for increase a timer variable that should runs every 10ms. Here I use the vTaskDelayUntil function and I think it crashes if this function sets the scheduler in suspend mode and then the can interrupt happens and call api function while the scheduler is in suspend mode.

Is that possible? How it's possible to call a function every 10ms in the right way? Can I use a hardware timer?

RE: STM32 crash in list.c

Posted by Richard on June 21, 2011
Suspending the scheduler will not stop interrupts from executing (as you know). If an interrupt attempts a context switch while the scheduler is suspended then the context switch is held pending until the point where the scheduler is resumed (un-suspended). That is normal sequence of events, and tested well, but that is not a guarantee of course. I would be surprised however if that was causing the crash without any external/other factors.

Regards.

RE: STM32 crash in list.c

Posted by Tobias Groll on June 21, 2011
void disk_timer_task(void *pvParameters) {
portTickType LastWakeTime;
const portTickType period = 10 / portTICK_RATE_MS;

LastWakeTime = xTaskGetTickCount();

for(;;)
{
vTaskDelayUntil(&LastWakeTime, period);
timeSinceBooted++;
}
}

thats the second task

timeSinceBooted is definded global.

If I don't start this task only the task that waits for can receive it doesn't crash. If is start this task it crashes.

Other tasks don't run.

RE: STM32 crash in list.c

Posted by Dave on June 22, 2011
portTICK_RATE_MS is calculated from configTICK_RATE_HZ. What is configTICK_RATE_HZ set to? It is defined in FreeRTOSConfig.h. If 10 / portTICK_RATE_MS was zero or 1 then you will have a problem if disk_timer_task has a high priority because tasks that have a lower priority will never run.

RE: STM32 crash in list.c

Posted by Tobias Groll on June 30, 2011
the disk_timer_task had the same priority as the other task.

But I don't use it anymore, I use the systick hook for that. But my tasks crash if I'have more than that tasks that waits for the can receive.

RE: STM32 crash in list.c

Posted by Tobias Groll on June 30, 2011
I think the problem is that the interrupt fires while the programm is in a critical section. I have checked the nvic priority register and that is set to 1111 0000 and I have checked the SCB register that is set to 11111010000001010000001100000000
011 at position 10:8 stands for the priority group and that is the right setting for no subpriority bits and 4 pre-emption priority bits.


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) 2004-2010 Richard Barry. Copyright (C) 2010-2016 Real Time Engineers Ltd.
Any and all data, files, source code, html content and documentation included in the FreeRTOSTM distribution or available on this site are the exclusive property of Real Time Engineers Ltd.. See the files license.txt (included in the distribution) and this copyright notice for more information. FreeRTOSTM and FreeRTOS.orgTM are trade marks of Real Time Engineers Ltd.

Latest News:

FreeRTOS V9.0.0 is now available for download.


Free TCP/IP and file system demos for the RTOS


Sponsored Links

⇓ Now With No Code Size Limit! ⇓
⇑ Free Download Without Registering ⇑


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Renesas Electronics Gold Alliance RTOS Partner.jpg

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Atmel RTOS partner supporting ARM Cortex-M3 and AVR32 microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Xilinx Microblaze and Zynq partner

Silicon Labs low power RTOS partner

Altera RTOS partner for Nios II and Cortex-A9 SoC

Freescale Alliance RTOS Member supporting ARM and ColdFire microcontrollers

Infineon ARM Cortex-M microcontrollers

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

Cypress RTOS partner supporting ARM Cortex-M3

Fujitsu RTOS partner supporting ARM Cortex-M3 and FM3

Microsemi (previously Actel) RTOS partner supporting ARM Cortex-M3

Atollic Partner

IAR Partner

Keil ARM Partner

Embedded Artists