2015-01-19 11:18 AM
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
2015-01-20 07:35 AM
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.2015-01-20 08:30 AM
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.2015-01-20 11:44 AM
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