USART_DREIF_bm after reset never set. Pwr down/up works.

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

Does anyone have problems with the USART when only a reset is performed and not a power down/up?

My code waits for the USART_DREIF_bm flag to be set indicating that it is ok to give the USART a byte.

If I start from power down, everything works. If I do a reset via the debugger or micro reset, the flag is never set.

I thought I'd ask the general question first. If more code is needed I will provide.
Thanks.

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

Are you sending one character before waiting for DREIF?

I do, and have never experienced a problem. Even if the manual says: "The transmit data register (DATA) can only be written when the data register empty flag (DREIF) is set, indicating that the register is empty and ready for new data." But then my app does not care much if there is a message with missing first byte. It will just reroute it to the bit bucket, so that may happen without my knowledge.

Einar Sjaavik

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

It may help if you tell us which Xmega you are using and maybe that bit of code.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

@einar - I always wait for the DRE flag to be set before giving the USART a byte to transmit.

@John - I am using XMEGA32D4. I used CodeWizard to generate the USART initialization code. I have had problems with CodeWizard not generating correct code for setting the system clock speed, so maybe it is that.

Basically to send a byte to the USART the code is as follows:

//wait for xmega to tell us it is ready for a char
// (USART_DREIF_M != 0) and CTS is not high from xbee 
//(PIN0_bm low)
while ( (   ((usart->STATUS & USART_DREIF_bm) == 0)  || (port->IN & PIN0_bm) ) && (iCount < iMaxWaitReady) )
{
  iCount++;
  cpu_delay_us(100,F_CPU32MHZ);  // c
}
		  
	
//	  	msp430 version : if ( ( (IFG2 & 
//UCA0TXIFG) != 0) && ( (P2IN & CTS) == 0)  )

if ( ((usart->STATUS & USART_DREIF_bm) != 0) )
{  // usart says ok to send char.
	usart->DATA = ucChar;
}
else
        return 0;

Note that although I do check for CTS in the main loop, the underlying test for the code to fail is DRE not being set.

And in case you really want to see the busy USART initialization performed by CodeWizard:

// USARTC0 initialization
void usartc0_init(void)
{
	// Note: the correct PORTC direction for the RxD, TxD and XCK signals
	// is configured in the ports_init function

	// Transmitter is enabled
	// Set TxD=1
	PORTC.OUTSET=0x08;
	

	// Communication mode: Asynchronous USART
	// Data bits: 8
	// Stop bits: 1
	// Parity: Disabled
	USARTC0.CTRLC=USART_CMODE_ASYNCHRONOUS_gc | USART_PMODE_DISABLED_gc | USART_CHSIZE_8BIT_gc;

	// Receive complete interrupt: Disabled
	// Transmit complete interrupt: Disabled
	// Data register empty interrupt: Disabled
	USARTC0.CTRLA=(USARTC0.CTRLA & (~(USART_RXCINTLVL_gm | USART_TXCINTLVL_gm | USART_DREINTLVL_gm))) |
	USART_RXCINTLVL_OFF_gc | USART_TXCINTLVL_OFF_gc | USART_DREINTLVL_OFF_gc;

	// Required Baud rate: 600
	// Real Baud Rate: 600.1 (x1 Mode), Error: 0.0 %
	// baud rate = 32,000,000 / (16 * (D04 + 1) = 32,000,000 / (16 * 3333) = 600.06
	// no scale factor needed.
	//USARTC0.BAUDCTRLA=0x04;
	//USARTC0.BAUDCTRLB= 0x0D;

    //Required Baud rate: 9600 - using 32Mhz clock
	// BAUDCTRLA and B calculated by Atmel excel spreadsheet
	// BSEL = 3317 = 0x0CF5
	// BSCALE = -4 = 1100b = 0xC- remember the bscale is high nibble of BAUDCTRLB register so need to multiply by 0x10 
	// BAUDCTRLA = F5
	// BAUDCTRLB = BSCALE + 0X0C
	// X2 = 0  (do not double clock)
	// ERROR% = 0.01%
	USARTC0.BAUDCTRLA = 0xF5;
	USARTC0.BAUDCTRLB = ( 0XC << USART_BSCALE_gp) | 0X0C;
	
    //Required Baud rate: 9600 - using 32Mhz clock
	// BAUDCTRLA and B calculated by Atmel excel spreadsheet
	// BSEL = 207 = 0xCF
	// BSCALE = 0
	// BAUDCTRLA = 0XCF
	// BAUDCTRLB = 0
	// X2 = 0  (do not double clock)
	// ERROR% = 0.16%
	//USARTC0.BAUDCTRLA = 0xCF;
	//USARTC0.BAUDCTRLB = 0;

    //Required Baud rate: 9600 - use this for 2Mhz clock
    // BAUDCTRLA and B calculated by Atmel excel spreadsheet clock set to default 2Mhz
    // BSEL = 12
    // BSCALE = 0
    // BAUDCTRLA = 12
    // BAUDCTRLB = 0
    // X2 = 0  (do not double clock)
    //USARTC0.BAUDCTRLA = 12;
    //USARTC0.BAUDCTRLB = 0;
	
	// Receiver: On
	// Transmitter: On
	// Double transmission speed mode: Off
	// Multi-processor communication mode: Off
	USARTC0.CTRLB=(USARTC0.CTRLB & (~(USART_RXEN_bm | USART_TXEN_bm | USART_CLK2X_bm | USART_MPCM_bm | USART_TXB8_bm))) |
	USART_RXEN_bm | USART_TXEN_bm;
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@einar -

Quote:
Even if the manual says: "The transmit data register (DATA) can only be written when the data register empty flag (DREIF) is set, indicating that the register is empty and ready for new data."

See I thought we were past those days where you don't really do what the manual says. I think the TI MSP chips are better in that respect.

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

Quote:

See I thought we were past those days where you don't really do what the manual says. I think the TI MSP chips are better in that respect.

Say what??

Anyway, your symptoms can often be caused by an uninitialized variable.

-- When started from a cold power-on, SRAM locations (though not guaranteed) will be zeroed.

-- From e.g. external reset, SRAM contents remain.

From the snippet shown, there are several conditions in the first test that lead to the simple check on DREIF. Is the code hanging in that loop, or in the simple test?

If the simple test, then is "usart" pointer set correctly?

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

It doesn't hang - it just times out after so long waiting for the flag to be set and returns 0:

if ( ((usart->STATUS & USART_DREIF_bm) != 0) ) 
{  // usart says ok to send char. 
   usart->DATA = ucChar; 
} 
else 
        return 0;

As far as "is usart being set properly" it is always the address of either USARTC or USARTD. In my case it is currently always USARTC. USARTC is initialized by the codewizard code.

Great suggestion on the SRAM. Once upon a time I would have known that. I'll look at that.

But in general you don't see the problem I describe?

Regarding your "Say What??" comment. Was that regarding "the manual being wrong" or that TI chips/documentation are more reliable?

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

masterofnone wrote:
void usartc0_init(void)
Is there is a PORTC.DIR there somewhere setting txd as output?

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

Yes the txd pin is set as an output. It is Bit3:

// Bit0: Input
// Bit1: Output
// Bit2: Input
// Bit3: Output
// Bit4: Output
// Bit5: Input
// Bit6: Output
// Bit7: Output
PORTC.DIR=0xDA;
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Was that regarding "the manual being wrong" or that TI chips/documentation are more reliable?

Both. I'll grant you a gripe once the cause of the situation is found. Right now the comment, both parts, seems to be a backlash in frustration. After all, are MSP more "reliable" than AVR? We could be here all month just deciding what "reliable" means. Same with the documentation.

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

I grabbed the new datasheet versions, and do not see any applicable data.

The family datasheet has what one would expect:

Quote:
 Bit 5 – DREIF: Data Register Empty Flag
This flag indicates whether the transmit buffer (DATA) is ready to receive new data. The flag is one when the transmit buffer is empty and zero when the transmit buffer contains data to be transmitted that has not yet been moved into the shift register. DREIF is set after a reset to indicate that the transmitter is ready. Always write this bit to zero when writing the STATUS register.

Quite interesting, eh? Supports your "reliability" claim.

But first, let's do a couple things. It would seem like a nearly trivial complete program should demonstrate the symptoms. Can you post an entire program for inspection?

And/or, add a "trap" on the suspect line for the value of "usart". Dump to an EEPROM location for examination, perhaps.

if ( ((usart->STATUS & USART_DREIF_bm) != 0) )
{  // usart says ok to send char.
   usart->DATA = ucChar;
}
else
{
// save or display value of "usart"
// if that seems valid, perhaps important config register values
        return 0; 
}

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

masterofnone wrote:
@einar -
Quote:
Even if the manual says: "The transmit data register (DATA) can only be written when the data register empty flag (DREIF) is set, indicating that the register is empty and ready for new data."

See I thought we were past those days where you don't really do what the manual says. I think the TI MSP chips are better in that respect.

The manual is accurate as far as I can tell. It works fine for me.

Speaking of TI MSP micros we have a product that uses a module from another company with one on it. The module has a non-volatile memory that isn't very non-volatile. Every now and then it gets corrupted. Turns out that there is a silicone bug in many MSP chips that randomly corrupts their memory when the supply voltage drops below a certain level, particularly when it happens slowly. Brown-out detection and other low-voltage protection systems built into the IC don't help. The only solution is an external reset chip, but that brings the minimum operating voltage up to about 3.0V.

So yeah, datasheets and manuals do lie sometimes. This isn't one of those times though, unless you can provide a minimal example to illustrate the problem that doesn't rely on library code.

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

The problem was LOOSE NUT BEHIND THE KEYBOARD.

1) I returned an int to an unsigned char. Funny the compiler didn't flag that (no warnings) despite using function prototypes.
2) I had a counter to keep track of the number of microseconds I was waiting for a byte to be transmitted. I forgot to reset that count after each byte transmitted - so it accumulated and by the 3rd byte had reached the "timeout" count. Still strange that it worked after powerdown but not reset. (As to whether the DREIF flag was never set - I swore I checked that and it wasn't set. But as I've demonstrated my mind is not stable :-)

Perhaps this thread should be deleted so no one is misled to believe there is a problem with the xmega chip (and to cover my embarrassment.)

The Atmel chip is fine. I like TI's examples better than Atmel. They break the examples down to very simple code (no function calls) that demonstrates each feature of the chip.

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

That's the worst type of problems one can have :lol: and we like these kind of thread so that we don't feel alone.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly