SDCC Z80 Compiler: Frage zu Warnung. MBC2-Board

Gast #7671615
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.

Angehängte Dateien:
Gast #7671644
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.

Gast #7671647
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.

Gast #7671664
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.

Gast #7671685
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

Angehängte Dateien:
Gast #7671793
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

Gast #7671800
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:
Gast #7671812
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.

Gast #7671815
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.

Gast #7671865
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?

Gast #7671882
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.

Angehängte Dateien:
#7686337
Lesenswert?

Thorsten M. schrieb:

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.

Das übliche vorgehen ist, die crt0.rel von SDCC zu lassen, wie sie ist, die eigene "crt0.rel" (muss nicht notwendigerweise so heißen) beim Linkeraufruf als erste .rel anzugeben, und --no-std-crt0 zu verwenden, also z.B.:

sdcc --no-std-crt0 crt0.rel dhry_1.rel dhry_2.rel portme.rel -o image.ihx

P.S.: Als Beispielprogramm für SDCC fürs MBC2-Board sollte sich z.B. der Dhrystone hier eignen: https://sourceforge.net/p/sdcc/code/HEAD/tree/trunk/sdcc-extra/historygraphs/dhrystone-z80/

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