Forum: Mikrocontroller und Digitale Elektronik SDCC Z80 Compiler: Frage zu Warnung. MBC2-Board


von Thorsten M. (cortex_user)


Angehängte Dateien:

Lesenswert?

Hallo,

Ich glaube es gibt hier einen Spezialisten, der mit an dem Projekt 
arbeitet. Ich pappe das Verzeichnis mal an als zip. Es geht um das 
beispiel ANSIest.c wo ich eine Warnung erhalte. Die crt.s Dazei sieht 
soweit gut aus, sie bildet ja den Startup Code, habe vor 10 Jahren mal 
selbst eine geschrieben aber ist nicht mehr so präsent.

Kompiliert wird mit sdc <filename>, da sollte crt.s mit eingebunden 
werden.
Die beiden crt.s habe ich mit

sdasz80 -plosgff -o S190818-R011023_crt0.s und
sdasz80 -o S190818_crt0.s

kompiliert, in crt0.rel umbenannt und damit die im SDCC Verzeichnis 
überschrieben.

Glaube Philipp heisst der Programmierer aber auch ein gewisser Leo kennt 
sih damit aus? Kannst Du mal drüber schauen? Die Warnungen scheinen 
merkwürdig zu sein, denn der Code ist nach der ersten Durchsicht ok.

gruss,
Throsten


E:\Embedded\Z80_MBC2\Backup_SD\SDCC>sdc ANSItest.c
ANSItest.c:3: warning 283: function declarator with no prototype
No compiler errors.
Error: utility srec_cat.exe not found!
Nothing to load to the target.

E:\Embedded\Z80_MBC2\Backup_SD\SDCC>sdc Blink_MBC2.c
Blink_MBC2.c:127: warning 283: function declarator with no prototype
Blink_MBC2.c:134: warning 283: function declarator with no prototype
No compiler errors.
Error: utility srec_cat.exe not found!
Nothing to load to the target.

: Bearbeitet durch User
von Thomas Z. (usbman)


Lesenswert?

probier mal
void main(void)

und beim 2. Beispiel
char userKey(void);

dann verschwinden die Warnungen. Leere Klammern sind ohne Prototypen 
nicht (mehr) erlaubt.
srec_cat.exe liegt nicht in deinem Pfad

von Harald K. (kirnbichler)


Lesenswert?

Thomas Z. schrieb:
> Leere Klammern sind ohne Prototypen
> nicht (mehr) erlaubt.

... und zwar schon seit C89 nicht mehr.

von Thorsten M. (cortex_user)


Lesenswert?

Thomas Z. schrieb:
> probier mal
> void main(void)
>
> und beim 2. Beispiel
> char userKey(void);

Da steht nichts anderes drin.

srec_cat.exe ist das Hex2Bin Tool von keil. Ist jetzt drin

E:\Embedded\Z80_MBC2\SDCC>sdc ANSItest.c
ANSItest.c:3: warning 283: function declarator with no prototype
No compiler errors.
All done! Output executable file (Intel-Hex): out.hex

Ok, Warnungen sind weg. Komisch.. früher ging auch while(1); jetzt musst 
es while(1){}; heissen.

: Bearbeitet durch User
von Thomas Z. (usbman)


Lesenswert?

Thorsten M. schrieb:
> Da steht nichts anderes drin.

dann ist das halt so. Ich frag mich dann aber schon warum du Hilfe 
suchst

von Thorsten M. (cortex_user)


Lesenswert?

Hier hinter scheinen sich die I/O Ports des MBC2 System zu verbergen. 
Leider bin ich etwas aus der Materie raus. Der MBC2 benutzt den Atmega 
als Interface für eine UART, ebenso für einen MC27... als I2C GPIO Port. 
Leider gibt es keine Doku wie man diese Peripherie ansteuert.

// Z80-MBC2 IOS I/O ports definitions
__sfr __at 0x00 Exec_port;          // IOS Execute Opcode read/write 
port
__sfr __at 0x01 StorOpc_port;       // IOS Store Opcode write only port
__sfr __at 0x01 SerRx_port;         // IOS Serial Rx read only port

Damals habe ich das so gemacht

// PIO 8255 Special I/O
__sfr __at 0x20 PIO8255_PORT_A;
__sfr __at 0x21 PIO8255_PORT_B;
__sfr __at 0x22 PIO8255_PORT_C;
__sfr __at 0x23 PIO8255_CNTRL;

Dahinter steckten 4 Register des 8255 am I/O Bus des Z80, die mit 
speziellen Werten gefüttert werden mussten, d.h. Command Register und 
Datenregister. Für den MBC2 gibt es leider gar nichts was dahinter 
steckt. Glaube maximal 256 I/O  Adressen sind da möglich. Die 
Adressierung lief über die unteren Adressleistungen A0-A7.

: Bearbeitet durch User
von Thorsten M. (cortex_user)


Lesenswert?

Thomas Z. schrieb:
> dann ist das halt so. Ich frag mich dann aber schon warum du Hilfe
> suchst

Du hast mir schon geholfen, da fehlte wirklich ein void. Danke!

von Thomas W. (dbstw)


Lesenswert?

Thorsten M. schrieb:
> Hier hinter scheinen sich die I/O Ports des MBC2 System zu verbergen.
> Leider bin ich etwas aus der Materie raus. Der MBC2 benutzt den Atmega
> als Interface für eine UART, ebenso für einen MC27... als I2C GPIO Port.
> Leider gibt es keine Doku wie man diese Peripherie ansteuert.

Du hast dieses "Bios". Wenn Du das aktuelle (auch letzte) "Bios" benutzt 
(S220718-R290823_IOS-Z80-MBC2.ino), findest Du ab line 892 die 
Definition der IO-Operationen, die vom ATMEGA ausgefuehrt werden. Ab 
line 974 findest Du den Zugriff auf den MCP27016:
1
 Wire.beginTransmission(GPIOEXP_ADDR);
2
 Wire.write(GPIOA_REG);              // Select GPIOA
3
 Wire.write(ioData);                 // Write value
4
 Wire.endTransmission();
Der Hinweis auf das Datenblatt des MCP27016 darf natuerlich nicht 
fehlen. Ich kann mich (als Schueler) der Kampf mit dem Datenblatt des 
6532 oder 6522 (heute sind das triviale Bausteine) gut erinnern.

Gruesse

Th.

von Thorsten M. (cortex_user)


Angehängte Dateien:

Lesenswert?

Danke für den Hinweis!

Ich denke diese Tabelle gibt da mehr Aufschluss drüber. Zumindest genug 
um erstmal eine LED blinken zu lassen. Die scheinen das alles über diese 
2 Ports laufen zu lassen und je nachdem welcher Wert reingeschrieben 
wird bedient der Atmel die passenden Routinen in seiner Firmware. Der 
hänggt ja auch nur an A0 vom Bus dran, mehr geht ja nicht. Ich frage 
mich wie der das RAM mit den Images bespielt, denn am Adressbus hängt er 
nicht dran, nur am Datenbus.

__sfr __at 0x00 EXEC_OPCODE;                        // IOS Execute 
Opcode read/write port
__sfr __at 0x01 STORE_OPCODE;                       // IOS Store Opcode 
write only port
__sfr __at 0x01 SER_RX;                             // IOS Serial Rx 
read only port

Danach will ich mcurses als Interface zum VT100 aufsetzen und mit dem 
SDCC eigene Programme schreiben.

// Currently defined Opcodes for I/O write operations:
      //
      //   Opcode     Name            Exchanged bytes
      // -------------------------------------------------
      // Opcode 0x00  USER LED        1
      // Opcode 0x01  SERIAL TX       1
      // Opcode 0x03  GPIOA Write     1
      // Opcode 0x04  GPIOB Write     1
      // Opcode 0x05  IODIRA Write    1
      // Opcode 0x06  IODIRB Write    1
      // Opcode 0x07  GPPUA Write     1
      // Opcode 0x08  GPPUB Write     1
      // Opcode 0x09  SELDISK         1
      // Opcode 0x0A  SELTRACK        2
      // Opcode 0x0B  SELSECT         1
      // Opcode 0x0C  WRITESECT       512
      // Opcode 0x0D  SETBANK         1
      // Opcode 0x0E  SETIRQ          1
      // Opcode 0x0F  SETTICK         1
      // Opcode 0x10  SETOPT          1
      // Opcode 0x11  SETSPP          1
      // Opcode 0x12  WRSPP           1
      // Opcode 0xFF  No operation    1

: Bearbeitet durch User
von Thomas W. (dbstw)


Lesenswert?

Thorsten M. schrieb:
> Danke für den Hinweis!
>
> Ich denke diese Tabelle gibt da mehr Aufschluss drüber. Zumindest genug
> um erstmal eine LED blinken zu lassen. Die scheinen das alles über diese
> 2 Ports laufen zu lassen und je nachdem welcher Wert reingeschrieben
> wird bedient der Atmel die passenden Routinen in seiner Firmware.

Im Endeffekt: Ja. Und wenn Du ein wenig bei CP/M 2.2 guckst, wirst Du 
sehen dass viele CP/M-BIOS-Funktionen direkt implementiert sind.

> Der
> hänggt ja auch nur an A0 vom Bus dran, mehr geht ja nicht. Ich frage
> mich wie der das RAM mit den Images bespielt, denn am Adressbus hängt er
> nicht dran, nur am Datenbus.

Das ist sehr pfiffig geloest: Da der ATMega die Clock und Reset 
kontrolliert, kann man die Z80 in einzelnen Clocks betreiben (klappt 
eigentlich nur bei der  CMOS-CPU). Nach dem Reset werden die passenden 
OPCodes auf den Bus geschrieben, die CPU fuehrt das aus und kann in das 
reale RAM einschreiben. Wenn Du den Boot-Loader dann in den RAM 
geschrieben hast, kannst Du neu starten und das Betriebssystem Deiner 
Wahl starten.

Das findet alles bei den Routinen loadByteToRAM(byte value) und 
loadHL(word value) statt (line 2506ff in S220718-R290823_IOS.MBC2.ino):
1
void loadByteToRAM(byte value)
2
// Load a given byte to RAM using a sequence of two Z80 instructions forced on the data bus.
3
// The RAM_CE2 signal is used to force the RAM in HiZ, so the Atmega can write the needed instruction/data
4
// on the data bus. Controlling the clock signal and knowing exactly how many clocks pulse are required it is possible control the
5
// whole loading process.
6
// In the following "T" are the T-cycles of the Z80 (See the Z80 datashet).
7
// The two instruction are "LD (HL), n" and "INC (HL)".

Zu Deinem Wunsch die blaue/weisse/pinke LED blinken zu lassen: Gucke 
bitte in "Examples with Basic.txt" auf der SD-Card: Du willst ein reines 
(ohne Betriebssystem) Z80-Programm ausfuehren. Es muesste dann reichen 
(Pseudo-Code):
1
  OUT 0x1, 0x0   ; Write USER LED
2
  OUT 0x0, 0x1   ; LED an
3
  [delay]
4
  OUT 0x1, 0x0   ;
5
  OUT 0x0, 0x0   ; LED aus

Gruesse

von Thorsten M. (cortex_user)


Lesenswert?

>>Im Endeffekt: Ja. Und wenn Du ein wenig bei CP/M 2.2 guckst, wirst Du
>>sehen dass viele CP/M-BIOS-Funktionen direkt implementiert sind.

Ich hatte damals sowas gemacht. Ginge das auch für die BIOS Routinen, 
dass man die aus C zugänglich macht mit den entsprechenden Parametern 
wenn man ihre Adresse kennt? Ich brauche ja eine API zum BIOS.

PS: Bin ich froh, dass diese EPROM Brennerei ein Ende hat! Habe noch 
rund 100 hier.

// Absolute Adressen des gesamten RAMs (ohne Stack) und ROMs
// Diese Array sind Overlays und benötigen keinen Speicherplatz

__at (ROM_START) unsigned char memory[0xffff];         // Kompletter 
Speicher
__at (RAM_SPECIAL) unsigned char ram_info[64];           // 
Löschsicherer Speicher

ROM_START und RAM_SPECIAL waren im crt.s definierte Areas, die ich vom C 
Program aus verwenden konnte.
1
  .module crt0            ; Modul Name für den Linker
2
3
    ; Memory Map Adressen der Zeropage (vom Benutzer definierbar)
4
    ; Definitions
5
6
    offset           .equ   0x4000        ; Basisadresse des Codes
7
    reset_vector     .equ   offset
8
    stack            .equ   0xffbf        ; Stack
9
    adr_vec_table    .equ   offset+0x40   ; Mode 2 Vektor Tabelle für STI Mostek Multi I/O
10
    adr_copyright    .equ   offset+0x80
11
    heap_size        .equ   2048         ; Benutzer definierte Heap Groesse
12
13
    ; Globale Funktionen und Variablen für das C-Programm
14
15
    .globl  _main
16
17
    ; Interruptroutinen für den Mostek MK3801 Multi I/O Baustein
18
    ; Manual STI Baustein MK3801 Figure 7
19
    .globl  _int_sti_gpi_0  ; General Purpose Interrupt 0
20
    .globl  _int_sti_gpi_1  ; General Purpose Interrupt 1
21
    .globl  _int_sti_gpi_2  ; General Purpose Interrupt 2
22
    .globl  _int_sti_gpi_3  ; General Purpose Interrupt 3
23
    .globl  _int_sti_timer_d
24
    .globl  _int_sti_timer_c
25
    .globl  _int_sti_gpi_4  ; General Purpose Interrupt 4
26
    .globl  _int_sti_gpi_5  ; General Purpose Interrupt 5
27
    .globl  _int_sti_timer_b
28
    .globl  _int_sti_transmit_buffer_empty
29
    .globl  _int_sti_transmit_error
30
    .globl  _int_sti_receive_error
31
    .globl  _int_sti_receive_buffer_full
32
    .globl  _int_sti_timer_a
33
    .globl  _int_sti_gpi_6  ; General Purpose Interrupt 6
34
    .globl  _int_sti_gpi_7  ; General Purpose Interrupt 7
35
36
    .globl l__INITIALIZER
37
    .globl s__INITIALIZER
38
    .globl s__INITIALIZED
39
40
    .globl ___sdcc_heap_init
41
    .globl _letzte_code_adresse
42
    .globl _erste_code_adresse
43
44
    ; -------------------------------------------------------------
45
46
    .area   _HEADER (ABS)
47
    ; Reset vector bei Kaltstart und Sprung ins User Programm
48
    .org    reset_vector
49
    _erste_code_adresse:
50
     jp init
51
52
    ; Warmstart mit NMI Interrupt (ohne Speicher loeschen)
53
     .org    reset_vector+3
54
     jp  init2
55
56
    ;///////////////////////////////////////////////////////////
57
    ; Tabelle der Mode 2 Int Vektoren auf die Handler Funktionen im C Modul
58
    ; Reihenfolge beachten !!! Siehe Manual Mostek 3801, Interrupt Tabelle
59
    .org adr_vec_table
60
    .dw (_int_sti_gpi_0)
61
    .dw (_int_sti_gpi_1)
62
    .dw (_int_sti_gpi_2)
63
    .dw (_int_sti_gpi_3)
64
    .dw (_int_sti_timer_d)
65
    .dw (_int_sti_timer_c)
66
    .dw (_int_sti_gpi_4)
67
    .dw (_int_sti_gpi_5)
68
    .dw (_int_sti_timer_b)
69
    .dw (_int_sti_transmit_error)
70
    .dw (_int_sti_transmit_buffer_empty)
71
    .dw (_int_sti_receive_error)
72
    .dw (_int_sti_receive_buffer_full)
73
    .dw (_int_sti_timer_a)
74
    .dw (_int_sti_gpi_6)
75
    .dw (_int_sti_gpi_7)
76
77
    .org adr_copyright
78
    .asciz "Z80/MK3801 System"
79
80
    ;///////////////////////////////////////////////////////////
81
    ; Anordung der Segmente fuer den Linker, ab hier nur relative
82
    ; Adressen
83
84
      .area  _CODE
85
      .area  _INITIALIZER
86
      .area  _HOME
87
      .area  _GSINIT
88
      .area  _GSFINAL
89
      .area  _DATA
90
      .area  _INITIALIZED
91
      .area  _BSEG
92
      .area  _BSS
93
      .area  _HEAP
94
95
; ---  Defintion der Heap Groesse
96
__sdcc_heap_start::
97
      .ds heap_size
98
99
      .area _HEAP_END
100
__sdcc_heap_end::
101
      .ds 1
102
103
    ;///////////////////////////////////////////////////////////
104
    ;; ------- Start des Hauptprogramms nach der Zeropage  -----------
105
106
    .area _CODE
107
    init:
108
    init2:
109
    ld  sp,#stack   ;; Stack an Spitze des RAM legen
110
    call gsinit     ;; Static Variablen init
111
    call  _main     ;; Hauptprogramm aufrufen
112
endlos:
113
    halt
114
    jr endlos
115
116
   .area  _GSINIT
117
118
 gsinit:
119
120
    ; Initialisiere den HEAP
121
    call ___sdcc_heap_init
122
123
    ; Initialisiere globale Variablen im RAM
124
    ld  bc, #l__INITIALIZER
125
    ld  a, b
126
    or  a, c
127
    jr  Z, weiter
128
    ld  de, #s__INITIALIZED
129
    ld  hl, #s__INITIALIZER
130
    ldir
131
132
weiter:
133
134
    ; // Hier muss ein ret rein
135
    .area _GSFINAL
136
      ret
137
     ;Markiert das Ende des Programmes
138
    .asciz "Z80 END OF PROGRAM"
139
     _letzte_code_adresse:

: Bearbeitet durch User
von Thomas W. (dbstw)


Lesenswert?

Ich verstehe nicht Dein Goal nicht: Willst Du ein CP/M-Programm 
schreiben (dann hast Du natuerlich alle Moeglichkeiten, dazu musst Du 
aber das BIOS haben), dann kannst Du die BIOS-Calls wie folgt benutzen 
(aus: http://www.gaby.de/cpm/manuals/archive/cpm22htm/ch5.htm)
1
As mentioned above, access to the FDOS functions is accomplished by passing a function number and information address through the primary point at location BOOT+0005H. In general, the function number is passed in register C with the information address in the double byte pair DE. Single byte values are returned in register A, with double byte values returned in HL, a zero value is returned when the function number is out of range. For reasons of compatibility, register A = L and register B = H upon return in all cases.

Aber gerade die Unabhaengigkeit von den festen Adressen war ja genau der 
grosse Fortschritt bei CP/M (und die Modularitaet der Teile des 
Betriebssystemes).

Alternativ wirklich ohne alles: Kleines Z80-Assembler, Start bei 0x0000 
(Reset0) und gut ist. Beides ist Moeglich.

Gruesse

Th.

von Thorsten M. (cortex_user)


Lesenswert?

Thomas W. schrieb:
> Ich verstehe nicht Dein Goal nicht: Willst Du ein CP/M-Programm
> schreiben (dann hast Du natuerlich alle Moeglichkeiten, dazu musst Du
> aber das BIOS haben), dann kannst Du die BIOS-Calls wie folgt benutzen

The principal entry point to the FDOS is at location BOOT+0005H 
(normally 0005H) where a jump to BASE is found. As mentioned above, 
access to the FDOS functions is accomplished by passing a function 
number and information address through the primary point at location 
BOOT+0005H

Danke, das reicht schon. Ich habe in den 90iger Asm Programme für den 
X86 geschrieben da musste man den INT21h beedienen für DOS und einen 
anderen fürs BIOS. Stand alles im PC Intern.

Ich brauche nur das VT100 Interface, den ganzen Low Level Disk Kram tue 
ich mir nicht an. Und ich muss mir ein C Konstrukt basteln, was die 
Funktionen anspringt, da ich auf Assembler verzichten will. Also eine C 
Funktion, die vielleicht etwas Inline Assembler hat die das managed.

char MyFunc(int parameter) {

   __asm Lade HIbyte(parameter)
   __asm Lade LObyte(parameter)
    CALL BDOS
    return (Rückgabewerte)

}

Habe zwar eine C Lib mcurses, die VT100 bedienen kann aber die müsste 
mein Programm dann mitschleppen, dabei gibt es das ja alles schon im 
BDOS.

Alternativ geht natürlich auch mbasic von Grant Serle, das sich auch 
kompilieren lässt zu einem COM File.ö Zusammen mit dem autostart 
Mechanismus kann man so ein Programm starten und zb die GPIO Leiste 
bedienen, das ist alls schon drin mit dem OUT und IN Befehlen. 
Allerdings ist die Editor Funktion nicht komfortabel, das würde ich 
alles schon gern am PC machen und dann hochladen als Text oder als 
Kompilat. Copy & Paste klappen aber im Terminalfenster, d.h. mans spart 
sich das mühsame Eintippen.

: Bearbeitet durch User
von Thomas W. (dbstw)


Lesenswert?

Thorsten M. schrieb:
>
> Habe zwar eine C Lib mcurses, die VT100 bedienen kann aber die müsste
> mein Programm dann mitschleppen, dabei gibt es das ja alles schon im
> BDOS.

Noe. BDOS steht fuer Basic DISK Operating System, ja, es hat auch 
Character I/O, RAW I/O und buffered Read and Write (praktisch ein 
PrintString), aber curses bietet deutlich mehr. Insbesondere 
Cursor-Control ist Deine Aufgabe.

Es sind ja jetzt vierzig Jahre her, es kann sein, dass sich Deine 
Erinnerungen etwas vermischen? Kannst Du Dich noch an die ellenlangen 
Listen von Terminal-Codes wg. Cursor-Up, -Down oder Erase Line erinnern?

Oder das Elend mit den Floppy-Disk-Formaten? Jeder hatte seine eigene 
Wurst?

von Thorsten M. (cortex_user)


Angehängte Dateien:

Lesenswert?

Thomas W. schrieb:
> Es sind ja jetzt vierzig Jahre her, es kann sein, dass sich Deine
> Erinnerungen etwas vermischen? Kannst Du Dich noch an die ellenlangen
> Listen von Terminal-Codes wg. Cursor-Up, -Down oder Erase Line erinnern?

In der mcurses von Frank (UKW) ist man davon entbunden, die Routinen 
bauen die ESC Sequenzen einfach ein. Es geht ja nur um Textfelder, 
Cursor zurück, poitionierend usw.

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Thorsten M. schrieb:
> In der mcurses von Frank (UKW) ist man davon entbunden, die Routinen
> bauen die ESC Sequenzen einfach ein.

Hier noch ergänzend die Doku dazu: MCURSES

: Bearbeitet durch Moderator
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.