2024-07-30 03:22 PM
I have a design using USART1 on an STM32F3 as a LIN slave receiver using the old standard peripheral drivers from ST Micro. The code is too much to post here, but I have LIN Break Detect and RX Not Empty interrupts enabled, and for some reason under some condition (not sure the cause yet), an interrupt is firing in USART1 and not getting cleared so the code is stuck in the ISR.
My first question: are there any LIN examples from ST Micro using the standard peripheral drivers? E.g. functions like USART_ReceiveData(), USART_GetITStatus(), etc. I have not been successful in finding any.
My second question: what is triggering the USART interrupt and why isn't it getting cleared?
The code for the setup and ISR for USART1 is below. The idea is, a LIN Break Detect interrupt on USART1 indicates the start of a LIN message, so clear the message buffer and reset the buffer index. Subsequent RXNE interrupts are for the message bytes being received; after receiving 0x55 (LIN sync) and the address/PID byte, the total expected message length is calculated. Once the expected number of bytes have been received, the buffer index and total expected bytes should match, so the message buffer is written to a FreeRTOS queue for another task to read.
When I run this code with the debugger, the first interrupt goes into the RXNE case, then immediately enters the ISR again and none of the status checks return true, so the code just keeps entering the ISR repeatedly and none of my RTOS tasks run. The state of the USART1 ISR, ICR, and CR1 registers while "stuck" in the ISR follow:
I see the Overrun bit set in the ISR register, which makes me think the USART1 is interrupting due to and RX overrun, but why isn't it getting cleared in the interrupt service routine (ORE case)?
USART1 setup:
USART_InitStruct.USART_BaudRate = 19200;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No ;
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
//Turn on periph clock for UART3
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
// Initialize USART1 with parameters above.
USART_Init (USART1, &USART_InitStruct);
// Enable DMA TX request.
USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
// Enable DMA channel for memory-to-peripheral (transmit) direction.
DMA_Cmd(DMA1_Channel4, ENABLE);
// Enable LIN mode
USART_LINCmd(USART1, ENABLE);
// Enable LIN break and Rx interrupts
USART_ITConfig(USART1, USART_IT_LBD, ENABLE);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
// Set up NVIC for the UART interrupt
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 10;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 10;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//Enable UART
USART_Cmd(USART1, ENABLE);
USART1 interrupt handler:
void USART1_IRQHandler(void)
{
// LIN message format is:
// LIN Break
// Address/PID
// Data
if (USART_GetITStatus(USART1, USART_IT_LBD))
{
USART_ClearFlag(USART1, USART_FLAG_LBD);
// clear message buffer, reset index and total length variables
memset(msgBuf.msgBytes, 0, sizeof(msgBuf.msgBytes));
msgIdx = 0;
totalMsgLen = 0xFF;
}
else if (USART_GetITStatus(USART1, USART_IT_RXNE))
{
msgBuf.msgBytes[msgIdx++] = USART_ReceiveData(USART1);
USART_ClearFlag(USART1, USART_FLAG_RXNE);
}
// attempt at clearing overrun interrupt, which may or may not be enabled? But doesn't fix the issue.
else if (USART_GetITStatus(USART1, USART_IT_ORE))
{
USART_ReceiveData(USART1);
}
// If 2 bytes received, sync (0x55) and PID/address, assign total message length for
// that address/PID.
if (msgIdx == 2)
{
switch (msgBuf.msgBytes[1])
{
// proprietary information, result is totalMsgLen gets set to some value > 2.
}
}
if (msgIdx == totalMsgLen)
{
msgIdx = 0;
totalMsgLen = 0xFF;
xQueueSendToBackFromISR(xLINRxQueue, &msgBuf, &xHigherPriorityTaskWoken);
// End the ISR!
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken);
}
return;
}
Solved! Go to Solution.
2024-07-30 04:15 PM
I think my issue was due to enabling the transmit DMA during USART setup. I don't want to enable it until a LIN message needs to be sent. Commenting out that line seems to have resolved the problem.
2024-07-30 04:15 PM
I think my issue was due to enabling the transmit DMA during USART setup. I don't want to enable it until a LIN message needs to be sent. Commenting out that line seems to have resolved the problem.