moving lpc17xx to use lpcopen
This commit is contained in:
256
hw/mcu/nxp/lpc_chip_175x_6x/src/adc_17xx_40xx.c
Normal file
256
hw/mcu/nxp/lpc_chip_175x_6x/src/adc_17xx_40xx.c
Normal 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;
|
||||
}
|
||||
1507
hw/mcu/nxp/lpc_chip_175x_6x/src/can_17xx_40xx.c
Normal file
1507
hw/mcu/nxp/lpc_chip_175x_6x/src/can_17xx_40xx.c
Normal file
File diff suppressed because it is too large
Load Diff
110
hw/mcu/nxp/lpc_chip_175x_6x/src/chip_17xx_40xx.c
Normal file
110
hw/mcu/nxp/lpc_chip_175x_6x/src/chip_17xx_40xx.c
Normal 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);
|
||||
|
||||
}
|
||||
516
hw/mcu/nxp/lpc_chip_175x_6x/src/clock_17xx_40xx.c
Normal file
516
hw/mcu/nxp/lpc_chip_175x_6x/src/clock_17xx_40xx.c
Normal 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
|
||||
64
hw/mcu/nxp/lpc_chip_175x_6x/src/cmp_17xx_40xx.c
Normal file
64
hw/mcu/nxp/lpc_chip_175x_6x/src/cmp_17xx_40xx.c
Normal 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) */
|
||||
110
hw/mcu/nxp/lpc_chip_175x_6x/src/crc_17xx_40xx.c
Normal file
110
hw/mcu/nxp/lpc_chip_175x_6x/src/crc_17xx_40xx.c
Normal 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) */
|
||||
84
hw/mcu/nxp/lpc_chip_175x_6x/src/dac_17xx_40xx.c
Normal file
84
hw/mcu/nxp/lpc_chip_175x_6x/src/dac_17xx_40xx.c
Normal 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;
|
||||
}
|
||||
}
|
||||
258
hw/mcu/nxp/lpc_chip_175x_6x/src/eeprom_17xx_40xx.c
Normal file
258
hw/mcu/nxp/lpc_chip_175x_6x/src/eeprom_17xx_40xx.c
Normal 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) */
|
||||
282
hw/mcu/nxp/lpc_chip_175x_6x/src/emc_17xx_40xx.c
Normal file
282
hw/mcu/nxp/lpc_chip_175x_6x/src/emc_17xx_40xx.c
Normal 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) */
|
||||
289
hw/mcu/nxp/lpc_chip_175x_6x/src/enet_17xx_40xx.c
Normal file
289
hw/mcu/nxp/lpc_chip_175x_6x/src/enet_17xx_40xx.c
Normal 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;
|
||||
}
|
||||
704
hw/mcu/nxp/lpc_chip_175x_6x/src/gpdma_17xx_40xx.c
Normal file
704
hw/mcu/nxp/lpc_chip_175x_6x/src/gpdma_17xx_40xx.c
Normal 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;
|
||||
}
|
||||
46
hw/mcu/nxp/lpc_chip_175x_6x/src/gpio_17xx_40xx.c
Normal file
46
hw/mcu/nxp/lpc_chip_175x_6x/src/gpio_17xx_40xx.c
Normal 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
|
||||
****************************************************************************/
|
||||
|
||||
46
hw/mcu/nxp/lpc_chip_175x_6x/src/gpioint_17xx_40xx.c
Normal file
46
hw/mcu/nxp/lpc_chip_175x_6x/src/gpioint_17xx_40xx.c
Normal 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
|
||||
****************************************************************************/
|
||||
|
||||
561
hw/mcu/nxp/lpc_chip_175x_6x/src/i2c_17xx_40xx.c
Normal file
561
hw/mcu/nxp/lpc_chip_175x_6x/src/i2c_17xx_40xx.c
Normal 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;
|
||||
}
|
||||
260
hw/mcu/nxp/lpc_chip_175x_6x/src/i2s_17xx_40xx.c
Normal file
260
hw/mcu/nxp/lpc_chip_175x_6x/src/i2s_17xx_40xx.c
Normal 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;
|
||||
}
|
||||
}
|
||||
175
hw/mcu/nxp/lpc_chip_175x_6x/src/iap.c
Normal file
175
hw/mcu/nxp/lpc_chip_175x_6x/src/iap.c
Normal 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];
|
||||
}
|
||||
83
hw/mcu/nxp/lpc_chip_175x_6x/src/iocon_17xx_40xx.c
Normal file
83
hw/mcu/nxp/lpc_chip_175x_6x/src/iocon_17xx_40xx.c
Normal 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);
|
||||
}
|
||||
}
|
||||
210
hw/mcu/nxp/lpc_chip_175x_6x/src/lcd_17xx_40xx.c
Normal file
210
hw/mcu/nxp/lpc_chip_175x_6x/src/lcd_17xx_40xx.c
Normal 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) */
|
||||
118
hw/mcu/nxp/lpc_chip_175x_6x/src/pmu_17xx_40xx.c
Normal file
118
hw/mcu/nxp/lpc_chip_175x_6x/src/pmu_17xx_40xx.c
Normal 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);
|
||||
}
|
||||
}
|
||||
167
hw/mcu/nxp/lpc_chip_175x_6x/src/ring_buffer.c
Normal file
167
hw/mcu/nxp/lpc_chip_175x_6x/src/ring_buffer.c
Normal 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;
|
||||
}
|
||||
100
hw/mcu/nxp/lpc_chip_175x_6x/src/ritimer_17xx_40xx.c
Normal file
100
hw/mcu/nxp/lpc_chip_175x_6x/src/ritimer_17xx_40xx.c
Normal 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) */
|
||||
221
hw/mcu/nxp/lpc_chip_175x_6x/src/rtc_17xx_40xx.c
Normal file
221
hw/mcu/nxp/lpc_chip_175x_6x/src/rtc_17xx_40xx.c
Normal 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*/
|
||||
247
hw/mcu/nxp/lpc_chip_175x_6x/src/sdc_17xx_40xx.c
Normal file
247
hw/mcu/nxp/lpc_chip_175x_6x/src/sdc_17xx_40xx.c
Normal 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) */
|
||||
1196
hw/mcu/nxp/lpc_chip_175x_6x/src/sdmmc_17xx_40xx.c
Normal file
1196
hw/mcu/nxp/lpc_chip_175x_6x/src/sdmmc_17xx_40xx.c
Normal file
File diff suppressed because it is too large
Load Diff
227
hw/mcu/nxp/lpc_chip_175x_6x/src/spi_17xx_40xx.c
Normal file
227
hw/mcu/nxp/lpc_chip_175x_6x/src/spi_17xx_40xx.c
Normal 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) */
|
||||
478
hw/mcu/nxp/lpc_chip_175x_6x/src/ssp_17xx_40xx.c
Normal file
478
hw/mcu/nxp/lpc_chip_175x_6x/src/ssp_17xx_40xx.c
Normal 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));
|
||||
}
|
||||
110
hw/mcu/nxp/lpc_chip_175x_6x/src/stopwatch_17xx_40xx.c
Normal file
110
hw/mcu/nxp/lpc_chip_175x_6x/src/stopwatch_17xx_40xx.c
Normal 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;
|
||||
}
|
||||
|
||||
70
hw/mcu/nxp/lpc_chip_175x_6x/src/sysctl_17xx_40xx.c
Normal file
70
hw/mcu/nxp/lpc_chip_175x_6x/src/sysctl_17xx_40xx.c
Normal 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)*/
|
||||
178
hw/mcu/nxp/lpc_chip_175x_6x/src/sysinit_17xx_40xx.c
Normal file
178
hw/mcu/nxp/lpc_chip_175x_6x/src/sysinit_17xx_40xx.c
Normal 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();
|
||||
}
|
||||
116
hw/mcu/nxp/lpc_chip_175x_6x/src/timer_17xx_40xx.c
Normal file
116
hw/mcu/nxp/lpc_chip_175x_6x/src/timer_17xx_40xx.c
Normal 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)));
|
||||
}
|
||||
533
hw/mcu/nxp/lpc_chip_175x_6x/src/uart_17xx_40xx.c
Normal file
533
hw/mcu/nxp/lpc_chip_175x_6x/src/uart_17xx_40xx.c
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
72
hw/mcu/nxp/lpc_chip_175x_6x/src/wwdt_17xx_40xx.c
Normal file
72
hw/mcu/nxp/lpc_chip_175x_6x/src/wwdt_17xx_40xx.c
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user