/* ********************************************************************** *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