英文:
AVR C programming: Code Doesn't Work (port pin won't toggled) Because Function Declared Outside of Main Function
问题
I see your code examples and hex code. If you have any specific questions or need assistance with anything related to these code snippets, please let me know, and I'll do my best to help.
英文:
I tried to programmed my arduino using avr-gcc, as you can see i tried to make a function:
#include <avr/io.h>
#include <util/delay.h>
#define ddr (uint8_t*) 0x24
#define port (uint8_t*) 0x25
//func
void blink(uint8_t* DIRECT,uint8_t* PORT,uint8_t val){
*DIRECT=val;
while(1){
*PORT=val;
_delay_ms(1000);
*PORT=0x0;
_delay_ms(1000);
}
}
int main(void){
uint8_t* DIRECT=ddr;
uint8_t* PORT=port;
blink(ddr,port,0x10);
return 0;
}
somehow the code only works when the 'blink' function declared inside of the main function.
im using avr-gcc on black arch linux, the compilation process doesnt give any error messages, im using arduino uno board with mcu atmega328p
this is the bash script:
#!/bin/bash
avr-gcc -Os -DF_CPU=16000000UL -mmcu=atmega328p -c -o led_func.o led_func.c
avr-gcc -o led_func.bin led_func.o
avr-objcopy -O ihex -R .eeprom led_func.bin led_func.hex
avrdude -F -V -c arduino -p atmega328p -P /dev/ttyACM0 -b 115200 -U flash:w:led_func.hex
i thought it's not normal to declare function inside the main() in c programs base on my experience using c language, but maybe it's different on avr ?
this is the equivalent of the code above with the same problems:
#include <avr/io.h>
#include <util/delay.h>
volatile int noob(){return 0;}
int main(){
//DDRB-->PORTB5
DDRB=0x10;
for(;;){
PORTB=0x10;
_delay_ms(1000);
PORTB=0x0;
_delay_ms(1000);
}
PORTB=0;
noob();
//return 0;
}
this is the hex code for the first code:
:10000000CF93DF930F92CDB7DEB7DC01FB014983BD
:1000100089818C93898180830F90DF91CF9108959E
:0C00200080E184B985B980E090E008958B
:00000001FF
this is the hex code for the last code:
:1000000080E184B985B92FEF33ED90E32150304082
:100010009040E1F700C0000015B82FEF33ED90E3FA
:0E002000215030409040E1F700C00000EBCFCF
:00000001FF
答案1
得分: 1
Here is the translation of the provided text:
我反编译了两个十六进制文件。两者都很奇怪。
第一个代码:
这段代码不能正常工作。我认为它只是一个已编译但未链接完成的模块。
第二个代码:
这段代码在R1寄存器为0的情况下可以工作。但R1寄存器未初始化。是否缺少初始化部分?我不知道,也许需要调用链接器。
我的第一个代码的结果是由AVR Studio使用avr-gcc 5.4.0在Windows上汇编的:
这段代码将正常工作。当然,中断向量表可以省略。栈指针初始化也可以省略。但地址0x68上的指令必须保留,因为它清除寄存器R1,然后在主函数中使用。
调用的命令:
(以下是一系列编译和链接命令的输出)
Please note that the translation provided above corresponds to the text segments without code and command invocations. If you have any specific questions or need further assistance, please let me know.
英文:
I decompiled both hex files. Both are weird.
first code:
0: cf 93 push r28
2: df 93 push r29
4: 0f 92 push r0
6: cd b7 in r28, 0x3d ; 61
8: de b7 in r29, 0x3e ; 62
a: dc 01 movw r26, r24
c: fb 01 movw r30, r22
e: 49 83 std Y+1, r20 ; 0x01
10: 89 81 ldd r24, Y+1 ; 0x01
12: 8c 93 st X, r24
14: 89 81 ldd r24, Y+1 ; 0x01
16: 80 83 st Z, r24
18: 0f 90 pop r0
1a: df 91 pop r29
1c: cf 91 pop r28
1e: 08 95 ret
20: 80 e1 ldi r24, 0x10 ; 16
22: 84 b9 out 0x04, r24 ; 4
24: 85 b9 out 0x05, r24 ; 5
26: 80 e0 ldi r24, 0x00 ; 0
28: 90 e0 ldi r25, 0x00 ; 0
2a: 08 95 ret
This code cannot work. I think it is only compiled module not linked to finish code.
Second code:
0: 80 e1 ldi r24, 0x10 ; 16
2: 84 b9 out 0x04, r24 ; 4
4: 85 b9 out 0x05, r24 ; 5
6: 2f ef ldi r18, 0xFF ; 255
8: 33 ed ldi r19, 0xD3 ; 211
a: 90 e3 ldi r25, 0x30 ; 48
c: 21 50 subi r18, 0x01 ; 1
e: 30 40 sbci r19, 0x00 ; 0
10: 90 40 sbci r25, 0x00 ; 0
12: e1 f7 brne .-8 ; 0xc
14: 00 c0 rjmp .+0 ; 0x16
16: 00 00 nop
18: 15 b8 out 0x05, r1 ; 5
1a: 2f ef ldi r18, 0xFF ; 255
1c: 33 ed ldi r19, 0xD3 ; 211
1e: 90 e3 ldi r25, 0x30 ; 48
20: 21 50 subi r18, 0x01 ; 1
22: 30 40 sbci r19, 0x00 ; 0
24: 90 40 sbci r25, 0x00 ; 0
26: e1 f7 brne .-8 ; 0x20
28: 00 c0 rjmp .+0 ; 0x2a
2a: 00 00 nop
2c: eb cf rjmp .-42 ; 0x4
This code can work if R1 register is 0. But it is not initialized. Missing init section ?? I don't know maybe the linker need to be called
My result of first code assembled by AVR studio with avr-gcc 5.4.0 on windows:
Disassembly of section .text:
00000000 <__vectors>:
0: 0c 94 34 00 jmp 0x68 ; 0x68 <__ctors_end>
4: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
8: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
10: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
14: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
18: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
1c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
20: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
24: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
28: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
2c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
30: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
34: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
38: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
3c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
40: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
44: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
48: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
4c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
50: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
54: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
58: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
5c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
60: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
64: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
00000068 <__ctors_end>:
68: 11 24 eor r1, r1
6a: 1f be out 0x3f, r1 ; 63
6c: cf ef ldi r28, 0xFF ; 255
6e: d8 e0 ldi r29, 0x08 ; 8
70: de bf out 0x3e, r29 ; 62
72: cd bf out 0x3d, r28 ; 61
74: 0e 94 40 00 call 0x80 ; 0x80 <main>
78: 0c 94 57 00 jmp 0xae ; 0xae <_exit>
0000007c <__bad_interrupt>:
7c: 0c 94 00 00 jmp 0 ; 0x0 <__vectors>
00000080 <main>:
80: 80 e1 ldi r24, 0x10 ; 16
82: 84 b9 out 0x04, r24 ; 4
84: 85 b9 out 0x05, r24 ; 5
86: 2f e3 ldi r18, 0x3F ; 63
88: 3d e0 ldi r19, 0x0D ; 13
8a: 93 e0 ldi r25, 0x03 ; 3
8c: 21 50 subi r18, 0x01 ; 1
8e: 30 40 sbci r19, 0x00 ; 0
90: 90 40 sbci r25, 0x00 ; 0
92: e1 f7 brne .-8 ; 0x8c <main+0xc>
94: 00 c0 rjmp .+0 ; 0x96 <main+0x16>
96: 00 00 nop
98: 15 b8 out 0x05, r1 ; 5
9a: 2f e3 ldi r18, 0x3F ; 63
9c: 3d e0 ldi r19, 0x0D ; 13
9e: 93 e0 ldi r25, 0x03 ; 3
a0: 21 50 subi r18, 0x01 ; 1
a2: 30 40 sbci r19, 0x00 ; 0
a4: 90 40 sbci r25, 0x00 ; 0
a6: e1 f7 brne .-8 ; 0xa0 <main+0x20>
a8: 00 c0 rjmp .+0 ; 0xaa <main+0x2a>
aa: 00 00 nop
ac: eb cf rjmp .-42 ; 0x84 <main+0x4>
000000ae <_exit>:
ae: f8 94 cli
000000b0 <__stop_program>:
b0: ff cf rjmp .-2 ; 0xb0 <__stop_program>
This code will work correctly. Of course interrupt vector table can be omitted. Also stack pointer initialization can be omitted. But instruction on address 0x68 must stay because clear register R1 then used in main.
Invoked commands:
"C:\Program Files (x86)\Atmel\Studio.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe" -x c -funsigned-char -funsigned-bitfields -DNDEBUG -I"C:\Program Files (x86)\Atmel\Studio.0\Packs\atmel\ATmega_DFP.3.300\include" -Os -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -Wall -mmcu=atmega328p -B "C:\Program Files (x86)\Atmel\Studio.0\Packs\atmel\ATmega_DFP.3.300\gcc\dev\atmega328p" -c -std=gnu99 -MD -MP -MF "main.d" -MT"main.d" -MT"main.o" -o "main.o" ".././main.c"
Finished building: .././main.c
Building target: GccApplication1.elf
Invoking: AVR/GNU Linker : 5.4.0
"C:\Program Files (x86)\Atmel\Studio.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe" -o GccApplication1.elf main.o -Wl,-Map="GccApplication1.map" -Wl,--start-group -Wl,-lm -Wl,--end-group -Wl,--gc-sections -mmcu=atmega328p -B "C:\Program Files (x86)\Atmel\Studio.0\Packs\atmel\ATmega_DFP.3.300\gcc\dev\atmega328p"
Finished building target: GccApplication1.elf
"C:\Program Files (x86)\Atmel\Studio.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe" -O ihex -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures "GccApplication1.elf" "GccApplication1.hex"
"C:\Program Files (x86)\Atmel\Studio.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe" -j .eeprom --set-section-flags=.eeprom=alloc,load --change-section-lma .eeprom=0 --no-change-warnings -O ihex "GccApplication1.elf" "GccApplication1.eep" || exit 0
"C:\Program Files (x86)\Atmel\Studio.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objdump.exe" -h -S "GccApplication1.elf" > "GccApplication1.lss"
"C:\Program Files (x86)\Atmel\Studio.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe" -O srec -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures "GccApplication1.elf" "GccApplication1.srec"
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论