Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending mutiple characters using USART1 on an atmega4809 results in 0xFF to be send

Solution:

Turns out it did not have anything to do with the USART. The problem was in the Makefile. I reused a Makefile I have been using for atmega328p and atmega2560 for a long time. But this Makefile does not include the .rodata section when converting the elf to hex file. I guess this section is never used for the "older" atmega parts. After including the .rodata section in the hex file everything worked as expected for the atmega4809.

Makefile part before:

$(OUT).hex: $(OUT).elf
    rm -f $(OUT).hex $(OUT).eep.hex
    $(OBJCOPY) -j .text -j .data -O ihex $(OUT).elf $(OUT).hex
    $(SIZE) $(OUT).hex

Makefile part after:

$(OUT).hex: $(OUT).elf
    rm -f $(OUT).hex $(OUT).eep.hex
    $(OBJCOPY) -j .text -j .data -j .rodata -O ihex $(OUT).elf $(OUT).hex
    $(SIZE) $(OUT).hex

Original question:

The following code results in:

enter image description here

#include <avr/io.h>

#define BAUDRATE 115200
#define BAUD_REG (F_CPU  * 64UL) / (16UL * BAUDRATE) 

void usart_init(USART_t * usart) {
  // Sets up usart
  usart->BAUD = BAUD_REG;
  usart->CTRLB = (1 << USART_TXEN_bp) | (1 << USART_RXEN_bp);
}

void usart_write(USART_t * usart, char c) {
    // Wait TX ready
    while (!(usart->STATUS & USART_DREIF_bm)) {;;}
    // Send character
    usart->TXDATAL = c;
}

int main(void)
{
  // Setup 16 MHz clock internal clock
  CCP = 0xD8;
  CLKCTRL_MCLKCTRLB = 0;

  // Setup uart1
  // Set alternate pin mux for uart1 to PC4 and PC5
  PORTMUX.USARTROUTEA |= PORTMUX_USART1_0_bm;
  // Set TX pin output
  VPORTC.DIR |= PIN4_bm;
  // Setup USART1
  usart_init(&USART1);

  // String to send
  char st[] = "Hello world!";
  // Pointer to iterate of characters
  char * st_ptr = st;

  // Send char -> works fine
  usart_write(&USART1, 'a');

  // Send string -> sends garbage
  while (*st_ptr) {
    usart_write(&USART1, *st_ptr++);
  }

  // Send another char -> works fine
  usart_write(&USART1, 'b');

  while (1) {;;}
}

I would expect "aHello world!b".

Writing single characters always works fine. When writing strings, the first character is fine the remaining characters result in 0xFF.

  • I've tried different baudrates (all same result).

  • Different compilers (The microchip toolchain, manually build gcc).

  • Adding a delay after sending each character. (same result).

What am I missing here?

Update: I changed to sending code to:

  // Send char -> works fine
  usart_write(&USART1, 'a');

  // String to send
  const char* st = "Hello world!";
  uint8_t i;
  for (i=0; i<8; i++) {
    char s = st[i];
    usart_write(&USART1, s);
  }

  // Send another char -> works fine
  usart_write(&USART1, 'b');

No difference unfortunately: a��������b

Update 2, progress:

  // Send char -> works fine
  usart_write(&USART1, 'a');

  // String to send
  const char* st = "Hello world!";
  usart_write(&USART1, st[0]);
  usart_write(&USART1, st[1]);
  usart_write(&USART1, st[2]);
  usart_write(&USART1, st[3]);
  usart_write(&USART1, st[4]);

  // Send another char -> works fine
  usart_write(&USART1, 'b');

Results in: aHellob

update 3:

  // Send char -> works fine
  usart_write(&USART1, 'a');

  // String to send
  const char* st = "UUUUUUUU";

  uint8_t i;
  for (i=0; i<8; i++) {
    char s = st[i];
    usart_write(&USART1, s);
  }

  usart_write(&USART1, st[0]);
  usart_write(&USART1, st[1]);
  usart_write(&USART1, st[2]);
  usart_write(&USART1, st[3]);
  usart_write(&USART1, st[4]);

  // Send another char -> works fine
  usart_write(&USART1, 'b');

No luck: a��������UUUUUb

Update 4 (delay added):

  // Send char -> works fine
  usart_write(&USART1, 'a');

  // String to send
  const char* st = "Hello world!";

  uint8_t i;
  for (i=0; i<8; i++) {
    char s = st[i];
    usart_write(&USART1, s);
    _delay_ms(10);
  }

  usart_write(&USART1, st[0]);
  usart_write(&USART1, st[1]);
  usart_write(&USART1, st[2]);
  usart_write(&USART1, st[3]);
  usart_write(&USART1, st[4]);

  // Send another char -> works fine
  usart_write(&USART1, 'b');

No luck: a��������Hellob

update 5: Found: hello world example Where the following code is used:

void USART1_sendChar(char c)
{
    while (!(USART1.STATUS & USART_DREIF_bm))
    {
        ;
    }        
    USART1.TXDATAL = c;
}

void USART1_sendString(char *str)
{
    for(size_t i = 0; i < strlen(str); i++)
    {
        USART1_sendChar(str[i]);
    }
}

Seems very similar

Update 6: Changed clock to 20MHz internal oscillator Disabled compiler optimizations, makefile snip:

# parent directory of the toolchain, device pack, and pyupdi directories
AVR_BASE_DIR      := /home/paul/workspace/atmega4809
#AVR_TOOLCHAIN_DIR := $(AVR_BASE_DIR)/avr8-gnu-toolchain-$(HOST_OS)_$(HOST_ARCH)
AVR_TOOLCHAIN_DIR := /usr
AVR_DFP_DIR       := $(lastword $(sort $(wildcard $(AVR_BASE_DIR)/Atmel.ATmega_DFP*)))

#CFLAGS_COMMON = -O2 -B $(AVR_DFP_DIR)/gcc/dev/$(DEVICE) -I $(AVR_DFP_DIR)/include -Wall -DF_CPU=$(F_CPU) -mmcu=$(DEVICE) -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -fdata-sections -ffunction-sections --param=min-pagesize=0 -mrelax -MMD -MP -Wa,-adhlns=$(OUT).lst
CFLAGS_COMMON = -O0 -B $(AVR_DFP_DIR)/gcc/dev/$(DEVICE) -I $(AVR_DFP_DIR)/include -Wall -DF_CPU=$(F_CPU) -mmcu=$(DEVICE) --param=min-pagesize=0 -mrelax -MMD -MP -Wa,-adhlns=$(OUT).lst
  // Send char -> works fine
  usart_write(&USART1, 'a');

  // String to send
  const char* st = "Hello world!";

  uint8_t i;
  for (i=0; i<8; i++) {
    char s = st[i];
    usart_write(&USART1, s);
  }

  usart_write(&USART1, st[0]);
  usart_write(&USART1, st[1]);
  usart_write(&USART1, st[2]);
  usart_write(&USART1, st[3]);
  usart_write(&USART1, st[4]);

  // Send another char -> works fine
  usart_write(&USART1, 'b');

Now every char from string "st" fails : a�������������b

Turning compiler optimizations back on:

CFLAGS_COMMON = -O2 -B $(AVR_DFP_DIR)/gcc/dev/$(DEVICE) -I $(AVR_DFP_DIR)/include -Wall -DF_CPU=$(F_CPU) -mmcu=$(DEVICE) -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -fdata-sections -ffunction-sections --param=min-pagesize=0 -mrelax -MMD -MP -Wa,-adhlns=$(OUT).lst

Some chars are working again:

a��������Hellob

Update 7:

  const char st[] = "Hello world!";

results in: a��������He���b

  const char * st = "Hello world!";

results in: a��������Hellob

update 8: Switched to usart2: Same result

Update 9: Its the initialization of the array:

 // String to send
  char st[8];
  st[0] = 'H';
  st[1] = 'e';
  st[2] = 'l';
  st[3] = 'l';
  st[4] = 'o';
  st[5] = ' ';
  st[6] = 'w';
  st[7] = 'o';

  // Send char -> works fine
  usart_write(&USART2, 'a');

  uint8_t i;
  for (i=0; i<8; i++) {
    char s = st[i];
    usart_write(&USART2, s);
  }

  usart_write(&USART2, st[0]);
  usart_write(&USART2, st[1]);
  usart_write(&USART2, st[2]);
  usart_write(&USART2, st[3]);
  usart_write(&USART2, st[4]);

  // Send another char -> works fine
  usart_write(&USART2, 'b');

Result: aHello woHellob

like image 801
Paulusbrand Avatar asked Oct 25 '25 01:10

Paulusbrand


1 Answers

Here is disassembly blink.hex file from the link in comments

Disassembly of section .sec1:

00000000 <.sec1>:
   0:   4f c0           rjmp    .+158           ;  0xa0
   2:   00 00           nop
   4:   55 c0           rjmp    .+170           ;  0xb0
   6:   00 00           nop
   8:   53 c0           rjmp    .+166           ;  0xb0
   a:   00 00           nop
   c:   51 c0           rjmp    .+162           ;  0xb0
   e:   00 00           nop
  10:   4f c0           rjmp    .+158           ;  0xb0
  12:   00 00           nop
  14:   4d c0           rjmp    .+154           ;  0xb0
  16:   00 00           nop
  18:   4b c0           rjmp    .+150           ;  0xb0
  1a:   00 00           nop
  1c:   49 c0           rjmp    .+146           ;  0xb0
  1e:   00 00           nop
  20:   47 c0           rjmp    .+142           ;  0xb0
  22:   00 00           nop
  24:   45 c0           rjmp    .+138           ;  0xb0
  26:   00 00           nop
  28:   43 c0           rjmp    .+134           ;  0xb0
  2a:   00 00           nop
  2c:   41 c0           rjmp    .+130           ;  0xb0
  2e:   00 00           nop
  30:   3f c0           rjmp    .+126           ;  0xb0
  32:   00 00           nop
  34:   3d c0           rjmp    .+122           ;  0xb0
  36:   00 00           nop
  38:   3b c0           rjmp    .+118           ;  0xb0
  3a:   00 00           nop
  3c:   39 c0           rjmp    .+114           ;  0xb0
  3e:   00 00           nop
  40:   37 c0           rjmp    .+110           ;  0xb0
  42:   00 00           nop
  44:   35 c0           rjmp    .+106           ;  0xb0
  46:   00 00           nop
  48:   33 c0           rjmp    .+102           ;  0xb0
  4a:   00 00           nop
  4c:   31 c0           rjmp    .+98            ;  0xb0
  4e:   00 00           nop
  50:   2f c0           rjmp    .+94            ;  0xb0
  52:   00 00           nop
  54:   2d c0           rjmp    .+90            ;  0xb0
  56:   00 00           nop
  58:   2b c0           rjmp    .+86            ;  0xb0
  5a:   00 00           nop
  5c:   29 c0           rjmp    .+82            ;  0xb0
  5e:   00 00           nop
  60:   27 c0           rjmp    .+78            ;  0xb0
  62:   00 00           nop
  64:   25 c0           rjmp    .+74            ;  0xb0
  66:   00 00           nop
  68:   23 c0           rjmp    .+70            ;  0xb0
  6a:   00 00           nop
  6c:   21 c0           rjmp    .+66            ;  0xb0
  6e:   00 00           nop
  70:   1f c0           rjmp    .+62            ;  0xb0
  72:   00 00           nop
  74:   1d c0           rjmp    .+58            ;  0xb0
  76:   00 00           nop
  78:   1b c0           rjmp    .+54            ;  0xb0
  7a:   00 00           nop
  7c:   19 c0           rjmp    .+50            ;  0xb0
  7e:   00 00           nop
  80:   17 c0           rjmp    .+46            ;  0xb0
  82:   00 00           nop
  84:   15 c0           rjmp    .+42            ;  0xb0
  86:   00 00           nop
  88:   13 c0           rjmp    .+38            ;  0xb0
  8a:   00 00           nop
  8c:   11 c0           rjmp    .+34            ;  0xb0
  8e:   00 00           nop
  90:   0f c0           rjmp    .+30            ;  0xb0
  92:   00 00           nop
  94:   0d c0           rjmp    .+26            ;  0xb0
  96:   00 00           nop
  98:   0b c0           rjmp    .+22            ;  0xb0
  9a:   00 00           nop
  9c:   09 c0           rjmp    .+18            ;  0xb0
  9e:   00 00           nop
  a0:   11 24           eor     r1, r1
  a2:   1f be           out     0x3f, r1        ; 63
  a4:   cf ef           ldi     r28, 0xFF       ; 255
  a6:   cd bf           out     0x3d, r28       ; 61
  a8:   df e3           ldi     r29, 0x3F       ; 63
  aa:   de bf           out     0x3e, r29       ; 62
  ac:   02 d0           rcall   .+4             ;  0xb2
  ae:   3d c0           rjmp    .+122           ;  0x12a
  b0:   a7 cf           rjmp    .-178           ;  0x0
  b2:   cd b7           in      r28, 0x3d       ; 61
  b4:   de b7           in      r29, 0x3e       ; 62
  b6:   2d 97           sbiw    r28, 0x0d       ; 13
  b8:   cd bf           out     0x3d, r28       ; 61
  ba:   de bf           out     0x3e, r29       ; 62
  bc:   88 ed           ldi     r24, 0xD8       ; 216
  be:   84 bf           out     0x34, r24       ; 52
  c0:   10 92 61 00     sts     0x0061, r1      ;  0x800061
  c4:   80 91 e2 05     lds     r24, 0x05E2     ;  0x8005e2
  c8:   84 60           ori     r24, 0x04       ; 4
  ca:   80 93 e2 05     sts     0x05E2, r24     ;  0x8005e2
  ce:   44 9a           sbi     0x08, 4 ; 8
  d0:   86 eb           ldi     r24, 0xB6       ; 182
  d2:   92 e0           ldi     r25, 0x02       ; 2
  d4:   80 93 28 08     sts     0x0828, r24     ;  0x800828
  d8:   90 93 29 08     sts     0x0829, r25     ;  0x800829
  dc:   80 ec           ldi     r24, 0xC0       ; 192
  de:   80 93 26 08     sts     0x0826, r24     ;  0x800826
  e2:   8d e0           ldi     r24, 0x0D       ; 13
  e4:   ee e2           ldi     r30, 0x2E       ; 46
  e6:   f1 e4           ldi     r31, 0x41       ; 65
  e8:   de 01           movw    r26, r28
  ea:   11 96           adiw    r26, 0x01       ; 1
  ec:   01 90           ld      r0, Z+
  ee:   0d 92           st      X+, r0
  f0:   8a 95           dec     r24
  f2:   e1 f7           brne    .-8             ;  0xec
  f4:   80 91 24 08     lds     r24, 0x0824     ;  0x800824
  f8:   85 ff           sbrs    r24, 5
  fa:   fc cf           rjmp    .-8             ;  0xf4
  fc:   81 e6           ldi     r24, 0x61       ; 97
  fe:   80 93 22 08     sts     0x0822, r24     ;  0x800822
 102:   fe 01           movw    r30, r28
 104:   32 96           adiw    r30, 0x02       ; 2
 106:   98 e4           ldi     r25, 0x48       ; 72
 108:   80 91 24 08     lds     r24, 0x0824     ;  0x800824
 10c:   85 ff           sbrs    r24, 5
 10e:   fc cf           rjmp    .-8             ;  0x108
 110:   90 93 22 08     sts     0x0822, r25     ;  0x800822
 114:   91 91           ld      r25, Z+
 116:   91 11           cpse    r25, r1
 118:   f7 cf           rjmp    .-18            ;  0x108
 11a:   80 91 24 08     lds     r24, 0x0824     ;  0x800824
 11e:   85 ff           sbrs    r24, 5
 120:   fc cf           rjmp    .-8             ;  0x11a
 122:   82 e6           ldi     r24, 0x62       ; 98
 124:   80 93 22 08     sts     0x0822, r24     ;  0x800822
 128:   ff cf           rjmp    .-2             ;  0x128
 12a:   f8 94           cli
 12c:   ff cf           rjmp    .-2             ;  0x12c

This part is interesting

char st[] = "Hello world!";
  e2:   8d e0           ldi     r24, 0x0D       ; R24 = 13 (string length)
  e4:   ee e2           ldi     r30, 0x2E       ; R31:R30 (Z) = 0x412E
                                                ; data address about 0x4000 is mapped progmem. 
                                                ; So Z point to address 0x012E in your code 
  e6:   f1 e4           ldi     r31, 0x41       
  e8:   de 01           movw    r26, r28        ;R29:R28 (Y) is pointer to actual stack pointer
  ea:   11 96           adiw    r26, 0x01       ;R27:R26 (X) is now pointer to st

loop:
  ec:   01 90           ld      r0, Z+
  ee:   0d 92           st      X+, r0
  f0:   8a 95           dec     r24
  f2:   e1 f7           brne    .-8             ;  0xec (loop) this loop copy 13 bytes 
                                                ;from PROMEM to SRAM to created array on the stack

But as can you see at address 0x12E in hex file is nothing. Its mean here is 0xFF value what is unprogrammed value for the flash.

In my compiled version with AVR studio is here 13 byte of your string. And in simulator all work OK.

Conclusion You have some problem with linking or converting to hex file.

Edit: I check also blink.elf and rodata is here

Disassembly of section .rodata:

0000412e <_end-0x7fe6d2>:
    412e:   48 65           ori r20, 0x58   ; 88
    4130:   6c 6c           ori r22, 0xCC   ; 204
    4132:   6f 20           and r6, r15
    4134:   77 6f           ori r23, 0xF7   ; 247
    4136:   72 6c           ori r23, 0xC2   ; 194
    4138:   64 21           and r22, r4
    ...

So it's mean that problem is in conversion to hex file. My AVR studio do this by

avr-objcopy.exe" -O ihex -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures  "GccApplication1.elf" "GccApplication1.hex"

Check your cmd. And in your hex file you must find text as last 13 bytes like my hex file. Line :0D01D40048656C6C6F20776F726C642100C1

:100000000C9450000C945A000C945A000C945A0012
:100010000C945A000C945A000C945A000C945A00F8
:100020000C945A000C945A000C945A000C945A00E8
:100030000C945A000C945A000C945A000C945A00D8
:100040000C945A000C945A000C945A000C945A00C8
:100050000C945A000C945A000C945A000C945A00B8
:100060000C945A000C945A000C945A000C945A00A8
:100070000C945A000C945A000C945A000C945A0098
:100080000C945A000C945A000C945A000C945A0088
:100090000C945A000C945A000C945A000C945A0078
:1000A00011241FBECFEFCDBFDFE3DEBF0E9495005E
:1000B0000C94E8000C940000CF93DF9300D0CDB7F0
:1000C000DEB789839A8389819A812BE232E0FC0131
:1000D0002087318789819A8120ECFC0126830000EA
:1000E0000F900F90DF91CF910895CF93DF9300D0C1
:1000F0001F92CDB7DEB789839A836B830000898115
:100100009A81FC018481882F90E080729927892B45
:10011000B1F389819A812B81FC012283000023960F
:10012000CDBFDEBFDF91CF910895CF93DF93CDB7E1
:10013000DEB72F97CDBFDEBF84E390E028EDFC0152
:10014000208381E690E0FC01108280EE95E020EEB5
:1001500035E0F90122812460FC01228388E090E0EF
:1001600028E030E0F90120812061FC01208380E259
:1001700098E00E945C008DE0E4EDF1E4DE0113966E
:1001800001900D928A95E1F7CE01039689839A83B7
:1001900061E680E298E00E9475000EC089819A8134
:1001A0009C012F5F3F4F29833A83FC018081682F98
:1001B00080E298E00E94750089819A81FC0180812B
:1001C000882361F762E680E298E00E947500FFCF25
:0401D000F894FFCFD1
:0D01D40048656C6C6F20776F726C642100C1
:00000001FF
like image 159
Peter Plesník Avatar answered Oct 26 '25 14:10

Peter Plesník