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))
{
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");
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);
#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.
#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.
#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
_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.
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.
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
_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.
heapStart = _firstHeapByte();
heapEnd = (void xdata *)CE0_END;
- rc = rom_init(heapStart, heapEnd);
+ rc = DSS_rom_init(heapStart, heapEnd);
if (noisy)
{
#include <tinibios.h>
#include <ds400rom.h>
+#include <stdio.h>
+
#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)
{
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;
}
}
-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;
IE |= 0x80;
}
-
void Serial0IrqHandler (void) interrupt 4 {
if (RI_0) {
receive0Buffer[receive0BufferHead]=SBUF0;
;
TI_0 = 0;
SBUF0=c;
- // TI_0=0;
}
}
return c;
}
-#if 0
-// FIXME: no ClockMilliSecondsDelay yet.
void Serial0SendBreak() {
P3 &= ~0x02;
ClockMilliSecondsDelay(2);
P3 |= 0x02;
}
-#endif
void Serial0Flush() {
ES0=0; // disable interrupts
}
}
-// 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())
+ ;
}
/* 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
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))
{
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);