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