cancel
Showing results for 
Search instead for 
Did you mean: 

Issue with uart USART_ISR_EOBF bit

SSmit.13
Senior

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

 

18 REPLIES 18

The important thing to understand is that these aren't "memories", but bits into a state machine or other combinational logic. The Reference Manual will likely explain or indicate expected behaviour. Doing register level coding requires a lot higher level of awareness to what the peripheral designer implemented, and why.

Writing SET bits can be done with a singular write instruction.

Using |= or &= can have other side effects if it reads high or low bits. It's also very inefficient.

The one that most often caused issues was TIM->SR &= ~1; You'd occasionally end up clearing bits you didn't mean too if an interrupt was latched between the read and write operations.

Doing this is also very inefficient, the optimizer can't fold actions on a "volatile" memory interactions. Your doing a pair of LOAD/STORE operations when you could do it in half of that.

	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

Do this

GPIOB->AFR[0] = (GPIOB->AFR[0] & ~0xff000000) | 0x77000000; //AF7 for both PB6 and PB7

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

I never knew this about only 1 bits do anything, I must have missed that.

 

Thanks for letting me know

😀

Hi

  I added the above at the start of my interupt routine , but still the RXNE bit cleared after clearing the EOBCF bit

 

Cheers

Scott

Bob S
Principal

Show your current code.

Below is the UART handler. When I placed a beakpoint  on the   USART1->ICR = USART_ICR_EOBCF; line ,the RXNE =1. As soon as I step onto the next instruction  the RXNE bit is cleared.

void USART1_IRQHandler(void)
{
	unsigned char data;

	if(USART1->ISR & USART_ISR_EOBF)
	   USART1->ICR = USART_ICR_EOBCF;  //after stepping pass this the RXNE is cleared

	if(USART1->ISR & USART_ISR_RXNE)  //RX interupt
	{
		data=USART1->RDR;
	 ....
        }

Scott

Pavel A.
Evangelist III

So change it as following:

void USART1_IRQHandler(void)
{
	unsigned char data;
	if(USART1->ISR & USART_ISR_RXNE)  //RX interupt
	{
		data=USART1->RDR;
	 ....
        }
	if(USART1->ISR & USART_ISR_EOBF)
	   USART1->ICR = USART_ICR_EOBCF;  // why this at all, in plain UART mode?
}

I previously done this, but was wanting to check what you previously said about , only a 1 bit effects the bits in the register. I removed the above line , but was curious why the RXNE bit was cleared. Still dont know what single write without a read would work.

Bits in the ICR register are write-only, so there's no sense in reading it anyway. It can read as all 0's or return some random value.

Bob S
Principal

> As soon as I step onto the next instruction the RXNE bit is cleared.

One possible explanation - if you have the SFR view open to show the UART registers, it re-reads those registers after every step. If the IDE reads/diplays the RDR register, that will clear the RXNE bit.  The IDE should **NOT** automatically read that register for exactly this reason, and I don't think it does.  But I don't recall for sure.  Or - do you by chance have a "watch" set on the RDR?

> Still dont know what single write without a read would work.

Look in the ref manual.  The bits in the ICR register are of type "rc_w1", which it says means "Software can read as well as clear this bit by writing 1. Writing 0 has no effect on the bit value."  Not the most clear explanation to me, but it means you can read the register if you want., but you don't have to.  To clear a bit, write a "1" to that bit position.  Writing a "0" to a bit has no effect.  THAT is why writing a single bit works to clear that bit, you are writing 0's to all the other bits.