| Author |
Message |
|
|
Posted: Jul 24, 2012 - 09:18 PM |
|


Joined: Mar 20, 2001
Posts: 1517
Location: Switzerland
|
|
I'm stuck getting a trivial USART test program working on a xmega32A4U.
Trying to debug it with some connected LEDs renders the problem even more confusing. The following code is supposed to write 'Hello World' at 9600 baud via USARTD0 (pin D3). It works only partially with the following symptoms:
- If the line with 'light LED 0' is commented I get an infinite amount of the character 'H'. LED1 never lights (the printf call never returns).
- If the line with 'light LED 0' is active, the LED0 lights, but I get no output at all. Nothing, nada.
I'm using the AVR toolchain provided by Atmel (Release 3.4.0.663).
Here the compilation steps:
Code:
avr-gcc -g -DF_CPU=2000000 -Wall -Os -mmcu=atxmega32a4u -c -o serial-out.o serial-out.c
avr-gcc -g -DF_CPU=2000000 -Wall -Os -mmcu=atxmega32a4u -Wl,-Map,serial-out.map -o serial-out.elf serial-out.o
avr-objcopy -j .text -j .data -O ihex serial-out.elf serial-out.hex
avrdude -q -p x32a4 -F -c dragon_pdi -P usb -U flash:w:serial-out.hex
Here the program:
Code:
#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>
static int uart_putchar(char c, FILE *stream);
static void uart_init (void);
static FILE mystdout = FDEV_SETUP_STREAM (uart_putchar, NULL, _FDEV_SETUP_WRITE);
int main (void)
{
uart_init();
stdout = &mystdout;
PORTC.DIR = 0xFF; // port C
while (1)
// PORTC.OUTSET = PIN0_bm; // light LED 0
printf("Hello, world!\n");
PORTC.OUTSET = PIN1_bm; // light LED 1
}
static int uart_putchar (char c, FILE *stream) {
if (c == '\n')
uart_putchar('\r', stream);
// Wait for the transmit buffer to be empty
while ( !( USARTD0.STATUS & USART_DREIF_bm) );
// Put our character into the transmit buffer
USARTD0.DATA = c;
return 0;
}
// Init USART. Transmit only (we're not receiving anything)
// We use USARTD0, transmit pin on PC3.
// Want 9600 baud. Have a 2 MHz clock. BSCALE = 0
// BSEL = ( 2000000 / (2^0 * 16*9600)) -1 = 12
// Fbaud = 2000000 / (2^0 * 16 * (12+1)) = 9615 bits/sec
static void uart_init (void) {
// Set the TxD pin high - set PORTC DIR register bit 3 to 1
PORTD.OUTSET = PIN3_bm;
// Set the TxD pin as an output - set PORTC OUT register bit 3 to 1
PORTD.DIRSET = PIN3_bm;
// Set baud rate & frame format
USARTD0.BAUDCTRLB = 0; // BSCALE = 0 as well
USARTD0.BAUDCTRLA = 12;
// Set mode of operation
USARTD0.CTRLA = 0; // no interrupts please
USARTD0.CTRLC = 0x03; // async, no parity, 8 bit data, 1 stop bit
// Enable transmitter only
USARTD0.CTRLB = USART_TXEN_bm;
}
Edit: This is essentially a code snippet copied from the Web. But simple enough that it should just work, |
_________________ Markus
Last edited by markus_b on Aug 01, 2012 - 09:32 PM; edited 1 time in total
|
| |
|
|
|
|
|
Posted: Jul 24, 2012 - 11:15 PM |
|


Joined: Apr 29, 2011
Posts: 207
Location: Portland, OR, US
|
|
I don't know why turning on an LED would prevent the USART from working...unless you have power problems.
The code looks like it should work. As a test, you could try replacing USART_DREIF_bm with USART_TXCIF_bm in the uart_putchar's while() loop. |
_________________ Gamu The Killer Narwhal
Portland, OR, US
_________________
Atmel Studio 6.1 on Windows 8
XMEGA-A1/XMEGA-A3BU
AVR Dragon (Ver. 2)
JTAGICE mkII
|
| |
|
|
|
|
|
Posted: Jul 24, 2012 - 11:42 PM |
|


Joined: Sep 04, 2007
Posts: 356
Location: Oxford (England)
|
|
Would curly braces after the while(1) help?
This isn't Python, you know!  |
_________________ Nigel Batten
www.batsocks.co.uk
|
| |
|
|
|
|
|
Posted: Jul 25, 2012 - 07:02 AM |
|


Joined: Mar 20, 2001
Posts: 1517
Location: Switzerland
|
|
Adding curly braces around the loop helps in part. It explains case 2), where I have no output. But for case 1) it is till the same: I get a endless loop of 'H' characters (1st character of the string, actually) and the printf never returns.
The loop looks now (and should have been looking) like this:
Code:
while (1) {
PORTC.OUTSET = PIN0_bm; // light LED 0
printf("Hello, world!\n");
PORTC.OUTSET = PIN1_bm; // light LED 1
}
As Output I get this:
Code:
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
|
_________________ Markus
|
| |
|
|
|
|
|
Posted: Jul 25, 2012 - 08:26 AM |
|

Joined: Jul 04, 2012
Posts: 21
Location: Madrid
|
|
Not sure how printf is implemented on avr, but maybe you should try creating your own function to output streams, something like
Code:
int sendString(char *string, FILE *stream){
while(*(string) != "\0")
usart_putchar(*(string++), stream);
return 0;
}
|
|
|
| |
|
|
|
|
|
Posted: Jul 25, 2012 - 09:56 AM |
|


Joined: Sep 04, 2007
Posts: 356
Location: Oxford (England)
|
|
Markus,
The code works fine on my XMega32A4U:
Code:
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
I'm also using:
Code:
avr-gcc (AVR_8_bit_GNU_Toolchain_3.4.0_663) 4.6.2
For reference (and it's unlikely to help), here's the compile command (spat out from my 'normal' makefile - I don't pretend to understand it all)
Code:
avr-gcc -c -mmcu=atxmega32a4 -I. -gdwarf-2 -DF_CPU=2000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./main.lst -std=gnu99 -MMD -MP -MF .dep/main.o.d main.c -o main.o
and here's the linker command...
Code:
avr-gcc -mmcu=atxmega32a4 -I. -gdwarf-2 -DF_CPU=2000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.o -std=gnu99 -MMD -MP -MF .dep/main.elf.d main.o --output main.elf -Wl,-Map=main.map,--cref -lm
As shown above, I compiled it for the XMega32A4, but it also works when compiled for the XMega32A4U (which makes the code slightly larger). |
_________________ Nigel Batten
www.batsocks.co.uk
|
| |
|
|
|
|
|
Posted: Jul 25, 2012 - 10:35 AM |
|


Joined: Mar 20, 2001
Posts: 1517
Location: Switzerland
|
|
|
algrizz wrote:
Not sure how printf is implemented on avr, but maybe you should try creating your own function to output streams, something like
Code:
int sendString(char *string, FILE *stream){
while(*(string) != "\0")
usart_putchar(*(string++), stream);
return 0;
}
I've tried is with your sendString instead of the printf. Same result, it prints 'HHHHHHHHHHHH'. I did have a similar routine on my own before with that same result. Then I went to search for examples on the net.
I've modified your code as follows, the LED does not light !
Code:
int sendString(char *string, FILE *stream){
while(*(string) != "\0") {
uart_putchar(*(string++), stream);
PORTC.OUTSET = PIN2_bm; // light LED 2
}
return 0;
}
Next step: Try with compiler parameters... |
_________________ Markus
|
| |
|
|
|
|
|
Posted: Jul 25, 2012 - 10:47 AM |
|


Joined: Jan 08, 2009
Posts: 1198
Location: Lund, Sweden
|
|
| I tried your code on a 128a1 (changed to USARTE0, since I have a FTDI-chip connected to that). It worked both with your command lines (changed to 128a1) and the commands I happened to have in my Makefile. |
|
|
| |
|
|
|
|
|
Posted: Jul 25, 2012 - 10:57 AM |
|


Joined: Mar 20, 2001
Posts: 1517
Location: Switzerland
|
|
I've attached my testcases. Can someone try the hex files ?
It is using the UARTD0 (Port D3, pin 23) at 9600 baud. |
_________________ Markus
|
| |
|
|
|
|
|
Posted: Jul 25, 2012 - 11:14 AM |
|


Joined: Sep 04, 2007
Posts: 356
Location: Oxford (England)
|
|
The code works.
I've just loaded serial-out.hex-printf onto a 32a4u and it works without any problems. A nice list of hello worlds.
I used
Code:
avrdude -px32a4 -Pusb -cavrisp2 -e -U flash:w:serial-out.hex-printf
and it squirts nicely into my PC via a SparkFun 3.3v FTDI USB adapter.
So if it's not the code... what is it?! Decoupling caps? Rubbish terminal software? Programming failure? |
_________________ Nigel Batten
www.batsocks.co.uk
|
| |
|
|
|
|
|
Posted: Jul 25, 2012 - 11:14 AM |
|


Joined: Mar 20, 2001
Posts: 1517
Location: Switzerland
|
|
| I just reinstalled avr-gcc-4.5.1 (the debian package from the wrightflyer site). There is one difference: Now both printf and sendString generate just 'H' characters. |
_________________ Markus
|
| |
|
|
|
|
|
Posted: Jul 25, 2012 - 11:19 AM |
|


Joined: Mar 20, 2001
Posts: 1517
Location: Switzerland
|
|
|
condemned wrote:
The code works.
I've just loaded serial-out.hex-printf onto a 32a4u and it works without any problems. A nice list of hello worlds.
I used
Code:
avrdude -px32a4 -Pusb -cavrisp2 -e -U flash:w:serial-out.hex-printf
and it squirts nicely into my PC via a SparkFun 3.3v FTDI USB adapter.
So if it's not the code... what is it?! Decoupling caps? Rubbish terminal software? Programming failure?
OK, So I have to verify the hardware. My x32a4u (QFP44) is had-soldered on a breakout board. On the board I do wire Vcc and Gnd together on the two available rails and there is a 100n decoupling cap.
I supply is with power via breadboard 3.3V supply, this supply gets its power from a USB power supply.
I can imagine that something causes a reset (brownout) and the 'H's come from the boot/reset loop.
Thanks for the help ! |
_________________ Markus
|
| |
|
|
|
|
|
Posted: Jul 25, 2012 - 11:27 AM |
|


Joined: Sep 04, 2007
Posts: 356
Location: Oxford (England)
|
|
The other version (serial-out.hex-sendstring) didn't work, however. The compilation warning was the hint...
Changing the code in sendString from
Code:
while(*(string) != "\0") {
to
Code:
while(*(string) != '\0') {
makes it work just fine.
Summary
Both versions of code now work fine.
The sendString version needed a tweak.
Each pair of power pins needs decoupling as close to the pins as possible. |
_________________ Nigel Batten
www.batsocks.co.uk
|
| |
|
|
|
|
|
Posted: Jul 25, 2012 - 11:50 AM |
|


Joined: Mar 20, 2001
Posts: 1517
Location: Switzerland
|
|
I did measure all pins, there is no short between any of them. Vcc and Gnd is connected the respective pins, too. I've measured Vcc at 2.28V. I've measured the noise on Vcc, I have impulses 50mV peak, with a 0.25us period. I suspect they are artifact of the default 2Mhz clock.
However in another test (the venerable led blinky), I make all ports blink and I have PA5 PA6 and PC6 wo do not blinks. All other ports do blink (and a initialize and blink the all pins at once).
Also the chip programs just fine.
Is my chip faulty ? |
_________________ Markus
|
| |
|
|
|
|
|
Posted: Jul 25, 2012 - 01:18 PM |
|


Joined: Sep 04, 2007
Posts: 356
Location: Oxford (England)
|
|
Have you added a decoupling cap to each pair of power pins? Near the pins?
Is the measured 2.28v coming from the 3.3v supply you mentioned earlier? If so, that seems very, very low.
Do you have any brown-out fuses programmed? (note that the brown-out voltages are different between the original and U variants of the chips) |
_________________ Nigel Batten
www.batsocks.co.uk
|
| |
|
|
|
|
|
Posted: Jul 25, 2012 - 02:02 PM |
|


Joined: Mar 20, 2001
Posts: 1517
Location: Switzerland
|
|
I seem to be very prone to typos. The voltage was 3.28 Volt (2.28 was a type). Much better !
In the meantime I've removed the chip and soldered another one in place. Hot air gun to the rescue !
This has solved the blink problem, I suppose the pins were not soldered well enough. This time I used a bit of solder pasta and hot air.
Blocking condensators: There is one on the protoboard. The protoboard has two power rails and all four power pins are connect there with short and quite think wires.
I have not touched the brownout/fuses at all.
Here the setup:
 |
_________________ Markus
|
| |
|
|
|
|
|
Posted: Jul 25, 2012 - 02:38 PM |
|


Joined: Sep 04, 2007
Posts: 356
Location: Oxford (England)
|
|
So there's just one decoupling cap on the whole board
If you've got any more 100nF caps, you could try plugging one into the sockets for each pair of power pins. Whilst not ideal, it might help.
AVR1012 wrote:
Decoupling capacitor should be placed close to the device for each supply pin pair in the signal group, low ESR caps should be used for better decoupling
For reference, I worry if my decoupling caps are farther away than this:
p.s. I love the idea of solder pasta  |
_________________ Nigel Batten
www.batsocks.co.uk
|
| |
|
|
|
|
|
Posted: Jul 25, 2012 - 03:07 PM |
|


Joined: Mar 20, 2001
Posts: 1517
Location: Switzerland
|
|
On the PCB I've designed I have a decoupling cap close to each pin. But I don't think this is that a big deal on a prototype for sending hello world out the UART. I'd complain about noise on my ADC and similar things, fine. But here I have only a micro, completely on its own.
However, I've added now an additional 330n ceramic and a 10u electrolytic. The noise on the power rails is now down to <10mV peak-to-peak. |
_________________ Markus
|
| |
|
|
|
|
|
Posted: Jul 25, 2012 - 03:22 PM |
|


Joined: Mar 20, 2001
Posts: 1517
Location: Switzerland
|
|
Did another test: Added a delay at the start. And added an additional blink there. The LED is now blinking due to a reset loop.
Added the hex here, could you test it ?
Here is sends a single mangled character out on pin23 and blinks o n pin10. |
_________________ Markus
|
| |
|
|
|
|
|
Posted: Jul 25, 2012 - 05:31 PM |
|


Joined: Mar 20, 2001
Posts: 1517
Location: Switzerland
|
|
The following code snipped does work. The problem seems to be related subroutine calls. Do I thrash my stack ? How can I verify ?
Code:
int main (void) {
char *s;
uart_init();
stdout = &mystdout;
PORTC.DIR = 0xFF; // port C
_delay_ms(500);
PORTC.OUTCLR = PIN0_bm; // light LED 0
_delay_ms(500);
while (1) {
s = hello;
PORTC.OUTSET = PIN0_bm; // light LED 0
while (*(s)!='\0') {
while ( !( USARTD0.STATUS & USART_DREIF_bm) );
USARTD0.DATA = *(s++);
}
_delay_ms(100);
PORTC.OUTSET = PIN2_bm; // light LED 1
}
}
|
_________________ Markus
|
| |
|
|
|
|
|
Posted: Jul 26, 2012 - 09:16 AM |
|


Joined: Sep 04, 2007
Posts: 356
Location: Oxford (England)
|
|
Hi Markus,
The .hex works just fine. A continuous stream of
Code:
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Pins c0, c1 and C2 are high. I couldn't see any pulses on them. |
_________________ Nigel Batten
www.batsocks.co.uk
|
| |
|
|
|
|
|
Posted: Jul 26, 2012 - 10:09 AM |
|


Joined: Mar 20, 2001
Posts: 1517
Location: Switzerland
|
|
Thanks Nigel,
It blinks only on reset. It blinks on mine, therefore I have a reset (when calling the sendString routine).
If I integrate the putchar and sendstring into main, then it works, see the last test.
Findings:
- The same binary/hex file runs differently on your atxmega32A4U and on mine. Works on yours, resets on mine.
-> This lets me suspect a hardware problem, causing the reset.
- If I eliminate subroutine calls (everything in main), then it works on mine too.
-> This lets me suspect a software problem (stack overrun), causing the reset.
Confused. |
_________________ Markus
|
| |
|
|
|
|
|
Posted: Aug 01, 2012 - 09:31 PM |
|


Joined: Mar 20, 2001
Posts: 1517
Location: Switzerland
|
|
After a week away from home (with no AVR) and installing Studio 6 in desperation in a VM I found the problem. It was related to stack and subroutine calls and it was hardware. The actual devices I have are xmega16a4u and not xmega32a4u.
What helped mislead me was that avrdude does not know about the -U variety. So I overwrote the signature check with -F, believing that avrdude complains about the signature because of the -U variety. |
_________________ Markus
|
| |
|
|
|
|
|