Sometimes a crash in the main-loop occurs: STM32F407 with CAN, USART1 and TIMER2
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