n° 219
Novembre 2017
Dicembre 13, 2017, 01:50:01 *
Benvenuto! Accedi o registrati.
Hai dimenticato l'e-mail di attivazione?

Accesso con nome utente, password e durata della sessione
Notizia:
 
   Indice   Linux Windows Techassistance Gameassistance videogame hardware Aiuto Ricerca Agenda Downloads Accedi Registrati  


* Messaggi recenti
Messaggi recenti
Pagine: [1] 2 3 4   Vai giù
  Stampa  
Autore Discussione: Z80: Problema puntatori ?  (Letto 20592 volte)
0 utenti e 1 Utente non registrato stanno visualizzando questa discussione.
GizMo
Newbie
*

Karma: +0/-0
Scollegato Scollegato

Messaggi: 40


Mostra profilo E-mail
« inserita:: Settembre 04, 2015, 05:50:38 »

Salve a tutti mi sono appena iscritto al forum e vi porgo i miei saluti, vengo al mio problema:

Ho come hobby l'elettronica e ho realizzato una motherboard con lo Z80 presentata in questo sito:
http://www.allthingsmicro.com/index.php/projects/20-z80-based-computer

Su questa scheda ho imparato da autodidatta a programmare in C, ho costruito una piccola interfaccia di espansione sopra la quale ho montato una compactflash e mi sono messo pian piano a scrivere prima le routines per accedere alla CF a basso livello, poi ho scritto le routines per creare e accedere a un filesystem che ho inventato di testa mia, poi ho scritto qualche piccolo programma, CD ... CAT ... LS ... Rename e un programmino che mi permette di fare l'upload di un file dal PC al filesystem dello Z80 attraverso la porta seriale, tutto funziona finche' lo eseguo dalla ram..

Siccome ero a buon punto con la struttura delle mie funzioni per usare il filesystem ho comprato su ebay un programmatore di eeprom tutto mio per poter riscrivere il mio bios, ho preso i sorgenti del monitor originale della scheda, quello fatto da "allthingsmicro" e ho pensato che visto era gia' in mini interprete dei comandi mi bastava includere i miei file .h per aggiungere tutte le varie funzioni, ricompilare e flasshare la eeprom.

Ho incluso il file con le funzioni base di i/o e ho provato a far fare al bios il semplice init dell'hardware, il compilatore (Z88DK) compila correttamente il sorgente, ma la scheda di blocca non appena tenta di avviare la ma funzione.

Ho guardanto un po' il codice binario generato e' penso di aver intuito il problema ma non so come risolverlo, il problema, per fare un'esempio e' questo:

int loop_busy()
do  {
      stato = inp(cfreg7);
    } while (stato > 128);

Dove "stato" e' un "unsigned char" dichiarato all'inizio del sorgente, il compilatore compila il codice ma non tiene presente che l'area di memoria sotto i primi 32k e' ROM, quidi "stato" punta ad un'area della ROM e si blocca tutto perche' non puo' scriverci.

Credo di aver capito che devo spostare le variabili delle mie funzioni in un'indirizzo che cade nella RAM, ho letto qualcosa ma non ottengo i risultati che mi aspetto, ad esempio se faccio:

unsigned char stato = &0x8000; /* 0x8000 e' il primo indirizzo della ram*/

il compilatore mi dice invalid address.

Qualcuno mi sa aiutare ?
Registrato
M.A.W. 1968
** LEGGETE IL REGOLAMENTO ! **
Global Moderator
Hero Member
*****

Karma: +224/-19
Scollegato Scollegato

Messaggi: 2988


Discrete And Combinatorial Mathematics


Mostra profilo WWW
« Risposta #1 inserita:: Settembre 05, 2015, 12:59:11 »

Il cross compiler Z88DK è una specializzazione del vecchio e limitato Small-C. Il numero complessivo di utenti è tale che, riunendoli tutti sugli spalti di una sala da biliardo, resterebbero ancora vuoti 5/7 delle sedie.  Occhi al cielo

Come la schiacciante maggioranza dei cross compiler, la configurazione delle memorie è affidata a semplici direttive (es. CRT_ORG_CODE, CRT_ORG_DATA) che nelle varie versioni hanno cambiato più volte collocazione, ma che in generale si trovano nei file *_crt0 che caratterizzano i singoli target.
Tali comportamenti sono comunque documentati, almeno in parte, sul relativo sito.


PS: il progettino didattico è una simpatica operazione nostalgia. Personalmente avrei incluso un novero più vasto di componenti di base, e affidato l'espandibilità ad un bus S-100. Quasi sette lustri fa ho iniziato a programmare in Assembly proprio su un sistema del genere, ma collocato su una doppia Eurocard industriale e con varie schede di I/O figlie entro un cestello rack, rottamato dal quadro di controllo di una punzonatrice per upgrade. Ghigno
Registrato

I Moderatori invitano tutti gli utenti a prendere visione del REGOLAMENTO e a rispettarlo.

Un blog? Io? Occhiolino
GizMo
Newbie
*

Karma: +0/-0
Scollegato Scollegato

Messaggi: 40


Mostra profilo E-mail
« Risposta #2 inserita:: Settembre 05, 2015, 12:05:48 »

ciao maw conta che io prima di costruire questa scheda non sapevo proprio niente di C, l'ho costruita perche' mi sembrava piu' divertente di un arduino e al momento mi sono abbastanza appassionato, a firmware scritto vorrei rifare con eagle un nuovo PCB con a bordo la CF e forse alcuni pio e un display tft, comunque i tempi non sono maturi ancora per fare nuovo hardware. Da ieri che ho postato il primo messaggio ho fatto alcune prove senza ancora riuscire a risolvere la cosa, ti posto i sorgenti per vedere se riesci a darmi una mano:

Questo e' il monitor di base, quello che da solo in rom funziona, quello non fatto da me e che vorrei modificare:

Codice:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mk2/mk2.h>
#include <mk2/vt100.h>
#include <mk2/crc16.h>
#include <mk2/xmodem.h>

#define CLS 1
#define LOAD 2
#define HELP 3
#define RUN 4
#define prompt "\n\rZ80>"
#define hwname "Z80 Motherboard MK3 RomOS v1.0\n\r"

#define RAM_LENGTH 29184 /*29184 Bytes (28K) of avaliable RAM for user applications*/

void SetupHomeScreen(void);
char *mk2strtok(unsigned char *s1,unsigned char *s2);
int CommandIndex(char *Cmd);

extern unsigned char *strtokt;
extern char *RAM_Start @ 32768;

main()
{
char CmdBuffer[50];
unsigned char RX;
char *Cmd = NULL;
char *Arg = NULL;
int LoadedApp=0;

int Ptr = 0;
int st;

InitSerialConsole(); /*Must do this to use serial portA as console*/
SetupHomeScreen(); /*Clear the screen,set the colours etc*/

while(1) { /*loop forever*/
Ptr = 0;
Cmd = NULL;
do {
RX = getchar(); /*wait for a character from keyboard*/
switch (RX) {
case 8: /*do we have a backspace*/
case 127: /*do we have a delete*/
if(Ptr != 0) { /*if its not the first char*/
Ptr--; /*move the command pointer back one*/
CursorLeft(((int*)1)); /*move the cursor back on the VT100*/
putchar(32); /*wipe out the character with a space*/
CursorLeft(((int*)1)); /*finally move the cursor back again*/
}
break;
case 10: /*do we have a cr*/
case 13: /*do we have a lf*/
if(Ptr==0) {
printf(prompt);
} else {
CmdBuffer[Ptr++] = '\0'; /*command entered so terminate the command string*/
}
break;
default: /*everything else*/
if(Ptr == 49) { /*is our command string getting to big for buffer 254?*/
putchar(7); /*yes send a bell*/
Ptr--; /*move the command pointer back one*/
CursorLeft(((int*)1)); /*move the cursor back on the VT100*/
putchar(32);  /*wipe out the character with a space*/
CursorLeft(((int*)1)); /*finally move the cursor back again*/
}
CmdBuffer[Ptr++] = RX; /*add the char to the command buffer and add one to the command pointer*/
putchar(RX); /*echo it back*/
}

} while ((RX != 10 && RX != 13) || Ptr==0); /*if we have a cr or lf exit*/

Cmd = mk2strtok(CmdBuffer," "); /*our syntax is command[ ]args[ ]args[ ]command[ ]args[ ]...pull each out using space as token*/
while(Cmd != NULL) {
switch(CommandIndex(Cmd)) { /*get a command number so we can switch case*/
case CLS:
SetupHomeScreen();
break;

case LOAD:
printf ("\n\rSend data using the xmodem protocol...\n\r");
st = XModemReceive(&RAM_Start, RAM_LENGTH);
switch(st) {
case -1:
printf("\n\rXmodem Error - Cancelled By Remote",prompt);
break;
case -2:
printf("\n\rXmodem Error - Sync Error",prompt);
break;
case -3:
printf("\n\rXmodem Error - Max Retry",prompt);
break;
default:
LoadedApp=1;
printf("\n\rXmodem successfully received %d bytes", st);
printf("\n\rPress anykey to run your application\n\r");
getchar();
#asm
call $8000
#endasm
Locate(((int*)0),((int*)24));
printf("Press anykey to return to bios");
getchar();
SetupHomeScreen();
break;
}
break;

case HELP:
printf("\n\rRecognised commands...\n\r\n\rcls\n\rload\n\rhelp\n\rrun\n\r");
printf(prompt);
break;

case RUN:
if(LoadedApp==1) {
#asm
call $8000
#endasm
Locate(((int*)0),((int*)24));
printf("Press anykey to return to bios");
getchar();
SetupHomeScreen();
}
else {
printf("\n\rNo Application Loaded",prompt);
}
break;

default:
printf("\n\r'%s' is not recognized as an command or program name",prompt,Cmd);
break;
}
Cmd = mk2strtok(NULL," ");
}
}
}

/*
 * CommandIndex
 * Returns a interger value for a command string
 *
 */

int CommandIndex(char *Cmd)

{
if(strcmp(Cmd,"cls")==0) return CLS;
if(strcmp(Cmd,"load")==0) return LOAD;
if(strcmp(Cmd,"help")==0) return HELP;
if(strcmp(Cmd,"run")==0) return RUN;
return -1;
}

/*
 * strtok for mk2
 * Uses Ram as temp storage not program space
 *
 */

char *mk2strtok(unsigned char *s1,unsigned char *s2)

{
  if(s1!=NULL)
    strtokt=s1;
  else
    s1=strtokt;
  s1+=strspn(s1,s2);
  if(*s1=='\0')
    return NULL;
  strtokt=s1;
  strtokt+=strcspn(s1,s2);
  if(*strtokt!='\0')
    *strtokt++='\0';
  return s1;
}

/*
 * Setup the home screen
 *
 */

void SetupHomeScreen(void)

{
Cls();
SetVTAttrib(VTBGBlack);
SetVTAttrib(VTFGGreen);
printf(hwname);
SetScroll(((int*)2),((int*)24));
SetSmoothScroll();
SetVTAttrib(VTFGWhite);
Locate(((int*)0),((int*)24));
printf(prompt);
}

Questa e' la mia libreria per l'I/O base

Codice:
/* Funzioni basilari di I/O sulla CF  */

/* Definizione dei registri della CF */
#define cfreg0 0x08 /* dati letti o da scrivere sulla cf */
#define cfreg1 0x09 /* leggi errore setta features */
#define cfreg2 0x0a /* quanti settori vuoi leggere in una volta */
#define cfreg3 0x0b /* indirizzo settore 0-7 bit */
#define cfreg4 0x0c /* indirizzo settore 8-15 bit */
#define cfreg5 0x0d /* indirizzo settore 16-23 bit */
#define cfreg6 0x0e /* indirizzo settore 24-27 bit */
#define cfreg7 0x0f /* leggi stato scrivi comando */

/* altri registri */
unsigned char stato;
unsigned char io_dialog;
unsigned char io_uscita;
unsigned char output[2];
unsigned char ram_buff[512];

unsigned char cf_size_alto;
unsigned char cf_size_medio;
unsigned char cf_size_basso;
unsigned long cf_size;
unsigned long cf_size2;
unsigned int cf_io_contatore = 0;
unsigned char cf_io_8b_contatore = 0;
unsigned char hw_presence = 0;

unsigned long address32;
unsigned char addr0;
unsigned char addr1;
unsigned char addr2;
unsigned char addr3;

/* inizializza la CF a 8 BIT */
int cf_init()
{
loop_busy();
outp(cfreg1, 0x01); /* features 8 bit */
loop_busy();
outp(cfreg7, 0xef); /* set features */
loop_busy();
hw_check();
if (hw_presence == 1) {
printf("\n\rCF inizializzata\n\r");
capacity_info();
  }
hw_error_status();
}

/* loop busy */
int loop_busy()
do  {
stato = inp(cfreg7);
    } while (stato > 128);

/* loop cmd ready*/
int loop_cmd_ready()
do {
stato = inp(cfreg7);
   } while (stato > 128);

/* loop data ready*/
int loop_ready()
do {
stato = inp(cfreg7);
   } while (stato == 1);

/* carica un settore di 512byte nel buffer */   
int load_seek(unsigned long lba_addr)
{
hw_error_status();
LBA(lba_addr);
cf_read_cmd();
for(cf_io_contatore = 0; cf_io_contatore < 512; cf_io_contatore++) /* carica il settore in ram */
{
ram_buff[cf_io_contatore] = inp(cfreg0);
}

}

/* scrive il buffer da 512byte in un settore */
int write_seek(unsigned long lba_addr)
{
hw_error_status();
LBA(lba_addr);
cf_write_cmd();
for(cf_io_contatore = 0; cf_io_contatore < 512; cf_io_contatore++)
        {
        outp(cfreg0, ram_buff[cf_io_contatore]);
        loop_busy();
}
}

/* Cancella via hardware il contenuto di un dato settore */
int erase_seek(unsigned long lba_addr)
{
hw_error_status();
LBA(lba_addr);
cf_erase_cmd();
}

/* comando lettura */
int cf_read_cmd()
{
set_size();
loop_cmd_ready();
outp(cfreg7, 0x20);
loop_busy();
loop_ready();
}

/* comando scrittura */
int cf_write_cmd()
{
set_size();
loop_cmd_ready();
outp(cfreg7, 0x30);
loop_busy();
loop_ready();
}

/* comando erase */
int cf_erase_cmd()
{
set_size();
loop_cmd_ready();
outp(cfreg7, 0xc0);
loop_busy();
loop_ready();
}

/* indirizzi*/
int LBA(unsigned long address32)
{
    addr3 = (address32 & 0xff000000UL) >> 24;
    addr2 = (address32 & 0x00ff0000UL) >> 16;
    addr1 = (address32 & 0x0000ff00UL) >>  8;
    addr0 = (address32 & 0x000000ffUL)      ;
   
if (addr3 =! 0)
{
printf("CF Addressing Overflow !\n\r");
}

outp(cfreg3, addr0);
loop_busy();

outp(cfreg4, addr1);
loop_busy();

outp(cfreg5, addr2);
loop_busy();

outp(cfreg6, 0xe0);
loop_busy();
}

/*Setta la dimensione di settore a 512byte*/
int set_size()
{
outp(cfreg2, 0x01); /*dimensione settore di 512 byte*/
loop_busy();
}

/*Legge la ID hardware e la carica nel buffer*/
int cf_id()
{
loop_cmd_ready();
outp(cfreg7, 0xec);
loop_busy();
for(cf_io_contatore = 0; cf_io_contatore < 512; cf_io_contatore++)
{
ram_buff[cf_io_contatore] = inp(cfreg0);
}
}

/*Stabilisce la dimensione della CF*/
int get_capacity()
{
cf_id();
cf_size_alto=ram_buff[116];
cf_size_medio=ram_buff[115];
cf_size_basso=ram_buff[114];
cf_size = (cf_size_alto*65536)+(cf_size_medio*256)+cf_size_basso;
}

int capacity_info()
{
get_capacity();
printf("%ld settori - ", cf_size);
cf_size2 = (cf_size*512)/1000000;
printf("Capacita' %ldMB\n\r", cf_size2);
}

/*svuota il buffer*/
int clear_buff()
{
for(cf_io_contatore = 0; cf_io_contatore < 512; cf_io_contatore++)
    {
ram_buff[cf_io_contatore] = 0;   
}
}

/*verifica la presenza della CF nello slot*/
int hw_check()
{
hw_presence = 0;
clear_buff();
cf_id();
for(cf_io_contatore = 0; cf_io_contatore < 256; cf_io_contatore++)
    {
if (ram_buff[cf_io_contatore] != 0, ram_buff[cf_io_contatore] != 104) {
hw_presence = 1;
    }
}
}
/* hardware error message */
int hw_error_status()
if (hw_presence == 0) {
printf("\n\rNessuna CF inserita! Spegni la scheda Z80\n\re inserisci una CF nello slot se vuoi\n\rutilizzare le funzioni di mass storage.\n\r");
      }

Ora se io includo cf-io.h e inserisco cf_init(); dopo SetupHomeScreen(); la scheda si blocca se compilo il codice per rom e lo metto su rom, mentre funziona se compilo il codice per ram e lo carico in ram.

La cosa ho notato e' che quando compilo per rom, osservando il binario in mezzo al codice c'e' un buco vuoto di 512byte, osservando la mappa che viene passata al compilatore effettivamente mi inserisce ram_buff nell'area rom....

La cosa che non capisco e' che se metto un arbitrario "unsigned char pippo[512];" dopo
Codice:
main()
{
char CmdBuffer[50];

Questo non succede, anche CmdBuffer[50] non appare nella mappa del compilatore e dentro al binario, quindi  mi sfugge come sia stato definito che le variabili e le stringe dentro a main(); devono essere mappate in ram, se lo capissi forse riuscirei anche a fare lo stesso con le variabili e le stringhe delle mie funzioni.
Registrato
M.A.W. 1968
** LEGGETE IL REGOLAMENTO ! **
Global Moderator
Hero Member
*****

Karma: +224/-19
Scollegato Scollegato

Messaggi: 2988


Discrete And Combinatorial Mathematics


Mostra profilo WWW
« Risposta #3 inserita:: Settembre 05, 2015, 01:33:27 »

Devi riguardare con attenzione la mappatura definita nel crt0 e negli altri file di configurazione. Codesto cross-assembler è piuttosto povero di opzioni e di documentazione, per cui dovrai perderci del tempo... in quel caso non c'è un modo semplice e immediato (es. #pragma) per attribuire una variabile ad una zona di memoria. 
Registrato

I Moderatori invitano tutti gli utenti a prendere visione del REGOLAMENTO e a rispettarlo.

Un blog? Io? Occhiolino
GizMo
Newbie
*

Karma: +0/-0
Scollegato Scollegato

Messaggi: 40


Mostra profilo E-mail
« Risposta #4 inserita:: Settembre 05, 2015, 01:58:27 »

Il file crt0 e' questo qui

Codice:
;----------------------------------------------------
;Startup Code for Z80 MKII
;www.allthingsmicro.com
;Derek Baker
;4/11/2011
;----------------------------------------------------

DEFC NV_RAM_Start = $0000
DEFC NV_RAM_Length = $7FFF
DEFC    RAM_Start = $8000
DEFC    RAM_Length = $7200
DEFC RES_RAM_Start = $F200
DEFC    RES_RAM_Length = $0939 ;2375(0x0949) bytes long, end address 0xFB47
DEFC    Stack_Top = $FFFF ;From 0xFBFF to FFFF
DEFC Stack_Size = $0400 ;1K

; DEFC DEFINED_complexstdio = 1


MODULE  mk2_crt0

;-----------------------------------------------------
; Include zcc_opt.def to find out information about us
;-----------------------------------------------------

INCLUDE "zcc_opt.def"

;-------
; Some general scope declarations
;-------

        XREF    _main       ;main() is always external to crt0 code
        
XDEF    cleanup     ;jp'd to by exit()
        XDEF    l_dcal       ;jp(hl), probably on the way out but may be some reference to it yet

        XDEF    _std_seed   ;Integer rand() seed

        XDEF    exitsp       ;Pointer to atexit() stack
        XDEF    exitcount   ;Number of atexit() functions registered

        XDEF    __sgoioblk   ;std* control block
        XDEF    _vfprintf   ;jp to printf() core routine

        XDEF    _heaplast     ;Near malloc heap variables
        XDEF    _heapblocks   ;
        XDEF _heap ;heap* area 512 bytes for use with malloc

        XDEF _bheap ;bheap* area 512 bytes for use with balloc
        XDEF _ba_qtb ;balloc heap table
        
        XDEF _strtokt ;used for modified strtok

        XDEF _intvectortbl ;Interupt* vector table

;--------------
; Reset Vector
;--------------
IF(startup=3)
        IF      !myzorg
                defc    myzorg  = $8000
        ENDIF
                org     myzorg
ELSE
org     $0000
        jp coldstart
nop ;53 nops to place INT Jump
nop ;We have had to do this because our system has the first 32K os ROM
nop ;The z88dk compiler only accepts the one org statement, and we could
nop ;find any other way of placing code at a location of choice.
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
;--------------
; INT
;--------------  
.INTResetVector      
        jp $FB50
nop ;43 nops to place MNI Jump
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
;--------------
; NMI
;--------------
.MNIResetVector        
        jp $FB60
ENDIF        
;--------------
; Program Start
;--------------

.coldstart
;--------------
; Clear RES_RAM
;--------------

if(startup=3) ;if we are creating an app don't clear ram

ELSE
di
ld hl,RES_RAM_Start
ld de,RES_RAM_Start+1
ld bc,RES_RAM_Length-1
ld (hl),0
ldir
ENDIF

;-------------------------------
; Setup Stack and Stack pointers
;-------------------------------

if(startup=3) ;if we are creating an app don't init stack, done by boot loader

ELSE
ld hl,Stack_Top-Stack_Size
ld sp,hl
ld (exitsp),sp
xor a
ld (exitcount),a
ENDIF

;------------------------------------------------
; Set up the std* stuff so we can be called again
;------------------------------------------------

if(startup=3) ;if we are creating an app don't init streams block, done by boot loader

ELSE
IF !DEFINED_nostreams
IF DEFINED_ANSIstdio
ld hl,__sgoioblk+2
ld (hl),19 ;stdin
ld hl,__sgoioblk+6
ld (hl),21 ;stdout
ld hl,__sgoioblk+10
ld (hl),21 ;stderr
ENDIF
ENDIF
ENDIF

ld hl,$8080
ld (fp_seed),hl

;-----------------------
; Entry to the user code
;-----------------------

call _main

;------------------------------------------------
.cleanup
;
;Deallocate memory which has been allocated here!
;------------------------------------------------

if(startup=3) ;if we are creating an app and we want it to return to the boot loader, your application must return from main not exit(x)
ret

ELSE
push hl   ;Save return value from main()

IF !DEFINED_nostreams
IF DEFINED_ANSIstdio
LIB closeall
call closeall
ENDIF
ENDIF

pop hl   ;Return value from main()

.endloop
jr endloop ;if the bootloader or other program not loaded into bootloader returns just loop

ENDIF

.l_dcal ;needed for backwards compatibility
jp (hl)

;------------------------------------------------------------------
; Select which printf core we want
; The compiler selects a printf version depending on what is needed
;------------------------------------------------------------------

._vfprintf
IF DEFINED_floatstdio
LIB vfprintf_fp
jp vfprintf_fp
ELSE
IF DEFINED_complexstdio
LIB vfprintf_comp
jp vfprintf_comp
ELSE
IF DEFINED_ministdio
LIB vfprintf_mini
jp vfprintf_mini
ENDIF
ENDIF
ENDIF

;----------------------------------------
; Static variables kept in safe workspace
;----------------------------------------

DEFVARS RES_RAM_Start ;2361(0x0939) bytes long
{
_intvectortbl ds.b 256 ;Interupt Vector Table,This must be on a 256 byte page boundary
_staticmemory ds.b 1024 ;Used for global variables
_strtokt ds.w 1 ;Used in modified strtok
_heap ds.b 512 ;heap area 512 bytes malloc etc
_heapblocks     ds.w    1       ;Number of free blocks
_heaplast       ds.w    1       ;Pointer to linked blocks
_bheap ds.b 512 ;heap area 512 bytes for use with balloc
_ba_qtb ds.b 1 ;Balloc heap table
__sgoioblk      ds.b    40       ;stdio control block
_std_seed       ds.w    1       ;Integer seed
exitsp          ds.w    1       ;atexit() stack
exitcount       ds.b    1       ;Number of atexit() routines
fp_seed         ds.w    3       ;Floating point seed (not used ATM)
extra           ds.w    3       ;Floating point spare register
fa              ds.w    3       ;Floating point accumulator
fasign          ds.b    1       ;Floating point variable
}

;-----------------------------------------
; Now, include the math routines if needed
;-----------------------------------------

IF NEED_floatpack
        INCLUDE "#float.asm"
ENDIF

riesco a intuire che nel pezzo all'inizio e quello finale e' definita la mappa della memoria per le variabili statiche, ma non compredo cosa dica di mappare le variabili della rom in ram.
Registrato
M.A.W. 1968
** LEGGETE IL REGOLAMENTO ! **
Global Moderator
Hero Member
*****

Karma: +224/-19
Scollegato Scollegato

Messaggi: 2988


Discrete And Combinatorial Mathematics


Mostra profilo WWW
« Risposta #5 inserita:: Settembre 06, 2015, 02:21:38 »

Il problema fondamentale è che i cross compiler delle patatine come Small-C, SDCC, Z88DK... non supportano nativamente neppure lo heap, distribuiscono allegramente le variabili globali dove capita in mezzo al codice, e di conseguenza hanno problemi enormi in caso di codice ROM-abile, laddove altri compilatori (anche di costo nullo) gestiscono elegantissimamente la cosa con un paio di direttive o un semplice template di configurazione. Come hai notato, il codice ROM dei progettisti della mini-scheda evita del tutto il ricorso a static a livello di modulo, proprio per aggirare il problema.

Il resto del codice funziona perché, sostanzialmente, ciò che viene dichiarato entro un blocco sintattico qualsivoglia finisce sullo "stack", e nei file di configurazione di default si trova una dichiarazione per qualcosa che gli assomiglia.

La documentazione di Z88DK (scarna e inerentemente contorta) raccomanda l'uso di una tecnica assolutamente non ortodossa per il codice ROM-abile, riassunta in questo post (suggerisco la lettura dell'intero thread).


Comunque la mia ultratrentennale esperienza con i sistemi embedded mi suggerisce che da codeste situazioni si riescono a cavare le gambe solo con l'uso di dosi abbondanti di Assembly, aggirando appropriatamente i limiti del cross-compiler (fortunatamente non certo l'unico disponibile per Z80: ce ne sono a dozzine, dai gratuiti ai più blasonati e costosi!).
Registrato

I Moderatori invitano tutti gli utenti a prendere visione del REGOLAMENTO e a rispettarlo.

Un blog? Io? Occhiolino
GizMo
Newbie
*

Karma: +0/-0
Scollegato Scollegato

Messaggi: 40


Mostra profilo E-mail
« Risposta #6 inserita:: Settembre 06, 2015, 02:39:22 »

tu che compilatore per Z80 mi consigli quindi ? poi diventa un casino portare i sorgenti che ho scritto e quelli del bios originale di partenza sul nuovo compilatore ?
Registrato
M.A.W. 1968
** LEGGETE IL REGOLAMENTO ! **
Global Moderator
Hero Member
*****

Karma: +224/-19
Scollegato Scollegato

Messaggi: 2988


Discrete And Combinatorial Mathematics


Mostra profilo WWW
« Risposta #7 inserita:: Settembre 06, 2015, 03:15:54 »

A parità di piattaforma, il porting da un compilatore molto limitato ad un uno più potente, in generale, è una passeggiata. La parte più difficile, in concreto, è il modo non standard di referenziare i singoli port di I/O ed eventualmente i loro bit: il 90% del lavoro di porting consiste sostanzialmente in questo.

Tra l'altro, io userei la maggior quantità possibile di Assembly per il codice in ROM, anche ai fini dell'ottimizzazione in spazio - senza contare che in Assembly hai effettivamente un controllo estremo sull'allocazione delle variabili, e su tutto il resto.

Prova a fare un giro su Google per farti un'idea dei cross-compiler disponibili...
Registrato

I Moderatori invitano tutti gli utenti a prendere visione del REGOLAMENTO e a rispettarlo.

Un blog? Io? Occhiolino
GizMo
Newbie
*

Karma: +0/-0
Scollegato Scollegato

Messaggi: 40


Mostra profilo E-mail
« Risposta #8 inserita:: Settembre 06, 2015, 11:35:24 »

intendi il comando outp(); inp(); di z88dk ?
Registrato
M.A.W. 1968
** LEGGETE IL REGOLAMENTO ! **
Global Moderator
Hero Member
*****

Karma: +224/-19
Scollegato Scollegato

Messaggi: 2988


Discrete And Combinatorial Mathematics


Mostra profilo WWW
« Risposta #9 inserita:: Settembre 06, 2015, 01:34:51 »

intendi il comando outp(); inp(); di z88dk ?

No. La maggior parte dei cross compiler permette di specificare l'accesso diretto ai singoli bit entro un port, senza uso apparente di algebra booleana: ad esempio con una sintassi da struct estesa, come in "port.bit" oppure "bit@port" o altre varianti.
Queste features sono comunque assenti da cross compiler come Small-C, sdcc e Z88DK.
Registrato

I Moderatori invitano tutti gli utenti a prendere visione del REGOLAMENTO e a rispettarlo.

Un blog? Io? Occhiolino
GizMo
Newbie
*

Karma: +0/-0
Scollegato Scollegato

Messaggi: 40


Mostra profilo E-mail
« Risposta #10 inserita:: Settembre 06, 2015, 04:26:15 »

io sto cercando su google da un po' ma non trovo niente, tutti parlano di z88dk sdcc etc... gli altri sono programmi dos e altra roba che non gira, qualcuno addirittura parla di usare un compilare per cpm con cpm in amulazione....
Registrato
M.A.W. 1968
** LEGGETE IL REGOLAMENTO ! **
Global Moderator
Hero Member
*****

Karma: +224/-19
Scollegato Scollegato

Messaggi: 2988


Discrete And Combinatorial Mathematics


Mostra profilo WWW
« Risposta #11 inserita:: Settembre 06, 2015, 04:48:27 »

io sto cercando su google da un po' ma non trovo niente, tutti parlano di z88dk sdcc etc... gli altri sono programmi dos e altra roba che non gira, qualcuno addirittura parla di usare un compilare per cpm con cpm in amulazione....

Partiamo dal presupposto che, in generale, sviluppare in C per lo Z80 originale (così come per tanti altri core anche più moderni, inclusi i soliti AVR e PIC baseline che furoreggiano tra gli amatori) non è un'idea entusiasmante, specialmente per target con quantità di memoria limitate: ciò a causa del limitatissimo supporto della CPU a costrutti anche mediamente avanzati del linguaggio, che inevitabilmente finiscono per aggiungere al binario ridondanze ingiustificate, che si traducono ovviamente in codice più lento e ingombrante.

Detto questo, la mia strategia quando si tratta di baloccarsi privatamente(1) con Z80 e 8080 consiste nell'usare PC d'epoca (inclusi alcuni 486/5x86 su single board industriali, su bus ISA passivo) con DOS 6.22 e/o Windows 98 per sviluppare con tools DOS: principalmente Assembly come Dunfield (che all'epoca avevo ovviamente licenziato in versione completa), ma anche all'occorrenza Hi-Tech C. Dave Dunfield aveva anche donato al Public Domain il suo compilatore Micro-C per PC DOS, che può produrre codice 8080.
L'hardware tradizionale consente inoltre di avere a disposizione vere porte seriali, parallele, slot ISA (ad esempio per il mio glorioso gang programmer Hi/Lo Systems a 4 ZIF, controllato da una schedina dedicata) e PCI senza alcun genere di problema.

In passato ho comunque usato estensivamente anche l'opzione CP/M, emulato o hosted sul target: uno dei migliori prodotti commerciali dell'epoca era senz'altro il BDS C, poi divenuto freeware e con sorgenti, ben documentato e ricco di opzioni. Anche Aztech C è degno di menzione, assieme ovviamente al C della stessa gloriosa Digital Research.

Se invece si parla di estensioni più recenti della famiglia Z80 e di applicazioni professionali, uso principalmente Avocet, IAR, Crossware e lo ZDS della stessa Zilog (gratuito, e potenzialmente usabile con lo Z80 originale), oltre a compilatori verticali come Dynamic C di ZWorld per Z180 e Rabbit.


(1) Magari ne avessi il tempo!  Occhi al cielo  Pianto
Registrato

I Moderatori invitano tutti gli utenti a prendere visione del REGOLAMENTO e a rispettarlo.

Un blog? Io? Occhiolino
GizMo
Newbie
*

Karma: +0/-0
Scollegato Scollegato

Messaggi: 40


Mostra profilo E-mail
« Risposta #12 inserita:: Settembre 06, 2015, 06:34:38 »

Maw ti ringrazio delle preziose informazioni, oggi mi sono passato un po' di tempo su internet ma l'assembler e' troppo difficile per me al momento, in tutti i modi ho risolto il problema in un modo che tra l'altro e' piuttosto interessante, almeno per me.

Ho trasformato il monitor originale della scheda in un semplice bios, gli faccio caricare un certo numero di settori dalla CF alla ram e poi avvio il programma caricato in memoria. Ho copiato sulla CF con dd il codice del monitor originale compilato con l'opzione per funzionare in ram e il risultato e' che all'accensione il codice nella rom carica il codice dalla CF e mi avvia correttamente il monitor, che ora funzionando in ram si presta a tutte le modifiche che mi pare senza farmi impazzire.

Il codice compilato del bios occupa 2,6k, quindi magari nella scheda futura usero' una 28c32 per il bios e avro' 60k a disposizione per la ram. Il monitor attuale compilato per ram sta dentro 5k quindi non penso di avere problemi di sorta.

Ti posto il codice che ho scritto per il bios cosi' mi bastoni se ho fatto cavolate (pero' funziona!)

Codice:
/* Z80 MK3 bios */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <mk2/mk2.h>
#include <mk2/vt100.h>

/* Definizione dei registri della CF */
#define cfreg0 0x08 /* dati letti o da scrivere sulla cf */
#define cfreg1 0x09 /* leggi errore setta features */
#define cfreg2 0x0a /* quanti settori vuoi leggere in una volta */
#define cfreg3 0x0b /* indirizzo settore 0-7 bit */
#define cfreg4 0x0c /* indirizzo settore 8-15 bit */
#define cfreg5 0x0d /* indirizzo settore 16-23 bit */
#define cfreg6 0x0e /* indirizzo settore 24-27 bit */
#define cfreg7 0x0f /* leggi stato scrivi comando */
#define ram_start 0x8000
#define boot_block_count 48

void SetupHomeScreen(void);

main()
{
unsigned char conta;
unsigned int conta2;
unsigned char stato;
unsigned long init_delay;
unsigned int ram = ram_start;

InitSerialConsole(); /* Usa la porta seriale A come console */
SetupHomeScreen();
printf("Attendi l'inizializzazione della CF...\n\r");
for(init_delay = 0; init_delay < 10000; init_delay++)
{
#asm
    nop
    #endasm
}

/* inizializza la CF */
do { stato = inp(cfreg7); } while (stato > 128); /* loop busy */
outp(cfreg1, 0x01); /* features 8 bit */
do { stato = inp(cfreg7); } while (stato > 128); /* loop busy */
outp(cfreg7, 0xef); /* set features */
do { stato = inp(cfreg7); } while (stato > 128); /* loop busy */
printf("CF inizializzata...\n\r");
/* inizializzazione terminata */

/* carica 40 settori ossia 20k in ram */
printf("Carico il Sistema Operativo...\n\r");
for(conta = 0; conta < boot_block_count; conta++)
{
outp(cfreg3, conta);
do { stato = inp(cfreg7); } while (stato > 128); /* loop busy */

outp(cfreg4, 0);
do { stato = inp(cfreg7); } while (stato > 128); /* loop busy */

outp(cfreg5, 0);
do { stato = inp(cfreg7); } while (stato > 128); /* loop busy */

outp(cfreg6, 0xe0);
do { stato = inp(cfreg7); } while (stato > 128); /* loop busy */

/* set_size */

outp(cfreg2, 0x01); /*dimensione settore di 512 byte*/
do { stato = inp(cfreg7); } while (stato > 128); /* loop busy */
do { stato = inp(cfreg7); } while (stato > 128); /* loop cmd ready */

/* CF read CMD */
outp(cfreg7, 0x20);
do { stato = inp(cfreg7); } while (stato > 128); /* loop busy */
do { stato = inp(cfreg7); } while (stato == 1); /* loop ready */

for(conta2 = 0; conta2 < 512; conta2++)
{
*ram = inp(cfreg0);
ram++;
}
}

/* avvia il programma caricato in memoria */
printf("Avvio il Sistema Operativo...\n\r");
#asm
call $8000
#endasm
}

void SetupHomeScreen(void)

{
Cls();
SetVTAttrib(VTBGBlack);
SetVTAttrib(VTFGGreen);
SetScroll(((int*)2),((int*)24));
SetSmoothScroll();
SetVTAttrib(VTFGWhite);
Locate(((int*)0),((int*)24));
}

Ho dovuto ripetere parti di codice perche' non c'era verso di far girare delle funzioni che usassero delle variabili...
Registrato
GizMo
Newbie
*

Karma: +0/-0
Scollegato Scollegato

Messaggi: 40


Mostra profilo E-mail
« Risposta #13 inserita:: Settembre 07, 2015, 01:46:45 »

Aggiornamento: ho modificato il monitor caricato sulla compactflash aggiungendo tutte le routines che avevo scritto in precedenza, ho modificato leggermente la struttura del filesystem in modo da iniziare dopo il blocco con il binario del sistema, ora ho un perfetto mini-dos che fa il boot dalla compactflash.

Riassumento il codice del bios richiedera' una eeprom da 4k, sistema su CF occupa 18k, se monto una ram da 64k mi rimangono 42k liberi per caricare altri programmi, quindi alla fine non e' poi male.
Registrato
M.A.W. 1968
** LEGGETE IL REGOLAMENTO ! **
Global Moderator
Hero Member
*****

Karma: +224/-19
Scollegato Scollegato

Messaggi: 2988


Discrete And Combinatorial Mathematics


Mostra profilo WWW
« Risposta #14 inserita:: Settembre 07, 2015, 03:08:51 »

Riassumento il codice del bios richiedera' una eeprom da 4k, sistema su CF occupa 18k, se monto una ram da 64k mi rimangono 42k liberi per caricare altri programmi, quindi alla fine non e' poi male.

Direi che suona come un compromesso accettabile, considerando tutto. In seguito magari ti divertirai ad implementare un completo FAT16 in Assembly, con boot sector, e scoprirai che la compatibilità in questo caso non ha prezzo troppo elevato.
Registrato

I Moderatori invitano tutti gli utenti a prendere visione del REGOLAMENTO e a rispettarlo.

Un blog? Io? Occhiolino
Pagine: [1] 2 3 4   Vai su
  Stampa  
 
Vai a:  

Copyright © 2017 Edizioni Master SpA. p.iva : 02105820787

Tutti i diritti di proprietà letteraria e artistica riservati. - Privacy



powered by Simple Machines