moving lpc17xx to use lpcopen

This commit is contained in:
hathach
2018-12-03 17:28:38 +07:00
parent f898f8f7a4
commit 5f10584983
97 changed files with 31929 additions and 44 deletions

View File

@@ -0,0 +1,256 @@
/*
* @brief LPC17xx/40xx A/D conversion driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/* Get the number of clock for a full conversion */
STATIC INLINE uint8_t getFullConvClk(void)
{
#if defined(CHIP_LPC177X_8X) || defined(CHIP_LPC40XX)
return 31;
#elif defined(CHIP_LPC175X_6X)
return 65;
#else
return 0;
#endif
}
/* Get divider value */
STATIC uint8_t getClkDiv(LPC_ADC_T *pADC, bool burstMode, uint32_t adcRate, uint8_t clks)
{
uint32_t adcBlockFreq;
uint32_t fullAdcRate;
uint8_t div;
/* The APB clock (PCLK_ADC0) is divided by (CLKDIV+1) to produce the clock for
A/D converter, which should be less than or equal to 4.5MHz.
A fully conversion requires (bits_accuracy+1) of these clocks.
ADC Clock = PCLK_ADC0 / (CLKDIV + 1);
ADC rate = ADC clock / (the number of clocks required for each conversion);
*/
#if defined(CHIP_LPC175X_6X)
adcBlockFreq = Chip_Clock_GetPeripheralClockRate(SYSCTL_PCLK_ADC);
#else
adcBlockFreq = Chip_Clock_GetPeripheralClockRate();
#endif
#if defined(ADC_ACC_12BITS)
fullAdcRate = adcRate * getFullConvClk();
#else
if (burstMode) {
fullAdcRate = adcRate * clks;
}
else {
fullAdcRate = adcRate * getFullConvClk();
}
#endif
/* Get the round value by fomular: (2*A + B)/(2*B) */
div = ((adcBlockFreq * 2 + fullAdcRate) / (fullAdcRate * 2)) - 1;
return div;
}
/* Set start mode for ADC */
void setStartMode(LPC_ADC_T *pADC, uint8_t start_mode)
{
uint32_t temp;
temp = pADC->CR & (~ADC_CR_START_MASK);
pADC->CR = temp | (ADC_CR_START_MODE_SEL((uint32_t) start_mode));
}
/* Get the ADC value */
Status readAdcVal(LPC_ADC_T *pADC, uint8_t channel, uint16_t *data)
{
uint32_t temp;
temp = pADC->DR[channel];
if (!ADC_DR_DONE(temp)) {
return ERROR;
}
/* if(ADC_DR_OVERRUN(temp) && (pADC->CR & ADC_CR_BURST)) */
/* return ERROR; */
*data = (uint16_t) ADC_DR_RESULT(temp);
return SUCCESS;
}
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initialize the ADC peripheral and the ADC setup structure to default value */
void Chip_ADC_Init(LPC_ADC_T *pADC, ADC_CLOCK_SETUP_T *ADCSetup)
{
uint8_t div;
uint32_t cr = 0;
uint32_t clk;
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_ADC);
#if defined(ADC_TRIM_SUPPORT)
pADC->ADTRM = 0xF00;
#endif
pADC->INTEN = 0; /* Disable all interrupts */
cr |= ADC_CR_PDN;
ADCSetup->adcRate = ADC_MAX_SAMPLE_RATE;
ADCSetup->bitsAccuracy = 0; /* LPC17xx/40xx doesn't support this setting */
clk = 0;
ADCSetup->burstMode = false;
div = getClkDiv(pADC, false, ADCSetup->adcRate, clk);
cr |= ADC_CR_CLKDIV(div);
#if !defined(ADC_ACC_12BITS)
cr |= ADC_CR_BITACC(ADCSetup->bitsAccuracy);
#endif /*defined(ADC_ACC_12BITS)*/
pADC->CR = cr;
}
/* Shutdown ADC */
void Chip_ADC_DeInit(LPC_ADC_T *pADC)
{
pADC->INTEN = 0x00000100;
pADC->CR = 0;
Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_ADC);
}
/* Get the ADC value */
Status Chip_ADC_ReadValue(LPC_ADC_T *pADC, uint8_t channel, uint16_t *data)
{
return readAdcVal(pADC, channel, data);
}
/* Get ADC Channel status from ADC data register */
FlagStatus Chip_ADC_ReadStatus(LPC_ADC_T *pADC, uint8_t channel, uint32_t StatusType)
{
switch (StatusType) {
case ADC_DR_DONE_STAT:
return (pADC->STAT & (1UL << channel)) ? SET : RESET;
case ADC_DR_OVERRUN_STAT:
channel += 8;
return (pADC->STAT & (1UL << channel)) ? SET : RESET;
case ADC_DR_ADINT_STAT:
return pADC->STAT >> 16 ? SET : RESET;
default:
break;
}
return RESET;
}
/* Enable/Disable interrupt for ADC channel */
void Chip_ADC_Int_SetChannelCmd(LPC_ADC_T *pADC, uint8_t channel, FunctionalState NewState)
{
if (NewState == ENABLE) {
pADC->INTEN |= (1UL << channel);
}
else {
pADC->INTEN &= (~(1UL << channel));
}
}
/* Select the mode starting the AD conversion */
void Chip_ADC_SetStartMode(LPC_ADC_T *pADC, ADC_START_MODE_T mode, ADC_EDGE_CFG_T EdgeOption)
{
if ((mode != ADC_START_NOW) && (mode != ADC_NO_START)) {
if (EdgeOption) {
pADC->CR |= ADC_CR_EDGE;
}
else {
pADC->CR &= ~ADC_CR_EDGE;
}
}
setStartMode(pADC, (uint8_t) mode);
}
/* Set the ADC Sample rate */
void Chip_ADC_SetSampleRate(LPC_ADC_T *pADC, ADC_CLOCK_SETUP_T *ADCSetup, uint32_t rate)
{
uint8_t div;
uint32_t cr;
cr = pADC->CR & (~ADC_SAMPLE_RATE_CONFIG_MASK);
ADCSetup->adcRate = rate;
div = getClkDiv(pADC, ADCSetup->burstMode, rate, (11 - ADCSetup->bitsAccuracy));
cr |= ADC_CR_CLKDIV(div);
#if !defined(ADC_ACC_12BITS)
cr |= ADC_CR_BITACC(ADCSetup->bitsAccuracy);
#endif /*defined(ADC_ACC_12BITS)*/
pADC->CR = cr;
}
/* Enable or disable the ADC channel on ADC peripheral */
void Chip_ADC_EnableChannel(LPC_ADC_T *pADC, ADC_CHANNEL_T channel, FunctionalState NewState)
{
if (NewState == ENABLE) {
pADC->CR |= ADC_CR_CH_SEL(channel);
}
else {
pADC->CR &= ~ADC_CR_START_MASK;
pADC->CR &= ~ADC_CR_CH_SEL(channel);
}
}
/* Enable burst mode */
void Chip_ADC_SetBurstCmd(LPC_ADC_T *pADC, FunctionalState NewState)
{
setStartMode(pADC, ADC_NO_START);
if (NewState == DISABLE) {
pADC->CR &= ~ADC_CR_BURST;
}
else {
pADC->CR |= ADC_CR_BURST;
}
}
/* Read the ADC value and convert it to 8bits value */
Status Chip_ADC_ReadByte(LPC_ADC_T *pADC, ADC_CHANNEL_T channel, uint8_t *data)
{
uint16_t temp;
Status rt;
rt = readAdcVal(pADC, channel, &temp);
*data = (uint8_t) temp;
return rt;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,110 @@
/*
* @brief LPC17xx/40xx Miscellaneous chip specific functions
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/* System Clock Frequency (Core Clock) */
uint32_t SystemCoreClock;
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
/* Update system core clock rate, should be called if the system has
a clock rate change */
void SystemCoreClockUpdate(void)
{
/* CPU core speed */
SystemCoreClock = Chip_Clock_GetSystemClockRate();
}
/* Sets up USB PLL, all needed clocks and enables USB PHY on the chip. USB pins which are
muxed to different pads are not initialized here. This routine assumes that the XTAL
OSC is enabled and running prior to this call. */
void Chip_USB_Init(void)
{
#if defined(CHIP_LPC175X_6X)
/* Setup USB PLL1 for a 48MHz clock
Input clock rate (FIN) is main oscillator = 12MHz
PLL1 Output = USBCLK = 48MHz = FIN * MSEL, so MSEL = 4.
FCCO = USBCLK = USBCLK * 2 * P. It must be between 156 MHz to 320 MHz.
so P = 2 and FCCO = 48MHz * 2 * 2 = 192MHz */
Chip_Clock_SetupPLL(SYSCTL_USB_PLL, 3, 1); /* Multiply by 4, Divide by 2 */
/* Use PLL1 output as USB Clock Source */
/* Enable PLL1 */
Chip_Clock_EnablePLL(SYSCTL_USB_PLL, SYSCTL_PLL_ENABLE);
/* Wait for PLL1 to lock */
while (!Chip_Clock_IsUSBPLLLocked()) {}
/* Connect PLL1 */
Chip_Clock_EnablePLL(SYSCTL_USB_PLL, SYSCTL_PLL_ENABLE | SYSCTL_PLL_CONNECT);
/* Wait for PLL1 to be connected */
while (!Chip_Clock_IsUSBPLLConnected()) {}
#else
/* Select XTAL as clock source for USB block and divider as 1 */
LPC_SYSCTL->USBCLKSEL = 0x1;
/* Setup USB PLL1 for a 48MHz clock
Input clock rate (FIN) is main oscillator = 12MHz
PLL output = 48MHz = FIN * MSEL, so MSEL = 4
FCCO must be between 156 MHz to 320 MHz, where FCCO = PLL output * 2 * P,
so P = 2 and FCCO = 48MHz * 2 * 2 = 192MHz */
Chip_Clock_SetupPLL(SYSCTL_USB_PLL, 3, 1);
/* Wait for USB PLL to lock */
while ((Chip_Clock_GetPLLStatus(SYSCTL_USB_PLL) & SYSCTL_PLLSTS_LOCKED) == 0) {}
/* Select PLL1/USBPLL as clock source for USB block and divider as 1 */
LPC_SYSCTL->USBCLKSEL = (SYSCTL_USBCLKSRC_USBPLL << 8) | 0x01;
#endif /* defined(CHIP_LPC175X_6X) */
/* Enable AHB clock to the USB block and USB RAM. */
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_USB);
}

View File

@@ -0,0 +1,516 @@
/*
* @brief LPC17xx/40xx System and Control driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
/* Enables or connects a PLL */
void Chip_Clock_EnablePLL(CHIP_SYSCTL_PLL_T PLLNum, uint32_t flags) {
uint32_t temp;
temp = LPC_SYSCTL->PLL[PLLNum].PLLCON;
temp |= flags;
LPC_SYSCTL->PLL[PLLNum].PLLCON = temp;
Chip_Clock_FeedPLL(PLLNum);
}
/* Disables or disconnects a PLL */
void Chip_Clock_DisablePLL(CHIP_SYSCTL_PLL_T PLLNum, uint32_t flags) {
uint32_t temp;
temp = LPC_SYSCTL->PLL[PLLNum].PLLCON;
temp &= ~flags;
LPC_SYSCTL->PLL[PLLNum].PLLCON = temp;
Chip_Clock_FeedPLL(PLLNum);
}
/* Sets up a PLL */
void Chip_Clock_SetupPLL(CHIP_SYSCTL_PLL_T PLLNum, uint32_t msel, uint32_t psel) {
uint32_t PLLcfg;
#if defined(CHIP_LPC175X_6X)
/* PLL0 and PLL1 are slightly different */
if (PLLNum == SYSCTL_MAIN_PLL) {
PLLcfg = (msel) | (psel << 16);
}
else {
PLLcfg = (msel) | (psel << 5);
}
#else
PLLcfg = (msel) | (psel << 5);
#endif
LPC_SYSCTL->PLL[PLLNum].PLLCFG = PLLcfg;
LPC_SYSCTL->PLL[PLLNum].PLLCON = 0x1;
Chip_Clock_FeedPLL(PLLNum);
}
/* Enables power and clocking for a peripheral */
void Chip_Clock_EnablePeriphClock(CHIP_SYSCTL_CLOCK_T clk) {
uint32_t bs = (uint32_t) clk;
#if defined(CHIP_LPC40XX)
if (bs >= 32) {
LPC_SYSCTL->PCONP1 |= (1 << (bs - 32));
}
else {
LPC_SYSCTL->PCONP |= (1 << bs);
}
#else
LPC_SYSCTL->PCONP |= (1 << bs);
#endif
}
/* Disables power and clocking for a peripheral */
void Chip_Clock_DisablePeriphClock(CHIP_SYSCTL_CLOCK_T clk) {
uint32_t bs = (uint32_t) clk;
#if defined(CHIP_LPC40XX)
if (bs >= 32) {
LPC_SYSCTL->PCONP1 &= ~(1 << (bs - 32));
}
else {
LPC_SYSCTL->PCONP |= ~(1 << bs);
}
#else
LPC_SYSCTL->PCONP |= ~(1 << bs);
#endif
}
/* Returns power enables state for a peripheral */
bool Chip_Clock_IsPeripheralClockEnabled(CHIP_SYSCTL_CLOCK_T clk)
{
uint32_t bs = (uint32_t) clk;
#if defined(CHIP_LPC40XX)
if (bs >= 32) {
bs = LPC_SYSCTL->PCONP1 & (1 << (bs - 32));
}
else {
bs = LPC_SYSCTL->PCONP & (1 << bs);
}
#else
bs = LPC_SYSCTL->PCONP & (1 << bs);
#endif
return (bool) (bs != 0);
}
/* Sets the current CPU clock source */
void Chip_Clock_SetCPUClockSource(CHIP_SYSCTL_CCLKSRC_T src)
{
#if defined(CHIP_LPC175X_6X)
/* LPC175x/6x CPU clock source is based on PLL connect status */
if (src == SYSCTL_CCLKSRC_MAINPLL) {
/* Connect PLL0 */
Chip_Clock_EnablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_CONNECT);
}
else {
Chip_Clock_DisablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_CONNECT);
}
#else
/* LPC177x/8x and 407x/8x CPU clock source is based on CCLKSEL */
if (src == SYSCTL_CCLKSRC_MAINPLL) {
/* Connect PLL0 */
LPC_SYSCTL->CCLKSEL |= (1 << 8);
}
else {
LPC_SYSCTL->CCLKSEL &= ~(1 << 8);
}
#endif
}
/* Returns the current CPU clock source */
CHIP_SYSCTL_CCLKSRC_T Chip_Clock_GetCPUClockSource(void)
{
CHIP_SYSCTL_CCLKSRC_T src;
#if defined(CHIP_LPC175X_6X)
/* LPC175x/6x CPU clock source is based on PLL connect status */
if (Chip_Clock_IsMainPLLConnected()) {
src = SYSCTL_CCLKSRC_MAINPLL;
}
else {
src = SYSCTL_CCLKSRC_SYSCLK;
}
#else
/* LPC177x/8x and 407x/8x CPU clock source is based on CCLKSEL */
if (LPC_SYSCTL->CCLKSEL & (1 << 8)) {
src = SYSCTL_CCLKSRC_MAINPLL;
}
else {
src = SYSCTL_CCLKSRC_SYSCLK;
}
#endif
return src;
}
/* Selects the CPU clock divider */
void Chip_Clock_SetCPUClockDiv(uint32_t div)
{
#if defined(CHIP_LPC175X_6X)
LPC_SYSCTL->CCLKSEL = div;
#else
uint32_t temp;
/* Save state of CPU clock source bit */
temp = LPC_SYSCTL->CCLKSEL & (1 << 8);
LPC_SYSCTL->CCLKSEL = temp | div;
#endif
}
/* Gets the CPU clock divider */
uint32_t Chip_Clock_GetCPUClockDiv(void)
{
#if defined(CHIP_LPC175X_6X)
return (LPC_SYSCTL->CCLKSEL & 0xFF) + 1;
#else
return LPC_SYSCTL->CCLKSEL & 0x1F;
#endif
}
#if !defined(CHIP_LPC175X_6X)
/* Selects the USB clock divider source */
void Chip_Clock_SetUSBClockSource(CHIP_SYSCTL_USBCLKSRC_T src)
{
uint32_t temp;
/* Mask out current source, but keep divider */
temp = LPC_SYSCTL->USBCLKSEL & ~(0x3 << 8);
LPC_SYSCTL->USBCLKSEL = temp | (((uint32_t) src) << 8);
}
#endif
/* Sets the USB clock divider */
void Chip_Clock_SetUSBClockDiv(uint32_t div)
{
uint32_t temp;
/* Mask out current divider */
#if defined(CHIP_LPC175X_6X)
temp = LPC_SYSCTL->USBCLKSEL & ~(0xF);
#else
temp = LPC_SYSCTL->USBCLKSEL & ~(0x1F);
#endif
LPC_SYSCTL->USBCLKSEL = temp | div;
}
/* Gets the USB clock divider */
uint32_t Chip_Clock_GetUSBClockDiv(void)
{
#if defined(CHIP_LPC175X_6X)
return (LPC_SYSCTL->USBCLKSEL & 0xF) + 1;
#else
return (LPC_SYSCTL->USBCLKSEL & 0x1F) + 1;
#endif
}
#if defined(CHIP_LPC175X_6X)
/* Selects a clock divider for a peripheral */
void Chip_Clock_SetPCLKDiv(CHIP_SYSCTL_PCLK_T clk, CHIP_SYSCTL_CLKDIV_T div)
{
uint32_t temp, bitIndex, regIndex = (uint32_t) clk;
/* Get register array index and clock index into the register */
bitIndex = ((regIndex % 16) * 2);
regIndex = regIndex / 16;
/* Mask and update register */
temp = LPC_SYSCTL->PCLKSEL[regIndex] & ~(0x3 << bitIndex);
temp |= (((uint32_t) div) << bitIndex);
LPC_SYSCTL->PCLKSEL[regIndex] = temp;
}
/* Gets a clock divider for a peripheral */
uint32_t Chip_Clock_GetPCLKDiv(CHIP_SYSCTL_PCLK_T clk)
{
uint32_t div = 1, bitIndex, regIndex = ((uint32_t) clk) * 2;
/* Get register array index and clock index into the register */
bitIndex = regIndex % 32;
regIndex = regIndex / 32;
/* Mask and update register */
div = LPC_SYSCTL->PCLKSEL[regIndex];
div = (div >> bitIndex) & 0x3;
if (div == SYSCTL_CLKDIV_4) {
div = 4;
}
else if (div == SYSCTL_CLKDIV_1) {
div = 1;
}
else if (div == SYSCTL_CLKDIV_2) {
div = 2;
}
else {
/* Special case for CAN clock divider */
if ((clk == SYSCTL_PCLK_CAN1) || (clk == SYSCTL_PCLK_CAN2) || (clk == SYSCTL_PCLK_ACF)) {
div = 6;
}
else {
div = 8;
}
}
return div;
}
#endif
/* Selects a source clock and divider rate for the CLKOUT pin */
void Chip_Clock_SetCLKOUTSource(CHIP_SYSCTL_CLKOUTSRC_T src,
uint32_t div)
{
uint32_t temp;
temp = LPC_SYSCTL->CLKOUTCFG & ~0x1FF;
temp |= ((uint32_t) src) | ((div - 1) << 4);
LPC_SYSCTL->CLKOUTCFG = temp;
}
/* Returns the current SYSCLK clock rate */
uint32_t Chip_Clock_GetSYSCLKRate(void)
{
/* Determine clock input rate to SYSCLK based on input selection */
switch (Chip_Clock_GetMainPLLSource()) {
case (uint32_t) SYSCTL_PLLCLKSRC_IRC:
return Chip_Clock_GetIntOscRate();
case (uint32_t) SYSCTL_PLLCLKSRC_MAINOSC:
return Chip_Clock_GetMainOscRate();
#if defined(CHIP_LPC175X_6X)
case (uint32_t) SYSCTL_PLLCLKSRC_RTC:
return Chip_Clock_GetRTCOscRate();
#endif
}
return 0;
}
/* Returns the main PLL output clock rate */
uint32_t Chip_Clock_GetMainPLLOutClockRate(void)
{
uint32_t clkhr = 0;
#if defined(CHIP_LPC175X_6X)
/* Only valid if enabled */
if (Chip_Clock_IsMainPLLEnabled()) {
uint32_t msel, nsel;
/* PLL0 rate is (FIN * 2 * MSEL) / NSEL, get MSEL and NSEL */
msel = 1 + (LPC_SYSCTL->PLL[SYSCTL_MAIN_PLL].PLLCFG & 0x7FFF);
nsel = 1 + ((LPC_SYSCTL->PLL[SYSCTL_MAIN_PLL].PLLCFG >> 16) & 0xFF);
clkhr = (Chip_Clock_GetMainPLLInClockRate() * 2 * msel) / nsel;
}
#else
if (Chip_Clock_IsMainPLLEnabled()) {
uint32_t msel;
/* PLL0 rate is (FIN * MSEL) */
msel = 1 + (LPC_SYSCTL->PLL[SYSCTL_MAIN_PLL].PLLCFG & 0x1F);
clkhr = (Chip_Clock_GetMainPLLInClockRate() * msel);
}
#endif
return (uint32_t) clkhr;
}
/* Get USB output clock rate */
uint32_t Chip_Clock_GetUSBPLLOutClockRate(void)
{
uint32_t clkhr = 0;
/* Only valid if enabled */
if (Chip_Clock_IsUSBPLLEnabled()) {
uint32_t msel;
/* PLL1 input clock (FIN) is always main oscillator */
/* PLL1 rate is (FIN * MSEL) */
msel = 1 + (LPC_SYSCTL->PLL[SYSCTL_USB_PLL].PLLCFG & 0x1F);
clkhr = (Chip_Clock_GetUSBPLLInClockRate() * msel);
}
return (uint32_t) clkhr;
}
/* Get the main clock rate */
/* On 175x/6x devices, this is the input clock to the CPU divider.
Additionally, on 177x/8x and 407x/8x devices, this is also the
input clock to the peripheral divider. */
uint32_t Chip_Clock_GetMainClockRate(void)
{
switch (Chip_Clock_GetCPUClockSource()) {
case SYSCTL_CCLKSRC_MAINPLL:
return Chip_Clock_GetMainPLLOutClockRate();
case SYSCTL_CCLKSRC_SYSCLK:
return Chip_Clock_GetSYSCLKRate();
default:
return 0;
}
}
/* Get CCLK rate */
uint32_t Chip_Clock_GetSystemClockRate(void)
{
return Chip_Clock_GetMainClockRate() / Chip_Clock_GetCPUClockDiv();
}
/* Returns the USB clock (USB_CLK) rate */
uint32_t Chip_Clock_GetUSBClockRate(void)
{
uint32_t div, clkrate;
#if defined(CHIP_LPC175X_6X)
/* The USB clock rate is derived from PLL1 or PLL0 */
if (Chip_Clock_IsUSBPLLConnected()) {
/* Use PLL1 clock for USB source with divider of 1 */
clkrate = Chip_Clock_GetUSBPLLOutClockRate();
div = 1;
}
else {
clkrate = Chip_Clock_GetMainClockRate();
div = Chip_Clock_GetUSBClockDiv();
}
#else
/* Get clock from source drving USB */
switch (Chip_Clock_GetUSBClockSource()) {
case SYSCTL_USBCLKSRC_SYSCLK:
default:
clkrate = Chip_Clock_GetSYSCLKRate();
break;
case SYSCTL_USBCLKSRC_MAINPLL:
clkrate = Chip_Clock_GetMainPLLOutClockRate();
break;
case SYSCTL_USBCLKSRC_USBPLL:
clkrate = Chip_Clock_GetUSBPLLOutClockRate();
break;
}
div = Chip_Clock_GetUSBClockDiv();
#endif
return clkrate / div;
}
#if !defined(CHIP_LPC175X_6X)
/* Selects the SPIFI clock divider source */
void Chip_Clock_SetSPIFIClockSource(CHIP_SYSCTL_SPIFICLKSRC_T src)
{
uint32_t temp;
/* Mask out current source, but keep divider */
temp = LPC_SYSCTL->SPIFICLKSEL & ~(0x3 << 8);
LPC_SYSCTL->SPIFICLKSEL = temp | (((uint32_t) src) << 8);
}
/* Sets the SPIFI clock divider */
void Chip_Clock_SetSPIFIClockDiv(uint32_t div)
{
uint32_t temp;
/* Mask out current divider */
temp = LPC_SYSCTL->SPIFICLKSEL & ~(0x1F);
LPC_SYSCTL->SPIFICLKSEL = temp | div;
}
/* Returns the SPIFI clock rate */
uint32_t Chip_Clock_GetSPIFIClockRate(void)
{
uint32_t div, clkrate;
/* Get clock from source drving USB */
switch (Chip_Clock_GetSPIFIClockSource()) {
case SYSCTL_SPIFICLKSRC_SYSCLK:
default:
clkrate = Chip_Clock_GetSYSCLKRate();
break;
case SYSCTL_SPIFICLKSRC_MAINPLL:
clkrate = Chip_Clock_GetMainPLLOutClockRate();
break;
case SYSCTL_SPIFICLKSRC_USBPLL:
clkrate = Chip_Clock_GetUSBPLLOutClockRate();
break;
}
div = Chip_Clock_GetSPIFIClockDiv();
return clkrate / div;
}
#endif
#if defined(CHIP_LPC175X_6X)
/* Returns the clock rate for a peripheral */
uint32_t Chip_Clock_GetPeripheralClockRate(CHIP_SYSCTL_PCLK_T clk) {
/* 175x/6x clock is derived from CPU clock with CPU divider */
return Chip_Clock_GetSystemClockRate() / Chip_Clock_GetPCLKDiv(clk);
}
#else
/* Returns the clock rate for all peripherals */
uint32_t Chip_Clock_GetPeripheralClockRate(void)
{
uint32_t clkrate = 0, div;
/* Get divider, a divider of 0 means the clock is disabled */
div = Chip_Clock_GetPCLKDiv();
if (div != 0) {
/* Derived from periperhal clock input and peripheral clock divider */
clkrate = Chip_Clock_GetMainClockRate() / div;
}
return clkrate;
}
#endif

View File

@@ -0,0 +1,64 @@
/*
* @brief LPC17xx/40xx Comparator driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
#if defined(CHIP_LPC40XX)
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initializes the CMP */
void Chip_CMP_Init(void)
{
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_CMP);
}
/* De-initializes the CMP */
void Chip_CMP_DeInit(void)
{
Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_CMP);
}
#endif /* defined(CHIP_LPC40XX) */

View File

@@ -0,0 +1,110 @@
/*
* @brief LPC17xx/40xx Cyclic Redundancy Check (CRC) Engine driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licenser disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
#if defined(CHIP_LPC177X_8X) || defined(CHIP_LPC40XX)
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
/* Sets up the CRC engine with defaults based on the polynomial to be used */
void Chip_CRC_UseDefaultConfig(CRC_POLY_T poly)
{
switch (poly) {
case CRC_POLY_CRC16:
LPC_CRC->MODE = MODE_CFG_CRC16;
LPC_CRC->SEED = CRC_SEED_CRC16;
break;
case CRC_POLY_CRC32:
LPC_CRC->MODE = MODE_CFG_CRC32;
LPC_CRC->SEED = CRC_SEED_CRC32;
break;
case CRC_POLY_CCITT:
default:
LPC_CRC->MODE = MODE_CFG_CCITT;
LPC_CRC->SEED = CRC_SEED_CCITT;
break;
}
}
/* configure CRC engine and compute CCITT checksum from 8-bit data */
uint32_t Chip_CRC_CRC8(const uint8_t *data, uint32_t bytes)
{
Chip_CRC_UseDefaultConfig(CRC_POLY_CCITT);
while (bytes > 0) {
Chip_CRC_Write8(*data);
data++;
bytes--;
}
return Chip_CRC_Sum();
}
/* Convenience function for computing a standard CRC16 checksum from 16-bit data block */
uint32_t Chip_CRC_CRC16(const uint16_t *data, uint32_t hwords)
{
Chip_CRC_UseDefaultConfig(CRC_POLY_CRC16);
while (hwords > 0) {
Chip_CRC_Write16(*data);
data++;
hwords--;
}
return Chip_CRC_Sum();
}
/* Convenience function for computing a standard CRC32 checksum from 32-bit data block */
uint32_t Chip_CRC_CRC32(const uint32_t *data, uint32_t words)
{
Chip_CRC_UseDefaultConfig(CRC_POLY_CRC32);
while (words > 0) {
Chip_CRC_Write32(*data);
data++;
words--;
}
return Chip_CRC_Sum();
}
#endif /* defined(CHIP_LPC177X_8X) || defined(CHIP_LPC40XX) */

View File

@@ -0,0 +1,84 @@
/*
* @brief LPC17xx/40xx D/A conversion driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initialize the DAC peripheral */
void Chip_DAC_Init(LPC_DAC_T *pDAC)
{
#if defined(CHIP_LPC177X_8X) || defined(CHIP_LPC40XX)
Chip_SYSCTL_PeriphReset(SYSCTL_RESET_DAC);
#endif
/* Set maximum update rate 1MHz */
Chip_DAC_SetBias(pDAC, DAC_MAX_UPDATE_RATE_1MHz);
}
/* Shutdown DAC peripheral */
void Chip_DAC_DeInit(LPC_DAC_T *pDAC)
{}
/* Update value to DAC buffer*/
void Chip_DAC_UpdateValue(LPC_DAC_T *pDAC, uint32_t dac_value)
{
uint32_t tmp;
tmp = pDAC->CR & DAC_BIAS_EN;
tmp |= DAC_VALUE(dac_value);
/* Update value */
pDAC->CR = tmp;
}
/* Set Maximum update rate for DAC */
void Chip_DAC_SetBias(LPC_DAC_T *pDAC, uint32_t bias)
{
pDAC->CR &= ~DAC_BIAS_EN;
if (bias == DAC_MAX_UPDATE_RATE_400kHz) {
pDAC->CR |= DAC_BIAS_EN;
}
}

View File

@@ -0,0 +1,258 @@
/*
* @brief LPC17xx/40xx EEPROM driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
#if defined(CHIP_LPC177X_8X) || defined(CHIP_LPC40XX)
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/* Setup EEPROM clock */
STATIC void setClkDiv(LPC_EEPROM_T *pEEPROM)
{
uint32_t clk;
/* Setup EEPROM timing to 375KHz based on PCLK rate */
clk = Chip_Clock_GetSystemClockRate();
/* Set EEPROM clock divide value*/
pEEPROM->CLKDIV = clk / 375000 - 1;
}
/* Setup EEPROM clock */
STATIC void setWaitState(LPC_EEPROM_T *pEEPROM)
{
uint32_t val, clk;
/* Setup EEPROM timing to 375KHz based on PCLK rate */
clk = Chip_Clock_GetSystemClockRate();
/* Setup EEPROM wait states to 15, 35, 35nS */
val = ((((clk / 1000000) * 15) / 1000) + 1);
val |= (((((clk / 1000000) * 55) / 1000) + 1) << 8);
val |= (((((clk / 1000000) * 35) / 1000) + 1) << 16);
Chip_EEPROM_SetWaitState(pEEPROM, val);
}
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initializes the EEPROM peripheral with specified parameter */
void Chip_EEPROM_Init(LPC_EEPROM_T *pEEPROM)
{
Chip_EEPROM_DisablePowerDown(pEEPROM);
setClkDiv(pEEPROM);
setWaitState(pEEPROM);
}
/* Wait for interrupt */
void Chip_EEPROM_WaitForIntStatus(LPC_EEPROM_T *pEEPROM, uint32_t mask)
{
uint32_t status;
while (1) {
status = Chip_EEPROM_GetIntStatus(pEEPROM);
if ((status & mask) == mask) {
break;
}
}
Chip_EEPROM_ClearIntStatus(pEEPROM, mask);
}
/* Erase data in page register */
void Chip_EEPROM_ErasePageRegister(LPC_EEPROM_T *pEEPROM)
{
uint32_t i = 0;
Chip_EEPROM_ClearIntStatus(pEEPROM, EEPROM_INT_ENDOFRW);
Chip_EEPROM_SetCmd(pEEPROM, EEPROM_CMD_32BITS_WRITE);
Chip_EEPROM_SetAddr(pEEPROM, 0, 0);
for (i = 0; i < EEPROM_PAGE_SIZE; i += 4) {
Chip_EEPROM_WriteData(pEEPROM, 0);
Chip_EEPROM_WaitForIntStatus(pEEPROM, EEPROM_INT_ENDOFRW);
}
}
/* Write data to page register */
uint32_t Chip_EEPROM_WritePageRegister(LPC_EEPROM_T *pEEPROM, uint16_t pageOffset,
uint8_t *pData, uint8_t wsize, uint32_t byteNum)
{
uint32_t i = 0;
uint32_t mask = (1 << (8 * wsize)) - 1;
Chip_EEPROM_ClearIntStatus(pEEPROM, EEPROM_INT_ENDOFRW);
if (wsize == 1) {
Chip_EEPROM_SetCmd(pEEPROM, EEPROM_CMD_8BITS_WRITE);
}
else if (wsize == 2) {
Chip_EEPROM_SetCmd(pEEPROM, EEPROM_CMD_16BITS_WRITE);
}
else {
Chip_EEPROM_SetCmd(pEEPROM, EEPROM_CMD_32BITS_WRITE);
}
Chip_EEPROM_SetAddr(pEEPROM, 0, pageOffset);
for (i = 0; i < byteNum; i += wsize) {
Chip_EEPROM_WriteData(pEEPROM, (*(uint32_t *) (&pData[i])) & mask);
Chip_EEPROM_WaitForIntStatus(pEEPROM, EEPROM_INT_ENDOFRW);
}
return i;
}
/* Write data from page register to non-volatile memory */
void Chip_EEPROM_EraseProgramPage(LPC_EEPROM_T *pEEPROM, uint16_t pageAddr)
{
Chip_EEPROM_ClearIntStatus(pEEPROM, EEPROM_CMD_ERASE_PRG_PAGE);
Chip_EEPROM_SetAddr(pEEPROM, pageAddr, 0);
Chip_EEPROM_SetCmd(pEEPROM, EEPROM_CMD_ERASE_PRG_PAGE);
Chip_EEPROM_WaitForIntStatus(pEEPROM, EEPROM_INT_ENDOFPROG);
}
/* Read data from non-volatile memory */
uint32_t Chip_EEPROM_ReadPage(LPC_EEPROM_T *pEEPROM,
uint16_t pageOffset,
uint16_t pageAddr,
uint8_t *pData,
uint8_t rsize,
uint32_t byteNum)
{
uint32_t i;
uint32_t mask = (1 << (8 * rsize)) - 1;
Chip_EEPROM_ClearIntStatus(pEEPROM, EEPROM_INT_ENDOFRW);
Chip_EEPROM_SetAddr(pEEPROM, pageAddr, pageOffset);
if (rsize == 1) {
Chip_EEPROM_SetCmd(pEEPROM, EEPROM_CMD_8BITS_READ | EEPROM_CMD_RDPREFETCH);
}
else if (rsize == 2) {
Chip_EEPROM_SetCmd(pEEPROM, EEPROM_CMD_16BITS_READ | EEPROM_CMD_RDPREFETCH);
}
else {
Chip_EEPROM_SetCmd(pEEPROM, EEPROM_CMD_32BITS_READ | EEPROM_CMD_RDPREFETCH);
}
/* read and store data in buffer */
for (i = 0; i < byteNum; i += rsize) {
(*(uint32_t *) (&pData[i]) ) &= ~mask;
(*(uint32_t *) (&pData[i]) ) |= (Chip_EEPROM_ReadData(pEEPROM) & mask);
Chip_EEPROM_WaitForIntStatus(pEEPROM, EEPROM_INT_ENDOFRW);
}
return i;
}
/* Write data to EEPROM at specific address */
Status Chip_EEPROM_Write(LPC_EEPROM_T *pEEPROM,
uint16_t pageOffset,
uint16_t pageAddr,
void *pData,
EEPROM_RWSIZE_T wsize,
uint32_t byteNum)
{
uint32_t wTotalByteNum = 0;
uint32_t wOffset = (pageOffset & (EEPROM_PAGE_SIZE - 1));
uint32_t wByteNum = EEPROM_PAGE_SIZE - wOffset;
while (byteNum) {
if (wByteNum > byteNum) {
wByteNum = byteNum;
}
/* update data to page register */
Chip_EEPROM_WritePageRegister(pEEPROM, wOffset,
&((uint8_t *) pData)[wTotalByteNum], (uint8_t) wsize, wByteNum);
Chip_EEPROM_EraseProgramPage(pEEPROM, pageAddr);
wTotalByteNum += wByteNum;
byteNum -= wByteNum;
/* Change to next page */
pageAddr++;
wOffset = 0;
wByteNum = EEPROM_PAGE_SIZE;
}
return SUCCESS;
}
/* Read data to EEPROM at specific address */
void Chip_EEPROM_Read(LPC_EEPROM_T *pEEPROM,
uint16_t pageOffset,
uint16_t pageAddr,
void *pData,
EEPROM_RWSIZE_T rsize,
uint32_t byteNum)
{
uint32_t rTotalByteNum = 0;
uint32_t rOffset = (pageOffset & (EEPROM_PAGE_SIZE - 1));
uint32_t rByteNum = EEPROM_PAGE_SIZE - rOffset;
/* read and store data in buffer */
while (byteNum) {
if (rByteNum > byteNum) {
rByteNum = byteNum;
}
/* update data to page register */
Chip_EEPROM_ReadPage(pEEPROM, rOffset, pageAddr,
&((uint8_t *) pData)[rTotalByteNum], (uint8_t) rsize, rByteNum);
rTotalByteNum += rByteNum;
byteNum -= rByteNum;
/* Change to next page */
pageAddr++;
rOffset = 0;
rByteNum = EEPROM_PAGE_SIZE;
}
}
/* Erase a page at the specific address */
void Chip_EEPROM_Erase(LPC_EEPROM_T *pEEPROM, uint16_t pageAddr)
{
Chip_EEPROM_ErasePageRegister(pEEPROM);
Chip_EEPROM_EraseProgramPage(pEEPROM, pageAddr);
}
#endif /* defined(CHIP_LPC177X_8X) || defined(CHIP_LPC40XX) */

View File

@@ -0,0 +1,282 @@
/*
* @brief LPC17xx/40xx EMC driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
#if defined(CHIP_LPC177X_8X) || defined(CHIP_LPC40XX)
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/* DIV function with result rounded up */
#define EMC_DIV_ROUND_UP(x, y) ((x + y - 1) / y)
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
#ifndef EMC_SUPPORT_ONLY_PL172
/* Get ARM External Memory Controller Version */
STATIC uint32_t getARMPeripheralID(void)
{
uint32_t *RegAdd;
RegAdd = (uint32_t *) ((uint32_t) LPC_EMC + 0xFE0);
return (RegAdd[0] & 0xFF) | ((RegAdd[1] & 0xFF) << 8) |
((RegAdd[2] & 0xFF) << 16) | (RegAdd[3] << 24);
}
#endif
/* Calculate Clock Count from Timing Unit(nanoseconds) */
STATIC uint32_t convertTimmingParam(uint32_t EMC_Clock, int32_t input_ns, uint32_t adjust)
{
uint32_t temp;
if (input_ns < 0) {
return (-input_ns) >> 8;
}
temp = EMC_Clock / 1000000; /* MHz calculation */
temp = temp * input_ns / 1000;
/* round up */
temp += 0xFF;
/* convert to simple integer number format */
temp >>= 8;
if (temp > adjust) {
return temp - adjust;
}
return 0;
}
/* Get Dynamic Memory Device Colum len */
STATIC uint32_t getColsLen(uint32_t DynConfig)
{
uint32_t DevBusWidth;
DevBusWidth = (DynConfig >> EMC_DYN_CONFIG_DEV_BUS_BIT) & 0x03;
if (DevBusWidth == 2) {
return 8;
}
else if (DevBusWidth == 1) {
return ((DynConfig >> (EMC_DYN_CONFIG_DEV_SIZE_BIT + 1)) & 0x03) + 8;
}
else if (DevBusWidth == 0) {
return ((DynConfig >> (EMC_DYN_CONFIG_DEV_SIZE_BIT + 1)) & 0x03) + 9;
}
return 0;
}
/* Initializes the Dynamic Controller according to the specified parameters
in the IP_EMC_DYN_CONFIG_T */
void initDynMem(LPC_EMC_T *pEMC, IP_EMC_DYN_CONFIG_T *Dynamic_Config, uint32_t EMC_Clock)
{
uint32_t ChipSelect, tmpclk;
int i;
for (ChipSelect = 0; ChipSelect < 4; ChipSelect++) {
LPC_EMC_T *EMC_Reg_add = (LPC_EMC_T *) ((uint32_t) pEMC + (ChipSelect << 5));
EMC_Reg_add->DYNAMICRASCAS0 = Dynamic_Config->DevConfig[ChipSelect].RAS |
((Dynamic_Config->DevConfig[ChipSelect].ModeRegister <<
(8 - EMC_DYN_MODE_CAS_BIT)) & 0xF00);
EMC_Reg_add->DYNAMICCONFIG0 = Dynamic_Config->DevConfig[ChipSelect].DynConfig;
}
pEMC->DYNAMICREADCONFIG = Dynamic_Config->ReadConfig; /* Read strategy */
pEMC->DYNAMICRP = convertTimmingParam(EMC_Clock, Dynamic_Config->tRP, 1);
pEMC->DYNAMICRAS = convertTimmingParam(EMC_Clock, Dynamic_Config->tRAS, 1);
pEMC->DYNAMICSREX = convertTimmingParam(EMC_Clock, Dynamic_Config->tSREX, 1);
pEMC->DYNAMICAPR = convertTimmingParam(EMC_Clock, Dynamic_Config->tAPR, 1);
pEMC->DYNAMICDAL = convertTimmingParam(EMC_Clock, Dynamic_Config->tDAL, 0);
pEMC->DYNAMICWR = convertTimmingParam(EMC_Clock, Dynamic_Config->tWR, 1);
pEMC->DYNAMICRC = convertTimmingParam(EMC_Clock, Dynamic_Config->tRC, 1);
pEMC->DYNAMICRFC = convertTimmingParam(EMC_Clock, Dynamic_Config->tRFC, 1);
pEMC->DYNAMICXSR = convertTimmingParam(EMC_Clock, Dynamic_Config->tXSR, 1);
pEMC->DYNAMICRRD = convertTimmingParam(EMC_Clock, Dynamic_Config->tRRD, 1);
pEMC->DYNAMICMRD = convertTimmingParam(EMC_Clock, Dynamic_Config->tMRD, 1);
/* TIM_Waitus(100); */
/*FIXME: if Timer driver is ready, it should replace below "for" delay technic */
for (i = 0; i < 1000; i++) { /* wait 100us */
}
pEMC->DYNAMICCONTROL = 0x00000183; /* Issue NOP command */
/* TIM_Waitus(200); */ /* wait 200us */
/*FIXME: if Timer driver is ready, it should replace below "for" delay technic */
for (i = 0; i < 1000; i++) {}
pEMC->DYNAMICCONTROL = 0x00000103; /* Issue PALL command */
pEMC->DYNAMICREFRESH = 2; /* ( 2 * 16 ) -> 32 clock cycles */
/* FIXME: TIM_Waitus(200); */ /* wait 200us */
for (i = 0; i < 80; i++) {}
tmpclk = EMC_DIV_ROUND_UP(convertTimmingParam(EMC_Clock, Dynamic_Config->RefreshPeriod, 0), 16);
pEMC->DYNAMICREFRESH = tmpclk;
pEMC->DYNAMICCONTROL = 0x00000083; /* Issue MODE command */
for (ChipSelect = 0; ChipSelect < 4; ChipSelect++) {
/*uint32_t burst_length;*/
uint32_t DynAddr;
uint8_t Col_len;
Col_len = getColsLen(Dynamic_Config->DevConfig[ChipSelect].DynConfig);
/* get bus wide: if 32bit, len is 4 else if 16bit len is 2 */
/* burst_length = 1 << ((((Dynamic_Config->DynConfig[ChipSelect] >> 14) & 1)^1) +1); */
if (Dynamic_Config->DevConfig[ChipSelect].DynConfig & (1 << EMC_DYN_CONFIG_DATA_BUS_WIDTH_BIT)) {
/*32bit bus */
/*burst_length = 2;*/
Col_len += 2;
}
else {
/*burst_length = 4;*/
Col_len += 1;
}
DynAddr = Dynamic_Config->DevConfig[ChipSelect].BaseAddr;
if (DynAddr != 0) {
uint32_t temp;
uint32_t ModeRegister;
ModeRegister = Dynamic_Config->DevConfig[ChipSelect].ModeRegister;
temp = *((volatile uint32_t *) (DynAddr | (ModeRegister << Col_len)));
temp = temp;
}
}
pEMC->DYNAMICCONTROL = 0x00000000; /* Issue NORMAL command */
/* enable buffers */
pEMC->DYNAMICCONFIG0 |= 1 << 19;
pEMC->DYNAMICCONFIG1 |= 1 << 19;
pEMC->DYNAMICCONFIG2 |= 1 << 19;
pEMC->DYNAMICCONFIG3 |= 1 << 19;
}
/* Initializes the Static Controller according to the specified parameters
* in the IP_EMC_STATIC_CONFIG_T
*/
void initStaticMem(LPC_EMC_T *pEMC, IP_EMC_STATIC_CONFIG_T *Static_Config, uint32_t EMC_Clock)
{
LPC_EMC_T *EMC_Reg_add = (LPC_EMC_T *) ((uint32_t) pEMC + ((Static_Config->ChipSelect) << 5));
EMC_Reg_add->STATICCONFIG0 = Static_Config->Config;
EMC_Reg_add->STATICWAITWEN0 = convertTimmingParam(EMC_Clock, Static_Config->WaitWen, 1);
EMC_Reg_add->STATICWAITOEN0 = convertTimmingParam(EMC_Clock, Static_Config->WaitOen, 0);
EMC_Reg_add->STATICWAITRD0 = convertTimmingParam(EMC_Clock, Static_Config->WaitRd, 1);
EMC_Reg_add->STATICWAITPAG0 = convertTimmingParam(EMC_Clock, Static_Config->WaitPage, 1);
EMC_Reg_add->STATICWAITWR0 = convertTimmingParam(EMC_Clock, Static_Config->WaitWr, 2);
EMC_Reg_add->STATICWAITTURN0 = convertTimmingParam(EMC_Clock, Static_Config->WaitTurn, 1);
}
/*****************************************************************************
* Public functions
****************************************************************************/
/* Dyanmic memory setup */
void Chip_EMC_Dynamic_Init(IP_EMC_DYN_CONFIG_T *Dynamic_Config)
{
uint32_t ClkFreq;
/* Note clocks must be enabled prior to this call */
ClkFreq = Chip_Clock_GetEMCClockRate();
initDynMem(LPC_EMC, Dynamic_Config, ClkFreq);
}
/* Enable Dynamic Memory Controller */
void Chip_EMC_Dynamic_Enable(uint8_t Enable)
{
if (Enable) {
LPC_EMC->DYNAMICCONTROL |= EMC_DYN_CONTROL_ENABLE;
}
else {
LPC_EMC->DYNAMICCONTROL &= ~EMC_DYN_CONTROL_ENABLE;
}
}
/* Static memory setup */
void Chip_EMC_Static_Init(IP_EMC_STATIC_CONFIG_T *Static_Config)
{
uint32_t ClkFreq;
/* Note clocks must be enabled prior to this call */
ClkFreq = Chip_Clock_GetEMCClockRate();
initStaticMem(LPC_EMC, Static_Config, ClkFreq);
}
/* Mirror CS1 to CS0 and DYCS0 */
void Chip_EMC_Mirror(uint8_t Enable)
{
if (Enable) {
LPC_EMC->CONTROL |= 1 << 1;
}
else {
LPC_EMC->CONTROL &= ~(1 << 1);
}
}
/* Enable EMC */
void Chip_EMC_Enable(uint8_t Enable)
{
if (Enable) {
LPC_EMC->CONTROL |= 1;
}
else {
LPC_EMC->CONTROL &= ~(1);
}
}
/* Set EMC LowPower Mode */
void Chip_EMC_LowPowerMode(uint8_t Enable)
{
if (Enable) {
LPC_EMC->CONTROL |= 1 << 2;
}
else {
LPC_EMC->CONTROL &= ~(1 << 2);
}
}
/* Initialize EMC */
void Chip_EMC_Init(uint32_t Enable, uint32_t ClockRatio, uint32_t EndianMode)
{
LPC_EMC->CONFIG = (EndianMode ? 1 : 0) | ((ClockRatio ? 1 : 0) << 8);
/* Enable EMC 001 Normal Memory Map, No low power mode */
LPC_EMC->CONTROL = (Enable ? 1 : 0);
}
#endif /* defined(CHIP_LPC177X_8X) || defined(CHIP_LPC40XX) */

View File

@@ -0,0 +1,289 @@
/*
* @brief LPC17xx/40xx ethernet driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/* Saved address for PHY and clock divider */
STATIC uint32_t phyAddr;
/* Divider index values for the MII PHY clock */
STATIC const uint8_t EnetClkDiv[] = {4, 6, 8, 10, 14, 20, 28, 36, 40, 44,
48, 52, 56, 60, 64};
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
STATIC INLINE void resetENET(LPC_ENET_T *pENET)
{
volatile uint32_t i;
#if defined(CHIP_LPC177X_8X) || defined(CHIP_LPC40XX)
Chip_SYSCTL_PeriphReset(SYSCTL_RESET_ENET);
#endif
/* Reset ethernet peripheral */
Chip_ENET_Reset(pENET);
for (i = 0; i < 100; i++) {}
}
/*****************************************************************************
* Public functions
****************************************************************************/
/* Basic Ethernet interface initialization */
void Chip_ENET_Init(LPC_ENET_T *pENET, bool useRMII)
{
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_ENET);
resetENET(pENET);
/* Initial MAC configuration for full duplex,
100Mbps, inter-frame gap use default values */
pENET->MAC.MAC1 = ENET_MAC1_PARF;
pENET->MAC.MAC2 = ENET_MAC2_FULLDUPLEX | ENET_MAC2_CRCEN | ENET_MAC2_PADCRCEN;
if (useRMII) {
pENET->CONTROL.COMMAND = ENET_COMMAND_FULLDUPLEX | ENET_COMMAND_PASSRUNTFRAME | ENET_COMMAND_RMII;
}
else {
pENET->CONTROL.COMMAND = ENET_COMMAND_FULLDUPLEX | ENET_COMMAND_PASSRUNTFRAME;
}
pENET->MAC.IPGT = ENET_IPGT_FULLDUPLEX;
pENET->MAC.IPGR = ENET_IPGR_P2_DEF;
pENET->MAC.SUPP = ENET_SUPP_100Mbps_SPEED;
pENET->MAC.MAXF = ENET_ETH_MAX_FLEN;
pENET->MAC.CLRT = ENET_CLRT_DEF;
/* Setup default filter */
pENET->CONTROL.COMMAND |= ENET_COMMAND_PASSRXFILTER;
/* Clear all MAC interrupts */
pENET->MODULE_CONTROL.INTCLEAR = 0xFFFF;
/* Disable MAC interrupts */
pENET->MODULE_CONTROL.INTENABLE = 0;
}
/* Ethernet interface shutdown */
void Chip_ENET_DeInit(LPC_ENET_T *pENET)
{
/* Disable packet reception */
pENET->MAC.MAC1 &= ~ENET_MAC1_RXENABLE;
pENET->CONTROL.COMMAND = 0;
/* Clear all MAC interrupts */
pENET->MODULE_CONTROL.INTCLEAR = 0xFFFF;
/* Disable MAC interrupts */
pENET->MODULE_CONTROL.INTENABLE = 0;
Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_ENET);
}
/* Sets up the PHY link clock divider and PHY address */
void Chip_ENET_SetupMII(LPC_ENET_T *pENET, uint32_t div, uint8_t addr)
{
/* Save clock divider and PHY address in MII address register */
phyAddr = ENET_MADR_PHYADDR(addr);
/* Write to MII configuration register and reset */
pENET->MAC.MCFG = ENET_MCFG_CLOCKSEL(div) | ENET_MCFG_RES_MII;
/* release reset */
pENET->MAC.MCFG &= ~(ENET_MCFG_RES_MII);
}
/* Find the divider index for a desired MII clock rate */
uint32_t Chip_ENET_FindMIIDiv(LPC_ENET_T *pENET, uint32_t clockRate)
{
uint32_t tmp, divIdx = 0;
/* Find desired divider value */
tmp = Chip_Clock_GetENETClockRate() / clockRate;
/* Determine divider index from desired divider */
for (divIdx = 0; divIdx < (sizeof(EnetClkDiv) / sizeof(EnetClkDiv[0])); divIdx++) {
/* Closest index, but not higher than desired rate */
if (EnetClkDiv[divIdx] >= tmp) {
return divIdx;
}
}
/* Use maximum divider index */
return (sizeof(EnetClkDiv) / sizeof(EnetClkDiv[0])) - 1;
}
/* Starts a PHY write via the MII */
void Chip_ENET_StartMIIWrite(LPC_ENET_T *pENET, uint8_t reg, uint16_t data)
{
/* Write value at PHY address and register */
pENET->MAC.MCMD = 0;
pENET->MAC.MADR = phyAddr | ENET_MADR_REGADDR(reg);
pENET->MAC.MWTD = data;
}
/*Starts a PHY read via the MII */
void Chip_ENET_StartMIIRead(LPC_ENET_T *pENET, uint8_t reg)
{
/* Read value at PHY address and register */
pENET->MAC.MADR = phyAddr | ENET_MADR_REGADDR(reg);
pENET->MAC.MCMD = ENET_MCMD_READ;
}
/* Read MII data */
uint16_t Chip_ENET_ReadMIIData(LPC_ENET_T *pENET)
{
pENET->MAC.MCMD = 0;
return pENET->MAC.MRDD;
}
/* Sets full duplex for the ENET interface */
void Chip_ENET_SetFullDuplex(LPC_ENET_T *pENET)
{
pENET->MAC.MAC2 |= ENET_MAC2_FULLDUPLEX;
pENET->CONTROL.COMMAND |= ENET_COMMAND_FULLDUPLEX;
pENET->MAC.IPGT = ENET_IPGT_FULLDUPLEX;
}
/* Sets half duplex for the ENET interface */
void Chip_ENET_SetHalfDuplex(LPC_ENET_T *pENET)
{
pENET->MAC.MAC2 &= ~ENET_MAC2_FULLDUPLEX;
pENET->CONTROL.COMMAND &= ~ENET_COMMAND_FULLDUPLEX;
pENET->MAC.IPGT = ENET_IPGT_HALFDUPLEX;
}
/* Configures the initial ethernet transmit descriptors */
void Chip_ENET_InitTxDescriptors(LPC_ENET_T *pENET,
ENET_TXDESC_T *pDescs,
ENET_TXSTAT_T *pStatus,
uint32_t descNum)
{
/* Setup descriptor list base addresses */
pENET->CONTROL.TX.DESCRIPTOR = (uint32_t) pDescs;
pENET->CONTROL.TX.DESCRIPTORNUMBER = descNum - 1;
pENET->CONTROL.TX.STATUS = (uint32_t) pStatus;
pENET->CONTROL.TX.PRODUCEINDEX = 0;
}
/* Configures the initial ethernet receive descriptors */
void Chip_ENET_InitRxDescriptors(LPC_ENET_T *pENET,
ENET_RXDESC_T *pDescs,
ENET_RXSTAT_T *pStatus,
uint32_t descNum)
{
/* Setup descriptor list base addresses */
pENET->CONTROL.RX.DESCRIPTOR = (uint32_t) pDescs;
pENET->CONTROL.RX.DESCRIPTORNUMBER = descNum - 1;
pENET->CONTROL.RX.STATUS = (uint32_t) pStatus;
pENET->CONTROL.RX.CONSUMEINDEX = 0;
}
/* Get status for the descriptor list */
ENET_BUFF_STATUS_T Chip_ENET_GetBufferStatus(LPC_ENET_T *pENET,
uint16_t produceIndex,
uint16_t consumeIndex,
uint16_t buffSize)
{
/* Empty descriptor list */
if (consumeIndex == produceIndex) {
return ENET_BUFF_EMPTY;
}
/* Full descriptor list */
if ((consumeIndex == 0) &&
(produceIndex == (buffSize - 1))) {
return ENET_BUFF_FULL;
}
/* Wrap-around, full descriptor list */
if (consumeIndex == (produceIndex + 1)) {
return ENET_BUFF_FULL;
}
return ENET_BUFF_PARTIAL_FULL;
}
/* Get the number of descriptor filled */
uint32_t Chip_ENET_GetFillDescNum(LPC_ENET_T *pENET, uint16_t produceIndex, uint16_t consumeIndex, uint16_t buffSize)
{
/* Empty descriptor list */
if (consumeIndex == produceIndex) {
return 0;
}
if (consumeIndex > produceIndex) {
return (buffSize - consumeIndex) + produceIndex;
}
return produceIndex - consumeIndex;
}
/* Increase the current Tx Produce Descriptor Index */
uint16_t Chip_ENET_IncTXProduceIndex(LPC_ENET_T *pENET)
{
/* Get current TX produce index */
uint32_t idx = pENET->CONTROL.TX.PRODUCEINDEX;
/* Start frame transmission by incrementing descriptor */
idx++;
if (idx > pENET->CONTROL.TX.DESCRIPTORNUMBER) {
idx = 0;
}
pENET->CONTROL.TX.PRODUCEINDEX = idx;
return idx;
}
/* Increase the current Rx Consume Descriptor Index */
uint16_t Chip_ENET_IncRXConsumeIndex(LPC_ENET_T *pENET)
{
/* Get current RX consume index */
uint32_t idx = pENET->CONTROL.RX.CONSUMEINDEX;
/* Consume descriptor */
idx++;
if (idx > pENET->CONTROL.RX.DESCRIPTORNUMBER) {
idx = 0;
}
pENET->CONTROL.RX.CONSUMEINDEX = idx;
return idx;
}

View File

@@ -0,0 +1,704 @@
/*
* @brief LPC17xx/40xx GPDMA driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/* Channel array to monitor free channel */
static DMA_ChannelHandle_t ChannelHandlerArray[GPDMA_NUMBER_CHANNELS];
#if defined(CHIP_LPC177X_8X) || defined(CHIP_LPC40XX)
/* Optimized Peripheral Source and Destination burst size (177x_8x,407x_8x) */
static const uint8_t GPDMA_LUTPerBurst[] = {
0, /* Reserved */
GPDMA_BSIZE_8, /* SD Card */
GPDMA_BSIZE_4, /* SSP0 Tx */
GPDMA_BSIZE_4, /* SSP0 Rx */
GPDMA_BSIZE_4, /* SSP1 Tx */
GPDMA_BSIZE_4, /* SSP1 Rx */
GPDMA_BSIZE_4, /* SSP2 Tx */
GPDMA_BSIZE_4, /* SSP2 Rx */
GPDMA_BSIZE_1, /* ADC */
GPDMA_BSIZE_1, /* DAC */
GPDMA_BSIZE_1, /* UART0 Tx */
GPDMA_BSIZE_1, /* UART0 Rx */
GPDMA_BSIZE_1, /* UART1 Tx */
GPDMA_BSIZE_1, /* UART1 Rx */
GPDMA_BSIZE_1, /* UART2 Tx */
GPDMA_BSIZE_1, /* UART2 Rx */
GPDMA_BSIZE_1, /* MAT0.0 */
GPDMA_BSIZE_1, /* MAT0.1 */
GPDMA_BSIZE_1, /* MAT1.0 */
GPDMA_BSIZE_1, /* MAT1.1 */
GPDMA_BSIZE_1, /* MAT2.0 */
GPDMA_BSIZE_1, /* MAT2.1 */
GPDMA_BSIZE_32, /* I2S channel 0 */
GPDMA_BSIZE_32, /* I2S channel 1 */
0, /* Reserved */
0, /* Reserved */
GPDMA_BSIZE_1, /* UART3 Tx */
GPDMA_BSIZE_1, /* UART3 Rx */
GPDMA_BSIZE_1, /* UART4 Tx */
GPDMA_BSIZE_1, /* UART4 Rx */
GPDMA_BSIZE_1, /* MAT3.0 */
GPDMA_BSIZE_1, /* MAT3.1 */
};
/* Optimized Peripheral Source and Destination transfer width (177x_8x,407x_8x) */
static const uint8_t GPDMA_LUTPerWid[] = {
0, /* Reserved */
GPDMA_WIDTH_WORD, /* SD Card */
GPDMA_WIDTH_BYTE, /* SSP0 Tx */
GPDMA_WIDTH_BYTE, /* SSP0 Rx */
GPDMA_WIDTH_BYTE, /* SSP1 Tx */
GPDMA_WIDTH_BYTE, /* SSP1 Rx */
GPDMA_WIDTH_BYTE, /* SSP2 Tx */
GPDMA_WIDTH_BYTE, /* SSP2 Rx */
GPDMA_WIDTH_WORD, /* ADC */
GPDMA_WIDTH_HALFWORD, /* DAC */
GPDMA_WIDTH_BYTE, /* UART0 Tx */
GPDMA_WIDTH_BYTE, /* UART0 Rx */
GPDMA_WIDTH_BYTE, /* UART1 Tx */
GPDMA_WIDTH_BYTE, /* UART1 Rx */
GPDMA_WIDTH_BYTE, /* UART2 Tx */
GPDMA_WIDTH_BYTE, /* UART2 Rx */
GPDMA_WIDTH_WORD, /* MAT0.0 */
GPDMA_WIDTH_WORD, /* MAT0.1 */
GPDMA_WIDTH_WORD, /* MAT1.0 */
GPDMA_WIDTH_WORD, /* MAT1.1 */
GPDMA_WIDTH_WORD, /* MAT2.0 */
GPDMA_WIDTH_WORD, /* MAT2.1 */
GPDMA_WIDTH_WORD, /* I2S channel 0 */
GPDMA_WIDTH_WORD, /* I2S channel 1 */
0, /* Reserved */
0, /* Reserved */
GPDMA_WIDTH_BYTE, /* UART3 Tx */
GPDMA_WIDTH_BYTE, /* UART3 Rx */
GPDMA_WIDTH_BYTE, /* UART4 Tx */
GPDMA_WIDTH_BYTE, /* UART4 Rx */
GPDMA_WIDTH_WORD, /* MAT3.0 */
GPDMA_WIDTH_WORD, /* MAT3.1 */
};
/* Lookup Table of Connection Type matched with (177x_8x,407x_8x) Peripheral Data (FIFO) register base address */
volatile static const void *GPDMA_LUTPerAddr[] = {
0, /* Reserved */
(&LPC_SDC->FIFO), /* SD Card */
(&LPC_SSP0->DR), /* SSP0 Tx */
(&LPC_SSP0->DR), /* SSP0 Rx */
(&LPC_SSP1->DR), /* SSP1 Tx */
(&LPC_SSP1->DR), /* SSP1 Rx */
(&LPC_SSP2->DR), /* SSP2 Tx */
(&LPC_SSP2->DR), /* SSP2 Rx */
(&LPC_ADC->GDR), /* ADC */
(&LPC_DAC->CR), /* DAC */
(&LPC_UART0-> /*RBTHDLR.*/ THR), /* UART0 Tx */
(&LPC_UART0-> /*RBTHDLR.*/ RBR), /* UART0 Rx */
(&LPC_UART1-> /*RBTHDLR.*/ THR), /* UART1 Tx */
(&LPC_UART1-> /*RBTHDLR.*/ RBR), /* UART1 Rx */
(&LPC_UART2-> /*RBTHDLR.*/ THR), /* UART2 Tx */
(&LPC_UART2-> /*RBTHDLR.*/ RBR), /* UART2 Rx */
(&LPC_TIMER0->MR[0]), /* MAT0.0 */
(&LPC_TIMER0->MR[1]), /* MAT0.1 */
(&LPC_TIMER1->MR[0]), /* MAT1.0 */
(&LPC_TIMER1->MR[1]), /* MAT1.1 */
(&LPC_TIMER2->MR[0]), /* MAT2.0 */
(&LPC_TIMER2->MR[1]), /* MAT2.1 */
(&LPC_I2S->TXFIFO), /* I2S Tx */
(&LPC_I2S->RXFIFO), /* I2S Rx */
0, /* Reverse */
0, /* Reverse */
(&LPC_UART3-> /*RBTHDLR.*/ THR), /* UART3 Tx */
(&LPC_UART3-> /*RBTHDLR.*/ RBR), /* UART3 Rx */
(&LPC_UART4-> /*RBTHDLR.*/ THR), /* UART4 Tx */
(&LPC_UART4-> /*RBTHDLR.*/ RBR), /* UART4 Rx */
(&LPC_TIMER3->MR[0]), /* MAT3.0 */
(&LPC_TIMER3->MR[1]) /* MAT3.1 */
};
#elif defined(CHIP_LPC175X_6X)
const uint8_t GPDMA_LUTPerBurst[] = {
GPDMA_BSIZE_4, // SSP0 Tx
GPDMA_BSIZE_4, // SSP0 Rx
GPDMA_BSIZE_4, // SSP1 Tx
GPDMA_BSIZE_4, // SSP1 Rx
GPDMA_BSIZE_1, // ADC
GPDMA_BSIZE_32, // I2S channel 0
GPDMA_BSIZE_32, // I2S channel 1
GPDMA_BSIZE_1, // DAC
GPDMA_BSIZE_1, // UART0 Tx
GPDMA_BSIZE_1, // UART0 Rx
GPDMA_BSIZE_1, // UART1 Tx
GPDMA_BSIZE_1, // UART1 Rx
GPDMA_BSIZE_1, // UART2 Tx
GPDMA_BSIZE_1, // UART2 Rx
GPDMA_BSIZE_1, // UART3 Tx
GPDMA_BSIZE_1, // UART3 Rx
GPDMA_BSIZE_1, // MAT0.0
GPDMA_BSIZE_1, // MAT0.1
GPDMA_BSIZE_1, // MAT1.0
GPDMA_BSIZE_1, // MAT1.1
GPDMA_BSIZE_1, // MAT2.0
GPDMA_BSIZE_1, // MAT2.1
GPDMA_BSIZE_1, // MAT3.0
GPDMA_BSIZE_1 // MAT3.1
};
/**
* @brief Optimized Peripheral Source and Destination transfer width
*/
const uint8_t GPDMA_LUTPerWid[] = {
GPDMA_WIDTH_BYTE, // SSP0 Tx
GPDMA_WIDTH_BYTE, // SSP0 Rx
GPDMA_WIDTH_BYTE, // SSP1 Tx
GPDMA_WIDTH_BYTE, // SSP1 Rx
GPDMA_WIDTH_WORD, // ADC
GPDMA_WIDTH_WORD, // I2S channel 0
GPDMA_WIDTH_WORD, // I2S channel 1
GPDMA_WIDTH_HALFWORD, // DAC
GPDMA_WIDTH_BYTE, // UART0 Tx
GPDMA_WIDTH_BYTE, // UART0 Rx
GPDMA_WIDTH_BYTE, // UART1 Tx
GPDMA_WIDTH_BYTE, // UART1 Rx
GPDMA_WIDTH_BYTE, // UART2 Tx
GPDMA_WIDTH_BYTE, // UART2 Rx
GPDMA_WIDTH_BYTE, // UART3 Tx
GPDMA_WIDTH_BYTE, // UART3 Rx
GPDMA_WIDTH_WORD, // MAT0.0
GPDMA_WIDTH_WORD, // MAT0.1
GPDMA_WIDTH_WORD, // MAT1.0
GPDMA_WIDTH_WORD, // MAT1.1
GPDMA_WIDTH_WORD, // MAT2.0
GPDMA_WIDTH_WORD, // MAT2.1
GPDMA_WIDTH_WORD, // MAT3.0
GPDMA_WIDTH_WORD // MAT3.1
};
/**
* @brief Peripheral Source and Destination address
*/
volatile const void *GPDMA_LUTPerAddr[] = {
(&LPC_SSP0->DR), // SSP0 Tx
(&LPC_SSP0->DR), // SSP0 Rx
(&LPC_SSP1->DR), // SSP1 Tx
(&LPC_SSP1->DR), // SSP1 Rx
(&LPC_ADC->GDR), // ADC
(&LPC_I2S->TXFIFO), // I2S Tx
(&LPC_I2S->RXFIFO), // I2S Rx
(&LPC_DAC->CR), // DAC
(&LPC_UART0-> /*RBTHDLR.*/ THR), // UART0 Tx
(&LPC_UART0-> /*RBTHDLR.*/ RBR), // UART0 Rx
(&LPC_UART1-> /*RBTHDLR.*/ THR), // UART1 Tx
(&LPC_UART1-> /*RBTHDLR.*/ RBR), // UART1 Rx
(&LPC_UART2-> /*RBTHDLR.*/ THR), // UART2 Tx
(&LPC_UART2-> /*RBTHDLR.*/ RBR), // UART2 Rx
(&LPC_UART3-> /*RBTHDLR.*/ THR), // UART3 Tx
(&LPC_UART3-> /*RBTHDLR.*/ RBR), // UART3 Rx
(&LPC_TIMER0->MR[0]), // MAT0.0
(&LPC_TIMER0->MR[1]), // MAT0.1
(&LPC_TIMER1->MR[0]), // MAT1.0
(&LPC_TIMER1->MR[1]), // MAT1.1
(&LPC_TIMER2->MR[0]), // MAT2.0
(&LPC_TIMER2->MR[1]), // MAT2.1
(&LPC_TIMER3->MR[0]), // MAT3.0
(&LPC_TIMER3->MR[1]) // MAT3.1
};
#endif
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/* Control which set of peripherals is connected to the DMA controller */
STATIC uint8_t configDMAMux(uint32_t gpdma_peripheral_connection_number)
{
#if defined(CHIP_LPC175X_6X)
if (gpdma_peripheral_connection_number > 15) {
LPC_SYSCTL->DMAREQSEL |= (1 << (gpdma_peripheral_connection_number - 16));
return gpdma_peripheral_connection_number - 8;
}
else {
if (gpdma_peripheral_connection_number > 7) {
LPC_SYSCTL->DMAREQSEL &= ~(1 << (gpdma_peripheral_connection_number - 8));
}
return gpdma_peripheral_connection_number;
}
#elif defined(CHIP_LPC177X_8X) || defined(CHIP_LPC40XX)
if (gpdma_peripheral_connection_number > 15) {
LPC_SYSCTL->DMAREQSEL |= (1 << (gpdma_peripheral_connection_number - 16));
return gpdma_peripheral_connection_number - 16;
}
else {
LPC_SYSCTL->DMAREQSEL &= ~(1 << (gpdma_peripheral_connection_number));
return gpdma_peripheral_connection_number;
}
#endif
}
uint32_t makeCtrlWord(const GPDMA_CH_CFG_T *GPDMAChannelConfig,
uint32_t GPDMA_LUTPerBurstSrcConn,
uint32_t GPDMA_LUTPerBurstDstConn,
uint32_t GPDMA_LUTPerWidSrcConn,
uint32_t GPDMA_LUTPerWidDstConn)
{
uint32_t ctrl_word = 0;
switch (GPDMAChannelConfig->TransferType) {
/* Memory to memory */
case GPDMA_TRANSFERTYPE_M2M_CONTROLLER_DMA:
ctrl_word = GPDMA_DMACCxControl_TransferSize(GPDMAChannelConfig->TransferSize)
| GPDMA_DMACCxControl_SBSize((4UL)) /**< Burst size = 32 */
| GPDMA_DMACCxControl_DBSize((4UL)) /**< Burst size = 32 */
| GPDMA_DMACCxControl_SWidth(GPDMAChannelConfig->TransferWidth)
| GPDMA_DMACCxControl_DWidth(GPDMAChannelConfig->TransferWidth)
| GPDMA_DMACCxControl_SI
| GPDMA_DMACCxControl_DI
| GPDMA_DMACCxControl_I;
break;
case GPDMA_TRANSFERTYPE_M2P_CONTROLLER_DMA:
case GPDMA_TRANSFERTYPE_M2P_CONTROLLER_PERIPHERAL:
ctrl_word = GPDMA_DMACCxControl_TransferSize((uint32_t) GPDMAChannelConfig->TransferSize)
| GPDMA_DMACCxControl_SBSize(GPDMA_LUTPerBurstDstConn)
| GPDMA_DMACCxControl_DBSize(GPDMA_LUTPerBurstDstConn)
| GPDMA_DMACCxControl_SWidth(GPDMA_LUTPerWidDstConn)
| GPDMA_DMACCxControl_DWidth(GPDMA_LUTPerWidDstConn)
| GPDMA_DMACCxControl_DestTransUseAHBMaster1
| GPDMA_DMACCxControl_SI
| GPDMA_DMACCxControl_I;
break;
case GPDMA_TRANSFERTYPE_P2M_CONTROLLER_DMA:
case GPDMA_TRANSFERTYPE_P2M_CONTROLLER_PERIPHERAL:
ctrl_word = GPDMA_DMACCxControl_TransferSize((uint32_t) GPDMAChannelConfig->TransferSize)
| GPDMA_DMACCxControl_SBSize(GPDMA_LUTPerBurstSrcConn)
| GPDMA_DMACCxControl_DBSize(GPDMA_LUTPerBurstSrcConn)
| GPDMA_DMACCxControl_SWidth(GPDMA_LUTPerWidSrcConn)
| GPDMA_DMACCxControl_DWidth(GPDMA_LUTPerWidSrcConn)
| GPDMA_DMACCxControl_SrcTransUseAHBMaster1
| GPDMA_DMACCxControl_DI
| GPDMA_DMACCxControl_I;
break;
case GPDMA_TRANSFERTYPE_P2P_CONTROLLER_DMA:
case GPDMA_TRANSFERTYPE_P2P_CONTROLLER_DestPERIPHERAL:
case GPDMA_TRANSFERTYPE_P2P_CONTROLLER_SrcPERIPHERAL:
ctrl_word = GPDMA_DMACCxControl_TransferSize((uint32_t) GPDMAChannelConfig->TransferSize)
| GPDMA_DMACCxControl_SBSize(GPDMA_LUTPerBurstSrcConn)
| GPDMA_DMACCxControl_DBSize(GPDMA_LUTPerBurstDstConn)
| GPDMA_DMACCxControl_SWidth(GPDMA_LUTPerWidSrcConn)
| GPDMA_DMACCxControl_DWidth(GPDMA_LUTPerWidDstConn)
| GPDMA_DMACCxControl_SrcTransUseAHBMaster1
| GPDMA_DMACCxControl_DestTransUseAHBMaster1
| GPDMA_DMACCxControl_I;
break;
/* Do not support any more transfer type, return ERROR */
default:
return ERROR;
}
return ctrl_word;
}
/* Set up the DPDMA according to the specification configuration details */
Status setupChannel(LPC_GPDMA_T *pGPDMA,
GPDMA_CH_CFG_T *GPDMAChannelConfig,
uint32_t CtrlWord,
uint32_t LinkListItem,
uint8_t SrcPeripheral,
uint8_t DstPeripheral)
{
GPDMA_CH_T *pDMAch;
if (pGPDMA->ENBLDCHNS & ((((1UL << (GPDMAChannelConfig->ChannelNum)) & 0xFF)))) {
/* This channel is enabled, return ERROR, need to release this channel first */
return ERROR;
}
/* Get Channel pointer */
pDMAch = (GPDMA_CH_T *) &(pGPDMA->CH[GPDMAChannelConfig->ChannelNum]);
/* Reset the Interrupt status */
pGPDMA->INTTCCLEAR = (((1UL << (GPDMAChannelConfig->ChannelNum)) & 0xFF));
pGPDMA->INTERRCLR = (((1UL << (GPDMAChannelConfig->ChannelNum)) & 0xFF));
/* Assign Linker List Item value */
pDMAch->LLI = LinkListItem;
/* Enable DMA channels, little endian */
pGPDMA->CONFIG = GPDMA_DMACConfig_E;
while (!(pGPDMA->CONFIG & GPDMA_DMACConfig_E)) {}
pDMAch->SRCADDR = GPDMAChannelConfig->SrcAddr;
pDMAch->DESTADDR = GPDMAChannelConfig->DstAddr;
/* Configure DMA Channel, enable Error Counter and Terminate counter */
pDMAch->CONFIG = GPDMA_DMACCxConfig_IE
| GPDMA_DMACCxConfig_ITC /*| GPDMA_DMACCxConfig_E*/
| GPDMA_DMACCxConfig_TransferType((uint32_t) GPDMAChannelConfig->TransferType)
| GPDMA_DMACCxConfig_SrcPeripheral(SrcPeripheral)
| GPDMA_DMACCxConfig_DestPeripheral(DstPeripheral);
pDMAch->CONTROL = CtrlWord;
return SUCCESS;
}
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initialize the GPDMA */
void Chip_GPDMA_Init(LPC_GPDMA_T *pGPDMA)
{
uint8_t i;
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_GPDMA);
/* Reset all channel configuration register */
for (i = 8; i > 0; i--) {
pGPDMA->CH[i - 1].CONFIG = 0;
}
/* Clear all DMA interrupt and error flag */
pGPDMA->INTTCCLEAR = 0xFF;
pGPDMA->INTERRCLR = 0xFF;
/* Reset all channels are free */
for (i = 0; i < GPDMA_NUMBER_CHANNELS; i++) {
ChannelHandlerArray[i].ChannelStatus = DISABLE;
}
}
/* Shutdown the GPDMA */
void Chip_GPDMA_DeInit(LPC_GPDMA_T *pGPDMA)
{
Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_GPDMA);
}
/* Stop a stream DMA transfer */
void Chip_GPDMA_Stop(LPC_GPDMA_T *pGPDMA,
uint8_t ChannelNum)
{
Chip_GPDMA_ChannelCmd(pGPDMA, (ChannelNum), DISABLE);
if (Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_INTTC, ChannelNum)) {
/* Clear terminate counter Interrupt pending */
Chip_GPDMA_ClearIntPending(pGPDMA, GPDMA_STATCLR_INTTC, ChannelNum);
}
if (Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_INTERR, ChannelNum)) {
/* Clear terminate counter Interrupt pending */
Chip_GPDMA_ClearIntPending(pGPDMA, GPDMA_STATCLR_INTERR, ChannelNum);
}
ChannelHandlerArray[ChannelNum].ChannelStatus = DISABLE;
}
/* The GPDMA stream interrupt status checking */
Status Chip_GPDMA_Interrupt(LPC_GPDMA_T *pGPDMA,
uint8_t ChannelNum)
{
if (Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_INT, ChannelNum)) {
/* Check counter terminal status */
if (Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_INTTC, ChannelNum)) {
/* Clear terminate counter Interrupt pending */
Chip_GPDMA_ClearIntPending(pGPDMA, GPDMA_STATCLR_INTTC, ChannelNum);
return SUCCESS;
}
/* Check error terminal status */
if (Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_INTERR, ChannelNum)) {
/* Clear error counter Interrupt pending */
Chip_GPDMA_ClearIntPending(pGPDMA, GPDMA_STATCLR_INTERR, ChannelNum);
return ERROR;
}
}
return ERROR;
}
int Chip_GPDMA_InitChannelCfg(LPC_GPDMA_T *pGPDMA,
GPDMA_CH_CFG_T *GPDMACfg,
uint8_t ChannelNum,
uint32_t src,
uint32_t dst,
uint32_t Size,
GPDMA_FLOW_CONTROL_T TransferType)
{
int rval = -1;
GPDMACfg->ChannelNum = ChannelNum;
GPDMACfg->TransferType = TransferType;
GPDMACfg->TransferSize = Size;
switch (TransferType) {
case GPDMA_TRANSFERTYPE_M2M_CONTROLLER_DMA:
GPDMACfg->SrcAddr = (uint32_t) src;
GPDMACfg->DstAddr = (uint32_t) dst;
rval = 3;
GPDMACfg->TransferWidth = GPDMA_WIDTH_WORD;
GPDMACfg->TransferSize = Size / 4;
break;
case GPDMA_TRANSFERTYPE_M2P_CONTROLLER_DMA:
case GPDMA_TRANSFERTYPE_M2P_CONTROLLER_PERIPHERAL:
GPDMACfg->SrcAddr = (uint32_t) src;
rval = 1;
GPDMACfg->DstAddr = (uint32_t) GPDMA_LUTPerAddr[dst];
break;
case GPDMA_TRANSFERTYPE_P2M_CONTROLLER_DMA:
case GPDMA_TRANSFERTYPE_P2M_CONTROLLER_PERIPHERAL:
GPDMACfg->SrcAddr = (uint32_t) GPDMA_LUTPerAddr[src];
GPDMACfg->DstAddr = (uint32_t) dst;
rval = 2;
break;
case GPDMA_TRANSFERTYPE_P2P_CONTROLLER_DMA:
case GPDMA_TRANSFERTYPE_P2P_CONTROLLER_DestPERIPHERAL:
case GPDMA_TRANSFERTYPE_P2P_CONTROLLER_SrcPERIPHERAL:
GPDMACfg->SrcAddr = (uint32_t) GPDMA_LUTPerAddr[src];
GPDMACfg->DstAddr = (uint32_t) GPDMA_LUTPerAddr[dst];
rval = 0;
break;
default:
break;
}
return rval;
}
/* Read the status from different registers according to the type */
IntStatus Chip_GPDMA_IntGetStatus(LPC_GPDMA_T *pGPDMA, GPDMA_STATUS_T type, uint8_t channel)
{
/**
* TODO check the channel <=8 type is exited
*/
switch (type) {
case GPDMA_STAT_INT:/* check status of DMA channel interrupts */
return (IntStatus) (pGPDMA->INTSTAT & (((1UL << channel) & 0xFF)));
case GPDMA_STAT_INTTC: /* check terminal count interrupt request status for DMA */
return (IntStatus) (pGPDMA->INTTCSTAT & (((1UL << channel) & 0xFF)));
case GPDMA_STAT_INTERR: /* check interrupt status for DMA channels */
return (IntStatus) (pGPDMA->INTERRSTAT & (((1UL << channel) & 0xFF)));
case GPDMA_STAT_RAWINTTC: /* check status of the terminal count interrupt for DMA channels */
return (IntStatus) (pGPDMA->RAWINTTCSTAT & (((1UL << channel) & 0xFF)));
case GPDMA_STAT_RAWINTERR: /* check status of the error interrupt for DMA channels */
return (IntStatus) (pGPDMA->RAWINTERRSTAT & (((1UL << channel) & 0xFF)));
default:/* check enable status for DMA channels */
return (IntStatus) (pGPDMA->ENBLDCHNS & (((1UL << channel) & 0xFF)));
}
}
/* Clear the Interrupt Flag from different registers according to the type */
void Chip_GPDMA_ClearIntPending(LPC_GPDMA_T *pGPDMA, GPDMA_STATECLEAR_T type, uint8_t channel)
{
if (type == GPDMA_STATCLR_INTTC) {
/* clears the terminal count interrupt request on DMA channel */
pGPDMA->INTTCCLEAR = (((1UL << (channel)) & 0xFF));
}
else {
/* clear the error interrupt request */
pGPDMA->INTERRCLR = (((1UL << (channel)) & 0xFF));
}
}
/* Enable or Disable the GPDMA Channel */
void Chip_GPDMA_ChannelCmd(LPC_GPDMA_T *pGPDMA, uint8_t channelNum, FunctionalState NewState)
{
GPDMA_CH_T *pDMAch;
/* Get Channel pointer */
pDMAch = (GPDMA_CH_T *) &(pGPDMA->CH[channelNum]);
if (NewState == ENABLE) {
pDMAch->CONFIG |= GPDMA_DMACCxConfig_E;
}
else {
pDMAch->CONFIG &= ~GPDMA_DMACCxConfig_E;
}
}
/* Do a DMA transfer M2M, M2P,P2M or P2P */
Status Chip_GPDMA_Transfer(LPC_GPDMA_T *pGPDMA,
uint8_t ChannelNum,
uint32_t src,
uint32_t dst,
GPDMA_FLOW_CONTROL_T TransferType,
uint32_t Size)
{
GPDMA_CH_CFG_T GPDMACfg;
uint8_t SrcPeripheral = 0, DstPeripheral = 0;
uint32_t cwrd;
int ret;
ret = Chip_GPDMA_InitChannelCfg(pGPDMA, &GPDMACfg, ChannelNum, src, dst, Size, TransferType);
if (ret < 0) {
return ERROR;
}
/* Adjust src/dst index if they are memory */
if (ret & 1) {
src = 0;
}
else {
SrcPeripheral = configDMAMux(src);
}
if (ret & 2) {
dst = 0;
}
else {
DstPeripheral = configDMAMux(dst);
}
cwrd = makeCtrlWord(&GPDMACfg,
(uint32_t) GPDMA_LUTPerBurst[src],
(uint32_t) GPDMA_LUTPerBurst[dst],
(uint32_t) GPDMA_LUTPerWid[src],
(uint32_t) GPDMA_LUTPerWid[dst]);
if (setupChannel(pGPDMA, &GPDMACfg, cwrd, 0, SrcPeripheral, DstPeripheral) == ERROR) {
return ERROR;
}
/* Start the Channel */
Chip_GPDMA_ChannelCmd(pGPDMA, ChannelNum, ENABLE);
return SUCCESS;
}
Status Chip_GPDMA_PrepareDescriptor(LPC_GPDMA_T *pGPDMA,
DMA_TransferDescriptor_t *DMADescriptor,
uint32_t src,
uint32_t dst,
uint32_t Size,
GPDMA_FLOW_CONTROL_T TransferType,
const DMA_TransferDescriptor_t *NextDescriptor)
{
int ret;
GPDMA_CH_CFG_T GPDMACfg;
ret = Chip_GPDMA_InitChannelCfg(pGPDMA, &GPDMACfg, 0, src, dst, Size, TransferType);
if (ret < 0) {
return ERROR;
}
/* Adjust src/dst index if they are memory */
if (ret & 1) {
src = 0;
}
if (ret & 2) {
dst = 0;
}
DMADescriptor->src = GPDMACfg.SrcAddr;
DMADescriptor->dst = GPDMACfg.DstAddr;
DMADescriptor->lli = (uint32_t) NextDescriptor;
DMADescriptor->ctrl = makeCtrlWord(&GPDMACfg,
(uint32_t) GPDMA_LUTPerBurst[src],
(uint32_t) GPDMA_LUTPerBurst[dst],
(uint32_t) GPDMA_LUTPerWid[src],
(uint32_t) GPDMA_LUTPerWid[dst]);
/* By default set interrupt only for last transfer */
if (NextDescriptor) {
DMADescriptor->ctrl &= ~GPDMA_DMACCxControl_I;
}
return SUCCESS;
}
/* Do a DMA scatter-gather transfer M2M, M2P,P2M or P2P using DMA descriptors */
Status Chip_GPDMA_SGTransfer(LPC_GPDMA_T *pGPDMA,
uint8_t ChannelNum,
const DMA_TransferDescriptor_t *DMADescriptor,
GPDMA_FLOW_CONTROL_T TransferType)
{
const DMA_TransferDescriptor_t *dsc = DMADescriptor;
GPDMA_CH_CFG_T GPDMACfg;
uint8_t SrcPeripheral = 0, DstPeripheral = 0;
uint32_t src = DMADescriptor->src, dst = DMADescriptor->dst;
int ret;
ret = Chip_GPDMA_InitChannelCfg(pGPDMA, &GPDMACfg, ChannelNum, src, dst, 0, TransferType);
if (ret < 0) {
return ERROR;
}
/* Adjust src/dst index if they are memory */
if (ret & 1) {
src = 0;
}
else {
SrcPeripheral = configDMAMux(src);
}
if (ret & 2) {
dst = 0;
}
else {
DstPeripheral = configDMAMux(dst);
}
if (setupChannel(pGPDMA, &GPDMACfg, dsc->ctrl, dsc->lli, SrcPeripheral, DstPeripheral) == ERROR) {
return ERROR;
}
/* Start the Channel */
Chip_GPDMA_ChannelCmd(pGPDMA, ChannelNum, ENABLE);
return SUCCESS;
}
/* Get a free GPDMA channel for one DMA connection */
uint8_t Chip_GPDMA_GetFreeChannel(LPC_GPDMA_T *pGPDMA,
uint32_t PeripheralConnection_ID)
{
uint8_t temp = 0;
for (temp = 0; temp < GPDMA_NUMBER_CHANNELS; temp++) {
if (!Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_ENABLED_CH,
temp) && (ChannelHandlerArray[temp].ChannelStatus == DISABLE)) {
ChannelHandlerArray[temp].ChannelStatus = ENABLE;
return temp;
}
}
return 0;
}

View File

@@ -0,0 +1,46 @@
/*
* @brief LPC17xx/40xx GPIO driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/

View File

@@ -0,0 +1,46 @@
/*
* @brief LPC17xx/40xx GPIO Interrupt driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/

View File

@@ -0,0 +1,561 @@
/*
* @brief LPC17xx/40xx I2C driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/* Control flags */
#define I2C_CON_FLAGS (I2C_CON_AA | I2C_CON_SI | I2C_CON_STO | I2C_CON_STA)
#define LPC_I2Cx(id) ((i2c[id].ip))
#define SLAVE_ACTIVE(iic) (((iic)->flags & 0xFF00) != 0)
#ifdef CHIP_LPC175X_6X
static const CHIP_SYSCTL_PCLK_T I2C_PeriphClk[I2C_NUM_INTERFACE] = {
SYSCTL_PCLK_I2C0,
SYSCTL_PCLK_I2C1,
SYSCTL_PCLK_I2C2
};
#endif
/* I2C common interface structure */
struct i2c_interface {
LPC_I2C_T *ip; /* IP base address of the I2C device */
CHIP_SYSCTL_CLOCK_T clk; /* Clock used by I2C */
I2C_EVENTHANDLER_T mEvent; /* Current active Master event handler */
I2C_EVENTHANDLER_T sEvent; /* Slave transfer events */
I2C_XFER_T *mXfer; /* Current active xfer pointer */
I2C_XFER_T *sXfer; /* Pointer to store xfer when bus is busy */
uint32_t flags; /* Flags used by I2C master and slave */
};
/* Slave interface structure */
struct i2c_slave_interface {
I2C_XFER_T *xfer;
I2C_EVENTHANDLER_T event;
};
/* I2C interfaces */
static struct i2c_interface i2c[I2C_NUM_INTERFACE] = {
{LPC_I2C0, SYSCTL_CLOCK_I2C0, Chip_I2C_EventHandler, NULL, NULL, NULL, 0},
{LPC_I2C1, SYSCTL_CLOCK_I2C1, Chip_I2C_EventHandler, NULL, NULL, NULL, 0},
{LPC_I2C2, SYSCTL_CLOCK_I2C2, Chip_I2C_EventHandler, NULL, NULL, NULL, 0}
};
static struct i2c_slave_interface i2c_slave[I2C_NUM_INTERFACE][I2C_SLAVE_NUM_INTERFACE];
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
STATIC INLINE void enableClk(I2C_ID_T id)
{
Chip_Clock_EnablePeriphClock(i2c[id].clk);
}
STATIC INLINE void disableClk(I2C_ID_T id)
{
Chip_Clock_DisablePeriphClock(i2c[id].clk);
}
/* Get the ADC Clock Rate */
STATIC INLINE uint32_t getClkRate(I2C_ID_T id)
{
#if defined(CHIP_LPC175X_6X)
return Chip_Clock_GetPeripheralClockRate(I2C_PeriphClk[id]);
#else
return Chip_Clock_GetPeripheralClockRate();
#endif
}
/* Enable I2C and start master transfer */
STATIC INLINE void startMasterXfer(LPC_I2C_T *pI2C)
{
/* Reset STA, STO, SI */
pI2C->CONCLR = I2C_CON_SI | I2C_CON_STO | I2C_CON_STA | I2C_CON_AA;
/* Enter to Master Transmitter mode */
pI2C->CONSET = I2C_CON_I2EN | I2C_CON_STA;
}
/* Enable I2C and enable slave transfers */
STATIC INLINE void startSlaverXfer(LPC_I2C_T *pI2C)
{
/* Reset STA, STO, SI */
pI2C->CONCLR = I2C_CON_SI | I2C_CON_STO | I2C_CON_STA;
/* Enter to Master Transmitter mode */
pI2C->CONSET = I2C_CON_I2EN | I2C_CON_AA;
}
/* Check if I2C bus is free */
STATIC INLINE int isI2CBusFree(LPC_I2C_T *pI2C)
{
return !(pI2C->CONSET & I2C_CON_STO);
}
/* Get current state of the I2C peripheral */
STATIC INLINE int getCurState(LPC_I2C_T *pI2C)
{
return (int) (pI2C->STAT & I2C_STAT_CODE_BITMASK);
}
/* Check if the active state belongs to master mode*/
STATIC INLINE int isMasterState(LPC_I2C_T *pI2C)
{
return getCurState(pI2C) < 0x60;
}
/* Set OWN slave address for specific slave ID */
STATIC void setSlaveAddr(LPC_I2C_T *pI2C, I2C_SLAVE_ID sid, uint8_t addr, uint8_t mask)
{
uint32_t index = (uint32_t) sid - 1;
pI2C->MASK[index] = mask;
if (sid == I2C_SLAVE_0) {
pI2C->ADR0 = addr;
}
else {
volatile uint32_t *abase = &pI2C->ADR1;
abase[index - 1] = addr;
}
}
/* Match the slave address */
STATIC int isSlaveAddrMatching(uint8_t addr1, uint8_t addr2, uint8_t mask)
{
mask |= 1;
return (addr1 & ~mask) == (addr2 & ~mask);
}
/* Get the index of the active slave */
STATIC I2C_SLAVE_ID lookupSlaveIndex(LPC_I2C_T *pI2C, uint8_t slaveAddr)
{
if (!(slaveAddr >> 1)) {
return I2C_SLAVE_GENERAL; /* General call address */
}
if (isSlaveAddrMatching(pI2C->ADR0, slaveAddr, pI2C->MASK[0])) {
return I2C_SLAVE_0;
}
if (isSlaveAddrMatching(pI2C->ADR1, slaveAddr, pI2C->MASK[1])) {
return I2C_SLAVE_1;
}
if (isSlaveAddrMatching(pI2C->ADR2, slaveAddr, pI2C->MASK[2])) {
return I2C_SLAVE_2;
}
if (isSlaveAddrMatching(pI2C->ADR3, slaveAddr, pI2C->MASK[3])) {
return I2C_SLAVE_3;
}
/* If everything is fine the code should never come here */
return I2C_SLAVE_GENERAL;
}
/* Master transfer state change handler handler */
int handleMasterXferState(LPC_I2C_T *pI2C, I2C_XFER_T *xfer)
{
uint32_t cclr = I2C_CON_FLAGS;
switch (getCurState(pI2C)) {
case 0x08: /* Start condition on bus */
case 0x10: /* Repeated start condition */
pI2C->DAT = (xfer->slaveAddr << 1) | (xfer->txSz == 0);
break;
/* Tx handling */
case 0x18: /* SLA+W sent and ACK received */
case 0x28: /* DATA sent and ACK received */
if (!xfer->txSz) {
cclr &= ~(xfer->rxSz ? I2C_CON_STA : I2C_CON_STO);
}
else {
pI2C->DAT = *xfer->txBuff++;
xfer->txSz--;
}
break;
/* Rx handling */
case 0x58: /* Data Received and NACK sent */
cclr &= ~I2C_CON_STO;
case 0x50: /* Data Received and ACK sent */
*xfer->rxBuff++ = pI2C->DAT;
xfer->rxSz--;
case 0x40: /* SLA+R sent and ACK received */
if (xfer->rxSz > 1) {
cclr &= ~I2C_CON_AA;
}
break;
/* NAK Handling */
case 0x20: /* SLA+W sent NAK received */
case 0x30: /* DATA sent NAK received */
case 0x48: /* SLA+R sent NAK received */
xfer->status = I2C_STATUS_NAK;
cclr &= ~I2C_CON_STO;
break;
case 0x38: /* Arbitration lost */
xfer->status = I2C_STATUS_ARBLOST;
break;
/* Bus Error */
case 0x00:
xfer->status = I2C_STATUS_BUSERR;
cclr &= ~I2C_CON_STO;
}
/* Set clear control flags */
pI2C->CONSET = cclr ^ I2C_CON_FLAGS;
pI2C->CONCLR = cclr;
/* If stopped return 0 */
if (!(cclr & I2C_CON_STO) || (xfer->status == I2C_STATUS_ARBLOST)) {
if (xfer->status == I2C_STATUS_BUSY) {
xfer->status = I2C_STATUS_DONE;
}
return 0;
}
return 1;
}
/* Find the slave address of SLA+W or SLA+R */
I2C_SLAVE_ID getSlaveIndex(LPC_I2C_T *pI2C)
{
switch (getCurState(pI2C)) {
case 0x60:
case 0x68:
case 0x70:
case 0x78:
case 0xA8:
case 0xB0:
return lookupSlaveIndex(pI2C, pI2C->DAT);
}
/* If everything is fine code should never come here */
return I2C_SLAVE_GENERAL;
}
/* Slave state machine handler */
int handleSlaveXferState(LPC_I2C_T *pI2C, I2C_XFER_T *xfer)
{
uint32_t cclr = I2C_CON_FLAGS;
int ret = RET_SLAVE_BUSY;
xfer->status = I2C_STATUS_BUSY;
switch (getCurState(pI2C)) {
case 0x80: /* SLA: Data received + ACK sent */
case 0x90: /* GC: Data received + ACK sent */
*xfer->rxBuff++ = pI2C->DAT;
xfer->rxSz--;
ret = RET_SLAVE_RX;
if (xfer->rxSz > 1) {
cclr &= ~I2C_CON_AA;
}
break;
case 0x60: /* Own SLA+W received */
case 0x68: /* Own SLA+W received after losing arbitration */
case 0x70: /* GC+W received */
case 0x78: /* GC+W received after losing arbitration */
xfer->slaveAddr = pI2C->DAT & ~1;
if (xfer->rxSz > 1) {
cclr &= ~I2C_CON_AA;
}
break;
case 0xA8: /* SLA+R received */
case 0xB0: /* SLA+R received after losing arbitration */
xfer->slaveAddr = pI2C->DAT & ~1;
case 0xB8: /* DATA sent and ACK received */
pI2C->DAT = *xfer->txBuff++;
xfer->txSz--;
if (xfer->txSz > 0) {
cclr &= ~I2C_CON_AA;
}
ret = RET_SLAVE_TX;
break;
case 0xC0: /* Data transmitted and NAK received */
case 0xC8: /* Last data transmitted and ACK received */
case 0x88: /* SLA: Data received + NAK sent */
case 0x98: /* GC: Data received + NAK sent */
case 0xA0: /* STOP/Repeated START condition received */
ret = RET_SLAVE_IDLE;
cclr &= ~I2C_CON_AA;
xfer->status = I2C_STATUS_DONE;
if (xfer->slaveAddr & 1) {
cclr &= ~I2C_CON_STA;
}
break;
}
/* Set clear control flags */
pI2C->CONSET = cclr ^ I2C_CON_FLAGS;
pI2C->CONCLR = cclr;
return ret;
}
/*****************************************************************************
* Public functions
****************************************************************************/
/* Chip event handler interrupt based */
void Chip_I2C_EventHandler(I2C_ID_T id, I2C_EVENT_T event)
{
struct i2c_interface *iic = &i2c[id];
volatile I2C_STATUS_T *stat;
/* Only WAIT event needs to be handled */
if (event != I2C_EVENT_WAIT) {
return;
}
stat = &iic->mXfer->status;
/* Wait for the status to change */
while (*stat == I2C_STATUS_BUSY) {}
}
/* Chip polling event handler */
void Chip_I2C_EventHandlerPolling(I2C_ID_T id, I2C_EVENT_T event)
{
struct i2c_interface *iic = &i2c[id];
volatile I2C_STATUS_T *stat;
/* Only WAIT event needs to be handled */
if (event != I2C_EVENT_WAIT) {
return;
}
stat = &iic->mXfer->status;
/* Call the state change handler till xfer is done */
while (*stat == I2C_STATUS_BUSY) {
if (Chip_I2C_IsStateChanged(id)) {
Chip_I2C_MasterStateHandler(id);
}
}
}
/* Initializes the LPC_I2C peripheral with specified parameter */
void Chip_I2C_Init(I2C_ID_T id)
{
enableClk(id);
/* Set I2C operation to default */
LPC_I2Cx(id)->CONCLR = (I2C_CON_AA | I2C_CON_SI | I2C_CON_STA | I2C_CON_I2EN);
}
/* De-initializes the I2C peripheral registers to their default reset values */
void Chip_I2C_DeInit(I2C_ID_T id)
{
/* Disable I2C control */
LPC_I2Cx(id)->CONCLR = I2C_CON_I2EN | I2C_CON_SI | I2C_CON_STO | I2C_CON_STA | I2C_CON_AA;
disableClk(id);
}
/* Set up clock rate for LPC_I2C peripheral */
void Chip_I2C_SetClockRate(I2C_ID_T id, uint32_t clockrate)
{
uint32_t SCLValue;
SCLValue = (getClkRate(id) / clockrate);
LPC_I2Cx(id)->SCLH = (uint32_t) (SCLValue >> 1);
LPC_I2Cx(id)->SCLL = (uint32_t) (SCLValue - LPC_I2Cx(id)->SCLH);
}
/* Get current clock rate for LPC_I2C peripheral */
uint32_t Chip_I2C_GetClockRate(I2C_ID_T id)
{
return getClkRate(id) / (LPC_I2Cx(id)->SCLH + LPC_I2Cx(id)->SCLL);
}
/* Set the master event handler */
int Chip_I2C_SetMasterEventHandler(I2C_ID_T id, I2C_EVENTHANDLER_T event)
{
struct i2c_interface *iic = &i2c[id];
if (!iic->mXfer) {
iic->mEvent = event;
}
return iic->mEvent == event;
}
/* Get the master event handler */
I2C_EVENTHANDLER_T Chip_I2C_GetMasterEventHandler(I2C_ID_T id)
{
return i2c[id].mEvent;
}
/* Transmit and Receive data in master mode */
int Chip_I2C_MasterTransfer(I2C_ID_T id, I2C_XFER_T *xfer)
{
struct i2c_interface *iic = &i2c[id];
iic->mEvent(id, I2C_EVENT_LOCK);
xfer->status = I2C_STATUS_BUSY;
iic->mXfer = xfer;
/* If slave xfer not in progress */
if (!iic->sXfer) {
startMasterXfer(iic->ip);
}
iic->mEvent(id, I2C_EVENT_WAIT);
iic->mXfer = 0;
/* Wait for stop condition to appear on bus */
while (!isI2CBusFree(iic->ip)) {}
/* Start slave if one is active */
if (SLAVE_ACTIVE(iic)) {
startSlaverXfer(iic->ip);
}
iic->mEvent(id, I2C_EVENT_UNLOCK);
return (int) xfer->status;
}
/* Master tx only */
int Chip_I2C_MasterSend(I2C_ID_T id, uint8_t slaveAddr, const uint8_t *buff, uint8_t len)
{
I2C_XFER_T xfer = {0};
xfer.slaveAddr = slaveAddr;
xfer.txBuff = buff;
xfer.txSz = len;
while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
return len - xfer.txSz;
}
/* Transmit one byte and receive an array of bytes after a repeated start condition is generated in Master mode.
* This function is useful for communicating with the I2C slave registers
*/
int Chip_I2C_MasterCmdRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t cmd, uint8_t *buff, int len)
{
I2C_XFER_T xfer = {0};
xfer.slaveAddr = slaveAddr;
xfer.txBuff = &cmd;
xfer.txSz = 1;
xfer.rxBuff = buff;
xfer.rxSz = len;
while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
return len - xfer.rxSz;
}
/* Sequential master read */
int Chip_I2C_MasterRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t *buff, int len)
{
I2C_XFER_T xfer = {0};
xfer.slaveAddr = slaveAddr;
xfer.rxBuff = buff;
xfer.rxSz = len;
while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
return len - xfer.rxSz;
}
/* Check if master state is active */
int Chip_I2C_IsMasterActive(I2C_ID_T id)
{
return isMasterState(i2c[id].ip);
}
/* State change handler for master transfer */
void Chip_I2C_MasterStateHandler(I2C_ID_T id)
{
if (!handleMasterXferState(i2c[id].ip, i2c[id].mXfer)) {
i2c[id].mEvent(id, I2C_EVENT_DONE);
}
}
/* Setup slave function */
void Chip_I2C_SlaveSetup(I2C_ID_T id,
I2C_SLAVE_ID sid,
I2C_XFER_T *xfer,
I2C_EVENTHANDLER_T event,
uint8_t addrMask)
{
struct i2c_interface *iic = &i2c[id];
struct i2c_slave_interface *si2c = &i2c_slave[id][sid];
si2c->xfer = xfer;
si2c->event = event;
/* Set up the slave address */
if (sid != I2C_SLAVE_GENERAL) {
setSlaveAddr(iic->ip, sid, xfer->slaveAddr, addrMask);
}
if (!SLAVE_ACTIVE(iic) && !iic->mXfer) {
startSlaverXfer(iic->ip);
}
iic->flags |= 1 << (sid + 8);
}
/* I2C Slave event handler */
void Chip_I2C_SlaveStateHandler(I2C_ID_T id)
{
int ret;
struct i2c_interface *iic = &i2c[id];
/* Get the currently addressed slave */
if (!iic->sXfer) {
struct i2c_slave_interface *si2c;
I2C_SLAVE_ID sid = getSlaveIndex(iic->ip);
si2c = &i2c_slave[id][sid];
iic->sXfer = si2c->xfer;
iic->sEvent = si2c->event;
}
iic->sXfer->slaveAddr |= iic->mXfer != 0;
ret = handleSlaveXferState(iic->ip, iic->sXfer);
if (ret) {
if (iic->sXfer->status == I2C_STATUS_DONE) {
iic->sXfer = 0;
}
iic->sEvent(id, (I2C_EVENT_T) ret);
}
}
/* Disable I2C device */
void Chip_I2C_Disable(I2C_ID_T id)
{
LPC_I2Cx(id)->CONCLR = I2C_I2CONCLR_I2ENC;
}
/* State change checking */
int Chip_I2C_IsStateChanged(I2C_ID_T id)
{
return (LPC_I2Cx(id)->CONSET & I2C_CON_SI) != 0;
}

View File

@@ -0,0 +1,260 @@
/*
* @brief LPC17xx/40xx I2S driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/* Get divider value */
STATIC Status getClkDiv(LPC_I2S_T *pI2S, I2S_AUDIO_FORMAT_T *format, uint16_t *pxDiv, uint16_t *pyDiv, uint32_t *pN)
{
uint32_t pClk;
uint32_t x, y;
uint64_t divider;
uint16_t dif;
uint16_t xDiv = 0, yDiv = 0;
uint32_t N;
uint16_t err, ErrorOptimal = 0xFFFF;
#if defined(CHIP_LPC175X_6X)
pClk = Chip_Clock_GetPeripheralClockRate(SYSCTL_PCLK_I2S);
#else
pClk = Chip_Clock_GetPeripheralClockRate();
#endif
/* divider is a fixed point number with 16 fractional bits */
divider = (((uint64_t) (format->SampleRate) * 2 * (format->WordWidth) * 2) << 16) / pClk;
/* find N that make x/y <= 1 -> divider <= 2^16 */
for (N = 64; N > 0; N--) {
if ((divider * N) < (1 << 16)) {
break;
}
}
if (N == 0) {
return ERROR;
}
divider *= N;
for (y = 255; y > 0; y--) {
x = y * divider;
if (x & (0xFF000000)) {
continue;
}
dif = x & 0xFFFF;
if (dif > 0x8000) {
err = 0x10000 - dif;
}
else {
err = dif;
}
if (err == 0) {
yDiv = y;
break;
}
else if (err < ErrorOptimal) {
ErrorOptimal = err;
yDiv = y;
}
}
xDiv = ((uint64_t) yDiv * (format->SampleRate) * 2 * (format->WordWidth) * N * 2) / pClk;
if (xDiv >= 256) {
xDiv = 0xFF;
}
if (xDiv == 0) {
xDiv = 1;
}
*pxDiv = xDiv;
*pyDiv = yDiv;
*pN = N;
return SUCCESS;
}
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initialize the I2S interface */
void Chip_I2S_Init(LPC_I2S_T *pI2S)
{
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_I2S);
}
/* Shutdown I2S */
void Chip_I2S_DeInit(LPC_I2S_T *pI2S)
{
pI2S->DAI = 0x07E1;
pI2S->DAO = 0x87E1;
pI2S->IRQ = 0;
pI2S->TXMODE = 0;
pI2S->RXMODE = 0;
pI2S->DMA[I2S_DMA_REQUEST_CHANNEL_1] = 0;
pI2S->DMA[I2S_DMA_REQUEST_CHANNEL_2] = 0;
Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_I2S);
}
/* Configure I2S for Audio Format input */
Status Chip_I2S_TxConfig(LPC_I2S_T *pI2S, I2S_AUDIO_FORMAT_T *format)
{
uint32_t temp;
uint16_t xDiv, yDiv;
uint32_t N;
if (getClkDiv(pI2S, format, &xDiv, &yDiv, &N) == ERROR) {
return ERROR;
}
temp = pI2S->DAO & (~(I2S_DAO_WORDWIDTH_MASK | I2S_DAO_MONO | I2S_DAO_SLAVE | I2S_DAO_WS_HALFPERIOD_MASK));
if (format->WordWidth <= 8) {
temp |= I2S_WORDWIDTH_8;
}
else if (format->WordWidth <= 16) {
temp |= I2S_WORDWIDTH_16;
}
else {
temp |= I2S_WORDWIDTH_32;
}
temp |= (format->ChannelNumber) == 1 ? I2S_MONO : I2S_STEREO;
temp |= I2S_MASTER_MODE;
temp |= I2S_DAO_WS_HALFPERIOD(format->WordWidth - 1);
pI2S->DAO = temp;
pI2S->TXMODE = I2S_TXMODE_CLKSEL(0);
pI2S->TXBITRATE = N - 1;
pI2S->TXRATE = yDiv | (xDiv << 8);
return SUCCESS;
}
/* Configure I2S for Audio Format input */
Status Chip_I2S_RxConfig(LPC_I2S_T *pI2S, I2S_AUDIO_FORMAT_T *format)
{
uint32_t temp;
uint16_t xDiv, yDiv;
uint32_t N;
if (getClkDiv(pI2S, format, &xDiv, &yDiv, &N) == ERROR) {
return ERROR;
}
temp = pI2S->DAI & (~(I2S_DAI_WORDWIDTH_MASK | I2S_DAI_MONO | I2S_DAI_SLAVE | I2S_DAI_WS_HALFPERIOD_MASK));
if (format->WordWidth <= 8) {
temp |= I2S_WORDWIDTH_8;
}
else if (format->WordWidth <= 16) {
temp |= I2S_WORDWIDTH_16;
}
else {
temp |= I2S_WORDWIDTH_32;
}
temp |= (format->ChannelNumber) == 1 ? I2S_MONO : I2S_STEREO;
temp |= I2S_MASTER_MODE;
temp |= I2S_DAI_WS_HALFPERIOD(format->WordWidth - 1);
pI2S->DAI = temp;
pI2S->RXMODE = I2S_RXMODE_CLKSEL(0);
pI2S->RXBITRATE = N - 1;
pI2S->RXRATE = yDiv | (xDiv << 8);
return SUCCESS;
}
/* Enable/Disable Interrupt with a specific FIFO depth */
void Chip_I2S_Int_TxCmd(LPC_I2S_T *pI2S, FunctionalState newState, uint8_t depth)
{
uint32_t temp;
depth &= 0x0F;
if (newState == ENABLE) {
pI2S->IRQ |= 0x02;
}
else {
pI2S->IRQ &= (~0x02);
}
temp = pI2S->IRQ & (~I2S_IRQ_TX_DEPTH_MASK);
pI2S->IRQ = temp | (I2S_IRQ_TX_DEPTH(depth));
}
/* Enable/Disable Interrupt with a specific FIFO depth */
void Chip_I2S_Int_RxCmd(LPC_I2S_T *pI2S, FunctionalState newState, uint8_t depth)
{
uint32_t temp;
depth &= 0x0F;
if (newState == ENABLE) {
pI2S->IRQ |= 0x01;
}
else {
pI2S->IRQ &= (~0x01);
}
temp = pI2S->IRQ & (~I2S_IRQ_RX_DEPTH_MASK);
pI2S->IRQ = temp | (I2S_IRQ_RX_DEPTH(depth));
}
/* Enable/Disable DMA with a specific FIFO depth */
void Chip_I2S_DMA_TxCmd(LPC_I2S_T *pI2S,
I2S_DMA_CHANNEL_T dmaNum,
FunctionalState newState,
uint8_t depth)
{
/* Set FIFO Level */
pI2S->DMA[dmaNum] &= ~(0x0F << 16);
pI2S->DMA[dmaNum] |= depth << 16;
/* Enable/Disable I2S transmit*/
if (newState == ENABLE) {
pI2S->DMA[dmaNum] |= 0x02;
}
else {
pI2S->DMA[dmaNum] &= ~0x02;
}
}
/* Enable/Disable DMA with a specific FIFO depth */
void Chip_I2S_DMA_RxCmd(LPC_I2S_T *pI2S,
I2S_DMA_CHANNEL_T dmaNum,
FunctionalState newState,
uint8_t depth)
{
/* Set FIFO Level */
pI2S->DMA[dmaNum] &= ~(0x0F << 8);
pI2S->DMA[dmaNum] |= depth << 8;
/* Enable/Disable I2S Receive */
if (newState == ENABLE) {
pI2S->DMA[dmaNum] |= 0x01;
}
else {
pI2S->DMA[dmaNum] &= ~0x01;
}
}

View File

@@ -0,0 +1,175 @@
/*
* @brief Common FLASH support functions
*
* @note
* Copyright(C) NXP Semiconductors, 2013
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
/* Prepare sector for write operation */
uint8_t Chip_IAP_PreSectorForReadWrite(uint32_t strSector, uint32_t endSector)
{
uint32_t command[5], result[4];
command[0] = IAP_PREWRRITE_CMD;
command[1] = strSector;
command[2] = endSector;
iap_entry(command, result);
return result[0];
}
/* Copy RAM to flash */
uint8_t Chip_IAP_CopyRamToFlash(uint32_t dstAdd, uint32_t *srcAdd, uint32_t byteswrt)
{
uint32_t command[5], result[4];
command[0] = IAP_WRISECTOR_CMD;
command[1] = dstAdd;
command[2] = (uint32_t) srcAdd;
command[3] = byteswrt;
command[4] = SystemCoreClock / 1000;
iap_entry(command, result);
return result[0];
}
/* Erase sector */
uint8_t Chip_IAP_EraseSector(uint32_t strSector, uint32_t endSector)
{
uint32_t command[5], result[4];
command[0] = IAP_ERSSECTOR_CMD;
command[1] = strSector;
command[2] = endSector;
command[3] = SystemCoreClock / 1000;
iap_entry(command, result);
return result[0];
}
/* Blank check sector */
uint8_t Chip_IAP_BlankCheckSector(uint32_t strSector, uint32_t endSector)
{
uint32_t command[5], result[4];
command[0] = IAP_BLANK_CHECK_SECTOR_CMD;
command[1] = strSector;
command[2] = endSector;
iap_entry(command, result);
return result[0];
}
/* Read part identification number */
uint32_t Chip_IAP_ReadPID()
{
uint32_t command[5], result[4];
command[0] = IAP_REPID_CMD;
iap_entry(command, result);
return result[1];
}
/* Read boot code version number */
uint8_t Chip_IAP_ReadBootCode()
{
uint32_t command[5], result[4];
command[0] = IAP_READ_BOOT_CODE_CMD;
iap_entry(command, result);
return result[0];
}
/* IAP compare */
uint8_t Chip_IAP_Compare(uint32_t dstAdd, uint32_t srcAdd, uint32_t bytescmp)
{
uint32_t command[5], result[4];
command[0] = IAP_COMPARE_CMD;
command[1] = dstAdd;
command[2] = srcAdd;
command[3] = bytescmp;
iap_entry(command, result);
return result[0];
}
/* Reinvoke ISP */
uint8_t Chip_IAP_ReinvokeISP()
{
uint32_t command[5], result[4];
command[0] = IAP_REINVOKE_ISP_CMD;
iap_entry(command, result);
return result[0];
}
/* Read the unique ID */
uint32_t Chip_IAP_ReadUID()
{
uint32_t command[5], result[4];
command[0] = IAP_READ_UID_CMD;
iap_entry(command, result);
return result[1];
}
/* Erase page */
uint8_t Chip_IAP_ErasePage(uint32_t strPage, uint32_t endPage)
{
uint32_t command[5], result[4];
command[0] = IAP_ERASE_PAGE_CMD;
command[1] = strPage;
command[2] = endPage;
command[3] = SystemCoreClock / 1000;
iap_entry(command, result);
return result[0];
}

View File

@@ -0,0 +1,83 @@
/*
* @brief LPC17xx/40xx IOCON driver
*
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
#if defined(CHIP_LPC175X_6X)
/* Sets I/O Control pin mux */
void Chip_IOCON_PinMuxSet(LPC_IOCON_T *pIOCON, uint8_t port, uint8_t pin, uint32_t modefunc)
{
Chip_IOCON_PinMux(pIOCON, port, pin,
/* mode is in bits 3:2 */
modefunc >> 2,
/* func is in bits 1:0 */
modefunc & 3 );
}
/* Setup pin modes and function */
void Chip_IOCON_PinMux(LPC_IOCON_T *pIOCON, uint8_t port, uint8_t pin, uint32_t mode, uint8_t func)
{
uint8_t reg, bitPos;
uint32_t temp;
bitPos = IOCON_BIT_INDEX(pin);
reg = IOCON_REG_INDEX(port,pin);
temp = pIOCON->PINSEL[reg] & ~(0x03UL << bitPos);
pIOCON->PINSEL[reg] = temp | (func << bitPos);
temp = pIOCON->PINMODE[reg] & ~(0x03UL << bitPos);
pIOCON->PINMODE[reg] = temp | (mode << bitPos);
}
#endif /* defined(CHIP_LPC175X_6X) */
/* Set all I/O Control pin muxing */
void Chip_IOCON_SetPinMuxing(LPC_IOCON_T *pIOCON, const PINMUX_GRP_T* pinArray, uint32_t arrayLength)
{
uint32_t ix;
for (ix = 0; ix < arrayLength; ix++ ) {
Chip_IOCON_PinMuxSet(pIOCON, pinArray[ix].pingrp, pinArray[ix].pinnum, pinArray[ix].modefunc);
}
}

View File

@@ -0,0 +1,210 @@
/*
* @brief LCD chip driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
#if defined(CHIP_LPC177X_8X) || defined(CHIP_LPC40XX)
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
static LCD_CURSOR_SIZE_OPT_T LCD_Cursor_Size = LCD_CURSOR_64x64;
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initialize the LCD controller */
void Chip_LCD_Init(LPC_LCD_T *pLCD, LCD_CONFIG_T *LCD_ConfigStruct)
{
uint32_t i, regValue, *pPal;
uint32_t pcd;
/* Enable LCD Clock */
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_LCD);
/* disable the display */
pLCD->CTRL &= ~CLCDC_LCDCTRL_ENABLE;
/* Setting LCD_TIMH register */
regValue = ( ((((LCD_ConfigStruct->PPL / 16) - 1) & 0x3F) << 2)
| (( (LCD_ConfigStruct->HSW - 1) & 0xFF) << 8)
| (( (LCD_ConfigStruct->HFP - 1) & 0xFF) << 16)
| (( (LCD_ConfigStruct->HBP - 1) & 0xFF) << 24) );
pLCD->TIMH = regValue;
/* Setting LCD_TIMV register */
regValue = ((((LCD_ConfigStruct->LPP - 1) & 0x3FF) << 0)
| (((LCD_ConfigStruct->VSW - 1) & 0x03F) << 10)
| (((LCD_ConfigStruct->VFP - 1) & 0x0FF) << 16)
| (((LCD_ConfigStruct->VBP - 1) & 0x0FF) << 24) );
pLCD->TIMV = regValue;
/* Generate the clock and signal polarity control word */
regValue = 0;
regValue = (((LCD_ConfigStruct->ACB - 1) & 0x1F) << 6);
regValue |= (LCD_ConfigStruct->IOE & 1) << 14;
regValue |= (LCD_ConfigStruct->IPC & 1) << 13;
regValue |= (LCD_ConfigStruct->IHS & 1) << 12;
regValue |= (LCD_ConfigStruct->IVS & 1) << 11;
/* Compute clocks per line based on panel type */
switch (LCD_ConfigStruct->LCD) {
case LCD_MONO_4:
regValue |= ((((LCD_ConfigStruct->PPL / 4) - 1) & 0x3FF) << 16);
break;
case LCD_MONO_8:
regValue |= ((((LCD_ConfigStruct->PPL / 8) - 1) & 0x3FF) << 16);
break;
case LCD_CSTN:
regValue |= (((((LCD_ConfigStruct->PPL * 3) / 8) - 1) & 0x3FF) << 16);
break;
case LCD_TFT:
default:
regValue |= /*1<<26 |*/ (((LCD_ConfigStruct->PPL - 1) & 0x3FF) << 16);
}
/* panel clock divisor */
pcd = 5;// LCD_ConfigStruct->pcd; /* TODO: should be calculated from LCDDCLK */
pcd &= 0x3FF;
regValue |= ((pcd >> 5) << 27) | ((pcd) & 0x1F);
pLCD->POL = regValue;
/* disable interrupts */
pLCD->INTMSK = 0;
/* set bits per pixel */
regValue = LCD_ConfigStruct->BPP << 1;
/* set color format RGB */
regValue |= LCD_ConfigStruct->color_format << 8;
regValue |= LCD_ConfigStruct->LCD << 4;
if (LCD_ConfigStruct->Dual == 1) {
regValue |= 1 << 7;
}
pLCD->CTRL = regValue;
/* clear palette */
pPal = (uint32_t *) (&(pLCD->PAL));
for (i = 0; i < 128; i++) {
*pPal = 0;
pPal++;
}
}
/* Shutdown the LCD controller */
void Chip_LCD_DeInit(LPC_LCD_T *pLCD)
{
Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_LCD);
}
/* Configure Cursor */
void Chip_LCD_Cursor_Config(LPC_LCD_T *pLCD, LCD_CURSOR_SIZE_OPT_T cursor_size, bool sync)
{
LCD_Cursor_Size = cursor_size;
pLCD->CRSR_CFG = ((sync ? 1 : 0) << 1) | cursor_size;
}
/* Write Cursor Image into Internal Cursor Image Buffer */
void Chip_LCD_Cursor_WriteImage(LPC_LCD_T *pLCD, uint8_t cursor_num, void *Image)
{
int i, j;
uint32_t *fifoptr, *crsr_ptr = (uint32_t *) Image;
/* Check if Cursor Size was configured as 32x32 or 64x64*/
if (LCD_Cursor_Size == LCD_CURSOR_32x32) {
i = cursor_num * 64;
j = i + 64;
}
else {
i = 0;
j = 256;
}
fifoptr = (void *) &(pLCD->CRSR_IMG[0]);
/* Copy Cursor Image content to FIFO */
for (; i < j; i++) {
*fifoptr = *crsr_ptr;
crsr_ptr++;
fifoptr++;
}
}
/* Load LCD Palette */
void Chip_LCD_LoadPalette(LPC_LCD_T *pLCD, void *palette)
{
LCD_PALETTE_ENTRY_T pal_entry, *ptr_pal_entry;
uint8_t i, *pal_ptr;
/* This function supports loading of the color palette from
the C file generated by the bmp2c utility. It expects the
palette to be passed as an array of 32-bit BGR entries having
the following format:
2:0 - Not used
7:3 - Blue
10:8 - Not used
15:11 - Green
18:16 - Not used
23:19 - Red
31:24 - Not used
arg = pointer to input palette table address */
ptr_pal_entry = &pal_entry;
pal_ptr = (uint8_t *) palette;
/* 256 entry in the palette table */
for (i = 0; i < 256 / 2; i++) {
pal_entry.Bl = (*pal_ptr++) >> 3; /* blue first */
pal_entry.Gl = (*pal_ptr++) >> 3; /* get green */
pal_entry.Rl = (*pal_ptr++) >> 3; /* get red */
pal_ptr++; /* skip over the unused byte */
/* do the most significant halfword of the palette */
pal_entry.Bu = (*pal_ptr++) >> 3; /* blue first */
pal_entry.Gu = (*pal_ptr++) >> 3; /* get green */
pal_entry.Ru = (*pal_ptr++) >> 3; /* get red */
pal_ptr++; /* skip over the unused byte */
pLCD->PAL[i] = *((uint32_t *) ptr_pal_entry);
}
}
#endif /* defined(CHIP_LPC177X_8X) || defined(CHIP_LPC40XX) */

View File

@@ -0,0 +1,118 @@
/*
* @brief LPC15xx PMU chip driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
/* Enter MCU Sleep mode */
void Chip_PMU_SleepState(LPC_PMU_T *pPMU)
{
/* Select Sleep/Deep Sleep mode */
pPMU->PCON &= ~(PMU_PCON_PM1_FLAG | PMU_PCON_PM0_FLAG);
/* Clearing SLEEPDEEP bit in SCR makes it Sleep mode */
SCB->SCR &= ~(1UL << SCB_SCR_SLEEPDEEP_Pos);
/* Enter sleep mode */
__WFI();
}
/* Enter MCU Deep Sleep mode */
void Chip_PMU_DeepSleepState(LPC_PMU_T *pPMU)
{
/* Select Sleep/Deep Sleep mode */
pPMU->PCON &= ~(PMU_PCON_PM1_FLAG | PMU_PCON_PM0_FLAG);
/* Setting SLEEPDEEP bit in SCR makes it Deep Sleep mode */
SCB->SCR |= (1UL << SCB_SCR_SLEEPDEEP_Pos);
/* Enter sleep mode */
__WFI();
}
/* Enter MCU Power down mode */
void Chip_PMU_PowerDownState(LPC_PMU_T *pPMU)
{
/* Select power down mode */
pPMU->PCON = (pPMU->PCON & ~PMU_PCON_PM1_FLAG) | PMU_PCON_PM0_FLAG;
/* Setting SLEEPDEEP bit in SCR makes it power down mode */
SCB->SCR |= (1UL << SCB_SCR_SLEEPDEEP_Pos);
/* Enter sleep mode */
__WFI();
}
/* Enter MCU Deep Power down mode */
void Chip_PMU_DeepPowerDownState(LPC_PMU_T *pPMU)
{
/* Select deep power down mode */
pPMU->PCON |= PMU_PCON_PM1_FLAG | PMU_PCON_PM0_FLAG;
/* Setting SLEEPDEEP bit in SCR makes it deep power down mode */
SCB->SCR |= (1UL << SCB_SCR_SLEEPDEEP_Pos);
/* Enter sleep mode */
__WFI();
}
/* Put some of the peripheral in sleep mode */
void Chip_PMU_Sleep(LPC_PMU_T *pPMU, CHIP_PMU_MCUPOWER_T SleepMode)
{
if (SleepMode == PMU_MCU_DEEP_SLEEP) {
Chip_PMU_DeepSleepState(pPMU);
}
else if (SleepMode == PMU_MCU_POWER_DOWN) {
Chip_PMU_PowerDownState(pPMU);
}
else if (SleepMode == PMU_MCU_DEEP_PWRDOWN) {
Chip_PMU_DeepPowerDownState(pPMU);
}
else {
/* PMU_MCU_SLEEP */
Chip_PMU_SleepState(pPMU);
}
}

View File

@@ -0,0 +1,167 @@
/*
* @brief Common ring buffer support functions
*
* @note
* Copyright(C) NXP Semiconductors, 2012
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include <string.h>
#include "ring_buffer.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
#define RB_INDH(rb) ((rb)->head & ((rb)->count - 1))
#define RB_INDT(rb) ((rb)->tail & ((rb)->count - 1))
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initialize ring buffer */
int RingBuffer_Init(RINGBUFF_T *RingBuff, void *buffer, int itemSize, int count)
{
RingBuff->data = buffer;
RingBuff->count = count;
RingBuff->itemSz = itemSize;
RingBuff->head = RingBuff->tail = 0;
return 1;
}
/* Insert a single item into Ring Buffer */
int RingBuffer_Insert(RINGBUFF_T *RingBuff, const void *data)
{
uint8_t *ptr = RingBuff->data;
/* We cannot insert when queue is full */
if (RingBuffer_IsFull(RingBuff))
return 0;
ptr += RB_INDH(RingBuff) * RingBuff->itemSz;
memcpy(ptr, data, RingBuff->itemSz);
RingBuff->head++;
return 1;
}
/* Insert multiple items into Ring Buffer */
int RingBuffer_InsertMult(RINGBUFF_T *RingBuff, const void *data, int num)
{
uint8_t *ptr = RingBuff->data;
int cnt1, cnt2;
/* We cannot insert when queue is full */
if (RingBuffer_IsFull(RingBuff))
return 0;
/* Calculate the segment lengths */
cnt1 = cnt2 = RingBuffer_GetFree(RingBuff);
if (RB_INDH(RingBuff) + cnt1 >= RingBuff->count)
cnt1 = RingBuff->count - RB_INDH(RingBuff);
cnt2 -= cnt1;
cnt1 = MIN(cnt1, num);
num -= cnt1;
cnt2 = MIN(cnt2, num);
num -= cnt2;
/* Write segment 1 */
ptr += RB_INDH(RingBuff) * RingBuff->itemSz;
memcpy(ptr, data, cnt1 * RingBuff->itemSz);
RingBuff->head += cnt1;
/* Write segment 2 */
ptr = (uint8_t *) RingBuff->data + RB_INDH(RingBuff) * RingBuff->itemSz;
data = (const uint8_t *) data + cnt1 * RingBuff->itemSz;
memcpy(ptr, data, cnt2 * RingBuff->itemSz);
RingBuff->head += cnt2;
return cnt1 + cnt2;
}
/* Pop single item from Ring Buffer */
int RingBuffer_Pop(RINGBUFF_T *RingBuff, void *data)
{
uint8_t *ptr = RingBuff->data;
/* We cannot pop when queue is empty */
if (RingBuffer_IsEmpty(RingBuff))
return 0;
ptr += RB_INDT(RingBuff) * RingBuff->itemSz;
memcpy(data, ptr, RingBuff->itemSz);
RingBuff->tail++;
return 1;
}
/* Pop multiple items from Ring buffer */
int RingBuffer_PopMult(RINGBUFF_T *RingBuff, void *data, int num)
{
uint8_t *ptr = RingBuff->data;
int cnt1, cnt2;
/* We cannot insert when queue is empty */
if (RingBuffer_IsEmpty(RingBuff))
return 0;
/* Calculate the segment lengths */
cnt1 = cnt2 = RingBuffer_GetCount(RingBuff);
if (RB_INDT(RingBuff) + cnt1 >= RingBuff->count)
cnt1 = RingBuff->count - RB_INDT(RingBuff);
cnt2 -= cnt1;
cnt1 = MIN(cnt1, num);
num -= cnt1;
cnt2 = MIN(cnt2, num);
num -= cnt2;
/* Write segment 1 */
ptr += RB_INDT(RingBuff) * RingBuff->itemSz;
memcpy(data, ptr, cnt1 * RingBuff->itemSz);
RingBuff->tail += cnt1;
/* Write segment 2 */
ptr = (uint8_t *) RingBuff->data + RB_INDT(RingBuff) * RingBuff->itemSz;
data = (uint8_t *) data + cnt1 * RingBuff->itemSz;
memcpy(data, ptr, cnt2 * RingBuff->itemSz);
RingBuff->tail += cnt2;
return cnt1 + cnt2;
}

View File

@@ -0,0 +1,100 @@
/*
* @brief LPC17xx/40xx RITimer driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
#if defined(CHIP_LPC175X_6X)
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initialize the RIT */
void Chip_RIT_Init(LPC_RITIMER_T *pRITimer)
{
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_RIT);
pRITimer->COMPVAL = 0xFFFFFFFF;
pRITimer->MASK = 0x00000000;
pRITimer->CTRL = 0x0C;
pRITimer->COUNTER = 0x00000000;
}
/* DeInitialize the RIT */
void Chip_RIT_DeInit(LPC_RITIMER_T *pRITimer)
{
Chip_RIT_Init(pRITimer);
Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_RIT);
}
/* Set timer interval value */
void Chip_RIT_SetTimerInterval(LPC_RITIMER_T *pRITimer, uint32_t time_interval)
{
uint32_t cmp_value;
/* Determine aapproximate compare value based on clock rate and passed interval */
cmp_value = (Chip_Clock_GetPeripheralClockRate(SYSCTL_PCLK_RIT) / 1000) * time_interval;
/* Set timer compare value */
Chip_RIT_SetCOMPVAL(pRITimer, cmp_value);
/* Set timer enable clear bit to clear timer to 0 whenever
counter value equals the contents of RICOMPVAL */
Chip_RIT_EnableCTRL(pRITimer, RIT_CTRL_ENCLR);
}
/* Check whether interrupt is pending */
IntStatus Chip_RIT_GetIntStatus(LPC_RITIMER_T *pRITimer)
{
uint8_t result;
if ((pRITimer->CTRL & RIT_CTRL_INT) == 1) {
result = SET;
}
else {
return RESET;
}
return (IntStatus) result;
}
#endif /* defined(CHIP_LPC175X_6X) */

View File

@@ -0,0 +1,221 @@
/*
* @brief LPC17xx/40xx RTC chip driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initialize the RTC peripheral */
void Chip_RTC_Init(LPC_RTC_T *pRTC)
{
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_RTC);
/* Disable RTC */
Chip_RTC_Enable(pRTC, DISABLE);
/* Disable Calibration */
Chip_RTC_CalibCounterCmd(pRTC, DISABLE);
/* Reset RTC Clock */
Chip_RTC_ResetClockTickCounter(pRTC);
/* Clear counter increment and alarm interrupt */
pRTC->ILR = RTC_IRL_RTCCIF | RTC_IRL_RTCALF;
while (pRTC->ILR != 0) {}
/* Clear all register to be default */
pRTC->CIIR = 0x00;
pRTC->AMR = 0xFF;
pRTC->CALIBRATION = 0x00;
}
/*De-initialize the RTC peripheral */
void Chip_RTC_DeInit(LPC_RTC_T *pRTC)
{
pRTC->CCR = 0x00;
Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_RTC);
}
/* Reset clock tick counter in the RTC peripheral */
void Chip_RTC_ResetClockTickCounter(LPC_RTC_T *pRTC)
{
do {
/* Reset RTC clock*/
pRTC->CCR |= RTC_CCR_CTCRST;
} while ((pRTC->CCR & RTC_CCR_CTCRST) != RTC_CCR_CTCRST);
do {
/* Finish resetting RTC clock */
pRTC->CCR &= (~RTC_CCR_CTCRST) & RTC_CCR_BITMASK;
} while (pRTC->CCR & RTC_CCR_CTCRST);
}
/* Start/Stop RTC peripheral */
void Chip_RTC_Enable(LPC_RTC_T *pRTC, FunctionalState NewState)
{
if (NewState == ENABLE) {
do {
pRTC->CCR |= RTC_CCR_CLKEN;
} while ((pRTC->CCR & RTC_CCR_CLKEN) == 0);
}
else {
pRTC->CCR &= (~RTC_CCR_CLKEN) & RTC_CCR_BITMASK;
}
}
/* Enable/Disable Counter increment interrupt for a time type in the RTC peripheral */
void Chip_RTC_CntIncrIntConfig(LPC_RTC_T *pRTC, uint32_t cntrMask, FunctionalState NewState)
{
if (NewState == ENABLE) {
pRTC->CIIR |= cntrMask;
}
else {
pRTC->CIIR &= (~cntrMask) & RTC_AMR_CIIR_BITMASK;
while (pRTC->CIIR & cntrMask) {}
}
}
/* Enable/Disable Alarm interrupt for a time type in the RTC peripheral */
void Chip_RTC_AlarmIntConfig(LPC_RTC_T *pRTC, uint32_t alarmMask, FunctionalState NewState)
{
if (NewState == ENABLE) {
pRTC->AMR &= (~alarmMask) & RTC_AMR_CIIR_BITMASK;
}
else {
pRTC->AMR |= (alarmMask);
while ((pRTC->AMR & alarmMask) == 0) {}
}
}
/* Set full time in the RTC peripheral */
void Chip_RTC_SetFullTime(LPC_RTC_T *pRTC, RTC_TIME_T *pFullTime)
{
RTC_TIMEINDEX_T i;
uint32_t ccr_val = pRTC->CCR;
/* Temporarily disable */
if (ccr_val & RTC_CCR_CLKEN) {
pRTC->CCR = ccr_val & (~RTC_CCR_CLKEN) & RTC_CCR_BITMASK;
}
/* Date time setting */
for (i = RTC_TIMETYPE_SECOND; i < RTC_TIMETYPE_LAST; i++) {
pRTC->TIME[i] = pFullTime->time[i];
}
/* Restore to old setting */
pRTC->CCR = ccr_val;
}
/* Get full time from the RTC peripheral */
void Chip_RTC_GetFullTime(LPC_RTC_T *pRTC, RTC_TIME_T *pFullTime)
{
RTC_TIMEINDEX_T i;
uint32_t secs = 0xFF;
/* Read full time, but verify second tick didn't change during the read. If
it did, re-read the time again so it will be consistent across all fields. */
while (secs != pRTC->TIME[RTC_TIMETYPE_SECOND]) {
secs = pFullTime->time[RTC_TIMETYPE_SECOND] = pRTC->TIME[RTC_TIMETYPE_SECOND];
for (i = RTC_TIMETYPE_MINUTE; i < RTC_TIMETYPE_LAST; i++) {
pFullTime->time[i] = pRTC->TIME[i];
}
}
}
/* Set full alarm time in the RTC peripheral */
void Chip_RTC_SetFullAlarmTime(LPC_RTC_T *pRTC, RTC_TIME_T *pFullTime)
{
RTC_TIMEINDEX_T i;
for (i = RTC_TIMETYPE_SECOND; i < RTC_TIMETYPE_LAST; i++) {
pRTC->ALRM[i] = pFullTime->time[i];
}
}
/* Get full alarm time in the RTC peripheral */
void Chip_RTC_GetFullAlarmTime(LPC_RTC_T *pRTC, RTC_TIME_T *pFullTime)
{
RTC_TIMEINDEX_T i;
for (i = RTC_TIMETYPE_SECOND; i < RTC_TIMETYPE_LAST; i++) {
pFullTime->time[i] = pRTC->ALRM[i];
}
}
/* Enable/Disable calibration counter in the RTC peripheral */
void Chip_RTC_CalibCounterCmd(LPC_RTC_T *pRTC, FunctionalState NewState)
{
if (NewState == ENABLE) {
do {
pRTC->CCR &= (~RTC_CCR_CCALEN) & RTC_CCR_BITMASK;
} while (pRTC->CCR & RTC_CCR_CCALEN);
}
else {
pRTC->CCR |= RTC_CCR_CCALEN;
}
}
#if RTC_EV_SUPPORT
/* Get first timestamp value */
void Chip_RTC_EV_GetFirstTimeStamp(LPC_RTC_T *pRTC, RTC_EV_CHANNEL_T ch, RTC_EV_TIMESTAMP_T *pTimeStamp)
{
pTimeStamp->sec = RTC_ER_TIMESTAMP_SEC(pRTC->ERFIRSTSTAMP[ch]);
pTimeStamp->min = RTC_ER_TIMESTAMP_MIN(pRTC->ERFIRSTSTAMP[ch]);
pTimeStamp->hour = RTC_ER_TIMESTAMP_HOUR(pRTC->ERFIRSTSTAMP[ch]);
pTimeStamp->dayofyear = RTC_ER_TIMESTAMP_DOY(pRTC->ERFIRSTSTAMP[ch]);
}
/* Get last timestamp value */
void Chip_RTC_EV_GetLastTimeStamp(LPC_RTC_T *pRTC, RTC_EV_CHANNEL_T ch, RTC_EV_TIMESTAMP_T *pTimeStamp)
{
pTimeStamp->sec = RTC_ER_TIMESTAMP_SEC(pRTC->ERLASTSTAMP[ch]);
pTimeStamp->min = RTC_ER_TIMESTAMP_MIN(pRTC->ERLASTSTAMP[ch]);
pTimeStamp->hour = RTC_ER_TIMESTAMP_HOUR(pRTC->ERLASTSTAMP[ch]);
pTimeStamp->dayofyear = RTC_ER_TIMESTAMP_DOY(pRTC->ERLASTSTAMP[ch]);
}
#endif /*RTC_EV_SUPPORT*/

View File

@@ -0,0 +1,247 @@
/*
* @brief SD Card Interface registers and control functions
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
#if defined(CHIP_LPC177X_8X) || defined(CHIP_LPC40XX)
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
static void writeDelay(void)
{
volatile uint8_t i;
for ( i = 0; i < 0x10; i++ ) { /* delay 3MCLK + 2PCLK */
}
}
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
/* Set power state of SDC peripheral */
void Chip_SDC_PowerControl(LPC_SDC_T *pSDC, SDC_PWR_CTRL_T pwrMode, uint32_t flag)
{
pSDC->POWER = SDC_PWR_CTRL(pwrMode) | flag;
writeDelay();
}
/* Set clock divider for SDC peripheral */
void Chip_SDC_SetClockDiv(LPC_SDC_T *pSDC, uint8_t div)
{
uint32_t temp;
temp = (pSDC->CLOCK & (~SDC_CLOCK_CLKDIV_BITMASK));
pSDC->CLOCK = temp | (SDC_CLOCK_CLKDIV(div));
writeDelay();
}
/* Clock control for SDC peripheral*/
void Chip_SDC_ClockControl(LPC_SDC_T *pSDC, SDC_CLOCK_CTRL_T ctrlType,
FunctionalState NewState)
{
if (NewState) {
pSDC->CLOCK |= (1 << ctrlType);
}
else {
pSDC->CLOCK &= (~(1 << ctrlType));
}
writeDelay();
}
/* Initialize SDC peripheral */
static void SDC_Init(LPC_SDC_T *pSDC)
{
/* Disable SD_CLK */
Chip_SDC_ClockControl(pSDC, SDC_CLOCK_ENABLE, DISABLE);
/* Power-off */
Chip_SDC_PowerControl(pSDC, SDC_POWER_OFF, 0);
writeDelay();
/* Disable all interrupts */
pSDC->MASK0 = 0;
/*Setting for timeout problem */
pSDC->DATATIMER = 0x1FFFFFFF;
pSDC->COMMAND = 0;
writeDelay();
pSDC->DATACTRL = 0;
writeDelay();
/* clear all pending interrupts */
pSDC->CLEAR = SDC_CLEAR_ALL;
}
/* Initializes the SDC card controller */
void Chip_SDC_Init(LPC_SDC_T *pSDC)
{
uint32_t i = 0;
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SDC);
Chip_SYSCTL_PeriphReset(SYSCTL_RESET_PCSDC);
/* Initialize GPDMA controller */
Chip_GPDMA_Init(LPC_GPDMA);
/* Initialize SDC peripheral */
SDC_Init(pSDC);
/* Power-up SDC Peripheral */
Chip_SDC_PowerControl(pSDC, SDC_POWER_UP, 0);
/* delays for the supply output is stable*/
for ( i = 0; i < 0x80000; i++ ) {}
Chip_SDC_SetClock(pSDC, SDC_IDENT_CLOCK_RATE);
Chip_SDC_ClockControl(pSDC, SDC_CLOCK_ENABLE, ENABLE);
/* Power-on SDC Interface */
Chip_SDC_PowerControl(pSDC, SDC_POWER_ON, 0);
}
/* Set Command Info */
void Chip_SDC_SetCommand(LPC_SDC_T *pSDC, uint32_t Cmd, uint32_t Arg)
{
/* Clear status register */
pSDC->CLEAR = SDC_CLEAR_ALL;
/* Set the argument first, finally command */
pSDC->ARGUMENT = Arg;
/* Write command value, enable the command */
pSDC->COMMAND = Cmd | SDC_COMMAND_ENABLE;
writeDelay();
}
/* Reset Command Info */
void Chip_SDC_ResetCommand(LPC_SDC_T *pSDC)
{
pSDC->CLEAR = SDC_CLEAR_ALL;
pSDC->ARGUMENT = 0xFFFFFFFF;
pSDC->COMMAND = 0;
writeDelay();
}
/* Get Command response */
void Chip_SDC_GetResp(LPC_SDC_T *pSDC, SDC_RESP_T *pResp)
{
uint8_t i;
pResp->CmdIndex = SDC_RESPCOMMAND_VAL(pSDC->RESPCMD);
for (i = 0; i < SDC_CARDSTATUS_BYTENUM; i++) {
pResp->Data[i] = pSDC->RESPONSE[i];
}
}
/* Setup Data Transfer Information */
void Chip_SDC_SetDataTransfer(LPC_SDC_T *pSDC, SDC_DATA_TRANSFER_T *pTransfer)
{
uint32_t DataCtrl = 0;
pSDC->DATATIMER = pTransfer->Timeout;
pSDC->DATALENGTH = pTransfer->BlockNum * SDC_DATACTRL_BLOCKSIZE_VAL(pTransfer->BlockSize);
DataCtrl = SDC_DATACTRL_ENABLE;
DataCtrl |= ((uint32_t) pTransfer->Dir) | ((uint32_t) pTransfer->Mode) | SDC_DATACTRL_BLOCKSIZE(
pTransfer->BlockSize);
if (pTransfer->DMAUsed) {
DataCtrl |= SDC_DATACTRL_DMA_ENABLE;
}
pSDC->DATACTRL = DataCtrl;
writeDelay();
}
/* Write data to FIFO */
void Chip_SDC_WriteFIFO(LPC_SDC_T *pSDC, uint32_t *pSrc, bool bFirstHalf)
{
uint8_t start = 0, end = 7;
if (!bFirstHalf) {
start += 8;
end += 8;
}
for (; start <= end; start++) {
pSDC->FIFO[start] = *pSrc;
pSrc++;
}
}
/* Read data from FIFO */
void Chip_SDC_ReadFIFO(LPC_SDC_T *pSDC, uint32_t *pDst, bool bFirstHalf)
{
uint8_t start = 0, end = 7;
if (!bFirstHalf) {
start += 8;
end += 8;
}
for (; start <= end; start++) {
*pDst = pSDC->FIFO[start];
pDst++;
}
}
/* Set SD_CLK Clock */
void Chip_SDC_SetClock(LPC_SDC_T *pSDC, uint32_t freq)
{
uint32_t PClk;
uint32_t ClkValue = 0;
PClk = Chip_Clock_GetPeripheralClockRate();
ClkValue = (PClk + 2 * freq - 1) / (2 * freq);
if (ClkValue > 0) {
ClkValue -= 1;
}
Chip_SDC_SetClockDiv(pSDC, ClkValue);
}
/* Shutdown the SDC card controller */
void Chip_SDC_DeInit(LPC_SDC_T *pSDC)
{
/* Power-off */
Chip_SDC_PowerControl(pSDC, SDC_POWER_OFF, 0);
Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_SDC);
}
#endif /* defined(CHIP_LPC177X_8X) || defined(CHIP_LPC4XX) */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,227 @@
/*
* @brief LPC17xx/40xx SPI driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
#if defined(CHIP_LPC175X_6X)
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/* Execute callback function */
STATIC void executeCallback(LPC_SPI_T *pSPI, SPI_CALLBACK_T pfunc)
{
if (pfunc) {
(pfunc) ();
}
}
/* Write byte(s) to FIFO buffer */
STATIC void writeData(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *pXfSetup, uint32_t num_bytes)
{
uint16_t data2write = 0xFFFF;
if ( pXfSetup->pTxData) {
data2write = pXfSetup->pTxData[pXfSetup->cnt];
if (num_bytes == 2) {
data2write |= pXfSetup->pTxData[pXfSetup->cnt + 1] << 8;
}
}
Chip_SPI_SendFrame(pSPI, data2write);
}
/* Read byte(s) from FIFO buffer */
STATIC void readData(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *pXfSetup, uint16_t rDat, uint32_t num_bytes)
{
rDat = Chip_SPI_ReceiveFrame(pSPI);
if (pXfSetup->pRxData) {
pXfSetup->pRxData[pXfSetup->cnt] = rDat;
if (num_bytes == 2) {
pXfSetup->pRxData[pXfSetup->cnt + 1] = rDat >> 8;
}
}
}
/*****************************************************************************
* Public functions
****************************************************************************/
/* SPI Polling Read/Write in blocking mode */
uint32_t Chip_SPI_RWFrames_Blocking(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *pXfSetup)
{
uint32_t status;
uint16_t rDat = 0x0000;
uint8_t bytes = 1;
/* Clear status */
Chip_SPI_Int_FlushData(pSPI);
if (Chip_SPI_GetDataSize(pSPI) != SPI_BITS_8) {
bytes = 2;
}
executeCallback(pSPI, pXfSetup->fnBefTransfer);
while (pXfSetup->cnt < pXfSetup->length) {
executeCallback(pSPI, pXfSetup->fnBefFrame);
/* write data to buffer */
writeData(pSPI, pXfSetup, bytes);
/* Wait for transfer completes */
while (1) {
status = Chip_SPI_GetStatus(pSPI);
/* Check error */
if (status & SPI_SR_ERROR) {
goto rw_end;
}
if (status & SPI_SR_SPIF) {
break;
}
}
executeCallback(pSPI, pXfSetup->fnAftFrame);
/* Read data*/
readData(pSPI, pXfSetup, rDat, bytes);
pXfSetup->cnt += bytes;
}
rw_end:
executeCallback(pSPI, pXfSetup->fnAftTransfer);
return pXfSetup->cnt;
}
/* Clean all data in RX FIFO of SPI */
void Chip_SPI_Int_FlushData(LPC_SPI_T *pSPI)
{
volatile uint32_t tmp;
Chip_SPI_GetStatus(pSPI);
tmp = Chip_SPI_ReceiveFrame(pSPI);
Chip_SPI_Int_ClearStatus(pSPI, SPI_INT_SPIF);
}
/* SPI Interrupt Read/Write with 8-bit frame width */
Status Chip_SPI_Int_RWFrames(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *pXfSetup, uint8_t bytes)
{
uint32_t status;
uint16_t rDat = 0x0000;
status = Chip_SPI_GetStatus(pSPI);
/* Check error status */
if (status & SPI_SR_ERROR) {
return ERROR;
}
Chip_SPI_Int_ClearStatus(pSPI, SPI_INT_SPIF);
if (status & SPI_SR_SPIF) {
executeCallback(pSPI, pXfSetup->fnAftFrame);
if (pXfSetup->cnt < pXfSetup->length) {
/* read data */
readData(pSPI, pXfSetup, rDat, bytes);
pXfSetup->cnt += bytes;
}
}
if (pXfSetup->cnt < pXfSetup->length) {
executeCallback(pSPI, pXfSetup->fnBefFrame);
/* Write data */
writeData(pSPI, pXfSetup, bytes);
}
else {
executeCallback(pSPI, pXfSetup->fnAftTransfer);
}
return SUCCESS;
}
/* SPI Interrupt Read/Write with 8-bit frame width */
Status Chip_SPI_Int_RWFrames8Bits(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *pXfSetup)
{
return Chip_SPI_Int_RWFrames(pSPI, pXfSetup, 1);
}
/* SPI Interrupt Read/Write with 16-bit frame width */
Status Chip_SPI_Int_RWFrames16Bits(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *pXfSetup)
{
return Chip_SPI_Int_RWFrames(pSPI, pXfSetup, 2);
}
/* Set the clock frequency for SPI interface */
void Chip_SPI_SetBitRate(LPC_SPI_T *pSPI, uint32_t bitRate)
{
uint32_t spiClk, counter;
/* Get SPI clock rate */
spiClk = Chip_Clock_GetPeripheralClockRate(SYSCTL_PCLK_SPI);
counter = spiClk / bitRate;
if (counter < 8) {
counter = 8;
}
counter = ((counter + 1) / 2) * 2;
if (counter > 254) {
counter = 254;
}
Chip_SPI_SetClockCounter(pSPI, counter);
}
/* Initialize the SPI */
void Chip_SPI_Init(LPC_SPI_T *pSPI)
{
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SPI);
Chip_SPI_SetMode(pSPI, SPI_MODE_MASTER);
pSPI->CR = (pSPI->CR & (~0xF1C)) | SPI_CR_BIT_EN | SPI_BITS_8 | SPI_CLOCK_CPHA0_CPOL0 | SPI_DATA_MSB_FIRST;
Chip_SPI_SetBitRate(pSPI, 400000);
}
/* De-initializes the SPI peripheral */
void Chip_SPI_DeInit(LPC_SPI_T *pSPI)
{
Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_SPI);
}
#endif /* defined(CHIP_LPC175X_6X) */

View File

@@ -0,0 +1,478 @@
/*
* @brief LPC17xx/40xx SSP driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
STATIC void SSP_Write2BFifo(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
{
if (xf_setup->tx_data) {
Chip_SSP_SendFrame(pSSP, (*(uint16_t *) ((uint32_t) xf_setup->tx_data +
xf_setup->tx_cnt)));
}
else {
Chip_SSP_SendFrame(pSSP, 0xFFFF);
}
xf_setup->tx_cnt += 2;
}
/** SSP macro: write 1 bytes to FIFO buffer */
STATIC void SSP_Write1BFifo(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
{
if (xf_setup->tx_data) {
Chip_SSP_SendFrame(pSSP, (*(uint8_t *) ((uint32_t) xf_setup->tx_data + xf_setup->tx_cnt)));
}
else {
Chip_SSP_SendFrame(pSSP, 0xFF);
}
xf_setup->tx_cnt++;
}
/** SSP macro: read 1 bytes from FIFO buffer */
STATIC void SSP_Read2BFifo(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
{
uint16_t rDat;
while ((Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET) &&
(xf_setup->rx_cnt < xf_setup->length)) {
rDat = Chip_SSP_ReceiveFrame(pSSP);
if (xf_setup->rx_data) {
*(uint16_t *) ((uint32_t) xf_setup->rx_data + xf_setup->rx_cnt) = rDat;
}
xf_setup->rx_cnt += 2;
}
}
/** SSP macro: read 2 bytes from FIFO buffer */
STATIC void SSP_Read1BFifo(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
{
uint16_t rDat;
while ((Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET) &&
(xf_setup->rx_cnt < xf_setup->length)) {
rDat = Chip_SSP_ReceiveFrame(pSSP);
if (xf_setup->rx_data) {
*(uint8_t *) ((uint32_t) xf_setup->rx_data + xf_setup->rx_cnt) = rDat;
}
xf_setup->rx_cnt++;
}
}
/* Returns clock for the peripheral block */
STATIC CHIP_SYSCTL_CLOCK_T Chip_SSP_GetClockIndex(LPC_SSP_T *pSSP)
{
CHIP_SYSCTL_CLOCK_T clkSSP;
if (pSSP == LPC_SSP1) {
clkSSP = SYSCTL_CLOCK_SSP1;
}
#if defined(CHIP_LPC177X_8X) || defined(CHIP_LPC40XX)
else if (pSSP == LPC_SSP2) {
clkSSP = SYSCTL_CLOCK_SSP2;
}
#endif
else {
clkSSP = SYSCTL_CLOCK_SSP0;
}
return clkSSP;
}
#if defined(CHIP_LPC175X_6X)
/* Returns clock ID for the peripheral block */
STATIC CHIP_SYSCTL_PCLK_T Chip_SSP_GetClkIndex(LPC_SSP_T *pSSP)
{
CHIP_SYSCTL_PCLK_T clkSSP;
if (pSSP == LPC_SSP0) {
clkSSP = SYSCTL_PCLK_SSP0;
}
else {
clkSSP = SYSCTL_PCLK_SSP1;
}
return clkSSP;
}
#endif
/*****************************************************************************
* Public functions
****************************************************************************/
/*Set up output clocks per bit for SSP bus*/
void Chip_SSP_SetClockRate(LPC_SSP_T *pSSP, uint32_t clk_rate, uint32_t prescale)
{
uint32_t temp;
temp = pSSP->CR0 & (~(SSP_CR0_SCR(0xFF)));
pSSP->CR0 = temp | (SSP_CR0_SCR(clk_rate));
pSSP->CPSR = prescale;
}
/* SSP Polling Read/Write in blocking mode */
uint32_t Chip_SSP_RWFrames_Blocking(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
{
/* Clear all remaining frames in RX FIFO */
while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE)) {
Chip_SSP_ReceiveFrame(pSSP);
}
/* Clear status */
Chip_SSP_ClearIntPending(pSSP, SSP_INT_CLEAR_BITMASK);
if (Chip_SSP_GetDataSize(pSSP) > SSP_BITS_8) {
while (xf_setup->rx_cnt < xf_setup->length || xf_setup->tx_cnt < xf_setup->length) {
/* write data to buffer */
if (( Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && ( xf_setup->tx_cnt < xf_setup->length) ) {
SSP_Write2BFifo(pSSP, xf_setup);
}
/* Check overrun error */
if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
return ERROR;
}
/* Check for any data available in RX FIFO */
SSP_Read2BFifo(pSSP, xf_setup);
}
}
else {
while (xf_setup->rx_cnt < xf_setup->length || xf_setup->tx_cnt < xf_setup->length) {
/* write data to buffer */
if (( Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && ( xf_setup->tx_cnt < xf_setup->length) ) {
SSP_Write1BFifo(pSSP, xf_setup);
}
/* Check overrun error */
if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
return ERROR;
}
/* Check for any data available in RX FIFO */
SSP_Read1BFifo(pSSP, xf_setup);
}
}
if (xf_setup->tx_data) {
return xf_setup->tx_cnt;
}
else if (xf_setup->rx_data) {
return xf_setup->rx_cnt;
}
return 0;
}
/* SSP Polling Write in blocking mode */
uint32_t Chip_SSP_WriteFrames_Blocking(LPC_SSP_T *pSSP, uint8_t *buffer, uint32_t buffer_len)
{
uint32_t tx_cnt = 0, rx_cnt = 0;
/* Clear all remaining frames in RX FIFO */
while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE)) {
Chip_SSP_ReceiveFrame(pSSP);
}
/* Clear status */
Chip_SSP_ClearIntPending(pSSP, SSP_INT_CLEAR_BITMASK);
if (Chip_SSP_GetDataSize(pSSP) > SSP_BITS_8) {
uint16_t *wdata16;
wdata16 = (uint16_t *) buffer;
while (tx_cnt < buffer_len || rx_cnt < buffer_len) {
/* write data to buffer */
if ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) {
Chip_SSP_SendFrame(pSSP, *wdata16);
wdata16++;
tx_cnt += 2;
}
/* Check overrun error */
if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
return ERROR;
}
/* Check for any data available in RX FIFO */
while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET) {
Chip_SSP_ReceiveFrame(pSSP); /* read dummy data */
rx_cnt += 2;
}
}
}
else {
uint8_t *wdata8;
wdata8 = buffer;
while (tx_cnt < buffer_len || rx_cnt < buffer_len) {
/* write data to buffer */
if ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) {
Chip_SSP_SendFrame(pSSP, *wdata8);
wdata8++;
tx_cnt++;
}
/* Check overrun error */
if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
return ERROR;
}
/* Check for any data available in RX FIFO */
while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET && rx_cnt < buffer_len) {
Chip_SSP_ReceiveFrame(pSSP); /* read dummy data */
rx_cnt++;
}
}
}
return tx_cnt;
}
/* SSP Polling Read in blocking mode */
uint32_t Chip_SSP_ReadFrames_Blocking(LPC_SSP_T *pSSP, uint8_t *buffer, uint32_t buffer_len)
{
uint32_t rx_cnt = 0, tx_cnt = 0;
/* Clear all remaining frames in RX FIFO */
while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE)) {
Chip_SSP_ReceiveFrame(pSSP);
}
/* Clear status */
Chip_SSP_ClearIntPending(pSSP, SSP_INT_CLEAR_BITMASK);
if (Chip_SSP_GetDataSize(pSSP) > SSP_BITS_8) {
uint16_t *rdata16;
rdata16 = (uint16_t *) buffer;
while (tx_cnt < buffer_len || rx_cnt < buffer_len) {
/* write data to buffer */
if ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) {
Chip_SSP_SendFrame(pSSP, 0xFFFF); /* just send dummy data */
tx_cnt += 2;
}
/* Check overrun error */
if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
return ERROR;
}
/* Check for any data available in RX FIFO */
while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET && rx_cnt < buffer_len) {
*rdata16 = Chip_SSP_ReceiveFrame(pSSP);
rdata16++;
rx_cnt += 2;
}
}
}
else {
uint8_t *rdata8;
rdata8 = buffer;
while (tx_cnt < buffer_len || rx_cnt < buffer_len) {
/* write data to buffer */
if ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) {
Chip_SSP_SendFrame(pSSP, 0xFF); /* just send dummy data */
tx_cnt++;
}
/* Check overrun error */
if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
return ERROR;
}
/* Check for any data available in RX FIFO */
while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET && rx_cnt < buffer_len) {
*rdata8 = Chip_SSP_ReceiveFrame(pSSP);
rdata8++;
rx_cnt++;
}
}
}
return rx_cnt;
}
/* Clean all data in RX FIFO of SSP */
void Chip_SSP_Int_FlushData(LPC_SSP_T *pSSP)
{
if (Chip_SSP_GetStatus(pSSP, SSP_STAT_BSY)) {
while (Chip_SSP_GetStatus(pSSP, SSP_STAT_BSY)) {}
}
/* Clear all remaining frames in RX FIFO */
while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE)) {
Chip_SSP_ReceiveFrame(pSSP);
}
/* Clear status */
Chip_SSP_ClearIntPending(pSSP, SSP_INT_CLEAR_BITMASK);
}
/* SSP Interrupt Read/Write with 8-bit frame width */
Status Chip_SSP_Int_RWFrames8Bits(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
{
/* Check overrun error in RIS register */
if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
return ERROR;
}
if ((xf_setup->tx_cnt != xf_setup->length) || (xf_setup->rx_cnt != xf_setup->length)) {
/* check if RX FIFO contains data */
SSP_Read1BFifo(pSSP, xf_setup);
while ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF)) && (xf_setup->tx_cnt != xf_setup->length)) {
/* Write data to buffer */
SSP_Write1BFifo(pSSP, xf_setup);
/* Check overrun error in RIS register */
if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
return ERROR;
}
/* Check for any data available in RX FIFO */
SSP_Read1BFifo(pSSP, xf_setup);
}
return SUCCESS;
}
return ERROR;
}
/* SSP Interrupt Read/Write with 16-bit frame width */
Status Chip_SSP_Int_RWFrames16Bits(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
{
/* Check overrun error in RIS register */
if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
return ERROR;
}
if ((xf_setup->tx_cnt != xf_setup->length) || (xf_setup->rx_cnt != xf_setup->length)) {
/* check if RX FIFO contains data */
SSP_Read2BFifo(pSSP, xf_setup);
while ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF)) && (xf_setup->tx_cnt != xf_setup->length)) {
/* Write data to buffer */
SSP_Write2BFifo(pSSP, xf_setup);
/* Check overrun error in RIS register */
if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
return ERROR;
}
/* Check for any data available in RX FIFO */
SSP_Read2BFifo(pSSP, xf_setup);
}
return SUCCESS;
}
return ERROR;
}
/* Set the SSP operating modes, master or slave */
void Chip_SSP_SetMaster(LPC_SSP_T *pSSP, bool master)
{
if (master) {
Chip_SSP_Set_Mode(pSSP, SSP_MODE_MASTER);
}
else {
Chip_SSP_Set_Mode(pSSP, SSP_MODE_SLAVE);
}
}
/* Set the clock frequency for SSP interface */
void Chip_SSP_SetBitRate(LPC_SSP_T *pSSP, uint32_t bitRate)
{
uint32_t ssp_clk, cr0_div, cmp_clk, prescale;
#if defined(CHIP_LPC175X_6X)
ssp_clk = Chip_Clock_GetPeripheralClockRate(Chip_SSP_GetClkIndex(pSSP));
#else
ssp_clk = Chip_Clock_GetPeripheralClockRate();
#endif
cr0_div = 0;
cmp_clk = 0xFFFFFFFF;
prescale = 2;
while (cmp_clk > bitRate) {
cmp_clk = ssp_clk / ((cr0_div + 1) * prescale);
if (cmp_clk > bitRate) {
cr0_div++;
if (cr0_div > 0xFF) {
cr0_div = 0;
prescale += 2;
}
}
}
Chip_SSP_SetClockRate(pSSP, cr0_div, prescale);
}
/* Initialize the SSP */
void Chip_SSP_Init(LPC_SSP_T *pSSP)
{
Chip_Clock_EnablePeriphClock(Chip_SSP_GetClockIndex(pSSP));
Chip_SSP_Set_Mode(pSSP, SSP_MODE_MASTER);
Chip_SSP_SetFormat(pSSP, SSP_BITS_8, SSP_FRAMEFORMAT_SPI, SSP_CLOCK_CPHA0_CPOL0);
Chip_SSP_SetBitRate(pSSP, 100000);
}
/* De-initializes the SSP peripheral */
void Chip_SSP_DeInit(LPC_SSP_T *pSSP)
{
Chip_SSP_Disable(pSSP);
Chip_Clock_DisablePeriphClock(Chip_SSP_GetClockIndex(pSSP));
}

View File

@@ -0,0 +1,110 @@
/*
* @brief LPC17xx_40xx specific stopwatch implementation
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
#include "stopwatch.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/* Precompute these to optimize runtime */
static uint32_t ticksPerSecond;
static uint32_t ticksPerMs;
static uint32_t ticksPerUs;
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initialize stopwatch */
void StopWatch_Init(void)
{
/* Use timer 1. Set prescaler to divide by 8, should give ticks at 3.75 MHz.
That gives a useable stopwatch measurement range of about 19 minutes
(if system clock is running at 120 MHz). */
const uint32_t prescaleDivisor = 8;
Chip_TIMER_Init(LPC_TIMER1);
Chip_TIMER_PrescaleSet(LPC_TIMER1, prescaleDivisor - 1);
Chip_TIMER_Enable(LPC_TIMER1);
/* Pre-compute tick rate. Note that peripheral clock supplied to the
timer includes a fixed divide by 4. */
ticksPerSecond = Chip_Clock_GetSystemClockRate() / prescaleDivisor / 4;
ticksPerMs = ticksPerSecond / 1000;
ticksPerUs = ticksPerSecond / 1000000;
}
/* Start a stopwatch */
uint32_t StopWatch_Start(void)
{
/* Return the current timer count. */
return Chip_TIMER_ReadCount(LPC_TIMER1);
}
/* Returns number of ticks per second of the stopwatch timer */
uint32_t StopWatch_TicksPerSecond(void)
{
return ticksPerSecond;
}
/* Converts from stopwatch ticks to mS. */
uint32_t StopWatch_TicksToMs(uint32_t ticks)
{
return ticks / ticksPerMs;
}
/* Converts from stopwatch ticks to uS. */
uint32_t StopWatch_TicksToUs(uint32_t ticks)
{
return ticks / ticksPerUs;
}
/* Converts from mS to stopwatch ticks. */
uint32_t StopWatch_MsToTicks(uint32_t mS)
{
return mS * ticksPerMs;
}
/* Converts from uS to stopwatch ticks. */
uint32_t StopWatch_UsToTicks(uint32_t uS)
{
return uS * ticksPerUs;
}

View File

@@ -0,0 +1,70 @@
/*
* @brief LPC17xx/40xx System and Control driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/* Returns and clears the current sleep mode entry flags */
uint32_t Chip_SYSCTL_GetClrSleepFlags(uint32_t flags) {
uint32_t savedFlags = LPC_SYSCTL->PCON;
LPC_SYSCTL->PCON = flags;
return savedFlags & (SYSCTL_PD_SMFLAG | SYSCTL_PD_DSFLAG |
SYSCTL_PD_PDFLAG | SYSCTL_PD_DPDFLAG);
}
#if !defined(CHIP_LPC175X_6X)
/* Resets a peripheral */
void Chip_SYSCTL_PeriphReset(CHIP_SYSCTL_RESET_T periph)
{
uint32_t bitIndex, regIndex = (uint32_t) periph;
/* Get register array index and clock index into the register */
bitIndex = (regIndex % 32);
regIndex = regIndex / 32;
/* Reset peripheral */
LPC_SYSCTL->RSTCON[regIndex] = (1 << bitIndex);
LPC_SYSCTL->RSTCON[regIndex] &= ~(1 << bitIndex);
}
#endif /*!defined(CHIP_LPC175X_6X)*/

View File

@@ -0,0 +1,178 @@
/*
* @brief LPC17xx/40xx Chip specific SystemInit
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
#if defined(CHIP_LPC175X_6X)
void Chip_SetupIrcClocking(void)
{
/* Disconnect the Main PLL if it is connected already */
if (Chip_Clock_IsMainPLLConnected()) {
Chip_Clock_DisablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_CONNECT);
}
/* Disable the PLL if it is enabled */
if (Chip_Clock_IsMainPLLEnabled()) {
Chip_Clock_DisablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_ENABLE);
}
Chip_Clock_SetCPUClockDiv(0);
Chip_Clock_SetMainPLLSource(SYSCTL_PLLCLKSRC_IRC);
/* FCCO = ((44+1) * 2 * 4MHz) / (0+1) = 360MHz */
Chip_Clock_SetupPLL(SYSCTL_MAIN_PLL, 44, 0);
Chip_Clock_EnablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_ENABLE);
Chip_Clock_SetCPUClockDiv(2);
while (!Chip_Clock_IsMainPLLLocked()) {} /* Wait for the PLL to Lock */
Chip_Clock_EnablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_CONNECT);
}
void Chip_SetupXtalClocking(void)
{
/* Disconnect the Main PLL if it is connected already */
if (Chip_Clock_IsMainPLLConnected()) {
Chip_Clock_DisablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_CONNECT);
}
/* Disable the PLL if it is enabled */
if (Chip_Clock_IsMainPLLEnabled()) {
Chip_Clock_DisablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_ENABLE);
}
/* Enable the crystal */
if (!Chip_Clock_IsCrystalEnabled())
Chip_Clock_EnableCrystal();
while(!Chip_Clock_IsCrystalEnabled()) {}
/* Set PLL0 Source to Crystal Oscillator */
Chip_Clock_SetCPUClockDiv(0);
Chip_Clock_SetMainPLLSource(SYSCTL_PLLCLKSRC_MAINOSC);
/* FCCO = ((15+1) * 2 * 12MHz) / (0+1) = 384MHz */
Chip_Clock_SetupPLL(SYSCTL_MAIN_PLL, 15, 0);
Chip_Clock_EnablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_ENABLE);
/* 384MHz / (3+1) = 96MHz */
Chip_Clock_SetCPUClockDiv(3);
while (!Chip_Clock_IsMainPLLLocked()) {} /* Wait for the PLL to Lock */
Chip_Clock_EnablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_CONNECT);
}
#endif
#if (defined(CHIP_LPC177X_8X) | defined(CHIP_LPC40XX))
/* Clock and PLL initialization based on the internal oscillator */
void Chip_SetupIrcClocking(void)
{
/* Clock the CPU from SYSCLK, in case if it is clocked by PLL0 */
Chip_Clock_SetCPUClockSource(SYSCTL_CCLKSRC_SYSCLK);
/* Disable the PLL if it is enabled */
if (Chip_Clock_IsMainPLLEnabled()) {
Chip_Clock_DisablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_ENABLE);
}
/* It is safe to switch the PLL Source to IRC */
Chip_Clock_SetMainPLLSource(SYSCTL_PLLCLKSRC_IRC);
/* FCCO = 12MHz * (9+1) * 2 * (0+1) = 240MHz */
/* Fout = FCCO / ((0+1) * 2) = 120MHz */
Chip_Clock_SetupPLL(SYSCTL_MAIN_PLL, 9, 0);
Chip_Clock_EnablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_ENABLE);
Chip_Clock_SetCPUClockDiv(1);
while (!Chip_Clock_IsMainPLLLocked()) {} /* Wait for the PLL to Lock */
Chip_Clock_SetCPUClockSource(SYSCTL_CCLKSRC_MAINPLL);
/* Peripheral clocking will be derived from PLL0 with a divider of 2 (60MHz) */
Chip_Clock_SetPCLKDiv(2);
}
/* Clock and PLL initialization based on the external oscillator */
void Chip_SetupXtalClocking(void)
{
/* Enable the crystal */
if (!Chip_Clock_IsCrystalEnabled())
Chip_Clock_EnableCrystal();
while(!Chip_Clock_IsCrystalEnabled()) {}
/* Clock the CPU from SYSCLK, in case if it is clocked by PLL0 */
Chip_Clock_SetCPUClockSource(SYSCTL_CCLKSRC_SYSCLK);
/* Disable the PLL if it is enabled */
if (Chip_Clock_IsMainPLLEnabled()) {
Chip_Clock_DisablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_ENABLE);
}
/* It is safe to switch the PLL Source to Crystal Oscillator */
Chip_Clock_SetMainPLLSource(SYSCTL_PLLCLKSRC_MAINOSC);
/* FCCO = 12MHz * (9+1) * 2 * (0+1) = 240MHz */
/* Fout = FCCO / ((0+1) * 2) = 120MHz */
Chip_Clock_SetupPLL(SYSCTL_MAIN_PLL, 9, 0);
Chip_Clock_EnablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_ENABLE);
Chip_Clock_SetCPUClockDiv(1);
while (!Chip_Clock_IsMainPLLLocked()) {} /* Wait for the PLL to Lock */
Chip_Clock_SetCPUClockSource(SYSCTL_CCLKSRC_MAINPLL);
/* Peripheral clocking will be derived from PLL0 with a divider of 2 (60MHz) */
Chip_Clock_SetPCLKDiv(2);
}
#endif
/* Set up and initialize hardware prior to call to main */
void Chip_SystemInit(void)
{
/* Setup Chip clocking */
Chip_SetupIrcClocking();
}

View File

@@ -0,0 +1,116 @@
/*
* @brief LPC17xx/40xx 16/32-bit Timer/PWM driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/* Returns clock for the peripheral block */
STATIC CHIP_SYSCTL_CLOCK_T Chip_Timer_GetClockIndex(LPC_TIMER_T *pTMR)
{
CHIP_SYSCTL_CLOCK_T clkTMR;
if (pTMR == LPC_TIMER1) {
clkTMR = SYSCTL_CLOCK_TIMER1;
}
else if (pTMR == LPC_TIMER2) {
clkTMR = SYSCTL_CLOCK_TIMER2;
}
else if (pTMR == LPC_TIMER3) {
clkTMR = SYSCTL_CLOCK_TIMER3;
}
else {
clkTMR = SYSCTL_CLOCK_TIMER0;
}
return clkTMR;
}
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initialize a timer */
void Chip_TIMER_Init(LPC_TIMER_T *pTMR)
{
Chip_Clock_EnablePeriphClock(Chip_Timer_GetClockIndex(pTMR));
}
/* Shutdown a timer */
void Chip_TIMER_DeInit(LPC_TIMER_T *pTMR)
{
Chip_Clock_DisablePeriphClock(Chip_Timer_GetClockIndex(pTMR));
}
/* Resets the timer terminal and prescale counts to 0 */
void Chip_TIMER_Reset(LPC_TIMER_T *pTMR)
{
uint32_t reg;
/* Disable timer, set terminal count to non-0 */
reg = pTMR->TCR;
pTMR->TCR = 0;
pTMR->TC = 1;
/* Reset timer counter */
pTMR->TCR = TIMER_RESET;
/* Wait for terminal count to clear */
while (pTMR->TC != 0) {}
/* Restore timer state */
pTMR->TCR = reg;
}
/* Sets external match control (MATn.matchnum) pin control */
void Chip_TIMER_ExtMatchControlSet(LPC_TIMER_T *pTMR, int8_t initial_state,
TIMER_PIN_MATCH_STATE_T matchState, int8_t matchnum)
{
uint32_t mask, reg;
/* Clear bits corresponding to selected match register */
mask = (1 << matchnum) | (0x03 << (4 + (matchnum * 2)));
reg = pTMR->EMR &= ~mask;
/* Set new configuration for selected match register */
pTMR->EMR = reg | (((uint32_t) initial_state) << matchnum) |
(((uint32_t) matchState) << (4 + (matchnum * 2)));
}

View File

@@ -0,0 +1,533 @@
/*
* @brief LPC11xx UART chip driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/* Autobaud status flag */
STATIC volatile FlagStatus ABsyncSts = RESET;
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/* Returns clock for the peripheral block */
STATIC CHIP_SYSCTL_CLOCK_T Chip_UART_GetClockIndex(LPC_USART_T *pUART)
{
CHIP_SYSCTL_CLOCK_T clkUART;
if (pUART == LPC_UART1) {
clkUART = SYSCTL_CLOCK_UART1;
}
else if (pUART == LPC_UART2) {
clkUART = SYSCTL_CLOCK_UART2;
}
else if (pUART == LPC_UART3) {
clkUART = SYSCTL_CLOCK_UART3;
}
#if defined(CHIP_LPC177X_8X) || defined(CHIP_LPC40XX)
else if (pUART == LPC_UART4) {
clkUART = SYSCTL_CLOCK_UART4;
}
#endif
else {
clkUART = SYSCTL_CLOCK_UART0;
}
return clkUART;
}
/* UART Autobaud command interrupt handler */
STATIC void Chip_UART_ABIntHandler(LPC_USART_T *pUART)
{
/* Handle End Of Autobaud interrupt */
if((Chip_UART_ReadIntIDReg(pUART) & UART_IIR_ABEO_INT) != 0) {
Chip_UART_SetAutoBaudReg(pUART, UART_ACR_ABEOINT_CLR);
Chip_UART_IntDisable(pUART, UART_IER_ABEOINT);
if (ABsyncSts == RESET) {
ABsyncSts = SET;
}
}
/* Handle Autobaud Timeout interrupt */
if((Chip_UART_ReadIntIDReg(pUART) & UART_IIR_ABTO_INT) != 0) {
Chip_UART_SetAutoBaudReg(pUART, UART_ACR_ABTOINT_CLR);
Chip_UART_IntDisable(pUART, UART_IER_ABTOINT);
}
}
#if defined(CHIP_LPC175X_6X)
/* Returns clock ID for the peripheral block */
STATIC CHIP_SYSCTL_PCLK_T Chip_UART_GetClkIndex(LPC_USART_T *pUART)
{
CHIP_SYSCTL_PCLK_T clkUART;
if (pUART == LPC_UART1) {
clkUART = SYSCTL_PCLK_UART1;
}
else if (pUART == LPC_UART2) {
clkUART = SYSCTL_PCLK_UART2;
}
else if (pUART == LPC_UART3) {
clkUART = SYSCTL_PCLK_UART3;
}
else {
clkUART = SYSCTL_PCLK_UART0;
}
return clkUART;
}
#endif
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initializes the pUART peripheral */
void Chip_UART_Init(LPC_USART_T *pUART)
{
uint32_t tmp;
(void) tmp;
/* Enable UART clocking. UART base clock(s) must already be enabled */
Chip_Clock_EnablePeriphClock(Chip_UART_GetClockIndex(pUART));
/* Enable FIFOs by default, reset them */
Chip_UART_SetupFIFOS(pUART, (UART_FCR_FIFO_EN | UART_FCR_RX_RS | UART_FCR_TX_RS));
/* Disable Tx */
Chip_UART_TXDisable(pUART);
/* Disable interrupts */
pUART->IER = 0;
/* Set LCR to default state */
pUART->LCR = 0;
/* Set ACR to default state */
pUART->ACR = 0;
/* Set RS485 control to default state */
pUART->RS485CTRL = 0;
/* Set RS485 delay timer to default state */
pUART->RS485DLY = 0;
/* Set RS485 addr match to default state */
pUART->RS485ADRMATCH = 0;
/* Clear MCR */
if (pUART == LPC_UART1) {
/* Set Modem Control to default state */
pUART->MCR = 0;
/*Dummy Reading to Clear Status */
tmp = pUART->MSR;
}
/* Default 8N1, with DLAB disabled */
Chip_UART_ConfigData(pUART, (UART_LCR_WLEN8 | UART_LCR_SBS_1BIT | UART_LCR_PARITY_DIS));
/* Disable fractional divider */
pUART->FDR = 0x10;
}
/* De-initializes the pUART peripheral */
void Chip_UART_DeInit(LPC_USART_T *pUART)
{
/* Disable Tx */
Chip_UART_TXDisable(pUART);
/* Disable clock */
Chip_Clock_DisablePeriphClock(Chip_UART_GetClockIndex(pUART));
}
/* Enable transmission on UART TxD pin */
void Chip_UART_TXEnable(LPC_USART_T *pUART)
{
#if defined(CHIP_LPC177X_8X) || defined(CHIP_LPC40XX)
if(pUART == LPC_UART4) {
pUART->TER2 = UART_TER2_TXEN;
}
else {
#endif
pUART->TER1 = UART_TER1_TXEN;
#if defined(CHIP_LPC177X_8X) || defined(CHIP_LPC40XX)
}
#endif
}
/* Disable transmission on UART TxD pin */
void Chip_UART_TXDisable(LPC_USART_T *pUART)
{
#if defined(CHIP_LPC177X_8X) || defined(CHIP_LPC40XX)
if(pUART == LPC_UART4) {
pUART->TER2 = 0;
}
else {
#endif
pUART->TER1 = 0;
#if defined(CHIP_LPC177X_8X) || defined(CHIP_LPC40XX)
}
#endif
}
/* Transmit a byte array through the UART peripheral (non-blocking) */
int Chip_UART_Send(LPC_USART_T *pUART, const void *data, int numBytes)
{
int sent = 0;
uint8_t *p8 = (uint8_t *) data;
/* Send until the transmit FIFO is full or out of bytes */
while ((sent < numBytes) &&
((Chip_UART_ReadLineStatus(pUART) & UART_LSR_THRE) != 0)) {
Chip_UART_SendByte(pUART, *p8);
p8++;
sent++;
}
return sent;
}
/* Check whether if UART is busy or not */
FlagStatus Chip_UART_CheckBusy(LPC_USART_T *pUART)
{
if (pUART->LSR & UART_LSR_TEMT) {
return RESET;
}
else {
return SET;
}
}
/* Transmit a byte array through the UART peripheral (blocking) */
int Chip_UART_SendBlocking(LPC_USART_T *pUART, const void *data, int numBytes)
{
int pass, sent = 0;
uint8_t *p8 = (uint8_t *) data;
while (numBytes > 0) {
pass = Chip_UART_Send(pUART, p8, numBytes);
numBytes -= pass;
sent += pass;
p8 += pass;
}
return sent;
}
/* Read data through the UART peripheral (non-blocking) */
int Chip_UART_Read(LPC_USART_T *pUART, void *data, int numBytes)
{
int readBytes = 0;
uint8_t *p8 = (uint8_t *) data;
/* Send until the transmit FIFO is full or out of bytes */
while ((readBytes < numBytes) &&
((Chip_UART_ReadLineStatus(pUART) & UART_LSR_RDR) != 0)) {
*p8 = Chip_UART_ReadByte(pUART);
p8++;
readBytes++;
}
return readBytes;
}
/* Read data through the UART peripheral (blocking) */
int Chip_UART_ReadBlocking(LPC_USART_T *pUART, void *data, int numBytes)
{
int pass, readBytes = 0;
uint8_t *p8 = (uint8_t *) data;
while (readBytes < numBytes) {
pass = Chip_UART_Read(pUART, p8, numBytes);
numBytes -= pass;
readBytes += pass;
p8 += pass;
}
return readBytes;
}
/* Determines and sets best dividers to get a target bit rate */
uint32_t Chip_UART_SetBaud(LPC_USART_T *pUART, uint32_t baudrate)
{
uint32_t div, divh, divl, clkin;
/* Determine UART clock in rate without FDR */
#if defined(CHIP_LPC175X_6X)
clkin = Chip_Clock_GetPeripheralClockRate(Chip_UART_GetClkIndex(pUART));
#else
clkin = Chip_Clock_GetPeripheralClockRate();
#endif
div = clkin / (baudrate * 16);
/* High and low halves of the divider */
divh = div / 256;
divl = div - (divh * 256);
Chip_UART_EnableDivisorAccess(pUART);
Chip_UART_SetDivisorLatches(pUART, divl, divh);
Chip_UART_DisableDivisorAccess(pUART);
/* Fractional FDR already setup for 1 in UART init */
return clkin / div;
}
/* UART receive-only interrupt handler for ring buffers */
void Chip_UART_RXIntHandlerRB(LPC_USART_T *pUART, RINGBUFF_T *pRB)
{
/* New data will be ignored if data not popped in time */
while (Chip_UART_ReadLineStatus(pUART) & UART_LSR_RDR) {
uint8_t ch = Chip_UART_ReadByte(pUART);
RingBuffer_Insert(pRB, &ch);
}
}
/* UART transmit-only interrupt handler for ring buffers */
void Chip_UART_TXIntHandlerRB(LPC_USART_T *pUART, RINGBUFF_T *pRB)
{
uint8_t ch;
/* Fill FIFO until full or until TX ring buffer is empty */
while ((Chip_UART_ReadLineStatus(pUART) & UART_LSR_THRE) != 0 &&
RingBuffer_Pop(pRB, &ch)) {
Chip_UART_SendByte(pUART, ch);
}
}
/* Populate a transmit ring buffer and start UART transmit */
uint32_t Chip_UART_SendRB(LPC_USART_T *pUART, RINGBUFF_T *pRB, const void *data, int bytes)
{
uint32_t ret;
uint8_t *p8 = (uint8_t *) data;
/* Don't let UART transmit ring buffer change in the UART IRQ handler */
Chip_UART_IntDisable(pUART, UART_IER_THREINT);
/* Move as much data as possible into transmit ring buffer */
ret = RingBuffer_InsertMult(pRB, p8, bytes);
Chip_UART_TXIntHandlerRB(pUART, pRB);
/* Add additional data to transmit ring buffer if possible */
ret += RingBuffer_InsertMult(pRB, (p8 + ret), (bytes - ret));
/* Enable UART transmit interrupt */
Chip_UART_IntEnable(pUART, UART_IER_THREINT);
return ret;
}
/* Copy data from a receive ring buffer */
int Chip_UART_ReadRB(LPC_USART_T *pUART, RINGBUFF_T *pRB, void *data, int bytes)
{
(void) pUART;
return RingBuffer_PopMult(pRB, (uint8_t *) data, bytes);
}
/* UART receive/transmit interrupt handler for ring buffers */
void Chip_UART_IRQRBHandler(LPC_USART_T *pUART, RINGBUFF_T *pRXRB, RINGBUFF_T *pTXRB)
{
/* Handle transmit interrupt if enabled */
if (pUART->IER & UART_IER_THREINT) {
Chip_UART_TXIntHandlerRB(pUART, pTXRB);
/* Disable transmit interrupt if the ring buffer is empty */
if (RingBuffer_IsEmpty(pTXRB)) {
Chip_UART_IntDisable(pUART, UART_IER_THREINT);
}
}
/* Handle receive interrupt */
Chip_UART_RXIntHandlerRB(pUART, pRXRB);
/* Handle Autobaud interrupts */
Chip_UART_ABIntHandler(pUART);
}
/* Determines and sets best dividers to get a target baud rate */
uint32_t Chip_UART_SetBaudFDR(LPC_USART_T *pUART, uint32_t baudrate)
{
uint32_t uClk;
uint32_t actualRate = 0, d, m, bestd, bestm, tmp;
uint32_t current_error, best_error;
uint64_t best_divisor, divisor;
uint32_t recalcbaud;
/* Get Clock rate */
#if defined(CHIP_LPC175X_6X)
uClk = Chip_Clock_GetPeripheralClockRate(Chip_UART_GetClkIndex(pUART));
#else
uClk = Chip_Clock_GetPeripheralClockRate();
#endif
/* In the Uart IP block, baud rate is calculated using FDR and DLL-DLM registers
* The formula is :
* BaudRate= uClk * (mulFracDiv/(mulFracDiv+dividerAddFracDiv) / (16 * (DLL)
* It involves floating point calculations. That's the reason the formulae are adjusted with
* Multiply and divide method.*/
/* The value of mulFracDiv and dividerAddFracDiv should comply to the following expressions:
* 0 < mulFracDiv <= 15, 0 <= dividerAddFracDiv <= 15 */
best_error = 0xFFFFFFFF;/* Worst case */
bestd = 0;
bestm = 0;
best_divisor = 0;
for (m = 1; m <= 15; m++) {
for (d = 0; d < m; d++) {
/* The result here is a fixed point number. The integer portion is in the upper 32 bits.
* The fractional portion is in the lower 32 bits.
*/
divisor = ((uint64_t) uClk << 28) * m / (baudrate * (m + d));
/* The fractional portion is the error. */
current_error = divisor & 0xFFFFFFFF;
/* Snag the integer portion of the divisor. */
tmp = divisor >> 32;
/* If closer to the next divisor... */
if (current_error > ((uint32_t) 1 << 31)) {
/* Increment to the next divisor... */
tmp++;
/* Now the error is the distance to the next divisor... */
current_error = -current_error;
}
/* Can't use a divisor that's less than 1 or more than 65535. */
if ((tmp < 1) || (tmp > 65535)) {
/* Out of range */
continue;
}
/* Also, if fractional divider is enabled can't use a divisor that is less than 3. */
if ((d != 0) && (tmp < 3)) {
/* Out of range */
continue;
}
/* Do we have a new best? */
if (current_error < best_error) {
best_error = current_error;
best_divisor = tmp;
bestd = d;
bestm = m;
/* If error is 0, that's perfect. We're done. */
if (best_error == 0) {
break;
}
}
} /* for (d) */
/* If error is 0, that's perfect. We're done. */
if (best_error == 0) {
break;
}
} /* for (m) */
if (best_divisor == 0) {
/* can not find best match */
return 0;
}
recalcbaud = (uClk >> 4) * bestm / (best_divisor * (bestm + bestd));
/* reuse best_error to evaluate baud error */
if (baudrate > recalcbaud) {
best_error = baudrate - recalcbaud;
}
else {
best_error = recalcbaud - baudrate;
}
best_error = (best_error * 100) / baudrate;
/* Update UART registers */
Chip_UART_EnableDivisorAccess(pUART);
Chip_UART_SetDivisorLatches(pUART, UART_LOAD_DLL(best_divisor), UART_LOAD_DLM(best_divisor));
Chip_UART_DisableDivisorAccess(pUART);
/* Set best fractional divider */
pUART->FDR = (UART_FDR_MULVAL(bestm) | UART_FDR_DIVADDVAL(bestd));
/* Return actual baud rate */
actualRate = recalcbaud;
return actualRate;
}
/* UART interrupt service routine */
FlagStatus Chip_UART_GetABEOStatus(LPC_USART_T *pUART)
{
(void) pUART;
return ABsyncSts;
}
/* Start/Stop Auto Baudrate activity */
void Chip_UART_ABCmd(LPC_USART_T *pUART, uint32_t mode, bool autorestart, FunctionalState NewState)
{
uint32_t tmp = 0;
if (NewState == ENABLE) {
/* Clear DLL and DLM value */
pUART->LCR |= UART_LCR_DLAB_EN;
pUART->DLL = 0;
pUART->DLM = 0;
pUART->LCR &= ~UART_LCR_DLAB_EN;
/* FDR value must be reset to default value */
pUART->FDR = 0x10;
if (mode == UART_ACR_MODE1) {
tmp = UART_ACR_START | UART_ACR_MODE;
}
else {
tmp = UART_ACR_START;
}
if (autorestart == true) {
tmp |= UART_ACR_AUTO_RESTART;
}
pUART->ACR = tmp;
}
else {
pUART->ACR = 0;
}
}

View File

@@ -0,0 +1,72 @@
/*
* @brief LPC17xx/40xx WWDT chip driver
*
* @note
* Copyright(C) NXP Semiconductors, 2014
* All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* LPC products. This software is supplied "AS IS" without any warranties of
* any kind, and NXP Semiconductors and its licensor disclaim any and
* all warranties, express or implied, including all implied warranties of
* merchantability, fitness for a particular purpose and non-infringement of
* intellectual property rights. NXP Semiconductors assumes no responsibility
* or liability for the use of the software, conveys no license or rights under any
* patent, copyright, mask work right, or any other intellectual property rights in
* or to any products. NXP Semiconductors reserves the right to make changes
* in the software without notification. NXP Semiconductors also makes no
* representation or warranty that such application will be suitable for the
* specified use without further testing or modification.
*
* @par
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors' and its
* licensor's relevant copyrights in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
*/
#include "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initialize the Watchdog timer */
void Chip_WWDT_Init(LPC_WWDT_T *pWWDT)
{
/* Disable watchdog */
pWWDT->MOD = 0;
pWWDT->TC = 0xFF;
#if defined(WATCHDOG_WINDOW_SUPPORT)
pWWDT->WARNINT = 0xFFFF;
pWWDT->WINDOW = 0xFFFFFF;
#endif
}
/* Clear WWDT interrupt status flags */
void Chip_WWDT_ClearStatusFlag(LPC_WWDT_T *pWWDT, uint32_t status)
{
if (status & WWDT_WDMOD_WDTOF) {
pWWDT->MOD &= (~WWDT_WDMOD_WDTOF) & WWDT_WDMOD_BITMASK;
}
if (status & WWDT_WDMOD_WDINT) {
pWWDT->MOD |= WWDT_WDMOD_WDINT;
}
}