cancel
Showing results for 
Search instead for 
Did you mean: 

Sometimes a crash in the main-loop occurs: STM32F407 with CAN, USART1 and TIMER2

torsten
Associate II
Posted on January 19, 2015 at 20:18

Dear All,

I am working on a project where I want to control a couple of motors via CAN (CANopen).

The STM32F407 is connected via an USB-Serial converter (FT232RL, FTDI) to a PC.

(USART1 with

USART_InitStructure.

USART_BaudRate

= 3072000;

)

On the PC a GUI application is running (configuration, demand value propagation for the STM32, monitoring of demand and actual values etc.).

TIMER2 is configured with a cycle time of 1 millisecond: Every millisecond a flag is set to trigger an action in the main-loop.

The following 3 interrupts are active overall:

1. Receive commands from PC

void

USART1_IRQHandler

(

void

)

{

if

(USART_GetITStatus(USART1, USART_IT_RXNE) ==

SET

)

{

rxBuf[p_rxBuf] = USART_ReceiveData(USART1);

2. Receive CAN messages (three each millisecond from three motor controller overall)

void

CAN1_RX0_IRQHandler

(

void

)

{

CAN_Receive(CAN1, CAN_FIFO0, &CAN1_RxMessage);

3. Trigger flag. If the flag is set some jobs (calculations, message processing etc.) will be done in the main-loop.

void

UB_TIMER2_ISR_CallBack

(

void

)

All interrupts are set up with

NVIC_InitStructure.

NVIC_IRQChannelPreemptionPriority

= 0;

NVIC_InitStructure.

NVIC_IRQChannelSubPriority

= 0;

So they shouldn't interrupt each other.

The information flow from STM32 to PC is done according to the following:

void

UART1_SendByte

(uint16_t val)

{

while

(USART_GetFlagStatus(USART1, USART_FLAG_TXE) ==

RESET

);

USART_SendData(USART1, val);

}

This happens in the main-loop during the trigger flag is set.

Every millisecond up to 80 Bytes are transferred from the STM32 to the PC (monitoring data).

Every millisecond up to 3 CAN messages are sent to the motor controllers:

timeout = 0;

while

(!(CAN1->

TSR

& CAN_TSR_TME0 || CAN1->

TSR

& CAN_TSR_TME1 ||

CAN1->

TSR

& CAN_TSR_TME2))

{

timeout++;

if

(timeout > CAN1_TX_TIMEOUT)

break

;

}

CAN_Transmit(CAN1, &CAN1_TxMessage);

This also happens in the main-loop during the trigger flag is set.

If I don't send data from the GUI to the STM32, everything is fine.

The motor-control-loop with cycle time of 1 millisecond (3 Tx-CAN-Msg, 3 Rx-CAN-Msg) works fine.

Also the information flow from STM32 to PC via USART1 is fine.

The blocking implementation of Tx-USART1 consumes CPU time, but even if I sent 80 bytes per millisecondm, the calculations and jobs in the main-loop according to the TIMER2 trigger signal consume only roundabout 40% of the available CPU time.

The Problem occurs if I send data from the PC to the STM32.

At first everything is fine, but somewhere along the line the crash happens.

In the main-loop nothing happens any longer, but the TIMER2 ISR still works, even sending data via USART1 works in the TIMER2 ISR.

Variables which are accessed in the main-loop and by interrupts are secured by bit-banding flags like the following:

#define

UART_RX_ISR_FLAG *((

volatile

unsigned

long

*) (0x22000000))

#define

UART_RX_MAIN_FLAG *((

volatile

unsigned

long

*) (0x22000004))

For data transfer from variables to CAN or USART1 Tx-buffers and vice versa I use “memcpy�?:

txBuf2[0] = 10;

txBuf2[1] = 76;

memcpy

(&txBuf2[2], &t, 4);

memcpy

(&txBuf2[6], &curDem[0], 12);

memcpy

(&txBuf2[18], &curAct[0], 12);

It would be really great if somebody has an idea what is the reason for that crashes

I seems so as if the USART1 Rx Interrupt causes the problem, but I have no idea how to work around.

Perhaps USART in DMA mode could be a workaround!???

Thanks in advance,

Torsten

12 REPLIES 12
AvaTar
Lead
Posted on January 20, 2015 at 16:35

Is it possible to observe and control this interrupt within another, e.g. TIMER 2 ISR???

Not a good idea. Better find what happens in the UART interrupt. How about debugging, i.e. attaching to the MCU when the problem actually occurs ? (Not sure if  your IDE supports this).

BTW, I think it is not a crash, but just an endless loop. The cause might be some kind of race condition, i.e. a certain sequence of interrupts exposing a bug in your UART interrupt handling.

Posted on January 20, 2015 at 17:30

The USART IRQ handler should probably check for error conditions on the receiver (framing, parity, overrun, etc) and be sure to clear them.

Don't poll the USART in other IRQ handlers, buffer both your input/output, and handle that buffer in the USART IRQ. If you just poll in a tight loop for USART TX under interrupt, it's not going to be servicing the RX.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
torsten
Associate II
Posted on January 20, 2015 at 20:44

Update:

I have cut the baud rate in half, from 3072000 Bit/s down to 1536000 Bit/s.

Because of the polling mode of USART-TX the CPU time consumption has increased from roundabout 40% up to 70%, but in general everything seems to work now.

I am going to test, if with USART in DMA mode or USART-TX in IRQ mode an unloading of the CPU could be achieved.

Thanks to all for your remarks and tips.

Best regards, Torsten