Sunday, July 5, 2015

Phase 1: core

/*
 **********************************************************************
 *name:         IE_EGWU_IVT.S
 *author:       Samuel Igwe
 *date:         06/30/2015
 *description:  Igbo Embedded EGWU_IVT.S source
 *              the interrupt vector table starts with the initial 
 *              stack address followed by the addresses of the function
 *              and ISR's. just allocate the space - leave it vacant
 *note:  this must be linked in first when building the .out file
 *              since i plan on remmapping VTOR to point to the IVT at
 *  the start of SRAM memory
 **********************************************************************
 */


#ifndef IE_EGWU_IVT_H

.global EGWU_IVT
.global EGWU_IVT_END
.extern main
.equ LPC177X_SRAM_BASE, 0x10000000
.equ    LPC177X_NUM_INT  , 40
.data
.align 4
EGWU_IVT:       .word   LPC177X_SRAM_BASE + (64 * 1024)
                .word   (main + 1)
                .skip   (14 * 4)
                .skip   (LPC177X_NUM_INT * 4)
EGWU_IVT_END:
#endif

 
 
 
 
/*
 ****************************************************************************
 *name:         IE_egwu_setup.h
 *author:       Samuel Igwe
 *date:         06/30/2015
 *description:  pll/clock/iopin initialization
 ****************************************************************************
 */
#ifndef IE_EGWU_SETUP_H
    #define     LPC177X_NUM_INT                 40
    #define     EGWU_CPU_CLK_RATE               120000000
    #define     EGWU_CPU_OSC_RATE               24000000
    #define     EGWU_SYSTICK_RATE               (EGWU_CPU_CLK_RATE/1000)

    #define     LPC177X_SRAM_BASE               0x10000000


    #define     LPC_BILED_PORT                  1
    #define     LPC_BILED_PIN1                  23
    #define     LPC_BILED_PIN2                  24

    #define     LPC_LED_PORT                    1
    #define     LPC_LED_PIN                     8

    #define     EGWU_NVIC_USER_BILED_MASK       0x1
    #define     EGWU_NVIC_FAULT_BILED_MASK      0x2



    #include "chip.h"
    #include "chip_lpc177x_8x.h"


    struct      STR_EGWU_SYSTICK        {
        volatile unsigned int wdSeconds;
        volatile unsigned int wdTicks;
        }strSysTick;

    

    #define     EGWU_UART_BUFFER_SIZE           64
    struct      STR_EGWU_UART           {
        volatile unsigned int  wdMutex;
        volatile unsigned int  wdCount;
        volatile unsigned int  wdIndex;
        volatile unsigned char sbBuf[EGWU_UART_BUFFER_SIZE];
        }strUart;

 
    extern      int     EGWU_IVT;
    const       uint32_t OscRateIn;


    void        egwu_setup_pll(void);
    void        egwu_setup_nvic(void);
    void        egwu_setup_gpio(void);
    void        egwu_setup_uart(void);

    void        egwu_nvic_systick_isr(void);
    void        egwu_nvic_fault_isr(void);
    void        egwu_nvic_user_isr(void);

    void        egwu_set_lpc_biled(unsigned int wdLedMask);

#endif
 
 
 
 
 
/*
 ****************************************************************************
 *name:         IE_egwu_setup.c
 *author:       Samuel Igwe
 *date:         06/30/2015
 *description:  pll/clock/iopin/nvic initialization
 ****************************************************************************
 */
#ifndef IE_EGWU_SETUP_C
#include "IE_egwu_setup.h"





/*
 ****************************************************************************
 *description:  pll/clock.
 *inputs:       none
 *note:         main pll (0)        m=5        p=1    
 *                              pllin=24  pllout=120  fcco=240  
 *               alt pll (1)        m=2        p=2
 *                              pllin=24  pllout48    fcco=192
 *
 *              the condition pllin  = 1 < 25Mhz and fcco = 156 -> 320 has 
 *              has been satisfied
 *              cpu = 120Mhz
 *              emc =  60Mhz
 *              gpio=  40Mhz
 *
 *              when using the internal oscillator aim for 120Mhz as well
 *              main pll (0)        m=10       p=1
 *                              pllin=12  pllout=120  fcco=240
 ****************************************************************************
 */
void
egwu_setup_pll(void)
{
    /*
     ************************************************************************
     *switch to using default clock source
     ************************************************************************
     */
    Chip_Clock_SetMainPLLSource(SYSCTL_PLLCLKSRC_IRC);
    Chip_Clock_SetCPUClockSource(SYSCTL_CCLKSRC_SYSCLK);
    Chip_Clock_DisablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_ENABLE);
    Chip_Clock_DisablePLL(SYSCTL_USB_PLL,  SYSCTL_PLL_ENABLE);


    /*
     ************************************************************************
     *use the internal rc clock for phase 1 and 2, while await replacement
     *caps for the crystal oscillator driver
     ************************************************************************
     */
#ifdef  EXT_CLK
    Chip_Clock_SetCrystalRangeHi();
    Chip_Clock_EnableCrystal();

    if((Chip_Clock_IsCrystalEnabled()) == TRUE)
        Chip_Clock_SetCPUClockSource(SYSCTL_CCLKSRC_MAINPLL);

    Chip_Clock_SetupPLL(SYSCTL_MAIN_PLL, 5, 1);
    Chip_Clock_SetupPLL(SYSCTL_USB_PLL,  2, 2);

    Chip_Clock_EnablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_ENABLE);
    Chip_Clock_EnablePLL(SYSCTL_USB_PLL,  SYSCTL_PLL_ENABLE);
#else
    Chip_Clock_SetupPLL(SYSCTL_MAIN_PLL, 10, 1);
    Chip_Clock_EnablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_ENABLE);
#endif


    /*
     ************************************************************************
     *delay a bit to let the logic do its thing
     ************************************************************************
     */
    while(Chip_Clock_IsMainPLLLocked() == 0)
        ;

#ifdef  EXT_CLK
    Chip_Clock_SetMainPLLSource(SYSCTL_PLLCLKSRC_MAINOSC);
    while(Chip_Clock_IsUSBPLLLocked() == 0)
        ;
#endif


    /*
     ************************************************************************
     *resume initialization
     ************************************************************************
     */
    Chip_Clock_SetCPUClockDiv(1);
    Chip_Clock_SetCPUClockSource(SYSCTL_CCLKSRC_MAINPLL);

#ifdef  EXT_CLK
    Chip_Clock_SetUSBClockDiv(1);
    Chip_Clock_SetUSBClockSource(SYSCTL_USBCLKSRC_USBPLL);
    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_USB);
#endif

    Chip_Clock_SetPCLKDiv(3);


    /*
     ************************************************************************
     *enable all the peripherals
     ************************************************************************
     */
    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_TIMER0);
    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_TIMER1);

    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_UART0);
    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_UART1);

    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_RTC);

    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_EMC);

    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_I2C0);
    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_I2C1);
    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_I2C2);

    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SSP0);
    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SSP1);

    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_USB);

    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_GPDMA);

    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_GPIO);


    /*
     ************************************************************************
     *enable emc and clkout
     ************************************************************************
     */
    Chip_Clock_SetEMCClockDiv(SYSCTL_EMC_DIV2); 
    Chip_Clock_SetCLKOUTSource(SYSCTL_CLKOUTSRC_MAINOSC, 3);
    Chip_Clock_EnableCLKOUT();
}





/*
 ****************************************************************************
 *description:  configure nvic
 *inputs:       none
 *notes:        assume vector table is the global "egwu_ivt"
 *              skip stack and reset positions
 *              default isrs
 *              egwu_nvic_fault_isr()
 *              egwu_nvic_systic_isr()
 *              egwu_nvic_user_isr()
 ****************************************************************************
 */
void
egwu_setup_nvic(void)
{
    volatile unsigned int wdTemp, *ptrTemp, wdCount;


    ptrTemp = (volatile unsigned int *)&EGWU_IVT;
    for(wdCount = 2; wdCount < (LPC177X_NUM_INT + 16); wdCount++)
        {
        if(wdCount < 15)                        /*faults*/
                wdTemp  = (int) egwu_nvic_fault_isr;
        else
                {
                if(wdCount == 15)               /*systick*/
                        wdTemp  = (int) egwu_nvic_systick_isr;
                else
                        wdTemp  = (int) egwu_nvic_user_isr;
                }

        
        wdTemp |= 1;                            /*thumb*/
        *(ptrTemp + wdCount) = wdTemp;
        }


    /*
     ************************************************************************
     *selecting nvic priority group 1  (there are 32 pre-rempt priority 
     *levels on the lpc17xx)
     *[7:3]     = preempt priority field (5 bits)
     *[2:0] = sub priority field         (3 bits)
     *
     *this allows me to allocate 32 interrupt priority levels thought I doubt
     *Id use that many interrupts in this project but one never knows
     *
     *for now set interrupts 
     *4 + 5 + 6 to priority level 0
     *11+14     to priority level 1
     *15 (timer)to priority level 2
     *interrupts 1 through 3 are fixed (reset to fault)
     ************************************************************************
     */
    NVIC_SetPriorityGrouping(1);
    for (wdCount = 4; wdCount <= 15; wdCount++)
        {
        if(wdCount <= 6)
                wdTemp = NVIC_EncodePriority(1, 0, (wdCount - 4));

        if(wdCount == 11 || wdCount == 14)
                wdTemp = NVIC_EncodePriority(1, 1, (wdCount - 11));

        if(wdCount == 15)
                wdTemp = NVIC_EncodePriority(1, 1, 0);


        NVIC_SetPriority(wdCount, wdTemp);
        }


    /*
     ************************************************************************
     *setup systick timer for 1mS tick
     *configure variables
     ************************************************************************
     */
    SysTick_Config(EGWU_CPU_CLK_RATE/1000);
    strSysTick.wdSeconds = 0;
    strSysTick.wdTicks   = 0;
    NVIC_EnableIRQ(15);


    /*
     ************************************************************************
     *cpu synchronization
     ************************************************************************
     */
    asm("dsb");
    asm("isb");


    /*
     ************************************************************************
     *enable mem/bus/usage fault interrupts
     ************************************************************************
     */
    wdTemp  = SCB_SHCSR_MEMFAULTENA_Msk;
    wdTemp |= SCB_SHCSR_BUSFAULTENA_Msk;
    wdTemp |= SCB_SHCSR_USGFAULTENA_Msk;
    SCB->SHCSR = wdTemp;


    /*
     ************************************************************************
     *remap vector table
     *enable interrupts on the processor level
     ************************************************************************
     */
    SCB->VTOR = LPC177X_SRAM_BASE;
    asm("cpsie i");
}





/*
 ****************************************************************************
 *description:  gpio configuration
 *inputs:       none
 *note:         mapping is as follows
 *              p0[00] - p0[01] =       fx4     =uart0
 *              p0[02] - p0[11] =       fx2     =sspi + i2c
 *              p0[12] - p0[13] =       fx1     =usb
 *              p0[15] - p0[18] =       fx2     =spi
 *              p0[23] - p0[25] =       fx1     =adc
 *              p0[26]          =       fx2     =dac
 *              p0[30]          =       fx0     =gpio1
 *              p0[31]          =       fx1     =usb
 *
 *              p1[02] - p1[10] =       fx0     =gpio
 *              p1[11] - p1[12] =       fx3     =pwm
 *              p1[14]          =       fx0     =gpio
 *              p1[18] - p1[19] =       fx0     =gpio3 and gpio4
 *              p1[23] - p1[24] =       fx0     =gpio (bi-led anode)
 *              p1[27]          =       fx4     =clkout
 *              p1[30] - p1[31] =       fx1     =usb
 *
 *              p2[00] - p[01]  =       fx1     =uart1
 *
 *              p2[10]          =       fx0     =isp_mode (dont use)
 *              p2[11]          =       fx1     =gbl_int
 *
 *              p2[14] - p2[31] =       fx1     =emc
 *
 *              p3[00] - p3[31] =       fx0     =emc
 *
 *              p4[00] - p4[31] =       fx0     =emc
 *
 *              p5[00] - p5[01] =       fx0     =emc
 ****************************************************************************
 */
void
egwu_setup_gpio(void)
{
    volatile unsigned int wdCount;


    /*
     ************************************************************************
     *port 3 and port 4 to function 1 and port 2 (14-31)
     ************************************************************************
     */
    for(wdCount = 0; wdCount < 32; wdCount++)
        {
        Chip_IOCON_PinMuxSet(LPC_IOCON, 3, wdCount, IOCON_FUNC1);
        Chip_IOCON_PinMuxSet(LPC_IOCON, 4, wdCount, IOCON_FUNC1);
        if(wdCount >= 14)
                Chip_IOCON_PinMuxSet(LPC_IOCON, 2, wdCount, IOCON_FUNC1);
        }


    /*
     ************************************************************************
     *port 0
     ************************************************************************
     */
    for(wdCount = 0; wdCount < 32; wdCount++)
        {
        if(wdCount <= 1)
                Chip_IOCON_PinMuxSet(LPC_IOCON, 0, wdCount, IOCON_FUNC4);
        else
                {
                if((wdCount >= 6  && wdCount <= 11) ||
                   (wdCount >= 15 && wdCount <= 18) ||
                   (wdCount == 26))
                        Chip_IOCON_PinMuxSet(LPC_IOCON, 0, wdCount, IOCON_FUNC2);
                else
                        {
                        if((wdCount >= 12 && wdCount <= 13) ||
                           (wdCount >= 23 && wdCount <= 25) ||
                           (wdCount == 31))
                                Chip_IOCON_PinMuxSet(LPC_IOCON, 0, wdCount, IOCON_FUNC1);
                        }
                }
        }


    /*
     ************************************************************************
     *port 1
     ************************************************************************
     */
    for(wdCount = 0; wdCount < 32; wdCount++)
        {
        if((wdCount >= 2  && wdCount <= 10) ||
           (wdCount >= 23 && wdCount <= 24) ||
           (wdCount == 14))
                Chip_IOCON_PinMuxSet(LPC_IOCON, 1, wdCount, IOCON_FUNC0);
        else
                {
                if(wdCount >= 11 &&  wdCount <= 12)
                        Chip_IOCON_PinMuxSet(LPC_IOCON, 1, wdCount, IOCON_FUNC3);
                else
                        {
                        if(wdCount  >= 30 && wdCount <= 31)
                                Chip_IOCON_PinMuxSet(LPC_IOCON, 1, wdCount, IOCON_FUNC1);
                        else
                                {
                                if(wdCount == 27)
                                        Chip_IOCON_PinMuxSet(LPC_IOCON, 1, wdCount, IOCON_FUNC4);
                                }
                        }
                }
        }


    /*
     ************************************************************************
     *port 2
     ************************************************************************
     */
    for(wdCount = 0; wdCount < 14; wdCount++)
        {
        if(wdCount <= 1)
                Chip_IOCON_PinMuxSet(LPC_IOCON, 2, wdCount, IOCON_FUNC2);
        else
                {
                if(wdCount >= 14)
                        Chip_IOCON_PinMuxSet(LPC_IOCON, 2, wdCount, IOCON_FUNC1);
                }
        }


    /*
     ************************************************************************
     *set direction for ports configured as gpio
     ************************************************************************
     */
    Chip_GPIO_SetPinDIRInput(LPC_GPIO, 0, 30);

    for(wdCount =0; wdCount < 32; wdCount++)
        {
        switch(wdCount)
                {
                case    2:
                case    5:
                case    9:
                case    10:
                case    14:
                        {
                        Chip_GPIO_SetPinDIRInput(LPC_GPIO, 1, wdCount);
                        break;
                        }
                case    3:
                case    4:
                case    6:
                case    7:
                case    8:
                case    23:
                case    24:
                        {
                        Chip_GPIO_SetPinDIROutput(LPC_GPIO, 1, wdCount);
                        break;
                        }
                }
        }
}





/*
 ****************************************************************************
 *description:  uart configuration
 *inputs:       none
 *notes:        using 40Mhz peripheral clock (cpuclock/3) to derive 115200 baud
 ****************************************************************************
 */
void
egwu_setup_uart(void)
{
    volatile unsigned int wdTemp;


    /*
     ************************************************************************
     *governing formula is as follows:
     *Uart(baudrate) =  PCLK (40Mhz)/16 x (256 x DLM) + DLL x (1 + DivVal/MulVal)
     *constraints
     *                  1 <= MulVal     <= 16
     *                  0 <= DivAddVal  <= 14
     *                  DivAddVal       <  MulVal
     ************************************************************************
     *115200 = 40Mhz/16 x [(256 x DLM) + DLL x (1 + D/M)
     *115200 = 40Mhz/16 x DLest
     *DLest  = 21.7
     *FRest =   1.5
     ************************************************************************
     *DLest =  INT(40Mhz/(16 x 115200 x FRest)
     *FRest =  40Mhz/(16 x 115200 x DLest)
     ************************************************************************
     *many fractional dividers can work so I chose FRest = 1.1 from table 398
     *FRest =  1.1
     ************************************************************************
     *DLest =  INT(40Mhz/(16 x 115200 x 1.1) = 19
     *FRest =  40Mhz/(16 x 115200 x 19)      = 1.142
     *this satisfies the condition 1.1 < Frest < 1.9
     ************************************************************************
     *DivAdd  = 1
     *MulVal  = 7
     ************************************************************************
     *technical baud rate = 40Mhz/(16 x 115200 x z) z = 21 
     ************************************************************************
     */

    Chip_UART_EnableDivisorAccess(LPC_UART0);
    Chip_UART_SetDivisorLatches(LPC_UART0, 21, 0);
    Chip_UART_DisableDivisorAccess(LPC_UART0);


    /*
     ************************************************************************
     *8-N-1
     ************************************************************************
     */
    wdTemp  = UART_LCR_WLEN8;
    wdTemp |= UART_LCR_SBS_1BIT;
    wdTemp |= UART_LCR_PARITY_DIS;
    Chip_UART_ConfigData(LPC_UART0, wdTemp);

    LPC_UART0->FDR = (UART_FDR_MULVAL(7) | UART_FDR_DIVADDVAL(1)); 


    /*
     ************************************************************************
     *reset RX and TX blocks and enable fifos
     ************************************************************************
     */
    wdTemp  = UART_FCR_FIFO_EN;
    wdTemp |= UART_FCR_RX_RS;
    wdTemp |= UART_FCR_TX_RS;
    wdTemp |= UART_FCR_TRG_LEV1;
    Chip_UART_SetupFIFOS(LPC_UART0, wdTemp);

    Chip_UART_TXEnable(LPC_UART0);
 

    /*
     ************************************************************************
     *enable interrupts
     ************************************************************************
     */
    wdTemp  = UART_IER_RBRINT;
    Chip_UART_IntEnable(LPC_UART0, wdTemp);
}



 

/*
 ****************************************************************************
 *description:  nvic systic handler
 *inputs:       none
 *note:         toggle P1[8] = 190 uC led used as heartbeat monitor
 ****************************************************************************
 */
void
egwu_nvic_systick_isr(void)
{
    volatile unsigned int wdTemp;

    strSysTick.wdTicks++;
    if(strSysTick.wdTicks == 1000)
        {
        strSysTick.wdTicks = 0;
        strSysTick.wdSeconds++;

        //wdTemp = Chip_GPIO_GetPinState(LPC_GPIO1, LPC_LED_PORT, LPC_LED_PIN);
        //Chip_GPIO_SetPinState(LPC_GPIO1, LPC_LED_PORT, LPC_LED_PIN, wdTemp);

        wdTemp = (((LPC_GPIO1->PIN) >> LPC_LED_PIN) & 0x1);
        wdTemp ^= 0x1;
        if(wdTemp == 0)
                (LPC_GPIO1->CLR) = (1 << LPC_LED_PIN);  
        else
                (LPC_GPIO1->SET) = (1 << LPC_LED_PIN);  
        }
}





/*
 ****************************************************************************
 *description:  nvic fault handler
 *inputs:       none
 ****************************************************************************
 */
void
egwu_nvic_fault_isr(void)
{
        egwu_set_lpc_biled(EGWU_NVIC_FAULT_BILED_MASK);
}





/*
 ****************************************************************************
 *description:  nvic user handler
 *inputs:       none
 ****************************************************************************
 */
void
egwu_nvic_user_isr(void)
{
egwu_set_lpc_biled(EGWU_NVIC_USER_BILED_MASK);
}





/*
 ****************************************************************************
 *description:  set the bi-led connected to the LPC
 *inputs:       unsigned int wdLedMask = led mask only lower two bits matter
 ****************************************************************************
 */
void
egwu_set_lpc_biled(unsigned int wdLedMask)
{
    wdLedMask &= 0x3;

    Chip_GPIO_SetPinState(LPC_GPIO, LPC_BILED_PORT, LPC_BILED_PIN1, wdLedMask);
    Chip_GPIO_SetPinState(LPC_GPIO, LPC_BILED_PORT, LPC_BILED_PIN2, (wdLedMask >> 1));
}




#endif

No comments:

Post a Comment