Hallo,
ich versuche seit geraumer Zeit zu meinem C Code einen Assembler-Code
hinzu zu fügen.
Ich kenne die Ansicht vieler hier, dass das Schwachsinn ist zu mischen.
Entweder C oder Assembler.
Mein Problem ist, ich bin ein absoluter Assembler-Neuling, möchte also
nicht mehr machen als unbedingt notwendig.
Ich soll für einen Microcontroller eine Demoapplikation programmieren
und dabei gleichzeitig Selbsttests einführen (Maschinensicherheit,
etc.). Diese Selbsttests liegen mir als Assembler vor (allerdings für
einen anderen µC), daher portiere ich sie nur. Das geht soweit auch ganz
gut, ich kann sie in AVR Studio simulieren lassen und sie laufen wie sie
sollen. Ist zwar einiges an Aufwand sie auf den AVR ATMega169 zu
portieren aber das soll nicht eure Sorge sein ;)
Ein Bsp. findet ihr in der Beispiel.asm.
Nun möchte ich die Datei aus einem meiner C-Dateien aus aufrufen. Ich
habe schon viel versucht, allerdings werde ich nicht so ganz schlau wie
das genau geht. Einige Tutorials konnten mir auch nicht helfen.
Ich habe jetzt die *.asm-Datei in *.S umbenannt, in das selbe
Verzeichnis wie meine restlichen Dateien verschoben und in der Makefile
verlinkt mittels:
1
"# List Assembler source files here.
2
# Make them always end in a capital .S. Files ending in a lowercase .s
3
# will not be considered source files but generated files (assembler
4
# output from the compiler), and will be deleted upon "make clean"!
5
# Even though the DOS/Win* filesystem matches both .s and .S the same,
6
# it will preserve the spelling of the filenames, and gcc itself does
7
# care about how the name is spelled on its command-line.
8
ASRC = Selftest"
wobei die Datei natürlich Selftest.S heißt.
Allerdings bekomme ich beim kompilieren etliche Fehler.
Habe jetzt auch schon das .include <***> in #include <avr/io.h> geändert
und aus LOW und HIGH entsprechend lo8 & hi8 gemacht.
1
#include <avr/io.h>
2
3
4
;Stack Initializieren
5
PPR_TEST: LDI R16, lo8(RAMEND)
6
OUT SPL , R16
7
LDI R16, hi8(RAMEND)
8
OUT SPH , R16
9
10
;Beginn des Tests
11
;Inkrementstest, wird der Stack-Pointer korrekt Inkrementiert?
12
PPR_PUSHPOP: IN R26, SPL ;StackPointer in Register X & Y schreiben
13
IN R27, SPH
14
IN R28, SPL
15
IN R29, SPH
16
LDI R16, 0xAA ;0xAA auf den Stack pushen (dabei wird SP dekrementiert)
17
PUSH R16
18
LD R16, -Y ;Anpassen des erwarteten Wertes.
19
IN R16, SPL ;aktuellen SP-Wert in Vergleichsvariablen schreiben
20
IN R17, SPH
21
CP R28, R16 ;Vergleich des aktuellen Stackpointers mit dem vorgesehenen Stackpointers
22
BRNE PPR_err1
23
CP R29, R17
24
BRNE PPR_err1
25
26
CLR R31
27
IN R28, SPL ;Stackpointer in Register Y schreiben
28
IN R29, SPH
29
LD R31, Y+ ;Anpassen des erwarteten Wertes
30
LD R31, Y
31
CPI R31, 0xAA ;Vergleich
32
BRNE PPR_err1
33
34
CLR R31
35
POP R31 ;Wert vom Stack holen
36
CPI R31, 0xAA ;Vergleich mit Erwartung
37
BRNE PPR_err1
38
39
40
IN R30, SPL ;aktuellen Stackpointerwert holen
41
IN R31, SPH
42
CP R30, R26 ;Vergleichen der Werte
43
BRNE PPR_err1
44
CP R31, R27
45
BRNE PPR_err1
46
47
PPR_RET: LDI ZH, HIGH(PPR_RET1)
48
LDI ZL, LOW(PPR_RET1)
49
PUSH ZL
50
PUSH ZH
51
RET
52
NOP
53
NOP
54
NOP
55
JMP PPR_err1
56
57
PPR_RET1: JMP PPR_ENDE
58
NOP
59
NOP
60
NOP
61
NOP
62
NOP
63
PPR_err1: JMP PPR_err1
64
65
PPR_ENDE: RET
trotzdem verbleiben folgende Fehler:
1
Selftest.s: Assembler messages:
2
Selftest.s:6: Error: constant value required
3
Selftest.s:8: Error: constant value required
4
Selftest.s:12: Error: constant value required
5
Selftest.s:13: Error: constant value required
6
Selftest.s:14: Error: constant value required
7
Selftest.s:15: Error: constant value required
8
Selftest.s:19: Error: constant value required
9
Selftest.s:20: Error: constant value required
10
Selftest.s:27: Error: constant value required
11
Selftest.s:28: Error: constant value required
12
Selftest.s:40: Error: constant value required
13
Selftest.s:41: Error: constant value required
14
Selftest.s:47: Error: constant value required
15
Selftest.s:47: Error: register number above 15 required
16
Selftest.s:47: Warning: expression possibly out of 8-bit range
17
Selftest.s:47: Error: garbage at end of line
18
Selftest.s:48: Error: constant value required
19
Selftest.s:48: Error: register number above 15 required
20
Selftest.s:48: Warning: expression possibly out of 8-bit range
21
Selftest.s:48: Error: garbage at end of line
22
Selftest.s:49: Error: constant value required
23
Selftest.s:50: Error: constant value required
24
Selftest.s:55: Error: illegal opcode jmp for mcu avr2
25
Selftest.s:57: Error: illegal opcode jmp for mcu avr2
26
Selftest.s:63: Error: illegal opcode jmp for mcu avr2
27
Selftest.s:64: Warning: partial line at end of file ignored
gibt es keine einfachere Methode, so dass ich quasi den ASM-Code aus dem
AVR-Studio 1:1 übernehmen kann und nur einen aufruf aus einer C-Datei zu
starten? Wenn ja, wie muss ich das einbinden, linken, etc.?
Vielen Dank schonmal für die Mühe!
Ueps
Hallo,
nur so am Rande: wenn der Stackpointer falsch oder garnicht
incrementiert dann kommt Dein C-Programm mit an Sicherheit grenzender
Wahrscheinlichkeit nie an die Stelle, die Dein Testprogramm aufruft...
Gruß aus Berlin
Michael
das mag wohl sein, allerdings ist es halt voraussetzung für einige
maschinen solche selbsttests durchzuführen ;) es ist auch nicht meine
entscheidung welche selbsttest implementiert werden und das ich jetzt
gerade diesen heraus gegriffen habe liegt auch einfach nur daran, dass
ich diesen grade zufällig als letzten portiert habe
> Ich habe jetzt die *.asm-Datei in *.S umbenannt, ...
Das sieht aber nicht so aus:
> Selftest.s:6: Error: constant value required
Wichtig ist das große 'S' am Ende. Nur denn wendet der GNU-Assembler den
C-Päprozesser auf die Datei an, so dass im Header-File definierte Makros
wie SPH und SPL richtig umgesetzt werden.
hallo,
danke für die Idee, leider war bzw. ist das S bereits groß geschrieben.
Aber es ist doch richtig, dass ich die Datei einfach UMBENANNT habe, ich
muss sie nicht irgendwie konvertieren oder so?
Am besten gibst du für asm-Dateien die Spreche explizit beim gcc-Aufruf
mit an:
1
-x assembler-with-cpp datei.asm
Dann ist die Endung egal. Ausserdem willst du ja nicht Assembler
übersetzen, sondern vorher noch den Präprozessor drüberrauschen lassen.
Zu dem undefined:
Wo wird ZL definiert? Wo ZH? SPL? SPH? ...
Wenn du das innerhalb von C verwenden willst, brauchst du noch
Prototypen und die Symbole müssen global sein.
Und beachte die C-ABI. Sonst fliegt dir alles um die Ohren!
GNU-C und Atmel-Assembler kombiniert sich nicht und der GNU-Assembler
ist nicht mit dem Atmel-Assembler kompatibel. Also müssen Programme für
Atmels Assembler erst umgeschrieben werden.
Johann L. wrote:
> Am besten gibst du für asm-Dateien die Spreche explizit beim gcc-Aufruf> mit an:>>
1
> -x assembler-with-cpp datei.asm
2
>
>> Dann ist die Endung egal. Ausserdem willst du ja nicht Assembler> übersetzen, sondern vorher noch den Präprozessor drüberrauschen lassen.
Wo mache ich das genau in der makefile? gibts da einen bestimmten punkt
in den das rein muss?
> Zu dem undefined:>> Wo wird ZL definiert? Wo ZH? SPL? SPH? ...
Diese Variablen werden doch in der *.inc definiert, welche von der *.h
<avr/io.h> aufgerufen werden. oder irre ich da? In meiner
Assembler-Datei hatte ich die *.inc explizit aufgerufen.
>> Wenn du das innerhalb von C verwenden willst, brauchst du noch> Prototypen und die Symbole müssen global sein.>> Und beachte die C-ABI. Sonst fliegt dir alles um die Ohren!
C-ABI? Entschuldige bitte aber ich bin leider noch nicht so tief im
ganzen drin, erläutere bitte was du damit meinst damit ich mir das mal
anschauen kann
>GNU-C und Atmel-Assembler kombiniert sich nicht und der GNU-Assembler>ist nicht mit dem Atmel-Assembler kompatibel. Also müssen Programme für>Atmels Assembler erst umgeschrieben werden.
Wie mache ich das? Was genau meinst du damit?
Max K. wrote:
> Wie mache ich das? Was genau meinst du damit?
Das heisst es gibt viele Dinge, die sich in beiden Assemblern
unterschiedlich ausdrücken. Ich kenne die auch nicht alle, da hilft nur:
Doku vom Atmel-Assembler und Doku vom GNU-Assembler vergleichen.
Auch die Schreibweise von Zugriffen auf I/O-Register unterscheidet sich
deutlich.
Weitere Falle: Atmel rechnet bei ROM-Adressen in Worten, d.h. die
Adress-Differenz zweier aufeinander folgender 16-Bit-Worte im Codespace
ist 1. Der GNU-Assembler hingegen rechnet in Bytes.
Max K. wrote:
> Johann L. wrote:>> Am besten gibst du für asm-Dateien die Spreche explizit beim gcc-Aufruf>> mit an:>>>>
1
>> -x assembler-with-cpp datei.asm
2
>>
>>>> Dann ist die Endung egal. Ausserdem willst du ja nicht Assembler>> übersetzen, sondern vorher noch den Präprozessor drüberrauschen lassen.>> Wo mache ich das genau in der makefile? gibts da einen bestimmten punkt> in den das rein muss?
Wer sich durch die generierten Makefiles durchbeissen will...
Such mal nach des Assembler-Quellen und wie die verwurstet werden.
>> Zu dem undefined:>>>> Wo wird ZL definiert? Wo ZH? SPL? SPH? ...>> Diese Variablen werden doch in der *.inc definiert, welche von der *.h> <avr/io.h> aufgerufen werden. oder irre ich da?
Ja. GCC verwendet kaum Quellen von Atmel ;-)
>> Wenn du das innerhalb von C verwenden willst, brauchst du noch>> Prototypen und die Symbole müssen global sein.>>>> Und beachte die C-ABI. Sonst fliegt dir alles um die Ohren!>> C-ABI? Entschuldige bitte aber ich bin leider noch nicht so tief im> ganzen drin, erläutere bitte was du damit meinst damit ich mir das mal> anschauen kann
Application Binary Interface.
http://www.roboternetz.de/wissen/index.php/Avr-gcc/Interna#Registerverwendung>>GNU-C und Atmel-Assembler kombiniert sich nicht und der GNU-Assembler>>ist nicht mit dem Atmel-Assembler kompatibel. Also müssen Programme für>>Atmels Assembler erst umgeschrieben werden.>> Wie mache ich das? Was genau meinst du damit?
-- Definiere ZL etc. in avr-as-Syntax.
-- Greife bei IN/OUT mit korrektenm Offset auf SFRs zu
-- Ersetze unbekannte Direktiven durch avr-as-Direktiven
Hilfreich ist sich anzuschauen, was avr-gcc aus ner C-Quelle bastelt.
Die Option heisst -save-temps (erzeugt .i/.ii und .s)
und für den Anfang reicht vielleicht schon Inline Assembler?
Der hat Fallstricke genug.
http://www.roboternetz.de/wissen/index.php/Inline-Assembler_in_avr-gcc
hallo,
danke werde mich da mal durchhangeln. mit inline-assembler habe ich auch
schon gearbeitet aber ich dachte es gibt halt eine möglichkeit direkt
von a nach b zu kopieren.
beim inline-assembler hat man ja auch das problem das diverse sachen
nicht so leicht ansprechbar sind wie beim direkten assembler..
> Aber es ist doch richtig, dass ich die Datei einfach UMBENANNT habe,
Ja. Aber wichtig ist vor allem, dass der Dateiname auch im Makefile mit
.S endet.
> ich muss sie nicht irgendwie konvertieren oder so?
Nein.
Dein Code wird bei mir fehlerfrei assembliert, wenn
- die verbleibenden HIGH und LOW durch hi8 bzw. lo8 ersetzt und
- alle SPL und SPH in den IN- und OUT-Befehlen durch _SFR_IO_ADDR(SPL)
bzw. _SFR_IO_ADDR(SPH) ersetzt werden. Mehr dazu hier:
http://www.nongnu.org/avr-libc/user-manual/group__avr__sfr__notes.html
Ungeachtet dessen wird es evtl. schwierig, die Testroutine auf übliche
Weise aus dem C-Programm aufzurufen, u.a. deswegen, weil der
Stackpointer verändert wird und Daten ins RAM geschrieben werden. Das
führt leicht zum Crash ;-)
Da der Code sowieso nur ganz zu Anfang der Programmausführung wirklich
sinnvoll ist, ist es wahrscheinlich am geschicktesten, ihn in die
.init0-Section zu schreiben. Was das bedeutet, steht hier:
http://www.nongnu.org/avr-libc/user-manual/mem_sections.html
Dann brauchst du dich auch nicht um die C-Aufrufkonventionen zu kümmern.
Ob Inline-Assembler oder eigene .S-Datei sollte eigentlich egal sein.
yalu wrote:
>> Aber es ist doch richtig, dass ich die Datei einfach UMBENANNT habe,>> Ja. Aber wichtig ist vor allem, dass der Dateiname auch im Makefile mit> .S endet.>>> ich muss sie nicht irgendwie konvertieren oder so?>> Nein.>> Dein Code wird bei mir fehlerfrei assembliert, wenn>> - die verbleibenden HIGH und LOW durch hi8 bzw. lo8 ersetzt und>> - alle SPL und SPH in den IN- und OUT-Befehlen durch _SFR_IO_ADDR(SPL)> bzw. _SFR_IO_ADDR(SPH) ersetzt werden. Mehr dazu hier:>> http://www.nongnu.org/avr-libc/user-manual/group__avr__sfr__notes.html>
Das hatte ich mir auch schon gedacht, allerdings bringt es bei mir keine
Besserung!
Mein Code:
1
#include <avr/io.h>
2
3
;Stack Initializieren
4
PPR_TEST: LDI R16, lo8(RAMEND)
5
OUT _SFR_IO_ADDR(SPL) , R16
6
LDI R16, hi8(RAMEND)
7
OUT _SFR_IO_ADDR(SPH) , R16
8
9
;Beginn des Tests
10
;Inkrementstest, wird der Stack-Pointer korrekt Inkrementiert?
11
PPR_PUSHPOP: IN R26, _SFR_IO_ADDR(SPL) ;StackPointer in Register X & Y schreiben
12
IN R27, _SFR_IO_ADDR(SPH)
13
IN R28, _SFR_IO_ADDR(SPL)
14
IN R29, _SFR_IO_ADDR(SPH)
15
LDI R16, 0xAA ;0xAA auf den Stack pushen (dabei wird SP dekrementiert)
16
PUSH R16
17
LD R16, -Y ;Anpassen des erwarteten Wertes.
18
IN R16, _SFR_IO_ADDR(SPL) ;aktuellen SP-Wert in Vergleichsvariablen schreiben
19
IN R17, _SFR_IO_ADDR(SPH)
20
CP R28, R16 ;Vergleich des aktuellen Stackpointers mit dem vorgesehenen Stackpointers
21
BRNE PPR_err1
22
CP R29, R17
23
BRNE PPR_err1
24
25
CLR R31
26
IN R28, _SFR_IO_ADDR(SPL) ;Stackpointer in Register Y schreiben
27
IN R29, _SFR_IO_ADDR(SPL)
28
LD R31, Y+ ;Anpassen des erwarteten Wertes
29
LD R31, Y
30
CPI R31, 0xAA ;Vergleich
31
BRNE PPR_err1
32
33
CLR R31
34
POP R31 ;Wert vom Stack holen
35
CPI R31, 0xAA ;Vergleich mit Erwartung
36
BRNE PPR_err1
37
38
39
IN R30, _SFR_IO_ADDR(SPL) ;aktuellen Stackpointerwert holen
40
IN R31, _SFR_IO_ADDR(SPH)
41
CP R30, R26 ;Vergleichen der Werte
42
BRNE PPR_err1
43
CP R31, R27
44
BRNE PPR_err1
45
46
PPR_RET: LDI R30, hi8(PPR_RET1)
47
LDI R31, lo8(PPR_RET1)
48
PUSH R30
49
PUSH R31
50
RET
51
NOP
52
NOP
53
NOP
54
JMP PPR_err1
55
56
PPR_RET1: JMP PPR_ENDE
57
NOP
58
NOP
59
NOP
60
NOP
61
NOP
62
PPR_err1: JMP PPR_err1
63
64
PPR_ENDE: RET
und die dazu gehörende Fehlermeldung
1
Selftest.s: Assembler messages:
2
Selftest.s:0: Warning: end of file not at end of a line; newline inserted
3
Selftest.s:5: Error: constant value required
4
Selftest.s:5: Error: `,' required
5
Selftest.s:5: Error: constant value required
6
Selftest.s:5: Error: garbage at end of line
7
Selftest.s:7: Error: constant value required
8
Selftest.s:7: Error: `,' required
9
Selftest.s:7: Error: constant value required
10
Selftest.s:7: Error: garbage at end of line
11
Selftest.s:11: Error: constant value required
12
Selftest.s:11: Error: garbage at end of line
13
Selftest.s:12: Error: constant value required
14
Selftest.s:12: Error: garbage at end of line
15
Selftest.s:13: Error: constant value required
16
Selftest.s:13: Error: garbage at end of line
17
Selftest.s:14: Error: constant value required
18
Selftest.s:14: Error: garbage at end of line
19
Selftest.s:18: Error: constant value required
20
Selftest.s:18: Error: garbage at end of line
21
Selftest.s:19: Error: constant value required
22
Selftest.s:19: Error: garbage at end of line
23
Selftest.s:26: Error: constant value required
24
Selftest.s:26: Error: garbage at end of line
25
Selftest.s:27: Error: constant value required
26
Selftest.s:27: Error: garbage at end of line
27
Selftest.s:39: Error: constant value required
28
Selftest.s:39: Error: garbage at end of line
29
Selftest.s:40: Error: constant value required
30
Selftest.s:40: Error: garbage at end of line
31
Selftest.s:54: Error: illegal opcode jmp for mcu avr2
32
Selftest.s:56: Error: illegal opcode jmp for mcu avr2
33
Selftest.s:62: Error: illegal opcode jmp for mcu avr2
34
make.exe: *** [Selftest] Error 1
> Ungeachtet dessen wird es evtl. schwierig, die Testroutine auf übliche> Weise aus dem C-Programm aufzurufen, u.a. deswegen, weil der> Stackpointer verändert wird und Daten ins RAM geschrieben werden. Das> führt leicht zum Crash ;-)>> Da der Code sowieso nur ganz zu Anfang der Programmausführung wirklich> sinnvoll ist, ist es wahrscheinlich am geschicktesten, ihn in die> .init0-Section zu schreiben. Was das bedeutet, steht hier:>> http://www.nongnu.org/avr-libc/user-manual/mem_sections.html>> Dann brauchst du dich auch nicht um die C-Aufrufkonventionen zu kümmern.> Ob Inline-Assembler oder eigene .S-Datei sollte eigentlich egal sein.
wie gesagt, es ist nicht meine entscheidung wann der test ausgeführt
wird. das da nochmal probleme auf mich zukommen werden habe ich schon
fast befürchtet, allerdings möchte ich jetzt den code erst ans laufen
bekommen. so langsam bin ich dran einfach mein ganzes programm in
assembler zu schreiben da ich keine lust auf dieses heckmeck habe von
wegen portieren, umschreiben, etc.pp.
klaut mir nur tage von meiner knappen zeit für meine bachelor-arbeit
Korrektur zu oben:
> ... ihn in die .init0-Section zu schreiben.
Besser: .init1-Section, da diese offiziell "user definable" ist.
Zu den Fehlermeldungen:
> Selftest.s: Assembler messages:> ...
Der Compiler/Assembler meint immer noch, er müsste eine Datei namens
Selftest.s (und nicht Selftest.S, wie es richtig wäre) assemblieren.
Poste doch mal das Makefile.
also das makefile ist nicht von mir. habe damals in den prozessor
reingeschnuppert mit dem buch von joe pardue (C Programming for
microcontrollers). dementsprechend habe ich auch sein makefile genommen.
und da bisher alles klappte und ich sowieso nicht ganz 100%
nachvollziehen konnte was da gemacht wird (läuft? läuft!, never touch a
running system und so) habe ich es einfach mal gelassen.. jedoch wird
auch dort explizit auf das große .S hingewiesen.
1
# WinAVR Sample makefile written by Eric B. Weddington, Jörg Wunsch, et al.
2
# Released to the Public Domain
3
# Please read the make user manual!
4
#
5
# Additional material for this makefile was submitted by:
6
# Tim Henigan
7
# Peter Fleury
8
# Reiner Patommel
9
# Sander Pool
10
# Frederik Rouleau
11
# Markus Pfaff
12
#
13
# On command line:
14
#
15
# make all = Make software.
16
#
17
# make clean = Clean out built project files.
18
#
19
# make coff = Convert ELF to AVR COFF (for use with AVR Studio 3.x or VMLAB).
20
#
21
# make extcoff = Convert ELF to AVR Extended COFF (for use with AVR Studio
22
# 4.07 or greater).
23
#
24
# make program = Download the hex file to the device, using avrdude. Please
25
# customize the avrdude settings below first!
26
#
27
# make filename.s = Just compile filename.c into the assembler code only
28
#
29
# To rebuild project do "make clean" then "make all".
30
#
31
32
33
# MCU name
34
MCU = atmega169
35
36
# Output format. (can be srec, ihex, binary)
37
FORMAT = ihex
38
39
# Target file name (without extension).
40
TARGET = Blinky
41
42
43
# List C source files here. (C dependencies are automatically generated.)
44
SRC = $(TARGET).c
45
46
47
# List Assembler source files here.
48
# Make them always end in a capital .S. Files ending in a lowercase .s
49
# will not be considered source files but generated files (assembler
50
# output from the compiler), and will be deleted upon "make clean"!
51
# Even though the DOS/Win* filesystem matches both .s and .S the same,
52
# it will preserve the spelling of the filenames, and gcc itself does
53
# care about how the name is spelled on its command-line.
54
ASRC = Selftest
55
56
57
# Optimization level, can be [0, 1, 2, 3, s].
58
# 0 = turn off optimization. s = optimize for size.
59
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
60
OPT = s
61
62
63
# List any extra directories to look for include files here.
64
# Each directory must be seperated by a space.
65
EXTRAINCDIRS =
66
67
68
# Compiler flag to set the C Standard level.
69
CSTANDARD_C89 = c89
70
CSTANDARD_GNU89 = gnu89
71
CSTANDARD_C99 = c99
72
CSTANDARD_GNU99 = gnu99
73
CSTANDARD = -std=$(CSTANDARD_GNU99)
74
75
76
77
# Compiler flags.
78
# -g: generate debugging information
79
# -O*: optimization level
80
# -f...: tuning, see GCC manual and avr-libc documentation
81
# -Wall...: warning level
82
# -Wa,...: tell GCC to pass this to the assembler.
.PHONY : all begin finish end sizebefore sizeafter gccversion \
392
build elf hex eep lss sym coff extcoff \
393
clean clean_list program
Danke euch nochmal, dass ihr hier zu helfen versucht!!!
(und meine Datei ist 100% *.S)
btw. arbeite unter Win2k, vllt. ist ja das von Windows aus, dass er das
case-sensitive ein wenig verschmeißt?!
Yieks.. das .S ist wirklich ein saudummer fehler.. warum ich das
vergessen habe weiß ich nicht.. *kopf=>tisch*
das mit dem einstiegspunkt schau ich mir jetzt noch an ;)
und das mit dem CAPSLOCK.. naja.. meine vorlagen sind in
CAPSLOCK-Schrift, ich habs selber nicht gemacht und ein kollege meinte
dann nur das sei konvention und ich soll mich dran halten..
danke für eure großartige hilfe ;)
mich sträubt es dagegen Tests, welche ich bereits auf den avr portiert
habe, jetzt nochmal komplett umschreiben zu müssen, damit sie als
inline-assembler laufen.
oder gibts da einen Kniff wie das ganze sehr einfach wird?
eine andere frage: warum gibt mir der befehl:
1
PPR_RET: LDI ZH, hi8(PPR_RET1)
2
LDI ZL, lo8(PPR_RET1)
3
PUSH ZL
4
PUSH ZH
5
RET
einen falschen Wert für was Label PPR_RET1 zurück? er springt an einen
völlig falsche Stelle, warum?
@ Stefan Ernst (sternst)
>Das dort ist Atmel-Assembler. Hier geht es aber um GCC-Assembler.
Mit dem bist recht allein. Den nutzt so gut wie keiner (direkt).
MFG
Falk
Falk Brunner wrote:
>>Das dort ist Atmel-Assembler. Hier geht es aber um GCC-Assembler.>> Mit dem bist recht allein. Den nutzt so gut wie keiner (direkt).
Ich kann dir nicht folgen. Was denkst du denn, um welchen Assembler es
hier geht, wenn nicht den AVR-Assembler des GCC?
also ich hatte das .include "µC.inc" (angepasst halt) in meinem
assembler-code den ich über avr-studio auch ausführen konnte. allerdings
geht das nicht, wenn ich es dem projekt hinzu linken möchte, dann kann
er damit nichtsmehr anfangen.
aber in der avr/io.h wird ja auch eine datei eingebunden, welche wohl
ähnliche elemente beinhaltet, da ich ja nun auf SPL etc. zugreifen kann.
@Johann L.: Es handelt sich dabei um einen Selbsttest (von einer ganzen
Reihe) den Sicherheitssteuerungen während des Betriebes ausführen müssen
um die korrekte Funktion des µC sicher zu stellen.
Klaus wrote:
> Frage: Was spricht gegen die Benutzung des Inlineassemblers?
Alles.
> Damit> dürfte das ganze doch wesentlich einfacher sein, oder?
Nein, es wird um eine Größenordnung komplizierter. Wenn du's nicht
glaubst, dann versuche einfach mal den obenstehenden Quelltext darin
umzuformen und poste ihn hier.
Der Inline-Assembler ist extrem stark mit dem Compiler verzahnt. Das
macht ihn einerseits zu einem sehr mächtigen Werkzeug für den
erfahrenen Anwender und vor allem für die Autoren der Systembiblio-
thek(en), da man letztlich Assemblercode einbinden lassen kann, der
sich nahtlos in die Optimierungskonzepte des Compilers integriert.
Andererseits ist die Lernkurve, die man dafür auf sich nimmt, doch
recht steil, und der resultierende Codeschnipsel oftmal nahezu
unleserlich.
Max K. wrote:
> eine andere frage: warum gibt mir der befehl:>>
1
> PPR_RET: LDI ZH, hi8(PPR_RET1)
2
> LDI ZL, lo8(PPR_RET1)
3
> PUSH ZL
4
> PUSH ZH
5
> RET
6
>
> einen falschen Wert für was Label PPR_RET1 zurück? er springt an einen> völlig falsche Stelle, warum?
Weil du die um ein Bit verschobene Adressierung zwischen dem Flash-ROM
als Quelle von Daten und dem Flash-ROM als Quelle von Code-Zeigern
nicht berücksichtigt hast.
Was diese Verrenkungen allerdings überhaupt bezwecken sollen, vermag
ich mir nicht vorzustellen. Du hast nur gerade bemerkt, dass das
offenbar zur Gruppe von "101 ways how to shoot into your foot" gehört.
Wer denkt sich denn überhaupt solche unsinnigen Tests aus?
Das muß ein Beamter gewesen sein, der noch nie nen MC gesehen hat.
Hast Du mal nen Link darauf?
Der Test, ob PUSH/POP funktioniert, sagt nämlich überhaupt nichts über
die Gesundheit des Programms aus.
Du mußt testen, ob der Stackpointer auf einen gültigen Wert zeigt, d.h.
zwischen "__bss_end" und "__stack".
Und dann noch, ob im Stack eine genügend große Reserve nicht
unterschritten wurde (Stack mit Muster füllen und prüfen, wieviel Bytes
mit dem Muster noch übrig sind).
Dieser Test würde wenigstens etwas Sinn machen und braucht auch kein
Assembler.
Peter
die tests findet man in einer publikation des BGIAs, genauer gesagt im
Report7 2006, welcher sich auf der Webseite des BGIAs befindet (diese
ist am einfachsten über www.dguv.de zu erreichen).
Der direkte Link ist hier:
http://www.dguv.de/bgia/de/pub/rep/rep05/bgia0706/index.jsp>Weil du die um ein Bit verschobene Adressierung zwischen dem Flash-ROM>als Quelle von Daten und dem Flash-ROM als Quelle von Code-Zeigern>nicht berücksichtigt hast.
Damit ich bei solchen Sachen nicht immer Fragen muss, wie man das am
besten löst, gibts ein geeignetes Tutorial, was mir solche Sachen
genauer erklärt?
habe meine Lösung von hier:
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack
Dort steht genau das beschrieben, was ich in meinem Code auch mache.
1
ldi ZH, high(testRoutine)
2
ldi ZL, low(testRoutine)
3
rcall indirectZCall
4
...
5
6
7
indirectZCall:
8
push ZL
9
push ZH
10
ret
was ja auch im reinen assembler-code unter avrstudio wunderbar
funktioniert hat.
es gibt noch eine weitere frage die mir unter den fingernägeln brennt,
da ich diese probleme auch bestimmt in meine abschlussarbeit aufnehmen
werde: worin unterschreidet sich denn nun genau der reine assembler von
dem wie ich ihn verwende (quasi die linkung zum projekt)? Müsste er
nicht theoretisch die gleichen Befehle unterstützen wie der reine?
Warum ist InlineASM so grundlegend anders? Warum ist es bei dieser Art
nicht möglich eine Datei mit den Definitionen anzugeben damit man auf
den gleichen Befehlssatz zurück greifen kann?
Ich versteh das Programm immer noch net.
Es wär wohl angebracht, sich über den Sinn des Programms zu unterhalten,
was es machen sollte und nicht, anstatt darüber, wie man Syntaxfehler in
einem unsinnigen Programm behebt...
Falls getestet werden soll, ob aufm Stack noch Platz ist, bzw wieviel
Speicher noch frei ist, mach ich das wie in
http://www.roboternetz.de/wissen/index.php/Speicherverbrauch_bestimmen_mit_avr-gcc#Dynamischer_RAM-Verbrauch
Das Programm führt mehrere, sehr simple Tests aus.
1. Es wird geprüft ob der Stackpointer bei PUSH korrekt dekrementiert
wird
2. Es wird geprüft ob der korrekte Wert auf den Stack gepusht wird
3. Es wird geprüft ob der korrekte Wert durch POP vom Stack geholt wird
4. Es wird geprüft ob der Stackpointer bei POP korrekt inkrementiert
wird
5. Es wird geprüft ob der RET-Befehl korrekt funktioniert (Sprung zur
Adresse auf Stack)
beachte: Die Stackinitializierung war nur für den Stand-Alone-Test da,
bei der Implementierung in ein festes Programm (bzw. in eine
Testroutinenbibliothek) wird dieser Teil natürlich gestrichen!
Max K. wrote:
> die tests findet man in einer publikation des BGIAs, genauer gesagt im> Report7 2006, welcher sich auf der Webseite des BGIAs befindet (diese> ist am einfachsten über www.dguv.de zu erreichen).>> Der direkte Link ist hier:> http://www.dguv.de/bgia/de/pub/rep/rep05/bgia0706/index.jsp
Das beschreibt leider nur, wie mal irgend jemand meinte, seinen 8051
testen zu müssen.
Es sagt aber überhaupt nichts über die Sinnhaftigkeit und Notwendigkeit
oder Verbindlichkeit aus.
Insbesondere die Überprüfung aller Maschinebefehle halte ich für äußerst
fragwürdig. Auch Testsoftware kann nur funktionieren, wenn die Befehle
funktionieren, sonst ist deren Verhalten unbestimmt.
Liegt ein Hardwaredefekt im MC selber vor, kann diesen nur ein anderer
funktionsfähiger MC sicher detektieren.
Ein Stummer kann eben nicht sagen, daß er nicht sprechen kann.
Peter
das wird durch ein redunantes bzw. mehrkanaliges system überprüft in dem
sich die systeme gegenseitig überprüfen. es geht hier aber explizit um
die tests eines systems.
ich kann es nur nochmal wiederholen, es ist bestandteil meiner arbeit
diese tests zu schreiben und auch wenn ihr damit rechthaben könnt, dass
das testen unsinnig ist (was nicht meine meinung wiederspiegelt), so
ändert es trotzdem nichts daran, dass ich sie implementieren muss und
möchte.
Max K. wrote:
> 5. Es wird geprüft ob der RET-Befehl korrekt funktioniert (Sprung zur> Adresse auf Stack)
Nö, das wird es eben nicht!
Wenn er nicht an diese Stelle springt, sondern irgendwo anders hin in
die Applikation hinein, merkt das Testprogramm es ja nicht.
Also ist es vollkommen nutzlos.
Du würdest nur merken, wenn es zufällig genau hinter das RET springt,
aber das wäre wie ein Sechser im Lotto.
Peter
er soll ja nicht irgendwo hin springen sondern in PPR_RET1, das macht er
zur zeit noch nicht und ich habe keine ahnung wie ich das fixen soll.
und wenn er irgendwo anders hinspringt, dann merkst du das spätestens
dann wenn der watchdog alarm schlägt oder die synchronisation mit dem
anderen gerät ansteht..
Max K. wrote:
> das wird durch ein redunantes bzw. mehrkanaliges system überprüft in dem> sich die systeme gegenseitig überprüfen. es geht hier aber explizit um> die tests eines systems.> ich kann es nur nochmal wiederholen, es ist bestandteil meiner arbeit> diese tests zu schreiben und auch wenn ihr damit rechthaben könnt, dass> das testen unsinnig ist (was nicht meine meinung wiederspiegelt), so> ändert es trotzdem nichts daran, dass ich sie implementieren muss und> möchte.
Sag jetzt bitte nicht, daß ihr SIL-4 Applikationen auf AVR
implementiert.
Wenn Du fragen zur Syntax von avr-as hast, ist auch avr-gcc eine gute
Adresse, um Fragen zu stellen.
Folgende Module testen deine indirekten Sprünge ohne Assembler. In
getrennten Modulen separat übersetzen.
1
// Modul 1
2
externvoidtest_ijmp(void**);
3
4
chari=0;
5
6
intgoto_label()
7
{
8
test_ijmp(&&L);
9
10
if(i==0)
11
return0;
12
13
L:
14
return1;
15
}
16
17
// Modul 2
18
externintgoto_label();
19
voidtest_ijmp(void**label)
20
{
21
goto*label;
22
}
23
24
intmain()
25
{
26
if(!goto_label())
27
abort();
28
29
exit(1);
30
31
return0;
32
}
Wie man die Adresse eines Labes nimmt, siehst du in der gcc-Ausgabe
(schau in die gcc-Ausgabe an, nicht irgendein Disassemble oder ein
as-Dump) zu Modul 2.
Entsprechende Vorlagen kannst Du fü die anderen Testfälle erhalten.
>er soll ja nicht irgendwo hin springen sondern in PPR_RET1, das macht er>zur zeit noch nicht und ich habe keine ahnung wie ich das fixen soll.
Versuchs mal so:
PPR_RET: LDI ZH, HIGH(PPR_RET1>>1)
LDI ZL, LOW(PPR_RET1>>1)
Gruss Helmi
vielen dank johann, das funktioniert. allerdings würde ich auch gerne
verstehen warum dem so ist. vielleicht hast du ja eine gute quelle wo
ich das nachvollziehen kann.
im groben gesagt: wir wollen damit kein steuerungssystem aufbauen, es
geht um die erforschung des verhaltens von homogen-redundanten systemen.
dazu schien uns einfach ein system aus zwei einfach zu programmierenden
AVR-Controllern geeignet. nichtsdestotrotz wollen wir realistische
bedingungen haben und implementieren daher alle notwendigen
softwarestücke.
Lies die oben gennanten Links endlich.
Dann wirst du irgendwann feststellen dass der AVR einer Harvard
Architektur hat.
D.h. Flash und Ram beginnen jeweils bei addresse 0
Dem Compiler muss man deshalb sagen welchen speicher man will.
--> obengennantelinks lesen ;-)
Max K. wrote:
> Das Programm führt mehrere, sehr simple Tests aus.
Ich halte das alles für extrem theoretisch. Gibt es eigentlich
Hinweise darauf, dass es jemals auch nur einen einzigen Fall von
kaputter CPU gegeben hätte, bei der diese Tests einen tatsächlich
existierenden Fehler aufgedeckt haben, obwohl ansonsten die CPU
noch in der Lage war, die ihr aufgetragenen Befehle abzuarbeiten?
Das kann ich mir nicht vorstellen. Wenn eine CPU so kaputt ist, dass
sie diese primitiven Dinge nicht mehr ausführen kann, warum sollte
sie dann noch in der Lage sein, die entsprechenden Befehle überhaupt
auszuführen?
Was ich mir vorstellen kann, ist dass ein Prozessor mit externem
RAM Probleme in der Verbindung zwischen CPU und RAM hat. Aber
erstens hat er dann wohl auch externen ROM, zu dem er mit wenigstens
gleicher Wahrscheinlichkeit Verbindungsprobleme hat (ergo den
eigentlich implementierten Code nicht mehr richtig rückliest und
daher sowieso nur noch Unsinn ausführt), und zweitens testet man
einen RAM nicht, indem man gezielt immmer nur das gleiche Bitmuster
schreibt. Die Wahrscheinlichkeit, dass der RAM dennoch kaputt ist,
ist dann immer noch ziemlich groß.
Max K. wrote:
> worin unterschreidet sich denn nun genau der reine assembler von> dem wie ich ihn verwende (quasi die linkung zum projekt)?
Was ist der ,,reine'' Assembler? Hat der sich gewaschen? :-)
Oder meinst du den eher primitiven Atmel-Assembler im Vergleich
zum GNU-Assembler, der beim GCC mit geliefert wird?
> Müsste er> nicht theoretisch die gleichen Befehle unterstützen wie der reine?
Der GNU-Assembler (gas) für den AVR unterstützt ja auch die gleichen
Befehle wie der Atmel-Assembler. Er unterstützt nur nicht die
gleichen Pseudo-Befehle, und die Definition der IO-Register in
den Include-Dateien ist bei der avr-libc primär auf die Benutzung
im C-Code ausgerichtet, sodass man für die Benutzung im Assemblercode
dieses Einschließen in _SFR_IO_ADDR() machen muss. (Alterantive
Varianten, die ohne diese Maßnahme auskommen, stehen in der Doku
zur avr-libc.)
> Warum ist InlineASM so grundlegend anders?
Weil der Inline-Assembler, wie schon beschrieben, als Ergänzung
für den Compiler realisiert ist, um dem geübten Anwender oder dem
Lieferanten der Systembibliothek ein möglichst universelles
Werkzeug in die Hand geben zu können, mit dem er allerlei Sonder-
funktionen seiner Umgebung in den C-Code integrieren kann, ohne
dabei den Optimierungsschritten des Compilers übermäßig im Weg herum
zu stehen. Dies geschieht, indem man nicht irgendwo stur auf den
Hardwareregister herum opert, wobei dem Compiler dann nichts anderes
übrig bleibt, als sie für den geneigten Inline-Assembler-Hacker
passend frei zu schaufeln, sondern man drückt seine Daten stattdessen
mit den gleichen sogenannten constraints aus, die der Compiler
intern ohnehin verwendet. Auf den AVR bezogen sagt man also
beispielsweise nicht: ,,Lieber Compiler, der Code hier befummelt
Register r22 und gibt sein Ergebnis in r24 aus, nun kümmere dich
mal!'', sondern man sagt: ,,Lieber Compiler, lege mir die Variable
für mein Zwischenergebnis an, wobei ich sie in einem der Register
oberhalb r16 benötige (nach dem Ende des inline asm statements
gehört die Variable dann wieder dir für beliebige Zwecke einschließ-
lich der geflissentlichen Entsorgung), und gib mir eine beliebige
Registervariable für mein Rechenergebnis, aus der du das dann gleich
1:1 weiter benutzen kannst.''
> Warum ist es bei dieser Art> nicht möglich eine Datei mit den Definitionen anzugeben damit man auf> den gleichen Befehlssatz zurück greifen kann?
Die Befehle sind die gleichen! Was nicht symbolisch direkt
zugreifbar ist, sind die Namen der IO-Register. Das liegt einfach
daran, dass diese in einem C-Programm vom Präprozessor durch
relativ umständlich anmutende Konstrukte ersetzt werden (Dereferen-
zieren eines Zeigers auf ein "volatile" ausgewiesenes uint8_t-Objekt),
denn es muss ja syntaktisch irgendwo in C hineinpassen. Damit sind
sie aber im inline-Assembler nicht mehr symbolisch verfügbar. Man
kann sie trotzdem symbolisch in das inline asm statement hineinfüttern,
aber halt über den Umweg eines constraints ("I" in diesem Falle).
Das wiederum sieht dann alles zusammen doch viel unlesbarer aus, als
wenn man gleich das direkte Assemblerprogramm nimmt.
Max K. wrote:
> und wenn er irgendwo anders hinspringt, dann merkst du das spätestens> dann wenn der watchdog alarm schlägt oder die synchronisation mit dem> anderen gerät ansteht..
Du stimmst mir also zu, daß das Testprogramm selber nicht merkt, wenn er
woanders hin springt.
D.h. nicht das Testprogramm bemerkt den fehlerhaften Ablauf, sondern
(eventuell) der Watchdog.
Damit ist doch klar das Testprogramm als völlig nutzlos und überflüssig
erkannt. Wozu also diese Mühe?
Ob das Testprogramm bei fehlerfreier CPU funktioniert, interessiert
keinen.
Es ist nur dann funktional, wenn es den fehlerhaften Zustand eindeutig
erkennt oder wenigstens in den meisten Fällen. Und das schafft dieses
Testprogramm eben nicht, also ist es überflüssig.
Ich bezweifle auch stark, ob man überhaupt ein Testprogramm schreiben
kann, welches einen Defekt der eigenen CPU erkennt.
Ein CPU-Defekt kann bewirken:
1. daß ein Befehl falsch dekodiert wird und z.B. als 2Word-Befehl
ausgeführt wird.
2. ein Befehl auf falsche Adressen, Register ausgeführt wird
3. ein Befehl mit falschen Werten ausgeführt wird
4. Ein Befehl falsch ausgeführt wird (z.B. Flags falsch setzt).
Und nun frage ich Dich, ob Dein Testprogramm diese Fehlerarten alle
erkennen kann.
Ein ernsthafter Testansatz wäre, daß ein zweiter MC den ersten per JTAG
in den Debug-Modus versetzt, eine Testsuite ausführt und dann per
Memory- und Registerdump überprüft, ob diese Testsuite einwandfrei
ausgeführt wurde.
Wobei allein das Erstellen der Testsuite schon anspruchsvoll genug ist.
Peter
P.S.:
Das richtige Erstellen einer funktionierenden Watchdogroutine ist auch
keine leichte Aufgabe.
gast wrote:
> Dann wirst du irgendwann feststellen dass der AVR einer Harvard> Architektur hat.> D.h. Flash und Ram beginnen jeweils bei addresse 0>> Dem Compiler muss man deshalb sagen welchen speicher man will.
Nein.
Hier geht es nicht um einen Compiler, sondern um einen Assembler ;-)
Daß AVR eine Hardvard-Architektur ist, spielt hier ausnahmnweise mal
keine Rolle. Was jedoch wichtig ist, ist wie ein Symbol verwendet
wird. CALL legt nämlich nicht die Byte-Adresse eines Symbols auf den
Stapel, sondern die Wort-Adresse. lo8(pm()) fügt andere RELOCs ein als
lo8(). Obwohl mit LPM zu lesende Daten auch im Flash stehen, benutzt LPM
ne andere Darstellung als CALL/IJMP/RET/RTI. Wenn ich mich recht
erinnere ist das RTI-Format auch anders als das von RET.
lo8(main>>1) funktioniert übrigens nicht, weil es dafür keine RELOCs
gibt.
Jörg Wunsch wrote:
> Max K. wrote:>> Ich halte das alles für extrem theoretisch. Gibt es eigentlich> Hinweise darauf, dass es jemals auch nur einen einzigen Fall von> kaputter CPU gegeben hätte, bei der diese Tests einen tatsächlich> existierenden Fehler aufgedeckt haben, obwohl ansonsten die CPU> noch in der Lage war, die ihr aufgetragenen Befehle abzuarbeiten?> Das kann ich mir nicht vorstellen. Wenn eine CPU so kaputt ist, dass> sie diese primitiven Dinge nicht mehr ausführen kann, warum sollte> sie dann noch in der Lage sein, die entsprechenden Befehle überhaupt> auszuführen?
Ich sag mal so: Die AVR-Gemeinde ist gesegnet mir einem µC, der
praktisch bugfrei ist und sich schlichtweg nicht mit dem Thema
Silicon-Bugs auseinandersetzen muss. Aber schau mal, was unter der Haube
Deines KFZ' tickt: vermutlich u.a. ein TriCore.
Ohne Compiler/Assembler/Linker, die die Armada an Silicon-Bugs
umschiffen, könnst den SI-Käfer in die Tonne treten.
Die Errata sind mehrere 100 Seiten dick, dazu im Vergleich hat AVR
maximal eine A4-Seite zu bieten. Da sind so Leckerli dabei, daß mache
Arithmetikbefehle nicht funzen, das PSW falsch gesetzt wird, hier und da
mal ein Trap erzeugt wird, Sprünge falsch ausgeführt werden oder falsche
Ergebnisse aus dem Speicher gelesen werden, wenn dort zu viele Bits der
gleichen Sorte stehen (Busleitung zu dünn ausgelegt).
Gleichwohl bin ich Deiner Auffassung, daß solche Tests zu einer Erhöhung
der Sicherheit nichts beitragen. Sie erhöhen eher das Risiko einer
abschmierenden Applikation durch unsauber imlementierte Tests. Errate
auf dem einen Exemplar verhalten sich vermutlich ebenso wie auf dem
anderen, und sporadische Fehler kann man weder aussschliessen, noch
bietet AVR Sicherheitskonzepte wie unterschiedliche Benutzerprioritäten
oder ein MPU (Memory Protection Unit).
Was AVR-Errata angeht, dürften zwei gleiche AVRs (das System ist homogen
ausgelegt) bei
http://sourceforge.net/tracker/index.php?func=detail&aid=2264356&group_id=68108&atid=520074
ununterscheidbar reagieren.
Guten Morgen,
danke für eure Anregungen. Ich kann eure Ansichten nachvollziehen, da
ich in gewissem Maße auch der Meinung bin, dass manche Tests so gesehen
keinen Sinn ergeben. Jedoch wurden am BGIA einige Nachforschungen
angestellt um diese Tests zu erstellen, daher werden diese nicht
komplett sinnlos sein.
Ich kann nur betonen, dass es nicht meine Aufgabe ist denn Sinn dieser
Tests zu belegen oder zu widerlegen, sie sind ein bestandteil der
Software, also meines Programms, welches ich auf den µC implementieren
werde.
Dies ist durch die Spezifikation meiner Abschlussarbeit festgehalten.
Ein nettes "Feature" von den Selbsttests ist aber, dass ich mich mit
Assembler beschäftige, was mich irgendwie fasziniert. Ich habe bis jetzt
nur mit hochsprachen ala Java etc. gewerkelt und steige gerade zum
ersten mal in die Programmierung eines µC ein. Auch den AVR habe ich
zuerst mit C bearbeitet und so ein Programm zur Synchronisation
geschrieben. Jedoch sah ich mich nicht in der Lage die hardwarenahen
Tests in dieser Sprache zu implementieren. Sogesehen sind die Tests
nicht ganz ohne Nutzen.
Außerdem seht ihr nur einen der vielen Tests aus dem Report. Da der
Report öffentlich ist könnt ihr ihn euch alle gerne anschauen (Link
weiter oben) und dann über die sinnhaftigkeit der Tests im einzelnen
sprechen. Ich bin mir sicher, dass meine Kollegen und meine Vorgesetzen
für Anmerkungen und Hinweise bezüglich dieser Tests dankbar sein werden.
Kontaktadressen findet ihr ebenso auf der Seiten oben.
@Jörg: Natürlich mein ich den ATMEL und den GCC-Assembler, wie gesagt
die definierung meiner Probleme fällt mir manchmal ein wenig schwer, da
ich den Überblick über die verschiedenen "Assembler"-Arten (wenn man es
so nennen darf) verliere. Das Problem habe ich auch wenn ich mir
tutorials anschaue. Ich kann leider oft nicht ersehen zu welcher Art das
Tutorial nun gehört.
Ich werde mich nun nochmal genauer mit dem GCC-Assembler auseinander
setzen, da es scheinbar dieser sein wird, mit welchem ich arbeiten
werde. Dies scheint mir die einfachste Lösung für meine Probleme zu
sein.
Max K. wrote:
> Jedoch wurden am BGIA einige Nachforschungen> angestellt um diese Tests zu erstellen, daher werden diese nicht> komplett sinnlos sein.
Das jemand irgendwas macht, begründet in keinster Weise die
Sinnhaftigkeit seine Tuns.
Sei mir nicht böse, aber auf mich macht der oben verlinkte Artikel einen
sehr laienhaften Eindruck. Nirgends wird auf die Fehlerhäufigkeit oder
die Erkennungssicherheit eingegangen.
> Ich kann nur betonen, dass es nicht meine Aufgabe ist denn Sinn dieser> Tests zu belegen oder zu widerlegen, sie sind ein bestandteil der> Software, also meines Programms, welches ich auf den µC implementieren> werde.> Dies ist durch die Spezifikation meiner Abschlussarbeit festgehalten.
Das ist Vogel-Strauß-Politik (Augen zu und durch):
Ich bastele einfach irgendwelche Tests rein und dann wird das ganze
schon (hoffentlich) sicher sein.
Damit wird sich keine Stelle, die eine SIL-Klassifizierung vornehmen
soll, zufrieden geben.
Du mußt erstmal überlegen, welche Fehlerquellen haben welche Signifikanz
und dann mußt Du das auch an konkreten Zahlen nachweisen.
Und dann erst kannst Du darangehen, die mit hoher Signifikanz als erstes
zu lösen.
Fehlfunktionen der CPU werden dabei an allerletzter Stelle stehen.
Und wenn, dann werden sie zu 99% Folgefehler sein (Fehler in der
Stromversorgung, Entkopplung, Kühlung usw.).
Peter
was heißt den vogel-strauß poliktik? Ich habe nicht die Aufgabe ein
absolut sicheres system aufzubauen. Meine aufgabe ist eben ein system
mit aktuellen sicherheitsmaßnahmen auszustatten. genau das werde ich
machen, auch wenn es in euren (und zum teil in meien augen) keinen
richtigen sinn hat. ich bin davon überzeugt, dass die arbeiten und
reports keineswegs laienhaft erstellt wurden.
aber selbst wenn, meine anweisung (bzw. die definition in der
spezifikation) steht und ich kann und möchte nicht davon abweichen, da
alles andere einen erfolg meiner abschlußarbeit gefährden würde!
Max K. wrote:
> aber selbst wenn, meine anweisung (bzw. die definition in der> spezifikation) steht und ich kann und möchte nicht davon abweichen, da> alles andere einen erfolg meiner abschlußarbeit gefährden würde!
Was für eine Art von Arbeit ist das denn? Vielleicht kannst du ja die
durchaus begründeten Zweifel (ich stimme hier mit Peter komplett
überein) wenigstens in einer Art Schlussbetrachtung oder Thesen oder
dergleichen anbringen? Bei einer wissenschaftlichen Arbeit sollte
ja die Benotung nun nicht davon abhängen, ob der Inhalt komplett die
(u. U. halt fehlerhaften) Erwartungen der Aufgabenstellung stützt
oder aber sie sauber widerlegt, solange die Beweisführung schlüssig
ist.
Jörg Wunsch wrote:
> Max K. wrote:>>> aber selbst wenn, meine anweisung (bzw. die definition in der>> spezifikation) steht und ich kann und möchte nicht davon abweichen, da>> alles andere einen erfolg meiner abschlußarbeit gefährden würde!>> Was für eine Art von Arbeit ist das denn? Vielleicht kannst du ja die> durchaus begründeten Zweifel (ich stimme hier mit Peter komplett> überein) wenigstens in einer Art Schlussbetrachtung oder Thesen oder> dergleichen anbringen? Bei einer wissenschaftlichen Arbeit sollte> ja die Benotung nun nicht davon abhängen, ob der Inhalt komplett die> (u. U. halt fehlerhaften) Erwartungen der Aufgabenstellung stützt> oder aber sie sauber widerlegt, solange die Beweisführung schlüssig> ist.
Möglich ist ein aufgreifen während des Resumee, allerdings darf ich
nicht einfach die hälfte der Tests weglassen mit der Begründung "Bringt
eh nichts"..
Es handelt sich hierbei um eine Bachelor-Abschlussarbeit, somit liegst
du mit wissenschaftlich schon richtig.
Max K. wrote:
> Möglich ist ein aufgreifen während des Resumee, allerdings darf ich> nicht einfach die hälfte der Tests weglassen mit der Begründung "Bringt> eh nichts"..
Es wäre ja eher darum gegangen, sie durch sinnvollere Tests zu
ersetzen, nachdem man demonstriert, dass sie in der ursprünglich
gedachten Form sowieso zwecklos sind.
wie gesagt, es hat seinen grund warum diese tests gewählt worden sind,
daran wird sich nichts ändern. es würde auch den rahmen einer 3monatigen
bachelor-arbeit sprengen wenn ich jetzt neben dem system noch die
selbsttests erstellen müsste, das könnte man vielleicht im rahmen einer
master-thesis (knapp 1 jahr mit vorhergehenden praktika) machen aber so
ist das schlicht und einfach zuviel.
ich danke euch für eure hilfe mit assembler, bitte euch jedoch nun das
thema mit dem selbsttests ruhen zu lassen, da ich da eh nichts dran
ändern kann / werde. Sollt ihr euch trotzdem noch dazu gezwungen fühlen
dort was zu verändern, ihr findet die adressen zu den verantwortlichen
leuten alle auf der öffentlichen DGUV respektive BGIA-Seite (links sind
schon weiter oben vorhanden).
In diesem Sinne: Danke euch, ihr habt toll geholfen, sollte noch was
sein werde ich mich melden aber bitte keine diskussion über sinn und
unsinn der selftests.. ;)
Max K. wrote:
> Guten Morgen,>> danke für eure Anregungen. Ich kann eure Ansichten nachvollziehen, da> ich in gewissem Maße auch der Meinung bin, dass manche Tests so gesehen> keinen Sinn ergeben. Jedoch wurden am BGIA einige Nachforschungen> angestellt um diese Tests zu erstellen, daher werden diese nicht> komplett sinnlos sein.
Immerhin haben die Tests ne psychologische Funktion:
Sie geben dem, der so ein System baut/beauftragt, das Gefühl und die
Beruhigung, was für die Sicherheit getan zu haben und einer Spez gefolgt
zu sein.
Zu deiner Arbeit:
Wenn du solche Tests implementierst, dann ist der WDT nicht gut
geeignet, um Instruktionen wie zB RET zu testet. Der WDT ist einfach zu
ungenau. Wenn ein RET in die Hose geht, passieren danach noch 1000
andere Instruktionen.
Also: Nicht den WDT nehmen, sondern eine Timer-IRQ, die auf genau so
viele Ticks getrimmt wird, wie bis zum Abarbeiten des RET erwartet
werden. Nach dem RET schlägt die IRQ zu, und in dieser liest du (bzw.
lässt den AVR lesen) den Inhalt des gepushten PC vom Stack und
vergleichst ihn mit der erwarteten Adresse. Falls ein RET nicht
funktioniert, ist damit die Nebenwirkung auf das System minimiert (ein
funktionierendes IRQ-System setzt auch der WDT-Ansatz voraus).
Zu einer Arbeit gehört auch deren Verortung in Raum und Zeit, und in der
Einleitung und/oder Zusammenfassung gehört auf jeden Fall ein Wort zum
Stand der Kunst. WDT, Checksummen auf Speicher, etc. und was das Design
zeitgemässer Systeme angeht. Im Zweifelsfalle in die SIL reinschauen
oder welche Sicherheitsaspekte Betriebsysteme wie pxros-hr bringen, die
Speicherschutz und Kapselung/Rückwirkungsfreiheit von Komponenten auf
Harwareebene garantieren.
Max K. wrote:
> wie gesagt, es hat seinen grund warum diese tests gewählt worden sind,> daran wird sich nichts ändern. es würde auch den rahmen einer 3monatigen> bachelor-arbeit sprengen wenn ich jetzt neben dem system noch die> selbsttests erstellen müsste
Da hast Du natürlich recht, daß die Anforderungen an eine reale
Produktentwicklung nicht mehr im Rahmen einer Studienarbeit liegen.
Es sollte Deine Arbeit also nicht beeinflussen, sondern nur mal ein
Denkanstoß über den Tellerrand hinaus gewesen sein.
Und 2-3 abschließende Sätze in dieser Richtung würden eine sehr gute
Arbeit auszeichnen.
Der Lösungsansatz von Johann bezüglich des RET-Tests ist gut.
Man könnte es sogar dahingehend optimieren, indem man einen Interrupt
nimmt, der nicht gebraucht wird, aber ständig getriggert ist, der
SPM_READY_vect ist ideal.
Und dann unmittelbar vor dem RET ein SEI machen, damit landest Du direkt
nach dem RET im Interrupt und ein RET in den Wald kann keinen Schaden
anrichten.
Bei den Rechentests ist zu beachten, daß der AVR keinen ACCU hat, d.h
zumindest eine Operation muß für alle 32 Register getestet werden.
Und natürlich muß nach jedem Rechentest nicht nur das Ergebnis, sondern
auch alle beeinflußten Flags (SREG) überprüft werden. Die Flags sollten
dazu vorher auf den "falschen" Wert gesetzt werden.
Peter
Hab noch eine kleine Frage hinter die ich leider nicht von alleine
komme.
Habe jetzt ne ganze Zeit lang wunderbar gearbeitet, jetzt habe ich
allerdings mein WinAVR geupdatet, da ich einen Bug mit.. ach ich weiß
nicht genau was es war, jedenfalls war es notwendig, dass ich meine
Version update.
Nun compiliert er nichtmehr sauber, bzw. er bricht ab mit folgender
meldung:
c:\WinAVR-20080610\bin\avr-objcopy.exe: --change-section-lma .eeprom=0x00000000 never used
ich habe nun gelesen, dass dies passiert falls man den "eeprom nicht
nutzt". Man soll darum im makefile einfach eine stelle ändern, was bei
mir aber schon so der fall ist:
@ Max K.
> Nun compiliert er nicht mehr sauber, bzw. er bricht ab mit> folgender Meldung:
Wie ist die komplette Meldung?
Es fehlt oben der letzte, entscheidende Satz.
Bei der gezeigten Meldung ist alles noch normal.
c:\WinAVR-20080610\bin\avr-objcopy.exe: --change-section-lma .eeprom=0x00000000 never used
41
42
Creating Extended Listing: Blinky.lss
43
avr-objdump -h -S Blinky.elf > Blinky.lss
44
45
Creating Symbol Table: Blinky.sym
46
avr-nm -n Blinky.elf > Blinky.sym
47
48
Size after:
49
Blinky.elf :
50
section size addr
51
.text 2338 0
52
.stab 10608 0
53
.stabstr 349 0
54
.debug_aranges 32 0
55
.debug_pubnames 27 0
56
.debug_info 142 0
57
.debug_abbrev 80 0
58
.debug_line 549 0
59
.debug_frame 32 0
60
.debug_str 109 0
61
Total 14266
62
63
64
65
Errors: none
66
-------- end --------
67
68
69
> Process Exit Code: 0
70
> Time Taken: 00:01
makefile siehe oben, angepasst mit den entsprechenden dateien, lief bis
vor dem update wunderbar..
edit: was ich mit "lief" genau meinte ist, dass ich das programm im
AVR-Studio wunderbar benutzen konnte. Jetzt aber included er die
Assembler-Programme nichtmehr und führt nurnoch den C-Teil aus. Der
Assemblerteil ist im AVR-Studio nicht zu sehen (weder in C-Ansicht, dort
sind die Funktionsaufrufe einfach weg, als auch im dissasembly, dort
springt er nach dem letzten befehl in eine schleife aus delay_basic
(woher die kommt weiß ich nicht) und anschließend wieder zum anfang!
Hmm, ich sehe nichts auffällig Falsches in dem Ausgabeprotokoll des
Makes.
Vielleicht mal das Projekt in ein Archiv packen und als Anhang posten.
Vielelicht kann jemand das live mit seinem WinAVR 20080610
nachvollziehen, wenn er in die Listings schauen kann.
ich verstehe gerade die welt nichtmehr.. ich habe jetzt zum bestimmt
10en mal die datei kompiliert und bei avr-studio neu geladen. jetzt geht
es auf einmal. ich bin mir relativ sicher nichts geändert zu haben, auch
die make-ausgabe sieht wieder genau so aus. jetzt sind aber die
selbsttests da.
sehr komisch, ich glaube es ist zeit für ein wochenende.. trotzdem danke
euch ;)
achja, kann ich mit
1
CALL XY
die methode
1
voidXY(){bla}
aufrufen?
die methode XY liegt in einer anderen, dem projekt angehörigen datei.
geht das so einfach oder muss ich in die .S datei noch was hinzufügen?
(bsp. wie header-datei von der *.c datei in welcher XY drin ist?)