Clearing TXCn before writing UDR

Go To Last Post
24 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I remember some sort of note about clearing this flag before writing UDR, but don't see it in any of the datasheets I am looking at (atmega640/328/etc.).  Does anyone remember or know where this info is?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In the versions of the ATmega328/P, ATmega32U4, and ATmega2560 data sheets I am using currently it is part of the TXB8n description.

 

Edit:

It only needs to be written to, not cleared, if and only if configured for 9 data bit operation since writing to UDRn initiates the data transmission.

 

Edit again:

Misread the bit in question.

Last Edited: Sun. Mar 24, 2019 - 02:21 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I certainly don't explicitly clear it and I use M328P USART. This is the only thing I bother with on the transmit side is:

#define TX_READY		(UCSR0A & (1<<UDRE0))

other than writing to UDR0, that is. I don't use interrupts on the transmit side; I have a PutChar() function that reads a character from a string, tests for null character, waits for TX_READY to go true, then writes the character to UDR0, increments the string pointer, and gets out.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Sun. Mar 24, 2019 - 02:20 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Found it in the USART initialization section:

 

Before doing a re-initialization with changed baud rate or frame format, be sure that there are no
ongoing transmissions during the period the registers are changed. The TXCn Flag can be used
to check that the Transmitter has completed all transfers, and the RXC Flag can be used to
check that there are no unread data in the receive buffer. Note that the TXCn Flag must be
cleared before each transmission (before UDRn is written) if it is used for this purpose.

 

BUT...why clear it before writing UDR?  If the flag can be SET when the last byte has been shifted out and UDR is empty, couldn't clearing it before writing UDR allow for it to be set on the glitch that at that exact moment (after clearing it, but before writing UDR) it completes a transmission?  Wouldn't it be better to write UDR and then clear TXCn ?  That way you know something is in the UDR buffer and it can't set the bit saying it is complete?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

USART TXC

 

The above is from the combined 48/88/168/328

datasheet.

 

--Mike

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

alank2 wrote:

BUT...why clear it before writing UDR?

They are talking about using TXC in polling

mode. You clear TXC before writing to UDR

so next time you notice TXC is set, it means

that the character was sent. You only ever

have one character placed in UDR, then

wait for TXC, clear it and send the next one.

 

--Mike

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Their example is all about changing the baud rate or making sure it isn't in the middle of transmitting, but I'm not sure they are stipulating someone is writing only one byte at a time and waiting for it to be sent before writing the next one.

 

I still wonder about the order however.  If you write UDR first, and then clear TXC, then you KNOW for certain that TXC is not set while the buffer has a character in it.  If you do what they suggest in the datasheet, couldn't TXC be technically set immediately after you clear it but before you write UDR?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think what they're talking about is if you put

a character in UDR, and then just before you

clear TXC an interrupt happens, and the handler

takes long enough that the character was sent

while the handler did its thing, then the interrupt

handler returns and TXC gets cleared, you will

never see TXC get set again.

 

--Mike

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sheesh -- much ado about nothing.  Did you miss the "REinitialization"?  How many of your apps reinitialize the USART during steady-state operation?  I've never had one.  Now, I certainly do have apps that go to sleep and shut down the USART first.  OF COURSE, if you don't want to lose anything, you have to wait for previous operations to complete -- you use the TXC flag for that.  Of course, when you start up again you want a clean slate, and no spurious flags.

 

Sounds like a snipe hunt.  Does your USART app that has communicated successfully for years now suddenly stopped working, and you suspect the TXC flag?

 

 

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What is snipe hunt?  Looked it up on google.  I would think a technical question like this is right on point.

 

I am thinking of shutting down the USART so I can send a break and then put it in action again.

Last Edited: Sun. Mar 24, 2019 - 03:32 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

alank2 wrote:
I am thinking of shutting down the USART so I can send a break and then put it in action again.

OK, fine.  If your app really needs that; perhaps outline the BREAK use.  I've never used any kind of break protocol on an AVR.  The last one I can recall is on Burroughs mainframe days.

 

Of course you need to clear the flags, just like any other peripheral before startup, if you don't want phantom hits.  Of course you need to wait for the previous operation to complete -- if you care to -- before aborting said operation.  I'm reaching my daily snipe bag limit.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So no one has any additional thoughts about the order of clearing the TXCn flag vs. setting UDR based on what the datasheet says?

 

I suppose it is possible that clearing TXCn and then setting UDR still doesn't give any time for TXCn to be set between them, but I wonder why risk it - and more importantly WHY does the datasheet recommend it this way?

 

      UCSR0A|=_BV(TXC0);

<could TXC0 get set here if conditions are just right>
      UDR0=TxBuffer[TxPos++];

 

vs.

 

      UDR0=TxBuffer[TxPos++];

      UCSR0A|=_BV(TXC0);

<no chance TXC0 gets set unless char is set AND buffer is empty>

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did you answer any of my repeated questions about the importance of this hunt, and the conditions?  I saw a mention of "break".  Indeed, that would be a reason to disable the U(S)ART.  I asked about what modern protocol might be using a break.  No answer on whether you want the operation in progress to abort or not.  If you are indeed going to load UDR as in your latest fragment, then you need to see TXC set (as you were already told about polling above) before you start fussing.  What does loading UDR have to do with a break condition?

 

If you actually tell what you need to do and what problems you are encountering, then there can be more answers. As it is I just see an esoteric question, about angels dancing on the head of a pin.

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why the anger/frustration theusch?  I think the question does stand on its own.  Does it have to have a valid reason to be asked?

 

I am working on an ATMEGA640 that will be used for I/O for a Z80.  The Z80 will issue commands to any of the 4 USARTS via its own IN/OUT instructions:

  PORT OFFSET 		IN							OUT
  0x00			RX byte (in<-data, 0 if empty)				TX byte (out->data, WAITS if buffer full)
  0x01			get RX buffer count (in<-count, opt0<-rxpeek)		reset port (out->_BV(0) clear rx buffer, _BV(1) clear tx buffer, or both)
  0x02			get TX buffer count (in<-count)				send break (out->milliseconds/10)
  0x03			get config (in<-UCSRC, opt0<-UBRRL, opt1<-UBRRH)	set config (opt0->UBRRL, opt1->UBRRH, out->UCSRC)

I want it to be able to send break seamlessly.  I am assuming I will purge the TX buffer if there is anything going on, but I'm waiting for some more thoughts on breaks on another forum before deciding that.

 

So, I can clear the flag before writing UDR like the datasheet suggests, or I could do it in reverse which makes more sense to me based on what the datasheet says.  Either way is it a huge deal?  No, but I figured this forum likes to get to the bottom of how AVR's work down to the instruction...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

alank2 wrote:

Either way is it a huge deal?

Up to you to decide.

 

Clearing the TXC flag before placing a character

in UDR guarantees the TXC flag will be set later.

 

Reversing the order doesn't provide this same

guarantee.

 

--Mike

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Interesting point Mike - could any frame possibly be fully transmitted BEFORE the very next instruction that clears the TXC flag assuming an atomic section?

 

Which brings up another question - if you clear the TXC flag before writing UDR and it isn't an atomic section, that only increases the chance that you cleared the flag and some condition can set it BEFORE it gets back to writing UDR which would have prevented it from being set...

 

It seems to me that the very safest thing to do is to write UDR and then clear the flag in an atomic section...  In this case, first writing UDR means that TCX *can't* be falsely set so when you clear it, it will stay cleared until all bits are shifted out and the buffer is empty.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Use a separate pin to generate the break. Wire tx via a 1k resistor to the i/o output pin and that becomes your tx line. When the usart is idle, ie pin high, you can easily pull it low with your output pin.

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think I get what you're after, you want TXC to

indicate when all data has been sent to a peer.

 

It's usually better to have the peer respond with

an "I got it" message. This is how protocols on

the internet are designed, for example.

 

Disabling interrupts and doing the two operations

back to back should work how you want though.

 

--Mike

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Absolutely Mike - I want to see that the TXCn flag being set means there are no current transmission occurring.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

alank2 wrote:
So, I can clear the flag before writing UDR like the datasheet suggests, or I could do it in reverse which makes more sense to me based on what the datasheet says.

Sheesh.  That would make no sense, in your code fragment.  It is obviously a ring-buffer implementation.  You would send the next byte, if any, after the previous is done.

 

Now, as writing a 1 clears the bit and it takes some time to actually send a byte, your way probably [would have to be a long ISR hitting right at the UDR load] won't cause any harm, it won't do any good and leaves a hole.

 

In polling mode, you only clear the flag and reload the UDR after it has been set.

 

alank2 wrote:
Absolutely Mike - I want to see that the TXCn flag being set means there are no current transmission occurring.

Very simplistic.  You have to know how many bytes you have queued up, if you are using a fairly-modern AVR8 model and you are using the UDRE method.

 

Yet again, it sure would help if you tell what you are trying to accomplish.  Yet again, you mentioned "break" but have not made it clear why TXC in steady-state operation might be related.

 

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

alank2 wrote:
So no one has any additional thoughts about the order of clearing the TXCn flag vs. setting UDR based on what the datasheet says?
I clear it after the write to UDR (atomically).  This guards against the race you mention in your #4.  When handling the UART with interrupts, the clear may not be necessary depending on how you're handing the UART.

 

avr-mike wrote:
Clearing the TXC flag before placing a character in UDR guarantees the TXC flag will be set later. Reversing the order doesn't provide this same guarantee.
I don't think so.  Clearing it after does not break the guarantee that it will be set later, unless you can't control the amount of time between the write to UDR and the write to TXC.  With interrupt enabled, you can't control that.  With them disabled, you can.  Clearing TXC before writing to UDR cannot preclude the mentioned race.  Yes it guarantees that TXC will be set, but it does note guarantee when that it will be the result of the completed transmission of the last frame written to UDR.
avr-mike wrote:
Disabling interrupts and doing the two operations back to back should work how you want though.
Correct.

 

A break can also be generated by changing baud rate to a slower speed, and transmitting a 0x00 frame, then restoring the baud rate.   That would be one reason to monitor TXC, both before the break, and after it.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Sun. Mar 24, 2019 - 09:27 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:
I clear it after the write to UDR (atomically).  This guards against the race you mention in your #4.

 

Thanks joeymorin - that is exactly what I was wondering.

 

joeymorin wrote:
When handling the UART with interrupts, the clear may not be necessary depending on how you're handing the UART.

 

If you don't mind could you elaborate on this scenario?

 

Thanks!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

alank2 wrote:
If you don't mind could you elaborate on this scenario?
If you enable TXCIEn and provide USART_TX_vect, then the flag will be cleared by hardware when the interrupt is serviced.

 

The ISR for TXCn can be used for a number of things.  In your case, it can be used to manage reconfiguring the USART for sending a break, and for restoring normal operation thereafter.  State in the ISR can help it manage which action to take.

 

Other uses include managing direction switchover in half-duplex comms, such as might be used with RS485.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Joey!