SDCC und ASM

#5553970
Lesenswert?

Hallo

In meinem C Programm berechne ich die CRC des bootloaders mit einer ASM 
Routine.
Board ist ein 8051(bootloader liegt auf 0x0000). Ich benutze SDCC. Das 
Programm wird auf Adresse 0x4000 geladen.
Es funktioniert mit den Parameter: --code-loc 0x4000 --stack-auto --vc
                mit den Parameter: --code-loc 0x4000 --model-large --vc
stimmt die berechnete CRC nicht mehr (immer 0xFFFF). Ich vermute, daß 
die Variablen von ASM zu C nicht übertragen werden. Fehlt da vielleicht 
noch eine Eistellung wegen XRAM. Wer kann helfen?

Viele Grüße
           Peter
Angehängte Dateien:
Gast #5554880
Lesenswert?

Peter W. schrieb:
> Ich vermute, daß
> die Variablen von ASM zu C nicht übertragen werden.
Ich würde versuchen, den Fehler weiter einzugrenzen.
Was passiert, wenn die asm-Routine eine feste Zuweisung an 'wert' macht?
An welche Stellen legt der Linker Stack und XStack?
Vielleicht gibt es dort gar keinen RAM?!

> Fehlt da vielleicht
> noch eine Eistellung wegen XRAM.
1
--xram-loc <Value> The start location of the external ram, default value is 0.
Hast Du denn 'external RAM' (XRAM)?
Wenn ja, an welcher Adresse?


Laut sdccman.pdf wird beim Huge-Modell alles auf 'banking' eingestellt.
Kann Deine Hardware das?
#5554904
Lesenswert?

Hast mal ùberlegt, wie "mov A,_wert" funktionieren soll,
wenn "_wert" im XRAM liegt?
Schau dir doch einfach mal den Code an, den der Compiler bei Benutzung 
von "wert" im "large"-Modell generiert. An XRAM kommt man nur indirekt.
Der Vorteil einer Hochsprache ist eben, daß man sich um solche Details 
nicht kümmern muß und der "Vorteil" von Assembler, das man jede 
Fehlermöglichkeit ausnutzen kann. Wobei die Toolchain (Assembler/Linker) 
schon Möglichkeiten hätte, sowas zu erkennen, offenbar aber nicht tut.
Eigentlich könnte es solche Fälle auch in den Sourcen der 
Laufzeitumgebung finden lassen. Da kannst du ja mal schauen, wie die das 
gelöst haben. Vermutlich gibt es ein Preprozesser-Makro, daß das aktuell 
benutzte Speichermodell beinhaltet und zukünftig deine 
"large"-Implementierung statt der schon vorhandenen 
"small"-Implementierung per #if ... #endif freigibt.

Edit:
SDCC Doku sagt, diese Makros zeigen das Memorymodell:
__SDCC_MODEL_SMALL
__SDCC_MODEL_MEDIUM
__SDCC_MODEL_LARGE

PS: du mußt ja nicht alles austauschen, aber die Zugriffe auf Variablen 
müssen eben Memory-Modell-spezifisch geschrieben werden.
#5555442
Lesenswert?

@ TIM
Bei einem festen 'wert' kommt auch das gleiche falsche Ergebnis.
xram 0x0000 - 0x3FFF
Was meinst Du mit banking - und ohne dem geht es wohl nicht?
Ich habe eine "features.h" im Ordner "SDCC_ASM" entdeckt. Die wollte ich 
einbinden - funktioniert nicht.

...
/* define _RETURN for correct returning from inline asm functions
*/
#if defined(__SDCC_MODEL_HUGE)
 #define _RETURN ljmp __sdcc_banked_ret
#else
 #define _RETURN ret
#endif
...
Könnte hier die Ursache liegen?
Übrigens finde ich kein model_huge im SDCC.



@ Carl D.
Ich dachte das macht alles der compiler für mich...! Muß ich das jetzt 
selber machen, aber wie?
Programm Beispiele zu diesem Thema finde ich leider nicht.


Viele Grüße
           Peter
Angehängte Dateien:
Gast #5555658
Lesenswert?

Peter W. schrieb:
> Ich habe eine "features.h" im Ordner "SDCC_ASM" entdeckt. Die wollte ich
> einbinden - funktioniert nicht.
Das ist keine valide Fehlerbeschreibung.

> Übrigens finde ich kein model_huge im SDCC.
Welche Version vom SDCC hast Du?
Meine Doku ist von der Version 3.4.1. Ob die auch tatsächlich die 
angegebenen Compilerschalter hat, habe ich nicht geprüft.
Angehängte Dateien:
(Firma: h.a.l.m.) #5555694
Lesenswert?

Im large Model werden dir deine variablen in den XRam gelegt.
Zugriff geht hier dann z.b. über den dptr und movx  oder indirekt
über Rx und dem Page select im sfr mit movx.
Du kannst dir deine variablen im large model auch in den
Data ram legen lassen mit dem Attribut __data vor der Deklaration.
Schaue ruhig mal in die *.map Datei da kann man einsehen
was vom sdcc wo abgelegt wird.
#5555794
Lesenswert?

> @ Carl D.
> Ich dachte das macht alles der compiler für mich...! Muß ich das jetzt
> selber machen, aber wie?
> Programm Beispiele zu diesem Thema finde ich leider nicht.

Large Memory Model legt nur die Default-Storrage-Class für Daten fest.
Um es ganz einfach zu machen könnte man einfach schreiben:
1
...
2
//#define CRC_IS_SMALL_MODEL
3
#define CRC_IS_LARGE_MODEL
4
#if defined(CRC_IS_LARGE_MODEL)
5
__xdata unsigned char wert = 0;
6
__xdata unsigned crc = 0xFFFF; // Startwert
7
#elif defined(CRC_IS_SMALL_MODEL)
8
__data unsigned char wert = 0;
9
__data unsigned crc = 0xFFFF; // Startwert
10
#endif
11

12
void crc16() {
13
    // clang-format off
14
  unsigned x = crc;
15
  __asm__(
16
#if defined( CRC_IS_LARGE_MODEL )
17
    " mov  dptr,#_crc  \n"
18
    " movx a,@dptr     \n"
19
    " mov  R2,a        \n"
20
    " inc  dptr        \n"
21
    " movx a,@dptr     \n"
22
    " mov  R3,a        \n"
23
    " mov  dptr,#_wert \n"
24
    " movx a,@dptr     \n"
25

26
#elif defined( CRC_IS_SMALL_MODEL )
27
   " MOV  R2,_crc   ;  \n"
28
   " MOV  R3,_crc+1 ;  \n"
29
   " MOV  A, _wert  ;  \n"
30
#endif
31
   " XRL  A,R3      ;  \n"
32
   " MOV  R3,A      ;  \n"
33
   " SWAP A         ;  \n"
34
   " ANL  A,#0x0F   ;  \n"
35
   "                ;  \n"
36
   " XRL  A,R3      ;  \n"
37
   " MOV  R3,A      ;  \n"
38
   " SWAP A         ;  \n"
39
   " RL   A         ;  \n"
40
   " MOV  B,A       ;  \n"
41
   " ANL  A,#0x1F   ;  \n"
42
   " XRL  A,R2      ;  \n"
43
   " MOV  R2,A      ;  \n"
44
   " MOV  A,B       ;  \n"
45
   " RR   A         ;  \n"
46
   " ANL  A,#0xF0   ;  \n"
47
   " XRL  A,R2      ;  \n"
48
   " ANL  B,#0xE0   ;  \n"
49
   "                ;  \n"
50
   " push A         ;  \n"
51
   " mov  A,B       ;  \n"
52
   " xrl  A,R2      ;  \n"
53
   " mov  B,A       ;  \n"
54
   " pop  A         ;  \n"
55
   "                ;  \n"
56
#ifdef CRC_IS_LARGE_MODEL
57
   " mov  dptr,#_crc   \n"
58
   " mov  A,R2         \n"
59
   " movx @dptr,A      \n"
60
   " mov  A,R3         \n"
61
   " inc  dptr         \n"
62
   " movx @dptr,A      \n"
63
#elif defined( CRC_IS_SMALL_MODEL )
64
   " MOV _crc+1,A      \n"
65
   " MOV _crc,  B      \n"
66
#endif
67
  );
68
    // clang-format on
69
}
70

71
int main() {
72
    unsigned int i = 0;
73
    unsigned int a = 0;
74

75
    for (i = 0; i < sizeof(dat); i++) {
76
        wert = dat[i];
77
        crc16();
78
    }
79
    ...

"__data" sorgt dafür, daß die in Inline Assembler genutzten Variablen
im direkt adressierbaren RAM liegen.
BTW, - neue ASM Syntax,
     - crc als unsigned int inklusive Zugriff aus Inline Assembker,
     - "umschaltbares" Speichermodell
#5556606
Lesenswert?

Peter W. schrieb:
> @ Carl D.
> Du hast Dir ja echt viel Arbeit gemacht - Danke. Werde ich mal
> ausprobieren.
>
> Viele Grüße
>            Peter

Naja, erstens wollte ich mal wieder das SDCC-Plugin in Eclipse 
ausprobieren und zweiten hab ich die CRC-Berechnung nur insoweit 
überarbeitet, daß ich crc und wert in Registern (die laut Doku SDCC frei 
verfügbar sind) abgelegt, um Speicherzugriff und Verarbeitung zu 
trennen. Für den eigentlichen Algorithmus bleiben sämmtliche Rechte und 
Risiken bei dir ;-)

Ich würde aber ehrlich gesagt überlegen, ob das Small-Modell nicht 
grundsätzlich besser wäre und nur z.B. Puffer mit __xdata verziert 
werden sollten. Durch die Attribute kann man den Speicherort ja genau 
festlegen. Wenn ich anschaue, was bei Large an Code produziert werden 
muß, dann würde ich mich dazu erst durch Speicherengpaß zwingen lassen.
#5557396
Lesenswert?

Hab das mal getestet mit mov dptr #_crc .......
funktioniert wunderbar.
Ich hatte meinen 8051_board umgebaut, um XRAM nutzen zu können. Das hat 
bei nur C_Programmen sofort funktioniert. Da hab ich mich schon 
gewundert, daß das eben mit dem ASM nicht mehr klappt.
So wie ich das jetzt sehe, werden beim model_large die lokalen Variablen 
zum größten Teil als globale im XRAM erzeugt - dazu noch reichlich. Das 
ist natürlich weniger schön.
Small_model ist natürlich besser!

Viele Grüße
           Peter

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren