AnsweredAssumed Answered

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

Question asked by bruns.torsten on Jan 19, 2015
Latest reply on Jan 20, 2015 by bruns.torsten

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

Outcomes