/* **************************************************************************** *name: IE_egwu_setup.h *author: Samuel Igwe *date: 06/30/2015 *description: pll/clock/iopin initialization **************************************************************************** */ #ifndef IE_EGWU_SETUP_H #define IE_EGWU_SETUP_H #include "chip.h" #include "chip_lpc177x_8x.h" #include "gpdma_17xx_40xx.h" #include "IE_egwu_uartio.h" /* ************************************************************************* *#defines ************************************************************************* */ #define EGWU_ONBOARD_UART LPC_UART1 #define EGWU_UART_BAUD_RATE 115200 #define LPC177X_NUM_INT 40 #define LPC177X_PREEMPT_PRIO_GROUP 2 #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 struct STR_EGWU_SYSTICK { volatile unsigned int wdSeconds; volatile unsigned int wdTicks; }strSysTick; #define MINIMUM_PERIPHERAL_IRQ_PRIORITY 3 enum egwu_int_pl { USB_INT_PL=MINIMUM_PERIPHERAL_IRQ_PRIORITY, UART_INT_PL, DMA_INT_PL, GPIO_INT_PL, WD_INT_PL}; extern int EGWU_IVT; const uint32_t OscRateIn; void (*ptrGpDmaUserIsr[GPDMA_NUMBER_CHANNELS])(void); unsigned int wdEnableGpDmaInt; /* ************************************************************************* *routines ************************************************************************* */ void setup_pll(void); void setup_nvic(void); void setup_gpio(void); void setup_uart(void); void nvic_systick_isr(void); void nvic_fault_isr(void); void nvic_user_isr(void); void gpio_set_lpc_biled(unsigned int wdLedMask); void setup_gpdma(void); void nvic_dma_isr(void); void gpdma_hook_chan_isr(int wdChannel,\ void (*ptrFunc)(void)); void gpdma_unhook_chan_isr(int wdChannel); void timer_delay_mS(int wdMs); #endif
/* **************************************************************************** *name: IE_egwu_setup.c *author: Samuel Igwe *date: 06/30/2015 *description: pll/clock/iopin initialization **************************************************************************** */ #ifndef IE_EGWU_SETUP_C #define 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 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 "ivt" * skip stack and reset positions * default isrs * nvic_fault_isr() * nvic_systic_isr() * nvic_user_isr() **************************************************************************** */ void setup_nvic(void) { volatile unsigned int wdTemp, *ptrTemp; volatile int wdCount; ptrTemp = (volatile unsigned int *)&EGWU_IVT; for(wdCount = 2; wdCount < (LPC177X_NUM_INT + 16); wdCount++) { if(wdCount < 15) /*faults*/ wdTemp = (int) nvic_fault_isr; else { switch(wdCount) { case 15: /*systick*/ wdTemp = (int) nvic_systick_isr; break; case 42: /*dma*/ wdTemp = (int) nvic_dma_isr; break; default: wdTemp = (int) nvic_user_isr; break; } } wdTemp |= 1; /*thumb - mandatory*/ *(ptrTemp + wdCount) = wdTemp; } /* ************************************************************************ *selecting nvic priority group 2 (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 (system handler priority) *4 + 5 + 6 to priority level 0 *11+14 to priority level 1 *15 (systick)to priority level 2 *(peripherals interrupt) *26 (dma) to priority level 3 *interrupts 1 through 3 are fixed (reset to fault) *set to rest to maximum priority (0xff) ************************************************************************ */ NVIC_SetPriorityGrouping(LPC177X_PREEMPT_PRIO_GROUP); for (wdCount = MemoryManagement_IRQn; wdCount < (LPC177X_NUM_INT); wdCount++) { switch(wdCount) { case UsageFault_IRQn: wdTemp = NVIC_EncodePriority(LPC177X_PREEMPT_PRIO_GROUP, 0, 0); break; case SVCall_IRQn: case PendSV_IRQn: wdTemp = NVIC_EncodePriority(LPC177X_PREEMPT_PRIO_GROUP, 1, 0); break; case SysTick_IRQn: wdTemp = NVIC_EncodePriority(LPC177X_PREEMPT_PRIO_GROUP, 2, 0); break; case DMA_IRQn: wdTemp = NVIC_EncodePriority(LPC177X_PREEMPT_PRIO_GROUP, 3, 0); break; default: wdTemp = NVIC_EncodePriority(LPC177X_PREEMPT_PRIO_GROUP, 9, 0); break; } NVIC_SetPriority(wdCount, wdTemp); } /* ************************************************************************ *setup systick timer for 1mS tick *configure variables ************************************************************************ */ strSysTick.wdSeconds = 0; strSysTick.wdTicks = 0; SysTick_Config(EGWU_CPU_CLK_RATE/1000); /* ************************************************************************ *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 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); else { if(wdCount == 30) Chip_IOCON_PinMuxSet(LPC_IOCON, 0, wdCount, IOCON_FUNC0); } } } } /* ************************************************************************ *port 1 ************************************************************************ */ for(wdCount = 0; wdCount < 32; wdCount++) { if((wdCount >= 2 && wdCount <= 10) || (wdCount >= 18 && wdCount <= 19) || (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); Chip_GPIO_SetPinDIROutput(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 18: case 19: 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 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 <= 15 * 0 <= DivAddVal <= 14 * DivAddVal < MulVal *[for 115200] ************************************************************************ *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) ************************************************************************ *DLest = INT(14.46) = 14 *FRest = 1.55 ************************************************************************ *this satisfies the condition 1.1 < Frest < 1.9 *DL = INT(40Mhz/(16 x 115200 x 1.55) = 14 *DL*FR = 14 x 1.55 = 21.7 ************************************************************************ *from the table *DivAdd = 5 *MulVal = 9 * *determined later that the values 6/7 work best for this osc and board ************************************************************************ *[for 9600] ************************************************************************ *9600 = 40Mhz/16 x [(256 x DLM) + DLL x (1 + D/M) *9600 = 40Mhz/16 x DLest *DLest = 260.41 *FRest = 1.5 ************************************************************************ *DLest = INT(40Mhz/(16 x 9600 x FRest) *FRest = 40Mhz/(16 x 9600 x DLest) ************************************************************************ *DLest = INT(173.61) = 173 *FRest = 1.505 ************************************************************************ *this satisfies the condition 1.1 < Frest < 1.9 *DL = INT(40Mhz/(16 x 9600 x 1.505) = 173.03 *DL*FR = 173 x 1.505 = 260.365 ************************************************************************ *from the table *DivAdd = 5 *MulVal = 9 ************************************************************************ */ #if (EGWU_UART_BAUD_RATE == 115200) Chip_UART_EnableDivisorAccess(EGWU_ONBOARD_UART); Chip_UART_SetDivisorLatches(EGWU_ONBOARD_UART, 14, 0); Chip_UART_DisableDivisorAccess(EGWU_ONBOARD_UART); /* ************************************************************************ *8-N-1 ************************************************************************ */ wdTemp = UART_LCR_WLEN8; wdTemp |= UART_LCR_SBS_1BIT; wdTemp |= UART_LCR_PARITY_DIS; Chip_UART_ConfigData(EGWU_ONBOARD_UART, wdTemp); EGWU_ONBOARD_UART->FDR = (UART_FDR_MULVAL(7) | UART_FDR_DIVADDVAL(6)); #else Chip_UART_EnableDivisorAccess(EGWU_ONBOARD_UART); Chip_UART_SetDivisorLatches(EGWU_ONBOARD_UART, 173, 0); Chip_UART_DisableDivisorAccess(EGWU_ONBOARD_UART); /* ************************************************************************ *8-N-1 ************************************************************************ */ wdTemp = UART_LCR_WLEN8; wdTemp |= UART_LCR_SBS_1BIT; wdTemp |= UART_LCR_PARITY_DIS; Chip_UART_ConfigData(EGWU_ONBOARD_UART, wdTemp); //EGWU_ONBOARD_UART->FDR = (UART_FDR_MULVAL(1) | UART_FDR_DIVADDVAL(0)); #ifdef DIVADDVAL EGWU_ONBOARD_UART->FDR = (UART_FDR_MULVAL(MULVAL) | UART_FDR_DIVADDVAL(DIVADDVAL)); #else EGWU_ONBOARD_UART->FDR = (UART_FDR_MULVAL(9) | UART_FDR_DIVADDVAL(5)); #endif #endif /* ************************************************************************ *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; wdTemp |= UART_FCR_DMAMODE_SEL; Chip_UART_SetupFIFOS(EGWU_ONBOARD_UART, wdTemp); Chip_UART_TXEnable(EGWU_ONBOARD_UART); /* ************************************************************************ *enable interrupts ************************************************************************ */ wdTemp = UART_IER_RBRINT; Chip_UART_IntEnable(EGWU_ONBOARD_UART, wdTemp); } /* **************************************************************************** *description: nvic systic handler *inputs: none *note: toggle P1[8] = 190 uC led used as heartbeat monitor **************************************************************************** */ void 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); uartio_tx_flush(); } } /* **************************************************************************** *description: nvic fault handler *inputs: none **************************************************************************** */ void nvic_fault_isr(void) { gpio_set_lpc_biled(EGWU_NVIC_FAULT_BILED_MASK); } /* **************************************************************************** *description: nvic user handler *inputs: none **************************************************************************** */ void nvic_user_isr(void) { gpio_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 gpio_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)); } /* ***************************************************************** *description: configure the gpdma peripheral * set array of pointers to int to 0 then init gpdma ***************************************************************** */ void setup_gpdma(void) { volatile unsigned int wdCount; for(wdCount=0; wdCount < GPDMA_NUMBER_CHANNELS; wdCount++) *(ptrGpDmaUserIsr + wdCount) = 0; wdEnableGpDmaInt = 0; Chip_GPDMA_Init(LPC_GPDMA); } /* ***************************************************************** *description: channel isr call back ***************************************************************** */ void nvic_dma_isr(void) { volatile unsigned int wdCount; for(wdCount=0; wdCount <GPDMA_NUMBER_CHANNELS; wdCount++) { if((Chip_GPDMA_Interrupt(LPC_GPDMA, wdCount) == SUCCESS) &&\ ptrGpDmaUserIsr[wdCount] != NULL) ptrGpDmaUserIsr[wdCount](); } } /* ***************************************************************** *description: hook channel ISR *inputs: int wdChannel = 0 to GPDMA_NUMBER_CHANNELS * void (*ptrFunc)(void) = pointer to callback function ***************************************************************** */ void gpdma_hook_chan_isr(int wdChannel, \ void (*ptrFunc)(void)) { if(ptrGpDmaUserIsr[wdChannel] == NULL) { ptrGpDmaUserIsr[wdChannel] = ptrFunc; wdEnableGpDmaInt++; NVIC_EnableIRQ(DMA_IRQn); } } /* ***************************************************************** *description: unhook channel ISR *input: int wdChannel = 0 to GPDMA_NUMBER_CHANNELS ***************************************************************** */ void gpdma_unhook_chan_isr(int wdChannel) { if(wdChannel >= GPDMA_NUMBER_CHANNELS) return; ptrGpDmaUserIsr[wdChannel] = 0; wdEnableGpDmaInt--; if(wdEnableGpDmaInt == 0) NVIC_DisableIRQ(DMA_IRQn); } /* ***************************************************************** *description: mS delay using TIMER0 *input: int wdMs = number of milliseconds to delay *note: peripheral clock is 40Mhz ***************************************************************** */ void timer_delay_mS(int wdMs) { volatile unsigned int wdTemp; Chip_TIMER_Reset(LPC_TIMER0); Chip_TIMER_Disable(LPC_TIMER0); Chip_TIMER_PrescaleSet(LPC_TIMER0, 40000); Chip_TIMER_SetMatch(LPC_TIMER0, 0, wdMs); Chip_TIMER_StopOnMatchEnable(LPC_TIMER0, 0); Chip_TIMER_Enable(LPC_TIMER0); do { wdTemp = Chip_TIMER_ReadCount(LPC_TIMER0); }while(wdTemp != wdMs); } #endif
No comments:
Post a Comment