Forum: Compiler & IDEs SDCC und ASM


von Peter W. (pe_wi)


Angehängte Dateien:

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

: Verschoben durch User
von Tim (Gast)


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?

von Carl D. (jcw2)


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.

: Bearbeitet durch User
von Peter W. (pe_wi)


Angehängte Dateien:

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

von Tim (Gast)


Angehängte Dateien:

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.

von Florian H. (Firma: h.a.l.m.) (flomann)


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.

von Carl D. (jcw2)


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

von Peter W. (pe_wi)


Lesenswert?

Vielen Dank für die Antworten

__data, klappt wunderbar

@  Florian H.
das *.map ist interessant hab ich mir bis jetzt noch nie angeschaut

@ Carl D.
Du hast Dir ja echt viel Arbeit gemacht - Danke. Werde ich mal 
ausprobieren.

Viele Grüße
           Peter

von Carl D. (jcw2)


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.

von Peter W. (pe_wi)


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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.