Forum: Mikrocontroller und Digitale Elektronik Von C51 in SDCC, CodeBlocks und Assembler (AT89C51AC3)


von Denis (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich mache eine Projektarbeit mit dem AT89C51AC3 ATMEL Mikrokontroller. 
Dafür muss ich ein neues Projekt aus alten Dateien erstellen. Darunter 
sind Startup.A51, Init.A51 und viele H-/C-Dateien. Diese Dateien wurden 
unter Windows 3.11 mit dem C51 Compiler („und A51 Assembler“) 
kompiliert.

Meine aktuelle Entwicklungsumgebung besteht aus „Code::Blocks“ und 
„SDCC“ Compiler.


Problembeschreibung:

1. Im Keil C51 Assemblercode wird eine C-Funktion aus anderem Modul 
Aufgerufen.  Vor dem Aufruf wird mit der „EXTRN“ Anweisung die Funktion 
bekanntgegeben.
--> Gesucht: Wie kann man die „EXTRN“ Anweisung im SDCC ersetzen oder 
umgehen???

2. Eine vollständige Assembler Datei (also nicht _asm ……….. _endasm; 
gemeint) in einer Kombination mit C- und H-Dateien kompilieren und 
linken mit SDCC und Code::Blocks.
--> Gesucht: INIT.A51 (oder INIT.ASM) und STARTUP.A51 (oder STARTUP.ASM)

Falls etwas unklar ist, oder Fragen einfach melden.


                       ***
                       ***
                    *********
                      *****
                        *


Nähere Informationen zu der Fragestellung:

Bei kompilieren kommt es zu folgenden Fehlern (SDCC Compiler):

************************************************************************

1. Fehler: in der Datei ZEIT_ASS.C

?ASxxxx-Error-<o> in line 608 of obj\Release\ZEIT_ASS.asm
removing obj\Release\ZEIT_ASS.rel
              <o> .org in REL area or directive / mnemonic error

In der Zeile 608 (ZEIT_ASS.asm) steht folgendes: EXTRN CODE 
(ZEITGEBER_DEK)


Der SDCC Compiler kennt nicht den EXTRN Befehl.
Gibt es eine Möglichkeit diesen durch einen anderen Befehl zu ersetzen?

Die Funktion zeitgeber_dek() ist in der ZEITGEB.C deklariert, die Datei 
ZEITGEB.H ist in der Datei ZEIT_ASS.C eingebunden und besteht aus C 
Funktionen.


Diese Datei besteht aus includes und zwei Funktionen:

Alte Version (C51 Compiler)
timer0 {

  #pragma ASM
  ...
  // Assemblercode
  ...
  #pragma ENDASM
}


Neue Version (SDCC Compiler)
timer0 {

  _asm

  // Assemblercode
  …
  _endasm;
}

Alte Version (C51 Compiler)
timer0 () interrupt{

  #pragma ASM
    EXTRN CODE (ZEITGEBER_DEK)

    // Assemblercode
    …
    PUSH  B
    …
    LCALL ZEITGEBER_DEK
    …
    POP  B
    …
  #pragma ENDASM
}


Neue Version (SDCC Compiler)
timer0 () interrupt{

  _asm
    EXTRN CODE (ZEITGEBER_DEK)

    // Assemblercode
    …
    PUSH  B
    …
    LCALL ZEITGEBER_DEK
    …
    POP  B
    …
  _endasm;
}

Zusätzlich ein Ausschnitt aus dem altem make-file:

// MACRO-Deklaration
LAT37 = d:\LAT37\PROG
C51OPTA = SRC SYMBOLS DEBUG OE OT(0,SIZE) RB(0) LARGE
A51OPT = ERRORPRINT NOPRINT DEBUG SYMBOLS
C51 = C51E
...
$(LAT37)\zeit_ass.obj : $(LAT37)\zeit_ass.c
        $(C51) zeit_ass.c   $(C51OPTA) >zeit_ass.err
        a51 zeit_ass.src $(A51OPT)
...

Habe ich das richtig verstanden?
Aus der ZEIT_ASS.C  mit a51 wird eine Assembler-Source Datei 
(zeit_ass.src) erstellt, dann wieder dieselbe Datei mit dem C51 Compiler 
kompiliert und zusammen mit der zeit_ass.src  eine Objektdatei 
ZEIT_ASS.obj erstellt.

=>  1. Frage: Wie kann ich das selbe mit Code::Blocks und SDCC 
realisieren?  < =

Mein Realisierungsversuch (Eigenschaften der zeit_ass.c Datei in 
Code::Blocks IDE)

Siehe Bild ZEIT.ASS Einstellung

********************************************************************

Zu 2. Fehler: in der Datei INIT.ASM

Diese Datei besteht aus folgenden Assembler Befehlen:

                NAME    ?C_INIT

                EXTRN CODE (MAIN)
                PUBLIC  ?C_START

?C_C51STARTUP   SEGMENT   CODE

;?C_INITSEG      SEGMENT   CODE          ; Segment with Initializing 
Data


;                RSEG    ?C_INITSEG
;                DB      0               ; Segment ist definiert, aber 
leer


                RSEG    ?C_C51STARTUP
?C_START:
                LJMP    MAIN

                END

Sobald diese einzelne Datei kompiliert wird, kommt folgende Warnung und 
Kompiliervorgang bricht ab. (das gleiche passiert bei INIT.ASM)

at 1: warning 119: don't know what to do with file 'INIT.A51'. file 
extension unsupported
SDCC : mcs51/gbz80/z80/avr/ds390/pic16/pic14/TININative/xa51/ds400/hc08 
2.9.0 #5416 (Mar 22 2009) (MINGW32)
Usage : sdcc [options] filename
Options :-

Mein Realisierungsversuch (Eigenschaften der zeit_ass.c Datei in 
Code::Blocks IDE)

Siehe Bild INIT.ASS Einstellung

Ausschnitt haus altem make-file:
// MACRO-Deklaration
LAT37 = d:\LAT37\PROG
A51OPT = ERRORPRINT NOPRINT DEBUG SYMBOLS
…
$(LAT37)\init.obj : $(LAT37)\init.a51
        a51 init.a51   $(A51OPT)
…

= >  2. Frage: Wie kann ich das selbe mit Code::Blocks und SDCC 
realisieren?  < =

Vielen Dank im Voraus
Denis

von Bernd N (Gast)


Lesenswert?

Du solltest dir einmal die SDCC Doku. durchlesen. Ich geh mal davon aus 
das die Startup.A51 von deinem Compiler erzeugt wurde... SDCC erzeugt 
ebenso einen Startupcode. Wenn du hier eigenen Code verwenden willst 
dann gilt:

uint8_t _sdcc_external_startup ()  {
// hier deinen Code einfügen.
  return 0;
}

Ansonsten gilt für deine Projekt Dateien... angenommen du hast 4 
Dateien,
1
sdcc -c --code-loc 0x0000 --model-small --opt-code-size --vc --verbose display.c
2
sdcc -c --code-loc 0x0000 --model-small --opt-code-size --vc --verbose adc.c
3
sdcc -c --code-loc 0x0000 --model-small --opt-code-size --vc --verbose eeprom.c
4
sdcc -c --code-loc 0x0000 --model-small --opt-code-size --vc --verbose RS232.c
5
sdcc -c --code-loc 0x0000 --model-small --opt-code-size --vc --verbose main.c
6
7
sdcc --code-loc 0x0000 --model-small --opt-code-size --verbose --vc main.rel adc.rel display.rel eeprom.rel RS232.rel

also wie gehabt. Compiler aufrufen, Linker aufrufen.

Ich müßte dein Projekt vor der Nase haben und dann kann man es sicher 
für den SDCC umbauen. So mal eben kann ich das auch nicht.

von Wolfgang R. (portside)


Lesenswert?

Keil und SDCC sind nicht kompatibel, da braucht man angepasste 
prozessorspezifische include Dateien also C Quellen anpassen. Die 
Assembler sind komplett verschieden, d.h. an alle Assemblerteile muss 
man Hand anlegen siehe die Memonic errors. Vorsicht die Byteorder der 
Compiler ist verschieden SDCC low und Keil high Endrian. Ebenso ist die 
Übergabe von Variable an Funktionen anders, andere und weniger Register.

Init und startup erzeugt SDCC in main selbst, da braucht man keine extra 
Dateien hinzu binden.

Wird wohl einfacher sein die Keil Dateien zu vergessen und das Project 
in SDCC selbst aufzubauen sonst schleppt man permanent Rucksäcke durch 
die Gegend.

von Bernd N (Gast)


Lesenswert?

>> Wird wohl einfacher sein die Keil Dateien zu vergessen und das Project
>> in SDCC selbst aufzubauen sonst schleppt man permanent Rucksäcke durch
>> die Gegend.

So ist es.

von Bernd N (Gast)


Lesenswert?

Zu schnell abgesendet :-)

Ich habe das Gefühl hier sollen die Assembler Dateien vom Keil mit dem 
Linker des SDCC verwurstet werden... das geht nicht!!!

von Matthias (Gast)


Lesenswert?

Bei so alten Projekten sollte man auch bei dem alten Compiler bleiben. 
Ansonsten ist viel Handarbeit erforderlich. Der Assembler a51.exe zu win 
3.11 Zeiten lief noch ohne Dongle. Die alten C51 Keil-Versionen vom 
Anfang der 90er können heute vom Ergebnis her noch locker mit SDCC 
mithalten.

von Denis (Gast)


Lesenswert?

Hallo,

vielen Dank für Ihre schnelle Antworten.


Wolfgang R. schrieb:
> Init und startup erzeugt SDCC in main selbst, da braucht man keine extra
> Dateien hinzu binden.


muss ich die INIT.A51 und die STARTUP.A51 ganz rauslassen? oder muss ich 
für SDCC eine neue Datei erstellen? falls ja, darf diese neue Datei im C 
geschrieben werden oder nur in Assembler? Wie soll es ungefähr aussehen?

Für Keil C51 Compiler gibt es Homepage mit allen Befehlen und 
Fehlermeldungen, gibt es sowass für den SDCC Compiler auch?

Gibt es einen HW Debugger für AT89C51AC3 der mit anderem Compiler außer 
Keil C51 sicher läuft und guten Support anbietet(Dokus, Forum). Können 
Sie einen außer Keil empfehlen. Vielleicht gibt es ein low cost Compiler 
bei dem man den Keil C51 code nicht anpassen muss?


Matthias schrieb:
> Bei so alten Projekten sollte man auch bei dem alten Compiler bleiben.

Ja würde ich gerne, aber den alten Compiler (C51 v4.01) kriege ich nicht 
zum Laufen. Vielleicht liegt es an dem Windows? Wo kriegt man raus ob es 
mit dem 7 oder XP kompatibel ist?

Gruß

Denis

**********************************************************************
STARTUP.A51
**********************************************************************

;Timer2 - Spezialregister

T2      BIT     090H.0
T2IE    BIT     0C8H.5
T2IP    BIT     0C8H.6
RCAP2H  DATA    0CBH
T2EX    BIT     090H.1
RCAP2L  DATA    0CAH
C_T2    BIT     0C8H.1
CP_RL2  BIT     0C8H.0
ET2     BIT     0A8H.5
TF2     BIT     0C8H.7
TH2     DATA    0CDH
TL2     DATA    0CCH
PT2     BIT     0B8H.5
TR2     BIT     0C8H.2
T2CON   DATA    0C8H
T2RSE   BIT     0C8H.4

; Modulname
                NAME    ?C_STARTUP
; Segmentdefinitionen

?C_C51STARTUP   SEGMENT   CODE
?STACK          SEGMENT   IDATA

                RSEG    ?STACK
                DS      1

                EXTRN CODE (?C_START)
                PUBLIC  ?C_STARTUP

                CSEG    AT      0
SERIE_47:
?C_STARTUP:     LJMP    STARTUP1


                RSEG    ?C_C51STARTUP
STARTUP1:

; Programmteil

; Initialisierung des Stapelzeigers

                MOV     SP,#?STACK-1

; Initialisierung der Ausgaenge

        MOV     P1,#0FFH
        MOV     P3,#0FFH


; XDATA-Speichertest

; externer Speicher mit AA fuellen


                MOV     A,#0AAH
                MOV     B,A

                MOV     R0,#00H
                MOV     R1,#08H         ; 2KByte  = #0800H

XDATA_SEITE_AA:
                ;CALL    DN_WATCHDOG
                DEC     R1
                MOV     P2,R1           ; Seitenadresse

XDATA_AA:       MOVX    @R0,A
                DJNZ    R0,XDATA_AA
                CJNE    R1,#00H,XDATA_SEITE_AA

;  AA ueberpruefen


                MOV     R0,#00H
                MOV     R1,#08H         ; 2KByte  = #0800H

XDATA_SEITE_AA_C:
                ;CALL    DN_WATCHDOG
                DEC     R1
                MOV     P2,R1           ; Seitenadresse

XDATA_AA_C:     MOVX    A,@R0
                XRL     A,B
                JNZ     XDATA_AA_FAIL
                DJNZ    R0,XDATA_AA_C
                CJNE    R1,#00H,XDATA_SEITE_AA_C
                JMP     XDATA_AA_C_E
XDATA_AA_FAIL:
                MOV     A,#11H
                JMP     CHECK_FAIL
XDATA_AA_C_E:

; externer Speicher mit 55 fuellen


                MOV     A,#055H
                MOV     B,A

                MOV     R0,#00H
                MOV     R1,#08H         ; 2KByte  = #0800H

XDATA_SEITE_55:
                ;CALL    DN_WATCHDOG
                DEC     R1
                MOV     P2,R1           ; Seitenadresse

XDATA_55:       MOVX    @R0,A
                DJNZ    R0,XDATA_55
                CJNE    R1,#00H,XDATA_SEITE_55

;  AA ueberpruefen


                MOV     R0,#00H
                MOV     R1,#08H         ; 2KByte  = #0800H

XDATA_SEITE_55_C:
                ;CALL    DN_WATCHDOG
                DEC     R1
                MOV     P2,R1           ; Seitenadresse

XDATA_55_C:     MOVX    A,@R0
                XRL     A,B
                JNZ     XDATA_55_FAIL
                DJNZ    R0,XDATA_55_C
                CJNE    R1,#00H,XDATA_SEITE_55_C
                JMP     XDATA_55_C_E
XDATA_55_FAIL:
                MOV     A,#11H
                JMP     CHECK_FAIL
XDATA_55_C_E:


; Fehlerbehandlung

        JMP     CHECK_FAIL_E
CHECK_FAIL:
        ;CALL    DN_WATCHDOG
CHECK_FAIL_SEND:
        ;CALL    DN_WATCHDOG
        JMP     CHECK_FAIL_SEND

CHECK_FAIL_E:


;  Programmstart

;  interner Speicher mit 00 fuellen, Initialisierung

                ;CALL    DN_WATCHDOG

                MOV     R0,#7FH
                CLR     A
IDATA_00:       MOV     @R0,A
                DJNZ    R0,IDATA_00


                LJMP    ?C_START        ; MAIN wird ueber INIT 
aufgerufen

                END
************************************************************************ 
*

von Matthias (Gast)


Lesenswert?

>Ja würde ich gerne, aber den alten Compiler (C51 v4.01) kriege ich nicht
>zum Laufen. Vielleicht liegt es an dem Windows? Wo kriegt man raus ob es
>mit dem 7 oder XP kompatibel ist?

Richte Dir Win98/95/Dos in einer VM (Virtual PC 2007) unter XP (Win7) 
ein. Damit klappt die Dongle-Erkennung problemlos. Direkt unter XP oder 
Win7 laufen die alten C51 Versionen nicht, da der Zugriff auf die 
parallele Schnittstelle nicht durchkommt.

Eine komplette Dokumentation ist bei SDCC übrigens mit dabei, siehe im 
Installations-Ordner. Die C-Befehle bedürfen keiner Beschreibung, da 
ANSI-kompatibel. Alles spezifische ist dort aber dokumentiert.

von Wolfgang R. (portside)


Lesenswert?

> Richte Dir Win98/95/Dos in einer VM (Virtual PC 2007) unter XP (Win7)
> ein. Damit klappt die Dongle-Erkennung problemlos. Direkt unter XP oder
> Win7 laufen die alten C51 Versionen nicht, da der Zugriff auf die
> parallele Schnittstelle nicht durchkommt.
>
Das ist wahrscheinlich der einzige Weg zum Erfolg, da wie mir scheint 
grundsätzliches Wissen wie das ein Compiler und Linker so macht fehlt.
Wie gesagt init und startup finden sich später in main.asm automatisch 
wieder bei SDCC.

> Eine komplette Dokumentation ist bei SDCC übrigens mit dabei, siehe im
> Installations-Ordner. Die C-Befehle bedürfen keiner Beschreibung, da
> ANSI-kompatibel. Alles spezifische ist dort aber dokumentiert.

Na ja der Assembler ist sehr schwach dokumentiert.

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.