Probier mal das hier aus.
Statt:
LDI R24, 255
Das hier:
LDI R24, 0
In einem Turtorial haben die den Pin als Eingang geschaltet.
Probier mal das hier aus.
Statt:
LDI R24, 255
Das hier:
LDI R24, 0
In einem Turtorial haben die den Pin als Eingang geschaltet.
Hulft nicht, das hatte ich auch schon probiert...
Aber Not macht erfinderisch:
Man macht sich eine minimale C-Datei, die genau das macht was man will:
Macht damit nen ASM-Dump:#include <avr/io.h>
void main(void) {
DDRD = 255;
PORTD = 255;
}
Kopiert sich das relevante in die eigenen main.S und schmeißt alles was komisch aussieht raus:GAS LISTING /tmp/cc7Qz3w0.s page 1
1 .file "main.c"
2 __SREG__ = 0x3f
3 __SP_H__ = 0x3e
4 __SP_L__ = 0x3d
5 __CCP__ = 0x34
6 __tmp_reg__ = 0
7 __zero_reg__ = 1
8 .text
9 .global main
10 .type main, @function
11 main:
12 0000 DF93 push r29
13 0002 CF93 push r28
14 0004 CDB7 in r28,__SP_L__
15 0006 DEB7 in r29,__SP_H__
16 /* prologue: function */
17 /* frame size = 0 */
18 /* stack size = 2 */
19 .L__stack_usage = 2
20 0008 81E3 ldi r24,lo8(49)
21 000a 90E0 ldi r25,hi8(49)
22 000c 2FEF ldi r18,lo8(-1)
23 000e FC01 movw r30,r24
24 0010 2083 st Z,r18
25 0012 82E3 ldi r24,lo8(50)
26 0014 90E0 ldi r25,hi8(50)
27 0016 2FEF ldi r18,lo8(-1)
28 0018 FC01 movw r30,r24
29 001a 2083 st Z,r18
30 /* epilogue start */
31 001c CF91 pop r28
32 001e DF91 pop r29
33 0020 0895 ret
34 .size main, .-main
GAS LISTING /tmp/cc7Qz3w0.s page 2
DEFINED SYMBOLS
*ABS*:00000000 main.c
/tmp/cc7Qz3w0.s:2 *ABS*:0000003f __SREG__
/tmp/cc7Qz3w0.s:3 *ABS*:0000003e __SP_H__
/tmp/cc7Qz3w0.s:4 *ABS*:0000003d __SP_L__
/tmp/cc7Qz3w0.s:5 *ABS*:00000034 __CCP__
/tmp/cc7Qz3w0.s:6 *ABS*:00000000 __tmp_reg__
/tmp/cc7Qz3w0.s:7 *ABS*:00000001 __zero_reg__
/tmp/cc7Qz3w0.s:11 .text:00000000 main
NO UNDEFINED SYMBOLS
Und Thada, schon leuchten die 2 LEDs. Jetzt muss ich nur noch Stück für Stück den Code auseinander nehmen und gucken wie der GCC das anstellt, dass die 2 leuchten...#include <avr/io.h>
.text
.global main
main:
push r29
push r28
ldi r24,lo8(49)
ldi r25,hi8(49)
ldi r18,lo8(-1)
movw r30,r24
st Z,r18
ldi r24,lo8(50)
ldi r25,hi8(50)
ldi r18,lo8(-1)
movw r30,r24
st Z,r18
pop r28
pop r29
ret
Hauptschleife:
rjmp Hauptschleife
Das Problem liegt darin wie die SFR namen definiert sind. Für C sind da die Adressen für den Zugriff als Speicher (per LDS / STS und ähnlich) angegeben. Für die Benutzung in ASM mit den Befehlen IN und OUT muss man davon noch 32 abziehen. Eine Erklärung findet sich im File sfr_defs.h.
Ich bin jetzt nicht sicher ob ich das richtige gemacht habe. Ist das das was du sehen möchtest?
Code:simon@simon-TravelMate-5735Z:~/Arbeitsfläche/test$ avr-objdump -d main.elf main.elf: file format elf32-avr Disassembly of section .text: 00000000 <__vectors>: 0: 0c 94 2a 00 jmp 0x54 ; 0x54 <__ctors_end> 4: 0c 94 34 00 jmp 0x68 ; 0x68 <__bad_interrupt> 8: 0c 94 34 00 jmp 0x68 ; 0x68 <__bad_interrupt> c: 0c 94 34 00 jmp 0x68 ; 0x68 <__bad_interrupt> 10: 0c 94 34 00 jmp 0x68 ; 0x68 <__bad_interrupt> 14: 0c 94 34 00 jmp 0x68 ; 0x68 <__bad_interrupt> 18: 0c 94 34 00 jmp 0x68 ; 0x68 <__bad_interrupt> 1c: 0c 94 34 00 jmp 0x68 ; 0x68 <__bad_interrupt> 20: 0c 94 34 00 jmp 0x68 ; 0x68 <__bad_interrupt> 24: 0c 94 34 00 jmp 0x68 ; 0x68 <__bad_interrupt> 28: 0c 94 34 00 jmp 0x68 ; 0x68 <__bad_interrupt> 2c: 0c 94 34 00 jmp 0x68 ; 0x68 <__bad_interrupt> 30: 0c 94 34 00 jmp 0x68 ; 0x68 <__bad_interrupt> 34: 0c 94 34 00 jmp 0x68 ; 0x68 <__bad_interrupt> 38: 0c 94 34 00 jmp 0x68 ; 0x68 <__bad_interrupt> 3c: 0c 94 34 00 jmp 0x68 ; 0x68 <__bad_interrupt> 40: 0c 94 34 00 jmp 0x68 ; 0x68 <__bad_interrupt> 44: 0c 94 34 00 jmp 0x68 ; 0x68 <__bad_interrupt> 48: 0c 94 34 00 jmp 0x68 ; 0x68 <__bad_interrupt> 4c: 0c 94 34 00 jmp 0x68 ; 0x68 <__bad_interrupt> 50: 0c 94 34 00 jmp 0x68 ; 0x68 <__bad_interrupt> 00000054 <__ctors_end>: 54: 11 24 eor r1, r1 56: 1f be out 0x3f, r1 ; 63 58: cf e5 ldi r28, 0x5F ; 95 5a: d8 e0 ldi r29, 0x08 ; 8 5c: de bf out 0x3e, r29 ; 62 5e: cd bf out 0x3d, r28 ; 61 60: 0e 94 36 00 call 0x6c ; 0x6c <main> 64: 0c 94 47 00 jmp 0x8e ; 0x8e <_exit> 00000068 <__bad_interrupt>: 68: 0c 94 00 00 jmp 0 ; 0x0 <__vectors> 0000006c <main>: 6c: df 93 push r29 6e: cf 93 push r28 70: cd b7 in r28, 0x3d ; 61 72: de b7 in r29, 0x3e ; 62 74: 81 e3 ldi r24, 0x31 ; 49 76: 90 e0 ldi r25, 0x00 ; 0 78: 2f ef ldi r18, 0xFF ; 255 7a: fc 01 movw r30, r24 7c: 20 83 st Z, r18 7e: 82 e3 ldi r24, 0x32 ; 50 80: 90 e0 ldi r25, 0x00 ; 0 82: 2f ef ldi r18, 0xFF ; 255 84: fc 01 movw r30, r24 86: 20 83 st Z, r18 88: cf 91 pop r28 8a: df 91 pop r29 8c: 08 95 ret 0000008e <_exit>: 8e: f8 94 cli 00000090 <__stop_program>: 90: ff cf rjmp .-2 ; 0x90 <__stop_program> simon@simon-TravelMate-5735Z:~/Arbeitsfläche/test$
Hat jetzt zwar ein bischen gebraucht, aber ich glaub ich habs gecheckt:Das Problem liegt darin wie die SFR namen definiert sind. Für C sind da die Adressen für den Zugriff als Speicher (per LDS / STS und ähnlich) angegeben. Für die Benutzung in ASM mit den Befehlen IN und OUT muss man davon noch 32 abziehen. Eine Erklärung findet sich im File sfr_defs.h.
Im Datenblatt steht:
Die $32 und $31 (jeweils zweite Zahl von Links) sind die Adresse, die der GCC benutzt (umgerechnet von Hex nach Dez sind das nämlich 50 und 49 - die sich auch im Quellcode wiederfinden)Code:$12 ($32) PORTD PORTD7 PORTD6 PORTD5 PORTD4 PORTD3 PORTD2 PORTD1 PORTD0 65 $11 ($31) DDRD DDD7 DDD6 DDD5 DDD4 DDD3 DDD2 DDD1 DDD0 65
Wenn ich jetzt 50-32 = 18 Rechne, und in 18 und auch 17 (49 - 32) jeweils 255 mit OUT reinschreibe, leuchten die LEDs!
Und Praktischerweise sind die 12 und 11 im Datenblatt (jeweils erste Zahl) von hex nach dez umgerechnet auch 18 und 17, ich brauch also auch nicht jedesmal mühsam -32 rechnen :-D
Vielen vielen Dank Besserwessi und Kampi! :-D
Viele herzliche Grüße
-schumi-
[EDIT]
Hier noch der aktuelle Quellcode:
Code:#include <avr/io.h> .text .global main main: LDI r24, 255 OUT DDRD-32, r24 LDI r24, 255 OUT PORTD-32, r24 Hauptschleife: rjmp Hauptschleife
Geändert von -schumi- (02.09.2011 um 17:30 Uhr)
Deine Erklärung check ich jetzt nicht ganz![]()
Der GCC benutzt DDRD. Aus irgend einem Grund, den ich noch nicht kenne, ist aber die Adresse, die sich hinter "DDRD" verbirgt für "OUT" und "IN" um 32 zu groß. -> 32 abziehen und passt.
Und im Datenblatt is die Adresse eben zweimal angegeben, erst ohne Klammern, so wie sie für "OUT" und "IN" passt und dann nochmal mit klammern, so wie sie sich hinter "DDRD", "PORTD" usw. verbirgt...
Was das jetzt alles auf sich hat -> Ich weis es (noch) nicht... Aber damit funktioniert es zumindest schonmal so weit...
Ok, hab mir jetzt mal die sfr_defs.h angeschaut, oben steht:
Und es funktioniert sogar :-DThe \c <avr/sfr_defs.h> file is included by all of the \c <avr/ioXXXX.h>
files, which use macros defined here to make the special function register
definitions look like C variables or simple constants, depending on the
<tt>_SFR_ASM_COMPAT</tt> define. Some examples from \c <avr/iocanxx.h> to
show how to define such macros:
\code
#define PORTA _SFR_IO8(0x02)
#define EEAR _SFR_IO16(0x21)
#define UDR0 _SFR_MEM8(0xC6)
#define TCNT3 _SFR_MEM16(0x94)
#define CANIDT _SFR_MEM32(0xF0)
\endcode
If \c _SFR_ASM_COMPAT is not defined, C programs can use names like
<tt>PORTA</tt> directly in C expressions (also on the left side of
assignment operators) and GCC will do the right thing (use short I/O
instructions if possible). The \c __SFR_OFFSET definition is not used in
any way in this case.
Define \c _SFR_ASM_COMPAT as 1 to make these names work as simple constants
(addresses of the I/O registers). This is necessary when included in
preprocessed assembler (*.S) source files, so it is done automatically if
\c __ASSEMBLER__ is defined. By default, all addresses are defined as if
they were memory addresses (used in \c lds/sts instructions). To use these
addresses in \c in/out instructions, you must subtract 0x20 from them.
For more backwards compatibility, insert the following at the start of your
old assembler source file:
\code
#define __SFR_OFFSET 0
\endcode
Code:#include <avr/io.h> #define _SFR_ASM_COMPAT 1 #define __SFR_OFFSET 0 .text .global main main: LDI r24, 255 OUT DDRD, r24 LDI r24, 255 OUT PORTD, r24 Hauptschleife: rjmp Hauptschleife
Hallo
Ich find das voll clever wie du das anpackst.
/* Port D */
#define PIND _SFR_IO8(0x10)
#define DDRD _SFR_IO8(0x11)
#define PORTD _SFR_IO8(0x12)
Das findet man in der Datei iom32.h die von io.h eingebunden wird. Find ich eh ziemlich "unsportlich":
#include <avr/io.h>
Gruß
mic
Bild hier
Atmel’s products are not intended, authorized, or warranted for use
as components in applications intended to support or sustain life!
Lesezeichen