added lpc18 lpcopen

This commit is contained in:
hathach
2018-12-04 12:39:48 +07:00
parent 819a03c14d
commit d40663d403
115 changed files with 43175 additions and 0 deletions

View File

@@ -0,0 +1,263 @@
/*
* @brief LPC18xx/43xx A/D conversion driver
*
* @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 "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)
{
return 11;
}
/* Returns clock index for the peripheral block */
STATIC CHIP_CCU_CLK_T Chip_ADC_GetClockIndex(LPC_ADC_T *pADC)
{
CHIP_CCU_CLK_T clkADC;
if (pADC == LPC_ADC1) {
clkADC = CLK_APB3_ADC1;
}
else {
clkADC = CLK_APB3_ADC0;
}
return clkADC;
}
/* 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);
*/
adcBlockFreq = Chip_Clock_GetRate(Chip_ADC_GetClockIndex(pADC));
if (burstMode) {
fullAdcRate = adcRate * clks;
}
else {
fullAdcRate = adcRate * getFullConvClk();
}
/* 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_EnableOpts(Chip_ADC_GetClockIndex(pADC), true, true, 1);
pADC->INTEN = 0; /* Disable all interrupts */
cr |= ADC_CR_PDN;
ADCSetup->adcRate = ADC_MAX_SAMPLE_RATE;
ADCSetup->bitsAccuracy = ADC_10BITS;
clk = 11;
ADCSetup->burstMode = false;
div = getClkDiv(pADC, false, ADCSetup->adcRate, clk);
cr |= ADC_CR_CLKDIV(div);
cr |= ADC_CR_BITACC(ADCSetup->bitsAccuracy);
pADC->CR = cr;
}
/* Shutdown ADC */
void Chip_ADC_DeInit(LPC_ADC_T *pADC)
{
pADC->INTEN = 0x00000100;
pADC->CR = 0;
Chip_Clock_Disable(Chip_ADC_GetClockIndex(pADC));
}
/* 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);
cr |= ADC_CR_BITACC(ADCSetup->bitsAccuracy);
pADC->CR = cr;
}
/* Set the ADC accuracy bits */
void Chip_ADC_SetResolution(LPC_ADC_T *pADC, ADC_CLOCK_SETUP_T *ADCSetup, ADC_RESOLUTION_T resolution)
{
ADCSetup->bitsAccuracy = resolution;
Chip_ADC_SetSampleRate(pADC, ADCSetup, ADCSetup->adcRate);
}
/* 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;
}

View File

@@ -0,0 +1,180 @@
/*
* @brief LPC18xx/43xx AES Engine driver
*
* @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 "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
#define BOOTROM_BASE 0x10400100
#define AES_API_TABLE_OFFSET 0x2
typedef void (*V_FP_V)(void);
typedef uint32_t (*U32_FP_V)(void);
static unsigned long *BOOTROM_API_TABLE;
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
static uint32_t (*aes_SetMode)(CHIP_AES_OP_MODE_T AesMode);
static void (*aes_LoadKey1)(void);
static void (*aes_LoadKey2)(void);
static void (*aes_LoadKeyRNG)(void);
static void (*aes_LoadKeySW)(uint8_t *pKey);
static void (*aes_LoadIV_SW)(uint8_t *pVector);
static void (*aes_LoadIV_IC)(void);
static uint32_t (*aes_Operate)(uint8_t *pDatOut, uint8_t *pDatIn, uint32_t size);
static uint32_t (*aes_ProgramKey1)(uint8_t *pKey);
static uint32_t (*aes_ProgramKey2)(uint8_t *pKey);
static uint32_t (*aes_Config_DMA) (uint32_t channel_id);
static uint32_t (*aes_Operate_DMA)(uint32_t channel_id, uint8_t *dataOutAddr, uint8_t *dataInAddr, uint32_t size);
static uint32_t (*aes_Get_Status_DMA) (uint32_t channel_id);
/*****************************************************************************
* Public functions
****************************************************************************/
/* CHIP AES Initialisation function */
void Chip_AES_Init(void)
{
uint32_t (*ROM_aes_Init)(void);
BOOTROM_API_TABLE = *((unsigned long * *) BOOTROM_BASE + AES_API_TABLE_OFFSET);
ROM_aes_Init = (uint32_t (*)(void))BOOTROM_API_TABLE[0];
aes_SetMode = (uint32_t (*)(CHIP_AES_OP_MODE_T AesMode))BOOTROM_API_TABLE[1];
aes_LoadKey1 = (void (*)(void))BOOTROM_API_TABLE[2];
aes_LoadKey2 = (void (*)(void))BOOTROM_API_TABLE[3];
aes_LoadKeyRNG = (void (*)(void))BOOTROM_API_TABLE[4];
aes_LoadKeySW = (void (*)(uint8_t *pKey))BOOTROM_API_TABLE[5];
aes_LoadIV_SW = (void (*)(uint8_t *pVector))BOOTROM_API_TABLE[6];
aes_LoadIV_IC = (void (*)(void))BOOTROM_API_TABLE[7];
aes_Operate = (uint32_t (*)(uint8_t *pDatOut, uint8_t *pDatIn, uint32_t Size))BOOTROM_API_TABLE[8];
aes_ProgramKey1 = (uint32_t (*)(uint8_t *pKey))BOOTROM_API_TABLE[9];
aes_ProgramKey2 = (uint32_t (*)(uint8_t *pKey))BOOTROM_API_TABLE[10];
aes_Config_DMA = (uint32_t (*)(uint32_t channel_id))BOOTROM_API_TABLE[11];
aes_Operate_DMA = (uint32_t (*)(uint32_t channel_id, uint8_t *dataOutAddr, uint8_t *dataInAddr, uint32_t size))BOOTROM_API_TABLE[12];
aes_Get_Status_DMA = (uint32_t (*) (uint32_t channel_id))BOOTROM_API_TABLE[13];
ROM_aes_Init();
}
/* Set Operation mode in AES Engine */
uint32_t Chip_AES_SetMode(CHIP_AES_OP_MODE_T AesMode)
{
return aes_SetMode(AesMode);
}
/* Load 128-bit user key in AES Engine */
void Chip_AES_LoadKey(uint32_t keyNum)
{
if (keyNum) {
aes_LoadKey2();
}
else {
aes_LoadKey1();
}
}
/* Load randomly generated key in AES engine */
void Chip_AES_LoadKeyRNG(void)
{
aes_LoadKeyRNG();
}
/* Load 128-bit AES software defined user key */
void Chip_AES_LoadKeySW(uint8_t *pKey)
{
aes_LoadKeySW(pKey);
}
/* Load 128-bit AES initialization vector */
void Chip_AES_LoadIV_SW(uint8_t *pVector)
{
aes_LoadIV_SW(pVector);
}
/* Load IC specific 128-bit AES initialization vector */
void Chip_AES_LoadIV_IC(void)
{
aes_LoadIV_IC();
}
/* Operate AES Engine */
uint32_t Chip_AES_Operate(uint8_t *pDatOut, uint8_t *pDatIn, uint32_t Size)
{
return aes_Operate(pDatOut, pDatIn, Size);
}
/* Program 128-bit AES Key in OTP */
uint32_t Chip_AES_ProgramKey(uint32_t KeyNum, uint8_t *pKey)
{
uint32_t status;
if (KeyNum) {
status = aes_ProgramKey2(pKey);
}
else {
status = aes_ProgramKey1(pKey);
}
return status;
}
/* Configure DMA channel to process AES block */
uint32_t Chip_AES_Config_DMA(uint32_t channel_id)
{
return aes_Config_DMA(channel_id);
}
/* Enables DMA channel and Operates AES Engine */
uint32_t Chip_AES_OperateDMA(uint32_t channel_id, uint8_t *dataOutAddr, uint8_t *dataInAddr, uint32_t size)
{
return aes_Operate_DMA(channel_id,dataOutAddr,dataInAddr,size);
}
/* Read status of DMA channels that process an AES data block. */
uint32_t Chip_AES_GetStatusDMA(uint32_t channel_id)
{
return aes_Get_Status_DMA(channel_id);
}

View File

@@ -0,0 +1,69 @@
/*
* @brief LPC18xx/43xx Alarm Timer driver
*
* @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 "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initialize Alarm Timer */
void Chip_ATIMER_Init(LPC_ATIMER_T *pATIMER, uint32_t PresetValue)
{
Chip_ATIMER_UpdatePresetValue(pATIMER, PresetValue);
Chip_ATIMER_ClearIntStatus(pATIMER);
}
/* Close ATIMER device */
void Chip_ATIMER_DeInit(LPC_ATIMER_T *pATIMER)
{
Chip_ATIMER_ClearIntStatus(pATIMER);
Chip_ATIMER_IntDisable(pATIMER);
}

View File

@@ -0,0 +1,317 @@
/*
* @brief LPC18xx/43xx CCAN driver
*
* @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 "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/* Configure the bit timing for CCAN bus */
STATIC void configTimming(LPC_CCAN_T *pCCAN,
uint32_t ClkDiv,
uint32_t BaudRatePrescaler,
uint8_t SynJumpWidth,
uint8_t Tseg1,
uint8_t Tseg2)
{
/* Reset software */
if (!(pCCAN->CNTL & CCAN_CTRL_INIT)) {
pCCAN->CNTL |= CCAN_CTRL_INIT;
}
/*Set bus timing */
pCCAN->CLKDIV = ClkDiv; /* Divider for CAN VPB3 clock */
pCCAN->CNTL |= CCAN_CTRL_CCE; /* Start configuring bit timing */
pCCAN->BT = (BaudRatePrescaler & 0x3F) | (SynJumpWidth & 0x03) << 6 | (Tseg1 & 0x0F) << 8 | (Tseg2 & 0x07) << 12;
pCCAN->BRPE = BaudRatePrescaler >> 6; /* Set Baud Rate Prescaler MSBs */
pCCAN->CNTL &= ~CCAN_CTRL_CCE; /* Stop configuring bit timing */
/* Finish software initialization */
pCCAN->CNTL &= ~CCAN_CTRL_INIT;
while ( pCCAN->CNTL & CCAN_CTRL_INIT ) {}
}
/* Return 1->32; 0 if not find free msg */
STATIC uint8_t getFreeMsgObject(LPC_CCAN_T *pCCAN)
{
uint32_t msg_valid;
uint8_t i;
msg_valid = Chip_CCAN_GetValidMsg(pCCAN);
for (i = 0; i < CCAN_MSG_MAX_NUM; i++) {
if (!((msg_valid >> i) & 1UL)) {
return i + 1;
}
}
return 0; // No free object
}
STATIC void freeMsgObject(LPC_CCAN_T *pCCAN, CCAN_MSG_IF_T IFSel, uint8_t msgNum)
{
Chip_CCAN_SetValidMsg(pCCAN, IFSel, msgNum, false);
}
/* Returns clock index for the peripheral block */
STATIC CHIP_CCU_CLK_T Chip_CCAN_GetClockIndex(LPC_CCAN_T *pCCAN)
{
CHIP_CCU_CLK_T clkCCAN;
if (pCCAN == LPC_C_CAN1) {
clkCCAN = CLK_APB1_CAN1;
}
else {
clkCCAN = CLK_APB3_CAN0;
}
return clkCCAN;
}
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initialize the CCAN peripheral, free all message object in RAM */
void Chip_CCAN_Init(LPC_CCAN_T *pCCAN)
{
uint8_t i;
Chip_Clock_EnableOpts(Chip_CCAN_GetClockIndex(pCCAN), true, false, 1);
for (i = 1; i <= CCAN_MSG_MAX_NUM; i++) {
freeMsgObject(pCCAN, CCAN_MSG_IF1, i);
}
Chip_CCAN_ClearStatus(pCCAN, (CCAN_STAT_RXOK | CCAN_STAT_TXOK));
}
/* De-initialize the CCAN peripheral */
void Chip_CCAN_DeInit(LPC_CCAN_T *pCCAN)
{
Chip_Clock_Disable(Chip_CCAN_GetClockIndex(pCCAN));
}
/* Select bit rate for CCAN bus */
Status Chip_CCAN_SetBitRate(LPC_CCAN_T *pCCAN, uint32_t bitRate)
{
uint32_t pClk, div, quanta, segs, seg1, seg2, clk_per_bit, can_sjw;
pClk = Chip_Clock_GetRate(Chip_CCAN_GetClockIndex(pCCAN));
clk_per_bit = pClk / bitRate;
for (div = 0; div <= 15; div++) {
for (quanta = 1; quanta <= 32; quanta++) {
for (segs = 3; segs <= 17; segs++) {
if (clk_per_bit == (segs * quanta * (div + 1))) {
segs -= 3;
seg1 = segs / 2;
seg2 = segs - seg1;
can_sjw = seg1 > 3 ? 3 : seg1;
configTimming(pCCAN, div, quanta - 1, can_sjw, seg1, seg2);
return SUCCESS;
}
}
}
}
return ERROR;
}
/* Clear the status of CCAN bus */
void Chip_CCAN_ClearStatus(LPC_CCAN_T *pCCAN, uint32_t val)
{
uint32_t tmp = Chip_CCAN_GetStatus(pCCAN);
Chip_CCAN_SetStatus(pCCAN, tmp & (~val));
}
/* Set a message into the message object in message RAM */
void Chip_CCAN_SetMsgObject(LPC_CCAN_T *pCCAN,
CCAN_MSG_IF_T IFSel,
CCAN_TRANSFER_DIR_T dir,
bool remoteFrame,
uint8_t msgNum,
const CCAN_MSG_OBJ_T *pMsgObj)
{
uint16_t *pData;
uint32_t msgCtrl = 0;
if (pMsgObj == NULL) {
return;
}
pData = (uint16_t *) (pMsgObj->data);
msgCtrl |= CCAN_IF_MCTRL_UMSK | CCAN_IF_MCTRL_RMTEN(remoteFrame) | CCAN_IF_MCTRL_EOB |
(pMsgObj->dlc & CCAN_IF_MCTRL_DLC_MSK);
if (dir == CCAN_TX_DIR) {
msgCtrl |= CCAN_IF_MCTRL_TXIE;
if (!remoteFrame) {
msgCtrl |= CCAN_IF_MCTRL_TXRQ;
}
}
else {
msgCtrl |= CCAN_IF_MCTRL_RXIE;
}
pCCAN->IF[IFSel].MCTRL = msgCtrl;
pCCAN->IF[IFSel].DA1 = *pData++; /* Lower two bytes of message pointer */
pCCAN->IF[IFSel].DA2 = *pData++; /* Upper two bytes of message pointer */
pCCAN->IF[IFSel].DB1 = *pData++; /* Lower two bytes of message pointer */
pCCAN->IF[IFSel].DB2 = *pData; /* Upper two bytes of message pointer */
/* Configure arbitration */
if (!(pMsgObj->id & (0x1 << 30))) { /* bit 30 is 0, standard frame */
/* Mxtd: 0, Mdir: 1, Mask is 0x7FF */
pCCAN->IF[IFSel].MSK2 = CCAN_IF_MASK2_MDIR(dir) | (CCAN_MSG_ID_STD_MASK << 2);
pCCAN->IF[IFSel].MSK1 = 0x0000;
/* MsgVal: 1, Mtd: 0, Dir: 1, ID = 0x200 */
pCCAN->IF[IFSel].ARB2 = CCAN_IF_ARB2_MSGVAL | CCAN_IF_ARB2_DIR(dir) | (pMsgObj->id << 2);
pCCAN->IF[IFSel].ARB1 = 0x0000;
}
else { /* Extended frame */
/* Mxtd: 1, Mdir: 1, Mask is 0x1FFFFFFF */
pCCAN->IF[IFSel].MSK2 = CCAN_IF_MASK2_MXTD | CCAN_IF_MASK2_MDIR(dir) | (CCAN_MSG_ID_EXT_MASK >> 16);
pCCAN->IF[IFSel].MSK1 = CCAN_MSG_ID_EXT_MASK & 0x0000FFFF;
/* MsgVal: 1, Mtd: 1, Dir: 1, ID = 0x200000 */
pCCAN->IF[IFSel].ARB2 = CCAN_IF_ARB2_MSGVAL | CCAN_IF_ARB2_XTD | CCAN_IF_ARB2_DIR(dir) | (pMsgObj->id >> 16);
pCCAN->IF[IFSel].ARB1 = pMsgObj->id & 0x0000FFFF;
}
Chip_CCAN_TransferMsgObject(pCCAN, IFSel, CCAN_IF_CMDMSK_WR | CCAN_IF_CMDMSK_TRANSFER_ALL, msgNum);
}
/* Get a message object in message RAM into the message buffer */
void Chip_CCAN_GetMsgObject(LPC_CCAN_T *pCCAN, CCAN_MSG_IF_T IFSel, uint8_t msgNum, CCAN_MSG_OBJ_T *pMsgObj)
{
uint32_t *pData;
if (!pMsgObj) {
return;
}
pData = (uint32_t *) pMsgObj->data;
Chip_CCAN_TransferMsgObject(pCCAN,
IFSel,
CCAN_IF_CMDMSK_RD | CCAN_IF_CMDMSK_TRANSFER_ALL | CCAN_IF_CMDMSK_R_CLRINTPND,
msgNum);
if (pCCAN->IF[IFSel].MCTRL & CCAN_IF_MCTRL_NEWD) {
pMsgObj->id = (pCCAN->IF[IFSel].ARB1) | (pCCAN->IF[IFSel].ARB2 << 16);
pMsgObj->dlc = pCCAN->IF[IFSel].MCTRL & CCAN_IF_MCTRL_DLC_MSK;
*pData++ = (pCCAN->IF[IFSel].DA2 << 16) | pCCAN->IF[IFSel].DA1;
*pData = (pCCAN->IF[IFSel].DB2 << 16) | pCCAN->IF[IFSel].DB1;
if (pMsgObj->id & (0x1 << 30)) {
pMsgObj->id &= CCAN_MSG_ID_EXT_MASK;
}
else {
pMsgObj->id >>= 18;
pMsgObj->id &= CCAN_MSG_ID_STD_MASK;
}
}
}
/* Data transfer between IF registers and Message RAM */
void Chip_CCAN_TransferMsgObject(LPC_CCAN_T *pCCAN,
CCAN_MSG_IF_T IFSel,
uint32_t mask,
uint32_t msgNum) {
msgNum &= 0x3F;
pCCAN->IF[IFSel].CMDMSK = mask;
pCCAN->IF[IFSel].CMDREQ = msgNum;
while (pCCAN->IF[IFSel].CMDREQ & CCAN_IF_CMDREQ_BUSY ) {}
}
/* Enable/Disable the message object to valid */
void Chip_CCAN_SetValidMsg(LPC_CCAN_T *pCCAN, CCAN_MSG_IF_T IFSel, uint8_t msgNum, bool valid)
{
uint32_t temp;
temp = pCCAN->IF[IFSel].ARB2;
if (!valid) {
pCCAN->IF[IFSel].ARB2 = (temp & (~CCAN_IF_ARB2_MSGVAL));
}
else {
pCCAN->IF[IFSel].ARB2 = (temp | (CCAN_IF_ARB2_MSGVAL));
}
Chip_CCAN_TransferMsgObject(pCCAN, IFSel, CCAN_IF_CMDMSK_WR | CCAN_IF_CMDMSK_ARB, msgNum);
}
/* Send a message */
void Chip_CCAN_Send(LPC_CCAN_T *pCCAN, CCAN_MSG_IF_T IFSel, bool remoteFrame, CCAN_MSG_OBJ_T *pMsgObj)
{
uint8_t msgNum = getFreeMsgObject(pCCAN);
if (!msgNum) {
return;
}
Chip_CCAN_SetMsgObject(pCCAN, IFSel, CCAN_TX_DIR, remoteFrame, msgNum, pMsgObj);
while (Chip_CCAN_GetTxRQST(pCCAN) >> (msgNum - 1)) { // blocking , wait for sending completed
}
if (!remoteFrame) {
freeMsgObject(pCCAN, IFSel, msgNum);
}
}
/* Register a message ID for receiving */
void Chip_CCAN_AddReceiveID(LPC_CCAN_T *pCCAN, CCAN_MSG_IF_T IFSel, uint32_t id)
{
CCAN_MSG_OBJ_T temp;
uint8_t msgNum = getFreeMsgObject(pCCAN);
if (!msgNum) {
return;
}
temp.id = id;
Chip_CCAN_SetMsgObject(pCCAN, IFSel, CCAN_RX_DIR, false, msgNum, &temp);
}
/* Remove a registered message ID from receiving */
void Chip_CCAN_DeleteReceiveID(LPC_CCAN_T *pCCAN, CCAN_MSG_IF_T IFSel, uint32_t id)
{
uint8_t i;
CCAN_MSG_OBJ_T temp;
for (i = 1; i <= CCAN_MSG_MAX_NUM; i++) {
Chip_CCAN_GetMsgObject(pCCAN, IFSel, i, &temp);
if (temp.id == id) {
freeMsgObject(pCCAN, IFSel, i);
}
}
}

View File

@@ -0,0 +1,123 @@
/*
* @brief LPC18xx/LPC43xx chip driver source
*
* @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 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"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/* USB PLL pre-initialized setup values for 480MHz output rate */
static const CGU_USBAUDIO_PLL_SETUP_T usbPLLSetup = {
0x0000601D, /* Default control with main osc input, PLL disabled */
0x06167FFA, /* M-divider value for 480MHz output from 12MHz input */
0x00000000, /* N-divider value */
0x00000000, /* Not applicable for USB PLL */
480000000 /* PLL output frequency */
};
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/* System Clock Frequency (Core Clock) */
uint32_t SystemCoreClock;
/*****************************************************************************
* Private functions
****************************************************************************/
static void Chip_USB_PllSetup(void)
{
/* No need to setup anything if PLL is already setup for the frequency */
if (Chip_Clock_GetClockInputHz(CLKIN_USBPLL) == usbPLLSetup.freq)
return ;
/* Setup default USB PLL state for a 480MHz output and attach */
Chip_Clock_SetupPLL(CLKIN_CRYSTAL, CGU_USB_PLL, &usbPLLSetup);
/* enable USB PLL */
Chip_Clock_EnablePLL(CGU_USB_PLL);
/* Wait for PLL lock */
while (!(Chip_Clock_GetPLLStatus(CGU_USB_PLL) & CGU_PLL_LOCKED)) {}
}
/*****************************************************************************
* Public functions
****************************************************************************/
void Chip_USB0_Init(void)
{
/* Set up USB PLL */
Chip_USB_PllSetup();
/* Setup USB0 base clock as clock out from USB PLL */
Chip_Clock_SetBaseClock( CLK_BASE_USB0, CLKIN_USBPLL, true, true);
/* enable USB main clock */
Chip_Clock_EnableBaseClock(CLK_BASE_USB0);
Chip_Clock_EnableOpts(CLK_MX_USB0, true, true, 1);
/* enable USB0 phy */
Chip_CREG_EnableUSB0Phy();
}
void Chip_USB1_Init(void)
{
/* Setup and enable the PLL */
Chip_USB_PllSetup();
/* USB1 needs a 60MHz clock. To get it, a divider of 4 and then 2 are
chained to make a divide by 8 function. Connect the output of
divider D to the USB1 base clock. */
Chip_Clock_SetDivider(CLK_IDIV_A, CLKIN_USBPLL, 4);
Chip_Clock_SetDivider(CLK_IDIV_D, CLKIN_IDIVA, 2);
Chip_Clock_SetBaseClock(CLK_BASE_USB1, CLKIN_IDIVD, true, true);
/* enable USB main clock */
Chip_Clock_EnableBaseClock(CLK_BASE_USB1);
Chip_Clock_EnableOpts(CLK_MX_USB1, true, true, 1);
/* enable USB1_DP and USB1_DN on chip FS phy.*/
LPC_SCU->SFSUSB = 0x12;
}
/* 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_GetRate(CLK_MX_MXCORE);
}

View File

@@ -0,0 +1,832 @@
/*
* @brief LPC18xx/43xx clock driver
*
* @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 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"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/* Maps a peripheral clock to it's base clock */
typedef struct {
CHIP_CCU_CLK_T clkstart;
CHIP_CCU_CLK_T clkend;
CHIP_CGU_BASE_CLK_T clkbase;
} CLK_PERIPH_TO_BASE_T;
static const CLK_PERIPH_TO_BASE_T periph_to_base[] = {
{CLK_APB3_BUS, CLK_APB3_CAN0, CLK_BASE_APB3},
{CLK_APB1_BUS, CLK_APB1_CAN1, CLK_BASE_APB1},
{CLK_SPIFI, CLK_SPIFI, CLK_BASE_SPIFI},
{CLK_MX_BUS, CLK_MX_QEI, CLK_BASE_MX},
#if defined(CHIP_LPC43XX)
{CLK_PERIPH_BUS, CLK_PERIPH_SGPIO, CLK_BASE_PERIPH},
#endif
{CLK_USB0, CLK_USB0, CLK_BASE_USB0},
{CLK_USB1, CLK_USB1, CLK_BASE_USB1},
#if defined(CHIP_LPC43XX)
{CLK_SPI, CLK_SPI, CLK_BASE_SPI},
{CLK_ADCHS, CLK_ADCHS, CLK_BASE_ADCHS},
#endif
{CLK_APLL, CLK_APLL, CLK_BASE_APLL},
{CLK_APB2_UART3, CLK_APB2_UART3, CLK_BASE_UART3},
{CLK_APB2_UART2, CLK_APB2_UART2, CLK_BASE_UART2},
{CLK_APB0_UART1, CLK_APB0_UART1, CLK_BASE_UART1},
{CLK_APB0_UART0, CLK_APB0_UART0, CLK_BASE_UART0},
{CLK_APB2_SSP1, CLK_APB2_SSP1, CLK_BASE_SSP1},
{CLK_APB0_SSP0, CLK_APB0_SSP0, CLK_BASE_SSP0},
{CLK_APB2_SDIO, CLK_APB2_SDIO, CLK_BASE_SDIO},
{CLK_CCU2_LAST, CLK_CCU2_LAST, CLK_BASE_NONE}
};
#define CRYSTAL_32K_FREQ_IN (32 * 1024)
/* Variables to use audio and usb pll frequency */
static uint32_t audio_usb_pll_freq[CGU_AUDIO_PLL+1];
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
__STATIC_INLINE uint32_t ABS(int val)
{
if (val < 0)
return -val;
return val;
}
static void pll_calc_divs(uint32_t freq, PLL_PARAM_T *ppll)
{
uint32_t prev = freq;
int n, m, p;
/* When direct mode is set FBSEL should be a don't care */
if (ppll->ctrl & (1 << 7)) {
ppll->ctrl &= ~(1 << 6);
}
for (n = 1; n <= 4; n++) {
for (p = 0; p < 4; p ++) {
for (m = 1; m <= 256; m++) {
uint32_t fcco, fout;
if (ppll->ctrl & (1 << 6)) {
fcco = ((m << (p + 1)) * ppll->fin) / n;
} else {
fcco = (m * ppll->fin) / n;
}
if (fcco < PLL_MIN_CCO_FREQ) continue;
if (fcco > PLL_MAX_CCO_FREQ) break;
if (ppll->ctrl & (1 << 7)) {
fout = fcco;
} else {
fout = fcco >> (p + 1);
}
if (ABS(freq - fout) < prev) {
ppll->nsel = n;
ppll->psel = p + 1;
ppll->msel = m;
ppll->fout = fout;
ppll->fcco = fcco;
prev = ABS(freq - fout);
}
}
}
}
}
static void pll_get_frac(uint32_t freq, PLL_PARAM_T *ppll)
{
int diff[3];
PLL_PARAM_T pll[3] = {{0},{0},{0}};
/* Try direct mode */
pll[0].ctrl |= (1 << 7);
pll[0].fin = ppll->fin;
pll[0].srcin = ppll->srcin;
pll_calc_divs(freq, &pll[0]);
if (pll[0].fout == freq) {
*ppll = pll[0];
return ;
}
diff[0] = ABS(freq - pll[0].fout);
/* Try non-Integer mode */
pll[2].ctrl &= ~(1 << 6); // need to set FBSEL to 0
pll[2].fin = ppll->fin;
pll[2].srcin = ppll->srcin;
pll_calc_divs(freq, &pll[2]);
if (pll[2].fout == freq) {
*ppll = pll[2];
return ;
}
diff[2] = ABS(freq - pll[2].fout);
if (freq <= 110000000) {
/* Try integer mode */
pll[1].ctrl = (1 << 6);
pll[1].fin = ppll->fin;
pll_calc_divs(freq, &pll[1]);
if (pll[1].fout == freq) {
*ppll = pll[1];
return ;
}
}
diff[1] = ABS(freq - pll[1].fout);
/* Find the min of 3 and return */
if (diff[0] <= diff[1]) {
if (diff[0] <= diff[2]) {
*ppll = pll[0];
} else {
*ppll = pll[2];
}
} else {
if (diff[1] <= diff[2]) {
*ppll = pll[1];
} else {
*ppll = pll[2];
}
}
}
/* Test PLL input values for a specific frequency range */
static uint32_t Chip_Clock_TestMainPLLMultiplier(uint32_t InputHz, uint32_t TestMult, uint32_t MinHz, uint32_t MaxHz)
{
uint32_t TestHz = TestMult * InputHz;
if ((TestHz < MinHz) || (TestHz > MAX_CLOCK_FREQ) || (TestHz > MaxHz)) {
TestHz = 0;
}
return TestHz;
}
/* Returns clock rate out of a divider */
static uint32_t Chip_Clock_GetDivRate(CHIP_CGU_CLKIN_T clock, CHIP_CGU_IDIV_T divider)
{
CHIP_CGU_CLKIN_T input;
uint32_t div;
input = Chip_Clock_GetDividerSource(divider);
div = Chip_Clock_GetDividerDivisor(divider);
return Chip_Clock_GetClockInputHz(input) / (div + 1);
}
/* Finds the base clock for the peripheral clock */
static CHIP_CGU_BASE_CLK_T Chip_Clock_FindBaseClock(CHIP_CCU_CLK_T clk)
{
CHIP_CGU_BASE_CLK_T baseclk = CLK_BASE_NONE;
int i = 0;
while ((baseclk == CLK_BASE_NONE) && (periph_to_base[i].clkbase != baseclk)) {
if ((clk >= periph_to_base[i].clkstart) && (clk <= periph_to_base[i].clkend)) {
baseclk = periph_to_base[i].clkbase;
}
else {
i++;
}
}
return baseclk;
}
/*****************************************************************************
* Public functions
****************************************************************************/
/* Enables the crystal oscillator */
void Chip_Clock_EnableCrystal(void)
{
volatile uint32_t delay = 1000;
uint32_t OldCrystalConfig = LPC_CGU->XTAL_OSC_CTRL;
/* Clear bypass mode */
OldCrystalConfig &= (~2);
if (OldCrystalConfig != LPC_CGU->XTAL_OSC_CTRL) {
LPC_CGU->XTAL_OSC_CTRL = OldCrystalConfig;
}
/* Enable crystal oscillator */
OldCrystalConfig &= (~1);
if (OscRateIn >= 20000000) {
OldCrystalConfig |= 4; /* Set high frequency mode */
}
LPC_CGU->XTAL_OSC_CTRL = OldCrystalConfig;
/* Delay for 250uSec */
while(delay--) {}
}
/* Calculate the Main PLL div values */
int Chip_Clock_CalcMainPLLValue(uint32_t freq, PLL_PARAM_T *ppll)
{
ppll->fin = Chip_Clock_GetClockInputHz(ppll->srcin);
/* Do sanity check on frequency */
if (freq > MAX_CLOCK_FREQ || freq < (PLL_MIN_CCO_FREQ / 16) || !ppll->fin) {
return -1;
}
ppll->ctrl = 1 << 7; /* Enable direct mode [If possible] */
ppll->nsel = 0;
ppll->psel = 0;
ppll->msel = freq / ppll->fin;
if (freq < PLL_MIN_CCO_FREQ || ppll->msel * ppll->fin != freq) {
pll_get_frac(freq, ppll);
if (!ppll->nsel) {
return -1;
}
ppll->nsel --;
}
if (ppll->msel == 0) {
return - 1;
}
if (ppll->psel) {
ppll->psel --;
}
ppll->msel --;
return 0;
}
/* Disables the crystal oscillator */
void Chip_Clock_DisableCrystal(void)
{
/* Disable crystal oscillator */
LPC_CGU->XTAL_OSC_CTRL |= 1;
}
/* Configures the main PLL */
uint32_t Chip_Clock_SetupMainPLLHz(CHIP_CGU_CLKIN_T Input, uint32_t MinHz, uint32_t DesiredHz, uint32_t MaxHz)
{
uint32_t freqin = Chip_Clock_GetClockInputHz(Input);
uint32_t Mult, LastMult, MultEnd;
uint32_t freqout, freqout2;
if (DesiredHz != 0xFFFFFFFF) {
/* Test DesiredHz rounded down */
Mult = DesiredHz / freqin;
freqout = Chip_Clock_TestMainPLLMultiplier(freqin, Mult, MinHz, MaxHz);
/* Test DesiredHz rounded up */
Mult++;
freqout2 = Chip_Clock_TestMainPLLMultiplier(freqin, Mult, MinHz, MaxHz);
if (freqout && !freqout2) { /* rounding up is no good? set first multiplier */
Mult--;
return Chip_Clock_SetupMainPLLMult(Input, Mult);
}
if (!freqout && freqout2) { /* didn't work until rounded up? set 2nd multiplier */
return Chip_Clock_SetupMainPLLMult(Input, Mult);
}
if (freqout && freqout2) { /* either multiplier okay? choose closer one */
if ((DesiredHz - freqout) > (freqout2 - DesiredHz)) {
Mult--;
return Chip_Clock_SetupMainPLLMult(Input, Mult);
}
else {
return Chip_Clock_SetupMainPLLMult(Input, Mult);
}
}
}
/* Neither multiplier okay? Try to start at MinHz and increment.
This should find the highest multiplier that is still good */
Mult = MinHz / freqin;
MultEnd = MaxHz / freqin;
LastMult = 0;
while (1) {
freqout = Chip_Clock_TestMainPLLMultiplier(freqin, Mult, MinHz, MaxHz);
if (freqout) {
LastMult = Mult;
}
if (Mult >= MultEnd) {
break;
}
Mult++;
}
if (LastMult) {
return Chip_Clock_SetupMainPLLMult(Input, LastMult);
}
return 0;
}
/* Directly set the PLL multipler */
uint32_t Chip_Clock_SetupMainPLLMult(CHIP_CGU_CLKIN_T Input, uint32_t mult)
{
volatile uint32_t delay = 250;
uint32_t freq = Chip_Clock_GetClockInputHz(Input);
uint32_t msel = 0, nsel = 0, psel = 0, pval = 1;
uint32_t PLLReg = LPC_CGU->PLL1_CTRL;
freq *= mult;
msel = mult - 1;
PLLReg &= ~(0x1F << 24);/* clear input source bits */
PLLReg |= Input << 24; /* set input source bits to parameter */
/* Clear other PLL input bits */
PLLReg &= ~((1 << 6) | /* FBSEL */
(1 << 1) | /* BYPASS */
(1 << 7) | /* DIRECT */
(0x03 << 8) | (0xFF << 16) | (0x03 << 12)); /* PSEL, MSEL, NSEL- divider ratios */
PLLReg |= (1 << 11); /* AUTOBLOCK */
if (freq < 156000000) {
/* psel is encoded such that 0=1, 1=2, 2=4, 3=8 */
while ((2 * (pval) * freq) < 156000000) {
psel++;
pval *= 2;
}
PLLReg |= (msel << 16) | (nsel << 12) | (psel << 8) | (1 << 6); /* dividers + FBSEL */
}
else if (freq < 320000000) {
PLLReg |= (msel << 16) | (nsel << 12) | (psel << 8) | (1 << 7) | (1 << 6); /* dividers + DIRECT + FBSEL */
}
else {
Chip_Clock_DisableMainPLL();
return 0;
}
LPC_CGU->PLL1_CTRL = PLLReg & ~(1 << 0);
/* Wait for 50uSec */
while(delay--) {}
return freq;
}
/* Returns the frequency of the main PLL */
uint32_t Chip_Clock_GetMainPLLHz(void)
{
uint32_t PLLReg = LPC_CGU->PLL1_CTRL;
uint32_t freq = Chip_Clock_GetClockInputHz((CHIP_CGU_CLKIN_T) ((PLLReg >> 24) & 0xF));
uint32_t msel, nsel, psel, direct, fbsel;
uint32_t m, n, p;
const uint8_t ptab[] = {1, 2, 4, 8};
/* No lock? */
if (!(LPC_CGU->PLL1_STAT & 1)) {
return 0;
}
msel = (PLLReg >> 16) & 0xFF;
nsel = (PLLReg >> 12) & 0x3;
psel = (PLLReg >> 8) & 0x3;
direct = (PLLReg >> 7) & 0x1;
fbsel = (PLLReg >> 6) & 0x1;
m = msel + 1;
n = nsel + 1;
p = ptab[psel];
if (direct || fbsel) {
return m * (freq / n);
}
return (m / (2 * p)) * (freq / n);
}
/* Sets up a CGU clock divider and it's input clock */
void Chip_Clock_SetDivider(CHIP_CGU_IDIV_T Divider, CHIP_CGU_CLKIN_T Input, uint32_t Divisor)
{
uint32_t reg = LPC_CGU->IDIV_CTRL[Divider];
Divisor--;
if (Input != CLKINPUT_PD) {
/* Mask off bits that need to changes */
reg &= ~((0x1F << 24) | 1 | (CHIP_CGU_IDIV_MASK(Divider) << 2));
/* Enable autoblocking, clear PD, and set clock source & divisor */
LPC_CGU->IDIV_CTRL[Divider] = reg | (1 << 11) | (Input << 24) | (Divisor << 2);
}
else {
LPC_CGU->IDIV_CTRL[Divider] = reg | 1; /* Power down this divider */
}
}
/* Gets a CGU clock divider source */
CHIP_CGU_CLKIN_T Chip_Clock_GetDividerSource(CHIP_CGU_IDIV_T Divider)
{
uint32_t reg = LPC_CGU->IDIV_CTRL[Divider];
if (reg & 1) { /* divider is powered down */
return CLKINPUT_PD;
}
return (CHIP_CGU_CLKIN_T) ((reg >> 24) & 0x1F);
}
/* Gets a CGU clock divider divisor */
uint32_t Chip_Clock_GetDividerDivisor(CHIP_CGU_IDIV_T Divider)
{
return (CHIP_CGU_CLKIN_T) ((LPC_CGU->IDIV_CTRL[Divider] >> 2) & CHIP_CGU_IDIV_MASK(Divider));
}
/* Returns the frequency of the specified input clock source */
uint32_t Chip_Clock_GetClockInputHz(CHIP_CGU_CLKIN_T input)
{
uint32_t rate = 0;
switch (input) {
case CLKIN_32K:
rate = CRYSTAL_32K_FREQ_IN;
break;
case CLKIN_IRC:
rate = CGU_IRC_FREQ;
break;
case CLKIN_ENET_RX:
if ((LPC_CREG->CREG6 & 0x07) != 0x4) {
/* MII mode requires 25MHz clock */
rate = 25000000;
}
break;
case CLKIN_ENET_TX:
if ((LPC_CREG->CREG6 & 0x07) != 0x4) {
rate = 25000000; /* MII uses 25 MHz */
} else {
rate = 50000000; /* RMII uses 50 MHz */
}
break;
case CLKIN_CLKIN:
rate = ExtRateIn;
break;
case CLKIN_CRYSTAL:
rate = OscRateIn;
break;
case CLKIN_USBPLL:
rate = audio_usb_pll_freq[CGU_USB_PLL];
break;
case CLKIN_AUDIOPLL:
rate = audio_usb_pll_freq[CGU_AUDIO_PLL];
break;
case CLKIN_MAINPLL:
rate = Chip_Clock_GetMainPLLHz();
break;
case CLKIN_IDIVA:
rate = Chip_Clock_GetDivRate(input, CLK_IDIV_A);
break;
case CLKIN_IDIVB:
rate = Chip_Clock_GetDivRate(input, CLK_IDIV_B);
break;
case CLKIN_IDIVC:
rate = Chip_Clock_GetDivRate(input, CLK_IDIV_C);
break;
case CLKIN_IDIVD:
rate = Chip_Clock_GetDivRate(input, CLK_IDIV_D);
break;
case CLKIN_IDIVE:
rate = Chip_Clock_GetDivRate(input, CLK_IDIV_E);
break;
case CLKINPUT_PD:
rate = 0;
break;
default:
break;
}
return rate;
}
/* Returns the frequency of the specified base clock source */
uint32_t Chip_Clock_GetBaseClocktHz(CHIP_CGU_BASE_CLK_T clock)
{
return Chip_Clock_GetClockInputHz(Chip_Clock_GetBaseClock(clock));
}
/* Sets a CGU Base Clock clock source */
void Chip_Clock_SetBaseClock(CHIP_CGU_BASE_CLK_T BaseClock, CHIP_CGU_CLKIN_T Input, bool autoblocken, bool powerdn)
{
uint32_t reg = LPC_CGU->BASE_CLK[BaseClock];
if (BaseClock < CLK_BASE_NONE) {
if (Input != CLKINPUT_PD) {
/* Mask off fields we plan to update */
reg &= ~((0x1F << 24) | 1 | (1 << 11));
if (autoblocken) {
reg |= (1 << 11);
}
if (powerdn) {
reg |= (1 << 0);
}
/* Set clock source */
reg |= (Input << 24);
LPC_CGU->BASE_CLK[BaseClock] = reg;
}
}
else {
LPC_CGU->BASE_CLK[BaseClock] = reg | 1; /* Power down this base clock */
}
}
/* Reads CGU Base Clock clock source information */
void Chip_Clock_GetBaseClockOpts(CHIP_CGU_BASE_CLK_T BaseClock, CHIP_CGU_CLKIN_T *Input, bool *autoblocken,
bool *powerdn)
{
uint32_t reg = LPC_CGU->BASE_CLK[BaseClock];
CHIP_CGU_CLKIN_T ClkIn = (CHIP_CGU_CLKIN_T) ((reg >> 24) & 0x1F );
if (BaseClock < CLK_BASE_NONE) {
/* Get settings */
*Input = ClkIn;
*autoblocken = (reg & (1 << 11)) ? true : false;
*powerdn = (reg & (1 << 0)) ? true : false;
}
else {
*Input = CLKINPUT_PD;
*powerdn = true;
*autoblocken = true;
}
}
/*Enables a base clock source */
void Chip_Clock_EnableBaseClock(CHIP_CGU_BASE_CLK_T BaseClock)
{
if (BaseClock < CLK_BASE_NONE) {
LPC_CGU->BASE_CLK[BaseClock] &= ~1;
}
}
/* Disables a base clock source */
void Chip_Clock_DisableBaseClock(CHIP_CGU_BASE_CLK_T BaseClock)
{
if (BaseClock < CLK_BASE_NONE) {
LPC_CGU->BASE_CLK[BaseClock] |= 1;
}
}
/* Returns base clock enable state */
bool Chip_Clock_IsBaseClockEnabled(CHIP_CGU_BASE_CLK_T BaseClock)
{
bool enabled;
if (BaseClock < CLK_BASE_NONE) {
enabled = (bool) ((LPC_CGU->BASE_CLK[BaseClock] & 1) == 0);
}
else {
enabled = false;
}
return enabled;
}
/* Gets a CGU Base Clock clock source */
CHIP_CGU_CLKIN_T Chip_Clock_GetBaseClock(CHIP_CGU_BASE_CLK_T BaseClock)
{
uint32_t reg;
if (BaseClock >= CLK_BASE_NONE) {
return CLKINPUT_PD;
}
reg = LPC_CGU->BASE_CLK[BaseClock];
/* base clock is powered down? */
if (reg & 1) {
return CLKINPUT_PD;
}
return (CHIP_CGU_CLKIN_T) ((reg >> 24) & 0x1F);
}
/* Enables a peripheral clock and sets clock states */
void Chip_Clock_EnableOpts(CHIP_CCU_CLK_T clk, bool autoen, bool wakeupen, int div)
{
uint32_t reg = 1;
if (autoen) {
reg |= (1 << 1);
}
if (wakeupen) {
reg |= (1 << 2);
}
/* Not all clocks support a divider, but we won't check that here. Only
dividers of 1 and 2 are allowed. Assume 1 if not 2 */
if (div == 2) {
reg |= (1 << 5);
}
/* Setup peripheral clock and start running */
if (clk >= CLK_CCU2_START) {
LPC_CCU2->CLKCCU[clk - CLK_CCU2_START].CFG = reg;
}
else {
LPC_CCU1->CLKCCU[clk].CFG = reg;
}
}
/* Enables a peripheral clock */
void Chip_Clock_Enable(CHIP_CCU_CLK_T clk)
{
/* Start peripheral clock running */
if (clk >= CLK_CCU2_START) {
LPC_CCU2->CLKCCU[clk - CLK_CCU2_START].CFG |= 1;
}
else {
LPC_CCU1->CLKCCU[clk].CFG |= 1;
}
}
/* Enable RTC Clock */
void Chip_Clock_RTCEnable(void)
{
LPC_CREG->CREG0 &= ~((1 << 3) | (1 << 2)); /* Reset 32Khz oscillator */
LPC_CREG->CREG0 |= (1 << 1) | (1 << 0); /* Enable 32 kHz & 1 kHz on osc32k and release reset */
}
/* Disables a peripheral clock */
void Chip_Clock_Disable(CHIP_CCU_CLK_T clk)
{
/* Stop peripheral clock */
if (clk >= CLK_CCU2_START) {
LPC_CCU2->CLKCCU[clk - CLK_CCU2_START].CFG &= ~1;
}
else {
LPC_CCU1->CLKCCU[clk].CFG &= ~1;
}
}
/**
* Disable all branch output clocks with wake up mechanism enabled.
* Only the clocks with wake up mechanism enabled will be disabled &
* power down sequence started
*/
void Chip_Clock_StartPowerDown(void)
{
/* Set Power Down bit */
LPC_CCU1->PM = 1;
LPC_CCU2->PM = 1;
}
/**
* Enable all branch output clocks after the wake up event.
* Only the clocks with wake up mechanism enabled will be enabled
*/
void Chip_Clock_ClearPowerDown(void)
{
/* Clear Power Down bit */
LPC_CCU1->PM = 0;
LPC_CCU2->PM = 0;
}
/* Returns a peripheral clock rate */
uint32_t Chip_Clock_GetRate(CHIP_CCU_CLK_T clk)
{
CHIP_CGU_BASE_CLK_T baseclk;
uint32_t reg, div, rate;
/* Get CCU config register for clock */
if (clk >= CLK_CCU2_START) {
reg = LPC_CCU2->CLKCCU[clk - CLK_CCU2_START].CFG;
}
else {
reg = LPC_CCU1->CLKCCU[clk].CFG;
}
/* Is the clock enabled? */
if (reg & 1) {
/* Get base clock for this peripheral clock */
baseclk = Chip_Clock_FindBaseClock(clk);
/* Get base clock rate */
rate = Chip_Clock_GetBaseClocktHz(baseclk);
/* Get divider for this clock */
if (((reg >> 5) & 0x7) == 0) {
div = 1;
}
else {
div = 2;/* No other dividers supported */
}
rate = rate / div;
}
else {
rate = 0;
}
return rate;
}
/* Get EMC Clock Rate */
uint32_t Chip_Clock_GetEMCRate(void)
{
uint32_t ClkFreq;
uint32_t EMCDiv;
ClkFreq = Chip_Clock_GetRate(CLK_MX_EMC);
/* EMC Divider readback at pos 27
TODO: just checked but dont mention in UM */
EMCDiv = (LPC_CCU1->CLKCCU[CLK_MX_EMC_DIV].CFG >> 27) & 0x07;
/* Check EMC Divider to get real EMC clock out */
if ((EMCDiv == 1) && (LPC_CREG->CREG6 & (1 << 16))) {
ClkFreq >>= 1;
}
return ClkFreq;
}
/* Sets up the audio or USB PLL */
void Chip_Clock_SetupPLL(CHIP_CGU_CLKIN_T Input, CHIP_CGU_USB_AUDIO_PLL_T pllnum,
const CGU_USBAUDIO_PLL_SETUP_T *pPLLSetup)
{
uint32_t reg = pPLLSetup->ctrl | (Input << 24);
/* Setup from passed values */
LPC_CGU->PLL[pllnum].PLL_CTRL = reg;
LPC_CGU->PLL[pllnum].PLL_MDIV = pPLLSetup->mdiv;
LPC_CGU->PLL[pllnum].PLL_NP_DIV = pPLLSetup->ndiv;
/* Fractional divider is for audio PLL only */
if (pllnum == CGU_AUDIO_PLL) {
LPC_CGU->PLL0AUDIO_FRAC = pPLLSetup->fract;
}
audio_usb_pll_freq[pllnum] = pPLLSetup->freq;
}
/* Enables the audio or USB PLL */
void Chip_Clock_EnablePLL(CHIP_CGU_USB_AUDIO_PLL_T pllnum)
{
LPC_CGU->PLL[pllnum].PLL_CTRL &= ~1;
}
/* Disables the audio or USB PLL */
void Chip_Clock_DisablePLL(CHIP_CGU_USB_AUDIO_PLL_T pllnum)
{
LPC_CGU->PLL[pllnum].PLL_CTRL |= 1;
}
/* Returns the PLL status */
uint32_t Chip_Clock_GetPLLStatus(CHIP_CGU_USB_AUDIO_PLL_T pllnum)
{
return LPC_CGU->PLL[pllnum].PLL_STAT;
}

View File

@@ -0,0 +1,91 @@
/*
* @brief LPC18xx/43xx D/A conversion driver
*
* @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 "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)
{
Chip_Clock_EnableOpts(CLK_APB3_DAC, true, true, 1);
/* 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)
{
Chip_Clock_Disable(CLK_APB3_DAC);
}
/* Update value to DAC buffer*/
void Chip_DAC_UpdateValue(LPC_DAC_T *pDAC, uint32_t dac_value)
{
uint32_t tmp;
tmp = pDAC->CR & DAC_BIAS_EN;
tmp |= DAC_VALUE(dac_value);
/* Update value */
pDAC->CR = tmp;
}
/* Set Maximum update rate for DAC */
void Chip_DAC_SetBias(LPC_DAC_T *pDAC, uint32_t bias)
{
pDAC->CR &= ~DAC_BIAS_EN;
if (bias == DAC_MAX_UPDATE_RATE_400kHz) {
pDAC->CR |= DAC_BIAS_EN;
}
}

View File

@@ -0,0 +1,106 @@
/*
* @brief LPC18xx/43xx EEPROM driver
*
* @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 "chip.h"
/*****************************************************************************
* 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_GetRate(CLK_MX_EEPROM);
/* Set EEPROM clock divide value*/
pEEPROM->CLKDIV = clk / EEPROM_CLOCK_DIV - 1;
}
/* Setup EEPROM clock */
STATIC INLINE void setWaitState(LPC_EEPROM_T *pEEPROM)
{
/* Setup EEPROM wait states*/
Chip_EEPROM_SetReadWaitState(pEEPROM, EEPROM_READ_WAIT_STATE_VAL);
Chip_EEPROM_SetWaitState(pEEPROM, EEPROM_WAIT_STATE_VAL);
}
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initializes the EEPROM peripheral with specified parameter */
void Chip_EEPROM_Init(LPC_EEPROM_T *pEEPROM)
{
/* Disable EEPROM power down mode */
Chip_EEPROM_DisablePowerDown(pEEPROM);
setClkDiv(pEEPROM);
setWaitState(pEEPROM);
}
/* Write data from page register to non-volatile memory */
void Chip_EEPROM_EraseProgramPage(LPC_EEPROM_T *pEEPROM)
{
Chip_EEPROM_ClearIntStatus(pEEPROM, EEPROM_CMD_ERASE_PRG_PAGE);
Chip_EEPROM_SetCmd(pEEPROM, EEPROM_CMD_ERASE_PRG_PAGE);
Chip_EEPROM_WaitForIntStatus(pEEPROM, EEPROM_INT_ENDOFPROG);
}
/* 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);
}

View File

@@ -0,0 +1,295 @@
/*
* @brief LPC18xx/43xx EMC driver
*
* @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 "chip.h"
/*****************************************************************************
* 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;
volatile 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);
for (i = 0; i < 1000; i++) { /* wait 100us */
}
pEMC->DYNAMICCONTROL = 0x00000183; /* Issue NOP command */
for (i = 0; i < 1000; i++) {}
pEMC->DYNAMICCONTROL = 0x00000103; /* Issue PALL command */
pEMC->DYNAMICREFRESH = 2; /* ( 2 * 16 ) -> 32 clock cycles */
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;
}
/* Check for RBC mode */
if (!(Dynamic_Config->DevConfig[ChipSelect].DynConfig & EMC_DYN_CONFIG_LPSDRAM)) {
if (!(Dynamic_Config->DevConfig[ChipSelect].DynConfig & (0x7 << EMC_DYN_CONFIG_DEV_SIZE_BIT))) {
/* 2 banks => 1 bank select bit */
Col_len += 1;
}
else {
/* 4 banks => 2 bank select bits */
Col_len += 2;
}
}
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_GetEMCRate();
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_GetEMCRate();
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);
}

View File

@@ -0,0 +1,188 @@
/*
* @brief LPC18xx/43xx Ethernet driver
*
* @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 "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/* Saved address for PHY and clock divider */
STATIC uint32_t phyCfg;
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
STATIC INLINE void reset(LPC_ENET_T *pENET)
{
Chip_RGU_TriggerReset(RGU_ETHERNET_RST);
while (Chip_RGU_InReset(RGU_ETHERNET_RST))
{}
/* Reset ethernet peripheral */
Chip_ENET_Reset(pENET);
}
STATIC uint32_t Chip_ENET_CalcMDCClock(void)
{
uint32_t val = SystemCoreClock / 1000000UL;
if (val >= 20 && val < 35)
return 2;
if (val >= 35 && val < 60)
return 3;
if (val >= 60 && val < 100)
return 0;
if (val >= 100 && val < 150)
return 1;
if (val >= 150 && val < 250)
return 4;
if (val >= 250 && val < 300)
return 5;
/* Code should never reach here
unless there is BUG in frequency settings
*/
return 0;
}
/*****************************************************************************
* Public functions
****************************************************************************/
/* Basic Ethernet interface initialization */
void Chip_ENET_Init(LPC_ENET_T *pENET, uint32_t phyAddr)
{
Chip_Clock_EnableOpts(CLK_MX_ETHERNET, true, true, 1);
reset(pENET);
/* Setup MII link divider to /102 and PHY address 1 */
Chip_ENET_SetupMII(pENET, Chip_ENET_CalcMDCClock(), phyAddr);
/* Enhanced descriptors, burst length = 1 */
pENET->DMA_BUS_MODE = DMA_BM_ATDS | DMA_BM_PBL(1) | DMA_BM_RPBL(1);
/* Initial MAC configuration for checksum offload, full duplex,
100Mbps, disable receive own in half duplex, inter-frame gap
of 64-bits */
pENET->MAC_CONFIG = MAC_CFG_BL(0) | MAC_CFG_IPC | MAC_CFG_DM |
MAC_CFG_DO | MAC_CFG_FES | MAC_CFG_PS | MAC_CFG_IFG(3);
/* Setup default filter */
pENET->MAC_FRAME_FILTER = MAC_FF_PR | MAC_FF_RA;
/* Flush transmit FIFO */
pENET->DMA_OP_MODE = DMA_OM_FTF;
/* Setup DMA to flush receive FIFOs at 32 bytes, service TX FIFOs at
64 bytes */
pENET->DMA_OP_MODE |= DMA_OM_RTC(1) | DMA_OM_TTC(0);
/* Clear all MAC interrupts */
pENET->DMA_STAT = DMA_ST_ALL;
/* Enable MAC interrupts */
pENET->DMA_INT_EN = 0;
}
/* Ethernet interface shutdown */
void Chip_ENET_DeInit(LPC_ENET_T *pENET)
{
/* Disable packet reception */
pENET->MAC_CONFIG = 0;
/* Flush transmit FIFO */
pENET->DMA_OP_MODE = DMA_OM_FTF;
/* Disable receive and transmit DMA processes */
pENET->DMA_OP_MODE = 0;
Chip_Clock_Disable(CLK_MX_ETHERNET);
}
/* 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 */
phyCfg = MAC_MIIA_PA(addr) | MAC_MIIA_CR(div);
}
/* 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_MII_ADDR = phyCfg | MAC_MIIA_GR(reg) | MAC_MIIA_W;
pENET->MAC_MII_DATA = (uint32_t) data;
pENET->MAC_MII_ADDR |= MAC_MIIA_GB;
}
/*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_MII_ADDR = phyCfg | MAC_MIIA_GR(reg);
pENET->MAC_MII_ADDR |= MAC_MIIA_GB;
}
/* Sets full or half duplex for the interface */
void Chip_ENET_SetDuplex(LPC_ENET_T *pENET, bool full)
{
if (full) {
pENET->MAC_CONFIG |= MAC_CFG_DM;
}
else {
pENET->MAC_CONFIG &= ~MAC_CFG_DM;
}
}
/* Sets speed for the interface */
void Chip_ENET_SetSpeed(LPC_ENET_T *pENET, bool speed100)
{
if (speed100) {
pENET->MAC_CONFIG |= MAC_CFG_FES;
}
else {
pENET->MAC_CONFIG &= ~MAC_CFG_FES;
}
}

View File

@@ -0,0 +1,117 @@
/*
* @brief LPC18xx/43xx event router driver
*
* @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 "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initialize the EVRT */
void Chip_EVRT_Init(void)
{
uint8_t i = 0;
// Clear all register to be default
LPC_EVRT->HILO = 0x0000;
LPC_EVRT->EDGE = 0x0000;
LPC_EVRT->CLR_EN = 0xFFFF;
do {
i++;
LPC_EVRT->CLR_STAT = 0xFFFFF;
} while ((LPC_EVRT->STATUS != 0) && (i < 10));
}
/* Set up the type of interrupt type for a source to EVRT */
void Chip_EVRT_ConfigIntSrcActiveType(CHIP_EVRT_SRC_T EVRT_Src, CHIP_EVRT_SRC_ACTIVE_T type)
{
switch (type) {
case EVRT_SRC_ACTIVE_LOW_LEVEL:
LPC_EVRT->HILO &= ~(1 << (uint8_t) EVRT_Src);
LPC_EVRT->EDGE &= ~(1 << (uint8_t) EVRT_Src);
break;
case EVRT_SRC_ACTIVE_HIGH_LEVEL:
LPC_EVRT->HILO |= (1 << (uint8_t) EVRT_Src);
LPC_EVRT->EDGE &= ~(1 << (uint8_t) EVRT_Src);
break;
case EVRT_SRC_ACTIVE_FALLING_EDGE:
LPC_EVRT->HILO &= ~(1 << (uint8_t) EVRT_Src);
LPC_EVRT->EDGE |= (1 << (uint8_t) EVRT_Src);
break;
case EVRT_SRC_ACTIVE_RISING_EDGE:
LPC_EVRT->HILO |= (1 << (uint8_t) EVRT_Src);
LPC_EVRT->EDGE |= (1 << (uint8_t) EVRT_Src);
break;
default:
break;
}
}
/* Enable or disable interrupt sources to EVRT */
void Chip_EVRT_SetUpIntSrc(CHIP_EVRT_SRC_T EVRT_Src, FunctionalState state)
{
if (state == ENABLE) {
LPC_EVRT->SET_EN = (1 << (uint8_t) EVRT_Src);
}
else {
LPC_EVRT->CLR_EN = (1 << (uint8_t) EVRT_Src);
}
}
/* Check if a source is sending interrupt to EVRT */
IntStatus Chip_EVRT_IsSourceInterrupting(CHIP_EVRT_SRC_T EVRT_Src)
{
if (LPC_EVRT->STATUS & (1 << (uint8_t) EVRT_Src)) {
return SET;
}
else {return RESET; }
}

View File

@@ -0,0 +1,752 @@
/*
* @brief LPC18xx/43xx GPDMA driver
*
* @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 "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/* Channel array to monitor free channel */
static DMA_ChannelHandle_t ChannelHandlerArray[GPDMA_NUMBER_CHANNELS];
/* Optimized Peripheral Source and Destination burst size (18xx,43xx) */
static const uint8_t GPDMA_LUTPerBurst[] = {
GPDMA_BSIZE_4, /* MEMORY */
GPDMA_BSIZE_1, /* MAT0.0 */
GPDMA_BSIZE_1, /* UART0 Tx */
GPDMA_BSIZE_1, /* MAT0.1 */
GPDMA_BSIZE_1, /* UART0 Rx */
GPDMA_BSIZE_1, /* MAT1.0 */
GPDMA_BSIZE_1, /* UART1 Tx */
GPDMA_BSIZE_1, /* MAT1.1 */
GPDMA_BSIZE_1, /* UART1 Rx */
GPDMA_BSIZE_1, /* MAT2.0 */
GPDMA_BSIZE_1, /* UART2 Tx */
GPDMA_BSIZE_1, /* MAT2.1 */
GPDMA_BSIZE_1, /* UART2 Rx */
GPDMA_BSIZE_1, /* MAT3.0 */
GPDMA_BSIZE_1, /* UART3 Tx */
0, /* SCT timer channel 0*/
GPDMA_BSIZE_1, /* MAT3.1 */
GPDMA_BSIZE_1, /* UART3 Rx */
0, /* SCT timer channel 1*/
GPDMA_BSIZE_4, /* SSP0 Rx */
GPDMA_BSIZE_32, /* I2S channel 0 */
GPDMA_BSIZE_4, /* SSP0 Tx */
GPDMA_BSIZE_32, /* I2S channel 1 */
GPDMA_BSIZE_4, /* SSP1 Rx */
GPDMA_BSIZE_4, /* SSP1 Tx */
GPDMA_BSIZE_4, /* ADC 0 */
GPDMA_BSIZE_4, /* ADC 1 */
GPDMA_BSIZE_1, /* DAC */
GPDMA_BSIZE_32, /* I2S channel 0 */
GPDMA_BSIZE_32 /* I2S channel 0 */
};
/* Optimized Peripheral Source and Destination transfer width (18xx,43xx) */
static const uint8_t GPDMA_LUTPerWid[] = {
GPDMA_WIDTH_WORD, /* MEMORY */
GPDMA_WIDTH_WORD, /* MAT0.0 */
GPDMA_WIDTH_BYTE, /* UART0 Tx */
GPDMA_WIDTH_WORD, /* MAT0.1 */
GPDMA_WIDTH_BYTE, /* UART0 Rx */
GPDMA_WIDTH_WORD, /* MAT1.0 */
GPDMA_WIDTH_BYTE, /* UART1 Tx */
GPDMA_WIDTH_WORD, /* MAT1.1 */
GPDMA_WIDTH_BYTE, /* UART1 Rx */
GPDMA_WIDTH_WORD, /* MAT2.0 */
GPDMA_WIDTH_BYTE, /* UART2 Tx */
GPDMA_WIDTH_WORD, /* MAT2.1 */
GPDMA_WIDTH_BYTE, /* UART2 Rx */
GPDMA_WIDTH_WORD, /* MAT3.0 */
GPDMA_WIDTH_BYTE, /* UART3 Tx */
0, /* SCT timer channel 0*/
GPDMA_WIDTH_WORD, /* MAT3.1 */
GPDMA_WIDTH_BYTE, /* UART3 Rx */
0, /* SCT timer channel 1*/
GPDMA_WIDTH_BYTE, /* SSP0 Rx */
GPDMA_WIDTH_WORD, /* I2S channel 0 */
GPDMA_WIDTH_BYTE, /* SSP0 Tx */
GPDMA_WIDTH_WORD, /* I2S channel 1 */
GPDMA_WIDTH_BYTE, /* SSP1 Rx */
GPDMA_WIDTH_BYTE, /* SSP1 Tx */
GPDMA_WIDTH_WORD, /* ADC 0 */
GPDMA_WIDTH_WORD, /* ADC 1 */
GPDMA_WIDTH_WORD, /* DAC */
GPDMA_WIDTH_WORD, /* I2S channel 0 */
GPDMA_WIDTH_WORD/* I2S channel 0 */
};
/* Lookup Table of Connection Type matched with (18xx,43xx) Peripheral Data (FIFO) register base address */
volatile static const void *GPDMA_LUTPerAddr[] = {
NULL, /* MEMORY */
(&LPC_TIMER0->MR), /* MAT0.0 */
(&LPC_USART0-> /*RBTHDLR.*/ THR), /* UART0 Tx */
((uint32_t *) &LPC_TIMER0->MR + 1), /* MAT0.1 */
(&LPC_USART0-> /*RBTHDLR.*/ RBR), /* UART0 Rx */
(&LPC_TIMER1->MR), /* MAT1.0 */
(&LPC_UART1-> /*RBTHDLR.*/ THR),/* UART1 Tx */
((uint32_t *) &LPC_TIMER1->MR + 1), /* MAT1.1 */
(&LPC_UART1-> /*RBTHDLR.*/ RBR),/* UART1 Rx */
(&LPC_TIMER2->MR), /* MAT2.0 */
(&LPC_USART2-> /*RBTHDLR.*/ THR), /* UART2 Tx */
((uint32_t *) &LPC_TIMER2->MR + 1), /* MAT2.1 */
(&LPC_USART2-> /*RBTHDLR.*/ RBR), /* UART2 Rx */
(&LPC_TIMER3->MR), /* MAT3.0 */
(&LPC_USART3-> /*RBTHDLR.*/ THR), /* UART3 Tx */
0, /* SCT timer channel 0*/
((uint32_t *) &LPC_TIMER3->MR + 1), /* MAT3.1 */
(&LPC_USART3-> /*RBTHDLR.*/ RBR), /* UART3 Rx */
0, /* SCT timer channel 1*/
(&LPC_SSP0->DR), /* SSP0 Rx */
(&LPC_I2S0->TXFIFO), /* I2S0 Tx on channel 0 */
(&LPC_SSP0->DR), /* SSP0 Tx */
(&LPC_I2S0->RXFIFO), /* I2S0 Rx on channel 1 */
(&LPC_SSP1->DR), /* SSP1 Rx */
(&LPC_SSP1->DR), /* SSP1 Tx */
(&LPC_ADC0->GDR), /* ADC 0 */
(&LPC_ADC1->GDR), /* ADC 1 */
(&LPC_DAC->CR), /* DAC */
(&LPC_I2S1->TXFIFO), /* I2S1 Tx on channel 0 */
(&LPC_I2S1->RXFIFO) /* I2S1 Rx on channel 1 */
};
/*****************************************************************************
* 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)
{
uint8_t function, channel;
switch (gpdma_peripheral_connection_number) {
case GPDMA_CONN_MAT0_0:
function = 0;
channel = 1;
break;
case GPDMA_CONN_UART0_Tx:
function = 1;
channel = 1;
break;
case GPDMA_CONN_MAT0_1:
function = 0;
channel = 2;
break;
case GPDMA_CONN_UART0_Rx:
function = 1;
channel = 2;
break;
case GPDMA_CONN_MAT1_0:
function = 0;
channel = 3;
break;
case GPDMA_CONN_UART1_Tx:
function = 1;
channel = 3;
break;
case GPDMA_CONN_I2S1_Tx_Channel_0:
function = 2;
channel = 3;
break;
case GPDMA_CONN_MAT1_1:
function = 0;
channel = 4;
break;
case GPDMA_CONN_UART1_Rx:
function = 1;
channel = 4;
break;
case GPDMA_CONN_I2S1_Rx_Channel_1:
function = 2;
channel = 4;
break;
case GPDMA_CONN_MAT2_0:
function = 0;
channel = 5;
break;
case GPDMA_CONN_UART2_Tx:
function = 1;
channel = 5;
break;
case GPDMA_CONN_MAT2_1:
function = 0;
channel = 6;
break;
case GPDMA_CONN_UART2_Rx:
function = 1;
channel = 6;
break;
case GPDMA_CONN_MAT3_0:
function = 0;
channel = 7;
break;
case GPDMA_CONN_UART3_Tx:
function = 1;
channel = 7;
break;
case GPDMA_CONN_SCT_0:
function = 2;
channel = 7;
break;
case GPDMA_CONN_MAT3_1:
function = 0;
channel = 8;
break;
case GPDMA_CONN_UART3_Rx:
function = 1;
channel = 8;
break;
case GPDMA_CONN_SCT_1:
function = 2;
channel = 8;
break;
case GPDMA_CONN_SSP0_Rx:
function = 0;
channel = 9;
break;
case GPDMA_CONN_I2S_Tx_Channel_0:
function = 1;
channel = 9;
break;
case GPDMA_CONN_SSP0_Tx:
function = 0;
channel = 10;
break;
case GPDMA_CONN_I2S_Rx_Channel_1:
function = 1;
channel = 10;
break;
case GPDMA_CONN_SSP1_Rx:
function = 0;
channel = 11;
break;
case GPDMA_CONN_SSP1_Tx:
function = 0;
channel = 12;
break;
case GPDMA_CONN_ADC_0:
function = 0;
channel = 13;
break;
case GPDMA_CONN_ADC_1:
function = 0;
channel = 14;
break;
case GPDMA_CONN_DAC:
function = 0;
channel = 15;
break;
default:
function = 3;
channel = 15;
break;
}
/* Set select function to dmamux register */
if (0 != gpdma_peripheral_connection_number) {
uint32_t temp;
temp = LPC_CREG->DMAMUX & (~(0x03 << (2 * channel)));
LPC_CREG->DMAMUX = temp | (function << (2 * channel));
}
return channel;
}
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_EnableOpts(CLK_MX_DMA, true, true, 1);
/* 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_Disable(CLK_MX_DMA);
}
/* Stop a stream DMA transfer */
void Chip_GPDMA_Stop(LPC_GPDMA_T *pGPDMA,
uint8_t ChannelNum)
{
Chip_GPDMA_ChannelCmd(pGPDMA, (ChannelNum), DISABLE);
if (Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_INTTC, ChannelNum)) {
/* Clear terminate counter Interrupt pending */
Chip_GPDMA_ClearIntPending(pGPDMA, GPDMA_STATCLR_INTTC, ChannelNum);
}
if (Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_INTERR, ChannelNum)) {
/* Clear terminate counter Interrupt pending */
Chip_GPDMA_ClearIntPending(pGPDMA, GPDMA_STATCLR_INTERR, ChannelNum);
}
ChannelHandlerArray[ChannelNum].ChannelStatus = DISABLE;
}
/* The GPDMA stream interrupt status checking */
Status Chip_GPDMA_Interrupt(LPC_GPDMA_T *pGPDMA,
uint8_t ChannelNum)
{
if (Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_INT, ChannelNum)) {
/* Check counter terminal status */
if (Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_INTTC, ChannelNum)) {
/* Clear terminate counter Interrupt pending */
Chip_GPDMA_ClearIntPending(pGPDMA, GPDMA_STATCLR_INTTC, ChannelNum);
return SUCCESS;
}
/* Check error terminal status */
if (Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_INTERR, ChannelNum)) {
/* Clear error counter Interrupt pending */
Chip_GPDMA_ClearIntPending(pGPDMA, GPDMA_STATCLR_INTERR, ChannelNum);
return ERROR;
}
}
return ERROR;
}
int Chip_GPDMA_InitChannelCfg(LPC_GPDMA_T *pGPDMA,
GPDMA_CH_CFG_T *GPDMACfg,
uint8_t ChannelNum,
uint32_t src,
uint32_t dst,
uint32_t Size,
GPDMA_FLOW_CONTROL_T TransferType)
{
int rval = -1;
GPDMACfg->ChannelNum = ChannelNum;
GPDMACfg->TransferType = TransferType;
GPDMACfg->TransferSize = Size;
switch (TransferType) {
case GPDMA_TRANSFERTYPE_M2M_CONTROLLER_DMA:
GPDMACfg->SrcAddr = (uint32_t) src;
GPDMACfg->DstAddr = (uint32_t) dst;
rval = 3;
GPDMACfg->TransferWidth = GPDMA_WIDTH_WORD;
GPDMACfg->TransferSize = Size / 4;
break;
case GPDMA_TRANSFERTYPE_M2P_CONTROLLER_DMA:
case GPDMA_TRANSFERTYPE_M2P_CONTROLLER_PERIPHERAL:
GPDMACfg->SrcAddr = (uint32_t) src;
rval = 1;
GPDMACfg->DstAddr = (uint32_t) GPDMA_LUTPerAddr[dst];
break;
case GPDMA_TRANSFERTYPE_P2M_CONTROLLER_DMA:
case GPDMA_TRANSFERTYPE_P2M_CONTROLLER_PERIPHERAL:
GPDMACfg->SrcAddr = (uint32_t) GPDMA_LUTPerAddr[src];
GPDMACfg->DstAddr = (uint32_t) dst;
rval = 2;
break;
case GPDMA_TRANSFERTYPE_P2P_CONTROLLER_DMA:
case GPDMA_TRANSFERTYPE_P2P_CONTROLLER_DestPERIPHERAL:
case GPDMA_TRANSFERTYPE_P2P_CONTROLLER_SrcPERIPHERAL:
GPDMACfg->SrcAddr = (uint32_t) GPDMA_LUTPerAddr[src];
GPDMACfg->DstAddr = (uint32_t) GPDMA_LUTPerAddr[dst];
rval = 0;
break;
default:
break;
}
return rval;
}
/* Read the status from different registers according to the type */
IntStatus Chip_GPDMA_IntGetStatus(LPC_GPDMA_T *pGPDMA, GPDMA_STATUS_T type, uint8_t channel)
{
/**
* TODO check the channel <=8 type is exited
*/
switch (type) {
case GPDMA_STAT_INT:/* check status of DMA channel interrupts */
return (IntStatus) (pGPDMA->INTSTAT & (((1UL << channel) & 0xFF)));
case GPDMA_STAT_INTTC: /* check terminal count interrupt request status for DMA */
return (IntStatus) (pGPDMA->INTTCSTAT & (((1UL << channel) & 0xFF)));
case GPDMA_STAT_INTERR: /* check interrupt status for DMA channels */
return (IntStatus) (pGPDMA->INTERRSTAT & (((1UL << channel) & 0xFF)));
case GPDMA_STAT_RAWINTTC: /* check status of the terminal count interrupt for DMA channels */
return (IntStatus) (pGPDMA->RAWINTTCSTAT & (((1UL << channel) & 0xFF)));
case GPDMA_STAT_RAWINTERR: /* check status of the error interrupt for DMA channels */
return (IntStatus) (pGPDMA->RAWINTERRSTAT & (((1UL << channel) & 0xFF)));
default:/* check enable status for DMA channels */
return (IntStatus) (pGPDMA->ENBLDCHNS & (((1UL << channel) & 0xFF)));
}
}
/* Clear the Interrupt Flag from different registers according to the type */
void Chip_GPDMA_ClearIntPending(LPC_GPDMA_T *pGPDMA, GPDMA_STATECLEAR_T type, uint8_t channel)
{
if (type == GPDMA_STATCLR_INTTC) {
/* clears the terminal count interrupt request on DMA channel */
pGPDMA->INTTCCLEAR = (((1UL << (channel)) & 0xFF));
}
else {
/* clear the error interrupt request */
pGPDMA->INTERRCLR = (((1UL << (channel)) & 0xFF));
}
}
/* Enable or Disable the GPDMA Channel */
void Chip_GPDMA_ChannelCmd(LPC_GPDMA_T *pGPDMA, uint8_t channelNum, FunctionalState NewState)
{
GPDMA_CH_T *pDMAch;
/* Get Channel pointer */
pDMAch = (GPDMA_CH_T *) &(pGPDMA->CH[channelNum]);
if (NewState == ENABLE) {
pDMAch->CONFIG |= GPDMA_DMACCxConfig_E;
}
else {
pDMAch->CONFIG &= ~GPDMA_DMACCxConfig_E;
}
}
/* Do a DMA transfer M2M, M2P,P2M or P2P */
Status Chip_GPDMA_Transfer(LPC_GPDMA_T *pGPDMA,
uint8_t ChannelNum,
uint32_t src,
uint32_t dst,
GPDMA_FLOW_CONTROL_T TransferType,
uint32_t Size)
{
GPDMA_CH_CFG_T GPDMACfg;
uint8_t SrcPeripheral = 0, DstPeripheral = 0;
uint32_t cwrd;
int ret;
ret = Chip_GPDMA_InitChannelCfg(pGPDMA, &GPDMACfg, ChannelNum, src, dst, Size, TransferType);
if (ret < 0) {
return ERROR;
}
/* Adjust src/dst index if they are memory */
if (ret & 1) {
src = 0;
}
else {
SrcPeripheral = configDMAMux(src);
}
if (ret & 2) {
dst = 0;
}
else {
DstPeripheral = configDMAMux(dst);
}
cwrd = makeCtrlWord(&GPDMACfg,
(uint32_t) GPDMA_LUTPerBurst[src],
(uint32_t) GPDMA_LUTPerBurst[dst],
(uint32_t) GPDMA_LUTPerWid[src],
(uint32_t) GPDMA_LUTPerWid[dst]);
if (setupChannel(pGPDMA, &GPDMACfg, cwrd, 0, SrcPeripheral, DstPeripheral) == ERROR) {
return ERROR;
}
/* Start the Channel */
Chip_GPDMA_ChannelCmd(pGPDMA, ChannelNum, ENABLE);
return SUCCESS;
}
Status Chip_GPDMA_PrepareDescriptor(LPC_GPDMA_T *pGPDMA,
DMA_TransferDescriptor_t *DMADescriptor,
uint32_t src,
uint32_t dst,
uint32_t Size,
GPDMA_FLOW_CONTROL_T TransferType,
const DMA_TransferDescriptor_t *NextDescriptor)
{
int ret;
GPDMA_CH_CFG_T GPDMACfg;
ret = Chip_GPDMA_InitChannelCfg(pGPDMA, &GPDMACfg, 0, src, dst, Size, TransferType);
if (ret < 0) {
return ERROR;
}
/* Adjust src/dst index if they are memory */
if (ret & 1) {
src = 0;
}
if (ret & 2) {
dst = 0;
}
DMADescriptor->src = GPDMACfg.SrcAddr;
DMADescriptor->dst = GPDMACfg.DstAddr;
DMADescriptor->lli = (uint32_t) NextDescriptor;
DMADescriptor->ctrl = makeCtrlWord(&GPDMACfg,
(uint32_t) GPDMA_LUTPerBurst[src],
(uint32_t) GPDMA_LUTPerBurst[dst],
(uint32_t) GPDMA_LUTPerWid[src],
(uint32_t) GPDMA_LUTPerWid[dst]);
/* By default set interrupt only for last transfer */
if (NextDescriptor) {
DMADescriptor->ctrl &= ~GPDMA_DMACCxControl_I;
}
return SUCCESS;
}
/* Do a DMA scatter-gather transfer M2M, M2P,P2M or P2P using DMA descriptors */
Status Chip_GPDMA_SGTransfer(LPC_GPDMA_T *pGPDMA,
uint8_t ChannelNum,
const DMA_TransferDescriptor_t *DMADescriptor,
GPDMA_FLOW_CONTROL_T TransferType)
{
const DMA_TransferDescriptor_t *dsc = DMADescriptor;
GPDMA_CH_CFG_T GPDMACfg;
uint8_t SrcPeripheral = 0, DstPeripheral = 0;
uint32_t src = DMADescriptor->src, dst = DMADescriptor->dst;
int ret;
ret = Chip_GPDMA_InitChannelCfg(pGPDMA, &GPDMACfg, ChannelNum, src, dst, 0, TransferType);
if (ret < 0) {
return ERROR;
}
/* Adjust src/dst index if they are memory */
if (ret & 1) {
src = 0;
}
else {
SrcPeripheral = configDMAMux(src);
}
if (ret & 2) {
dst = 0;
}
else {
DstPeripheral = configDMAMux(dst);
}
if (setupChannel(pGPDMA, &GPDMACfg, dsc->ctrl, dsc->lli, SrcPeripheral, DstPeripheral) == ERROR) {
return ERROR;
}
/* Start the Channel */
Chip_GPDMA_ChannelCmd(pGPDMA, ChannelNum, ENABLE);
return SUCCESS;
}
/* Get a free GPDMA channel for one DMA connection */
uint8_t Chip_GPDMA_GetFreeChannel(LPC_GPDMA_T *pGPDMA,
uint32_t PeripheralConnection_ID)
{
uint8_t temp = 0;
for (temp = 0; temp < GPDMA_NUMBER_CHANNELS; temp++) {
if (!Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_ENABLED_CH,
temp) && (ChannelHandlerArray[temp].ChannelStatus == DISABLE)) {
ChannelHandlerArray[temp].ChannelStatus = ENABLE;
return temp;
}
}
return 0;
}

View File

@@ -0,0 +1,66 @@
/*
* @brief LPC18xx/43xx GPIO driver
*
* @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
****************************************************************************/
/* Initialize GPIO block */
void Chip_GPIO_Init(LPC_GPIO_T *pGPIO)
{
}
/* De-Initialize GPIO block */
void Chip_GPIO_DeInit(LPC_GPIO_T *pGPIO)
{
}

View File

@@ -0,0 +1,54 @@
/*
* @brief LPC18xx/43xx GPIO group driver
*
* @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
****************************************************************************/

View File

@@ -0,0 +1,560 @@
/*
* @brief LPC18xx/43xx I2C driver
*
* @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
****************************************************************************/
/* 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)
/* I2C common interface structure */
struct i2c_interface {
LPC_I2C_T *ip; /* IP base address of the I2C device */
CHIP_CCU_CLK_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, CLK_APB1_I2C0, Chip_I2C_EventHandler, NULL, NULL, NULL, 0},
{LPC_I2C1, CLK_APB3_I2C1, 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_Enable(i2c[id].clk);
}
STATIC INLINE void disableClk(I2C_ID_T id)
{
Chip_Clock_Disable(i2c[id].clk);
}
/* Get the ADC Clock Rate */
STATIC INLINE uint32_t getClkRate(I2C_ID_T id)
{
return Chip_Clock_GetRate(i2c[id].clk);
}
/* 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_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_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 0x48: /* SLA+R sent NAK received */
xfer->status = I2C_STATUS_SLAVENAK;
cclr &= ~I2C_CON_STO;
break;
case 0x30: /* DATA 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 & ~I2C_CON_STO;
/* 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 & ~I2C_CON_STO;
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_STA | I2C_CON_AA;
disableClk(id);
}
/* Set up clock rate for LPC_I2C peripheral */
void Chip_I2C_SetClockRate(I2C_ID_T id, uint32_t clockrate)
{
uint32_t SCLValue;
SCLValue = (getClkRate(id) / clockrate);
LPC_I2Cx(id)->SCLH = (uint32_t) (SCLValue >> 1);
LPC_I2Cx(id)->SCLL = (uint32_t) (SCLValue - LPC_I2Cx(id)->SCLH);
}
/* Get current clock rate for LPC_I2C peripheral */
uint32_t Chip_I2C_GetClockRate(I2C_ID_T id)
{
return getClkRate(id) / (LPC_I2Cx(id)->SCLH + LPC_I2Cx(id)->SCLL);
}
/* Set the master event handler */
int Chip_I2C_SetMasterEventHandler(I2C_ID_T id, I2C_EVENTHANDLER_T event)
{
struct i2c_interface *iic = &i2c[id];
if (!iic->mXfer) {
iic->mEvent = event;
}
return iic->mEvent == event;
}
/* Get the master event handler */
I2C_EVENTHANDLER_T Chip_I2C_GetMasterEventHandler(I2C_ID_T id)
{
return i2c[id].mEvent;
}
/* Transmit and Receive data in master mode */
int Chip_I2C_MasterTransfer(I2C_ID_T id, I2C_XFER_T *xfer)
{
struct i2c_interface *iic = &i2c[id];
iic->mEvent(id, I2C_EVENT_LOCK);
xfer->status = I2C_STATUS_BUSY;
iic->mXfer = xfer;
/* If slave xfer not in progress */
if (!iic->sXfer) {
startMasterXfer(iic->ip);
}
iic->mEvent(id, I2C_EVENT_WAIT);
iic->mXfer = 0;
/* Wait for stop condition to appear on bus */
while (!isI2CBusFree(iic->ip)) {}
/* Start slave if one is active */
if (SLAVE_ACTIVE(iic)) {
startSlaverXfer(iic->ip);
}
iic->mEvent(id, I2C_EVENT_UNLOCK);
return (int) xfer->status;
}
/* Master tx only */
int Chip_I2C_MasterSend(I2C_ID_T id, uint8_t slaveAddr, const uint8_t *buff, uint8_t len)
{
I2C_XFER_T xfer = {0};
xfer.slaveAddr = slaveAddr;
xfer.txBuff = buff;
xfer.txSz = len;
while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
return len - xfer.txSz;
}
/* Transmit one byte and receive an array of bytes after a repeated start condition is generated in Master mode.
* This function is useful for communicating with the I2C slave registers
*/
int Chip_I2C_MasterCmdRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t cmd, uint8_t *buff, int len)
{
I2C_XFER_T xfer = {0};
xfer.slaveAddr = slaveAddr;
xfer.txBuff = &cmd;
xfer.txSz = 1;
xfer.rxBuff = buff;
xfer.rxSz = len;
while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
return len - xfer.rxSz;
}
/* Sequential master read */
int Chip_I2C_MasterRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t *buff, int len)
{
I2C_XFER_T xfer = {0};
xfer.slaveAddr = slaveAddr;
xfer.rxBuff = buff;
xfer.rxSz = len;
while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
return len - xfer.rxSz;
}
/* Check if master state is active */
int Chip_I2C_IsMasterActive(I2C_ID_T id)
{
return isMasterState(i2c[id].ip);
}
/* State change handler for master transfer */
void Chip_I2C_MasterStateHandler(I2C_ID_T id)
{
if (!handleMasterXferState(i2c[id].ip, i2c[id].mXfer)) {
i2c[id].mEvent(id, I2C_EVENT_DONE);
}
}
/* Setup slave function */
void Chip_I2C_SlaveSetup(I2C_ID_T id,
I2C_SLAVE_ID sid,
I2C_XFER_T *xfer,
I2C_EVENTHANDLER_T event,
uint8_t addrMask)
{
struct i2c_interface *iic = &i2c[id];
struct i2c_slave_interface *si2c = &i2c_slave[id][sid];
si2c->xfer = xfer;
si2c->event = event;
/* Set up the slave address */
if (sid != I2C_SLAVE_GENERAL) {
setSlaveAddr(iic->ip, sid, xfer->slaveAddr, addrMask);
}
if (!SLAVE_ACTIVE(iic) && !iic->mXfer) {
startSlaverXfer(iic->ip);
}
iic->flags |= 1 << (sid + 8);
}
/* I2C Slave event handler */
void Chip_I2C_SlaveStateHandler(I2C_ID_T id)
{
int ret;
struct i2c_interface *iic = &i2c[id];
/* Get the currently addressed slave */
if (!iic->sXfer) {
struct i2c_slave_interface *si2c;
I2C_SLAVE_ID sid = getSlaveIndex(iic->ip);
si2c = &i2c_slave[id][sid];
iic->sXfer = si2c->xfer;
iic->sEvent = si2c->event;
}
iic->sXfer->slaveAddr |= iic->mXfer != 0;
ret = handleSlaveXferState(iic->ip, iic->sXfer);
if (ret) {
if (iic->sXfer->status == I2C_STATUS_DONE) {
iic->sXfer = 0;
}
iic->sEvent(id, (I2C_EVENT_T) ret);
}
}
/* Disable I2C device */
void Chip_I2C_Disable(I2C_ID_T id)
{
LPC_I2Cx(id)->CONCLR = I2C_I2CONCLR_I2ENC;
}
/* State change checking */
int Chip_I2C_IsStateChanged(I2C_ID_T id)
{
return (LPC_I2Cx(id)->CONSET & I2C_CON_SI) != 0;
}

View File

@@ -0,0 +1,274 @@
/*
* @brief LPC18xx/43xx I2C master driver
*
* @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
****************************************************************************/
/* Control flags */
#define I2C_CON_FLAGS (I2C_CON_AA | I2C_CON_SI | I2C_CON_STO | I2C_CON_STA)
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/* Get the ADC Clock Rate */
static CHIP_CCU_CLK_T i2cm_getClkId(LPC_I2C_T *pI2C)
{
return (pI2C == LPC_I2C0)? CLK_APB1_I2C0 : CLK_APB3_I2C1;
}
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initializes the LPC_I2C peripheral with specified parameter */
void Chip_I2CM_Init(LPC_I2C_T *pI2C)
{
/* Enable I2C clock */
Chip_Clock_Enable(i2cm_getClkId(pI2C));
/* Reset I2C state machine */
Chip_I2CM_ResetControl(pI2C);
}
/* De-initializes the I2C peripheral registers to their default reset values */
void Chip_I2CM_DeInit(LPC_I2C_T *pI2C)
{
/* Reset I2C state machine */
Chip_I2CM_ResetControl(pI2C);
/* Disable I2C clock */
Chip_Clock_Disable(i2cm_getClkId(pI2C));
}
/* Set up bus speed for LPC_I2C interface */
void Chip_I2CM_SetBusSpeed(LPC_I2C_T *pI2C, uint32_t busSpeed)
{
uint32_t clockDiv = (Chip_Clock_GetRate(i2cm_getClkId(pI2C)) / busSpeed);
Chip_I2CM_SetDutyCycle(pI2C, (clockDiv >> 1), (clockDiv - (clockDiv >> 1)));
}
/* Master transfer state change handler handler */
uint32_t Chip_I2CM_XferHandler(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer)
{
uint32_t cclr = I2C_CON_FLAGS;
switch (Chip_I2CM_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 0x20: /* SLA+W sent NAK received */
case 0x30: /* DATA sent NAK received */
if ((xfer->options & I2CM_XFER_OPTION_IGNORE_NACK) == 0) {
xfer->status = I2CM_STATUS_NAK;
cclr &= ~I2C_CON_STO;
break;
}
case 0x18: /* SLA+W sent and ACK received */
case 0x28: /* DATA sent and ACK received */
if (!xfer->txSz) {
if (xfer->rxSz) {
cclr &= ~I2C_CON_STA;
}
else {
xfer->status = I2CM_STATUS_OK;
cclr &= ~I2C_CON_STO;
}
}
else {
pI2C->DAT = *xfer->txBuff++;
xfer->txSz--;
}
break;
/* Rx handling */
case 0x58: /* Data Received and NACK sent */
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) || (xfer->options & I2CM_XFER_OPTION_LAST_RX_ACK)) {
cclr &= ~I2C_CON_AA;
}
if (xfer->rxSz == 0) {
xfer->status = I2CM_STATUS_OK;
cclr &= ~I2C_CON_STO;
}
break;
/* NAK Handling */
case 0x48: /* SLA+R sent NAK received */
xfer->status = I2CM_STATUS_SLAVE_NAK;
cclr &= ~I2C_CON_STO;
break;
case 0x38: /* Arbitration lost */
xfer->status = I2CM_STATUS_ARBLOST;
break;
case 0x00: /* Bus Error */
xfer->status = I2CM_STATUS_BUS_ERROR;
cclr &= ~I2C_CON_STO;
break;
case 0xF8:
return 0;
default:
xfer->status = I2CM_STATUS_ERROR;
cclr &= ~I2C_CON_STO;
break;
}
/* Set clear control flags */
pI2C->CONSET = cclr ^ I2C_CON_FLAGS;
/* Stop flag should not be cleared as it is a reserved bit */
pI2C->CONCLR = cclr & (I2C_CON_AA | I2C_CON_SI | I2C_CON_STA);
return xfer->status != I2CM_STATUS_BUSY;
}
/* Transmit and Receive data in master mode */
void Chip_I2CM_Xfer(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer)
{
/* set the transfer status as busy */
xfer->status = I2CM_STATUS_BUSY;
/* Clear controller state. */
Chip_I2CM_ResetControl(pI2C);
/* Enter to Master Transmitter mode */
Chip_I2CM_SendStart(pI2C);
}
/* Transmit and Receive data in master mode */
uint32_t Chip_I2CM_XferBlocking(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer)
{
uint32_t ret = 0;
/* start transfer */
Chip_I2CM_Xfer(pI2C, xfer);
while (ret == 0) {
/* wait for status change interrupt */
while ( Chip_I2CM_StateChanged(pI2C) == 0) {}
/* call state change handler */
ret = Chip_I2CM_XferHandler(pI2C, xfer);
}
return ret;
}
/* Master tx only */
uint32_t Chip_I2CM_Write(LPC_I2C_T *pI2C, const uint8_t *buff, uint32_t len)
{
uint32_t txLen = 0, err = 0;
/* clear state change interrupt status */
Chip_I2CM_ClearSI(pI2C);
/* generate START condition */
Chip_I2CM_SendStart(pI2C);
while ((txLen < len) && (err == 0)) {
/* wait for status change interrupt */
while ( Chip_I2CM_StateChanged(pI2C) == 0) {}
/* check status and send data */
switch (Chip_I2CM_GetCurState(pI2C)) {
case 0x08: /* Start condition on bus */
case 0x10: /* Repeated start condition */
case 0x18: /* SLA+W sent and ACK received */
case 0x28: /* DATA sent and ACK received */
Chip_I2CM_WriteByte(pI2C, buff[txLen++]);
break;
case 0x38: /* Arbitration lost */
break;
default: /* we shouldn't be in any other state */
err = 1;
break;
}
/* clear state change interrupt status */
Chip_I2CM_ClearSI(pI2C);
}
return txLen;
}
/* Sequential master read */
uint32_t Chip_I2CM_Read(LPC_I2C_T *pI2C, uint8_t *buff, uint32_t len)
{
uint32_t rxLen = 0, err = 0;
/* clear state change interrupt status */
Chip_I2CM_ClearSI(pI2C);
/* generate START condition and auto-ack data received */
pI2C->CONSET = I2C_CON_AA | I2C_CON_STA;
while ((rxLen < len) && (err == 0)) {
/* wait for status change interrupt */
while ( Chip_I2CM_StateChanged(pI2C) == 0) {}
/* check status and send data */
switch (Chip_I2CM_GetCurState(pI2C)) {
case 0x08: /* Start condition on bus */
case 0x10: /* Repeated start condition */
case 0x40: /* SLA+R sent and ACK received */
case 0x50: /* Data Received and ACK sent */
buff[rxLen++] = Chip_I2CM_ReadByte(pI2C);
break;
case 0x38: /* Arbitration lost */
break;
default: /* we shouldn't be in any other state */
err = 1;
break;
}
/* clear state change interrupt status */
Chip_I2CM_ClearSI(pI2C);
}
return rxLen;
}

View File

@@ -0,0 +1,264 @@
/*
* @brief LPC18xx/43xx I2S driver
*
* @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 "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;
pClk = Chip_Clock_GetRate(CLK_APB1_I2S);
/* 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_Enable(CLK_APB1_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_Disable(CLK_APB1_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) {
temp = pI2S->IRQ & (~I2S_IRQ_TX_DEPTH_MASK);
pI2S->IRQ = temp | (I2S_IRQ_TX_DEPTH(depth));
pI2S->IRQ |= 0x02;
}
else {
pI2S->IRQ &= (~0x02);
}
}
/* 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) {
temp = pI2S->IRQ & (~I2S_IRQ_RX_DEPTH_MASK);
pI2S->IRQ = temp | (I2S_IRQ_RX_DEPTH(depth));
pI2S->IRQ |= 0x01;
}
else {
pI2S->IRQ &= (~0x01);
}
}
/* 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)
{
/* Enable/Disable I2S transmit*/
if (newState == ENABLE) {
/* Set FIFO Level */
pI2S->DMA[I2S_DMA_REQUEST_CHANNEL_1] &= ~(0x0F << 16);
pI2S->DMA[I2S_DMA_REQUEST_CHANNEL_1] |= depth << 16;
pI2S->DMA[I2S_DMA_REQUEST_CHANNEL_1] |= 0x02;
}
else {
pI2S->DMA[I2S_DMA_REQUEST_CHANNEL_1] &= ~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)
{
/* Enable/Disable I2S Receive */
if (newState == ENABLE) {
/* Set FIFO Level */
pI2S->DMA[I2S_DMA_REQUEST_CHANNEL_2] &= ~(0x0F << 8);
pI2S->DMA[I2S_DMA_REQUEST_CHANNEL_2] |= depth << 8;
pI2S->DMA[I2S_DMA_REQUEST_CHANNEL_2] |= 0x01;
}
else {
pI2S->DMA[I2S_DMA_REQUEST_CHANNEL_2] &= ~0x01;
}
}

View File

@@ -0,0 +1,211 @@
/*
* @brief Common FLASH IAP 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
****************************************************************************/
/* Initializes the IAP command interface */
uint8_t Chip_IAP_Init(void)
{
uint32_t command[5], result[4];
command[0] = 49; /* IAP_INIT */
result[0] = IAP_CMD_SUCCESS;
iap_entry(command, result);
return result[0];
}
/* Prepare sector for write operation */
uint8_t Chip_IAP_PreSectorForReadWrite(uint32_t strSector, uint32_t endSector, uint8_t flashBank)
{
uint32_t command[5], result[4];
command[0] = IAP_PREWRRITE_CMD;
command[1] = strSector;
command[2] = endSector;
command[3] = flashBank;
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, uint8_t flashBank)
{
uint32_t command[5], result[4];
command[0] = IAP_ERSSECTOR_CMD;
command[1] = strSector;
command[2] = endSector;
command[3] = SystemCoreClock / 1000;
command[4] = flashBank;
iap_entry(command, result);
return result[0];
}
/* Blank check sector */
uint8_t Chip_IAP_BlankCheckSector(uint32_t strSector, uint32_t endSector, uint8_t flashBank)
{
uint32_t command[5], result[4];
command[0] = IAP_BLANK_CHECK_SECTOR_CMD;
command[1] = strSector;
command[2] = endSector;
command[3] = flashBank;
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 uid[])
{
uint32_t command[5], result[5], i;
command[0] = IAP_READ_UID_CMD;
iap_entry(command, result);
for(i = 0; i < 4; i++) {
uid[i] = result[i + 1];
}
return result[0];
}
/* 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];
}
/* Set active boot flash bank */
uint8_t Chip_IAP_SetBootFlashBank(uint8_t bankNum)
{
uint32_t command[5], result[4];
command[0] = IAP_SET_BOOT_FLASH;
command[1] = bankNum;
command[2] = SystemCoreClock / 1000;
iap_entry(command, result);
return result[0];
}

View File

@@ -0,0 +1,212 @@
/*
* @brief LPC18xx/43xx LCD chip driver
*
* @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 "chip.h"
/*****************************************************************************
* 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_EnableOpts(CLK_MX_LCD, true, true, 1);
/* 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_Disable(CLK_MX_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 = {0};
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 */
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 *)&pal_entry);
}
}

View File

@@ -0,0 +1,151 @@
/*
* @brief LPC18xx/43xx OTP Controller driver
*
* @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 "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
#define BOOTROM_BASE 0x10400100
#define OTP_API_TABLE_OFFSET 0x1
static unsigned long *BOOTROM_API_TABLE;
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
static uint32_t (*Otp_ProgBootSrc)(CHIP_OTP_BOOT_SRC_T BootSrc);
static uint32_t (*Otp_ProgJTAGDis)(void);
static uint32_t (*Otp_ProgUSBID)(uint32_t ProductID, uint32_t VendorID);
static uint32_t (*Otp_ProgGP0)(uint32_t Data, uint32_t Mask);
static uint32_t (*Otp_ProgGP1)(uint32_t Data, uint32_t Mask);
static uint32_t (*Otp_ProgGP2)(uint32_t Data, uint32_t Mask);
static uint32_t (*Otp_ProgKey1)(uint8_t *key);
static uint32_t (*Otp_ProgKey2)(uint8_t *key);
static uint32_t (*Otp_GenRand)(void);
/*****************************************************************************
* Public functions
****************************************************************************/
/* CHIP OTP Initialisation function */
uint32_t Chip_OTP_Init(void)
{
uint32_t (*ROM_otp_Init)(void);
BOOTROM_API_TABLE = *((unsigned long * *) BOOTROM_BASE + OTP_API_TABLE_OFFSET);
ROM_otp_Init = (uint32_t (*)(void))BOOTROM_API_TABLE[0];
Otp_ProgBootSrc = (uint32_t (*)(CHIP_OTP_BOOT_SRC_T BootSrc))BOOTROM_API_TABLE[1];
Otp_ProgJTAGDis = (uint32_t (*)(void))BOOTROM_API_TABLE[2];
Otp_ProgUSBID = (uint32_t (*)(uint32_t ProductID, uint32_t VendorID))BOOTROM_API_TABLE[3];
Otp_ProgGP0 = (uint32_t (*)(uint32_t Data, uint32_t Mask))BOOTROM_API_TABLE[8];
Otp_ProgGP1 = (uint32_t (*)(uint32_t Data, uint32_t Mask))BOOTROM_API_TABLE[9];
Otp_ProgGP2 = (uint32_t (*)(uint32_t Data, uint32_t Mask))BOOTROM_API_TABLE[10];
Otp_ProgKey1 = (uint32_t (*)(uint8_t *key))BOOTROM_API_TABLE[11];
Otp_ProgKey2 = (uint32_t (*)(uint8_t *key))BOOTROM_API_TABLE[12];
Otp_GenRand = (uint32_t (*)(void))BOOTROM_API_TABLE[13];
return ROM_otp_Init();
}
/* Program boot source in OTP Controller */
uint32_t Chip_OTP_ProgBootSrc(CHIP_OTP_BOOT_SRC_T BootSrc)
{
return Otp_ProgBootSrc(BootSrc);
}
/* Program the JTAG bit in OTP Controller */
uint32_t Chip_OTP_ProgJTAGDis(void)
{
return Otp_ProgJTAGDis();
}
/* Program USB ID in OTP Controller */
uint32_t Chip_OTP_ProgUSBID(uint32_t ProductID, uint32_t VendorID)
{
return Otp_ProgUSBID(ProductID, VendorID);
}
/* Program OTP GP Word memory */
uint32_t Chip_OTP_ProgGPWord(uint32_t WordNum, uint32_t Data, uint32_t Mask)
{
uint32_t status;
switch (WordNum) {
case 1:
status = Otp_ProgGP1(Data, Mask);
break;
case 2:
status = Otp_ProgGP2(Data, Mask);
break;
case 0:
default:
status = Otp_ProgGP0(Data, Mask);
break;
}
return status;
}
/* Program AES Key */
uint32_t Chip_OTP_ProgKey(uint32_t KeyNum, uint8_t *key)
{
uint32_t status;
if (KeyNum) {
status = Otp_ProgKey2(key);
}
else {
status = Otp_ProgKey1(key);
}
return status;
}
/* Generate Random Number using HW Random Number Generator */
uint32_t Chip_OTP_GenRand(void)
{
return Otp_GenRand();
}

View File

@@ -0,0 +1,54 @@
/*
* @brief LPC18xx/43xx Pin Interrupt and Pattern Match driver
*
* @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 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"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/

View File

@@ -0,0 +1,75 @@
/*
* @brief LPC18xx/43xx Power Management Controller driver
*
* @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 "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
/* Set to sleep mode */
void Chip_PMC_Sleep(void)
{
/* Sleep Mode*/
__WFI();
}
/* Set power state */
void Chip_PMC_Set_PwrState(CHIP_PMC_PWR_STATE_T PwrState)
{
/* Set Deep sleep mode bit in System Control register of M4 core */
SCB->SCR = 0x4;
/* Set power state in PMC */
LPC_PMC->PD0_SLEEP0_MODE = (uint32_t) PwrState;
__WFI();
}

View File

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

View File

@@ -0,0 +1,103 @@
/*
* @brief LPC18xx/43xx RITimer chip driver
*
* @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 "chip.h"
/*****************************************************************************
* 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_EnableOpts(CLK_MX_RITIMER, true, true, 1);
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_Disable(CLK_MX_RITIMER);
}
/* 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_GetRate(CLK_MX_RITIMER) / 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;
}

View File

@@ -0,0 +1,226 @@
/*
* @brief LPC18xx/43xx RTC driver
*
* @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 "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_RTCEnable();
/* 2-Second delay after enabling RTC clock */
LPC_ATIMER->DOWNCOUNTER = 2048;
while (LPC_ATIMER->DOWNCOUNTER);
/* 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;
}
/* Reset clock tick counter in the RTC peripheral */
void Chip_RTC_ResetClockTickCounter(LPC_RTC_T *pRTC)
{
/* Reset RTC clock*/
pRTC->CCR |= RTC_CCR_CTCRST;
while (!(pRTC->CCR & RTC_CCR_CTCRST)) {}
/* Finish resetting RTC clock */
pRTC->CCR = (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) {
pRTC->CCR |= RTC_CCR_CLKEN;
} else {
pRTC->CCR = (pRTC->CCR & ~RTC_CCR_CLKEN) & RTC_CCR_BITMASK;
}
}
/* Enable/Disable Counter increment interrupt for a time type in the RTC peripheral */
void Chip_RTC_CntIncrIntConfig(LPC_RTC_T *pRTC, uint32_t cntrMask, FunctionalState NewState)
{
if (NewState == ENABLE) {
pRTC->CIIR |= cntrMask;
}
else {
pRTC->CIIR &= (~cntrMask) & RTC_AMR_CIIR_BITMASK;
while (pRTC->CIIR & cntrMask) {}
}
}
/* Enable/Disable Alarm interrupt for a time type in the RTC peripheral */
void Chip_RTC_AlarmIntConfig(LPC_RTC_T *pRTC, uint32_t alarmMask, FunctionalState NewState)
{
if (NewState == ENABLE) {
pRTC->AMR &= (~alarmMask) & RTC_AMR_CIIR_BITMASK;
}
else {
pRTC->AMR |= (alarmMask);
while ((pRTC->AMR & alarmMask) == 0) {}
}
}
/* Set full time in the RTC peripheral */
void Chip_RTC_SetFullTime(LPC_RTC_T *pRTC, RTC_TIME_T *pFullTime)
{
RTC_TIMEINDEX_T i;
uint32_t ccr_val = pRTC->CCR;
/* Temporarily disable */
if (ccr_val & RTC_CCR_CLKEN) {
pRTC->CCR = ccr_val & (~RTC_CCR_CLKEN) & RTC_CCR_BITMASK;
}
/* Date time setting */
for (i = RTC_TIMETYPE_SECOND; i < RTC_TIMETYPE_LAST; i++) {
pRTC->TIME[i] = pFullTime->time[i];
}
/* Restore to old setting */
pRTC->CCR = ccr_val;
}
/* Get full time from the RTC peripheral */
void Chip_RTC_GetFullTime(LPC_RTC_T *pRTC, RTC_TIME_T *pFullTime)
{
RTC_TIMEINDEX_T i;
uint32_t secs = 0xFF;
/* Read full time, but verify second tick didn't change during the read. If
it did, re-read the time again so it will be consistent across all fields. */
while (secs != pRTC->TIME[RTC_TIMETYPE_SECOND]) {
secs = pFullTime->time[RTC_TIMETYPE_SECOND] = pRTC->TIME[RTC_TIMETYPE_SECOND];
for (i = RTC_TIMETYPE_MINUTE; i < RTC_TIMETYPE_LAST; i++) {
pFullTime->time[i] = pRTC->TIME[i];
}
}
}
/* Set full alarm time in the RTC peripheral */
void Chip_RTC_SetFullAlarmTime(LPC_RTC_T *pRTC, RTC_TIME_T *pFullTime)
{
RTC_TIMEINDEX_T i;
for (i = RTC_TIMETYPE_SECOND; i < RTC_TIMETYPE_LAST; i++) {
pRTC->ALRM[i] = pFullTime->time[i];
}
}
/* Get full alarm time in the RTC peripheral */
void Chip_RTC_GetFullAlarmTime(LPC_RTC_T *pRTC, RTC_TIME_T *pFullTime)
{
RTC_TIMEINDEX_T i;
for (i = RTC_TIMETYPE_SECOND; i < RTC_TIMETYPE_LAST; i++) {
pFullTime->time[i] = pRTC->ALRM[i];
}
}
/* Enable/Disable calibration counter in the RTC peripheral */
void Chip_RTC_CalibCounterCmd(LPC_RTC_T *pRTC, FunctionalState NewState)
{
if (NewState == ENABLE) {
do {
pRTC->CCR &= (~RTC_CCR_CCALEN) & RTC_CCR_BITMASK;
} while (pRTC->CCR & RTC_CCR_CCALEN);
}
else {
pRTC->CCR |= RTC_CCR_CCALEN;
}
}
#if RTC_EV_SUPPORT
/* Get first timestamp value */
void Chip_RTC_EV_GetFirstTimeStamp(LPC_RTC_T *pRTC, RTC_EV_CHANNEL_T ch, RTC_EV_TIMESTAMP_T *pTimeStamp)
{
pTimeStamp->sec = RTC_ER_TIMESTAMP_SEC(pRTC->ERFIRSTSTAMP[ch]);
pTimeStamp->min = RTC_ER_TIMESTAMP_MIN(pRTC->ERFIRSTSTAMP[ch]);
pTimeStamp->hour = RTC_ER_TIMESTAMP_HOUR(pRTC->ERFIRSTSTAMP[ch]);
pTimeStamp->dayofyear = RTC_ER_TIMESTAMP_DOY(pRTC->ERFIRSTSTAMP[ch]);
}
/* Get last timestamp value */
void Chip_RTC_EV_GetLastTimeStamp(LPC_RTC_T *pRTC, RTC_EV_CHANNEL_T ch, RTC_EV_TIMESTAMP_T *pTimeStamp)
{
pTimeStamp->sec = RTC_ER_TIMESTAMP_SEC(pRTC->ERLASTSTAMP[ch]);
pTimeStamp->min = RTC_ER_TIMESTAMP_MIN(pRTC->ERLASTSTAMP[ch]);
pTimeStamp->hour = RTC_ER_TIMESTAMP_HOUR(pRTC->ERLASTSTAMP[ch]);
pTimeStamp->dayofyear = RTC_ER_TIMESTAMP_DOY(pRTC->ERLASTSTAMP[ch]);
}
#endif /*RTC_EV_SUPPORT*/

View File

@@ -0,0 +1,93 @@
/*
* @brief LPC18xx/43xx State Configurable Timer driver
*
* @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 "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initialize SCT */
void Chip_SCT_Init(LPC_SCT_T *pSCT)
{
Chip_Clock_EnableOpts(CLK_MX_SCT, true, true, 1);
}
/* Shutdown SCT */
void Chip_SCT_DeInit(LPC_SCT_T *pSCT)
{
Chip_Clock_Disable(CLK_MX_SCT);
}
/* Set/Clear SCT control register */
void Chip_SCT_SetClrControl(LPC_SCT_T *pSCT, uint32_t value, FunctionalState ena)
{
uint32_t tem;
tem = pSCT->CTRL_U;
if (ena == ENABLE) {
tem |= value;
}
else {
tem &= (~value);
}
pSCT->CTRL_U = tem;
}
/* Set Conflict resolution */
void Chip_SCT_SetConflictResolution(LPC_SCT_T *pSCT, uint8_t outnum, uint8_t value)
{
uint32_t tem;
tem = pSCT->RES;
tem &= ~(0x03 << (2 * outnum));
tem |= (value << (2 * outnum));
pSCT->RES = tem;
}

View File

@@ -0,0 +1,93 @@
/*
* @brief LPC18xx_43xx State Configurable Timer PWM driver
*
* @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
****************************************************************************/
/* Setup the OUTPUT pin corresponding to the PWM index */
void Chip_SCTPWM_SetOutPin(LPC_SCT_T *pSCT, uint8_t index, uint8_t pin)
{
int ix = (int) index;
pSCT->EVENT[ix].CTRL = index | (1 << 12);
pSCT->EVENT[ix].STATE = 1;
pSCT->OUT[pin].SET = 1;
pSCT->OUT[pin].CLR = 1 << ix;
/* Clear the output in-case of conflict */
pSCT->RES = (pSCT->RES & ~(3 << (pin << 1))) | (0x01 << (pin << 1));
/* Set and Clear do not depend on direction */
pSCT->OUTPUTDIRCTRL = (pSCT->OUTPUTDIRCTRL & ~(3 << (pin << 1)));
}
/* Set the PWM frequency */
void Chip_SCTPWM_SetRate(LPC_SCT_T *pSCT, uint32_t freq)
{
uint32_t rate;
rate = Chip_Clock_GetRate(CLK_MX_SCT) / freq;;
/* Stop the SCT before configuration */
Chip_SCTPWM_Stop(pSCT);
/* Set MATCH0 for max limit */
pSCT->REGMODE_L = 0;
pSCT->REGMODE_H = 0;
Chip_SCT_SetMatchCount(pSCT, SCT_MATCH_0, 0);
Chip_SCT_SetMatchReload(pSCT, SCT_MATCH_0, rate);
pSCT->EVENT[0].CTRL = 1 << 12;
pSCT->EVENT[0].STATE = 1;
pSCT->LIMIT_L = 1;
/* Set SCT Counter to count 32-bits and reset to 0 after reaching MATCH0 */
Chip_SCT_Config(pSCT, SCT_CONFIG_32BIT_COUNTER | SCT_CONFIG_AUTOLIMIT_L);
}

View File

@@ -0,0 +1,229 @@
/*
* @brief LPC18xx/43xx SD/SDIO driver
*
* @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 "chip.h"
#include "string.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initializes the SD/MMC controller */
void Chip_SDIF_Init(LPC_SDMMC_T *pSDMMC)
{
/* Enable SDIO module clock */
Chip_Clock_EnableOpts(CLK_MX_SDIO, true, true, 1);
/* Software reset */
pSDMMC->BMOD = MCI_BMOD_SWR;
/* reset all blocks */
pSDMMC->CTRL = MCI_CTRL_RESET | MCI_CTRL_FIFO_RESET | MCI_CTRL_DMA_RESET;
while (pSDMMC->CTRL & (MCI_CTRL_RESET | MCI_CTRL_FIFO_RESET | MCI_CTRL_DMA_RESET)) {}
/* Internal DMA setup for control register */
pSDMMC->CTRL = MCI_CTRL_USE_INT_DMAC | MCI_CTRL_INT_ENABLE;
pSDMMC->INTMASK = 0;
/* Clear the interrupts for the host controller */
pSDMMC->RINTSTS = 0xFFFFFFFF;
/* Put in max timeout */
pSDMMC->TMOUT = 0xFFFFFFFF;
/* FIFO threshold settings for DMA, DMA burst of 4, FIFO watermark at 16 */
pSDMMC->FIFOTH = MCI_FIFOTH_DMA_MTS_4 | MCI_FIFOTH_RX_WM((SD_FIFO_SZ / 2) - 1) | MCI_FIFOTH_TX_WM(SD_FIFO_SZ / 2);
/* Enable internal DMA, burst size of 4, fixed burst */
pSDMMC->BMOD = MCI_BMOD_DE | MCI_BMOD_PBL4 | MCI_BMOD_DSL(4);
/* disable clock to CIU (needs latch) */
pSDMMC->CLKENA = 0;
pSDMMC->CLKSRC = 0;
}
/* Shutdown the SD/MMC controller */
void Chip_SDIF_DeInit(LPC_SDMMC_T *pSDMMC)
{
/* Disable the clock */
Chip_Clock_Disable(CLK_MX_SDIO);
}
/* Function to send command to Card interface unit (CIU) */
int32_t Chip_SDIF_SendCmd(LPC_SDMMC_T *pSDMMC, uint32_t cmd, uint32_t arg)
{
volatile int32_t tmo = 50;
volatile int delay;
/* set command arg reg*/
pSDMMC->CMDARG = arg;
pSDMMC->CMD = MCI_CMD_START | cmd;
/* poll untill command is accepted by the CIU */
while (--tmo && (pSDMMC->CMD & MCI_CMD_START)) {
if (tmo & 1) {
delay = 50;
}
else {
delay = 18000;
}
while (--delay > 1) {}
}
return (tmo < 1) ? 1 : 0;
}
/* Read the response from the last command */
void Chip_SDIF_GetResponse(LPC_SDMMC_T *pSDMMC, uint32_t *resp)
{
/* on this chip response is not a fifo so read all 4 regs */
resp[0] = pSDMMC->RESP0;
resp[1] = pSDMMC->RESP1;
resp[2] = pSDMMC->RESP2;
resp[3] = pSDMMC->RESP3;
}
/* Sets the SD bus clock speed */
void Chip_SDIF_SetClock(LPC_SDMMC_T *pSDMMC, uint32_t clk_rate, uint32_t speed)
{
/* compute SD/MMC clock dividers */
uint32_t div;
div = ((clk_rate / speed) + 2) >> 1;
if ((div == pSDMMC->CLKDIV) && pSDMMC->CLKENA) {
return; /* Closest speed is already set */
}
/* disable clock */
pSDMMC->CLKENA = 0;
/* User divider 0 */
pSDMMC->CLKSRC = MCI_CLKSRC_CLKDIV0;
/* inform CIU */
Chip_SDIF_SendCmd(pSDMMC, MCI_CMD_UPD_CLK | MCI_CMD_PRV_DAT_WAIT, 0);
/* set divider 0 to desired value */
pSDMMC->CLKDIV = MCI_CLOCK_DIVIDER(0, div);
/* inform CIU */
Chip_SDIF_SendCmd(pSDMMC, MCI_CMD_UPD_CLK | MCI_CMD_PRV_DAT_WAIT, 0);
/* enable clock */
pSDMMC->CLKENA = MCI_CLKEN_ENABLE;
/* inform CIU */
Chip_SDIF_SendCmd(pSDMMC, MCI_CMD_UPD_CLK | MCI_CMD_PRV_DAT_WAIT, 0);
}
/* Function to clear interrupt & FIFOs */
void Chip_SDIF_SetClearIntFifo(LPC_SDMMC_T *pSDMMC)
{
/* reset all blocks */
pSDMMC->CTRL |= MCI_CTRL_FIFO_RESET;
/* wait till resets clear */
while (pSDMMC->CTRL & MCI_CTRL_FIFO_RESET) {}
/* Clear interrupt status */
pSDMMC->RINTSTS = 0xFFFFFFFF;
}
/* Setup DMA descriptors */
void Chip_SDIF_DmaSetup(LPC_SDMMC_T *pSDMMC, sdif_device *psdif_dev, uint32_t addr, uint32_t size)
{
int i = 0;
uint32_t ctrl, maxs;
/* Reset DMA */
pSDMMC->CTRL |= MCI_CTRL_DMA_RESET | MCI_CTRL_FIFO_RESET;
while (pSDMMC->CTRL & MCI_CTRL_DMA_RESET) {}
/* Build a descriptor list using the chained DMA method */
while (size > 0) {
/* Limit size of the transfer to maximum buffer size */
maxs = size;
if (maxs > MCI_DMADES1_MAXTR) {
maxs = MCI_DMADES1_MAXTR;
}
size -= maxs;
/* Set buffer size */
psdif_dev->mci_dma_dd[i].des1 = MCI_DMADES1_BS1(maxs);
/* Setup buffer address (chained) */
psdif_dev->mci_dma_dd[i].des2 = addr + (i * MCI_DMADES1_MAXTR);
/* Setup basic control */
ctrl = MCI_DMADES0_OWN | MCI_DMADES0_CH;
if (i == 0) {
ctrl |= MCI_DMADES0_FS; /* First DMA buffer */
}
/* No more data? Then this is the last descriptor */
if (!size) {
ctrl |= MCI_DMADES0_LD;
}
else {
ctrl |= MCI_DMADES0_DIC;
}
/* Another descriptor is needed */
psdif_dev->mci_dma_dd[i].des3 = (uint32_t) &psdif_dev->mci_dma_dd[i + 1];
psdif_dev->mci_dma_dd[i].des0 = ctrl;
i++;
}
/* Set DMA derscriptor base address */
pSDMMC->DBADDR = (uint32_t) &psdif_dev->mci_dma_dd[0];
}

View File

@@ -0,0 +1,598 @@
/*
* @brief LPC18xx/43xx SD/SDIO driver
*
* @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 "chip.h"
#include "string.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/* Global instance of the current card */
static mci_card_struct *g_card_info;
/* Helper definition: all SD error conditions in the status word */
#define SD_INT_ERROR (MCI_INT_RESP_ERR | MCI_INT_RCRC | MCI_INT_DCRC | \
MCI_INT_RTO | MCI_INT_DTO | MCI_INT_HTO | MCI_INT_FRUN | MCI_INT_HLE | \
MCI_INT_SBE | MCI_INT_EBE)
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/* Function to execute a command */
static int32_t sdmmc_execute_command(LPC_SDMMC_T *pSDMMC, uint32_t cmd, uint32_t arg, uint32_t wait_status)
{
int32_t step = (cmd & CMD_BIT_APP) ? 2 : 1;
int32_t status = 0;
uint32_t cmd_reg = 0;
if (!wait_status) {
wait_status = (cmd & CMD_MASK_RESP) ? MCI_INT_CMD_DONE : MCI_INT_DATA_OVER;
}
/* Clear the interrupts & FIFOs*/
if (cmd & CMD_BIT_DATA) {
Chip_SDIF_SetClearIntFifo(pSDMMC);
}
/* also check error conditions */
wait_status |= MCI_INT_EBE | MCI_INT_SBE | MCI_INT_HLE | MCI_INT_RTO | MCI_INT_RCRC | MCI_INT_RESP_ERR;
if (wait_status & MCI_INT_DATA_OVER) {
wait_status |= MCI_INT_FRUN | MCI_INT_HTO | MCI_INT_DTO | MCI_INT_DCRC;
}
while (step) {
Chip_SDIF_SetClock(pSDMMC, Chip_Clock_GetBaseClocktHz(CLK_BASE_SDIO), g_card_info->card_info.speed);
/* Clear the interrupts */
Chip_SDIF_ClrIntStatus(pSDMMC, 0xFFFFFFFF);
g_card_info->card_info.evsetup_cb((void *) &wait_status);
switch (step) {
case 1: /* Execute command */
cmd_reg = ((cmd & CMD_MASK_CMD) >> CMD_SHIFT_CMD) |
((cmd & CMD_BIT_INIT) ? MCI_CMD_INIT : 0) |
((cmd & CMD_BIT_DATA) ? (MCI_CMD_DAT_EXP | MCI_CMD_PRV_DAT_WAIT) : 0) |
(((cmd & CMD_MASK_RESP) == CMD_RESP_R2) ? MCI_CMD_RESP_LONG : 0) |
((cmd & CMD_MASK_RESP) ? MCI_CMD_RESP_EXP : 0) |
((cmd & CMD_BIT_WRITE) ? MCI_CMD_DAT_WR : 0) |
((cmd & CMD_BIT_STREAM) ? MCI_CMD_STRM_MODE : 0) |
((cmd & CMD_BIT_BUSY) ? MCI_CMD_STOP : 0) |
((cmd & CMD_BIT_AUTO_STOP) ? MCI_CMD_SEND_STOP : 0) |
MCI_CMD_START;
/* wait for previos data finsh for select/deselect commands */
if (((cmd & CMD_MASK_CMD) >> CMD_SHIFT_CMD) == MMC_SELECT_CARD) {
cmd_reg |= MCI_CMD_PRV_DAT_WAIT;
}
/* wait for command to be accepted by CIU */
if (Chip_SDIF_SendCmd(pSDMMC, cmd_reg, arg) == 0) {
--step;
}
break;
case 0:
return 0;
case 2: /* APP prefix */
cmd_reg = MMC_APP_CMD | MCI_CMD_RESP_EXP |
((cmd & CMD_BIT_INIT) ? MCI_CMD_INIT : 0) |
MCI_CMD_START;
if (Chip_SDIF_SendCmd(pSDMMC, cmd_reg, g_card_info->card_info.rca << 16) == 0) {
--step;
}
break;
}
/* wait for command response */
status = g_card_info->card_info.waitfunc_cb();
/* We return an error if there is a timeout, even if we've fetched a response */
if (status & SD_INT_ERROR) {
return status;
}
if (status & MCI_INT_CMD_DONE) {
switch (cmd & CMD_MASK_RESP) {
case 0:
break;
case CMD_RESP_R1:
case CMD_RESP_R3:
case CMD_RESP_R2:
Chip_SDIF_GetResponse(pSDMMC, &g_card_info->card_info.response[0]);
break;
}
}
}
return 0;
}
/* Checks whether card is acquired properly or not */
static int32_t prv_card_acquired(void)
{
return g_card_info->card_info.cid[0] != 0;
}
/* Helper function to get a bit field withing multi-word buffer. Used to get
fields with-in CSD & EXT-CSD */
static uint32_t prv_get_bits(int32_t start, int32_t end, uint32_t *data)
{
uint32_t v;
uint32_t i = end >> 5;
uint32_t j = start & 0x1f;
if (i == (start >> 5)) {
v = (data[i] >> j);
}
else {
v = ((data[i] << (32 - j)) | (data[start >> 5] >> j));
}
return v & ((1 << (end - start + 1)) - 1);
}
/* Function to process the CSD & EXT-CSD of the card */
static void prv_process_csd(LPC_SDMMC_T *pSDMMC)
{
int32_t status = 0;
int32_t c_size = 0;
int32_t c_size_mult = 0;
int32_t mult = 0;
/* compute block length based on CSD response */
g_card_info->card_info.block_len = 1 << prv_get_bits(80, 83, g_card_info->card_info.csd);
if ((g_card_info->card_info.card_type & CARD_TYPE_HC) && (g_card_info->card_info.card_type & CARD_TYPE_SD)) {
/* See section 5.3.3 CSD Register (CSD Version 2.0) of SD2.0 spec an explanation for the calculation of these values */
c_size = prv_get_bits(48, 69, (uint32_t *) g_card_info->card_info.csd) + 1;
g_card_info->card_info.blocknr = c_size << 10; /* 512 byte blocks */
}
else {
/* See section 5.3 of the 4.1 revision of the MMC specs for an explanation for the calculation of these values */
c_size = prv_get_bits(62, 73, (uint32_t *) g_card_info->card_info.csd);
c_size_mult = prv_get_bits(47, 49, (uint32_t *) g_card_info->card_info.csd);
mult = 1 << (c_size_mult + 2);
g_card_info->card_info.blocknr = (c_size + 1) * mult;
/* adjust blocknr to 512/block */
if (g_card_info->card_info.block_len > MMC_SECTOR_SIZE) {
g_card_info->card_info.blocknr = g_card_info->card_info.blocknr * (g_card_info->card_info.block_len >> 9);
}
/* get extended CSD for newer MMC cards CSD spec >= 4.0*/
if (((g_card_info->card_info.card_type & CARD_TYPE_SD) == 0) &&
(prv_get_bits(122, 125, (uint32_t *) g_card_info->card_info.csd) >= 4)) {
/* put card in trans state */
status = sdmmc_execute_command(pSDMMC, CMD_SELECT_CARD, g_card_info->card_info.rca << 16, 0);
/* set block size and byte count */
Chip_SDIF_SetBlkSizeByteCnt(pSDMMC, MMC_SECTOR_SIZE);
/* send EXT_CSD command */
Chip_SDIF_DmaSetup(pSDMMC,
&g_card_info->sdif_dev,
(uint32_t) g_card_info->card_info.ext_csd,
MMC_SECTOR_SIZE);
status = sdmmc_execute_command(pSDMMC, CMD_SEND_EXT_CSD, 0, 0 | MCI_INT_DATA_OVER);
if ((status & SD_INT_ERROR) == 0) {
/* check EXT_CSD_VER is greater than 1.1 */
if ((g_card_info->card_info.ext_csd[48] & 0xFF) > 1) {
g_card_info->card_info.blocknr = g_card_info->card_info.ext_csd[53];/* bytes 212:215 represent sec count */
}
/* switch to 52MHz clock if card type is set to 1 or else set to 26MHz */
if ((g_card_info->card_info.ext_csd[49] & 0xFF) == 1) {
/* for type 1 MMC cards high speed is 52MHz */
g_card_info->card_info.speed = MMC_HIGH_BUS_MAX_CLOCK;
}
else {
/* for type 0 MMC cards high speed is 26MHz */
g_card_info->card_info.speed = MMC_LOW_BUS_MAX_CLOCK;
}
}
}
}
g_card_info->card_info.device_size = (uint64_t) g_card_info->card_info.blocknr << 9; /* blocknr * 512 */
}
/* Puts current selected card in trans state */
static int32_t prv_set_trans_state(LPC_SDMMC_T *pSDMMC)
{
uint32_t status;
/* get current state of the card */
status = sdmmc_execute_command(pSDMMC, CMD_SEND_STATUS, g_card_info->card_info.rca << 16, 0);
if (status & MCI_INT_RTO) {
/* unable to get the card state. So return immediatly. */
return -1;
}
/* check card state in response */
status = R1_CURRENT_STATE(g_card_info->card_info.response[0]);
switch (status) {
case SDMMC_STBY_ST:
/* put card in 'Trans' state */
status = sdmmc_execute_command(pSDMMC, CMD_SELECT_CARD, g_card_info->card_info.rca << 16, 0);
if (status != 0) {
/* unable to put the card in Trans state. So return immediatly. */
return -1;
}
break;
case SDMMC_TRAN_ST:
/*do nothing */
break;
default:
/* card shouldn't be in other states so return */
return -1;
}
return 0;
}
/* Sets card data width and block size */
static int32_t prv_set_card_params(LPC_SDMMC_T *pSDMMC)
{
int32_t status;
#if SDIO_BUS_WIDTH > 1
if (g_card_info->card_info.card_type & CARD_TYPE_SD) {
status = sdmmc_execute_command(pSDMMC, CMD_SD_SET_WIDTH, 2, 0);
if (status != 0) {
return -1;
}
/* if positive response */
Chip_SDIF_SetCardType(pSDMMC, MCI_CTYPE_4BIT);
}
#elif SDIO_BUS_WIDTH > 4
#error 8-bit mode not supported yet!
#endif
/* set block length */
Chip_SDIF_SetBlkSize(pSDMMC, MMC_SECTOR_SIZE);
status = sdmmc_execute_command(pSDMMC, CMD_SET_BLOCKLEN, MMC_SECTOR_SIZE, 0);
if (status != 0) {
return -1;
}
return 0;
}
/*****************************************************************************
* Public functions
****************************************************************************/
/* Get card's current state (idle, transfer, program, etc.) */
int32_t Chip_SDMMC_GetState(LPC_SDMMC_T *pSDMMC)
{
uint32_t status;
/* get current state of the card */
status = sdmmc_execute_command(pSDMMC, CMD_SEND_STATUS, g_card_info->card_info.rca << 16, 0);
if (status & MCI_INT_RTO) {
return -1;
}
/* check card state in response */
return (int32_t) R1_CURRENT_STATE(g_card_info->card_info.response[0]);
}
/* Function to enumerate the SD/MMC/SDHC/MMC+ cards */
uint32_t Chip_SDMMC_Acquire(LPC_SDMMC_T *pSDMMC, mci_card_struct *pcardinfo)
{
int32_t status;
int32_t tries = 0;
uint32_t ocr = OCR_VOLTAGE_RANGE_MSK;
uint32_t r;
int32_t state = 0;
uint32_t command = 0;
g_card_info = pcardinfo;
/* clear card type */
Chip_SDIF_SetCardType(pSDMMC, 0);
/* set high speed for the card as 20MHz */
g_card_info->card_info.speed = MMC_MAX_CLOCK;
status = sdmmc_execute_command(pSDMMC, CMD_IDLE, 0, MCI_INT_CMD_DONE);
while (state < 100) {
switch (state) {
case 0: /* Setup for SD */
/* check if it is SDHC card */
status = sdmmc_execute_command(pSDMMC, CMD_SD_SEND_IF_COND, SD_SEND_IF_ARG, 0);
if (!(status & MCI_INT_RTO)) {
/* check response has same echo pattern */
if ((g_card_info->card_info.response[0] & SD_SEND_IF_ECHO_MSK) == SD_SEND_IF_RESP) {
ocr |= OCR_HC_CCS;
}
}
++state;
command = CMD_SD_OP_COND;
tries = INIT_OP_RETRIES;
/* assume SD card */
g_card_info->card_info.card_type |= CARD_TYPE_SD;
g_card_info->card_info.speed = SD_MAX_CLOCK;
break;
case 10: /* Setup for MMC */
/* start fresh for MMC crds */
g_card_info->card_info.card_type &= ~CARD_TYPE_SD;
status = sdmmc_execute_command(pSDMMC, CMD_IDLE, 0, MCI_INT_CMD_DONE);
command = CMD_MMC_OP_COND;
tries = INIT_OP_RETRIES;
ocr |= OCR_HC_CCS;
++state;
/* for MMC cards high speed is 20MHz */
g_card_info->card_info.speed = MMC_MAX_CLOCK;
break;
case 1:
case 11:
status = sdmmc_execute_command(pSDMMC, command, 0, 0);
if (status & MCI_INT_RTO) {
state += 9; /* Mode unavailable */
}
else {
++state;
}
break;
case 2: /* Initial OCR check */
case 12:
ocr = g_card_info->card_info.response[0] | (ocr & OCR_HC_CCS);
if (ocr & OCR_ALL_READY) {
++state;
}
else {
state += 2;
}
break;
case 3: /* Initial wait for OCR clear */
case 13:
while ((ocr & OCR_ALL_READY) && --tries > 0) {
g_card_info->card_info.msdelay_func(MS_ACQUIRE_DELAY);
status = sdmmc_execute_command(pSDMMC, command, 0, 0);
ocr = g_card_info->card_info.response[0] | (ocr & OCR_HC_CCS);
}
if (ocr & OCR_ALL_READY) {
state += 7;
}
else {
++state;
}
break;
case 14:
/* for MMC cards set high capacity bit */
ocr |= OCR_HC_CCS;
case 4: /* Assign OCR */
tries = SET_OP_RETRIES;
ocr &= OCR_VOLTAGE_RANGE_MSK | OCR_HC_CCS; /* Mask for the bits we care about */
do {
g_card_info->card_info.msdelay_func(MS_ACQUIRE_DELAY);
status = sdmmc_execute_command(pSDMMC, command, ocr, 0);
r = g_card_info->card_info.response[0];
} while (!(r & OCR_ALL_READY) && --tries > 0);
if (r & OCR_ALL_READY) {
/* is it high capacity card */
g_card_info->card_info.card_type |= (r & OCR_HC_CCS);
++state;
}
else {
state += 6;
}
break;
case 5: /* CID polling */
case 15:
status = sdmmc_execute_command(pSDMMC, CMD_ALL_SEND_CID, 0, 0);
memcpy(&g_card_info->card_info.cid, &g_card_info->card_info.response[0], 16);
++state;
break;
case 6: /* RCA send, for SD get RCA */
status = sdmmc_execute_command(pSDMMC, CMD_SD_SEND_RCA, 0, 0);
g_card_info->card_info.rca = (g_card_info->card_info.response[0]) >> 16;
++state;
break;
case 16: /* RCA assignment for MMC set to 1 */
g_card_info->card_info.rca = 1;
status = sdmmc_execute_command(pSDMMC, CMD_MMC_SET_RCA, g_card_info->card_info.rca << 16, 0);
++state;
break;
case 7:
case 17:
status = sdmmc_execute_command(pSDMMC, CMD_SEND_CSD, g_card_info->card_info.rca << 16, 0);
memcpy(&g_card_info->card_info.csd, &g_card_info->card_info.response[0], 16);
state = 100;
break;
default:
state += 100; /* break from while loop */
break;
}
}
/* Compute card size, block size and no. of blocks based on CSD response recived. */
if (prv_card_acquired()) {
prv_process_csd(pSDMMC);
/* Setup card data width and block size (once) */
if (prv_set_trans_state(pSDMMC) != 0) {
return 0;
}
if (prv_set_card_params(pSDMMC) != 0) {
return 0;
}
}
return prv_card_acquired();
}
/* Get the device size of SD/MMC card (after enumeration) */
uint64_t Chip_SDMMC_GetDeviceSize(LPC_SDMMC_T *pSDMMC)
{
return g_card_info->card_info.device_size;
}
/* Get the number of blocks in SD/MMC card (after enumeration) */
int32_t Chip_SDMMC_GetDeviceBlocks(LPC_SDMMC_T *pSDMMC)
{
return g_card_info->card_info.blocknr;
}
/* Performs the read of data from the SD/MMC card */
int32_t Chip_SDMMC_ReadBlocks(LPC_SDMMC_T *pSDMMC, void *buffer, int32_t start_block, int32_t num_blocks)
{
int32_t cbRead = (num_blocks) * MMC_SECTOR_SIZE;
int32_t status = 0;
int32_t index;
/* if card is not acquired return immediately */
if (( start_block < 0) || ( (start_block + num_blocks) > g_card_info->card_info.blocknr) ) {
return 0;
}
/* put card in trans state */
if (prv_set_trans_state(pSDMMC) != 0) {
return 0;
}
/* set number of bytes to read */
Chip_SDIF_SetByteCnt(pSDMMC, cbRead);
/* if high capacity card use block indexing */
if (g_card_info->card_info.card_type & CARD_TYPE_HC) {
index = start_block;
}
else { /*fix at 512 bytes*/
index = start_block << 9; // \* g_card_info->card_info.block_len;
}
Chip_SDIF_DmaSetup(pSDMMC, &g_card_info->sdif_dev, (uint32_t) buffer, cbRead);
/* Select single or multiple read based on number of blocks */
if (num_blocks == 1) {
status = sdmmc_execute_command(pSDMMC, CMD_READ_SINGLE, index, 0 | MCI_INT_DATA_OVER);
}
else {
status = sdmmc_execute_command(pSDMMC, CMD_READ_MULTIPLE, index, 0 | MCI_INT_DATA_OVER);
}
if (status != 0) {
cbRead = 0;
}
/*Wait for card program to finish*/
while (Chip_SDMMC_GetState(pSDMMC) != SDMMC_TRAN_ST) {}
return cbRead;
}
/* Performs write of data to the SD/MMC card */
int32_t Chip_SDMMC_WriteBlocks(LPC_SDMMC_T *pSDMMC, void *buffer, int32_t start_block, int32_t num_blocks)
{
int32_t cbWrote = num_blocks * MMC_SECTOR_SIZE;
int32_t status;
int32_t index;
/* if card is not acquired return immediately */
if (( start_block < 0) || ( (start_block + num_blocks) > g_card_info->card_info.blocknr) ) {
return 0;
}
/*Wait for card program to finish*/
while (Chip_SDMMC_GetState(pSDMMC) != SDMMC_TRAN_ST) {}
/* put card in trans state */
if (prv_set_trans_state(pSDMMC) != 0) {
return 0;
}
/* set number of bytes to write */
Chip_SDIF_SetByteCnt(pSDMMC, cbWrote);
/* if high capacity card use block indexing */
if (g_card_info->card_info.card_type & CARD_TYPE_HC) {
index = start_block;
}
else { /*fix at 512 bytes*/
index = start_block << 9; // * g_card_info->card_info.block_len;
}
Chip_SDIF_DmaSetup(pSDMMC, &g_card_info->sdif_dev, (uint32_t) buffer, cbWrote);
/* Select single or multiple write based on number of blocks */
if (num_blocks == 1) {
status = sdmmc_execute_command(pSDMMC, CMD_WRITE_SINGLE, index, 0 | MCI_INT_DATA_OVER);
}
else {
status = sdmmc_execute_command(pSDMMC, CMD_WRITE_MULTIPLE, index, 0 | MCI_INT_DATA_OVER);
}
/*Wait for card program to finish*/
while (Chip_SDMMC_GetState(pSDMMC) != SDMMC_TRAN_ST) {}
if (status != 0) {
cbWrote = 0;
}
return cbWrote;
}

View File

@@ -0,0 +1,233 @@
/*
* @brief LPC43xx SPI driver
*
* @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 "chip.h"
#if defined(CHIP_LPC43XX)
/*****************************************************************************
* 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_GetRate(CLK_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_Enable(CLK_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_Disable(CLK_SPI);
}
#endif

View File

@@ -0,0 +1,475 @@
/*
* @brief LPC18xx/43xx SSP driver
*
* @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 "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 index for the register interface */
STATIC CHIP_CCU_CLK_T Chip_SSP_GetClockIndex(LPC_SSP_T *pSSP)
{
CHIP_CCU_CLK_T clkSSP;
if (pSSP == LPC_SSP1) {
clkSSP = CLK_MX_SSP1;
}
else {
clkSSP = CLK_MX_SSP0;
}
return clkSSP;
}
/* Returns clock index for the peripheral block */
STATIC CHIP_CCU_CLK_T Chip_SSP_GetPeriphClockIndex(LPC_SSP_T *pSSP)
{
CHIP_CCU_CLK_T clkSSP;
if (pSSP == LPC_SSP1) {
clkSSP = CLK_APB2_SSP1;
}
else {
clkSSP = CLK_APB0_SSP0;
}
return clkSSP;
}
/*****************************************************************************
* 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, const 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 {
const 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;
ssp_clk = Chip_Clock_GetRate(Chip_SSP_GetPeriphClockIndex(pSSP));
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_Enable(Chip_SSP_GetClockIndex(pSSP));
Chip_Clock_Enable(Chip_SSP_GetPeriphClockIndex(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_Disable(Chip_SSP_GetPeriphClockIndex(pSSP));
Chip_Clock_Disable(Chip_SSP_GetClockIndex(pSSP));
}

View File

@@ -0,0 +1,112 @@
/*
* @brief LPC18xx/43xx 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 */
const uint32_t prescaleDivisor = 8;
Chip_TIMER_Init(LPC_TIMER0);
Chip_TIMER_PrescaleSet(LPC_TIMER0, prescaleDivisor - 1);
Chip_TIMER_Enable(LPC_TIMER0);
/* Pre-compute tick rate. */
ticksPerSecond = Chip_Clock_GetRate(CLK_MX_TIMER0) / prescaleDivisor;
ticksPerMs = ticksPerSecond / 1000;
ticksPerUs = ticksPerSecond / 1000000;
}
/* Start a stopwatch */
uint32_t StopWatch_Start(void)
{
/* Return the current timer count. */
return Chip_TIMER_ReadCount(LPC_TIMER0);
}
/* Returns number of ticks per second of the stopwatch timer */
uint32_t StopWatch_TicksPerSecond(void)
{
return ticksPerSecond;
}
/* Converts from stopwatch ticks to mS. */
uint32_t StopWatch_TicksToMs(uint32_t ticks)
{
return ticks / ticksPerMs;
}
/* Converts from stopwatch ticks to uS. */
uint32_t StopWatch_TicksToUs(uint32_t ticks)
{
return ticks / ticksPerUs;
}
/* Converts from mS to stopwatch ticks. */
uint32_t StopWatch_MsToTicks(uint32_t mS)
{
return mS * ticksPerMs;
}
/* Converts from uS to stopwatch ticks. */
uint32_t StopWatch_UsToTicks(uint32_t uS)
{
return uS * ticksPerUs;
}

View File

@@ -0,0 +1,166 @@
/*
* @brief LPC18xx/LPC43xx Chip specific SystemInit
*
* @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
****************************************************************************/
/* Structure for initial base clock states */
struct CLK_BASE_STATES {
CHIP_CGU_BASE_CLK_T clk; /* Base clock */
CHIP_CGU_CLKIN_T clkin; /* Base clock source, see UM for allowable souorces per base clock */
bool autoblock_enab; /* Set to true to enable autoblocking on frequency change */
bool powerdn; /* Set to true if the base clock is initially powered down */
};
static const struct CLK_BASE_STATES InitClkStates[] = {
{CLK_BASE_SAFE, CLKIN_IRC, true, false},
{CLK_BASE_APB1, CLKIN_MAINPLL, true, false},
{CLK_BASE_APB3, CLKIN_MAINPLL, true, false},
{CLK_BASE_USB0, CLKIN_USBPLL, true, true},
#if defined(CHIP_LPC43XX)
{CLK_BASE_PERIPH, CLKIN_MAINPLL, true, false},
{CLK_BASE_SPI, CLKIN_MAINPLL, true, false},
{CLK_BASE_ADCHS, CLKIN_MAINPLL, true, true},
#endif
{CLK_BASE_SDIO, CLKIN_MAINPLL, true, false},
{CLK_BASE_SSP0, CLKIN_MAINPLL, true, false},
{CLK_BASE_SSP1, CLKIN_MAINPLL, true, false},
{CLK_BASE_UART0, CLKIN_MAINPLL, true, false},
{CLK_BASE_UART1, CLKIN_MAINPLL, true, false},
{CLK_BASE_UART2, CLKIN_MAINPLL, true, false},
{CLK_BASE_UART3, CLKIN_MAINPLL, true, false},
{CLK_BASE_OUT, CLKINPUT_PD, true, false},
{CLK_BASE_APLL, CLKINPUT_PD, true, false},
{CLK_BASE_CGU_OUT0, CLKINPUT_PD, true, false},
{CLK_BASE_CGU_OUT1, CLKINPUT_PD, true, false},
};
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
/* Setup Chip Core clock */
void Chip_SetupCoreClock(CHIP_CGU_CLKIN_T clkin, uint32_t core_freq, bool setbase)
{
int i;
volatile uint32_t delay = 500;
uint32_t direct = 0, pdivide = 0;
PLL_PARAM_T ppll;
if (clkin == CLKIN_CRYSTAL) {
/* Switch main system clocking to crystal */
Chip_Clock_EnableCrystal();
}
Chip_Clock_SetBaseClock(CLK_BASE_MX, clkin, true, false);
Chip_Clock_DisableMainPLL(); /* Disable PLL */
/* Calculate the PLL Parameters */
ppll.srcin = clkin;
Chip_Clock_CalcMainPLLValue(core_freq, &ppll);
if (core_freq > 110000000UL) {
if (ppll.ctrl & (1 << 6)) {
while(1); // to run in integer mode above 110 MHz, you need to use IDIV clock to boot strap CPU to that freq
} else if (ppll.ctrl & (1 << 7)){
direct = 1;
ppll.ctrl &= ~(1 << 7);
} else {
pdivide = 1;
ppll.psel++;
}
}
/* Setup and start the PLL */
Chip_Clock_SetupMainPLL(&ppll);
/* Wait for the PLL to lock */
while(!Chip_Clock_MainPLLLocked()) {}
/* Set core clock base as PLL1 */
Chip_Clock_SetBaseClock(CLK_BASE_MX, CLKIN_MAINPLL, true, false);
if (direct) {
delay = 1000;
while(delay --){} /* Wait for approx 50 uSec -- for power supply to stabilize*/
ppll.ctrl |= 1 << 7;
Chip_Clock_SetupMainPLL(&ppll); /* Set DIRECT to operate at full frequency */
} else if (pdivide) {
delay = 1000;
while(delay --){} /* Wait for approx 50 uSec -- for power supply to stabilize */
ppll.psel--;
Chip_Clock_SetupMainPLL(&ppll); /* Set PDIV to operate at full frequency */
}
if (setbase) {
/* Setup system base clocks and initial states. This won't enable and
disable individual clocks, but sets up the base clock sources for
each individual peripheral clock. */
for (i = 0; i < (sizeof(InitClkStates) / sizeof(InitClkStates[0])); i++) {
Chip_Clock_SetBaseClock(InitClkStates[i].clk, InitClkStates[i].clkin,
InitClkStates[i].autoblock_enab, InitClkStates[i].powerdn);
}
}
}
/* Setup system clocking */
void Chip_SetupXtalClocking(void)
{
Chip_SetupCoreClock(CLKIN_CRYSTAL, MAX_CLOCK_FREQ, true);
}
/* Set up and initialize hardware prior to call to main */
void Chip_SetupIrcClocking(void)
{
Chip_SetupCoreClock(CLKIN_IRC, MAX_CLOCK_FREQ, true);
}
/* Set up and initialize hardware prior to call to main */
void Chip_SystemInit(void)
{
/* Initial internal clocking */
Chip_SetupIrcClocking();
}

View File

@@ -0,0 +1,123 @@
/*
* @brief LPC18xx/43xx 16/32-bit Timer/PWM driver
*
* @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 "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/* Returns clock index for the peripheral block */
STATIC CHIP_CCU_CLK_T Chip_TIMER_GetClockIndex(LPC_TIMER_T *pTMR)
{
CHIP_CCU_CLK_T clkTMR;
if (pTMR == LPC_TIMER3) {
clkTMR = CLK_MX_TIMER3;
}
else if (pTMR == LPC_TIMER2) {
clkTMR = CLK_MX_TIMER2;
}
else if (pTMR == LPC_TIMER1) {
clkTMR = CLK_MX_TIMER1;
}
else {
clkTMR = CLK_MX_TIMER0;
}
return clkTMR;
}
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initialize a timer */
void Chip_TIMER_Init(LPC_TIMER_T *pTMR)
{
Chip_Clock_Enable(Chip_TIMER_GetClockIndex(pTMR));
}
/* Shutdown a timer */
void Chip_TIMER_DeInit(LPC_TIMER_T *pTMR)
{
Chip_Clock_Disable(Chip_TIMER_GetClockIndex(pTMR));
}
/* Resets the timer terminal and prescale counts to 0 */
void Chip_TIMER_Reset(LPC_TIMER_T *pTMR)
{
uint32_t reg;
/* Disable timer, set terminal count to non-0 */
reg = pTMR->TCR;
pTMR->TCR = 0;
pTMR->TC = 1;
/* Reset timer counter */
pTMR->TCR = TIMER_RESET;
/* Wait for terminal count to clear */
while (pTMR->TC != 0) {}
/* Restore timer state */
pTMR->TCR = reg;
}
/* Sets external match control (MATn.matchnum) pin control */
void Chip_TIMER_ExtMatchControlSet(LPC_TIMER_T *pTMR, int8_t initial_state,
TIMER_PIN_MATCH_STATE_T matchState, int8_t matchnum)
{
uint32_t mask, reg;
/* Clear bits corresponding to selected match register */
mask = (1 << matchnum) | (0x03 << (4 + (matchnum * 2)));
reg = pTMR->EMR &= ~mask;
/* Set new configuration for selected match register */
pTMR->EMR = reg | (((uint32_t) initial_state) << matchnum) |
(((uint32_t) matchState) << (4 + (matchnum * 2)));
}

View File

@@ -0,0 +1,430 @@
/*
* @brief LPC18xx/43xx UART chip driver
*
* @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 "chip.h"
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
/* Autobaud status flag */
STATIC volatile FlagStatus ABsyncSts = RESET;
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/* UART Peripheral clocks */
static const CHIP_CCU_CLK_T UART_PClock[] = {CLK_MX_UART0, CLK_MX_UART1, CLK_MX_UART2, CLK_MX_UART3};
/* UART Bus clocks */
static const CHIP_CCU_CLK_T UART_BClock[] = {CLK_APB0_UART0, CLK_APB0_UART1, CLK_APB2_UART2, CLK_APB2_UART3};
/* Returns clock index for the peripheral block */
static int Chip_UART_GetIndex(LPC_USART_T *pUART)
{
uint32_t base = (uint32_t) pUART;
switch(base) {
case LPC_USART0_BASE:
return 0;
case LPC_UART1_BASE:
return 1;
case LPC_USART2_BASE:
return 2;
case LPC_USART3_BASE:
return 3;
default:
return 0; /* Should never come here */
}
}
/* 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);
}
}
/*****************************************************************************
* Public functions
****************************************************************************/
/* Initializes the pUART peripheral */
void Chip_UART_Init(LPC_USART_T *pUART)
{
volatile uint32_t tmp;
/* Enable UART clocking. UART base clock(s) must already be enabled */
Chip_Clock_EnableOpts(UART_PClock[Chip_UART_GetIndex(pUART)], true, true, 1);
/* 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_Disable(UART_PClock[Chip_UART_GetIndex(pUART)]);
}
/* 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 (numBytes > 0) {
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 */
clkin = Chip_Clock_GetRate(UART_BClock[Chip_UART_GetIndex(pUART)]);
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 alreadt setup for 1 in UART init */
return (clkin / div) >> 4;
}
/* 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);
}
/* Turn off interrupt if the ring buffer is empty */
if (RingBuffer_IsEmpty(pRB)) {
/* Shut down transmit */
Chip_UART_IntDisable(pUART, UART_IER_THREINT);
}
}
/* 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 baud)
{
uint32_t sdiv = 0, sm = 1, sd = 0;
uint32_t pclk, m, d;
uint32_t odiff = -1UL; /* old best diff */
/* Get base clock for the corresponding UART */
pclk = Chip_Clock_GetRate(UART_BClock[Chip_UART_GetIndex(pUART)]);
/* Loop through all possible fractional divider values */
for (m = 1; odiff && m < 16; m++) {
for (d = 0; d < m; d++) {
uint32_t diff, div;
uint64_t dval = (((uint64_t) pclk << 28) * m) / (baud * (m + d));
/* Lower 32-bit of dval has diff */
diff = (uint32_t) dval;
/* Upper 32-bit of dval has div */
div = (uint32_t) (dval >> 32);
/* Closer to next div */
if ((int)diff < 0) {
diff = -diff;
div ++;
}
/* Check if new value is worse than old or out of range */
if (odiff < diff || !div || (div >> 16) || (div < 3 && d)) {
continue;
}
/* Store the new better values */
sdiv = div;
sd = d;
sm = m;
odiff = diff;
/* On perfect match, break loop */
if(!diff) {
break;
}
}
}
/* Return 0 if a vaild divisor is not possible */
if (!sdiv) {
return 0;
}
/* Update UART registers */
Chip_UART_EnableDivisorAccess(pUART);
Chip_UART_SetDivisorLatches(pUART, UART_LOAD_DLL(sdiv), UART_LOAD_DLM(sdiv));
Chip_UART_DisableDivisorAccess(pUART);
/* Set best fractional divider */
pUART->FDR = (UART_FDR_MULVAL(sm) | UART_FDR_DIVADDVAL(sd));
/* Return actual baud rate */
return (pclk >> 4) * sm / (sdiv * (sm + sd));
}
/* UART interrupt service routine */
FlagStatus Chip_UART_GetABEOStatus(LPC_USART_T *pUART)
{
(void) pUART;
return ABsyncSts;
}
/* Start/Stop Auto Baudrate activity */
void Chip_UART_ABCmd(LPC_USART_T *pUART, uint32_t mode, bool autorestart, FunctionalState NewState)
{
uint32_t tmp = 0;
if (NewState == ENABLE) {
/* Clear DLL and DLM value */
pUART->LCR |= UART_LCR_DLAB_EN;
pUART->DLL = 0;
pUART->DLM = 0;
pUART->LCR &= ~UART_LCR_DLAB_EN;
/* FDR value must be reset to default value */
pUART->FDR = 0x10;
if (mode == UART_ACR_MODE1) {
tmp = UART_ACR_START | UART_ACR_MODE;
}
else {
tmp = UART_ACR_START;
}
if (autorestart == true) {
tmp |= UART_ACR_AUTO_RESTART;
}
pUART->ACR = tmp;
}
else {
pUART->ACR = 0;
}
}

View File

@@ -0,0 +1,84 @@
/*
* @brief LPC18xx/43xx WWDT driver
*
* @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 "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
}
/* Shutdown the Watchdog timer */
void Chip_WWDT_DeInit(LPC_WWDT_T *pWWDT)
{
}
/* 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;
}
}