From b1e6c68c30c3738dce2127d500f505c865334f12 Mon Sep 17 00:00:00 2001 From: kvigor Date: Mon, 30 Jun 2003 21:57:29 +0000 Subject: [PATCH] More DS400 support git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@2717 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- device/examples/ds400/monitor400/mon400.c | 95 +++++++++++++++-- device/include/ds400rom.h | 8 +- device/lib/ds400/ds400rom.c | 121 ++++++++++++++++++++-- device/lib/ds400/tinibios.c | 107 +++++-------------- src/ds390/gen.c | 8 +- 5 files changed, 239 insertions(+), 100 deletions(-) diff --git a/device/examples/ds400/monitor400/mon400.c b/device/examples/ds400/monitor400/mon400.c index 478c5927..5f39556e 100644 --- a/device/examples/ds400/monitor400/mon400.c +++ b/device/examples/ds400/monitor400/mon400.c @@ -11,18 +11,59 @@ void usage(void) puts("Available commands:\n"); puts("ledon: turns LED on."); puts("ledoff: turns LED off."); - puts("startclock: starts millisecond timer."); puts("clock: reports millisecond timer."); puts("sleep: sleeps for 10 seconds (or forever if you didn't startclock first)."); } +void blinker(void) +{ + int i, j; + + while (1) + { + P5 |= 4; + for (j = 0; j < 10; j++) + { + for (i = 0; i < 32767; i++) + { + ; + } + } + + P5 &= ~4; + + for (j = 0; j < 10; j++) + { + for (i = 0; i < 32767; i++) + { + ; + } + } + } +} + + void main(void) { char buffer[80]; // At this stage, the rom isn't initalized. We do have polled serial I/O, though. printf("TINIm400 monitor rev 0.0\n"); - + + P5 |= 4; // LED off. + + // double the cpu speed. + if (1) + { + PMR = 0x82; + PMR = 0x92; + + while (!(EXIF & 8)) + ; + + PMR = 0x12; + } + // Intialize the ROM. if (romInit(1)) { @@ -52,15 +93,14 @@ void main(void) P5 |= 4; printf("LED off.\n"); } - else if (!strcmp(buffer, "startclock")) - { - printf("Starting clock...\n"); - ClockInit(); - } else if (!strcmp(buffer, "clock")) { printf("Clock: %ld\n", ClockTicks()); } + else if (!strcmp(buffer, "thread")) + { + printf("Thread ID: %d\n", (int)DSS_getthreadID()); + } else if (!strcmp(buffer, "sleep")) { printf("Sleeping for 10 seconds...\n"); @@ -69,7 +109,46 @@ void main(void) printf("Back.\n"); } - + else if (!strcmp(buffer, "pmr")) + { + printf("PMR: %x\n", PMR); + } + else if (!strcmp(buffer, "exif")) + { + printf("EXIF: %x\n", EXIF); + } + else if (!strcmp(buffer, "blink")) + { + blinker(); + } + else if (!strcmp(buffer, "t0")) + { + printf("TH0:TL0 %x:%x\n", TH0, TL0); + } + else if (!strcmp(buffer, "t2")) + { + printf("TH2:TL2 %x:%x\n", TH2, TH2); + } + else if (!strcmp(buffer, "faster")) + { + printf("going really fast...\n"); + P5 |= 4; // LED off. + + PMR = 0x82; + PMR = 0x8a; // 8a for REAL fast + PMR = 0x9a; // 9a for REAL fast. + + while (!(EXIF & 8)) + ; + + PMR = 0x1a; // 1a for REAL fast. + +_asm + nop +_endasm; + + P5 &= ~5; // LED on. + } else if (buffer[0]) { printf("Unknown command \"%s\".\n", buffer); diff --git a/device/include/ds400rom.h b/device/include/ds400rom.h index 20a679b7..86d0f531 100644 --- a/device/include/ds400rom.h +++ b/device/include/ds400rom.h @@ -3,8 +3,12 @@ #ifndef DS400ROM_H_ #define DS400ROM_H_ -extern unsigned char rom_init(void xdata *loMem, - void xdata *hiMem) _naked; +extern unsigned char DSS_rom_init(void xdata *loMem, + void xdata *hiMem) _naked; + +extern unsigned long DSS_gettimemillis(void) _naked; + +extern unsigned char DSS_getthreadID(void) _naked; // Utility functions. diff --git a/device/lib/ds400/ds400rom.c b/device/lib/ds400/ds400rom.c index 219d367e..0a91d1df 100644 --- a/device/lib/ds400/ds400rom.c +++ b/device/lib/ds400/ds400rom.c @@ -41,6 +41,9 @@ #define R7_B3 0x1F +// The top of the redirect function table in RAM. +#define CALL_TABLE_TOP 256 + // The bank the ROM is stored in. Should be 0FFh for production // 400's. Change this value when running with a debug ROM. @@ -188,6 +191,42 @@ #define ROMXT_AUTOBAUD (99 * ROMXT_ENTRYSIZE) #define ROMXT_TFTP_CLOSE (100 * ROMXT_ENTRYSIZE) + +#define ROMRT_ENTRYSIZE 3 + +// +// ROM REDIRECT TABLE FUNCTIONS (denoted with ROMRT) +// +#define ROMRT_KERNELMALLOC ( 1 * ROMRT_ENTRYSIZE) +#define ROMRT_KERNELFREE ( 2 * ROMRT_ENTRYSIZE) +#define ROMRT_MALLOC ( 3 * ROMRT_ENTRYSIZE) +#define ROMRT_FREE ( 4 * ROMRT_ENTRYSIZE) +#define ROMRT_MALLOCDIRTY ( 5 * ROMRT_ENTRYSIZE) +#define ROMRT_DEREF ( 6 * ROMRT_ENTRYSIZE) +#define ROMRT_GETFREERAM ( 7 * ROMRT_ENTRYSIZE) +#define ROMRT_GETTIMEMILLIS ( 8 * ROMRT_ENTRYSIZE) +#define ROMRT_GETTHREADID ( 9 * ROMRT_ENTRYSIZE) +#define ROMRT_THREADRESUME (10 * ROMRT_ENTRYSIZE) +#define ROMRT_THREADIOSLEEP (11 * ROMRT_ENTRYSIZE) +#define ROMRT_THREADIOSLEEPNC (12 * ROMRT_ENTRYSIZE) +#define ROMRT_THREADSAVE (13 * ROMRT_ENTRYSIZE) +#define ROMRT_THREADRESTORE (14 * ROMRT_ENTRYSIZE) +#define ROMRT_SLEEP (15 * ROMRT_ENTRYSIZE) +#define ROMRT_GETTASKID (16 * ROMRT_ENTRYSIZE) +#define ROMRT_INFOSENDCHAR (17 * ROMRT_ENTRYSIZE) +#define ROMRT_IP_COMPUTECHECKSUM_SOFTWARE (18 * ROMRT_ENTRYSIZE) +#define ROMRT_0 (19 * ROMRT_ENTRYSIZE) // undefined +#define ROMRT_DHCPNOTIFY (20 * ROMRT_ENTRYSIZE) +#define ROMRT_ROM_TASK_CREATE (21 * ROMRT_ENTRYSIZE) +#define ROMRT_ROM_TASK_DUPLICATE (22 * ROMRT_ENTRYSIZE) +#define ROMRT_ROM_TASK_DESTROY (23 * ROMRT_ENTRYSIZE) +#define ROMRT_ROM_TASK_SWITCH_IN (24 * ROMRT_ENTRYSIZE) +#define ROMRT_ROM_TASK_SWITCH_OUT (25 * ROMRT_ENTRYSIZE) +#define ROMRT_OWIP_READCONFIG (26 * ROMRT_ENTRYSIZE) +#define ROMRT_SETMACID (27 * ROMRT_ENTRYSIZE) +#define ROMRT_UNDEREF (28 * ROMRT_ENTRYSIZE) + + #define GETC \ clr a \ movc a, @a+dptr @@ -242,6 +281,44 @@ _asm _endasm ; } +// expects function number in R6_B3 (low byte) & R7_B3 (high byte) +void _romredirect(void) _naked +{ +_asm + push dpx + push dph + push dpl + push acc + ; dptr = CALL_TABLE_TOP + function offset. + mov a, #(CALL_TABLE_TOP & 0xff) + add a, R6_B3 ; add function offset to the table + mov dpl, a + mov a, #((CALL_TABLE_TOP >> 8) & 0xff) + addc a, R7_B3 + mov dph, a + mov dpx, #((CALL_TABLE_TOP >> 16) & 0xff) + movx a, @dptr ; read high byte + mov R5_B3, a + inc dptr + movx a, @dptr ; read mid byte + mov R4_B3, a + inc dptr + movx a, @dptr ; read low byte + mov R3_B3, a + pop acc ; restore acc and dptr + pop dpl + pop dph + pop dpx + push R3_B3 ; push low byte of target address + push R4_B3 + push R5_B3 ; push high byte of target address + ret ; this is not a ret, it is a call! + + ; the called function ends with a ret which will return to our original caller. +_endasm; +} + + // This macro is invalid for the standard C preprocessor, since it // includes a hash character in the expansion, hence the SDCC specific // pragma. @@ -251,9 +328,14 @@ _endasm ; mov R7_B3, #((x >> 8) & 0xff) \ lcall __romcall +#define ROMREDIRECT(x) \ + mov R6_B3, #(x & 0xff) \ + mov R7_B3, #((x >> 8) & 0xff) \ + lcall __romredirect + -// rom_init: the ds400 ROM_INIT ROM function. -unsigned char rom_init(void xdata *loMem, +// DSS_rom_init: the ds400 ROM_INIT ROM function. +unsigned char DSS_rom_init(void xdata *loMem, void xdata *hiMem) _naked { // shut compiler up about unused parameters. @@ -266,8 +348,8 @@ _asm mov r2, dpx mov r1, dph mov r0, dpl - ; hiMem is in _rom_init_PARM_2 - mov dptr, #_rom_init_PARM_2 + ; hiMem is in _DSS_rom_init_PARM_2 + mov dptr, #_DSS_rom_init_PARM_2 mov r5, dpx mov r4, dph mov r3, dpl @@ -280,7 +362,34 @@ _asm _endasm ; } -// all other ROM functions should go here, using rom_init as a template... +// DSS_gettimemillis: note that the ROM actually returns 5 bytes of time, +// we're discarding the high byte here. +unsigned long DSS_gettimemillis(void) _naked +{ +_asm + ; no parameters to load. + ROMREDIRECT(ROMRT_GETTIMEMILLIS) + ; results in r4 - r0, return in DPTR/B + mov dpl, r0 + mov dph, r1 + mov dpx, r2 + mov b, r3 + ret +_endasm; +} + +unsigned char DSS_getthreadID(void) _naked +{ +_asm + ; no parameters to load. + ROMREDIRECT(ROMRT_GETTHREADID) + ; results in acc, return in dpl + mov dpl, a + ret +_endasm; +} + + // Various utility functions. @@ -336,7 +445,7 @@ unsigned char romInit(unsigned char noisy) heapStart = _firstHeapByte(); heapEnd = (void xdata *)CE0_END; - rc = rom_init(heapStart, heapEnd); + rc = DSS_rom_init(heapStart, heapEnd); if (noisy) { diff --git a/device/lib/ds400/tinibios.c b/device/lib/ds400/tinibios.c index 259b06d4..eefc2038 100755 --- a/device/lib/ds400/tinibios.c +++ b/device/lib/ds400/tinibios.c @@ -27,10 +27,12 @@ #include #include +#include + #define TIMED_ACCESS(sfr,value) { TA=0xaa; TA=0x55; sfr=value; } #undef OSCILLATOR -#define OSCILLATOR 14725600 +#define OSCILLATOR 14745600 unsigned char _sdcc_external_startup(void) { @@ -86,13 +88,26 @@ static data unsigned char serial0Buffered; If buffered!=0, characters received are buffered using an interrupt */ + +#define SERIAL0_BAUDRATE 115200 +#define TIMER_RELOAD (65536 - ((OSCILLATOR) / (32 * SERIAL0_BAUDRATE))) + void Serial0Init (unsigned long baud, unsigned char buffered) { ES0 = 0; // disable serial channel 0 interrupt +#if 0 // Need no port setup, done by boot rom. - baud; +#else + SCON0 = 0x5A; // 10 bit serial 0, use timer baud rate, enable recieving + RCAP2H = (TIMER_RELOAD >> 8) & 0xff; + RCAP2L = TIMER_RELOAD & 0xff; + T2CON = 0x30; // Enable timer 2 for serial port + TR2 = 1; // Set timer 2 to run + + baud; +#endif serial0Buffered=buffered; @@ -106,16 +121,6 @@ void Serial0Init (unsigned long baud, unsigned char buffered) { } } -void Serial0Baud(unsigned long baud) { - TR2=0; // stop timer - baud=-((long)OSCILLATOR/(32*baud)); - TL2=RCAP2L= baud; - TH2=RCAP2H= baud>>8; - TF2=0; // clear overflow flag - TR2=1; // start timer -} - - void Serial0SwitchToBuffered(void) { IE &= ~0x80; @@ -128,7 +133,6 @@ void Serial0SwitchToBuffered(void) IE |= 0x80; } - void Serial0IrqHandler (void) interrupt 4 { if (RI_0) { receive0Buffer[receive0BufferHead]=SBUF0; @@ -168,7 +172,6 @@ void Serial0PutChar (char c) ; TI_0 = 0; SBUF0=c; - // TI_0=0; } } @@ -191,14 +194,11 @@ char Serial0GetChar (void) return c; } -#if 0 -// FIXME: no ClockMilliSecondsDelay yet. void Serial0SendBreak() { P3 &= ~0x02; ClockMilliSecondsDelay(2); P3 |= 0x02; } -#endif void Serial0Flush() { ES0=0; // disable interrupts @@ -212,77 +212,24 @@ void Serial0Flush() { } } -// now let's go for the clock stuff - -// these REALLY need to be in data space for the irq routine! -static data unsigned long milliSeconds=0; -static data unsigned int timer0ReloadValue; +// now let's go for the clock stuff - on the DS400, we can just +// use the ROM's millisecond timer, running off timer 0. +// +// for now, this timer runs too fast by about 20%. We need an implementation of +// task_settickreload to fix this. void ClockInit() { - unsigned long timerReloadValue= OSCILLATOR / 1000 / 4; - - timer0ReloadValue=~timerReloadValue; - // initialise timer 0 - ET0=0; // disable timer interrupts initially - - TCON = (TCON&0xcc)|0x00; // stop timer, clear overflow - TMOD = (TMOD&0xf0)|0x01; // 16 bit counter - CKCON|=0x08; // timer uses xtal/4 - - TL0=timer0ReloadValue&0xff; - TH0=timer0ReloadValue>>8; - - installInterrupt(ClockIrqHandler, 0xB); - - ET0=1; // enable timer interrupts - TR0=1; // start timer -} - -// This needs to be SUPER fast. What we really want is: - -#if 0 -void junk_ClockIrqHandler (void) interrupt 10 { - TL0=timer0ReloadValue&0xff; - TH0=timer0ReloadValue>>8; - milliSeconds++; -} -#else -// but look at the code, and the pushes and pops, so: -void ClockIrqHandler (void) interrupt 1 _naked -{ - _asm - push acc - push psw - mov _TL0,_timer0ReloadValue - mov _TH0,_timer0ReloadValue+1 - clr a - inc _milliSeconds+0 - cjne a,_milliSeconds+0,_ClockIrqHandlerDone - inc _milliSeconds+1 - cjne a,_milliSeconds+1,_ClockIrqHandlerDone - inc _milliSeconds+2 - cjne a,_milliSeconds+2,_ClockIrqHandlerDone - inc _milliSeconds+3 - _ClockIrqHandlerDone: - pop psw - pop acc - reti - _endasm; + // nada, all done by DSS_rom_init } -#endif // we can't just use milliSeconds unsigned long ClockTicks(void) { - unsigned long ms; - ET0=0; - ms=milliSeconds; - ET0=1; - return ms; + return DSS_gettimemillis(); } void ClockMilliSecondsDelay(unsigned long delay) { - long ms=ClockTicks()+delay; + unsigned long ms = DSS_gettimemillis() + delay; - while (ms>ClockTicks()) - ; + while (ms > DSS_gettimemillis()) + ; } diff --git a/src/ds390/gen.c b/src/ds390/gen.c index 2adeded3..f697a3b1 100644 --- a/src/ds390/gen.c +++ b/src/ds390/gen.c @@ -2045,8 +2045,8 @@ saveRegisters (iCode * lic) /* if the registers have been saved already then do nothing */ - if (ic->regsSaved || - (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))))) + if (ic->regsSaved + || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) ) return ; /* special case if DPTR alive across a function call then must save it @@ -2549,7 +2549,7 @@ genCall (iCode * ic) the same register bank then we need to save the destination registers on the stack */ dtype = operandType (IC_LEFT (ic)); - if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) && + if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) && (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) && IFFUNC_ISISR (currFunc->type)) { @@ -2705,7 +2705,7 @@ genPcall (iCode * ic) the same register bank then we need to save the destination registers on the stack */ dtype = operandType (IC_LEFT (ic)); - if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) && + if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) && IFFUNC_ISISR (currFunc->type) && (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) { saveRBank (FUNC_REGBANK (dtype), ic, TRUE); -- 2.30.2