+2003-07-01 Kevin Vigor <kevin@vigor.nu>
+
+ * DS800C400 fun, improved ROM interface and tinibios.
+
2003-06-27 Kevin Vigor <kevin@vigor.nu>
* More support for DS80C400. Now includes beginning of interface to ROM.
{
char buffer[80];
- // At this stage, the rom isn't initalized. We do have polled serial I/O, though.
+ // At this stage, the rom isn't initalized. We do have polled serial I/O, but that's
+ // about the only functional library service.
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))
- {
- // We're hosed. romInit will have printed an error, nothing more to do.
- return;
- }
-
- P5 &= ~4; // LED on.
- // Switch to interrupt driven serial I/O now that the rom is initialized.
- Serial0SwitchToBuffered();
+ romInit(1, SPEED_2X);
+ // Now we're cooking with gas.
+
while (1)
{
// monitor prompt.
}
else if (!strcmp(buffer, "thread"))
{
- printf("Thread ID: %d\n", (int)DSS_getthreadID());
+ printf("Thread ID: %d\n", (int)task_getthreadID());
}
else if (!strcmp(buffer, "sleep"))
{
#ifndef DS400ROM_H_
#define DS400ROM_H_
-extern unsigned char DSS_rom_init(void xdata *loMem,
- void xdata *hiMem) _naked;
+extern unsigned char init_rom(void xdata *loMem,
+ void xdata *hiMem) _naked;
-extern unsigned long DSS_gettimemillis(void) _naked;
+extern unsigned long task_gettimemillis_long(void) _naked;
-extern unsigned char DSS_getthreadID(void) _naked;
+extern unsigned char task_getthreadID(void) _naked;
-// Utility functions.
+/** Timer reload value for 14.746 MHz crystal. */
+#define RELOAD_14_746 0xfb33
-// A wrapper which calls rom_init allocating all available RAM in CE0
-// to the heap.
-unsigned char romInit(unsigned char noisy);
+/** Timer reload value for 18.432 MHz crystal. */
+#define RELOAD_18_432 0xfa00
-// Install an interrupt handler.
-void installInterrupt(void (*isrPtr)(void), unsigned char offset);
+/** Timer reload value for 29.491 MHz crystal. */
+#define RELOAD_29_491 0xfd99
+
+/** Timer reload value for 36.864 MHz crystal. */
+#define RELOAD_36_864 0xfd00
+
+/** Timer reload value for 58.982 MHz crystal. */
+#define RELOAD_58_982 0xfecc
+
+/** Timer reload value for 73.728 MHz crystal. */
+#define RELOAD_73_728 0xfe80
+
+extern unsigned int task_gettickreload(void);
+
+extern void task_settickreload(unsigned);
#endif
#define SERIAL_1_RECEIVE_BUFFER_SIZE 64
// I know someone is fooling with the crystals
-#define OSCILLATOR 18432000L
+#if defined(SDCC_ds400)
+# define OSCILLATOR 14745600L
+#else
+# define OSCILLATOR 18432000L
+#endif
/* Set the cpu speed in clocks per machine cycle, valid values are:
1024: Divide-by-1024 (power management) mode (screws ALL timers and serial)
unsigned char _sdcc_external_startup(void);
void Serial0IrqHandler (void) interrupt 4;
void Serial1IrqHandler (void) interrupt 7;
+
+#if !defined(SDCC_ds400)
void ClockInit();
void ClockIrqHandler (void) interrupt 1 _naked;
+#endif
+
+#if defined(SDCC_ds400)
+// functions for dealing with the ds400 ROM firmware.
+
+// A wrapper which calls rom_init allocating all available RAM in CE0
+// to the heap, sets the serial port to SERIAL_0_BAUD, sets up the
+// millisecond timer, and diddles the clock multiplier.
+
+// Values for the romInit "speed" parameter.
+#define SPEED_1X 0 /* no clock multiplier, normal speed. */
+#define SPEED_2X 1 /* 2x clock multiplier. */
+#define SPEED_4X 2 /* 4x clock, DOESN'T WORK ON TINIm400! */
+
+unsigned char romInit(unsigned char noisy,
+ char speed);
+
+// Install an interrupt handler.
+void installInterrupt(void (*isrPtr)(void), unsigned char offset);
+#endif
+
#endif /* TINIBIOS_H */
#include <stdio.h>
#include <ds400rom.h>
+// ROM globals, taken from startup400.a51
+data unsigned char at 0x68 DSS_wos_crit_count;
+data unsigned int at 0x6b DSS_timerReload;
+data unsigned char at 0x6d DSS_curr_pc[3];
+data unsigned char at 0x72 DSS_sched[3];
+data unsigned char at 0x74 DSS_ms_count[5];
+data unsigned char at 0x7b DSS_hb_chandle[5];
+
// Register bank 3 equates.
#define R0_B3 0x18
#define R1_B3 0x19
lcall __romredirect
-// DSS_rom_init: the ds400 ROM_INIT ROM function.
-unsigned char DSS_rom_init(void xdata *loMem,
+// init_rom: the ds400 ROM_INIT ROM function.
+unsigned char init_rom(void xdata *loMem,
void xdata *hiMem) _naked
{
// shut compiler up about unused parameters.
mov r2, dpx
mov r1, dph
mov r0, dpl
- ; hiMem is in _DSS_rom_init_PARM_2
- mov dptr, #_DSS_rom_init_PARM_2
+ ; hiMem is in _init_rom_PARM_2
+ mov dptr, #_init_rom_PARM_2
mov r5, dpx
mov r4, dph
mov r3, dpl
// 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
+unsigned long task_gettimemillis_long(void) _naked
{
_asm
; no parameters to load.
_endasm;
}
-unsigned char DSS_getthreadID(void) _naked
+unsigned char task_getthreadID(void) _naked
{
_asm
; no parameters to load.
_endasm;
}
-
-
-// Various utility functions.
-
-// Return the start of the XI_SEG. Really just a workaround for the
-// fact that the linker defined symbol (s_XISEG) isn't directly accessible
-// from C due to the lack of a leading underscore, and I'm too lazy to hack
-// the linker.
-static void xdata *_xisegStart(void) _naked
-{
-_asm
- mov dptr, #(s_XISEG)
- ret
-_endasm;
-}
-
-// Return the length of the XI_SEG. Really just a workaround for the
-// fact that the linker defined symbol (l_XISEG) isn't directly accessible
-// from C due to the lack of a leading underscore, and I'm too lazy to hack
-// the linker.
-static unsigned _xisegLen(void) _naked
-{
-_asm
- mov dptr, #(l_XISEG)
- ret
-_endasm;
-}
-
-// Returns the address of the first byte available for heap memory,
-// i.e. the first byte following the XI_SEG.
-static void xdata *_firstHeapByte(void)
+unsigned int task_gettickreload(void)
{
- unsigned char xdata *start;
-
- start = (unsigned char xdata *) _xisegStart();
- start += _xisegLen();
-
- return (void xdata *)start;
+ return DSS_timerReload;
}
-// A simple wrapper for ROM_INIT which allocates all available RAM in the CE0 area
-// to the heap.
-
-// The last addressible byte of the CE0 area.
-#define CE0_END 0xfffff
-
-unsigned char romInit(unsigned char noisy)
+void task_settickreload(unsigned int rl)
{
- void xdata *heapStart;
- void xdata *heapEnd;
- unsigned long heapLen;
- unsigned char rc;
-
- heapStart = _firstHeapByte();
- heapEnd = (void xdata *)CE0_END;
-
- rc = DSS_rom_init(heapStart, heapEnd);
-
- if (noisy)
- {
- if (rc)
- {
- printf("error: rom_init returns %d\n", (int)rc);
- }
- else
- {
- heapLen = CE0_END - (unsigned long)heapStart;
- printf("Heap starts at %p, length %luK\n", heapStart, heapLen / 1024);
- }
- }
- return rc;
+ DSS_timerReload = rl;
}
-// Install an interrupt handler.
-void installInterrupt(void (*isrPtr)(void), unsigned char offset)
-{
- unsigned char xdata * vectPtr = (unsigned char xdata *) offset;
- unsigned long isr = (unsigned long)isrPtr;
-
- *vectPtr++ = 0x02;
- *vectPtr++ = (unsigned char)(isr >> 16);
- *vectPtr++ = (unsigned char)(isr >> 8);
- *vectPtr = (unsigned char)isr;
-}
#define TIMED_ACCESS(sfr,value) { TA=0xaa; TA=0x55; sfr=value; }
-#undef OSCILLATOR
-#define OSCILLATOR 14745600
-
unsigned char _sdcc_external_startup(void)
{
IE = 0; // Disable all interrupts.
*/
-#define SERIAL0_BAUDRATE 115200
-#define TIMER_RELOAD (65536 - ((OSCILLATOR) / (32 * SERIAL0_BAUDRATE)))
+#define TIMER_RELOAD (65536 - ((OSCILLATOR) / (32 * SERIAL_0_BAUD)))
void Serial0Init (unsigned long baud, unsigned char buffered) {
// we can't just use milliSeconds
unsigned long ClockTicks(void) {
- return DSS_gettimemillis();
+ return task_gettimemillis_long();
}
void ClockMilliSecondsDelay(unsigned long delay) {
- unsigned long ms = DSS_gettimemillis() + delay;
+ unsigned long ms = task_gettimemillis_long() + delay;
- while (ms > DSS_gettimemillis())
+ while (ms > task_gettimemillis_long())
;
}
+
+// Return the start of the XI_SEG. Really just a workaround for the
+// fact that the linker defined symbol (s_XISEG) isn't directly accessible
+// from C due to the lack of a leading underscore, and I'm too lazy to hack
+// the linker.
+static void xdata *_xisegStart(void) _naked
+{
+_asm
+ mov dptr, #(s_XISEG)
+ ret
+_endasm;
+}
+
+// Return the length of the XI_SEG. Really just a workaround for the
+// fact that the linker defined symbol (l_XISEG) isn't directly accessible
+// from C due to the lack of a leading underscore, and I'm too lazy to hack
+// the linker.
+static unsigned _xisegLen(void) _naked
+{
+_asm
+ mov dptr, #(l_XISEG)
+ ret
+_endasm;
+}
+
+// Returns the address of the first byte available for heap memory,
+// i.e. the first byte following the XI_SEG.
+static void xdata *_firstHeapByte(void)
+{
+ unsigned char xdata *start;
+
+ start = (unsigned char xdata *) _xisegStart();
+ start += _xisegLen();
+
+ return (void xdata *)start;
+}
+
+// TINIm400 specific startup.
+
+// The last addressible byte of the CE0 area.
+#define CE0_END 0xfffff
+
+unsigned char romInit(unsigned char noisy,
+ char speed)
+{
+ void xdata *heapStart;
+ void xdata *heapEnd;
+ unsigned long heapLen;
+ unsigned char rc;
+
+ if (speed == SPEED_2X)
+ {
+ PMR = 0x82;
+ PMR = 0x92;
+
+ while (!(EXIF & 8))
+ ;
+
+ PMR = 0x12;
+ }
+ else if (speed == SPEED_4X)
+ {
+ // Hangs on TINIm400!
+ PMR = 0x82;
+ PMR = 0x8a;
+ PMR = 0x9a;
+
+ while (!(EXIF & 8))
+ ;
+
+ PMR = 0x1a;
+ }
+
+ heapStart = _firstHeapByte();
+ heapEnd = (void xdata *)CE0_END;
+
+ rc = init_rom(heapStart, heapEnd);
+
+ if (noisy)
+ {
+ if (rc)
+ {
+ printf("error: rom_init returns %d\n", (int)rc);
+ return rc;
+ }
+ else
+ {
+ heapLen = CE0_END - (unsigned long)heapStart;
+ printf("Heap starts at %p, length %luK\n", heapStart, heapLen / 1024);
+ }
+ }
+
+ task_settickreload(RELOAD_14_746);
+
+ // Switch to interrupt driven serial I/O now that the rom is initialized.
+ Serial0SwitchToBuffered();
+
+ P5 &= ~4; // LED on.
+
+ return 0;
+}
+
+// Install an interrupt handler.
+void installInterrupt(void (*isrPtr)(void), unsigned char offset)
+{
+ unsigned char xdata * vectPtr = (unsigned char xdata *) offset;
+ unsigned long isr = (unsigned long)isrPtr;
+
+ *vectPtr++ = 0x02;
+ *vectPtr++ = (unsigned char)(isr >> 16);
+ *vectPtr++ = (unsigned char)(isr >> 8);
+ *vectPtr = (unsigned char)isr;
+}
fprintf (asmFile, "%s", iComments2);
copyFile (asmFile, xidata->oFile);
+ /* If the port wants to generate any extra areas, let it do so. */
+ if (port->extraAreas.genExtraAreaDeclaration)
+ {
+ port->extraAreas.genExtraAreaDeclaration(asmFile,
+ mainf && IFFUNC_HASBODY(mainf->type));
+ }
+
/* copy the interrupt vector table */
if (mainf && IFFUNC_HASBODY(mainf->type))
{
if ( (options.stack_loc) && (options.stack_loc<0x100) ) {
WRITE_SEG_LOC ("SSEG", options.stack_loc);
}
+
+ /* If the port has any special linker area declarations, get 'em */
+ if (port->extraAreas.genExtraAreaLinkOptions)
+ {
+ port->extraAreas.genExtraAreaLinkOptions(lnkfile);
+ }
/* add the extra linker options */
fputStrSet(lnkfile, linkOptionsSet);
NULL,
0,
},
+ { NULL, NULL },
{
-1, 1, 4, 1, 1, 0},
/* avr has an 8 bit mul */
NULL,
1
},
+ { NULL, NULL },
{
+1, 1, 4, 1, 1, 0
},
NULL,
1
},
+ { NULL, NULL },
{
+1, 1, 4, 1, 1, 0
},
} /* MODEL_FLAT24 */
}
+extern char * iComments2;
+
+static void _ds400_generateRomDataArea(FILE *fp, bool isMain)
+{
+ /* Only do this for the file containing main() */
+ if (isMain)
+ {
+ fprintf(fp, "%s", iComments2);
+ fprintf(fp, "; the direct data area used by the DS80c400 ROM code.\n");
+ fprintf(fp, "%s", iComments2);
+ fprintf(fp, ".area ROMSEG (ABS,CON,DATA)\n\n");
+ fprintf(fp, ".ds 24 ; 24 bytes of directs used starting at 0x68\n\n");
+ }
+}
+
+static void _ds400_linkRomDataArea(FILE *fp)
+{
+ fprintf(fp, "-b ROMSEG = 0x0068\n");
+}
+
+
PORT ds400_port =
{
TARGET_ID_DS400,
NULL,
1
},
+ { _ds400_generateRomDataArea, _ds400_linkRomDataArea },
{
+1, 1, 4, 1, 1, 0
},
NULL,
1
},
+ { NULL, NULL },
{
+1, 0, 4, 1, 1, 0
},
NULL,
1 // code is read only
},
+ { NULL, NULL },
{
+1, 1, 4, 1, 1, 0
},
NULL,
1 // code is read only
},
+ { NULL, NULL },
{
+1, 1, 4, 1, 1, 0
},
}
mem;
+ struct
+ {
+ void (*genExtraAreaDeclaration)(FILE *, bool);
+ void (*genExtraAreaLinkOptions)(FILE *);
+ }
+ extraAreas;
+
/* stack related information */
struct
{
NULL, // default global map
1
},
+ { NULL, NULL },
{
-1, // stack grows down
0, // bank overhead NUY
NULL,
1
},
+ { NULL, NULL },
{
-1, 0, 0, 4, 0, 2
},
NULL,
1
},
+ { NULL, NULL },
{
-1, 0, 0, 2, 0, 4
},
#if defined(SDCC_ds400)
// Intialize the ROM.
- if (romInit(1))
+ if (romInit(1, SPEED_2X))
{
// We're hosed. romInit will have printed an error, nothing more to do.
return;
}
-
- ClockInit();
-
- P5 &= ~4; // LED on.
#endif
printf("[dhry]\n");
#if DEBUG
Number_Of_Runs = 1;
#else
- // Number_Of_Runs = 32766;
- Number_Of_Runs = 2048;
+#if defined(SDCC_ds400)
+ Number_Of_Runs = 10240;
+#else
+ Number_Of_Runs = 32766;
+#endif
#endif
runTime = clock();