Pau*_*and 4 c embedded avr avr-gcc usart
解决方案:
\n事实证明它与 USART 没有任何关系。问题出在 Makefile 中。我重复使用了长期以来一直用于 atmega328p 和 atmega2560 的 Makefile。但是在将 elf 转换为 hex 文件时,此 Makefile 不包含 .rodata 部分。我想这部分从来没有用于“旧的”atmega 部件。在十六进制文件中包含 .rodata 部分后,一切都按 atmega4809 的预期工作。
\nMakefile 之前的部分:
\n$(OUT).hex: $(OUT).elf\n rm -f $(OUT).hex $(OUT).eep.hex\n $(OBJCOPY) -j .text -j .data -O ihex $(OUT).elf $(OUT).hex\n $(SIZE) $(OUT).hex\n
Run Code Online (Sandbox Code Playgroud)\n之后的 Makefile 部分:
\n$(OUT).hex: $(OUT).elf\n rm -f $(OUT).hex $(OUT).eep.hex\n $(OBJCOPY) -j .text -j .data -j .rodata -O ihex $(OUT).elf $(OUT).hex\n $(SIZE) $(OUT).hex\n
Run Code Online (Sandbox Code Playgroud)\n原问题:
\n以下代码的结果是:
\n\n$(OUT).hex: $(OUT).elf\n rm -f $(OUT).hex $(OUT).eep.hex\n $(OBJCOPY) -j .text -j .data -O ihex $(OUT).elf $(OUT).hex\n $(SIZE) $(OUT).hex\n
Run Code Online (Sandbox Code Playgroud)\n我期待“aHello world!b”。
\n写单个字符总是没问题。写入字符串时,第一个字符即可,其余字符结果为 0xFF。
\n我尝试过不同的波特率(结果相同)。
\n不同的编译器(microchip工具链,手动构建gcc)。
\n发送每个字符后添加延迟。(相同的结果)。
\n我在这里缺少什么?
\n更新:\n我更改为将代码发送至:
\n$(OUT).hex: $(OUT).elf\n rm -f $(OUT).hex $(OUT).eep.hex\n $(OBJCOPY) -j .text -j .data -j .rodata -O ihex $(OUT).elf $(OUT).hex\n $(SIZE) $(OUT).hex\n
Run Code Online (Sandbox Code Playgroud)\n不幸的是没有区别:\na\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef \xbf\xbdb
\n更新2,进度:
\n#include <avr/io.h>\n\n#define BAUDRATE 115200\n#define BAUD_REG (F_CPU * 64UL) / (16UL * BAUDRATE) \n\nvoid usart_init(USART_t * usart) {\n // Sets up usart\n usart->BAUD = BAUD_REG;\n usart->CTRLB = (1 << USART_TXEN_bp) | (1 << USART_RXEN_bp);\n}\n\nvoid usart_write(USART_t * usart, char c) {\n // Wait TX ready\n while (!(usart->STATUS & USART_DREIF_bm)) {;;}\n // Send character\n usart->TXDATAL = c;\n}\n\nint main(void)\n{\n // Setup 16 MHz clock internal clock\n CCP = 0xD8;\n CLKCTRL_MCLKCTRLB = 0;\n\n // Setup uart1\n // Set alternate pin mux for uart1 to PC4 and PC5\n PORTMUX.USARTROUTEA |= PORTMUX_USART1_0_bm;\n // Set TX pin output\n VPORTC.DIR |= PIN4_bm;\n // Setup USART1\n usart_init(&USART1);\n\n // String to send\n char st[] = "Hello world!";\n // Pointer to iterate of characters\n char * st_ptr = st;\n\n // Send char -> works fine\n usart_write(&USART1, \'a\');\n\n // Send string -> sends garbage\n while (*st_ptr) {\n usart_write(&USART1, *st_ptr++);\n }\n\n // Send another char -> works fine\n usart_write(&USART1, \'b\');\n\n while (1) {;;}\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n结果:\naHellob
\n更新3:
\n // Send char -> works fine\n usart_write(&USART1, \'a\');\n\n // String to send\n const char* st = "Hello world!";\n uint8_t i;\n for (i=0; i<8; i++) {\n char s = st[i];\n usart_write(&USART1, s);\n }\n\n // Send another char -> works fine\n usart_write(&USART1, \'b\');\n
Run Code Online (Sandbox Code Playgroud)\n不走运:\na\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\ xbf\xbdUUUUUb
\n更新4(添加延迟):
\n // Send char -> works fine\n usart_write(&USART1, \'a\');\n\n // String to send\n const char* st = "Hello world!";\n usart_write(&USART1, st[0]);\n usart_write(&USART1, st[1]);\n usart_write(&USART1, st[2]);\n usart_write(&USART1, st[3]);\n usart_write(&USART1, st[4]);\n\n // Send another char -> works fine\n usart_write(&USART1, \'b\');\n
Run Code Online (Sandbox Code Playgroud)\n不走运:\na\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\ xbf\xbd你好
\n更新 5:\n发现:hello world 示例\n其中使用以下代码:
\n // Send char -> works fine\n usart_write(&USART1, \'a\');\n\n // String to send\n const char* st = "UUUUUUUU";\n\n uint8_t i;\n for (i=0; i<8; i++) {\n char s = st[i];\n usart_write(&USART1, s);\n }\n\n usart_write(&USART1, st[0]);\n usart_write(&USART1, st[1]);\n usart_write(&USART1, st[2]);\n usart_write(&USART1, st[3]);\n usart_write(&USART1, st[4]);\n\n // Send another char -> works fine\n usart_write(&USART1, \'b\');\n
Run Code Online (Sandbox Code Playgroud)\n看起来很相似
\n更新 6:\n将时钟更改为 20MHz 内部振荡器\n禁用编译器优化,makefile 片段:
\n# parent directory of the toolchain, device pack, and pyupdi directories\nAVR_BASE_DIR := /home/paul/workspace/atmega4809\n#AVR_TOOLCHAIN_DIR := $(AVR_BASE_DIR)/avr8-gnu-toolchain-$(HOST_OS)_$(HOST_ARCH)\nAVR_TOOLCHAIN_DIR := /usr\nAVR_DFP_DIR := $(lastword $(sort $(wildcard $(AVR_BASE_DIR)/Atmel.ATmega_DFP*)))\n\n#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\nCFLAGS_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\n
Run Code Online (Sandbox Code Playgroud)\n // Send char -> works fine\n usart_write(&USART1, \'a\');\n\n // String to send\n const char* st = "Hello world!";\n\n uint8_t i;\n for (i=0; i<8; i++) {\n char s = st[i];\n usart_write(&USART1, s);\n _delay_ms(10);\n }\n\n usart_write(&USART1, st[0]);\n usart_write(&USART1, st[1]);\n usart_write(&USART1, st[2]);\n usart_write(&USART1, st[3]);\n usart_write(&USART1, st[4]);\n\n // Send another char -> works fine\n usart_write(&USART1, \'b\');\n
Run Code Online (Sandbox Code Playgroud)\n现在字符串“st”中的每个字符都失败:\na\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef \xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdb
\n重新打开编译器优化:
\nCFLAGS_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\n
Run Code Online (Sandbox Code Playgroud)\n一些字符再次工作:
\na\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdHellob
\n更新7:
\nvoid USART1_sendChar(char c)\n{\n while (!(USART1.STATUS & USART_DREIF_bm))\n {\n ;\n } \n USART1.TXDATAL = c;\n}\n\nvoid USART1_sendString(char *str)\n{\n for(size_t i = 0; i < strlen(str); i++)\n {\n USART1_sendChar(str[i]);\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n结果为:\na\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\ xbf\xbdHe\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdb
\n# parent directory of the toolchain, device pack, and pyupdi directories\nAVR_BASE_DIR := /home/paul/workspace/atmega4809\n#AVR_TOOLCHAIN_DIR := $(AVR_BASE_DIR)/avr8-gnu-toolchain-$(HOST_OS)_$(HOST_ARCH)\nAVR_TOOLCHAIN_DIR := /usr\nAVR_DFP_DIR := $(lastword $(sort $(wildcard $(AVR_BASE_DIR)/Atmel.ATmega_DFP*)))\n\n#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\nCFLAGS_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\n
Run Code Online (Sandbox Code Playgroud)\n结果为:\na\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\ xbf\xbd你好
\n更新 8:\n切换到 usart2:\n相同的结果
\n更新 9:\n它是数组的初始化:
\n // Send char -> works fine\n usart_write(&USART1, \'a\');\n\n // String to send\n const char* st = "Hello world!";\n\n uint8_t i;\n for (i=0; i<8; i++) {\n char s = st[i];\n usart_write(&USART1, s);\n }\n\n usart_write(&USART1, st[0]);\n usart_write(&USART1, st[1]);\n usart_write(&USART1, st[2]);\n usart_write(&USART1, st[3]);\n usart_write(&USART1, st[4]);\n\n // Send another char -> works fine\n usart_write(&USART1, \'b\');\n
Run Code Online (Sandbox Code Playgroud)\n结果:\naHello woHellob
\n这是评论中链接的反汇编blink.hex文件
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
Run Code Online (Sandbox Code Playgroud)
这部分很有趣
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
Run Code Online (Sandbox Code Playgroud)
但正如您所见,十六进制文件中的地址 0x12E 没有任何内容。这里它的意思是 0xFF 值,即闪存的未编程值。
在我用 AVR studio 编译的版本中,这里是字符串的 13 个字节。并且在模拟器中一切正常。
结论您在链接或转换为十六进制文件时遇到一些问题。
编辑:我还检查blink.elf和rodata在这里
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
...
Run Code Online (Sandbox Code Playgroud)
所以这意味着问题出在转换为十六进制文件时。我的 AVR 工作室是这样做的
avr-objcopy.exe" -O ihex -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures "GccApplication1.elf" "GccApplication1.hex"
Run Code Online (Sandbox Code Playgroud)
检查你的命令。在您的十六进制文件中,您必须找到最后 13 个字节的文本,就像我的十六进制文件一样。线路: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
Run Code Online (Sandbox Code Playgroud)