* Removed svn:executable property from non-executable files
[fw/sdcc] / device / lib / ds390 / tinibios.c
old mode 100755 (executable)
new mode 100644 (file)
index bb4b389..1f6363d
@@ -1,3 +1,27 @@
+/*-------------------------------------------------------------------------
+  tinibios.c - startup and serial routines for the DS80C390 (tested on TINI)
+  
+   Written By - Johan Knol, johan.knol@iduna.nl
+    
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   
+   In other words, you are welcome to use, share and improve this program.
+   You are forbidden to forbid anyone else to use, share and improve
+   what you give them.   Help stamp out software-hoarding!  
+-------------------------------------------------------------------------*/
+
 #include <tinibios.h>
 #include <stdio.h>
 
@@ -20,7 +44,8 @@ unsigned char _sdcc_external_startup(void)
   // CKCON|=0xc0;
 
   // default stretch cycles for MOVX
-  CKCON = (CKCON&0xf8)|(CPU_MOVX_STRETCH&0x07);
+  //CKCON = (CKCON&0xf8)|(CPU_MOVX_STRETCH&0x07);
+  CKCON=0xf9;
 
   // use internal 4k RAM as data(stack) memory at 0x400000 and
   // move CANx memory access to 0x401000 and upwards
@@ -30,57 +55,57 @@ unsigned char _sdcc_external_startup(void)
   // select default cpu speed
   CpuSpeed(CPU_SPEED);
 
-  _asm
+  __asm
     ; save the 24-bit return address
     pop ar2; msb
     pop ar1
     pop ar0; lsb
 
 
-    mov _ESP,#0x00; reinitialize the stack
-    mov _SP,#0x00
-
     mov _TA,#0xaa; timed access
     mov _TA,#0x55
     mov _ACON,#0x06; 24 bit addresses, 10 bit stack at 0x400000
 
+    mov _ESP,#0x00; reinitialize the stack
+    mov _SP,#0x00
+
     ; restore the 24-bit return address
     push ar0; lsb
     push ar1
     push ar2; msb
-  _endasm;
+  __endasm;
 
   // Copy the Interrupt Vector Table (128 bytes) from 0x10000 to 0x100000
   // This isn't needed for older bootloaders than the 0515, but it won't harm
-  _asm
-  push dpx
-  push dph
-  push dpl
-  push dps
-  push b
-  push acc
-  mov dps,#0x00 ; make sure no autoincrement in progress
-  mov dptr,#0x10000 ; from
-  inc dps ; switch to alternate dptr
-  mov dptr,#0x100000 ; to
-  mov b,#0x80 ; count
+  __asm
+    push dpx
+    push dph
+    push dpl
+    push dps
+    push b
+    push acc
+    mov dps,#0x00 ; make sure no autoincrement in progress
+    mov dptr,#0x10000 ; from
+    inc dps ; switch to alternate dptr
+    mov dptr,#0x100000 ; to
+    mov b,#0x80 ; count
 
 _Startup390CopyIVT:
-  inc dps
-  movx a,@dptr
-  inc dptr
-  inc dps
-  movx @dptr,a
-  inc dptr
-  djnz b,_Startup390CopyIVT
-
-  pop acc
-  pop b
-  pop dps
-  pop dpl
-  pop dph
-  pop dpx
-  _endasm;
+    inc dps
+    movx a,@dptr
+    inc dptr
+    inc dps
+    movx @dptr,a
+    inc dptr
+    djnz b,_Startup390CopyIVT
+
+    pop acc
+    pop b
+    pop dps
+    pop dpl
+    pop dph
+    pop dpx
+  __endasm;
 
   // global interrupt enable, all masks cleared
   // let the Gods be with us :)
@@ -107,10 +132,12 @@ _Startup390CopyIVT:
 
 unsigned int cpuSpeed;
 
-void CpuSpeed(unsigned int speed) {
-
+void CpuSpeed(unsigned int speed)
+{
+#if 0
   while (0 && (EXIF&0x04))
     ; // cpu operates from ring buffer
+#endif
   PMR = 0x80; // div4, CTM off, multiplier 2x
   switch (speed) 
     {
@@ -154,7 +181,7 @@ static volatile int receive0BufferTail=0;
 // no buffering for transmit
 static volatile char transmit0IsBusy=0;
 
-static data unsigned char serial0Buffered;
+static __data unsigned char serial0Buffered;
 
 /* Initialize serial0.
 
@@ -164,8 +191,8 @@ static data unsigned char serial0Buffered;
    If buffered!=0, characters received are buffered using an interrupt
 */
 
-void Serial0Init (unsigned long baud, unsigned char buffered) {
-  
+void Serial0Init (unsigned long baud, unsigned char buffered)
+{
   if (baud==0) {
     ES0=0; // disable interrupts
     SCON0 &= 0xef; // disable receiver
@@ -190,7 +217,7 @@ void Serial0Init (unsigned long baud, unsigned char buffered) {
   
   serial0Buffered=buffered;
  
- if (buffered) {
 if (buffered) {
     RI_0=TI_0=0; // clear "pending" interrupts
     ES0 = 1; // enable serial channel 0 interrupt
   } else {
@@ -199,7 +226,8 @@ void Serial0Init (unsigned long baud, unsigned char buffered) {
   }
 }
 
-void Serial0Baud(unsigned long baud) {
+void Serial0Baud(unsigned long baud)
+{
   TR2=0; // stop timer
   baud=-((long)OSCILLATOR/(32*baud));
   TL2=RCAP2L= baud;
@@ -208,7 +236,8 @@ void Serial0Baud(unsigned long baud) {
   TR2=1; // start timer
 }  
 
-void Serial0IrqHandler (void) interrupt 4 {
+void Serial0IrqHandler (void) __interrupt 4
+{
   if (RI_0) {
     receive0Buffer[receive0BufferHead]=SBUF0;
     receive0BufferHead=(receive0BufferHead+1)&(S0RBS-1);
@@ -224,7 +253,8 @@ void Serial0IrqHandler (void) interrupt 4 {
   }
 }
 
-char Serial0CharArrived(void) {
+char Serial0CharArrived(void)
+{
   if (serial0Buffered) {
     if (receive0BufferHead!=receive0BufferTail)
       return receive0Buffer[receive0BufferTail];
@@ -269,13 +299,15 @@ char Serial0GetChar (void)
   return c;
 }
 
-void Serial0SendBreak() {
+void Serial0SendBreak()
+{
   P3 &= ~0x02;
   ClockMilliSecondsDelay(2);
   P3 |= 0x02;
 }
 
-void Serial0Flush() {
+void Serial0Flush()
+{
   ES0=0; // disable interrupts
   receive0BufferHead=receive0BufferTail=0;
   RI_0=0;
@@ -301,7 +333,7 @@ static volatile int receive1BufferTail=0;
 // no buffering for transmit
 static volatile char transmit1IsBusy=0;
 
-static data unsigned char serial1Buffered;
+static __data unsigned char serial1Buffered;
 
 /* Initialize serial1.
 
@@ -311,11 +343,12 @@ static data unsigned char serial1Buffered;
    If buffered!=0, characters received are buffered using an interrupt
 */
 
-void Serial1Init (unsigned long baud, unsigned char buffered) {
-  
-  if (baud=0) {
+void Serial1Init (unsigned long baud, unsigned char buffered)
+{
+  if (baud==0) {
     ES1=0; // disable interrupt
     SCON1 &= 0xef; // disable receiver
+    return; // and don't touch it
   }
 
   ES1 = 0; // disable channel 1 interrupt
@@ -333,7 +366,7 @@ void Serial1Init (unsigned long baud, unsigned char buffered) {
   // set the baud rate
   Serial1Baud(baud);
   
-  serial0Buffered=buffered;
+  serial1Buffered=buffered;
 
   if (buffered) {
     RI_1=TI_1=0; // clear "pending" interrupts
@@ -344,7 +377,8 @@ void Serial1Init (unsigned long baud, unsigned char buffered) {
   }
 }
 
-void Serial1Baud(unsigned long baud) {
+void Serial1Baud(unsigned long baud)
+{
   TR1=0; // stop timer
   baud=-((long)OSCILLATOR/(32*baud));
   TL1=TH1 = baud;
@@ -352,7 +386,8 @@ void Serial1Baud(unsigned long baud) {
   TR1=1; // start timer
 }  
 
-void Serial1IrqHandler (void) interrupt 7 {
+void Serial1IrqHandler (void) __interrupt 7
+{
   if (RI_1) {
     receive1Buffer[receive1BufferHead]=SBUF1;
     receive1BufferHead=(receive1BufferHead+1)&(S1RBS-1);
@@ -366,7 +401,8 @@ void Serial1IrqHandler (void) interrupt 7 {
   }
 }
 
-char Serial1CharArrived(void) {
+char Serial1CharArrived(void)
+{
   if (serial1Buffered) {
     if (receive1BufferHead!=receive1BufferTail)
       return receive1Buffer[receive1BufferTail];
@@ -411,13 +447,15 @@ char Serial1GetChar (void)
   return c;
 }
 
-void Serial1SendBreak() {
+void Serial1SendBreak()
+{
   P5 &= ~0x08;
   ClockMilliSecondsDelay(2);
   P5 |= 0x08;
 }
 
-void Serial1Flush() {
+void Serial1Flush()
+{
   ES1=0; // disable interrupts
   receive1BufferHead=receive1BufferTail=0;
   RI_1=0;
@@ -431,12 +469,12 @@ void Serial1Flush() {
 
 // now let's go for the clock stuff
 
-//#define TIMER_0_RELOAD_VALUE 18432000L/2/1000 // appr. 1ms
+// these REALLY need to be in data space for the irq routine!
+static __data unsigned long milliSeconds=0;
+static __data unsigned int timer0ReloadValue;
 
-static data unsigned long milliSeconds=0;
-static data unsigned int timer0ReloadValue;
-
-void ClockInit() {
+void ClockInit()
+{
   unsigned long timerReloadValue=OSCILLATOR/1000;
 
   switch (cpuSpeed) {
@@ -445,30 +483,57 @@ void ClockInit() {
   case 2:  // not tested yet
   default: timerReloadValue/=2; break;
   }
-  timer0ReloadValue=timerReloadValue;
+  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|=0x80; // timer uses xtal/4
+  CKCON|=0x08; // timer uses xtal/4
   
-  TL0=~(timer0ReloadValue&0xff);
-  TH0=~(timer0ReloadValue>>8);
+  TL0=timer0ReloadValue&0xff;
+  TH0=timer0ReloadValue>>8;
   
   ET0=1; // enable timer interrupts
   TR0=1; // start timer
 }
 
-void ClockIrqHandler (void) interrupt 1 {
-  // we have lost some time here
-  TL0=~(timer0ReloadValue&0xff);
-  TH0=~(timer0ReloadValue>>8);
+// 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++;
-  // that's all for now :)
 }
+#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;
+}
+#endif
 
 // we can't just use milliSeconds
-unsigned long ClockTicks(void) {
+unsigned long ClockTicks(void)
+{
   unsigned long ms;
   ET0=0;
   ms=milliSeconds;
@@ -476,7 +541,8 @@ unsigned long ClockTicks(void) {
   return ms;
 }
 
-void ClockMilliSecondsDelay(unsigned long delay) {
+void ClockMilliSecondsDelay(unsigned long delay)
+{
   long ms=ClockTicks()+delay;
 
   while (ms>ClockTicks())
@@ -484,38 +550,38 @@ void ClockMilliSecondsDelay(unsigned long delay) {
 }
 
 // stolen from Kevin Vigor, works only for TINI at default speed
-void ClockMicroSecondsDelay(unsigned int delay) {
-   delay; /* shut compiler up. */
+void ClockMicroSecondsDelay(unsigned int delay)
+{
+  delay; /* shut compiler up. */
    
-   _asm
+  __asm
      
-   ; delay is in dpl/dph
-   mov r0, dpl
-   mov  r1, dph
-   
-   mov a, r0
-   orl  a, r1                  ; quick out for zero case.
-   jz   _usDelayDone
+    ; delay is in dpl/dph
+    mov        r0, dpl
+    mov  r1, dph
+
+    mov        a, r0
+    orl  a, r1                 ; quick out for zero case.
+    jz   _usDelayDone
    
-   inc r1
-   cjne r0, #0, _usDelayLoop
-   dec  r1
+    inc        r1
+    cjne r0, #0, _usDelayLoop
+    dec  r1
    
-   _usDelayLoop:
-   nop
-   nop
-   nop
-   nop
-   nop
-   nop
-   nop                         ; 7 nops
-   djnz r0, _usDelayLoop       ; 3 cycles x 1 = 3 cycles
-                               ; 10 cycles per iter
+  _usDelayLoop:
+    nop
+    nop
+    nop
+    nop
+    nop
+    nop
+    nop                                ; 7 nops
+    djnz r0, _usDelayLoop      ; 3 cycles x 1 = 3 cycles
+                               ; 10 cycles per iter
                                ; we want 9.216, but more is better
-                               ; than less.
-   djnz r1, _usDelayLoop       
-_usDelayDone:
+                               ; than less.
+    djnz r1, _usDelayLoop      
+  _usDelayDone:
    
-   _endasm;
-  
+  __endasm;
 }