added lpc18 lpcopen
This commit is contained in:
263
hw/mcu/nxp/lpc_chip_18xx/src/adc_18xx_43xx.c
Normal file
263
hw/mcu/nxp/lpc_chip_18xx/src/adc_18xx_43xx.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
180
hw/mcu/nxp/lpc_chip_18xx/src/aes_18xx_43xx.c
Normal file
180
hw/mcu/nxp/lpc_chip_18xx/src/aes_18xx_43xx.c
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
69
hw/mcu/nxp/lpc_chip_18xx/src/atimer_18xx_43xx.c
Normal file
69
hw/mcu/nxp/lpc_chip_18xx/src/atimer_18xx_43xx.c
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
317
hw/mcu/nxp/lpc_chip_18xx/src/ccan_18xx_43xx.c
Normal file
317
hw/mcu/nxp/lpc_chip_18xx/src/ccan_18xx_43xx.c
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
123
hw/mcu/nxp/lpc_chip_18xx/src/chip_18xx_43xx.c
Normal file
123
hw/mcu/nxp/lpc_chip_18xx/src/chip_18xx_43xx.c
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
832
hw/mcu/nxp/lpc_chip_18xx/src/clock_18xx_43xx.c
Normal file
832
hw/mcu/nxp/lpc_chip_18xx/src/clock_18xx_43xx.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
91
hw/mcu/nxp/lpc_chip_18xx/src/dac_18xx_43xx.c
Normal file
91
hw/mcu/nxp/lpc_chip_18xx/src/dac_18xx_43xx.c
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
106
hw/mcu/nxp/lpc_chip_18xx/src/eeprom_18xx_43xx.c
Normal file
106
hw/mcu/nxp/lpc_chip_18xx/src/eeprom_18xx_43xx.c
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
295
hw/mcu/nxp/lpc_chip_18xx/src/emc_18xx_43xx.c
Normal file
295
hw/mcu/nxp/lpc_chip_18xx/src/emc_18xx_43xx.c
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
188
hw/mcu/nxp/lpc_chip_18xx/src/enet_18xx_43xx.c
Normal file
188
hw/mcu/nxp/lpc_chip_18xx/src/enet_18xx_43xx.c
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
117
hw/mcu/nxp/lpc_chip_18xx/src/evrt_18xx_43xx.c
Normal file
117
hw/mcu/nxp/lpc_chip_18xx/src/evrt_18xx_43xx.c
Normal 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; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
752
hw/mcu/nxp/lpc_chip_18xx/src/gpdma_18xx_43xx.c
Normal file
752
hw/mcu/nxp/lpc_chip_18xx/src/gpdma_18xx_43xx.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
66
hw/mcu/nxp/lpc_chip_18xx/src/gpio_18xx_43xx.c
Normal file
66
hw/mcu/nxp/lpc_chip_18xx/src/gpio_18xx_43xx.c
Normal 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)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
54
hw/mcu/nxp/lpc_chip_18xx/src/gpiogroup_18xx_43xx.c
Normal file
54
hw/mcu/nxp/lpc_chip_18xx/src/gpiogroup_18xx_43xx.c
Normal 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
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
560
hw/mcu/nxp/lpc_chip_18xx/src/i2c_18xx_43xx.c
Normal file
560
hw/mcu/nxp/lpc_chip_18xx/src/i2c_18xx_43xx.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
274
hw/mcu/nxp/lpc_chip_18xx/src/i2cm_18xx_43xx.c
Normal file
274
hw/mcu/nxp/lpc_chip_18xx/src/i2cm_18xx_43xx.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
264
hw/mcu/nxp/lpc_chip_18xx/src/i2s_18xx_43xx.c
Normal file
264
hw/mcu/nxp/lpc_chip_18xx/src/i2s_18xx_43xx.c
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
211
hw/mcu/nxp/lpc_chip_18xx/src/iap_18xx_43xx.c
Normal file
211
hw/mcu/nxp/lpc_chip_18xx/src/iap_18xx_43xx.c
Normal 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];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
212
hw/mcu/nxp/lpc_chip_18xx/src/lcd_18xx_43xx.c
Normal file
212
hw/mcu/nxp/lpc_chip_18xx/src/lcd_18xx_43xx.c
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
151
hw/mcu/nxp/lpc_chip_18xx/src/otp_18xx_43xx.c
Normal file
151
hw/mcu/nxp/lpc_chip_18xx/src/otp_18xx_43xx.c
Normal 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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
54
hw/mcu/nxp/lpc_chip_18xx/src/pinint_18xx_43xx.c
Normal file
54
hw/mcu/nxp/lpc_chip_18xx/src/pinint_18xx_43xx.c
Normal 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
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
75
hw/mcu/nxp/lpc_chip_18xx/src/pmc_18xx_43xx.c
Normal file
75
hw/mcu/nxp/lpc_chip_18xx/src/pmc_18xx_43xx.c
Normal 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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
173
hw/mcu/nxp/lpc_chip_18xx/src/ring_buffer.c
Normal file
173
hw/mcu/nxp/lpc_chip_18xx/src/ring_buffer.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
103
hw/mcu/nxp/lpc_chip_18xx/src/ritimer_18xx_43xx.c
Normal file
103
hw/mcu/nxp/lpc_chip_18xx/src/ritimer_18xx_43xx.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
226
hw/mcu/nxp/lpc_chip_18xx/src/rtc_18xx_43xx.c
Normal file
226
hw/mcu/nxp/lpc_chip_18xx/src/rtc_18xx_43xx.c
Normal 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*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
93
hw/mcu/nxp/lpc_chip_18xx/src/sct_18xx_43xx.c
Normal file
93
hw/mcu/nxp/lpc_chip_18xx/src/sct_18xx_43xx.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
93
hw/mcu/nxp/lpc_chip_18xx/src/sct_pwm_18xx_43xx.c
Normal file
93
hw/mcu/nxp/lpc_chip_18xx/src/sct_pwm_18xx_43xx.c
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
229
hw/mcu/nxp/lpc_chip_18xx/src/sdif_18xx_43xx.c
Normal file
229
hw/mcu/nxp/lpc_chip_18xx/src/sdif_18xx_43xx.c
Normal 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];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
598
hw/mcu/nxp/lpc_chip_18xx/src/sdmmc_18xx_43xx.c
Normal file
598
hw/mcu/nxp/lpc_chip_18xx/src/sdmmc_18xx_43xx.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
233
hw/mcu/nxp/lpc_chip_18xx/src/spi_18xx_43xx.c
Normal file
233
hw/mcu/nxp/lpc_chip_18xx/src/spi_18xx_43xx.c
Normal 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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
475
hw/mcu/nxp/lpc_chip_18xx/src/ssp_18xx_43xx.c
Normal file
475
hw/mcu/nxp/lpc_chip_18xx/src/ssp_18xx_43xx.c
Normal 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));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
112
hw/mcu/nxp/lpc_chip_18xx/src/stopwatch_18xx_43xx.c
Normal file
112
hw/mcu/nxp/lpc_chip_18xx/src/stopwatch_18xx_43xx.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
166
hw/mcu/nxp/lpc_chip_18xx/src/sysinit_18xx_43xx.c
Normal file
166
hw/mcu/nxp/lpc_chip_18xx/src/sysinit_18xx_43xx.c
Normal 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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
123
hw/mcu/nxp/lpc_chip_18xx/src/timer_18xx_43xx.c
Normal file
123
hw/mcu/nxp/lpc_chip_18xx/src/timer_18xx_43xx.c
Normal 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)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
430
hw/mcu/nxp/lpc_chip_18xx/src/uart_18xx_43xx.c
Normal file
430
hw/mcu/nxp/lpc_chip_18xx/src/uart_18xx_43xx.c
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
84
hw/mcu/nxp/lpc_chip_18xx/src/wwdt_18xx_43xx.c
Normal file
84
hw/mcu/nxp/lpc_chip_18xx/src/wwdt_18xx_43xx.c
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user