Replacement for buggy startup source
[fw/sdcc] / device / examples / startupcode / src / cpu_c515a.c
diff --git a/device/examples/startupcode/src/cpu_c515a.c b/device/examples/startupcode/src/cpu_c515a.c
new file mode 100644 (file)
index 0000000..6333a4f
--- /dev/null
@@ -0,0 +1,589 @@
+/********************************************************************/
+/* Function    : Siemens CPU C515A-L24M dependinge Functions   FILE */
+/*------------------------------------------------------------------*/
+/* Description : All CPU dependig functions like UART fe. are       */
+/*               are initialized here                               */
+/*------------------------------------------------------------------*/
+/* Author      : Michael Schmitt                                    */
+/*------------------------------------------------------------------*/
+/* Input       : none                                               */
+/*------------------------------------------------------------------*/
+/* Returnvalue : none                                               */
+/*------------------------------------------------------------------*/
+/* History     : 00/03    V1.0 Initial Version                      */
+/*                                                                  */
+/********************************************************************/
+#ifndef __FILE_CPU_C515A
+#define __FILE_CPU_C515A
+
+// All that has to be included and / or defined is done here
+
+#include "../inc/hardware_describtion.h"
+
+// END INCLUDES & DEFINES ===========================================
+
+/********************************************************************/
+/* Function    : CpuIdle()                                      SUB */
+/*------------------------------------------------------------------*/
+/* Description : If no CPU Power is need, we put into idle mode     */
+/*------------------------------------------------------------------*/
+/* Author      : Michael Schmitt                                    */
+/*------------------------------------------------------------------*/
+/* Input       : none                                               */
+/*------------------------------------------------------------------*/
+/* Returnvalue : none                                               */
+/*------------------------------------------------------------------*/
+/* History     : 00/03    V1.0 Initial Version                      */
+/*                                                                  */
+/********************************************************************/
+
+void CpuIdle()
+{
+    // The Siemens Manual says, that we have to wait until the AD-Conversion
+    // is completed before we put the cpu into idle mode
+
+    // wait until AD-Conversion is finished
+    while( BSY )
+    {
+        //
+    }
+
+
+    CPUIDLE = 1;
+#ifdef USE_SYSTEM_TIMER
+    PCON |= 0x01; // IDL-Bit in register PCON starts IDLE Mode
+    PCON |= 0x20; //
+#else
+    // If there is no regular INT source, we better do not use
+    // the IDLE Mode
+    NOP;
+#endif
+    CPUIDLE = 0;
+}
+
+/********************************************************************/
+/* Function    : WatchDog()                                     SUB */
+/*------------------------------------------------------------------*/
+/* Description : Internal (and external) Watchdogs trigger          */
+/*------------------------------------------------------------------*/
+/* Author      : Michael Schmitt                                    */
+/*------------------------------------------------------------------*/
+/* Input       : none                                               */
+/*------------------------------------------------------------------*/
+/* Returnvalue : none                                               */
+/*------------------------------------------------------------------*/
+/* History     : 00/03    V1.0 Initial Version                      */
+/*                                                                  */
+/********************************************************************/
+
+void WatchDog( void )
+{
+    //NOP;
+    // retrigger Externer Watchdog
+    // Interner Watchdog not yet implemented
+}
+
+
+// ===========================================================================
+// Serial IO with the internal UART in Interrupt Mode
+#ifdef SERIAL_VIA_INTERRUPT
+
+#define SERIAL_IS_DEFINED
+
+// Transmit Buffersize
+#ifndef SERIAL_VIA_INTERRUPT_XBUFLEN
+#error "SERIAL_VIA_INTERRUPT_XBUFLEN not defined using default size 8"
+#define SERIAL_VIA_INTERRUPT_XBUFLEN 8
+#endif
+
+// Receive Buffersize
+#ifndef SERIAL_VIA_INTERRUPT_RBUFLEN
+#error "SERIAL_VIA_INTERRUPT_RBUFLEN not defined using default size 8"
+#define SERIAL_VIA_INTERRUPT_RBUFLEN 8
+#endif
+
+// in interrupt mode the ing buffer is placed in XDATA memory
+volatile xdata static unsigned char SERIAL_VIA_INTERRUPT_RBUF[SERIAL_VIA_INTERRUPT_RBUFLEN];
+volatile xdata static unsigned char SERIAL_VIA_INTERRUPT_XBUF[SERIAL_VIA_INTERRUPT_XBUFLEN];
+volatile xdata static unsigned char SERIAL_VIA_INTERRUPT_RCNT;
+volatile xdata static unsigned char SERIAL_VIA_INTERRUPT_XCNT;
+volatile xdata static unsigned char SERIAL_VIA_INTERRUPT_RPOS;
+volatile xdata static unsigned char SERIAL_VIA_INTERRUPT_XPOS;
+volatile xdata static unsigned char SERIAL_VIA_INTERRUPT_BUSY;
+
+#endif // SERIAL_VIA_INTERRUPT
+
+// ===========================================================================
+// Serial IO with them internal UART in Polling Mode
+#ifdef SERIAL_VIA_POLLING
+#define SERIAL_IS_DEFINED
+#endif // SERIAL_VIA_POLLING
+
+#ifdef SERIAL_IS_DEFINED
+// calculate the reloadvalues acc. to the definitions
+#ifndef CPUCLKHZ
+#error "CPUCLKHZ not defined !"
+#endif
+#ifndef BAUDRATE
+#error "BAUDRATE not defined !"
+#endif
+// The Siemens CPU C515A has a build in Baudrategenerator, therefore we use it instead
+// of timer 1 this gives a better resolution
+#define BAUDRATEGENENATOR_USED
+#define BAUDRATEGENRELOADVALUE (1024-(2*CPUCLKHZ/64/BAUDRATE))
+#define TIMER1MODE2RELOADVALUE  (256-(2*CPUCLKHZ/32/12/BAUDRATE))
+
+#endif // SERIAL_IS_DEFINED
+
+// ===========================================================================
+// now to the serial functions
+#ifdef SERIAL_VIA_INTERRUPT
+/********************************************************************/
+/* Function    : SERIAL_VIA_INTERRUPT()                         ISR */
+/*------------------------------------------------------------------*/
+/* Description : If a serial INT occours, the sub function is called*/
+/*               if a char is not yet transmitted, it is stored in  */
+/*               the uart and transmitted, if a char has been       */
+/*               received, it will be placed in the rx-buffer
+/*------------------------------------------------------------------*/
+/* Author      : Michael Schmitt                                    */
+/*------------------------------------------------------------------*/
+/* Input       : none                                               */
+/*------------------------------------------------------------------*/
+/* Returnvalue : none                                               */
+/*------------------------------------------------------------------*/
+/* History     : 00/03    V1.0 Initial Version                      */
+/*                                                                  */
+/********************************************************************/
+void SERIALVIAINTERRUPT (void) interrupt SI0_VECTOR
+{
+    if (RI)
+    {
+        RI = 0;
+        // char that are already inside the buffer should not be overwritten
+        if (SERIAL_VIA_INTERRUPT_RCNT < SERIAL_VIA_INTERRUPT_RBUFLEN)
+        {
+            SERIAL_VIA_INTERRUPT_RBUF [(SERIAL_VIA_INTERRUPT_RPOS+SERIAL_VIA_INTERRUPT_RCNT++) % SERIAL_VIA_INTERRUPT_RBUFLEN] = SBUF;
+        }
+   }
+   if (TI)
+   {
+       TI = 0;
+       if (SERIAL_VIA_INTERRUPT_BUSY = SERIAL_VIA_INTERRUPT_XCNT)
+       {   /* Assignment, _not_ comparison! */
+           SERIAL_VIA_INTERRUPT_XCNT--;
+           SBUF = SERIAL_VIA_INTERRUPT_XBUF [SERIAL_VIA_INTERRUPT_XPOS++];
+           if (SERIAL_VIA_INTERRUPT_XPOS >= SERIAL_VIA_INTERRUPT_XBUFLEN)
+           {
+               SERIAL_VIA_INTERRUPT_XPOS = 0;
+           }
+       }
+   }
+}
+
+/********************************************************************/
+/* Function    : putchar()                                      SUB */
+/*------------------------------------------------------------------*/
+/* Description : everybody knows what this function is doing        */
+/*------------------------------------------------------------------*/
+/* Author      : Michael Schmitt                                    */
+/*------------------------------------------------------------------*/
+/* Input       : char Byte                                          */
+/*------------------------------------------------------------------*/
+/* Returnvalue : none                                               */
+/*------------------------------------------------------------------*/
+/* History     : 00/03    V1.0 Initial Version                      */
+/*                                                                  */
+/********************************************************************/
+void putchar(  char Byte )
+{
+    while (SERIAL_VIA_INTERRUPT_XCNT >= SERIAL_VIA_INTERRUPT_XBUFLEN)
+    {
+        // buffer is full, wait until room
+        WatchDog();
+        CpuIdle();
+    }
+    ES = 0;
+
+    if (SERIAL_VIA_INTERRUPT_BUSY)
+    {
+        SERIAL_VIA_INTERRUPT_XBUF[(SERIAL_VIA_INTERRUPT_XPOS+SERIAL_VIA_INTERRUPT_XCNT++) % SERIAL_VIA_INTERRUPT_XBUFLEN] = Byte;
+    }
+    else
+    {
+        SBUF = Byte;
+        SERIAL_VIA_INTERRUPT_BUSY = 1;
+    }
+    ES = 1;
+}
+
+/********************************************************************/
+/* Function    : getchar()                                      SUB */
+/*------------------------------------------------------------------*/
+/* Description : everybody knows what this function is doing        */
+/*------------------------------------------------------------------*/
+/* Author      : Michael Schmitt                                    */
+/*------------------------------------------------------------------*/
+/* Input       : none                                               */
+/*------------------------------------------------------------------*/
+/* Returnvalue : char Byte                                          */
+/*------------------------------------------------------------------*/
+/* History     : 00/03    V1.0 Initial Version                      */
+/*                                                                  */
+/********************************************************************/
+unsigned char getchar( void )
+{
+    unsigned char c;
+    while (!SERIAL_VIA_INTERRUPT_RCNT)
+    {
+        // no char avail, so wait
+        WatchDog();
+        CpuIdle();
+    }
+    ES = 0;
+    SERIAL_VIA_INTERRUPT_RCNT--;
+    c = SERIAL_VIA_INTERRUPT_RBUF [SERIAL_VIA_INTERRUPT_RPOS++];
+    if (SERIAL_VIA_INTERRUPT_RPOS >= SERIAL_VIA_INTERRUPT_RBUFLEN)
+    {
+        SERIAL_VIA_INTERRUPT_RPOS = 0;
+
+    }
+    ES = 1;
+    return (c);
+}
+
+/********************************************************************/
+/* Function    : keypressed()                                   SUB */
+/*------------------------------------------------------------------*/
+/* Description : checks, if a char is available                     */
+/*------------------------------------------------------------------*/
+/* Author      : Michael Schmitt                                    */
+/*------------------------------------------------------------------*/
+/* Input       : none                                               */
+/*------------------------------------------------------------------*/
+/* Returnvalue : TRUE yes, FALSE no                                 */
+/*------------------------------------------------------------------*/
+/* History     : 00/03    V1.0 Initial Version                      */
+/*                                                                  */
+/********************************************************************/
+unsigned char keypressed( void )
+{
+    unsigned char c;
+
+    if(SERIAL_VIA_INTERRUPT_RCNT)
+    {
+        c = TRUE;
+    }
+    else
+    {
+        c = FALSE;
+    }
+    return (c);
+}
+
+#endif
+
+// ===========================================================================
+// Now the Internal UART Handling if Polling Method is used
+#ifdef SERIAL_VIA_POLLING
+/********************************************************************/
+/* Function    : putchar()                                      SUB */
+/*------------------------------------------------------------------*/
+/* Description : everybody knows what this function is doing        */
+/*------------------------------------------------------------------*/
+/* Author      : Michael Schmitt                                    */
+/*------------------------------------------------------------------*/
+/* Input       : char Byte                                          */
+/*------------------------------------------------------------------*/
+/* Returnvalue : none                                               */
+/*------------------------------------------------------------------*/
+/* History     : 00/03    V1.0 Initial Version                      */
+/*                                                                  */
+/********************************************************************/
+void putchar(  char Byte )
+{
+    while( !TI ) /* wait for TI==1 */
+    {
+        WatchDog();
+        CpuIdle();
+    }
+    SBUF = Byte;
+    TI = 0;
+}
+
+/********************************************************************/
+/* Function    : getchar()                                      SUB */
+/*------------------------------------------------------------------*/
+/* Description : everybody knows what this function is doing        */
+/*------------------------------------------------------------------*/
+/* Author      : Michael Schmitt                                    */
+/*------------------------------------------------------------------*/
+/* Input       : none                                               */
+/*------------------------------------------------------------------*/
+/* Returnvalue : char Byte                                          */
+/*------------------------------------------------------------------*/
+/* History     : 00/03    V1.0 Initial Version                      */
+/*                                                                  */
+/********************************************************************/
+unsigned char getchar( void )
+{
+    while( !RI ) /* wait for RI==1 */
+    {
+        WatchDog();
+        CpuIdle();
+    }
+    RI=0;
+    return (SBUF);
+}
+
+/********************************************************************/
+/* Function    : keypressed()                                   SUB */
+/*------------------------------------------------------------------*/
+/* Description : is a char available ?                              */
+/*------------------------------------------------------------------*/
+/* Author      : Michael Schmitt                                    */
+/*------------------------------------------------------------------*/
+/* Input       : none                                               */
+/*------------------------------------------------------------------*/
+/* Returnvalue : TRUE yes, FALSE no                                 */
+/*------------------------------------------------------------------*/
+/* History     : 00/03    V1.0 Initial Version                      */
+/*                                                                  */
+/********************************************************************/
+unsigned char keypressed( void )
+{
+    unsigned char c;
+
+    if(RI)
+    {
+        c = TRUE;
+    }
+    else
+    {
+        c = FALSE;
+    }
+    return (c);
+}
+
+#endif
+
+// ===========================================================================
+// System Timer
+#ifdef USE_SYSTEM_TIMER
+
+volatile unsigned long SystemTicks1msec;
+
+// Here are the definitions of the 1kHz Timer 0
+// used for delay( xx_msec )
+#ifndef CPUCLKHZ
+#error "CPUCLKHZ is not defined !"
+#endif
+
+#define TIMER0INTSPERSECOND     1000
+#define TIMER0MODE1RELOADVALUE  (-((CPUCLKHZ/TIMER0INTSPERSECOND)/12))
+
+/********************************************************************/
+/* Function    : delayMsec()                                    SUB */
+/*------------------------------------------------------------------*/
+/* Description : waste some CPU-Time, CPU will be set into IDLE Mode*/
+/*               and is waked up every 1msec by TIMER0              */
+/*------------------------------------------------------------------*/
+/* Author      : Michael Schmitt                                    */
+/*------------------------------------------------------------------*/
+/* Input       : unsigned long delayTime                            */
+/*------------------------------------------------------------------*/
+/* Returnvalue : none                                               */
+/*------------------------------------------------------------------*/
+/* History     : 99/10    V1.0 Initial Version                      */
+/*                                                                  */
+/********************************************************************/
+void DelayMsec( unsigned long delayTime )
+{
+    delayTime += SystemTicks1msec;
+    WatchDog();
+    while( SystemTicks1msec < delayTime )
+    {
+        CpuIdle();
+        WatchDog();
+    }
+    WatchDog();
+}
+
+/********************************************************************/
+/* Function    : timer0_isr                                     ISR */
+/*------------------------------------------------------------------*/
+/* Description : This ISR is called every 1msec and inc. a variable */
+/*               that is used for delay()                           */
+/*------------------------------------------------------------------*/
+/* Author      : Michael Schmitt                                    */
+/*------------------------------------------------------------------*/
+/* Input       : none                                               */
+/*------------------------------------------------------------------*/
+/* Returnvalue : none                                               */
+/*------------------------------------------------------------------*/
+/* History     : 99/10    V1.0 Initial Version                      */
+/*                                                                  */
+/********************************************************************/
+void timer0_isr (void) interrupt TF0_VECTOR
+{
+    /* Interruptrate will be slightly slower than wanted */
+    /* because TL0 is not 0 here, not bug-fix yet */
+    TL0 = (TIMER0MODE1RELOADVALUE & 0x00FF);
+    TH0 = (TIMER0MODE1RELOADVALUE >> 8);
+    SystemTicks1msec++;
+}
+#endif // USE_SYSTEM_TIMER
+
+// ===========================================================================
+// Analog Stuff
+#ifdef USE_ANALOGPORT
+
+unsigned int ADCGetValue( char ADCPort )
+{
+    // if a conversion is busy, wait
+    while( BSY )
+    {
+        //
+    }
+    WatchDog();
+
+    // set AD-Port
+    ADCON1 &= 0xF8;             // clear MX0 to MX2
+    ADCON1 |= (ADCPort & 0x07); // set Port
+
+    // start AD Conversion
+    ADDATL = 0x00;
+
+    while( BSY )
+    {
+        //
+    }
+    WatchDog();
+
+    // read AD Converter Register
+    return( (((unsigned int)ADDATH) << 2) + ((unsigned int)ADDATL >> 6) );
+}
+#endif
+
+// ===========================================================================
+
+// ===================================================================
+// Global Hardware Init
+/********************************************************************/
+/* Function    : InitHardware()                                 SUB */
+/*------------------------------------------------------------------*/
+/* Description : Should be the first executed after reset to get a  */
+/*               proper initalised CPU                              */
+/*------------------------------------------------------------------*/
+/* Author      : Michael Schmitt                                    */
+/*------------------------------------------------------------------*/
+/* Input       : none                                               */
+/*------------------------------------------------------------------*/
+/* Returnvalue : none                                               */
+/*------------------------------------------------------------------*/
+/* History     : 99/10    V1.0 Initial Version                      */
+/*                                                                  */
+/********************************************************************/
+void InitHardware( void )
+{
+#ifdef USE_SYSTEM_TIMER
+    SystemTicks1msec = 0x0;
+#endif // USE_SYSTEM_TIMER
+
+    EA = 0;         // Disable ALL Ints
+    ES = 0;         // Disable Serial Int
+    ET1 = 0;        // Disable Timer 1 Int
+    EX1 = 0;        // Disable External Interrupt 1
+    ET0 = 0;        // Disable Timer 0 Int
+    EX0 = 0;        // Disable External Interrupt 0
+    EADC = 0;       // Disable A/D Converter Interrupt
+
+    TR1 = 0;        // Stop Timer 1
+    TR0 = 0;        // Stop Timer 0
+
+    // The Siemens CPU C515A has 8 Analog inputs with 10Bit resolution
+    // Conversion Clock is generated from CPU-Clock but should be less
+    // than max 2MHZ.
+    if( CPUCLKHZ < 16000000 )
+    {
+        // CPU Speed < 16MHz Prescaler Ratio is divide by 4 (Reset default)
+        ADCON1 &= ~ADCON1_ADCL;
+        // the automatic A/D Converter Calibration needs
+        // Reset Calibration phase = 26624 / CPUCLKHZ
+        // @ 16MHz this is about 1,7msec
+        // or 2219 machine cycle
+    }
+    else
+    {
+        // CPU Speed > 16MHz Prescaler Ratio is divide by 4 (Reset default)
+        ADCON1 |= ADCON1_ADCL;
+        // the automatic A/D Converter Calibration needs
+        // Reset Calibration phase = 53248 / CPUCLKHZ
+        // @ 246MHz this is about 2,3msec
+        // or 4438 machine cycle
+    }
+
+
+    // AD-Conversion stars intern and not with P40 ADST#
+    ADCON0 &= ~ADCON0_ADM;
+
+#ifdef USE_SYSTEM_TIMER
+    // Init Timer 0 as Software Interrupt for 1mSec Timer
+    TL0 = (TIMER0MODE1RELOADVALUE & 0x00FF);
+    TH0 = (TIMER0MODE1RELOADVALUE >> 8);
+    TMOD &= 0xf0;
+    TMOD |= 0x01;       // Setting Timer 0 als GATE=0 TIMER und MODE 1 16-bit Timer mode
+    TR0  = 1;           // Enabling Timer 0
+    TR0 = 1;            // Start Timer 0
+    ET0 = 1;            // Enable Timer 0 Interrupt
+#endif
+
+#ifdef SERIAL_VIA_INTERRUPT
+    // Ringbuffer for Serielle UART  init
+    SERIAL_VIA_INTERRUPT_RCNT = 0;
+    SERIAL_VIA_INTERRUPT_XCNT = 0;
+    SERIAL_VIA_INTERRUPT_RPOS = 0;
+    SERIAL_VIA_INTERRUPT_XPOS = 0;
+    SERIAL_VIA_INTERRUPT_BUSY = 0;
+#endif
+
+#ifdef SERIAL_IS_DEFINED
+#ifdef BAUDRATEGENENATOR_USED
+
+    // We use the internal Bauratengenerator of the Siemens CPU
+    SRELL = (BAUDRATEGENRELOADVALUE & 0x00FF);
+    SRELH = (BAUDRATEGENRELOADVALUE >> 8);
+    ADCON0 |= 0x80; // set BD-Bit, we use internal Baudrate gen.
+    PCON |= 0x80;   // SMOD-Bit forr double Baudrate
+
+#else
+
+    // use TIMER1 im Mode 2
+    PCON |= 0x80;   // set SMOD-Bit for double Baudrate
+    TH1 = TIMER1MODE2RELOADVALUE;
+    TL1 = TIMER1MODE2RELOADVALUE;
+    TMOD &= 0x0f;
+    TMOD |= 0x20;   // Timer 1 als GATE=0 TIMER und MODE 2 8-bit auto reload
+    TR1  = 1;       // Enabling Timer 1
+
+#endif
+
+    SCON  = 0x40;       // Init Serial Port as 8-Bit UART
+    SCON |= 0x10;       // Enabling Seriel receive REN-Bit
+    SCON |= 0x02;       // Setting TI-Bit
+
+#ifdef SERIAL_VIA_INTERRUPT
+        ES = 1;         // Enable Serial Interrupt
+#endif
+
+#endif
+
+#ifdef USE_CPU_Internal_XRAM
+    // CPU Internal SRAM einable
+    SYSCON = ((SYSCON) & ((UBYTE)~(XMAP0_BIT | XMAP1_BIT)));
+#endif
+
+    EA = 1;             // Enable all Enabled Interrupts
+}
+
+#endif