2024-01-24 08:58 AM
Hi
I have a stm32L433, and setup Uart1 for standard TX and RX with interrupt for both send and receive (9600N81 setup). I don't use any hardware handshake . Within the IRQ routine occasionally the USART_ISR_EOBF bit in the ISR is set , and I am not using smartcard mode , and the EOBIE bit is not set in the CR2 register.. I have the below , and even after its cleared it then keeps getting set and cant get any data.
void USART1_IRQHandler(void)
{
unsigned char data;
if(USART1->ISR & USART_ISR_FE)
USART1->ICR |= USART_ICR_FECF;
if(USART1->ISR & USART_ISR_EOBF)
USART1->ICR |= USART_ICR_EOBCF;
if(USART1->ISR & USART_ISR_RXNE) //RX interupt
{
data=USART1->RDR;
...
Many thanks
Scott
Solved! Go to Solution.
2024-01-28 09:42 PM
Is the RMW to ICR the appropriate approach?
What else in ISR is set. Show configuration of the USART and the registers when it fails.
The Noise, Overrun or Framing Errors are more probable.
2024-01-24 09:10 AM
Use this button to properly post source code:
To get that extra row of icons, press this button:
2024-01-24 10:34 AM
I would not expect that bit getting set to prevent receiving incoming bytes. But I have zero experience using smartcard mode. And, yes, I understand (or presume) that you are not using smartcode mode, just normal UART. From the code you posted, it looks like it should flow down to the RXNE block whether or not EOBF is set. Is that happening?
Are you using the HAL libraries? It doesn't look like it from your code above, or at least you are not using HAL code to respond to the interrupt.
For STM32 code it is good practice when checking interrupt flags to check BOTH the ISR bit AND the IE bit, and only respond if both are set. Look at the HAL UART IRQ handler for examples (even if you aren't using HAL), in stm32l4xx_hal_uart.c HAL_UART_IRQHandler().
2024-01-24 11:03 AM
Hi
Most times it works fine, its the other times the EOBF is set. When its set, it doesnt run down to the RXNE routine.
You mention "check BOTH the ISR bit AND the IE bit". I check the ISR register as below, whats the IE bit?
Thanks
Scott
void SetupUart1Port(void)
{
//////////////////////////
//setup serial port...
//UART 1
//PB6-TX PB7-RX
GPIOB->MODER &= ~0b1111000000000000; //clear pins PB6 , PB7
GPIOB->MODER |= 0b1010000000000000; //alternate function for both pins
GPIOB->AFR[0] &= ~0xff000000; //mask out
GPIOB->AFR[0] |= 0x77000000; //AF7 for both PB6 and PB7
GPIOB->OSPEEDR &= ~0xf000; //mask out
GPIOB->OSPEEDR |= 0xf000; //speed high for PB7 and PB6
GPIOB->PUPDR &= ~0xf000; //mask out pullup
GPIOB->PUPDR |= 0x5000; //pullup
RCC->APB2ENR |= RCC_APB2ENR_USART1EN; //enable uart 1 clock
//??RCC->CCIPR &= ~0xc0;//mask out clock
RCC->CCIPR &= ~0xf;//mask out clock
RCC->CCIPR |= 0x5;//select SYSCLCK
USART_Init(USART1,BAUD9600);
NVIC_SetPriority(USART1_IRQn,1);
NVIC_EnableIRQ(USART1_IRQn);
USART1->CR1 &= ~USART_CR1_TXEIE; //clear tx interupt com 1
USART1->CR1 |= USART_CR1_RXNEIE; //rx interupt com 1
}
void USART_Init(USART_TypeDef *USARTx,int Baud)
{
USARTx->CR1 &= ~USART_CR1_UE; //disable uart
USARTx->CR1 &= ~USART_CR1_M0;// 8 bits
USARTx->CR1 &= ~USART_CR1_M1;// 8 bits
USARTx->CR2 &= ~USART_CR2_STOP;// 1 stop bit
USARTx->CR1 &= ~USART_CR1_PCE;// no parity
USARTx->CR1 &= ~USART_CR1_OVER8; //oversample
USARTx->BRR = Baud; //set baud
USARTx->CR1 |= (USART_CR1_TE | USART_CR1_RE); //enable tx and rx
USARTx->CR1 |= USART_CR1_UE; //enable uart
while((USARTx->ISR & USART_ISR_TEACK)==0); //verify uart is ready for transmission
while((USARTx->ISR & USART_ISR_REACK)==0); //verify uart is ready for reception
}
void USART1_IRQHandler(void)
{
unsigned char data;
if(USART1->ISR & USART_ISR_FE)
USART1->ICR |= USART_ICR_FECF;
if(USART1->ISR & USART_ISR_EOBF)
USART1->ICR |= USART_ICR_EOBCF;
if(USART1->ISR & USART_ISR_RXNE) //RX interupt
{
data=USART1->RDR;
......
}
}
2024-01-28 09:20 PM
> When its set, it doesnt run down to the RXNE routine.
The code you posted SHOULD still get to the RXNE test even if EOBF is set. Are you saying that when EOBF is set RXNE is not?
> whats the IE bit
The "interrupt enable" bit in the CR1 register, for example RXNEIE. You code should only respond to an interrupt if the interrupt/ISR flag is set AND the corresponding IE bit is set. Normally this is as issue only when enabling and disabling interrupts, as it is possible to enter the IRQ handler after your code has cleared the IE bit (depends on timing or IRQ vs timing of code and instruction pipelining). This is mostly "good programming practice" but is likely not the issue here.
2024-01-28 09:42 PM
Is the RMW to ICR the appropriate approach?
What else in ISR is set. Show configuration of the USART and the registers when it fails.
The Noise, Overrun or Framing Errors are more probable.
2024-01-30 03:53 AM
What I have noticed is if I clear the flags before checking the RXNE flag, then the RXNE gets cleared. If I put at the end then works as expected. I am thinking I dont even have to check this flag as I dont use this feature.
void USART1_IRQHandler(void)
{
unsigned char data;
if(USART1->ISR & USART_ISR_FE)
USART1->ICR |= USART_ICR_FECF;
if(USART1->ISR & USART_ISR_EOBF)
USART1->ICR |= USART_ICR_EOBCF; <<this clears the RXNE bit
if(USART1->ISR & USART_ISR_RXNE) //RX interupt
{
data=USART1->RDR;
...
}
}
Below is the snap shot prior to moving the above to the end..
Best Regards
Scott
2024-01-30 09:46 AM
As @Tesla DeLorean said (or strongly hinted at) - do not do a read-modify-write (RMW) to the ICR (oops, I missed that). And the "|=" operation is a RMW. Just write the (single) bit for the flag you want to clear.
2024-01-30 01:23 PM
I thought the only way is to either do a |= or read in the register then | the bit and write the result back in. Either way its read in. If not how would I set the bit without doing the just mentioned?
2024-01-30 01:38 PM
Just write to it. Only bits that are "1" do anything.
if(USART1->ISR & USART_ISR_EOBF) {
USART1->ICR = USART_ICR_EOBCF; // Clear EOBCF and only EOBCF
}