summaryrefslogtreecommitdiff
path: root/arch/arm/lpc17xx/Drivers/source
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/lpc17xx/Drivers/source')
-rw-r--r--arch/arm/lpc17xx/Drivers/source/debug_frmwrk.c305
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_adc.c340
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_can.c1891
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_clkpwr.c338
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_dac.c139
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_emac.c950
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_exti.c158
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_gpdma.c450
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_gpio.c749
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_i2c.c1373
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_i2s.c642
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_libcfg_default.c64
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_mcpwm.c497
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_nvic.c136
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_pinsel.c306
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_pwm.c533
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_qei.c502
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_rit.c187
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_rtc.c771
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_spi.c431
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_ssp.c682
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_systick.c180
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_timer.c591
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_uart.c1366
-rw-r--r--arch/arm/lpc17xx/Drivers/source/lpc17xx_wdt.c261
-rw-r--r--arch/arm/lpc17xx/Drivers/source/makefile84
26 files changed, 13926 insertions, 0 deletions
diff --git a/arch/arm/lpc17xx/Drivers/source/debug_frmwrk.c b/arch/arm/lpc17xx/Drivers/source/debug_frmwrk.c
new file mode 100644
index 0000000..7e63e04
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/debug_frmwrk.c
@@ -0,0 +1,305 @@
+/***********************************************************************//**
+ * @file debug_frmwrk.c
+ * @brief Contains some utilities that used for debugging through UART
+ * @version 2.0
+ * @date 21. May. 2010
+ * @author NXP MCU SW Application Team
+ *----------------------------------------------------------------------------
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+#include "debug_frmwrk.h"
+#include "lpc17xx_pinsel.h"
+
+/* If this source file built with example, the LPC17xx FW library configuration
+ * file in each example directory ("lpc17xx_libcfg.h") must be included,
+ * otherwise the default FW library configuration file must be included instead
+ */
+#ifdef __BUILD_WITH_EXAMPLE__
+#include "lpc17xx_libcfg.h"
+#else
+#include "lpc17xx_libcfg_default.h"
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+#ifdef _DBGFWK
+/* Debug framework */
+
+void (*_db_msg)(LPC_UART_TypeDef *UARTx, const void *s);
+void (*_db_msg_)(LPC_UART_TypeDef *UARTx, const void *s);
+void (*_db_char)(LPC_UART_TypeDef *UARTx, uint8_t ch);
+void (*_db_dec)(LPC_UART_TypeDef *UARTx, uint8_t decn);
+void (*_db_dec_16)(LPC_UART_TypeDef *UARTx, uint16_t decn);
+void (*_db_dec_32)(LPC_UART_TypeDef *UARTx, uint32_t decn);
+void (*_db_hex)(LPC_UART_TypeDef *UARTx, uint8_t hexn);
+void (*_db_hex_16)(LPC_UART_TypeDef *UARTx, uint16_t hexn);
+void (*_db_hex_32)(LPC_UART_TypeDef *UARTx, uint32_t hexn);
+uint8_t (*_db_get_char)(LPC_UART_TypeDef *UARTx);
+
+
+/*********************************************************************//**
+ * @brief Puts a character to UART port
+ * @param[in] UARTx Pointer to UART peripheral
+ * @param[in] ch Character to put
+ * @return None
+ **********************************************************************/
+void UARTPutChar (LPC_UART_TypeDef *UARTx, uint8_t ch)
+{
+ UART_Send(UARTx, &ch, 1, BLOCKING);
+}
+
+
+/*********************************************************************//**
+ * @brief Get a character to UART port
+ * @param[in] UARTx Pointer to UART peripheral
+ * @return character value that returned
+ **********************************************************************/
+uint8_t UARTGetChar (LPC_UART_TypeDef *UARTx)
+{
+ uint8_t tmp = 0;
+ UART_Receive(UARTx, &tmp, 1, BLOCKING);
+ return(tmp);
+}
+
+
+/*********************************************************************//**
+ * @brief Puts a string to UART port
+ * @param[in] UARTx Pointer to UART peripheral
+ * @param[in] str string to put
+ * @return None
+ **********************************************************************/
+void UARTPuts(LPC_UART_TypeDef *UARTx, const void *str)
+{
+ uint8_t *s = (uint8_t *) str;
+
+ while (*s)
+ {
+ UARTPutChar(UARTx, *s++);
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Puts a string to UART port and print new line
+ * @param[in] UARTx Pointer to UART peripheral
+ * @param[in] str String to put
+ * @return None
+ **********************************************************************/
+void UARTPuts_(LPC_UART_TypeDef *UARTx, const void *str)
+{
+ UARTPuts (UARTx, str);
+ UARTPuts (UARTx, "\n\r");
+}
+
+
+/*********************************************************************//**
+ * @brief Puts a decimal number to UART port
+ * @param[in] UARTx Pointer to UART peripheral
+ * @param[in] decnum Decimal number (8-bit long)
+ * @return None
+ **********************************************************************/
+void UARTPutDec(LPC_UART_TypeDef *UARTx, uint8_t decnum)
+{
+ uint8_t c1=decnum%10;
+ uint8_t c2=(decnum/10)%10;
+ uint8_t c3=(decnum/100)%10;
+ UARTPutChar(UARTx, '0'+c3);
+ UARTPutChar(UARTx, '0'+c2);
+ UARTPutChar(UARTx, '0'+c1);
+}
+
+/*********************************************************************//**
+ * @brief Puts a decimal number to UART port
+ * @param[in] UARTx Pointer to UART peripheral
+ * @param[in] decnum Decimal number (8-bit long)
+ * @return None
+ **********************************************************************/
+void UARTPutDec16(LPC_UART_TypeDef *UARTx, uint16_t decnum)
+{
+ uint8_t c1=decnum%10;
+ uint8_t c2=(decnum/10)%10;
+ uint8_t c3=(decnum/100)%10;
+ uint8_t c4=(decnum/1000)%10;
+ uint8_t c5=(decnum/10000)%10;
+ UARTPutChar(UARTx, '0'+c5);
+ UARTPutChar(UARTx, '0'+c4);
+ UARTPutChar(UARTx, '0'+c3);
+ UARTPutChar(UARTx, '0'+c2);
+ UARTPutChar(UARTx, '0'+c1);
+}
+
+/*********************************************************************//**
+ * @brief Puts a decimal number to UART port
+ * @param[in] UARTx Pointer to UART peripheral
+ * @param[in] decnum Decimal number (8-bit long)
+ * @return None
+ **********************************************************************/
+void UARTPutDec32(LPC_UART_TypeDef *UARTx, uint32_t decnum)
+{
+ uint8_t c1=decnum%10;
+ uint8_t c2=(decnum/10)%10;
+ uint8_t c3=(decnum/100)%10;
+ uint8_t c4=(decnum/1000)%10;
+ uint8_t c5=(decnum/10000)%10;
+ uint8_t c6=(decnum/100000)%10;
+ uint8_t c7=(decnum/1000000)%10;
+ uint8_t c8=(decnum/10000000)%10;
+ uint8_t c9=(decnum/100000000)%10;
+ uint8_t c10=(decnum/100000000)%10;
+ UARTPutChar(UARTx, '0'+c10);
+ UARTPutChar(UARTx, '0'+c9);
+ UARTPutChar(UARTx, '0'+c8);
+ UARTPutChar(UARTx, '0'+c7);
+ UARTPutChar(UARTx, '0'+c6);
+ UARTPutChar(UARTx, '0'+c5);
+ UARTPutChar(UARTx, '0'+c4);
+ UARTPutChar(UARTx, '0'+c3);
+ UARTPutChar(UARTx, '0'+c2);
+ UARTPutChar(UARTx, '0'+c1);
+}
+
+/*********************************************************************//**
+ * @brief Puts a hex number to UART port
+ * @param[in] UARTx Pointer to UART peripheral
+ * @param[in] hexnum Hex number (8-bit long)
+ * @return None
+ **********************************************************************/
+void UARTPutHex (LPC_UART_TypeDef *UARTx, uint8_t hexnum)
+{
+ uint8_t nibble, i;
+
+ UARTPuts(UARTx, "0x");
+ i = 1;
+ do {
+ nibble = (hexnum >> (4*i)) & 0x0F;
+ UARTPutChar(UARTx, (nibble > 9) ? ('A' + nibble - 10) : ('0' + nibble));
+ } while (i--);
+}
+
+
+/*********************************************************************//**
+ * @brief Puts a hex number to UART port
+ * @param[in] UARTx Pointer to UART peripheral
+ * @param[in] hexnum Hex number (16-bit long)
+ * @return None
+ **********************************************************************/
+void UARTPutHex16 (LPC_UART_TypeDef *UARTx, uint16_t hexnum)
+{
+ uint8_t nibble, i;
+
+ UARTPuts(UARTx, "0x");
+ i = 3;
+ do {
+ nibble = (hexnum >> (4*i)) & 0x0F;
+ UARTPutChar(UARTx, (nibble > 9) ? ('A' + nibble - 10) : ('0' + nibble));
+ } while (i--);
+}
+
+/*********************************************************************//**
+ * @brief Puts a hex number to UART port
+ * @param[in] UARTx Pointer to UART peripheral
+ * @param[in] hexnum Hex number (32-bit long)
+ * @return None
+ **********************************************************************/
+void UARTPutHex32 (LPC_UART_TypeDef *UARTx, uint32_t hexnum)
+{
+ uint8_t nibble, i;
+
+ UARTPuts(UARTx, "0x");
+ i = 7;
+ do {
+ nibble = (hexnum >> (4*i)) & 0x0F;
+ UARTPutChar(UARTx, (nibble > 9) ? ('A' + nibble - 10) : ('0' + nibble));
+ } while (i--);
+}
+
+///*********************************************************************//**
+// * @brief print function that supports format as same as printf()
+// * function of <stdio.h> library
+// * @param[in] None
+// * @return None
+// **********************************************************************/
+//void _printf (const char *format, ...)
+//{
+// static char buffer[512 + 1];
+// va_list vArgs;
+// char *tmp;
+// va_start(vArgs, format);
+// vsprintf((char *)buffer, (char const *)format, vArgs);
+// va_end(vArgs);
+//
+// _DBG(buffer);
+//}
+
+/*********************************************************************//**
+ * @brief Initialize Debug frame work through initializing UART port
+ * @param[in] None
+ * @return None
+ **********************************************************************/
+void debug_frmwrk_init(void)
+{
+ UART_CFG_Type UARTConfigStruct;
+ PINSEL_CFG_Type PinCfg;
+
+#if (USED_UART_DEBUG_PORT==0)
+ /*
+ * Initialize UART0 pin connect
+ */
+ PinCfg.Funcnum = 1;
+ PinCfg.OpenDrain = 0;
+ PinCfg.Pinmode = 0;
+ PinCfg.Pinnum = 2;
+ PinCfg.Portnum = 0;
+ PINSEL_ConfigPin(&PinCfg);
+ PinCfg.Pinnum = 3;
+ PINSEL_ConfigPin(&PinCfg);
+#elif #if (USED_UART_DEBUG_PORT==1)
+ /*
+ * Initialize UART1 pin connect
+ */
+ PinCfg.Funcnum = 1;
+ PinCfg.OpenDrain = 0;
+ PinCfg.Pinmode = 0;
+ PinCfg.Pinnum = 15;
+ PinCfg.Portnum = 0;
+ PINSEL_ConfigPin(&PinCfg);
+ PinCfg.Pinnum = 16;
+ PINSEL_ConfigPin(&PinCfg);
+#endif
+
+ /* Initialize UART Configuration parameter structure to default state:
+ * Baudrate = 9600bps
+ * 8 data bit
+ * 1 Stop bit
+ * None parity
+ */
+ UART_ConfigStructInit(&UARTConfigStruct);
+ // Re-configure baudrate to 115200bps
+ UARTConfigStruct.Baud_rate = 115200;
+
+ // Initialize DEBUG_UART_PORT peripheral with given to corresponding parameter
+ UART_Init(DEBUG_UART_PORT, &UARTConfigStruct);
+
+ // Enable UART Transmit
+ UART_TxCmd(DEBUG_UART_PORT, ENABLE);
+
+ _db_msg = UARTPuts;
+ _db_msg_ = UARTPuts_;
+ _db_char = UARTPutChar;
+ _db_hex = UARTPutHex;
+ _db_hex_16 = UARTPutHex16;
+ _db_hex_32 = UARTPutHex32;
+ _db_dec = UARTPutDec;
+ _db_dec_16 = UARTPutDec16;
+ _db_dec_32 = UARTPutDec32;
+ _db_get_char = UARTGetChar;
+}
+#endif /*_DBGFWK */
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_adc.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_adc.c
new file mode 100644
index 0000000..a49c2cf
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_adc.c
@@ -0,0 +1,340 @@
+/***********************************************************************//**
+ * @file lpc17xx_adc.c
+ * @brief Contains all functions support for ADC firmware library on LPC17xx
+ * @version 3.0
+ * @date 18. June. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup ADC
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_adc.h"
+#include "lpc17xx_clkpwr.h"
+
+/* If this source file built with example, the LPC17xx FW library configuration
+ * file in each example directory ("lpc17xx_libcfg.h") must be included,
+ * otherwise the default FW library configuration file must be included instead
+ */
+#ifdef __BUILD_WITH_EXAMPLE__
+#include "lpc17xx_libcfg.h"
+#else
+#include "lpc17xx_libcfg_default.h"
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+
+#ifdef _ADC
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup ADC_Public_Functions
+ * @{
+ */
+
+/*********************************************************************//**
+ * @brief Initial for ADC
+ * + Set bit PCADC
+ * + Set clock for ADC
+ * + Set Clock Frequency
+ * @param[in] ADCx pointer to LPC_ADC_TypeDef, should be: LPC_ADC
+ * @param[in] rate ADC conversion rate, should be <=200KHz
+ * @return None
+ **********************************************************************/
+void ADC_Init(LPC_ADC_TypeDef *ADCx, uint32_t rate)
+{
+ uint32_t temp, tmp;
+
+ CHECK_PARAM(PARAM_ADCx(ADCx));
+ CHECK_PARAM(PARAM_ADC_RATE(rate));
+
+ // Turn on power and clock
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCAD, ENABLE);
+
+ ADCx->ADCR = 0;
+
+ //Enable PDN bit
+ tmp = ADC_CR_PDN;
+ // Set clock frequency
+ temp = CLKPWR_GetPCLK(CLKPWR_PCLKSEL_ADC);
+ /* 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 13MHz.
+ * A fully conversion requires 65 of these clocks.
+ * ADC clock = PCLK_ADC0 / (CLKDIV + 1);
+ * ADC rate = ADC clock / 65;
+ */
+ temp = (temp /(rate * 65)) - 1;
+ tmp |= ADC_CR_CLKDIV(temp);
+
+ ADCx->ADCR = tmp;
+}
+
+
+/*********************************************************************//**
+* @brief Close ADC
+* @param[in] ADCx pointer to LPC_ADC_TypeDef, should be: LPC_ADC
+* @return None
+**********************************************************************/
+void ADC_DeInit(LPC_ADC_TypeDef *ADCx)
+{
+ CHECK_PARAM(PARAM_ADCx(ADCx));
+
+ // Clear PDN bit
+ ADCx->ADCR &= ~ADC_CR_PDN;
+ // Turn on power and clock
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCAD, DISABLE);
+}
+
+
+/*********************************************************************//**
+* @brief Get Result conversion from A/D data register
+* @param[in] channel number which want to read back the result
+* @return Result of conversion
+*********************************************************************/
+uint32_t ADC_GetData(uint32_t channel)
+{
+ uint32_t adc_value;
+
+ CHECK_PARAM(PARAM_ADC_CHANNEL_SELECTION(channel));
+
+ adc_value = *(uint32_t *)((&LPC_ADC->ADDR0) + channel);
+ return ADC_GDR_RESULT(adc_value);
+}
+
+/*********************************************************************//**
+* @brief Set start mode for ADC
+* @param[in] ADCx pointer to LPC_ADC_TypeDef, should be: LPC_ADC
+* @param[in] start_mode Start mode choose one of modes in
+* 'ADC_START_OPT' enumeration type definition, should be:
+* - ADC_START_CONTINUOUS
+* - ADC_START_NOW
+* - ADC_START_ON_EINT0
+* - ADC_START_ON_CAP01
+* - ADC_START_ON_MAT01
+* - ADC_START_ON_MAT03
+* - ADC_START_ON_MAT10
+* - ADC_START_ON_MAT11
+* @return None
+*********************************************************************/
+void ADC_StartCmd(LPC_ADC_TypeDef *ADCx, uint8_t start_mode)
+{
+ CHECK_PARAM(PARAM_ADCx(ADCx));
+ CHECK_PARAM(PARAM_ADC_START_OPT(start_mode));
+
+ ADCx->ADCR &= ~ADC_CR_START_MASK;
+ ADCx->ADCR |=ADC_CR_START_MODE_SEL((uint32_t)start_mode);
+}
+
+
+/*********************************************************************//**
+* @brief ADC Burst mode setting
+* @param[in] ADCx pointer to LPC_ADC_TypeDef, should be: LPC_ADC
+* @param[in] NewState
+* - 1: Set Burst mode
+* - 0: reset Burst mode
+* @return None
+**********************************************************************/
+void ADC_BurstCmd(LPC_ADC_TypeDef *ADCx, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_ADCx(ADCx));
+
+ ADCx->ADCR &= ~ADC_CR_BURST;
+ if (NewState){
+ ADCx->ADCR |= ADC_CR_BURST;
+ }
+}
+
+/*********************************************************************//**
+* @brief Set AD conversion in power mode
+* @param[in] ADCx pointer to LPC_ADC_TypeDef, should be: LPC_ADC
+* @param[in] NewState
+* - 1: AD converter is optional
+* - 0: AD Converter is in power down mode
+* @return None
+**********************************************************************/
+void ADC_PowerdownCmd(LPC_ADC_TypeDef *ADCx, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_ADCx(ADCx));
+
+ ADCx->ADCR &= ~ADC_CR_PDN;
+ if (NewState){
+ ADCx->ADCR |= ADC_CR_PDN;
+ }
+}
+
+/*********************************************************************//**
+* @brief Set Edge start configuration
+* @param[in] ADCx pointer to LPC_ADC_TypeDef, should be: LPC_ADC
+* @param[in] EdgeOption is ADC_START_ON_RISING and ADC_START_ON_FALLING
+* 0:ADC_START_ON_RISING
+* 1:ADC_START_ON_FALLING
+* @return None
+**********************************************************************/
+void ADC_EdgeStartConfig(LPC_ADC_TypeDef *ADCx, uint8_t EdgeOption)
+{
+ CHECK_PARAM(PARAM_ADCx(ADCx));
+ CHECK_PARAM(PARAM_ADC_START_ON_EDGE_OPT(EdgeOption));
+
+ ADCx->ADCR &= ~ADC_CR_EDGE;
+ if (EdgeOption){
+ ADCx->ADCR |= ADC_CR_EDGE;
+ }
+}
+
+/*********************************************************************//**
+* @brief ADC interrupt configuration
+* @param[in] ADCx pointer to LPC_ADC_TypeDef, should be: LPC_ADC
+* @param[in] IntType: type of interrupt, should be:
+* - ADC_ADINTEN0: Interrupt channel 0
+* - ADC_ADINTEN1: Interrupt channel 1
+* ...
+* - ADC_ADINTEN7: Interrupt channel 7
+* - ADC_ADGINTEN: Individual channel/global flag done generate an interrupt
+* @param[in] NewState:
+* - SET : enable ADC interrupt
+* - RESET: disable ADC interrupt
+* @return None
+**********************************************************************/
+void ADC_IntConfig (LPC_ADC_TypeDef *ADCx, ADC_TYPE_INT_OPT IntType, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_ADCx(ADCx));
+ CHECK_PARAM(PARAM_ADC_TYPE_INT_OPT(IntType));
+
+ ADCx->ADINTEN &= ~ADC_INTEN_CH(IntType);
+ if (NewState){
+ ADCx->ADINTEN |= ADC_INTEN_CH(IntType);
+ }
+}
+
+/*********************************************************************//**
+* @brief Enable/Disable ADC channel number
+* @param[in] ADCx pointer to LPC_ADC_TypeDef, should be: LPC_ADC
+* @param[in] Channel channel number
+* @param[in] NewState Enable or Disable
+*
+* @return None
+**********************************************************************/
+void ADC_ChannelCmd (LPC_ADC_TypeDef *ADCx, uint8_t Channel, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_ADCx(ADCx));
+ CHECK_PARAM(PARAM_ADC_CHANNEL_SELECTION(Channel));
+
+ if (NewState == ENABLE) {
+ ADCx->ADCR |= ADC_CR_CH_SEL(Channel);
+ } else {
+ ADCx->ADCR &= ~ADC_CR_CH_SEL(Channel);
+ }
+}
+
+/*********************************************************************//**
+* @brief Get ADC result
+* @param[in] ADCx pointer to LPC_ADC_TypeDef, should be: LPC_ADC
+* @param[in] channel: channel number, should be 0...7
+* @return Data conversion
+**********************************************************************/
+uint16_t ADC_ChannelGetData(LPC_ADC_TypeDef *ADCx, uint8_t channel)
+{
+ uint32_t adc_value;
+
+ CHECK_PARAM(PARAM_ADCx(ADCx));
+ CHECK_PARAM(PARAM_ADC_CHANNEL_SELECTION(channel));
+
+ adc_value = *(uint32_t *) ((&ADCx->ADDR0) + channel);
+ return ADC_DR_RESULT(adc_value);
+}
+
+/*********************************************************************//**
+* @brief Get ADC Chanel status from ADC data register
+* @param[in] ADCx pointer to LPC_ADC_TypeDef, should be: LPC_ADC
+* @param[in] channel: channel number, should be 0..7
+* @param[in] StatusType
+* 0:Burst status
+* 1:Done status
+* @return SET / RESET
+**********************************************************************/
+FlagStatus ADC_ChannelGetStatus(LPC_ADC_TypeDef *ADCx, uint8_t channel, uint32_t StatusType)
+{
+ uint32_t temp;
+
+ CHECK_PARAM(PARAM_ADCx(ADCx));
+ CHECK_PARAM(PARAM_ADC_CHANNEL_SELECTION(channel));
+ CHECK_PARAM(PARAM_ADC_DATA_STATUS(StatusType));
+
+ temp = *(uint32_t *) ((&ADCx->ADDR0) + channel);
+ if (StatusType) {
+ temp &= ADC_DR_DONE_FLAG;
+ }else{
+ temp &= ADC_DR_OVERRUN_FLAG;
+ }
+ if (temp) {
+ return SET;
+ } else {
+ return RESET;
+ }
+
+}
+
+/*********************************************************************//**
+* @brief Get ADC Data from AD Global register
+* @param[in] ADCx pointer to LPC_ADC_TypeDef, should be: LPC_ADC
+* @return Result of conversion
+**********************************************************************/
+uint32_t ADC_GlobalGetData(LPC_ADC_TypeDef *ADCx)
+{
+ CHECK_PARAM(PARAM_ADCx(ADCx));
+
+ return ((uint32_t)(ADCx->ADGDR));
+}
+
+/*********************************************************************//**
+* @brief Get ADC Chanel status from AD global data register
+* @param[in] ADCx pointer to LPC_ADC_TypeDef, should be: LPC_ADC
+* @param[in] StatusType
+* 0:Burst status
+* 1:Done status
+* @return SET / RESET
+**********************************************************************/
+FlagStatus ADC_GlobalGetStatus(LPC_ADC_TypeDef *ADCx, uint32_t StatusType)
+{
+ uint32_t temp;
+
+ CHECK_PARAM(PARAM_ADCx(ADCx));
+ CHECK_PARAM(PARAM_ADC_DATA_STATUS(StatusType));
+
+ temp = ADCx->ADGDR;
+ if (StatusType){
+ temp &= ADC_DR_DONE_FLAG;
+ }else{
+ temp &= ADC_DR_OVERRUN_FLAG;
+ }
+ if (temp){
+ return SET;
+ }else{
+ return RESET;
+ }
+}
+
+/**
+ * @}
+ */
+
+#endif /* _ADC */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
+
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_can.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_can.c
new file mode 100644
index 0000000..eef871f
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_can.c
@@ -0,0 +1,1891 @@
+/***********************************************************************//**
+ * @file lpc17xx_can.c
+ * @brief Contains all functions support for CAN firmware library on LPC17xx
+ * @version 3.0
+ * @date 18. June. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup CAN
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_can.h"
+#include "lpc17xx_clkpwr.h"
+
+/* If this source file built with example, the LPC17xx FW library configuration
+ * file in each example directory ("lpc17xx_libcfg.h") must be included,
+ * otherwise the default FW library configuration file must be included instead
+ */
+#ifdef __BUILD_WITH_EXAMPLE__
+#include "lpc17xx_libcfg.h"
+#else
+#include "lpc17xx_libcfg_default.h"
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+
+#ifdef _CAN
+
+/* Private Variables ---------------------------------------------------------- */
+/** @defgroup CAN_Private_Variables CAN Private Variables
+ * @{
+ */
+
+FunctionalState FULLCAN_ENABLE;
+
+
+/* Counts number of filters (CAN message objects) used */
+uint16_t CANAF_FullCAN_cnt = 0;
+uint16_t CANAF_std_cnt = 0;
+uint16_t CANAF_gstd_cnt = 0;
+uint16_t CANAF_ext_cnt = 0;
+uint16_t CANAF_gext_cnt = 0;
+
+/* End of Private Variables ----------------------------------------------------*/
+/**
+ * @}
+ */
+
+/* Private Variables ---------------------------------------------------------- */
+static void can_SetBaudrate (LPC_CAN_TypeDef *CANx, uint32_t baudrate);
+
+/*********************************************************************//**
+ * @brief Setting CAN baud rate (bps)
+ * @param[in] CANx point to LPC_CAN_TypeDef object, should be:
+ * - LPC_CAN1: CAN1 peripheral
+ * - LPC_CAN2: CAN2 peripheral
+ * @param[in] baudrate: is the baud rate value will be set
+ * @return None
+ ***********************************************************************/
+static void can_SetBaudrate (LPC_CAN_TypeDef *CANx, uint32_t baudrate)
+{
+ uint32_t result = 0;
+ uint8_t NT, TSEG1, TSEG2;
+ uint32_t CANPclk = 0;
+ uint32_t BRP;
+ CHECK_PARAM(PARAM_CANx(CANx));
+
+ if (CANx == LPC_CAN1)
+ {
+ CANPclk = CLKPWR_GetPCLK (CLKPWR_PCONP_PCAN1);
+ }
+ else
+ {
+ CANPclk = CLKPWR_GetPCLK (CLKPWR_PCONP_PCAN2);
+ }
+ result = CANPclk / baudrate;
+ /* Calculate suitable nominal time value
+ * NT (nominal time) = (TSEG1 + TSEG2 + 3)
+ * NT <= 24
+ * TSEG1 >= 2*TSEG2
+ */
+ for(NT=24;NT>0;NT=NT-2)
+ {
+ if ((result%NT)==0)
+ {
+ BRP = result / NT - 1;
+ NT--;
+ TSEG2 = (NT/3) - 1;
+ TSEG1 = NT -(NT/3) - 1;
+ break;
+ }
+ }
+ /* Enter reset mode */
+ CANx->MOD = 0x01;
+ /* Set bit timing
+ * Default: SAM = 0x00;
+ * SJW = 0x03;
+ */
+ CANx->BTR = (TSEG2<<20)|(TSEG1<<16)|(3<<14)|BRP;
+ /* Return to normal operating */
+ CANx->MOD = 0;
+}
+/* End of Private Functions ----------------------------------------------------*/
+
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup CAN_Public_Functions
+ * @{
+ */
+
+/********************************************************************//**
+ * @brief Initialize CAN peripheral with given baudrate
+ * @param[in] CANx pointer to LPC_CAN_TypeDef, should be:
+ * - LPC_CAN1: CAN1 peripheral
+ * - LPC_CAN2: CAN2 peripheral
+ * @param[in] baudrate: the value of CAN baudrate will be set (bps)
+ * @return None
+ *********************************************************************/
+void CAN_Init(LPC_CAN_TypeDef *CANx, uint32_t baudrate)
+{
+ uint32_t temp;
+ uint16_t i;
+ CHECK_PARAM(PARAM_CANx(CANx));
+
+ if(CANx == LPC_CAN1)
+ {
+ /* Turn on power and clock for CAN1 */
+ CLKPWR_ConfigPPWR(CLKPWR_PCONP_PCAN1, ENABLE);
+ /* Set clock divide for CAN1 */
+ CLKPWR_SetPCLKDiv (CLKPWR_PCONP_PCAN1, CLKPWR_PCLKSEL_CCLK_DIV_4);
+ }
+ else
+ {
+ /* Turn on power and clock for CAN1 */
+ CLKPWR_ConfigPPWR(CLKPWR_PCONP_PCAN2, ENABLE);
+ /* Set clock divide for CAN2 */
+ CLKPWR_SetPCLKDiv (CLKPWR_PCONP_PCAN2, CLKPWR_PCLKSEL_CCLK_DIV_4);
+ }
+
+ CANx->MOD = 1; // Enter Reset Mode
+ CANx->IER = 0; // Disable All CAN Interrupts
+ CANx->GSR = 0;
+ /* Request command to release Rx, Tx buffer and clear data overrun */
+ //CANx->CMR = CAN_CMR_AT | CAN_CMR_RRB | CAN_CMR_CDO;
+ CANx->CMR = (1<<1)|(1<<2)|(1<<3);
+ /* Read to clear interrupt pending in interrupt capture register */
+ temp = CANx->ICR;
+ CANx->MOD = 0;// Return Normal operating
+
+ //Reset CANAF value
+ LPC_CANAF->AFMR = 0x01;
+
+ //clear ALUT RAM
+ for (i = 0; i < 512; i++) {
+ LPC_CANAF_RAM->mask[i] = 0x00;
+ }
+
+ LPC_CANAF->SFF_sa = 0x00;
+ LPC_CANAF->SFF_GRP_sa = 0x00;
+ LPC_CANAF->EFF_sa = 0x00;
+ LPC_CANAF->EFF_GRP_sa = 0x00;
+ LPC_CANAF->ENDofTable = 0x00;
+
+ LPC_CANAF->AFMR = 0x00;
+ /* Set baudrate */
+ can_SetBaudrate (CANx, baudrate);
+}
+
+/********************************************************************//**
+ * @brief CAN deInit
+ * @param[in] CANx pointer to LPC_CAN_TypeDef, should be:
+ * - LPC_CAN1: CAN1 peripheral
+ * - LPC_CAN2: CAN2 peripheral
+ * @return None
+ *********************************************************************/
+void CAN_DeInit(LPC_CAN_TypeDef *CANx)
+{
+ CHECK_PARAM(PARAM_CANx(CANx));
+
+ if(CANx == LPC_CAN1)
+ {
+ /* Turn on power and clock for CAN1 */
+ CLKPWR_ConfigPPWR(CLKPWR_PCONP_PCAN1, DISABLE);
+ }
+ else
+ {
+ /* Turn on power and clock for CAN1 */
+ CLKPWR_ConfigPPWR(CLKPWR_PCONP_PCAN2, DISABLE);
+ }
+}
+
+/********************************************************************//**
+ * @brief Setup Acceptance Filter Look-Up Table
+ * @param[in] CANAFx pointer to LPC_CANAF_TypeDef
+ * Should be: LPC_CANAF
+ * @param[in] AFSection the pointer to AF_SectionDef structure
+ * It contain information about 5 sections will be install in AFLUT
+ * @return CAN Error could be:
+ * - CAN_OBJECTS_FULL_ERROR: No more rx or tx objects available
+ * - CAN_AF_ENTRY_ERROR: table error-violation of ascending numerical order
+ * - CAN_OK: ID is added into table successfully
+ *********************************************************************/
+CAN_ERROR CAN_SetupAFLUT(LPC_CANAF_TypeDef* CANAFx, AF_SectionDef* AFSection)
+{
+ uint8_t ctrl1,ctrl2;
+ uint8_t dis1, dis2;
+ uint16_t SID, SID_temp,i, count = 0;
+ uint32_t EID, EID_temp, entry, buf;
+ uint16_t lowerSID, upperSID;
+ uint32_t lowerEID, upperEID;
+
+ CHECK_PARAM(PARAM_CANAFx(CANAFx));
+ CANAFx->AFMR = 0x01;
+
+/***** setup FullCAN Table *****/
+ if(AFSection->FullCAN_Sec == NULL)
+ {
+ FULLCAN_ENABLE = DISABLE;
+ }
+ else
+ {
+ FULLCAN_ENABLE = ENABLE;
+ for(i=0;i<(AFSection->FC_NumEntry);i++)
+ {
+ if(count + 1 > 64)
+ {
+ return CAN_OBJECTS_FULL_ERROR;
+ }
+ ctrl1 = AFSection->FullCAN_Sec->controller;
+ SID = AFSection->FullCAN_Sec->id_11;
+ dis1 = AFSection->FullCAN_Sec->disable;
+
+ CHECK_PARAM(PARAM_CTRL(ctrl1));
+ CHECK_PARAM(PARAM_ID_11(SID));
+ CHECK_PARAM(PARAM_MSG_DISABLE(dis1));
+ entry = 0x00; //reset entry value
+ if((CANAF_FullCAN_cnt & 0x00000001)==0)
+ {
+ if(count!=0x00)
+ {
+ buf = LPC_CANAF_RAM->mask[count-1];
+ SID_temp = (buf & 0x000003FF);
+ if(SID_temp > SID)
+ {
+ return CAN_AF_ENTRY_ERROR;
+ }
+ }
+ entry = (ctrl1<<29)|(dis1<<28)|(SID<<16)|(1<<27);
+ LPC_CANAF_RAM->mask[count] &= 0x0000FFFF;
+ LPC_CANAF_RAM->mask[count] |= entry;
+ CANAF_FullCAN_cnt++;
+ }
+ else
+ {
+ buf = LPC_CANAF_RAM->mask[count];
+ SID_temp = (buf & 0x03FF0000)>>16;
+ if(SID_temp > SID)
+ {
+ return CAN_AF_ENTRY_ERROR;
+ }
+ entry = (ctrl1<<13)|(dis1<<12)|(SID<<0)|(1<<11);
+ LPC_CANAF_RAM->mask[count] &= 0xFFFF0000;
+ LPC_CANAF_RAM->mask[count]|= entry;
+ count++;
+ CANAF_FullCAN_cnt++;
+ }
+ AFSection->FullCAN_Sec = (FullCAN_Entry *)((uint32_t)(AFSection->FullCAN_Sec)+ sizeof(FullCAN_Entry));
+ }
+ }
+
+/***** Setup Explicit Standard Frame Format Section *****/
+ if(AFSection->SFF_Sec != NULL)
+ {
+ for(i=0;i<(AFSection->SFF_NumEntry);i++)
+ {
+ if(count + 1 > 512)
+ {
+ return CAN_OBJECTS_FULL_ERROR;
+ }
+ ctrl1 = AFSection->SFF_Sec->controller;
+ SID = AFSection->SFF_Sec->id_11;
+ dis1 = AFSection->SFF_Sec->disable;
+
+ //check parameter
+ CHECK_PARAM(PARAM_CTRL(ctrl1));
+ CHECK_PARAM(PARAM_ID_11(SID));
+ CHECK_PARAM(PARAM_MSG_DISABLE(dis1));
+
+ entry = 0x00; //reset entry value
+ if((CANAF_std_cnt & 0x00000001)==0)
+ {
+ if(CANAF_std_cnt !=0 )
+ {
+ buf = LPC_CANAF_RAM->mask[count-1];
+ SID_temp = (buf & 0x00000FFF);
+ if(SID_temp > SID)
+ {
+ return CAN_AF_ENTRY_ERROR;
+ }
+ }
+ entry = (ctrl1<<29)|(dis1<<28)|(SID<<16);
+ LPC_CANAF_RAM->mask[count] &= 0x0000FFFF;
+ LPC_CANAF_RAM->mask[count] |= entry;
+ CANAF_std_cnt++;
+ }
+ else
+ {
+ buf = LPC_CANAF_RAM->mask[count];
+ SID_temp = (buf & 0x0FFF0000)>>16;
+ if(SID_temp > SID)
+ {
+ return CAN_AF_ENTRY_ERROR;
+ }
+ entry = (ctrl1<<13)|(dis1<<12)|(SID<<0);
+ LPC_CANAF_RAM->mask[count] &= 0xFFFF0000;
+ LPC_CANAF_RAM->mask[count] |= entry;
+ count++;
+ CANAF_std_cnt++;
+ }
+ AFSection->SFF_Sec = (SFF_Entry *)((uint32_t)(AFSection->SFF_Sec)+ sizeof(SFF_Entry));
+ }
+ }
+
+/***** Setup Group of Standard Frame Format Identifier Section *****/
+ if(AFSection->SFF_GPR_Sec != NULL)
+ {
+ for(i=0;i<(AFSection->SFF_GPR_NumEntry);i++)
+ {
+ if(count + 1 > 512)
+ {
+ return CAN_OBJECTS_FULL_ERROR;
+ }
+ ctrl1 = AFSection->SFF_GPR_Sec->controller1;
+ ctrl2 = AFSection->SFF_GPR_Sec->controller2;
+ dis1 = AFSection->SFF_GPR_Sec->disable1;
+ dis2 = AFSection->SFF_GPR_Sec->disable2;
+ lowerSID = AFSection->SFF_GPR_Sec->lowerID;
+ upperSID = AFSection->SFF_GPR_Sec->upperID;
+
+ /* check parameter */
+ CHECK_PARAM(PARAM_CTRL(ctrl1));
+ CHECK_PARAM(PARAM_CTRL(ctrl2));
+ CHECK_PARAM(PARAM_MSG_DISABLE(dis1));
+ CHECK_PARAM(PARAM_MSG_DISABLE(dis2));
+ CHECK_PARAM(PARAM_ID_11(lowerSID));
+ CHECK_PARAM(PARAM_ID_11(upperSID));
+
+ entry = 0x00;
+ if(CANAF_gstd_cnt!=0)
+ {
+ buf = LPC_CANAF_RAM->mask[count-1];
+ SID_temp = buf & 0x00000FFF;
+ if(SID_temp > lowerSID)
+ {
+ return CAN_AF_ENTRY_ERROR;
+ }
+ }
+ entry = (ctrl1 << 29)|(dis1 << 28)|(lowerSID << 16)| \
+ (ctrl2 << 13)|(dis2 << 12)|(upperSID << 0);
+ LPC_CANAF_RAM->mask[count] = entry;
+ CANAF_gstd_cnt++;
+ count++;
+ AFSection->SFF_GPR_Sec = (SFF_GPR_Entry *)((uint32_t)(AFSection->SFF_GPR_Sec)+ sizeof(SFF_GPR_Entry));
+ }
+ }
+
+/***** Setup Explicit Extend Frame Format Identifier Section *****/
+ if(AFSection->EFF_Sec != NULL)
+ {
+ for(i=0;i<(AFSection->EFF_NumEntry);i++)
+ {
+ if(count + 1 > 512)
+ {
+ return CAN_OBJECTS_FULL_ERROR;
+ }
+ EID = AFSection->EFF_Sec->ID_29;
+ ctrl1 = AFSection->EFF_Sec->controller;
+
+ // check parameter
+ CHECK_PARAM(PARAM_ID_29(EID));
+ CHECK_PARAM(PARAM_CTRL(ctrl1));
+
+ entry = 0x00; //reset entry value
+ if(CANAF_ext_cnt != 0)
+ {
+ buf = LPC_CANAF_RAM->mask[count-1];
+ EID_temp = buf & 0x0FFFFFFF;
+ if(EID_temp > EID)
+ {
+ return CAN_AF_ENTRY_ERROR;
+ }
+ }
+ entry = (ctrl1 << 29)|(EID << 0);
+ LPC_CANAF_RAM->mask[count] = entry;
+ CANAF_ext_cnt ++;
+ count++;
+ AFSection->EFF_Sec = (EFF_Entry *)((uint32_t)(AFSection->EFF_Sec)+ sizeof(EFF_Entry));
+ }
+ }
+
+/***** Setup Group of Extended Frame Format Identifier Section *****/
+ if(AFSection->EFF_GPR_Sec != NULL)
+ {
+ for(i=0;i<(AFSection->EFF_GPR_NumEntry);i++)
+ {
+ if(count + 2 > 512)
+ {
+ return CAN_OBJECTS_FULL_ERROR;
+ }
+ ctrl1 = AFSection->EFF_GPR_Sec->controller1;
+ ctrl2 = AFSection->EFF_GPR_Sec->controller2;
+ lowerEID = AFSection->EFF_GPR_Sec->lowerEID;
+ upperEID = AFSection->EFF_GPR_Sec->upperEID;
+
+ //check parameter
+ CHECK_PARAM(PARAM_CTRL(ctrl1));
+ CHECK_PARAM(PARAM_CTRL(ctrl2));
+ CHECK_PARAM(PARAM_ID_29(lowerEID));
+ CHECK_PARAM(PARAM_ID_29(upperEID));
+
+ entry = 0x00;
+ if(CANAF_gext_cnt != 0)
+ {
+ buf = LPC_CANAF_RAM->mask[count-1];
+ EID_temp = buf & 0x0FFFFFFF;
+ if(EID_temp > lowerEID)
+ {
+ return CAN_AF_ENTRY_ERROR;
+ }
+ }
+ entry = (ctrl1 << 29)|(lowerEID << 0);
+ LPC_CANAF_RAM->mask[count++] = entry;
+ entry = (ctrl2 << 29)|(upperEID << 0);
+ LPC_CANAF_RAM->mask[count++] = entry;
+ CANAF_gext_cnt++;
+ AFSection->EFF_GPR_Sec = (EFF_GPR_Entry *)((uint32_t)(AFSection->EFF_GPR_Sec)+ sizeof(EFF_GPR_Entry));
+ }
+ }
+ //update address values
+ LPC_CANAF->SFF_sa = ((CANAF_FullCAN_cnt + 1)>>1)<<2;
+ LPC_CANAF->SFF_GRP_sa = LPC_CANAF->SFF_sa + (((CANAF_std_cnt+1)>>1)<< 2);
+ LPC_CANAF->EFF_sa = LPC_CANAF->SFF_GRP_sa + (CANAF_gstd_cnt << 2);
+ LPC_CANAF->EFF_GRP_sa = LPC_CANAF->EFF_sa + (CANAF_ext_cnt << 2);
+ LPC_CANAF->ENDofTable = LPC_CANAF->EFF_GRP_sa + (CANAF_gext_cnt << 3);
+
+ if(FULLCAN_ENABLE == DISABLE)
+ {
+ LPC_CANAF->AFMR = 0x00; // Normal mode
+ }
+ else
+ {
+ LPC_CANAF->AFMR = 0x04;
+ }
+ return CAN_OK;
+}
+/********************************************************************//**
+ * @brief Add Explicit ID into AF Look-Up Table dynamically.
+ * @param[in] CANx pointer to LPC_CAN_TypeDef, should be:
+ * - LPC_CAN1: CAN1 peripheral
+ * - LPC_CAN2: CAN2 peripheral
+ * @param[in] id: The ID of entry will be added
+ * @param[in] format: is the type of ID Frame Format, should be:
+ * - STD_ID_FORMAT: 11-bit ID value
+ * - EXT_ID_FORMAT: 29-bit ID value
+ * @return CAN Error, could be:
+ * - CAN_OBJECTS_FULL_ERROR: No more rx or tx objects available
+ * - CAN_ID_EXIT_ERROR: ID exited in table
+ * - CAN_OK: ID is added into table successfully
+ *********************************************************************/
+CAN_ERROR CAN_LoadExplicitEntry(LPC_CAN_TypeDef* CANx, uint32_t id, CAN_ID_FORMAT_Type format)
+{
+ uint32_t tmp0 = 0;
+ uint32_t buf0=0, buf1=0;
+ int16_t cnt1=0, cnt2=0, bound1=0, total=0;
+
+
+ CHECK_PARAM(PARAM_CANx(CANx));
+ CHECK_PARAM(PARAM_ID_FORMAT(format));
+
+ if (CANx == LPC_CAN1)
+ {
+ tmp0 = 0;
+ }
+ else if (CANx == LPC_CAN2)
+ {
+ tmp0 = 1;
+ }
+
+ /* Acceptance Filter Memory full - return */
+ total =((CANAF_FullCAN_cnt+1)>>1)+ CANAF_FullCAN_cnt*3 +((CANAF_std_cnt + 1) >> 1)+ \
+ CANAF_gstd_cnt + CANAF_ext_cnt + (CANAF_gext_cnt<<1);
+ if (total >= 512){ //don't have enough space
+ return CAN_OBJECTS_FULL_ERROR;
+ }
+
+ /* Setup Acceptance Filter Configuration
+ Acceptance Filter Mode Register = Off */
+ LPC_CANAF->AFMR = 0x00000001;
+
+/*********** Add Explicit Standard Identifier Frame Format entry *********/
+ if(format == STD_ID_FORMAT)
+ {
+ id &= 0x07FF;
+ id |= (tmp0 << 13); /* Add controller number */
+ /* Move all remaining sections one place up
+ if new entry will increase FullCAN list */
+ if ((CANAF_std_cnt & 0x0001) == 0)
+ {
+ cnt1 = ((CANAF_FullCAN_cnt+1)>>1)+((CANAF_std_cnt+1)>>1);
+ bound1 = total - cnt1;
+ buf0 = LPC_CANAF_RAM->mask[cnt1];
+ while(bound1--)
+ {
+ cnt1++;
+ buf1 = LPC_CANAF_RAM->mask[cnt1];
+ LPC_CANAF_RAM->mask[cnt1] = buf0;
+ buf0 = buf1;
+ }
+ }
+ if (CANAF_std_cnt == 0)
+ {
+ cnt2 = (CANAF_FullCAN_cnt + 1)>>1;
+ /* For entering first ID */
+ LPC_CANAF_RAM->mask[cnt2] = 0x0000FFFF | (id << 16);
+ }
+ else if (CANAF_std_cnt == 1)
+ {
+ cnt2 = (CANAF_FullCAN_cnt + 1)>>1;
+ /* For entering second ID */
+ if ((LPC_CANAF_RAM->mask[cnt2] >> 16) > id)
+ {
+ LPC_CANAF_RAM->mask[cnt2] = (LPC_CANAF_RAM->mask[cnt2] >> 16) | (id << 16);
+ }
+ else
+ {
+ LPC_CANAF_RAM->mask[cnt2] = (LPC_CANAF_RAM->mask[cnt2] & 0xFFFF0000) | id;
+ }
+ }
+ else
+ {
+ /* Find where to insert new ID */
+ cnt1 = (CANAF_FullCAN_cnt+1)>>1;
+ cnt2 = CANAF_std_cnt;
+ bound1 = ((CANAF_FullCAN_cnt+1)>>1)+((CANAF_std_cnt+1)>>1);
+ while (cnt1 < bound1)
+ {
+ /* Loop through standard existing IDs */
+ if ((LPC_CANAF_RAM->mask[cnt1] >> 16) > id)
+ {
+ cnt2 = cnt1 * 2;
+ break;
+ }
+
+ if ((LPC_CANAF_RAM->mask[cnt1] & 0x0000FFFF) > id)
+ {
+ cnt2 = cnt1 * 2 + 1;
+ break;
+ }
+
+ cnt1++;
+ }
+ /* cnt1 = U32 where to insert new ID */
+ /* cnt2 = U16 where to insert new ID */
+
+ if (cnt1 == bound1)
+ {
+ /* Adding ID as last entry */
+ /* Even number of IDs exists */
+ if ((CANAF_std_cnt & 0x0001) == 0)
+ {
+ LPC_CANAF_RAM->mask[cnt1] = 0x0000FFFF | (id << 16);
+ }
+ /* Odd number of IDs exists */
+ else
+ {
+ LPC_CANAF_RAM->mask[cnt1] = (LPC_CANAF_RAM->mask[cnt1] & 0xFFFF0000) | id;
+ }
+ }
+ else
+ {
+ buf0 = LPC_CANAF_RAM->mask[cnt1]; /* Remember current entry */
+ if ((cnt2 & 0x0001) == 0)
+ {
+ /* Insert new mask to even address*/
+ buf1 = (id << 16) | (buf0 >> 16);
+ }
+ else
+ {
+ /* Insert new mask to odd address */
+ buf1 = (buf0 & 0xFFFF0000) | id;
+ }
+ LPC_CANAF_RAM->mask[cnt1] = buf1;/* Insert mask */
+ bound1 = ((CANAF_FullCAN_cnt+1)>>1)+((CANAF_std_cnt+1)>>1)-1;
+ /* Move all remaining standard mask entries one place up */
+ while (cnt1 < bound1)
+ {
+ cnt1++;
+ buf1 = LPC_CANAF_RAM->mask[cnt1];
+ LPC_CANAF_RAM->mask[cnt1] = (buf1 >> 16) | (buf0 << 16);
+ buf0 = buf1;
+ }
+
+ if ((CANAF_std_cnt & 0x0001) == 0)
+ {
+ /* Even number of IDs exists */
+ LPC_CANAF_RAM->mask[cnt1+1] = (buf0 <<16) |(0x0000FFFF);
+ }
+ }
+ }
+ CANAF_std_cnt++;
+ //update address values
+ LPC_CANAF->SFF_GRP_sa +=0x04 ;
+ LPC_CANAF->EFF_sa +=0x04 ;
+ LPC_CANAF->EFF_GRP_sa +=0x04;
+ LPC_CANAF->ENDofTable +=0x04;
+ }
+
+/*********** Add Explicit Extended Identifier Frame Format entry *********/
+ else
+ {
+ /* Add controller number */
+ id |= (tmp0) << 29;
+
+ cnt1 = ((CANAF_FullCAN_cnt+1)>>1)+(((CANAF_std_cnt + 1) >> 1) + CANAF_gstd_cnt);
+ cnt2 = 0;
+ while (cnt2 < CANAF_ext_cnt)
+ {
+ /* Loop through extended existing masks*/
+ if (LPC_CANAF_RAM->mask[cnt1] > id)
+ {
+ break;
+ }
+ cnt1++;/* cnt1 = U32 where to insert new mask */
+ cnt2++;
+ }
+
+ buf0 = LPC_CANAF_RAM->mask[cnt1]; /* Remember current entry */
+ LPC_CANAF_RAM->mask[cnt1] = id; /* Insert mask */
+
+ CANAF_ext_cnt++;
+
+ bound1 = total;
+ /* Move all remaining extended mask entries one place up*/
+ while (cnt2 < bound1)
+ {
+ cnt1++;
+ cnt2++;
+ buf1 = LPC_CANAF_RAM->mask[cnt1];
+ LPC_CANAF_RAM->mask[cnt1] = buf0;
+ buf0 = buf1;
+ }
+ /* update address values */
+ LPC_CANAF->EFF_GRP_sa += 4;
+ LPC_CANAF->ENDofTable += 4;
+ }
+ if(CANAF_FullCAN_cnt == 0) //not use FullCAN mode
+ {
+ LPC_CANAF->AFMR = 0x00;//not use FullCAN mode
+ }
+ else
+ {
+ LPC_CANAF->AFMR = 0x04;
+ }
+
+ return CAN_OK;
+}
+
+/********************************************************************//**
+ * @brief Load FullCAN entry into AFLUT
+ * @param[in] CANx: CAN peripheral selected, should be:
+ * - LPC_CAN1: CAN1 peripheral
+ * - LPC_CAN2: CAN2 peripheral
+ * @param[in] id: identifier of entry that will be added
+ * @return CAN_ERROR, could be:
+ * - CAN_OK: loading is successful
+ * - CAN_ID_EXIT_ERROR: ID exited in FullCAN Section
+ * - CAN_OBJECTS_FULL_ERROR: no more space available
+ *********************************************************************/
+CAN_ERROR CAN_LoadFullCANEntry (LPC_CAN_TypeDef* CANx, uint16_t id)
+{
+ uint32_t ctrl0 = 0;
+ uint32_t buf0=0, buf1=0, buf2=0;
+ uint32_t tmp0=0, tmp1=0, tmp2=0;
+ int16_t cnt1=0, cnt2=0, bound1=0, total=0;
+
+ CHECK_PARAM(PARAM_CANx(CANx));
+
+ if (CANx == LPC_CAN1)
+ {
+ ctrl0 = 0;
+ }
+ else if (CANx == LPC_CAN2)
+ {
+ ctrl0 = 1;
+ }
+
+ /* Acceptance Filter Memory full - return */
+ total =((CANAF_FullCAN_cnt+1)>>1)+ CANAF_FullCAN_cnt*3 +((CANAF_std_cnt + 1) >> 1)+ \
+ CANAF_gstd_cnt + CANAF_ext_cnt + (CANAF_gext_cnt<<1);
+ //don't have enough space for this fullCAN Entry and its Object(3*32 bytes)
+ if ((total >=508)||(CANAF_FullCAN_cnt>=64)){
+ return CAN_OBJECTS_FULL_ERROR;
+ }
+ /* Setup Acceptance Filter Configuration
+ Acceptance Filter Mode Register = Off */
+ LPC_CANAF->AFMR = 0x00000001;
+
+ /* Add mask for standard identifiers */
+ id &= 0x07FF;
+ id |= (ctrl0 << 13) | (1 << 11); /* Add controller number */
+// total = ((CANAF_std_cnt + 1) >> 1)+ CANAF_gstd_cnt + CANAF_ext_cnt + (CANAF_gext_cnt<<1);
+ /* Move all remaining sections one place up
+ if new entry will increase FullCAN list */
+ if (((CANAF_FullCAN_cnt & 0x0001) == 0)&&(total!=0))
+ {
+ //then remove remaining section
+ cnt1 = (CANAF_FullCAN_cnt >> 1);
+ bound1 = total;
+ buf0 = LPC_CANAF_RAM->mask[cnt1];
+
+ while (bound1--)
+ {
+ cnt1++;
+ buf1 = LPC_CANAF_RAM->mask[cnt1];
+ LPC_CANAF_RAM->mask[cnt1] = buf0;
+ buf0 = buf1;
+ }
+ }
+ if (CANAF_FullCAN_cnt == 0)
+ {
+ /* For entering first ID */
+ LPC_CANAF_RAM->mask[0] = 0x0000FFFF | (id << 16);
+ }
+ else if (CANAF_FullCAN_cnt == 1)
+ {
+ /* For entering second ID */
+ if ((LPC_CANAF_RAM->mask[0] >> 16) > id)
+ {
+ LPC_CANAF_RAM->mask[0] = (LPC_CANAF_RAM->mask[0] >> 16) | (id << 16);
+ }
+ else
+ {
+ LPC_CANAF_RAM->mask[0] = (LPC_CANAF_RAM->mask[0] & 0xFFFF0000) | id;
+ }
+ }
+ else
+ {
+ /* Find where to insert new ID */
+ cnt1 = 0;
+ cnt2 = CANAF_FullCAN_cnt;
+ bound1 = (CANAF_FullCAN_cnt - 1) >> 1;
+ while (cnt1 <= bound1)
+ {
+ /* Loop through standard existing IDs */
+ if ((LPC_CANAF_RAM->mask[cnt1] >> 16) > id)
+ {
+ cnt2 = cnt1 * 2;
+ break;
+ }
+
+ if ((LPC_CANAF_RAM->mask[cnt1] & 0x0000FFFF) > id)
+ {
+ cnt2 = cnt1 * 2 + 1;
+ break;
+ }
+
+ cnt1++;
+ }
+ /* cnt1 = U32 where to insert new ID */
+ /* cnt2 = U16 where to insert new ID */
+
+ if (cnt1 > bound1)
+ {
+ /* Adding ID as last entry */
+ /* Even number of IDs exists */
+ if ((CANAF_FullCAN_cnt & 0x0001) == 0)
+ {
+ LPC_CANAF_RAM->mask[cnt1] = 0x0000FFFF | (id << 16);
+ }
+ /* Odd number of IDs exists */
+ else
+ {
+ LPC_CANAF_RAM->mask[cnt1] = (LPC_CANAF_RAM->mask[cnt1] & 0xFFFF0000) | id;
+ }
+ }
+ else
+ {
+ buf0 = LPC_CANAF_RAM->mask[cnt1]; /* Remember current entry */
+ if ((cnt2 & 0x0001) == 0)
+ {
+ /* Insert new mask to even address*/
+ buf1 = (id << 16) | (buf0 >> 16);
+ }
+ else
+ {
+ /* Insert new mask to odd address */
+ buf1 = (buf0 & 0xFFFF0000) | id;
+ }
+ LPC_CANAF_RAM->mask[cnt1] = buf1;/* Insert mask */
+ bound1 = CANAF_FullCAN_cnt >> 1;
+ /* Move all remaining standard mask entries one place up */
+ while (cnt1 < bound1)
+ {
+ cnt1++;
+ buf1 = LPC_CANAF_RAM->mask[cnt1];
+ LPC_CANAF_RAM->mask[cnt1] = (buf1 >> 16) | (buf0 << 16);
+ buf0 = buf1;
+ }
+
+ if ((CANAF_FullCAN_cnt & 0x0001) == 0)
+ {
+ /* Even number of IDs exists */
+ LPC_CANAF_RAM->mask[cnt1] = (LPC_CANAF_RAM->mask[cnt1] & 0xFFFF0000)
+ | (0x0000FFFF);
+ }
+ }
+ }
+ //restruct FulCAN Object Section
+ bound1 = CANAF_FullCAN_cnt - cnt2;
+ cnt1 = total - (CANAF_FullCAN_cnt)*3 + cnt2*3 + 1;
+ buf0 = LPC_CANAF_RAM->mask[cnt1];
+ buf1 = LPC_CANAF_RAM->mask[cnt1+1];
+ buf2 = LPC_CANAF_RAM->mask[cnt1+2];
+ LPC_CANAF_RAM->mask[cnt1]=LPC_CANAF_RAM->mask[cnt1+1]= LPC_CANAF_RAM->mask[cnt1+2]=0x00;
+ cnt1+=3;
+ while(bound1--)
+ {
+ tmp0 = LPC_CANAF_RAM->mask[cnt1];
+ tmp1 = LPC_CANAF_RAM->mask[cnt1+1];
+ tmp2 = LPC_CANAF_RAM->mask[cnt1+2];
+ LPC_CANAF_RAM->mask[cnt1]= buf0;
+ LPC_CANAF_RAM->mask[cnt1+1]= buf1;
+ LPC_CANAF_RAM->mask[cnt1+2]= buf2;
+ buf0 = tmp0;
+ buf1 = tmp1;
+ buf2 = tmp2;
+ cnt1+=3;
+ }
+ CANAF_FullCAN_cnt++;
+ //update address values
+ LPC_CANAF->SFF_sa +=0x04;
+ LPC_CANAF->SFF_GRP_sa +=0x04 ;
+ LPC_CANAF->EFF_sa +=0x04 ;
+ LPC_CANAF->EFF_GRP_sa +=0x04;
+ LPC_CANAF->ENDofTable +=0x04;
+
+ LPC_CANAF->AFMR = 0x04;
+ return CAN_OK;
+}
+
+/********************************************************************//**
+ * @brief Load Group entry into AFLUT
+ * @param[in] CANx: CAN peripheral selected, should be:
+ * - LPC_CAN1: CAN1 peripheral
+ * - LPC_CAN2: CAN2 peripheral
+ * @param[in] lowerID, upperID: lower and upper identifier of entry
+ * @param[in] format: type of ID format, should be:
+ * - STD_ID_FORMAT: Standard ID format (11-bit value)
+ * - EXT_ID_FORMAT: Extended ID format (29-bit value)
+ * @return CAN_ERROR, could be:
+ * - CAN_OK: loading is successful
+ * - CAN_CONFLICT_ID_ERROR: Conflict ID occurs
+ * - CAN_OBJECTS_FULL_ERROR: no more space available
+ *********************************************************************/
+CAN_ERROR CAN_LoadGroupEntry(LPC_CAN_TypeDef* CANx, uint32_t lowerID, \
+ uint32_t upperID, CAN_ID_FORMAT_Type format)
+{
+ uint16_t tmp = 0;
+ uint32_t buf0, buf1, entry1, entry2, LID,UID;
+ int16_t cnt1, bound1, total;
+
+ CHECK_PARAM(PARAM_CANx(CANx));
+ CHECK_PARAM(PARAM_ID_FORMAT(format));
+
+ if(lowerID > upperID) return CAN_CONFLICT_ID_ERROR;
+ if(CANx == LPC_CAN1)
+ {
+ tmp = 0;
+ }
+ else
+ {
+ tmp = 1;
+ }
+
+ total =((CANAF_FullCAN_cnt+1)>>1)+ CANAF_FullCAN_cnt*3 +((CANAF_std_cnt + 1) >> 1)+ \
+ CANAF_gstd_cnt + CANAF_ext_cnt + (CANAF_gext_cnt<<1);
+
+ /* Setup Acceptance Filter Configuration
+ Acceptance Filter Mode Register = Off */
+ LPC_CANAF->AFMR = 0x00000001;
+
+/*********Add Group of Standard Identifier Frame Format************/
+ if(format == STD_ID_FORMAT)
+ {
+ if ((total >= 512)){//don't have enough space
+ return CAN_OBJECTS_FULL_ERROR;
+ }
+ lowerID &=0x7FF; //mask ID
+ upperID &=0x7FF;
+ entry1 = (tmp << 29)|(lowerID << 16)|(tmp << 13)|(upperID << 0);
+ cnt1 = ((CANAF_FullCAN_cnt+1)>>1) + ((CANAF_std_cnt + 1) >> 1);
+
+ //if this is the first Group standard ID entry
+ if(CANAF_gstd_cnt == 0)
+ {
+ LPC_CANAF_RAM->mask[cnt1] = entry1;
+ }
+ else
+ {
+ //find the position to add new Group entry
+ bound1 = ((CANAF_FullCAN_cnt+1)>>1) + ((CANAF_std_cnt + 1) >> 1) + CANAF_gstd_cnt;
+ while(cnt1 < bound1)
+ {
+ buf0 = LPC_CANAF_RAM->mask[cnt1];
+ LID = (buf0 >> 16)&0x7FF;
+ UID = buf0 & 0x7FF;
+ if (upperID <= LID)
+ {
+ //add new entry before this entry
+ LPC_CANAF_RAM->mask[cnt1] = entry1;
+ break;
+ }
+ else if (lowerID >= UID)
+ {
+ //load next entry to compare
+ cnt1 ++;
+ }
+ else
+ return CAN_CONFLICT_ID_ERROR;
+ }
+ if(cnt1 >= bound1)
+ {
+ //add new entry at the last position in this list
+ buf0 = LPC_CANAF_RAM->mask[cnt1];
+ LPC_CANAF_RAM->mask[cnt1] = entry1;
+ }
+
+ //remove all remaining entry of this section one place up
+ bound1 = total - cnt1;
+ while(bound1--)
+ {
+ cnt1++;
+ buf1 = LPC_CANAF_RAM->mask[cnt1];
+ LPC_CANAF_RAM->mask[cnt1] = buf0;
+ buf0 = buf1;
+ }
+ }
+ CANAF_gstd_cnt++;
+ //update address values
+ LPC_CANAF->EFF_sa +=0x04 ;
+ LPC_CANAF->EFF_GRP_sa +=0x04;
+ LPC_CANAF->ENDofTable +=0x04;
+ }
+
+
+/*********Add Group of Extended Identifier Frame Format************/
+ else
+ {
+ if ((total >= 511)){//don't have enough space
+ return CAN_OBJECTS_FULL_ERROR;
+ }
+ lowerID &= 0x1FFFFFFF; //mask ID
+ upperID &= 0x1FFFFFFF;
+ entry1 = (tmp << 29)|(lowerID << 0);
+ entry2 = (tmp << 29)|(upperID << 0);
+
+ cnt1 = ((CANAF_FullCAN_cnt+1)>>1) + ((CANAF_std_cnt + 1) >> 1) + CANAF_gstd_cnt + CANAF_ext_cnt;
+ //if this is the first Group standard ID entry
+ if(CANAF_gext_cnt == 0)
+ {
+ LPC_CANAF_RAM->mask[cnt1] = entry1;
+ LPC_CANAF_RAM->mask[cnt1+1] = entry2;
+ }
+ else
+ {
+ //find the position to add new Group entry
+ bound1 = ((CANAF_FullCAN_cnt+1)>>1) + ((CANAF_std_cnt + 1) >> 1) + CANAF_gstd_cnt \
+ + CANAF_ext_cnt + (CANAF_gext_cnt<<1);
+ while(cnt1 < bound1)
+ {
+ buf0 = LPC_CANAF_RAM->mask[cnt1];
+ buf1 = LPC_CANAF_RAM->mask[cnt1+1];
+ LID = buf0 & 0x1FFFFFFF; //mask ID
+ UID = buf1 & 0x1FFFFFFF;
+ if (upperID <= LID)
+ {
+ //add new entry before this entry
+ LPC_CANAF_RAM->mask[cnt1] = entry1;
+ LPC_CANAF_RAM->mask[++cnt1] = entry2;
+ break;
+ }
+ else if (lowerID >= UID)
+ {
+ //load next entry to compare
+ cnt1 +=2;
+ }
+ else
+ return CAN_CONFLICT_ID_ERROR;
+ }
+ if(cnt1 >= bound1)
+ {
+ //add new entry at the last position in this list
+ buf0 = LPC_CANAF_RAM->mask[cnt1];
+ buf1 = LPC_CANAF_RAM->mask[cnt1+1];
+ LPC_CANAF_RAM->mask[cnt1] = entry1;
+ LPC_CANAF_RAM->mask[++cnt1] = entry2;
+ }
+ //remove all remaining entry of this section two place up
+ bound1 = total - cnt1 + 1;
+ cnt1++;
+ while(bound1>0)
+ {
+ entry1 = LPC_CANAF_RAM->mask[cnt1];
+ entry2 = LPC_CANAF_RAM->mask[cnt1+1];
+ LPC_CANAF_RAM->mask[cnt1] = buf0;
+ LPC_CANAF_RAM->mask[cnt1+1] = buf1;
+ buf0 = entry1;
+ buf1 = entry2;
+ cnt1 +=2;
+ bound1 -=2;
+ }
+ }
+ CANAF_gext_cnt++;
+ //update address values
+ LPC_CANAF->ENDofTable +=0x08;
+ }
+ LPC_CANAF->AFMR = 0x04;
+ return CAN_OK;
+}
+
+/********************************************************************//**
+ * @brief Remove AFLUT entry (FullCAN entry and Explicit Standard entry)
+ * @param[in] EntryType: the type of entry that want to remove, should be:
+ * - FULLCAN_ENTRY
+ * - EXPLICIT_STANDARD_ENTRY
+ * - GROUP_STANDARD_ENTRY
+ * - EXPLICIT_EXTEND_ENTRY
+ * - GROUP_EXTEND_ENTRY
+ * @param[in] position: the position of this entry in its section
+ * Note: the first position is 0
+ * @return CAN_ERROR, could be:
+ * - CAN_OK: removing is successful
+ * - CAN_ENTRY_NOT_EXIT_ERROR: entry want to remove is not exit
+ *********************************************************************/
+CAN_ERROR CAN_RemoveEntry(AFLUT_ENTRY_Type EntryType, uint16_t position)
+{
+ uint16_t cnt, bound, total;
+ uint32_t buf0, buf1;
+ CHECK_PARAM(PARAM_AFLUT_ENTRY_TYPE(EntryType));
+ CHECK_PARAM(PARAM_POSITION(position));
+
+ /* Setup Acceptance Filter Configuration
+ Acceptance Filter Mode Register = Off */
+ LPC_CANAF->AFMR = 0x00000001;
+ total = ((CANAF_FullCAN_cnt+1)>>1)+((CANAF_std_cnt + 1) >> 1) + \
+ CANAF_gstd_cnt + CANAF_ext_cnt + (CANAF_gext_cnt<<1);
+
+
+/************** Remove FullCAN Entry *************/
+ if(EntryType == FULLCAN_ENTRY)
+ {
+ if((CANAF_FullCAN_cnt==0)||(position >= CANAF_FullCAN_cnt))
+ {
+ return CAN_ENTRY_NOT_EXIT_ERROR;
+ }
+ else
+ {
+ cnt = position >> 1;
+ buf0 = LPC_CANAF_RAM->mask[cnt];
+ bound = (CANAF_FullCAN_cnt - position -1)>>1;
+ if((position & 0x0001) == 0) //event position
+ {
+ while(bound--)
+ {
+ //remove all remaining FullCAN entry one place down
+ buf1 = LPC_CANAF_RAM->mask[cnt+1];
+ LPC_CANAF_RAM->mask[cnt] = (buf1 >> 16) | (buf0 << 16);
+ buf0 = buf1;
+ cnt++;
+ }
+ }
+ else //odd position
+ {
+ while(bound--)
+ {
+ //remove all remaining FullCAN entry one place down
+ buf1 = LPC_CANAF_RAM->mask[cnt+1];
+ LPC_CANAF_RAM->mask[cnt] = (buf0 & 0xFFFF0000)|(buf1 >> 16);
+ LPC_CANAF_RAM->mask[cnt+1] = LPC_CANAF_RAM->mask[cnt+1] << 16;
+ buf0 = buf1<<16;
+ cnt++;
+ }
+ }
+ if((CANAF_FullCAN_cnt & 0x0001) == 0)
+ {
+ if((position & 0x0001)==0)
+ LPC_CANAF_RAM->mask[cnt] = (buf0 << 16) | (0x0000FFFF);
+ else
+ LPC_CANAF_RAM->mask[cnt] = buf0 | 0x0000FFFF;
+ }
+ else
+ {
+ //remove all remaining section one place down
+ cnt = (CANAF_FullCAN_cnt + 1)>>1;
+ bound = total + CANAF_FullCAN_cnt * 3;
+ while(bound>cnt)
+ {
+ LPC_CANAF_RAM->mask[cnt-1] = LPC_CANAF_RAM->mask[cnt];
+ cnt++;
+ }
+ LPC_CANAF_RAM->mask[cnt-1]=0x00;
+ //update address values
+ LPC_CANAF->SFF_sa -=0x04;
+ LPC_CANAF->SFF_GRP_sa -=0x04 ;
+ LPC_CANAF->EFF_sa -=0x04 ;
+ LPC_CANAF->EFF_GRP_sa -=0x04;
+ LPC_CANAF->ENDofTable -=0x04;
+ }
+ CANAF_FullCAN_cnt--;
+
+ //delete its FullCAN Object in the FullCAN Object section
+ //remove all remaining FullCAN Object three place down
+ cnt = total + position * 3;
+ bound = (CANAF_FullCAN_cnt - position + 1) * 3;
+
+ while(bound)
+ {
+ LPC_CANAF_RAM->mask[cnt]=LPC_CANAF_RAM->mask[cnt+3];;
+ LPC_CANAF_RAM->mask[cnt+1]=LPC_CANAF_RAM->mask[cnt+4];
+ LPC_CANAF_RAM->mask[cnt+2]=LPC_CANAF_RAM->mask[cnt+5];
+ bound -=3;
+ cnt +=3;
+ }
+ }
+ }
+
+/************** Remove Explicit Standard ID Entry *************/
+ else if(EntryType == EXPLICIT_STANDARD_ENTRY)
+ {
+ if((CANAF_std_cnt==0)||(position >= CANAF_std_cnt))
+ {
+ return CAN_ENTRY_NOT_EXIT_ERROR;
+ }
+ else
+ {
+ cnt = ((CANAF_FullCAN_cnt+1)>>1)+ (position >> 1);
+ buf0 = LPC_CANAF_RAM->mask[cnt];
+ bound = (CANAF_std_cnt - position - 1)>>1;
+ if((position & 0x0001) == 0) //event position
+ {
+ while(bound--)
+ {
+ //remove all remaining FullCAN entry one place down
+ buf1 = LPC_CANAF_RAM->mask[cnt+1];
+ LPC_CANAF_RAM->mask[cnt] = (buf1 >> 16) | (buf0 << 16);
+ buf0 = buf1;
+ cnt++;
+ }
+ }
+ else //odd position
+ {
+ while(bound--)
+ {
+ //remove all remaining FullCAN entry one place down
+ buf1 = LPC_CANAF_RAM->mask[cnt+1];
+ LPC_CANAF_RAM->mask[cnt] = (buf0 & 0xFFFF0000)|(buf1 >> 16);
+ LPC_CANAF_RAM->mask[cnt+1] = LPC_CANAF_RAM->mask[cnt+1] << 16;
+ buf0 = buf1<<16;
+ cnt++;
+ }
+ }
+ if((CANAF_std_cnt & 0x0001) == 0)
+ {
+ if((position & 0x0001)==0)
+ LPC_CANAF_RAM->mask[cnt] = (buf0 << 16) | (0x0000FFFF);
+ else
+ LPC_CANAF_RAM->mask[cnt] = buf0 | 0x0000FFFF;
+ }
+ else
+ {
+ //remove all remaining section one place down
+ cnt = ((CANAF_FullCAN_cnt + 1)>>1) + ((CANAF_std_cnt + 1) >> 1);
+ bound = total + CANAF_FullCAN_cnt * 3;
+ while(bound>cnt)
+ {
+ LPC_CANAF_RAM->mask[cnt-1] = LPC_CANAF_RAM->mask[cnt];
+ cnt++;
+ }
+ LPC_CANAF_RAM->mask[cnt-1]=0x00;
+ //update address value
+ LPC_CANAF->SFF_GRP_sa -=0x04 ;
+ LPC_CANAF->EFF_sa -=0x04 ;
+ LPC_CANAF->EFF_GRP_sa -=0x04;
+ LPC_CANAF->ENDofTable -=0x04;
+ }
+ CANAF_std_cnt--;
+ }
+ }
+
+/************** Remove Group of Standard ID Entry *************/
+ else if(EntryType == GROUP_STANDARD_ENTRY)
+ {
+ if((CANAF_gstd_cnt==0)||(position >= CANAF_gstd_cnt))
+ {
+ return CAN_ENTRY_NOT_EXIT_ERROR;
+ }
+ else
+ {
+ cnt = ((CANAF_FullCAN_cnt + 1)>>1) + ((CANAF_std_cnt + 1) >> 1)+ position + 1;
+ bound = total + CANAF_FullCAN_cnt * 3;
+ while (cnt<bound)
+ {
+ LPC_CANAF_RAM->mask[cnt-1] = LPC_CANAF_RAM->mask[cnt];
+ cnt++;
+ }
+ LPC_CANAF_RAM->mask[cnt-1]=0x00;
+ }
+ CANAF_gstd_cnt--;
+ //update address value
+ LPC_CANAF->EFF_sa -=0x04;
+ LPC_CANAF->EFF_GRP_sa -=0x04;
+ LPC_CANAF->ENDofTable -=0x04;
+ }
+
+/************** Remove Explicit Extended ID Entry *************/
+ else if(EntryType == EXPLICIT_EXTEND_ENTRY)
+ {
+ if((CANAF_ext_cnt==0)||(position >= CANAF_ext_cnt))
+ {
+ return CAN_ENTRY_NOT_EXIT_ERROR;
+ }
+ else
+ {
+ cnt = ((CANAF_FullCAN_cnt + 1)>>1) + ((CANAF_std_cnt + 1) >> 1)+ CANAF_gstd_cnt + position + 1;
+ bound = total + CANAF_FullCAN_cnt * 3;
+ while (cnt<bound)
+ {
+ LPC_CANAF_RAM->mask[cnt-1] = LPC_CANAF_RAM->mask[cnt];
+ cnt++;
+ }
+ LPC_CANAF_RAM->mask[cnt-1]=0x00;
+ }
+ CANAF_ext_cnt--;
+ LPC_CANAF->EFF_GRP_sa -=0x04;
+ LPC_CANAF->ENDofTable -=0x04;
+ }
+
+/************** Remove Group of Extended ID Entry *************/
+ else
+ {
+ if((CANAF_gext_cnt==0)||(position >= CANAF_gext_cnt))
+ {
+ return CAN_ENTRY_NOT_EXIT_ERROR;
+ }
+ else
+ {
+ cnt = total - (CANAF_gext_cnt<<1) + (position<<1);
+ bound = total + CANAF_FullCAN_cnt * 3;
+ while (cnt<bound)
+ {
+ //remove all remaining entry two place up
+ LPC_CANAF_RAM->mask[cnt] = LPC_CANAF_RAM->mask[cnt+2];
+ LPC_CANAF_RAM->mask[cnt+1] = LPC_CANAF_RAM->mask[cnt+3];
+ cnt+=2;
+ }
+ }
+ CANAF_gext_cnt--;
+ LPC_CANAF->ENDofTable -=0x08;
+ }
+ LPC_CANAF->AFMR = 0x04;
+ return CAN_OK;
+}
+
+/********************************************************************//**
+ * @brief Send message data
+ * @param[in] CANx pointer to LPC_CAN_TypeDef, should be:
+ * - LPC_CAN1: CAN1 peripheral
+ * - LPC_CAN2: CAN2 peripheral
+ * @param[in] CAN_Msg point to the CAN_MSG_Type Structure, it contains message
+ * information such as: ID, DLC, RTR, ID Format
+ * @return Status:
+ * - SUCCESS: send message successfully
+ * - ERROR: send message unsuccessfully
+ *********************************************************************/
+Status CAN_SendMsg (LPC_CAN_TypeDef *CANx, CAN_MSG_Type *CAN_Msg)
+{
+ uint32_t data;
+ CHECK_PARAM(PARAM_CANx(CANx));
+ CHECK_PARAM(PARAM_ID_FORMAT(CAN_Msg->format));
+ if(CAN_Msg->format==STD_ID_FORMAT)
+ {
+ CHECK_PARAM(PARAM_ID_11(CAN_Msg->id));
+ }
+ else
+ {
+ CHECK_PARAM(PARAM_ID_29(CAN_Msg->id));
+ }
+ CHECK_PARAM(PARAM_DLC(CAN_Msg->len));
+ CHECK_PARAM(PARAM_FRAME_TYPE(CAN_Msg->type));
+
+ //Check status of Transmit Buffer 1
+ if ((CANx->SR & 0x00000004)>>2)
+ {
+ /* Transmit Channel 1 is available */
+ /* Write frame informations and frame data into its CANxTFI1,
+ * CANxTID1, CANxTDA1, CANxTDB1 register */
+ CANx->TFI1 &= ~0x000F0000;
+ CANx->TFI1 |= (CAN_Msg->len)<<16;
+ if(CAN_Msg->type == REMOTE_FRAME)
+ {
+ CANx->TFI1 |= (1<<30); //set bit RTR
+ }
+ else
+ {
+ CANx->TFI1 &= ~(1<<30);
+ }
+ if(CAN_Msg->format == EXT_ID_FORMAT)
+ {
+ CANx->TFI1 |= (1<<31); //set bit FF
+ }
+ else
+ {
+ CANx->TFI1 &= ~(1<<31);
+ }
+
+ /* Write CAN ID*/
+ CANx->TID1 = CAN_Msg->id;
+
+ /*Write first 4 data bytes*/
+ data = (CAN_Msg->dataA[0])|(((CAN_Msg->dataA[1]))<<8)|((CAN_Msg->dataA[2])<<16)|((CAN_Msg->dataA[3])<<24);
+ CANx->TDA1 = data;
+
+ /*Write second 4 data bytes*/
+ data = (CAN_Msg->dataB[0])|(((CAN_Msg->dataB[1]))<<8)|((CAN_Msg->dataB[2])<<16)|((CAN_Msg->dataB[3])<<24);
+ CANx->TDB1 = data;
+
+ /*Write transmission request*/
+ CANx->CMR = 0x21;
+ return SUCCESS;
+ }
+ //check status of Transmit Buffer 2
+ else if((CANx->SR & 0x00000004)>>10)
+ {
+ /* Transmit Channel 2 is available */
+ /* Write frame informations and frame data into its CANxTFI2,
+ * CANxTID2, CANxTDA2, CANxTDB2 register */
+ CANx->TFI2 &= ~0x000F0000;
+ CANx->TFI2 |= (CAN_Msg->len)<<16;
+ if(CAN_Msg->type == REMOTE_FRAME)
+ {
+ CANx->TFI2 |= (1<<30); //set bit RTR
+ }
+ else
+ {
+ CANx->TFI2 &= ~(1<<30);
+ }
+ if(CAN_Msg->format == EXT_ID_FORMAT)
+ {
+ CANx->TFI2 |= (1<<31); //set bit FF
+ }
+ else
+ {
+ CANx->TFI2 &= ~(1<<31);
+ }
+
+ /* Write CAN ID*/
+ CANx->TID2 = CAN_Msg->id;
+
+ /*Write first 4 data bytes*/
+ data = (CAN_Msg->dataA[0])|(((CAN_Msg->dataA[1]))<<8)|((CAN_Msg->dataA[2])<<16)|((CAN_Msg->dataA[3])<<24);
+ CANx->TDA2 = data;
+
+ /*Write second 4 data bytes*/
+ data = (CAN_Msg->dataB[0])|(((CAN_Msg->dataB[1]))<<8)|((CAN_Msg->dataB[2])<<16)|((CAN_Msg->dataB[3])<<24);
+ CANx->TDB2 = data;
+
+ /*Write transmission request*/
+ CANx->CMR = 0x41;
+ return SUCCESS;
+ }
+ //check status of Transmit Buffer 3
+ else if ((CANx->SR & 0x00000004)>>18)
+ {
+ /* Transmit Channel 3 is available */
+ /* Write frame informations and frame data into its CANxTFI3,
+ * CANxTID3, CANxTDA3, CANxTDB3 register */
+ CANx->TFI3 &= ~0x000F0000;
+ CANx->TFI3 |= (CAN_Msg->len)<<16;
+ if(CAN_Msg->type == REMOTE_FRAME)
+ {
+ CANx->TFI3 |= (1<<30); //set bit RTR
+ }
+ else
+ {
+ CANx->TFI3 &= ~(1<<30);
+ }
+ if(CAN_Msg->format == EXT_ID_FORMAT)
+ {
+ CANx->TFI3 |= (1<<31); //set bit FF
+ }
+ else
+ {
+ CANx->TFI3 &= ~(1<<31);
+ }
+
+ /* Write CAN ID*/
+ CANx->TID3 = CAN_Msg->id;
+
+ /*Write first 4 data bytes*/
+ data = (CAN_Msg->dataA[0])|(((CAN_Msg->dataA[1]))<<8)|((CAN_Msg->dataA[2])<<16)|((CAN_Msg->dataA[3])<<24);
+ CANx->TDA3 = data;
+
+ /*Write second 4 data bytes*/
+ data = (CAN_Msg->dataB[0])|(((CAN_Msg->dataB[1]))<<8)|((CAN_Msg->dataB[2])<<16)|((CAN_Msg->dataB[3])<<24);
+ CANx->TDB3 = data;
+
+ /*Write transmission request*/
+ CANx->CMR = 0x81;
+ return SUCCESS;
+ }
+ else
+ {
+ return ERROR;
+ }
+}
+
+/********************************************************************//**
+ * @brief Receive message data
+ * @param[in] CANx pointer to LPC_CAN_TypeDef, should be:
+ * - LPC_CAN1: CAN1 peripheral
+ * - LPC_CAN2: CAN2 peripheral
+ * @param[in] CAN_Msg point to the CAN_MSG_Type Struct, it will contain received
+ * message information such as: ID, DLC, RTR, ID Format
+ * @return Status:
+ * - SUCCESS: receive message successfully
+ * - ERROR: receive message unsuccessfully
+ *********************************************************************/
+Status CAN_ReceiveMsg (LPC_CAN_TypeDef *CANx, CAN_MSG_Type *CAN_Msg)
+{
+ uint32_t data;
+
+ CHECK_PARAM(PARAM_CANx(CANx));
+
+ //check status of Receive Buffer
+ if((CANx->SR &0x00000001))
+ {
+ /* Receive message is available */
+ /* Read frame informations */
+ CAN_Msg->format = (uint8_t)(((CANx->RFS) & 0x80000000)>>31);
+ CAN_Msg->type = (uint8_t)(((CANx->RFS) & 0x40000000)>>30);
+ CAN_Msg->len = (uint8_t)(((CANx->RFS) & 0x000F0000)>>16);
+
+
+ /* Read CAN message identifier */
+ CAN_Msg->id = CANx->RID;
+
+ /* Read the data if received message was DATA FRAME */
+ if (CAN_Msg->type == DATA_FRAME)
+ {
+ /* Read first 4 data bytes */
+ data = CANx->RDA;
+ *((uint8_t *) &CAN_Msg->dataA[0])= data & 0x000000FF;
+ *((uint8_t *) &CAN_Msg->dataA[1])= (data & 0x0000FF00)>>8;;
+ *((uint8_t *) &CAN_Msg->dataA[2])= (data & 0x00FF0000)>>16;
+ *((uint8_t *) &CAN_Msg->dataA[3])= (data & 0xFF000000)>>24;
+
+ /* Read second 4 data bytes */
+ data = CANx->RDB;
+ *((uint8_t *) &CAN_Msg->dataB[0])= data & 0x000000FF;
+ *((uint8_t *) &CAN_Msg->dataB[1])= (data & 0x0000FF00)>>8;
+ *((uint8_t *) &CAN_Msg->dataB[2])= (data & 0x00FF0000)>>16;
+ *((uint8_t *) &CAN_Msg->dataB[3])= (data & 0xFF000000)>>24;
+
+ /*release receive buffer*/
+ CANx->CMR = 0x04;
+ }
+ else
+ {
+ /* Received Frame is a Remote Frame, not have data, we just receive
+ * message information only */
+ return SUCCESS;
+ }
+ }
+ else
+ {
+ // no receive message available
+ return ERROR;
+ }
+ return SUCCESS;
+}
+
+/********************************************************************//**
+ * @brief Receive FullCAN Object
+ * @param[in] CANAFx: CAN Acceptance Filter register, should be: LPC_CANAF
+ * @param[in] CAN_Msg point to the CAN_MSG_Type Struct, it will contain received
+ * message information such as: ID, DLC, RTR, ID Format
+ * @return CAN_ERROR, could be:
+ * - CAN_FULL_OBJ_NOT_RCV: FullCAN Object is not be received
+ * - CAN_OK: Received FullCAN Object successful
+ *
+ *********************************************************************/
+CAN_ERROR FCAN_ReadObj (LPC_CANAF_TypeDef* CANAFx, CAN_MSG_Type *CAN_Msg)
+{
+ uint32_t *pSrc, data;
+ uint32_t interrut_word, msg_idx, test_bit, head_idx, tail_idx;
+
+ CHECK_PARAM(PARAM_CANAFx(CANAFx));
+
+ interrut_word = 0;
+
+ if (LPC_CANAF->FCANIC0 != 0)
+ {
+ interrut_word = LPC_CANAF->FCANIC0;
+ head_idx = 0;
+ tail_idx = 31;
+ }
+ else if (LPC_CANAF->FCANIC1 != 0)
+ {
+ interrut_word = LPC_CANAF->FCANIC1;
+ head_idx = 32;
+ tail_idx = 63;
+ }
+
+ if (interrut_word != 0)
+ {
+ /* Detect for interrupt pending */
+ msg_idx = 0;
+ for (msg_idx = head_idx; msg_idx <= tail_idx; msg_idx++)
+ {
+ test_bit = interrut_word & 0x1;
+ interrut_word = interrut_word >> 1;
+
+ if (test_bit)
+ {
+ pSrc = (uint32_t *) (LPC_CANAF->ENDofTable + LPC_CANAF_RAM_BASE + msg_idx * 12);
+
+ /* Has been finished updating the content */
+ if ((*pSrc & 0x03000000L) == 0x03000000L)
+ {
+ /*clear semaphore*/
+ *pSrc &= 0xFCFFFFFF;
+
+ /*Set to DatA*/
+ pSrc++;
+ /* Copy to dest buf */
+ data = *pSrc;
+ *((uint8_t *) &CAN_Msg->dataA[0])= data & 0x000000FF;
+ *((uint8_t *) &CAN_Msg->dataA[1])= (data & 0x0000FF00)>>8;
+ *((uint8_t *) &CAN_Msg->dataA[2])= (data & 0x00FF0000)>>16;
+ *((uint8_t *) &CAN_Msg->dataA[3])= (data & 0xFF000000)>>24;
+
+ /*Set to DatB*/
+ pSrc++;
+ /* Copy to dest buf */
+ data = *pSrc;
+ *((uint8_t *) &CAN_Msg->dataB[0])= data & 0x000000FF;
+ *((uint8_t *) &CAN_Msg->dataB[1])= (data & 0x0000FF00)>>8;
+ *((uint8_t *) &CAN_Msg->dataB[2])= (data & 0x00FF0000)>>16;
+ *((uint8_t *) &CAN_Msg->dataB[3])= (data & 0xFF000000)>>24;
+ /*Back to Dat1*/
+ pSrc -= 2;
+
+ CAN_Msg->id = *pSrc & 0x7FF;
+ CAN_Msg->len = (uint8_t) (*pSrc >> 16) & 0x0F;
+ CAN_Msg->format = 0; //FullCAN Object ID always is 11-bit value
+ CAN_Msg->type = (uint8_t)(*pSrc >> 30) &0x01;
+ /*Re-read semaphore*/
+ if ((*pSrc & 0x03000000L) == 0)
+ {
+ return CAN_OK;
+ }
+ }
+ }
+ }
+ }
+ return CAN_FULL_OBJ_NOT_RCV;
+}
+/********************************************************************//**
+ * @brief Get CAN Control Status
+ * @param[in] CANx pointer to LPC_CAN_TypeDef, should be:
+ * - LPC_CAN1: CAN1 peripheral
+ * - LPC_CAN2: CAN2 peripheral
+ * @param[in] arg: type of CAN status to get from CAN status register
+ * Should be:
+ * - CANCTRL_GLOBAL_STS: CAN Global Status
+ * - CANCTRL_INT_CAP: CAN Interrupt and Capture
+ * - CANCTRL_ERR_WRN: CAN Error Warning Limit
+ * - CANCTRL_STS: CAN Control Status
+ * @return Current Control Status that you want to get value
+ *********************************************************************/
+uint32_t CAN_GetCTRLStatus (LPC_CAN_TypeDef* CANx, CAN_CTRL_STS_Type arg)
+{
+ CHECK_PARAM(PARAM_CANx(CANx));
+ CHECK_PARAM(PARAM_CTRL_STS_TYPE(arg));
+
+ switch (arg)
+ {
+ case CANCTRL_GLOBAL_STS:
+ return CANx->GSR;
+
+ case CANCTRL_INT_CAP:
+ return CANx->ICR;
+
+ case CANCTRL_ERR_WRN:
+ return CANx->EWL;
+
+ default: // CANCTRL_STS
+ return CANx->SR;
+ }
+}
+/********************************************************************//**
+ * @brief Get CAN Central Status
+ * @param[in] CANCRx point to LPC_CANCR_TypeDef, should be: LPC_CANCR
+ * @param[in] arg: type of CAN status to get from CAN Central status register
+ * Should be:
+ * - CANCR_TX_STS: Central CAN Tx Status
+ * - CANCR_RX_STS: Central CAN Rx Status
+ * - CANCR_MS: Central CAN Miscellaneous Status
+ * @return Current Central Status that you want to get value
+ *********************************************************************/
+uint32_t CAN_GetCRStatus (LPC_CANCR_TypeDef* CANCRx, CAN_CR_STS_Type arg)
+{
+ CHECK_PARAM(PARAM_CANCRx(CANCRx));
+ CHECK_PARAM(PARAM_CR_STS_TYPE(arg));
+
+ switch (arg)
+ {
+ case CANCR_TX_STS:
+ return CANCRx->CANTxSR;
+
+ case CANCR_RX_STS:
+ return CANCRx->CANRxSR;
+
+ default: // CANCR_MS
+ return CANCRx->CANMSR;
+ }
+}
+/********************************************************************//**
+ * @brief Enable/Disable CAN Interrupt
+ * @param[in] CANx pointer to LPC_CAN_TypeDef, should be:
+ * - LPC_CAN1: CAN1 peripheral
+ * - LPC_CAN2: CAN2 peripheral
+ * @param[in] arg: type of CAN interrupt that you want to enable/disable
+ * Should be:
+ * - CANINT_RIE: CAN Receiver Interrupt Enable
+ * - CANINT_TIE1: CAN Transmit Interrupt Enable
+ * - CANINT_EIE: CAN Error Warning Interrupt Enable
+ * - CANINT_DOIE: CAN Data Overrun Interrupt Enable
+ * - CANINT_WUIE: CAN Wake-Up Interrupt Enable
+ * - CANINT_EPIE: CAN Error Passive Interrupt Enable
+ * - CANINT_ALIE: CAN Arbitration Lost Interrupt Enable
+ * - CANINT_BEIE: CAN Bus Error Interrupt Enable
+ * - CANINT_IDIE: CAN ID Ready Interrupt Enable
+ * - CANINT_TIE2: CAN Transmit Interrupt Enable for Buffer2
+ * - CANINT_TIE3: CAN Transmit Interrupt Enable for Buffer3
+ * - CANINT_FCE: FullCAN Interrupt Enable
+ * @param[in] NewState: New state of this function, should be:
+ * - ENABLE
+ * - DISABLE
+ * @return none
+ *********************************************************************/
+void CAN_IRQCmd (LPC_CAN_TypeDef* CANx, CAN_INT_EN_Type arg, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_CANx(CANx));
+ CHECK_PARAM(PARAM_INT_EN_TYPE(arg));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ if(NewState == ENABLE)
+ {
+ if(arg==CANINT_FCE)
+ {
+ LPC_CANAF->AFMR = 0x01;
+ LPC_CANAF->FCANIE = 0x01;
+ LPC_CANAF->AFMR = 0x04;
+ }
+ else
+ CANx->IER |= (1 << arg);
+ }
+ else
+ {
+ if(arg==CANINT_FCE){
+ LPC_CANAF->AFMR = 0x01;
+ LPC_CANAF->FCANIE = 0x01;
+ LPC_CANAF->AFMR = 0x00;
+ }
+ else
+ CANx->IER &= ~(1 << arg);
+ }
+}
+
+/********************************************************************//**
+ * @brief Setting Acceptance Filter mode
+ * @param[in] CANAFx point to LPC_CANAF_TypeDef object, should be: LPC_CANAF
+ * @param[in] AFMode: type of AF mode that you want to set, should be:
+ * - CAN_Normal: Normal mode
+ * - CAN_AccOff: Acceptance Filter Off Mode
+ * - CAN_AccBP: Acceptance Fileter Bypass Mode
+ * - CAN_eFCAN: FullCAN Mode Enhancement
+ * @return none
+ *********************************************************************/
+void CAN_SetAFMode (LPC_CANAF_TypeDef* CANAFx, CAN_AFMODE_Type AFMode)
+{
+ CHECK_PARAM(PARAM_CANAFx(CANAFx));
+ CHECK_PARAM(PARAM_AFMODE_TYPE(AFMode));
+
+ switch(AFMode)
+ {
+ case CAN_Normal:
+ CANAFx->AFMR = 0x00;
+ break;
+ case CAN_AccOff:
+ CANAFx->AFMR = 0x01;
+ break;
+ case CAN_AccBP:
+ CANAFx->AFMR = 0x02;
+ break;
+ case CAN_eFCAN:
+ CANAFx->AFMR = 0x04;
+ break;
+ }
+}
+
+/********************************************************************//**
+ * @brief Enable/Disable CAN Mode
+ * @param[in] CANx pointer to LPC_CAN_TypeDef, should be:
+ * - LPC_CAN1: CAN1 peripheral
+ * - LPC_CAN2: CAN2 peripheral
+ * @param[in] mode: type of CAN mode that you want to enable/disable, should be:
+ * - CAN_OPERATING_MODE: Normal Operating Mode
+ * - CAN_RESET_MODE: Reset Mode
+ * - CAN_LISTENONLY_MODE: Listen Only Mode
+ * - CAN_SELFTEST_MODE: Self Test Mode
+ * - CAN_TXPRIORITY_MODE: Transmit Priority Mode
+ * - CAN_SLEEP_MODE: Sleep Mode
+ * - CAN_RXPOLARITY_MODE: Receive Polarity Mode
+ * - CAN_TEST_MODE: Test Mode
+ * @param[in] NewState: New State of this function, should be:
+ * - ENABLE
+ * - DISABLE
+ * @return none
+ *********************************************************************/
+void CAN_ModeConfig(LPC_CAN_TypeDef* CANx, CAN_MODE_Type mode, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_CANx(CANx));
+ CHECK_PARAM(PARAM_MODE_TYPE(mode));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ switch(mode)
+ {
+ case CAN_OPERATING_MODE:
+ CANx->MOD = 0x00;
+ break;
+ case CAN_RESET_MODE:
+ if(NewState == ENABLE)
+ CANx->MOD |=CAN_MOD_RM;
+ else
+ CANx->MOD &= ~CAN_MOD_RM;
+ break;
+ case CAN_LISTENONLY_MODE:
+ CANx->MOD |=CAN_MOD_RM;//Enter Reset mode
+ if(NewState == ENABLE)
+ CANx->MOD |=CAN_MOD_LOM;
+ else
+ CANx->MOD &=~CAN_MOD_LOM;
+ CANx->MOD &=~CAN_MOD_RM;//Release Reset mode
+ break;
+ case CAN_SELFTEST_MODE:
+ CANx->MOD |=CAN_MOD_RM;//Enter Reset mode
+ if(NewState == ENABLE)
+ CANx->MOD |=CAN_MOD_STM;
+ else
+ CANx->MOD &=~CAN_MOD_STM;
+ CANx->MOD &=~CAN_MOD_RM;//Release Reset mode
+ break;
+ case CAN_TXPRIORITY_MODE:
+ if(NewState == ENABLE)
+ CANx->MOD |=CAN_MOD_TPM;
+ else
+ CANx->MOD &=~CAN_MOD_TPM;
+ break;
+ case CAN_SLEEP_MODE:
+ if(NewState == ENABLE)
+ CANx->MOD |=CAN_MOD_SM;
+ else
+ CANx->MOD &=~CAN_MOD_SM;
+ break;
+ case CAN_RXPOLARITY_MODE:
+ if(NewState == ENABLE)
+ CANx->MOD |=CAN_MOD_RPM;
+ else
+ CANx->MOD &=~CAN_MOD_RPM;
+ break;
+ case CAN_TEST_MODE:
+ if(NewState == ENABLE)
+ CANx->MOD |=CAN_MOD_TM;
+ else
+ CANx->MOD &=~CAN_MOD_TM;
+ break;
+ }
+}
+/*********************************************************************//**
+ * @brief Set CAN command request
+ * @param[in] CANx point to CAN peripheral selected, should be:
+ * - LPC_CAN1: CAN1 peripheral
+ * - LPC_CAN2: CAN2 peripheral
+ * @param[in] CMRType command request type, should be:
+ * - CAN_CMR_TR: Transmission request
+ * - CAN_CMR_AT: Abort Transmission request
+ * - CAN_CMR_RRB: Release Receive Buffer request
+ * - CAN_CMR_CDO: Clear Data Overrun request
+ * - CAN_CMR_SRR: Self Reception request
+ * - CAN_CMR_STB1: Select Tx Buffer 1 request
+ * - CAN_CMR_STB2: Select Tx Buffer 2 request
+ * - CAN_CMR_STB3: Select Tx Buffer 3 request
+ * @return CANICR (CAN interrupt and Capture register) value
+ **********************************************************************/
+void CAN_SetCommand(LPC_CAN_TypeDef* CANx, uint32_t CMRType)
+{
+ CHECK_PARAM(PARAM_CANx(CANx));
+ CANx->CMR |= CMRType;
+}
+
+/*********************************************************************//**
+ * @brief Get CAN interrupt status
+ * @param[in] CANx point to CAN peripheral selected, should be:
+ * - LPC_CAN1: CAN1 peripheral
+ * - LPC_CAN2: CAN2 peripheral
+ * @return CANICR (CAN interrupt and Capture register) value
+ **********************************************************************/
+uint32_t CAN_IntGetStatus(LPC_CAN_TypeDef* CANx)
+{
+ CHECK_PARAM(PARAM_CANx(CANx));
+ return CANx->ICR;
+}
+
+/*********************************************************************//**
+ * @brief Check if FullCAN interrupt enable or not
+ * @param[in] CANAFx point to LPC_CANAF_TypeDef object, should be: LPC_CANAF
+ * @return IntStatus, could be:
+ * - SET: if FullCAN interrupt is enable
+ * - RESET: if FullCAN interrupt is disable
+ **********************************************************************/
+IntStatus CAN_FullCANIntGetStatus (LPC_CANAF_TypeDef* CANAFx)
+{
+ CHECK_PARAM( PARAM_CANAFx(CANAFx));
+ if (CANAFx->FCANIE)
+ return SET;
+ return RESET;
+}
+
+/*********************************************************************//**
+ * @brief Get value of FullCAN interrupt and capture register
+ * @param[in] CANAFx point to LPC_CANAF_TypeDef object, should be: LPC_CANAF
+ * @param[in] type: FullCAN IC type, should be:
+ * - FULLCAN_IC0: FullCAN Interrupt Capture 0
+ * - FULLCAN_IC1: FullCAN Interrupt Capture 1
+ * @return FCANIC0 or FCANIC1 (FullCAN interrupt and Capture register) value
+ **********************************************************************/
+uint32_t CAN_FullCANPendGetStatus(LPC_CANAF_TypeDef* CANAFx, FullCAN_IC_Type type)
+{
+ CHECK_PARAM(PARAM_CANAFx(CANAFx));
+ CHECK_PARAM( PARAM_FULLCAN_IC(type));
+ if (type == FULLCAN_IC0)
+ return CANAFx->FCANIC0;
+ return CANAFx->FCANIC1;
+}
+/* End of Public Variables ---------------------------------------------------------- */
+/**
+ * @}
+ */
+
+#endif /* _CAN */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_clkpwr.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_clkpwr.c
new file mode 100644
index 0000000..dde358b
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_clkpwr.c
@@ -0,0 +1,338 @@
+/***********************************************************************//**
+ * @file lpc17xx_clkpwr.c
+ * @brief Contains all functions support for Clock and Power Control
+ * firmware library on LPC17xx
+ * @version 3.0
+ * @date 18. June. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup CLKPWR
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_clkpwr.h"
+
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup CLKPWR_Public_Functions
+ * @{
+ */
+
+/*********************************************************************//**
+ * @brief Set value of each Peripheral Clock Selection
+ * @param[in] ClkType Peripheral Clock Selection of each type,
+ * should be one of the following:
+ * - CLKPWR_PCLKSEL_WDT : WDT
+ - CLKPWR_PCLKSEL_TIMER0 : Timer 0
+ - CLKPWR_PCLKSEL_TIMER1 : Timer 1
+ - CLKPWR_PCLKSEL_UART0 : UART 0
+ - CLKPWR_PCLKSEL_UART1 : UART 1
+ - CLKPWR_PCLKSEL_PWM1 : PWM 1
+ - CLKPWR_PCLKSEL_I2C0 : I2C 0
+ - CLKPWR_PCLKSEL_SPI : SPI
+ - CLKPWR_PCLKSEL_SSP1 : SSP 1
+ - CLKPWR_PCLKSEL_DAC : DAC
+ - CLKPWR_PCLKSEL_ADC : ADC
+ - CLKPWR_PCLKSEL_CAN1 : CAN 1
+ - CLKPWR_PCLKSEL_CAN2 : CAN 2
+ - CLKPWR_PCLKSEL_ACF : ACF
+ - CLKPWR_PCLKSEL_QEI : QEI
+ - CLKPWR_PCLKSEL_PCB : PCB
+ - CLKPWR_PCLKSEL_I2C1 : I2C 1
+ - CLKPWR_PCLKSEL_SSP0 : SSP 0
+ - CLKPWR_PCLKSEL_TIMER2 : Timer 2
+ - CLKPWR_PCLKSEL_TIMER3 : Timer 3
+ - CLKPWR_PCLKSEL_UART2 : UART 2
+ - CLKPWR_PCLKSEL_UART3 : UART 3
+ - CLKPWR_PCLKSEL_I2C2 : I2C 2
+ - CLKPWR_PCLKSEL_I2S : I2S
+ - CLKPWR_PCLKSEL_RIT : RIT
+ - CLKPWR_PCLKSEL_SYSCON : SYSCON
+ - CLKPWR_PCLKSEL_MC : MC
+
+ * @param[in] DivVal Value of divider, should be:
+ * - CLKPWR_PCLKSEL_CCLK_DIV_4 : PCLK_peripheral = CCLK/4
+ * - CLKPWR_PCLKSEL_CCLK_DIV_1 : PCLK_peripheral = CCLK/1
+ * - CLKPWR_PCLKSEL_CCLK_DIV_2 : PCLK_peripheral = CCLK/2
+ *
+ * @return none
+ **********************************************************************/
+void CLKPWR_SetPCLKDiv (uint32_t ClkType, uint32_t DivVal)
+{
+ uint32_t bitpos;
+
+ bitpos = (ClkType < 32) ? (ClkType) : (ClkType - 32);
+
+ /* PCLKSEL0 selected */
+ if (ClkType < 32)
+ {
+ /* Clear two bit at bit position */
+ LPC_SC->PCLKSEL0 &= (~(CLKPWR_PCLKSEL_BITMASK(bitpos)));
+
+ /* Set two selected bit */
+ LPC_SC->PCLKSEL0 |= (CLKPWR_PCLKSEL_SET(bitpos, DivVal));
+ }
+ /* PCLKSEL1 selected */
+ else
+ {
+ /* Clear two bit at bit position */
+ LPC_SC->PCLKSEL1 &= ~(CLKPWR_PCLKSEL_BITMASK(bitpos));
+
+ /* Set two selected bit */
+ LPC_SC->PCLKSEL1 |= (CLKPWR_PCLKSEL_SET(bitpos, DivVal));
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Get current value of each Peripheral Clock Selection
+ * @param[in] ClkType Peripheral Clock Selection of each type,
+ * should be one of the following:
+ * - CLKPWR_PCLKSEL_WDT : WDT
+ - CLKPWR_PCLKSEL_TIMER0 : Timer 0
+ - CLKPWR_PCLKSEL_TIMER1 : Timer 1
+ - CLKPWR_PCLKSEL_UART0 : UART 0
+ - CLKPWR_PCLKSEL_UART1 : UART 1
+ - CLKPWR_PCLKSEL_PWM1 : PWM 1
+ - CLKPWR_PCLKSEL_I2C0 : I2C 0
+ - CLKPWR_PCLKSEL_SPI : SPI
+ - CLKPWR_PCLKSEL_SSP1 : SSP 1
+ - CLKPWR_PCLKSEL_DAC : DAC
+ - CLKPWR_PCLKSEL_ADC : ADC
+ - CLKPWR_PCLKSEL_CAN1 : CAN 1
+ - CLKPWR_PCLKSEL_CAN2 : CAN 2
+ - CLKPWR_PCLKSEL_ACF : ACF
+ - CLKPWR_PCLKSEL_QEI : QEI
+ - CLKPWR_PCLKSEL_PCB : PCB
+ - CLKPWR_PCLKSEL_I2C1 : I2C 1
+ - CLKPWR_PCLKSEL_SSP0 : SSP 0
+ - CLKPWR_PCLKSEL_TIMER2 : Timer 2
+ - CLKPWR_PCLKSEL_TIMER3 : Timer 3
+ - CLKPWR_PCLKSEL_UART2 : UART 2
+ - CLKPWR_PCLKSEL_UART3 : UART 3
+ - CLKPWR_PCLKSEL_I2C2 : I2C 2
+ - CLKPWR_PCLKSEL_I2S : I2S
+ - CLKPWR_PCLKSEL_RIT : RIT
+ - CLKPWR_PCLKSEL_SYSCON : SYSCON
+ - CLKPWR_PCLKSEL_MC : MC
+
+ * @return Value of Selected Peripheral Clock Selection
+ **********************************************************************/
+uint32_t CLKPWR_GetPCLKSEL (uint32_t ClkType)
+{
+ uint32_t bitpos, retval;
+
+ if (ClkType < 32)
+ {
+ bitpos = ClkType;
+ retval = LPC_SC->PCLKSEL0;
+ }
+ else
+ {
+ bitpos = ClkType - 32;
+ retval = LPC_SC->PCLKSEL1;
+ }
+
+ retval = CLKPWR_PCLKSEL_GET(bitpos, retval);
+ return retval;
+}
+
+
+
+/*********************************************************************//**
+ * @brief Get current value of each Peripheral Clock
+ * @param[in] ClkType Peripheral Clock Selection of each type,
+ * should be one of the following:
+ * - CLKPWR_PCLKSEL_WDT : WDT
+ - CLKPWR_PCLKSEL_TIMER0 : Timer 0
+ - CLKPWR_PCLKSEL_TIMER1 : Timer 1
+ - CLKPWR_PCLKSEL_UART0 : UART 0
+ - CLKPWR_PCLKSEL_UART1 : UART 1
+ - CLKPWR_PCLKSEL_PWM1 : PWM 1
+ - CLKPWR_PCLKSEL_I2C0 : I2C 0
+ - CLKPWR_PCLKSEL_SPI : SPI
+ - CLKPWR_PCLKSEL_SSP1 : SSP 1
+ - CLKPWR_PCLKSEL_DAC : DAC
+ - CLKPWR_PCLKSEL_ADC : ADC
+ - CLKPWR_PCLKSEL_CAN1 : CAN 1
+ - CLKPWR_PCLKSEL_CAN2 : CAN 2
+ - CLKPWR_PCLKSEL_ACF : ACF
+ - CLKPWR_PCLKSEL_QEI : QEI
+ - CLKPWR_PCLKSEL_PCB : PCB
+ - CLKPWR_PCLKSEL_I2C1 : I2C 1
+ - CLKPWR_PCLKSEL_SSP0 : SSP 0
+ - CLKPWR_PCLKSEL_TIMER2 : Timer 2
+ - CLKPWR_PCLKSEL_TIMER3 : Timer 3
+ - CLKPWR_PCLKSEL_UART2 : UART 2
+ - CLKPWR_PCLKSEL_UART3 : UART 3
+ - CLKPWR_PCLKSEL_I2C2 : I2C 2
+ - CLKPWR_PCLKSEL_I2S : I2S
+ - CLKPWR_PCLKSEL_RIT : RIT
+ - CLKPWR_PCLKSEL_SYSCON : SYSCON
+ - CLKPWR_PCLKSEL_MC : MC
+
+ * @return Value of Selected Peripheral Clock
+ **********************************************************************/
+uint32_t CLKPWR_GetPCLK (uint32_t ClkType)
+{
+ uint32_t retval, div;
+
+ retval = SystemCoreClock;
+ div = CLKPWR_GetPCLKSEL(ClkType);
+
+ switch (div)
+ {
+ case 0:
+ div = 4;
+ break;
+
+ case 1:
+ div = 1;
+ break;
+
+ case 2:
+ div = 2;
+ break;
+
+ case 3:
+ div = 8;
+ break;
+ }
+ retval /= div;
+
+ return retval;
+}
+
+
+
+/*********************************************************************//**
+ * @brief Configure power supply for each peripheral according to NewState
+ * @param[in] PPType Type of peripheral used to enable power,
+ * should be one of the following:
+ * - CLKPWR_PCONP_PCTIM0 : Timer 0
+ - CLKPWR_PCONP_PCTIM1 : Timer 1
+ - CLKPWR_PCONP_PCUART0 : UART 0
+ - CLKPWR_PCONP_PCUART1 : UART 1
+ - CLKPWR_PCONP_PCPWM1 : PWM 1
+ - CLKPWR_PCONP_PCI2C0 : I2C 0
+ - CLKPWR_PCONP_PCSPI : SPI
+ - CLKPWR_PCONP_PCRTC : RTC
+ - CLKPWR_PCONP_PCSSP1 : SSP 1
+ - CLKPWR_PCONP_PCAD : ADC
+ - CLKPWR_PCONP_PCAN1 : CAN 1
+ - CLKPWR_PCONP_PCAN2 : CAN 2
+ - CLKPWR_PCONP_PCGPIO : GPIO
+ - CLKPWR_PCONP_PCRIT : RIT
+ - CLKPWR_PCONP_PCMC : MC
+ - CLKPWR_PCONP_PCQEI : QEI
+ - CLKPWR_PCONP_PCI2C1 : I2C 1
+ - CLKPWR_PCONP_PCSSP0 : SSP 0
+ - CLKPWR_PCONP_PCTIM2 : Timer 2
+ - CLKPWR_PCONP_PCTIM3 : Timer 3
+ - CLKPWR_PCONP_PCUART2 : UART 2
+ - CLKPWR_PCONP_PCUART3 : UART 3
+ - CLKPWR_PCONP_PCI2C2 : I2C 2
+ - CLKPWR_PCONP_PCI2S : I2S
+ - CLKPWR_PCONP_PCGPDMA : GPDMA
+ - CLKPWR_PCONP_PCENET : Ethernet
+ - CLKPWR_PCONP_PCUSB : USB
+ *
+ * @param[in] NewState New state of Peripheral Power, should be:
+ * - ENABLE : Enable power for this peripheral
+ * - DISABLE : Disable power for this peripheral
+ *
+ * @return none
+ **********************************************************************/
+void CLKPWR_ConfigPPWR (uint32_t PPType, FunctionalState NewState)
+{
+ if (NewState == ENABLE)
+ {
+ LPC_SC->PCONP |= PPType & CLKPWR_PCONP_BITMASK;
+ }
+ else if (NewState == DISABLE)
+ {
+ LPC_SC->PCONP &= (~PPType) & CLKPWR_PCONP_BITMASK;
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Enter Sleep mode with co-operated instruction by the Cortex-M3.
+ * @param[in] None
+ * @return None
+ **********************************************************************/
+void CLKPWR_Sleep(void)
+{
+ LPC_SC->PCON = 0x00;
+ /* Sleep Mode*/
+ __WFI();
+}
+
+
+/*********************************************************************//**
+ * @brief Enter Deep Sleep mode with co-operated instruction by the Cortex-M3.
+ * @param[in] None
+ * @return None
+ **********************************************************************/
+void CLKPWR_DeepSleep(void)
+{
+ /* Deep-Sleep Mode, set SLEEPDEEP bit */
+ SCB->SCR = 0x4;
+ LPC_SC->PCON = 0x8;
+ /* Deep Sleep Mode*/
+ __WFI();
+}
+
+
+/*********************************************************************//**
+ * @brief Enter Power Down mode with co-operated instruction by the Cortex-M3.
+ * @param[in] None
+ * @return None
+ **********************************************************************/
+void CLKPWR_PowerDown(void)
+{
+ /* Deep-Sleep Mode, set SLEEPDEEP bit */
+ SCB->SCR = 0x4;
+ LPC_SC->PCON = 0x09;
+ /* Power Down Mode*/
+ __WFI();
+}
+
+
+/*********************************************************************//**
+ * @brief Enter Deep Power Down mode with co-operated instruction by the Cortex-M3.
+ * @param[in] None
+ * @return None
+ **********************************************************************/
+void CLKPWR_DeepPowerDown(void)
+{
+ /* Deep-Sleep Mode, set SLEEPDEEP bit */
+ SCB->SCR = 0x4;
+ LPC_SC->PCON = 0x03;
+ /* Deep Power Down Mode*/
+ __WFI();
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_dac.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_dac.c
new file mode 100644
index 0000000..5f2d7fb
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_dac.c
@@ -0,0 +1,139 @@
+/**
+ * @file lpc17xx_dac.c
+ * @brief Contains all functions support for DAC firmware library on LPC17xx
+ * @version 2.0
+ * @date 21. May. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup DAC
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_dac.h"
+#include "lpc17xx_clkpwr.h"
+
+/* If this source file built with example, the LPC17xx FW library configuration
+ * file in each example directory ("lpc17xx_libcfg.h") must be included,
+ * otherwise the default FW library configuration file must be included instead
+ */
+#ifdef __BUILD_WITH_EXAMPLE__
+#include "lpc17xx_libcfg.h"
+#else
+#include "lpc17xx_libcfg_default.h"
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+
+#ifdef _DAC
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup DAC_Public_Functions
+ * @{
+ */
+
+/*********************************************************************//**
+ * @brief Initial ADC configuration
+ * - Maximum current is 700 uA
+ * - Value to AOUT is 0
+ * @param[in] DACx pointer to LPC_DAC_TypeDef, should be: LPC_DAC
+ * @return None
+ ***********************************************************************/
+void DAC_Init(LPC_DAC_TypeDef *DACx)
+{
+ CHECK_PARAM(PARAM_DACx(DACx));
+ /* Set default clock divider for DAC */
+ // CLKPWR_SetPCLKDiv (CLKPWR_PCLKSEL_DAC, CLKPWR_PCLKSEL_CCLK_DIV_4);
+ //Set maximum current output
+ DAC_SetBias(LPC_DAC,DAC_MAX_CURRENT_700uA);
+}
+
+/*********************************************************************//**
+ * @brief Update value to DAC
+ * @param[in] DACx pointer to LPC_DAC_TypeDef, should be: LPC_DAC
+ * @param[in] dac_value : value 10 bit to be converted to output
+ * @return None
+ ***********************************************************************/
+void DAC_UpdateValue (LPC_DAC_TypeDef *DACx,uint32_t dac_value)
+{
+ uint32_t tmp;
+ CHECK_PARAM(PARAM_DACx(DACx));
+ tmp = DACx->DACR & DAC_BIAS_EN;
+ tmp |= DAC_VALUE(dac_value);
+ // Update value
+ DACx->DACR = tmp;
+}
+
+/*********************************************************************//**
+ * @brief Set Maximum current for DAC
+ * @param[in] DACx pointer to LPC_DAC_TypeDef, should be: LPC_DAC
+ * @param[in] bias : 0 is 700 uA
+ * 1 350 uA
+ * @return None
+ ***********************************************************************/
+void DAC_SetBias (LPC_DAC_TypeDef *DACx,uint32_t bias)
+{
+ CHECK_PARAM(PARAM_DAC_CURRENT_OPT(bias));
+ DACx->DACR &=~DAC_BIAS_EN;
+ if (bias == DAC_MAX_CURRENT_350uA)
+ {
+ DACx->DACR |= DAC_BIAS_EN;
+ }
+}
+
+/*********************************************************************//**
+ * @brief To enable the DMA operation and control DMA timer
+ * @param[in] DACx pointer to LPC_DAC_TypeDef, should be: LPC_DAC
+ * @param[in] DAC_ConverterConfigStruct pointer to DAC_CONVERTER_CFG_Type
+ * - DBLBUF_ENA : enable/disable DACR double buffering feature
+ * - CNT_ENA : enable/disable timer out counter
+ * - DMA_ENA : enable/disable DMA access
+ * @return None
+ ***********************************************************************/
+void DAC_ConfigDAConverterControl (LPC_DAC_TypeDef *DACx,DAC_CONVERTER_CFG_Type *DAC_ConverterConfigStruct)
+{
+ CHECK_PARAM(PARAM_DACx(DACx));
+ DACx->DACCTRL &= ~DAC_DACCTRL_MASK;
+ if (DAC_ConverterConfigStruct->DBLBUF_ENA)
+ DACx->DACCTRL |= DAC_DBLBUF_ENA;
+ if (DAC_ConverterConfigStruct->CNT_ENA)
+ DACx->DACCTRL |= DAC_CNT_ENA;
+ if (DAC_ConverterConfigStruct->DMA_ENA)
+ DACx->DACCTRL |= DAC_DMA_ENA;
+}
+
+/*********************************************************************//**
+ * @brief Set reload value for interrupt/DMA counter
+ * @param[in] DACx pointer to LPC_DAC_TypeDef, should be: LPC_DAC
+ * @param[in] time_out time out to reload for interrupt/DMA counter
+ * @return None
+ ***********************************************************************/
+void DAC_SetDMATimeOut(LPC_DAC_TypeDef *DACx, uint32_t time_out)
+{
+ CHECK_PARAM(PARAM_DACx(DACx));
+ DACx->DACCNTVAL = DAC_CCNT_VALUE(time_out);
+}
+
+/**
+ * @}
+ */
+
+#endif /* _DAC */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_emac.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_emac.c
new file mode 100644
index 0000000..0128f5b
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_emac.c
@@ -0,0 +1,950 @@
+/**
+ * @file lpc17xx_emac.c
+ * @brief Contains all functions support for Ethernet MAC firmware library on LPC17xx
+ * @version 2.0
+ * @date 21. May. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup EMAC
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_emac.h"
+#include "lpc17xx_clkpwr.h"
+
+/* If this source file built with example, the LPC17xx FW library configuration
+ * file in each example directory ("lpc17xx_libcfg.h") must be included,
+ * otherwise the default FW library configuration file must be included instead
+ */
+#ifdef __BUILD_WITH_EXAMPLE__
+#include "lpc17xx_libcfg.h"
+#else
+#include "lpc17xx_libcfg_default.h"
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+
+#ifdef _EMAC
+
+/* Private Variables ---------------------------------------------------------- */
+/** @defgroup EMAC_Private_Variables EMAC Private Variables
+ * @{
+ */
+
+/* MII Mgmt Configuration register - Clock divider setting */
+const uint8_t EMAC_clkdiv[] = { 4, 6, 8, 10, 14, 20, 28 };
+
+/* EMAC local DMA Descriptors */
+
+/** Rx Descriptor data array */
+static RX_Desc Rx_Desc[EMAC_NUM_RX_FRAG];
+
+/** Rx Status data array - Must be 8-Byte aligned */
+#if defined ( __CC_ARM )
+static __align(8) RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG];
+#elif defined ( __ICCARM__ )
+#pragma data_alignment=8
+static RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG];
+#elif defined ( __GNUC__ )
+static __attribute__ ((aligned (8))) RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG];
+#endif
+
+/** Tx Descriptor data array */
+static TX_Desc Tx_Desc[EMAC_NUM_TX_FRAG];
+/** Tx Status data array */
+static TX_Stat Tx_Stat[EMAC_NUM_TX_FRAG];
+
+/* EMAC local DMA buffers */
+/** Rx buffer data */
+static uint32_t rx_buf[EMAC_NUM_RX_FRAG][EMAC_ETH_MAX_FLEN>>2];
+/** Tx buffer data */
+static uint32_t tx_buf[EMAC_NUM_TX_FRAG][EMAC_ETH_MAX_FLEN>>2];
+
+/**
+ * @}
+ */
+
+/* Private Functions ---------------------------------------------------------- */
+static void rx_descr_init (void);
+static void tx_descr_init (void);
+static int32_t write_PHY (uint32_t PhyReg, uint16_t Value);
+static int32_t read_PHY (uint32_t PhyReg);
+
+static void setEmacAddr(uint8_t abStationAddr[]);
+static int32_t emac_CRCCalc(uint8_t frame_no_fcs[], int32_t frame_len);
+
+
+/*--------------------------- rx_descr_init ---------------------------------*/
+/*********************************************************************//**
+ * @brief Initializes RX Descriptor
+ * @param[in] None
+ * @return None
+ ***********************************************************************/
+static void rx_descr_init (void)
+{
+ /* Initialize Receive Descriptor and Status array. */
+ uint32_t i;
+
+ for (i = 0; i < EMAC_NUM_RX_FRAG; i++) {
+ Rx_Desc[i].Packet = (uint32_t)&rx_buf[i];
+ Rx_Desc[i].Ctrl = EMAC_RCTRL_INT | (EMAC_ETH_MAX_FLEN - 1);
+ Rx_Stat[i].Info = 0;
+ Rx_Stat[i].HashCRC = 0;
+ }
+
+ /* Set EMAC Receive Descriptor Registers. */
+ LPC_EMAC->RxDescriptor = (uint32_t)&Rx_Desc[0];
+ LPC_EMAC->RxStatus = (uint32_t)&Rx_Stat[0];
+ LPC_EMAC->RxDescriptorNumber = EMAC_NUM_RX_FRAG - 1;
+
+ /* Rx Descriptors Point to 0 */
+ LPC_EMAC->RxConsumeIndex = 0;
+}
+
+
+/*--------------------------- tx_descr_init ---- ----------------------------*/
+/*********************************************************************//**
+ * @brief Initializes TX Descriptor
+ * @param[in] None
+ * @return None
+ ***********************************************************************/
+static void tx_descr_init (void) {
+ /* Initialize Transmit Descriptor and Status array. */
+ uint32_t i;
+
+ for (i = 0; i < EMAC_NUM_TX_FRAG; i++) {
+ Tx_Desc[i].Packet = (uint32_t)&tx_buf[i];
+ Tx_Desc[i].Ctrl = 0;
+ Tx_Stat[i].Info = 0;
+ }
+
+ /* Set EMAC Transmit Descriptor Registers. */
+ LPC_EMAC->TxDescriptor = (uint32_t)&Tx_Desc[0];
+ LPC_EMAC->TxStatus = (uint32_t)&Tx_Stat[0];
+ LPC_EMAC->TxDescriptorNumber = EMAC_NUM_TX_FRAG - 1;
+
+ /* Tx Descriptors Point to 0 */
+ LPC_EMAC->TxProduceIndex = 0;
+}
+
+
+/*--------------------------- write_PHY -------------------------------------*/
+/*********************************************************************//**
+ * @brief Write value to PHY device
+ * @param[in] PhyReg: PHY Register address
+ * @param[in] Value: Value to write
+ * @return 0 - if success
+ * 1 - if fail
+ ***********************************************************************/
+static int32_t write_PHY (uint32_t PhyReg, uint16_t Value)
+{
+ /* Write a data 'Value' to PHY register 'PhyReg'. */
+ uint32_t tout;
+
+ LPC_EMAC->MADR = EMAC_DEF_ADR | PhyReg;
+ LPC_EMAC->MWTD = Value;
+
+ /* Wait until operation completed */
+ tout = 0;
+ for (tout = 0; tout < EMAC_MII_WR_TOUT; tout++) {
+ if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) {
+ return (0);
+ }
+ }
+ // Time out!
+ return (-1);
+}
+
+
+/*--------------------------- read_PHY --------------------------------------*/
+/*********************************************************************//**
+ * @brief Read value from PHY device
+ * @param[in] PhyReg: PHY Register address
+ * @return 0 - if success
+ * 1 - if fail
+ ***********************************************************************/
+static int32_t read_PHY (uint32_t PhyReg)
+{
+ /* Read a PHY register 'PhyReg'. */
+ uint32_t tout;
+
+ LPC_EMAC->MADR = EMAC_DEF_ADR | PhyReg;
+ LPC_EMAC->MCMD = EMAC_MCMD_READ;
+
+ /* Wait until operation completed */
+ tout = 0;
+ for (tout = 0; tout < EMAC_MII_RD_TOUT; tout++) {
+ if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) {
+ LPC_EMAC->MCMD = 0;
+ return (LPC_EMAC->MRDD);
+ }
+ }
+ // Time out!
+ return (-1);
+}
+
+/*********************************************************************//**
+ * @brief Set Station MAC address for EMAC module
+ * @param[in] abStationAddr Pointer to Station address that contains 6-bytes
+ * of MAC address (should be in order from MAC Address 1 to MAC Address 6)
+ * @return None
+ **********************************************************************/
+static void setEmacAddr(uint8_t abStationAddr[])
+{
+ /* Set the Ethernet MAC Address registers */
+ LPC_EMAC->SA0 = ((uint32_t)abStationAddr[5] << 8) | (uint32_t)abStationAddr[4];
+ LPC_EMAC->SA1 = ((uint32_t)abStationAddr[3] << 8) | (uint32_t)abStationAddr[2];
+ LPC_EMAC->SA2 = ((uint32_t)abStationAddr[1] << 8) | (uint32_t)abStationAddr[0];
+}
+
+
+/*********************************************************************//**
+ * @brief Calculates CRC code for number of bytes in the frame
+ * @param[in] frame_no_fcs Pointer to the first byte of the frame
+ * @param[in] frame_len length of the frame without the FCS
+ * @return the CRC as a 32 bit integer
+ **********************************************************************/
+static int32_t emac_CRCCalc(uint8_t frame_no_fcs[], int32_t frame_len)
+{
+ int i; // iterator
+ int j; // another iterator
+ char byte; // current byte
+ int crc; // CRC result
+ int q0, q1, q2, q3; // temporary variables
+ crc = 0xFFFFFFFF;
+ for (i = 0; i < frame_len; i++) {
+ byte = *frame_no_fcs++;
+ for (j = 0; j < 2; j++) {
+ if (((crc >> 28) ^ (byte >> 3)) & 0x00000001) {
+ q3 = 0x04C11DB7;
+ } else {
+ q3 = 0x00000000;
+ }
+ if (((crc >> 29) ^ (byte >> 2)) & 0x00000001) {
+ q2 = 0x09823B6E;
+ } else {
+ q2 = 0x00000000;
+ }
+ if (((crc >> 30) ^ (byte >> 1)) & 0x00000001) {
+ q1 = 0x130476DC;
+ } else {
+ q1 = 0x00000000;
+ }
+ if (((crc >> 31) ^ (byte >> 0)) & 0x00000001) {
+ q0 = 0x2608EDB8;
+ } else {
+ q0 = 0x00000000;
+ }
+ crc = (crc << 4) ^ q3 ^ q2 ^ q1 ^ q0;
+ byte >>= 4;
+ }
+ }
+ return crc;
+}
+/* End of Private Functions --------------------------------------------------- */
+
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup EMAC_Public_Functions
+ * @{
+ */
+
+
+/*********************************************************************//**
+ * @brief Initializes the EMAC peripheral according to the specified
+* parameters in the EMAC_ConfigStruct.
+ * @param[in] EMAC_ConfigStruct Pointer to a EMAC_CFG_Type structure
+* that contains the configuration information for the
+* specified EMAC peripheral.
+ * @return None
+ *
+ * Note: This function will initialize EMAC module according to procedure below:
+ * - Remove the soft reset condition from the MAC
+ * - Configure the PHY via the MIIM interface of the MAC
+ * - Select RMII mode
+ * - Configure the transmit and receive DMA engines, including the descriptor arrays
+ * - Configure the host registers (MAC1,MAC2 etc.) in the MAC
+ * - Enable the receive and transmit data paths
+ * In default state after initializing, only Rx Done and Tx Done interrupt are enabled,
+ * all remain interrupts are disabled
+ * (Ref. from LPC17xx UM)
+ **********************************************************************/
+Status EMAC_Init(EMAC_CFG_Type *EMAC_ConfigStruct)
+{
+ /* Initialize the EMAC Ethernet controller. */
+ int32_t regv,tout, tmp;
+
+ /* Set up clock and power for Ethernet module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, ENABLE);
+
+ /* Reset all EMAC internal modules */
+ LPC_EMAC->MAC1 = EMAC_MAC1_RES_TX | EMAC_MAC1_RES_MCS_TX | EMAC_MAC1_RES_RX |
+ EMAC_MAC1_RES_MCS_RX | EMAC_MAC1_SIM_RES | EMAC_MAC1_SOFT_RES;
+
+ LPC_EMAC->Command = EMAC_CR_REG_RES | EMAC_CR_TX_RES | EMAC_CR_RX_RES | EMAC_CR_PASS_RUNT_FRM;
+
+ /* A short delay after reset. */
+ for (tout = 100; tout; tout--);
+
+ /* Initialize MAC control registers. */
+ LPC_EMAC->MAC1 = EMAC_MAC1_PASS_ALL;
+ LPC_EMAC->MAC2 = EMAC_MAC2_CRC_EN | EMAC_MAC2_PAD_EN;
+ LPC_EMAC->MAXF = EMAC_ETH_MAX_FLEN;
+ /*
+ * Find the clock that close to desired target clock
+ */
+ tmp = SystemCoreClock / EMAC_MCFG_MII_MAXCLK;
+ for (tout = 0; tout < sizeof (EMAC_clkdiv); tout++){
+ if (EMAC_clkdiv[tout] >= tmp) break;
+ }
+ tout++;
+ // Write to MAC configuration register and reset
+ LPC_EMAC->MCFG = EMAC_MCFG_CLK_SEL(tout) | EMAC_MCFG_RES_MII;
+ // release reset
+ LPC_EMAC->MCFG &= ~(EMAC_MCFG_RES_MII);
+ LPC_EMAC->CLRT = EMAC_CLRT_DEF;
+ LPC_EMAC->IPGR = EMAC_IPGR_P2_DEF;
+
+ /* Enable Reduced MII interface. */
+ LPC_EMAC->Command = EMAC_CR_RMII | EMAC_CR_PASS_RUNT_FRM;
+
+ /* Reset Reduced MII Logic. */
+ LPC_EMAC->SUPP = EMAC_SUPP_RES_RMII;
+
+ for (tout = 100; tout; tout--);
+ LPC_EMAC->SUPP = 0;
+
+ /* Put the DP83848C in reset mode */
+ write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_BMCR_RESET);
+
+ /* Wait for hardware reset to end. */
+ for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) {
+ regv = read_PHY (EMAC_PHY_REG_BMCR);
+ if (!(regv & (EMAC_PHY_BMCR_RESET | EMAC_PHY_BMCR_POWERDOWN))) {
+ /* Reset complete, device not Power Down. */
+ break;
+ }
+ if (tout == 0){
+ // Time out, return ERROR
+ return (ERROR);
+ }
+ }
+
+ // Set PHY mode
+ if (EMAC_SetPHYMode(EMAC_ConfigStruct->Mode) < 0){
+ return (ERROR);
+ }
+
+ // Set EMAC address
+ setEmacAddr(EMAC_ConfigStruct->pbEMAC_Addr);
+
+ /* Initialize Tx and Rx DMA Descriptors */
+ rx_descr_init ();
+ tx_descr_init ();
+
+ // Set Receive Filter register: enable broadcast and multicast
+ LPC_EMAC->RxFilterCtrl = EMAC_RFC_MCAST_EN | EMAC_RFC_BCAST_EN | EMAC_RFC_PERFECT_EN;
+
+ /* Enable Rx Done and Tx Done interrupt for EMAC */
+ LPC_EMAC->IntEnable = EMAC_INT_RX_DONE | EMAC_INT_TX_DONE;
+
+ /* Reset all interrupts */
+ LPC_EMAC->IntClear = 0xFFFF;
+
+ /* Enable receive and transmit mode of MAC Ethernet core */
+ LPC_EMAC->Command |= (EMAC_CR_RX_EN | EMAC_CR_TX_EN);
+ LPC_EMAC->MAC1 |= EMAC_MAC1_REC_EN;
+
+ return SUCCESS;
+}
+
+
+/*********************************************************************//**
+ * @brief De-initializes the EMAC peripheral registers to their
+* default reset values.
+ * @param[in] None
+ * @return None
+ **********************************************************************/
+void EMAC_DeInit(void)
+{
+ // Disable all interrupt
+ LPC_EMAC->IntEnable = 0x00;
+ // Clear all pending interrupt
+ LPC_EMAC->IntClear = (0xFF) | (EMAC_INT_SOFT_INT | EMAC_INT_WAKEUP);
+
+ /* TurnOff clock and power for Ethernet module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, DISABLE);
+}
+
+
+/*********************************************************************//**
+ * @brief Check specified PHY status in EMAC peripheral
+ * @param[in] ulPHYState Specified PHY Status Type, should be:
+ * - EMAC_PHY_STAT_LINK: Link Status
+ * - EMAC_PHY_STAT_SPEED: Speed Status
+ * - EMAC_PHY_STAT_DUP: Duplex Status
+ * @return Status of specified PHY status (0 or 1).
+ * (-1) if error.
+ *
+ * Note:
+ * For EMAC_PHY_STAT_LINK, return value:
+ * - 0: Link Down
+ * - 1: Link Up
+ * For EMAC_PHY_STAT_SPEED, return value:
+ * - 0: 10Mbps
+ * - 1: 100Mbps
+ * For EMAC_PHY_STAT_DUP, return value:
+ * - 0: Half-Duplex
+ * - 1: Full-Duplex
+ **********************************************************************/
+int32_t EMAC_CheckPHYStatus(uint32_t ulPHYState)
+{
+ int32_t regv, tmp;
+#ifdef MCB_LPC_1768
+ regv = read_PHY (EMAC_PHY_REG_STS);
+ switch(ulPHYState){
+ case EMAC_PHY_STAT_LINK:
+ tmp = (regv & EMAC_PHY_SR_LINK) ? 1 : 0;
+ break;
+ case EMAC_PHY_STAT_SPEED:
+ tmp = (regv & EMAC_PHY_SR_SPEED) ? 0 : 1;
+ break;
+ case EMAC_PHY_STAT_DUP:
+ tmp = (regv & EMAC_PHY_SR_FULL_DUP) ? 1 : 0;
+ break;
+#elif defined(IAR_LPC_1768)
+ /* Use IAR_LPC_1768 board:
+ * FSZ8721BL doesn't have Status Register
+ * so we read Basic Mode Status Register (0x01h) instead
+ */
+ regv = read_PHY (EMAC_PHY_REG_BMSR);
+ switch(ulPHYState){
+ case EMAC_PHY_STAT_LINK:
+ tmp = (regv & EMAC_PHY_BMSR_LINK_STATUS) ? 1 : 0;
+ break;
+ case EMAC_PHY_STAT_SPEED:
+ tmp = (regv & EMAC_PHY_SR_100_SPEED) ? 1 : 0;
+ break;
+ case EMAC_PHY_STAT_DUP:
+ tmp = (regv & EMAC_PHY_SR_FULL_DUP) ? 1 : 0;
+ break;
+#endif
+ default:
+ tmp = -1;
+ break;
+ }
+ return (tmp);
+}
+
+
+/*********************************************************************//**
+ * @brief Set specified PHY mode in EMAC peripheral
+ * @param[in] ulPHYMode Specified PHY mode, should be:
+ * - EMAC_MODE_AUTO
+ * - EMAC_MODE_10M_FULL
+ * - EMAC_MODE_10M_HALF
+ * - EMAC_MODE_100M_FULL
+ * - EMAC_MODE_100M_HALF
+ * @return Return (0) if no error, otherwise return (-1)
+ **********************************************************************/
+int32_t EMAC_SetPHYMode(uint32_t ulPHYMode)
+{
+ int32_t id1, id2, tout, regv;
+
+ /* Check if this is a DP83848C PHY. */
+ id1 = read_PHY (EMAC_PHY_REG_IDR1);
+ id2 = read_PHY (EMAC_PHY_REG_IDR2);
+
+#ifdef MCB_LPC_1768
+ if (((id1 << 16) | (id2 & 0xFFF0)) == EMAC_DP83848C_ID) {
+ switch(ulPHYMode){
+ case EMAC_MODE_AUTO:
+ write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_AUTO_NEG);
+#elif defined(IAR_LPC_1768) /* Use IAR LPC1768 KickStart board */
+ if (((id1 << 16) | id2) == EMAC_KSZ8721BL_ID) {
+ /* Configure the PHY device */
+ switch(ulPHYMode){
+ case EMAC_MODE_AUTO:
+ /* Use auto-negotiation about the link speed. */
+ write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_AUTO_NEG);
+// write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_BMCR_AN);
+#endif
+ /* Wait to complete Auto_Negotiation */
+ for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) {
+ regv = read_PHY (EMAC_PHY_REG_BMSR);
+ if (regv & EMAC_PHY_BMSR_AUTO_DONE) {
+ /* Auto-negotiation Complete. */
+ break;
+ }
+ if (tout == 0){
+ // Time out, return error
+ return (-1);
+ }
+ }
+ break;
+ case EMAC_MODE_10M_FULL:
+ /* Connect at 10MBit full-duplex */
+ write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_FULLD_10M);
+ break;
+ case EMAC_MODE_10M_HALF:
+ /* Connect at 10MBit half-duplex */
+ write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_HALFD_10M);
+ break;
+ case EMAC_MODE_100M_FULL:
+ /* Connect at 100MBit full-duplex */
+ write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_FULLD_100M);
+ break;
+ case EMAC_MODE_100M_HALF:
+ /* Connect at 100MBit half-duplex */
+ write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_HALFD_100M);
+ break;
+ default:
+ // un-supported
+ return (-1);
+ }
+ }
+ // It's not correct module ID
+ else {
+ return (-1);
+ }
+
+ // Update EMAC configuration with current PHY status
+ if (EMAC_UpdatePHYStatus() < 0){
+ return (-1);
+ }
+
+ // Complete
+ return (0);
+}
+
+
+/*********************************************************************//**
+ * @brief Auto-Configures value for the EMAC configuration register to
+ * match with current PHY mode
+ * @param[in] None
+ * @return Return (0) if no error, otherwise return (-1)
+ *
+ * Note: The EMAC configuration will be auto-configured:
+ * - Speed mode.
+ * - Half/Full duplex mode
+ **********************************************************************/
+int32_t EMAC_UpdatePHYStatus(void)
+{
+ int32_t regv, tout;
+
+ /* Check the link status. */
+#ifdef MCB_LPC_1768
+ for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) {
+ regv = read_PHY (EMAC_PHY_REG_STS);
+ if (regv & EMAC_PHY_SR_LINK) {
+ /* Link is on. */
+ break;
+ }
+ if (tout == 0){
+ // time out
+ return (-1);
+ }
+ }
+ /* Configure Full/Half Duplex mode. */
+ if (regv & EMAC_PHY_SR_DUP) {
+ /* Full duplex is enabled. */
+ LPC_EMAC->MAC2 |= EMAC_MAC2_FULL_DUP;
+ LPC_EMAC->Command |= EMAC_CR_FULL_DUP;
+ LPC_EMAC->IPGT = EMAC_IPGT_FULL_DUP;
+ } else {
+ /* Half duplex mode. */
+ LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP;
+ }
+ if (regv & EMAC_PHY_SR_SPEED) {
+ /* 10MBit mode. */
+ LPC_EMAC->SUPP = 0;
+ } else {
+ /* 100MBit mode. */
+ LPC_EMAC->SUPP = EMAC_SUPP_SPEED;
+ }
+#elif defined(IAR_LPC_1768)
+ for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) {
+ regv = read_PHY (EMAC_PHY_REG_BMSR);
+ if (regv & EMAC_PHY_BMSR_LINK_STATUS) {
+ /* Link is on. */
+ break;
+ }
+ if (tout == 0){
+ // time out
+ return (-1);
+ }
+ }
+
+ /* Configure Full/Half Duplex mode. */
+ if (regv & EMAC_PHY_SR_FULL_DUP) {
+ /* Full duplex is enabled. */
+ LPC_EMAC->MAC2 |= EMAC_MAC2_FULL_DUP;
+ LPC_EMAC->Command |= EMAC_CR_FULL_DUP;
+ LPC_EMAC->IPGT = EMAC_IPGT_FULL_DUP;
+ } else {
+ /* Half duplex mode. */
+ LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP;
+ }
+
+ /* Configure 100MBit/10MBit mode. */
+ if (!(regv & EMAC_PHY_SR_100_SPEED)) {
+ /* 10MBit mode. */
+ LPC_EMAC->SUPP = 0;
+ } else {
+ /* 100MBit mode. */
+ LPC_EMAC->SUPP = EMAC_SUPP_SPEED;
+ }
+#endif
+ // Complete
+ return (0);
+}
+
+
+/*********************************************************************//**
+ * @brief Enable/Disable hash filter functionality for specified destination
+ * MAC address in EMAC module
+ * @param[in] dstMAC_addr Pointer to the first MAC destination address, should
+ * be 6-bytes length, in order LSB to the MSB
+ * @param[in] NewState New State of this command, should be:
+ * - ENABLE.
+ * - DISABLE.
+ * @return None
+ *
+ * Note:
+ * The standard Ethernet cyclic redundancy check (CRC) function is calculated from
+ * the 6 byte destination address in the Ethernet frame (this CRC is calculated
+ * anyway as part of calculating the CRC of the whole frame), then bits [28:23] out of
+ * the 32 bits CRC result are taken to form the hash. The 6 bit hash is used to access
+ * the hash table: it is used as an index in the 64 bit HashFilter register that has been
+ * programmed with accept values. If the selected accept value is 1, the frame is
+ * accepted.
+ **********************************************************************/
+void EMAC_SetHashFilter(uint8_t dstMAC_addr[], FunctionalState NewState)
+{
+ uint32_t *pReg;
+ uint32_t tmp;
+ int32_t crc;
+
+ // Calculate the CRC from the destination MAC address
+ crc = emac_CRCCalc(dstMAC_addr, 6);
+ // Extract the value from CRC to get index value for hash filter table
+ crc = (crc >> 23) & 0x3F;
+
+ pReg = (crc > 31) ? ((uint32_t *)&LPC_EMAC->HashFilterH) \
+ : ((uint32_t *)&LPC_EMAC->HashFilterL);
+ tmp = (crc > 31) ? (crc - 32) : crc;
+ if (NewState == ENABLE) {
+ (*pReg) |= (1UL << tmp);
+ } else {
+ (*pReg) &= ~(1UL << tmp);
+ }
+ // Enable Rx Filter
+ LPC_EMAC->Command &= ~EMAC_CR_PASS_RX_FILT;
+}
+
+/*********************************************************************//**
+ * @brief Enable/Disable Filter mode for each specified type EMAC peripheral
+ * @param[in] ulFilterMode Filter mode, should be:
+ * - EMAC_RFC_UCAST_EN: all frames of unicast types
+ * will be accepted
+ * - EMAC_RFC_BCAST_EN: broadcast frame will be
+ * accepted
+ * - EMAC_RFC_MCAST_EN: all frames of multicast
+ * types will be accepted
+ * - EMAC_RFC_UCAST_HASH_EN: The imperfect hash
+ * filter will be applied to unicast addresses
+ * - EMAC_RFC_MCAST_HASH_EN: The imperfect hash
+ * filter will be applied to multicast addresses
+ * - EMAC_RFC_PERFECT_EN: the destination address
+ * will be compared with the 6 byte station address
+ * programmed in the station address by the filter
+ * - EMAC_RFC_MAGP_WOL_EN: the result of the magic
+ * packet filter will generate a WoL interrupt when
+ * there is a match
+ * - EMAC_RFC_PFILT_WOL_EN: the result of the perfect address
+ * matching filter and the imperfect hash filter will
+ * generate a WoL interrupt when there is a match
+ * @param[in] NewState New State of this command, should be:
+ * - ENABLE
+ * - DISABLE
+ * @return None
+ **********************************************************************/
+void EMAC_SetFilterMode(uint32_t ulFilterMode, FunctionalState NewState)
+{
+ if (NewState == ENABLE){
+ LPC_EMAC->RxFilterCtrl |= ulFilterMode;
+ } else {
+ LPC_EMAC->RxFilterCtrl &= ~ulFilterMode;
+ }
+}
+
+/*********************************************************************//**
+ * @brief Get status of Wake On LAN Filter for each specified
+ * type in EMAC peripheral, clear this status if it is set
+ * @param[in] ulWoLMode WoL Filter mode, should be:
+ * - EMAC_WOL_UCAST: unicast frames caused WoL
+ * - EMAC_WOL_UCAST: broadcast frame caused WoL
+ * - EMAC_WOL_MCAST: multicast frame caused WoL
+ * - EMAC_WOL_UCAST_HASH: unicast frame that passes the
+ * imperfect hash filter caused WoL
+ * - EMAC_WOL_MCAST_HASH: multicast frame that passes the
+ * imperfect hash filter caused WoL
+ * - EMAC_WOL_PERFECT:perfect address matching filter
+ * caused WoL
+ * - EMAC_WOL_RX_FILTER: the receive filter caused WoL
+ * - EMAC_WOL_MAG_PACKET: the magic packet filter caused WoL
+ * @return SET/RESET
+ **********************************************************************/
+FlagStatus EMAC_GetWoLStatus(uint32_t ulWoLMode)
+{
+ if (LPC_EMAC->RxFilterWoLStatus & ulWoLMode) {
+ LPC_EMAC->RxFilterWoLClear = ulWoLMode;
+ return SET;
+ } else {
+ return RESET;
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Write data to Tx packet data buffer at current index due to
+ * TxProduceIndex
+ * @param[in] pDataStruct Pointer to a EMAC_PACKETBUF_Type structure
+ * data that contain specified information about
+ * Packet data buffer.
+ * @return None
+ **********************************************************************/
+void EMAC_WritePacketBuffer(EMAC_PACKETBUF_Type *pDataStruct)
+{
+ uint32_t idx,len;
+ uint32_t *sp,*dp;
+
+ idx = LPC_EMAC->TxProduceIndex;
+ sp = (uint32_t *)pDataStruct->pbDataBuf;
+ dp = (uint32_t *)Tx_Desc[idx].Packet;
+ /* Copy frame data to EMAC packet buffers. */
+ for (len = (pDataStruct->ulDataLen + 3) >> 2; len; len--) {
+ *dp++ = *sp++;
+ }
+ Tx_Desc[idx].Ctrl = (pDataStruct->ulDataLen - 1) | (EMAC_TCTRL_INT | EMAC_TCTRL_LAST);
+}
+
+/*********************************************************************//**
+ * @brief Read data from Rx packet data buffer at current index due
+ * to RxConsumeIndex
+ * @param[in] pDataStruct Pointer to a EMAC_PACKETBUF_Type structure
+ * data that contain specified information about
+ * Packet data buffer.
+ * @return None
+ **********************************************************************/
+void EMAC_ReadPacketBuffer(EMAC_PACKETBUF_Type *pDataStruct)
+{
+ uint32_t idx, len;
+ uint32_t *dp, *sp;
+
+ idx = LPC_EMAC->RxConsumeIndex;
+ dp = (uint32_t *)pDataStruct->pbDataBuf;
+ sp = (uint32_t *)Rx_Desc[idx].Packet;
+
+ if (pDataStruct->pbDataBuf != NULL) {
+ for (len = (pDataStruct->ulDataLen + 3) >> 2; len; len--) {
+ *dp++ = *sp++;
+ }
+ }
+}
+
+/*********************************************************************//**
+ * @brief Enable/Disable interrupt for each type in EMAC
+ * @param[in] ulIntType Interrupt Type, should be:
+ * - EMAC_INT_RX_OVERRUN: Receive Overrun
+ * - EMAC_INT_RX_ERR: Receive Error
+ * - EMAC_INT_RX_FIN: Receive Descriptor Finish
+ * - EMAC_INT_RX_DONE: Receive Done
+ * - EMAC_INT_TX_UNDERRUN: Transmit Under-run
+ * - EMAC_INT_TX_ERR: Transmit Error
+ * - EMAC_INT_TX_FIN: Transmit descriptor finish
+ * - EMAC_INT_TX_DONE: Transmit Done
+ * - EMAC_INT_SOFT_INT: Software interrupt
+ * - EMAC_INT_WAKEUP: Wakeup interrupt
+ * @param[in] NewState New State of this function, should be:
+ * - ENABLE.
+ * - DISABLE.
+ * @return None
+ **********************************************************************/
+void EMAC_IntCmd(uint32_t ulIntType, FunctionalState NewState)
+{
+ if (NewState == ENABLE) {
+ LPC_EMAC->IntEnable |= ulIntType;
+ } else {
+ LPC_EMAC->IntEnable &= ~(ulIntType);
+ }
+}
+
+/*********************************************************************//**
+ * @brief Check whether if specified interrupt flag is set or not
+ * for each interrupt type in EMAC and clear interrupt pending
+ * if it is set.
+ * @param[in] ulIntType Interrupt Type, should be:
+ * - EMAC_INT_RX_OVERRUN: Receive Overrun
+ * - EMAC_INT_RX_ERR: Receive Error
+ * - EMAC_INT_RX_FIN: Receive Descriptor Finish
+ * - EMAC_INT_RX_DONE: Receive Done
+ * - EMAC_INT_TX_UNDERRUN: Transmit Under-run
+ * - EMAC_INT_TX_ERR: Transmit Error
+ * - EMAC_INT_TX_FIN: Transmit descriptor finish
+ * - EMAC_INT_TX_DONE: Transmit Done
+ * - EMAC_INT_SOFT_INT: Software interrupt
+ * - EMAC_INT_WAKEUP: Wakeup interrupt
+ * @return New state of specified interrupt (SET or RESET)
+ **********************************************************************/
+IntStatus EMAC_IntGetStatus(uint32_t ulIntType)
+{
+ if (LPC_EMAC->IntStatus & ulIntType) {
+ LPC_EMAC->IntClear = ulIntType;
+ return SET;
+ } else {
+ return RESET;
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Check whether if the current RxConsumeIndex is not equal to the
+ * current RxProduceIndex.
+ * @param[in] None
+ * @return TRUE if they're not equal, otherwise return FALSE
+ *
+ * Note: In case the RxConsumeIndex is not equal to the RxProduceIndex,
+ * it means there're available data has been received. They should be read
+ * out and released the Receive Data Buffer by updating the RxConsumeIndex value.
+ **********************************************************************/
+Bool EMAC_CheckReceiveIndex(void)
+{
+ if (LPC_EMAC->RxConsumeIndex != LPC_EMAC->RxProduceIndex) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Check whether if the current TxProduceIndex is not equal to the
+ * current RxProduceIndex - 1.
+ * @param[in] None
+ * @return TRUE if they're not equal, otherwise return FALSE
+ *
+ * Note: In case the RxConsumeIndex is equal to the RxProduceIndex - 1,
+ * it means the transmit buffer is available and data can be written to transmit
+ * buffer to be sent.
+ **********************************************************************/
+Bool EMAC_CheckTransmitIndex(void)
+{
+ uint32_t tmp = LPC_EMAC->TxConsumeIndex -1;
+ if (LPC_EMAC->TxProduceIndex == tmp) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Get current status value of receive data (due to RxConsumeIndex)
+ * @param[in] ulRxStatType Received Status type, should be one of following:
+ * - EMAC_RINFO_CTRL_FRAME: Control Frame
+ * - EMAC_RINFO_VLAN: VLAN Frame
+ * - EMAC_RINFO_FAIL_FILT: RX Filter Failed
+ * - EMAC_RINFO_MCAST: Multicast Frame
+ * - EMAC_RINFO_BCAST: Broadcast Frame
+ * - EMAC_RINFO_CRC_ERR: CRC Error in Frame
+ * - EMAC_RINFO_SYM_ERR: Symbol Error from PHY
+ * - EMAC_RINFO_LEN_ERR: Length Error
+ * - EMAC_RINFO_RANGE_ERR: Range error(exceeded max size)
+ * - EMAC_RINFO_ALIGN_ERR: Alignment error
+ * - EMAC_RINFO_OVERRUN: Receive overrun
+ * - EMAC_RINFO_NO_DESCR: No new Descriptor available
+ * - EMAC_RINFO_LAST_FLAG: last Fragment in Frame
+ * - EMAC_RINFO_ERR: Error Occurred (OR of all error)
+ * @return Current value of receive data (due to RxConsumeIndex)
+ **********************************************************************/
+FlagStatus EMAC_CheckReceiveDataStatus(uint32_t ulRxStatType)
+{
+ uint32_t idx;
+ idx = LPC_EMAC->RxConsumeIndex;
+ return (((Rx_Stat[idx].Info) & ulRxStatType) ? SET : RESET);
+}
+
+
+/*********************************************************************//**
+ * @brief Get size of current Received data in received buffer (due to
+ * RxConsumeIndex)
+ * @param[in] None
+ * @return Size of received data
+ **********************************************************************/
+uint32_t EMAC_GetReceiveDataSize(void)
+{
+ uint32_t idx;
+ idx =LPC_EMAC->RxConsumeIndex;
+ return ((Rx_Stat[idx].Info) & EMAC_RINFO_SIZE);
+}
+
+/*********************************************************************//**
+ * @brief Increase the RxConsumeIndex (after reading the Receive buffer
+ * to release the Receive buffer) and wrap-around the index if
+ * it reaches the maximum Receive Number
+ * @param[in] None
+ * @return None
+ **********************************************************************/
+void EMAC_UpdateRxConsumeIndex(void)
+{
+ // Get current Rx consume index
+ uint32_t idx = LPC_EMAC->RxConsumeIndex;
+
+ /* Release frame from EMAC buffer */
+ if (++idx == EMAC_NUM_RX_FRAG) idx = 0;
+ LPC_EMAC->RxConsumeIndex = idx;
+}
+
+/*********************************************************************//**
+ * @brief Increase the TxProduceIndex (after writting to the Transmit buffer
+ * to enable the Transmit buffer) and wrap-around the index if
+ * it reaches the maximum Transmit Number
+ * @param[in] None
+ * @return None
+ **********************************************************************/
+void EMAC_UpdateTxProduceIndex(void)
+{
+ // Get current Tx produce index
+ uint32_t idx = LPC_EMAC->TxProduceIndex;
+
+ /* Start frame transmission */
+ if (++idx == EMAC_NUM_TX_FRAG) idx = 0;
+ LPC_EMAC->TxProduceIndex = idx;
+}
+
+
+/**
+ * @}
+ */
+
+#endif /* _EMAC */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_exti.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_exti.c
new file mode 100644
index 0000000..fa06ba7
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_exti.c
@@ -0,0 +1,158 @@
+/**
+ * @file lpc17xx_exti.c
+ * @brief Contains all functions support for External interrupt firmware library on LPC17xx
+ * @version 3.0
+ * @date 18. June. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup EXTI
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_exti.h"
+
+/* If this source file built with example, the LPC17xx FW library configuration
+ * file in each example directory ("lpc17xx_libcfg.h") must be included,
+ * otherwise the default FW library configuration file must be included instead
+ */
+#ifdef __BUILD_WITH_EXAMPLE__
+#include "lpc17xx_libcfg.h"
+#else
+#include "lpc17xx_libcfg_default.h"
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+
+#ifdef _EXTI
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup EXTI_Public_Functions
+ * @{
+ */
+
+/*********************************************************************//**
+ * @brief Initial for EXT
+ * - Set EXTINT, EXTMODE, EXTPOLAR registers to default value
+ * @param[in] None
+ * @return None
+ **********************************************************************/
+void EXTI_Init(void)
+{
+ LPC_SC->EXTINT = 0xF;
+ LPC_SC->EXTMODE = 0x0;
+ LPC_SC->EXTPOLAR = 0x0;
+}
+
+
+/*********************************************************************//**
+* @brief Close EXT
+* @param[in] None
+* @return None
+**********************************************************************/
+void EXTI_DeInit(void)
+{
+ ;
+}
+
+/*********************************************************************//**
+ * @brief Configuration for EXT
+ * - Set EXTINT, EXTMODE, EXTPOLAR register
+ * @param[in] EXTICfg Pointer to a EXTI_InitTypeDef structure
+ * that contains the configuration information for the
+ * specified external interrupt
+ * @return None
+ **********************************************************************/
+void EXTI_Config(EXTI_InitTypeDef *EXTICfg)
+{
+ LPC_SC->EXTINT = 0x0;
+ EXTI_SetMode(EXTICfg->EXTI_Line, EXTICfg->EXTI_Mode);
+ EXTI_SetPolarity(EXTICfg->EXTI_Line, EXTICfg->EXTI_polarity);
+}
+
+/*********************************************************************//**
+* @brief Set mode for EXTI pin
+* @param[in] EXTILine external interrupt line, should be:
+* - EXTI_EINT0: external interrupt line 0
+* - EXTI_EINT1: external interrupt line 1
+* - EXTI_EINT2: external interrupt line 2
+* - EXTI_EINT3: external interrupt line 3
+* @param[in] mode external mode, should be:
+* - EXTI_MODE_LEVEL_SENSITIVE
+* - EXTI_MODE_EDGE_SENSITIVE
+* @return None
+*********************************************************************/
+void EXTI_SetMode(EXTI_LINE_ENUM EXTILine, EXTI_MODE_ENUM mode)
+{
+ if(mode == EXTI_MODE_EDGE_SENSITIVE)
+ {
+ LPC_SC->EXTMODE |= (1 << EXTILine);
+ }
+ else if(mode == EXTI_MODE_LEVEL_SENSITIVE)
+ {
+ LPC_SC->EXTMODE &= ~(1 << EXTILine);
+ }
+}
+
+/*********************************************************************//**
+* @brief Set polarity for EXTI pin
+* @param[in] EXTILine external interrupt line, should be:
+* - EXTI_EINT0: external interrupt line 0
+* - EXTI_EINT1: external interrupt line 1
+* - EXTI_EINT2: external interrupt line 2
+* - EXTI_EINT3: external interrupt line 3
+* @param[in] polarity external polarity value, should be:
+* - EXTI_POLARITY_LOW_ACTIVE_OR_FALLING_EDGE
+* - EXTI_POLARITY_LOW_ACTIVE_OR_FALLING_EDGE
+* @return None
+*********************************************************************/
+void EXTI_SetPolarity(EXTI_LINE_ENUM EXTILine, EXTI_POLARITY_ENUM polarity)
+{
+ if(polarity == EXTI_POLARITY_HIGH_ACTIVE_OR_RISING_EDGE)
+ {
+ LPC_SC->EXTPOLAR |= (1 << EXTILine);
+ }
+ else if(polarity == EXTI_POLARITY_LOW_ACTIVE_OR_FALLING_EDGE)
+ {
+ LPC_SC->EXTPOLAR &= ~(1 << EXTILine);
+ }
+}
+
+/*********************************************************************//**
+* @brief Clear External interrupt flag
+* @param[in] EXTILine external interrupt line, should be:
+* - EXTI_EINT0: external interrupt line 0
+* - EXTI_EINT1: external interrupt line 1
+* - EXTI_EINT2: external interrupt line 2
+* - EXTI_EINT3: external interrupt line 3
+* @return None
+*********************************************************************/
+void EXTI_ClearEXTIFlag(EXTI_LINE_ENUM EXTILine)
+{
+ LPC_SC->EXTINT |= (1 << EXTILine);
+}
+
+/**
+ * @}
+ */
+
+#endif /* _EXTI */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
+
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_gpdma.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_gpdma.c
new file mode 100644
index 0000000..a8a6299
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_gpdma.c
@@ -0,0 +1,450 @@
+/***********************************************************************//**
+ * @file lpc17xx_gpdma.c
+ * @brief Contains all functions support for GPDMA firmware library on LPC17xx
+ * @version 2.0
+ * @date 21. May. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup GPDMA
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_gpdma.h"
+#include "lpc17xx_clkpwr.h"
+
+/* If this source file built with example, the LPC17xx FW library configuration
+ * file in each example directory ("lpc17xx_libcfg.h") must be included,
+ * otherwise the default FW library configuration file must be included instead
+ */
+#ifdef __BUILD_WITH_EXAMPLE__
+#include "lpc17xx_libcfg.h"
+#else
+#include "lpc17xx_libcfg_default.h"
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+#ifdef _GPDMA
+
+
+/* Private Variables ---------------------------------------------------------- */
+/** @defgroup GPDMA_Private_Variables GPDMA Private Variables
+ * @{
+ */
+
+/**
+ * @brief Lookup Table of Connection Type matched with
+ * Peripheral Data (FIFO) register base address
+ */
+#ifdef __IAR_SYSTEMS_ICC__
+volatile const void *GPDMA_LUTPerAddr[] = {
+ (&LPC_SSP0->DR), // SSP0 Tx
+ (&LPC_SSP0->DR), // SSP0 Rx
+ (&LPC_SSP1->DR), // SSP1 Tx
+ (&LPC_SSP1->DR), // SSP1 Rx
+ (&LPC_ADC->ADGDR), // ADC
+ (&LPC_I2S->I2STXFIFO), // I2S Tx
+ (&LPC_I2S->I2SRXFIFO), // I2S Rx
+ (&LPC_DAC->DACR), // DAC
+ (&LPC_UART0->/*RBTHDLR.*/THR), // UART0 Tx
+ (&LPC_UART0->/*RBTHDLR.*/RBR), // UART0 Rx
+ (&LPC_UART1->/*RBTHDLR.*/THR), // UART1 Tx
+ (&LPC_UART1->/*RBTHDLR.*/RBR), // UART1 Rx
+ (&LPC_UART2->/*RBTHDLR.*/THR), // UART2 Tx
+ (&LPC_UART2->/*RBTHDLR.*/RBR), // UART2 Rx
+ (&LPC_UART3->/*RBTHDLR.*/THR), // UART3 Tx
+ (&LPC_UART3->/*RBTHDLR.*/RBR), // UART3 Rx
+ (&LPC_TIM0->MR0), // MAT0.0
+ (&LPC_TIM0->MR1), // MAT0.1
+ (&LPC_TIM1->MR0), // MAT1.0
+ (&LPC_TIM1->MR1), // MAT1.1
+ (&LPC_TIM2->MR0), // MAT2.0
+ (&LPC_TIM2->MR1), // MAT2.1
+ (&LPC_TIM3->MR0), // MAT3.0
+ (&LPC_TIM3->MR1), // MAT3.1
+};
+#else
+const uint32_t GPDMA_LUTPerAddr[] = {
+ ((uint32_t)&LPC_SSP0->DR), // SSP0 Tx
+ ((uint32_t)&LPC_SSP0->DR), // SSP0 Rx
+ ((uint32_t)&LPC_SSP1->DR), // SSP1 Tx
+ ((uint32_t)&LPC_SSP1->DR), // SSP1 Rx
+ ((uint32_t)&LPC_ADC->ADGDR), // ADC
+ ((uint32_t)&LPC_I2S->I2STXFIFO), // I2S Tx
+ ((uint32_t)&LPC_I2S->I2SRXFIFO), // I2S Rx
+ ((uint32_t)&LPC_DAC->DACR), // DAC
+ ((uint32_t)&LPC_UART0->/*RBTHDLR.*/THR), // UART0 Tx
+ ((uint32_t)&LPC_UART0->/*RBTHDLR.*/RBR), // UART0 Rx
+ ((uint32_t)&LPC_UART1->/*RBTHDLR.*/THR), // UART1 Tx
+ ((uint32_t)&LPC_UART1->/*RBTHDLR.*/RBR), // UART1 Rx
+ ((uint32_t)&LPC_UART2->/*RBTHDLR.*/THR), // UART2 Tx
+ ((uint32_t)&LPC_UART2->/*RBTHDLR.*/RBR), // UART2 Rx
+ ((uint32_t)&LPC_UART3->/*RBTHDLR.*/THR), // UART3 Tx
+ ((uint32_t)&LPC_UART3->/*RBTHDLR.*/RBR), // UART3 Rx
+ ((uint32_t)&LPC_TIM0->MR0), // MAT0.0
+ ((uint32_t)&LPC_TIM0->MR1), // MAT0.1
+ ((uint32_t)&LPC_TIM1->MR0), // MAT1.0
+ ((uint32_t)&LPC_TIM1->MR1), // MAT1.1
+ ((uint32_t)&LPC_TIM2->MR0), // MAT2.0
+ ((uint32_t)&LPC_TIM2->MR1), // MAT2.1
+ ((uint32_t)&LPC_TIM3->MR0), // MAT3.0
+ ((uint32_t)&LPC_TIM3->MR1), // MAT3.1
+};
+#endif
+/**
+ * @brief Lookup Table of GPDMA Channel Number matched with
+ * GPDMA channel pointer
+ */
+const LPC_GPDMACH_TypeDef *pGPDMACh[8] = {
+ LPC_GPDMACH0, // GPDMA Channel 0
+ LPC_GPDMACH1, // GPDMA Channel 1
+ LPC_GPDMACH2, // GPDMA Channel 2
+ LPC_GPDMACH3, // GPDMA Channel 3
+ LPC_GPDMACH4, // GPDMA Channel 4
+ LPC_GPDMACH5, // GPDMA Channel 5
+ LPC_GPDMACH6, // GPDMA Channel 6
+ LPC_GPDMACH7, // GPDMA Channel 7
+};
+/**
+ * @brief Optimized Peripheral Source and Destination burst size
+ */
+const uint8_t GPDMA_LUTPerBurst[] = {
+ GPDMA_BSIZE_4, // SSP0 Tx
+ GPDMA_BSIZE_4, // SSP0 Rx
+ GPDMA_BSIZE_4, // SSP1 Tx
+ GPDMA_BSIZE_4, // SSP1 Rx
+ GPDMA_BSIZE_4, // ADC
+ GPDMA_BSIZE_32, // I2S channel 0
+ GPDMA_BSIZE_32, // I2S channel 1
+ GPDMA_BSIZE_1, // DAC
+ GPDMA_BSIZE_1, // UART0 Tx
+ GPDMA_BSIZE_1, // UART0 Rx
+ GPDMA_BSIZE_1, // UART1 Tx
+ GPDMA_BSIZE_1, // UART1 Rx
+ GPDMA_BSIZE_1, // UART2 Tx
+ GPDMA_BSIZE_1, // UART2 Rx
+ GPDMA_BSIZE_1, // UART3 Tx
+ GPDMA_BSIZE_1, // UART3 Rx
+ GPDMA_BSIZE_1, // MAT0.0
+ GPDMA_BSIZE_1, // MAT0.1
+ GPDMA_BSIZE_1, // MAT1.0
+ GPDMA_BSIZE_1, // MAT1.1
+ GPDMA_BSIZE_1, // MAT2.0
+ GPDMA_BSIZE_1, // MAT2.1
+ GPDMA_BSIZE_1, // MAT3.0
+ GPDMA_BSIZE_1, // MAT3.1
+};
+/**
+ * @brief Optimized Peripheral Source and Destination transfer width
+ */
+const uint8_t GPDMA_LUTPerWid[] = {
+ GPDMA_WIDTH_BYTE, // SSP0 Tx
+ GPDMA_WIDTH_BYTE, // SSP0 Rx
+ GPDMA_WIDTH_BYTE, // SSP1 Tx
+ GPDMA_WIDTH_BYTE, // SSP1 Rx
+ GPDMA_WIDTH_WORD, // ADC
+ GPDMA_WIDTH_WORD, // I2S channel 0
+ GPDMA_WIDTH_WORD, // I2S channel 1
+ GPDMA_WIDTH_BYTE, // DAC
+ GPDMA_WIDTH_BYTE, // UART0 Tx
+ GPDMA_WIDTH_BYTE, // UART0 Rx
+ GPDMA_WIDTH_BYTE, // UART1 Tx
+ GPDMA_WIDTH_BYTE, // UART1 Rx
+ GPDMA_WIDTH_BYTE, // UART2 Tx
+ GPDMA_WIDTH_BYTE, // UART2 Rx
+ GPDMA_WIDTH_BYTE, // UART3 Tx
+ GPDMA_WIDTH_BYTE, // UART3 Rx
+ GPDMA_WIDTH_WORD, // MAT0.0
+ GPDMA_WIDTH_WORD, // MAT0.1
+ GPDMA_WIDTH_WORD, // MAT1.0
+ GPDMA_WIDTH_WORD, // MAT1.1
+ GPDMA_WIDTH_WORD, // MAT2.0
+ GPDMA_WIDTH_WORD, // MAT2.1
+ GPDMA_WIDTH_WORD, // MAT3.0
+ GPDMA_WIDTH_WORD, // MAT3.1
+};
+
+/**
+ * @}
+ */
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup GPDMA_Public_Functions
+ * @{
+ */
+
+/********************************************************************//**
+ * @brief Initialize GPDMA controller
+ * @param None
+ * @return None
+ *********************************************************************/
+void GPDMA_Init(void)
+{
+ /* Enable GPDMA clock */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCGPDMA, ENABLE);
+
+ // Reset all channel configuration register
+ LPC_GPDMACH0->DMACCConfig = 0;
+ LPC_GPDMACH1->DMACCConfig = 0;
+ LPC_GPDMACH2->DMACCConfig = 0;
+ LPC_GPDMACH3->DMACCConfig = 0;
+ LPC_GPDMACH4->DMACCConfig = 0;
+ LPC_GPDMACH5->DMACCConfig = 0;
+ LPC_GPDMACH6->DMACCConfig = 0;
+ LPC_GPDMACH7->DMACCConfig = 0;
+
+ /* Clear all DMA interrupt and error flag */
+ LPC_GPDMA->DMACIntTCClear = 0xFF;
+ LPC_GPDMA->DMACIntErrClr = 0xFF;
+}
+
+/********************************************************************//**
+ * @brief Setup GPDMA channel peripheral according to the specified
+ * parameters in the GPDMAChannelConfig.
+ * @param[in] GPDMAChannelConfig Pointer to a GPDMA_CH_CFG_Type
+ * structure that contains the configuration
+ * information for the specified GPDMA channel peripheral.
+ * @return ERROR if selected channel is enabled before
+ * or SUCCESS if channel is configured successfully
+ *********************************************************************/
+Status GPDMA_Setup(GPDMA_Channel_CFG_Type *GPDMAChannelConfig)
+{
+ LPC_GPDMACH_TypeDef *pDMAch;
+ uint32_t tmp1, tmp2;
+
+ if (LPC_GPDMA->DMACEnbldChns & (GPDMA_DMACEnbldChns_Ch(GPDMAChannelConfig->ChannelNum))) {
+ // This channel is enabled, return ERROR, need to release this channel first
+ return ERROR;
+ }
+
+ // Get Channel pointer
+ pDMAch = (LPC_GPDMACH_TypeDef *) pGPDMACh[GPDMAChannelConfig->ChannelNum];
+
+ // Reset the Interrupt status
+ LPC_GPDMA->DMACIntTCClear = GPDMA_DMACIntTCClear_Ch(GPDMAChannelConfig->ChannelNum);
+ LPC_GPDMA->DMACIntErrClr = GPDMA_DMACIntErrClr_Ch(GPDMAChannelConfig->ChannelNum);
+
+ // Clear DMA configure
+ pDMAch->DMACCControl = 0x00;
+ pDMAch->DMACCConfig = 0x00;
+
+ /* Assign Linker List Item value */
+ pDMAch->DMACCLLI = GPDMAChannelConfig->DMALLI;
+
+ /* Set value to Channel Control Registers */
+ switch (GPDMAChannelConfig->TransferType)
+ {
+ // Memory to memory
+ case GPDMA_TRANSFERTYPE_M2M:
+ // Assign physical source and destination address
+ pDMAch->DMACCSrcAddr = GPDMAChannelConfig->SrcMemAddr;
+ pDMAch->DMACCDestAddr = GPDMAChannelConfig->DstMemAddr;
+ pDMAch->DMACCControl
+ = GPDMA_DMACCxControl_TransferSize(GPDMAChannelConfig->TransferSize) \
+ | GPDMA_DMACCxControl_SBSize(GPDMA_BSIZE_32) \
+ | GPDMA_DMACCxControl_DBSize(GPDMA_BSIZE_32) \
+ | GPDMA_DMACCxControl_SWidth(GPDMAChannelConfig->TransferWidth) \
+ | GPDMA_DMACCxControl_DWidth(GPDMAChannelConfig->TransferWidth) \
+ | GPDMA_DMACCxControl_SI \
+ | GPDMA_DMACCxControl_DI \
+ | GPDMA_DMACCxControl_I;
+ break;
+ // Memory to peripheral
+ case GPDMA_TRANSFERTYPE_M2P:
+ // Assign physical source
+ pDMAch->DMACCSrcAddr = GPDMAChannelConfig->SrcMemAddr;
+ // Assign peripheral destination address
+ pDMAch->DMACCDestAddr = (uint32_t)GPDMA_LUTPerAddr[GPDMAChannelConfig->DstConn];
+ pDMAch->DMACCControl
+ = GPDMA_DMACCxControl_TransferSize((uint32_t)GPDMAChannelConfig->TransferSize) \
+ | GPDMA_DMACCxControl_SBSize((uint32_t)GPDMA_LUTPerBurst[GPDMAChannelConfig->DstConn]) \
+ | GPDMA_DMACCxControl_DBSize((uint32_t)GPDMA_LUTPerBurst[GPDMAChannelConfig->DstConn]) \
+ | GPDMA_DMACCxControl_SWidth((uint32_t)GPDMA_LUTPerWid[GPDMAChannelConfig->DstConn]) \
+ | GPDMA_DMACCxControl_DWidth((uint32_t)GPDMA_LUTPerWid[GPDMAChannelConfig->DstConn]) \
+ | GPDMA_DMACCxControl_SI \
+ | GPDMA_DMACCxControl_I;
+ break;
+ // Peripheral to memory
+ case GPDMA_TRANSFERTYPE_P2M:
+ // Assign peripheral source address
+ pDMAch->DMACCSrcAddr = (uint32_t)GPDMA_LUTPerAddr[GPDMAChannelConfig->SrcConn];
+ // Assign memory destination address
+ pDMAch->DMACCDestAddr = GPDMAChannelConfig->DstMemAddr;
+ pDMAch->DMACCControl
+ = GPDMA_DMACCxControl_TransferSize((uint32_t)GPDMAChannelConfig->TransferSize) \
+ | GPDMA_DMACCxControl_SBSize((uint32_t)GPDMA_LUTPerBurst[GPDMAChannelConfig->SrcConn]) \
+ | GPDMA_DMACCxControl_DBSize((uint32_t)GPDMA_LUTPerBurst[GPDMAChannelConfig->SrcConn]) \
+ | GPDMA_DMACCxControl_SWidth((uint32_t)GPDMA_LUTPerWid[GPDMAChannelConfig->SrcConn]) \
+ | GPDMA_DMACCxControl_DWidth((uint32_t)GPDMA_LUTPerWid[GPDMAChannelConfig->SrcConn]) \
+ | GPDMA_DMACCxControl_DI \
+ | GPDMA_DMACCxControl_I;
+ break;
+ // Peripheral to peripheral
+ case GPDMA_TRANSFERTYPE_P2P:
+ // Assign peripheral source address
+ pDMAch->DMACCSrcAddr = (uint32_t)GPDMA_LUTPerAddr[GPDMAChannelConfig->SrcConn];
+ // Assign peripheral destination address
+ pDMAch->DMACCDestAddr = (uint32_t)GPDMA_LUTPerAddr[GPDMAChannelConfig->DstConn];
+ pDMAch->DMACCControl
+ = GPDMA_DMACCxControl_TransferSize((uint32_t)GPDMAChannelConfig->TransferSize) \
+ | GPDMA_DMACCxControl_SBSize((uint32_t)GPDMA_LUTPerBurst[GPDMAChannelConfig->SrcConn]) \
+ | GPDMA_DMACCxControl_DBSize((uint32_t)GPDMA_LUTPerBurst[GPDMAChannelConfig->DstConn]) \
+ | GPDMA_DMACCxControl_SWidth((uint32_t)GPDMA_LUTPerWid[GPDMAChannelConfig->SrcConn]) \
+ | GPDMA_DMACCxControl_DWidth((uint32_t)GPDMA_LUTPerWid[GPDMAChannelConfig->DstConn]) \
+ | GPDMA_DMACCxControl_I;
+ break;
+ // Do not support any more transfer type, return ERROR
+ default:
+ return ERROR;
+ }
+
+ /* Re-Configure DMA Request Select for source peripheral */
+ if (GPDMAChannelConfig->SrcConn > 15)
+ {
+ DMAREQSEL |= (1<<(GPDMAChannelConfig->SrcConn - 16));
+ } else {
+ DMAREQSEL &= ~(1<<(GPDMAChannelConfig->SrcConn - 8));
+ }
+
+ /* Re-Configure DMA Request Select for Destination peripheral */
+ if (GPDMAChannelConfig->DstConn > 15)
+ {
+ DMAREQSEL |= (1<<(GPDMAChannelConfig->DstConn - 16));
+ } else {
+ DMAREQSEL &= ~(1<<(GPDMAChannelConfig->DstConn - 8));
+ }
+
+ /* Enable DMA channels, little endian */
+ LPC_GPDMA->DMACConfig = GPDMA_DMACConfig_E;
+ while (!(LPC_GPDMA->DMACConfig & GPDMA_DMACConfig_E));
+
+ // Calculate absolute value for Connection number
+ tmp1 = GPDMAChannelConfig->SrcConn;
+ tmp1 = ((tmp1 > 15) ? (tmp1 - 8) : tmp1);
+ tmp2 = GPDMAChannelConfig->DstConn;
+ tmp2 = ((tmp2 > 15) ? (tmp2 - 8) : tmp2);
+
+ // Configure DMA Channel, enable Error Counter and Terminate counter
+ pDMAch->DMACCConfig = GPDMA_DMACCxConfig_IE | GPDMA_DMACCxConfig_ITC /*| GPDMA_DMACCxConfig_E*/ \
+ | GPDMA_DMACCxConfig_TransferType((uint32_t)GPDMAChannelConfig->TransferType) \
+ | GPDMA_DMACCxConfig_SrcPeripheral(tmp1) \
+ | GPDMA_DMACCxConfig_DestPeripheral(tmp2);
+
+ return SUCCESS;
+}
+
+
+/*********************************************************************//**
+ * @brief Enable/Disable DMA channel
+ * @param[in] channelNum GPDMA channel, should be in range from 0 to 7
+ * @param[in] NewState New State of this command, should be:
+ * - ENABLE.
+ * - DISABLE.
+ * @return None
+ **********************************************************************/
+void GPDMA_ChannelCmd(uint8_t channelNum, FunctionalState NewState)
+{
+ LPC_GPDMACH_TypeDef *pDMAch;
+
+ // Get Channel pointer
+ pDMAch = (LPC_GPDMACH_TypeDef *) pGPDMACh[channelNum];
+
+ if (NewState == ENABLE) {
+ pDMAch->DMACCConfig |= GPDMA_DMACCxConfig_E;
+ } else {
+ pDMAch->DMACCConfig &= ~GPDMA_DMACCxConfig_E;
+ }
+}
+/*********************************************************************//**
+ * @brief Check if corresponding channel does have an active interrupt
+ * request or not
+ * @param[in] type type of status, should be:
+ * - GPDMA_STAT_INT: GPDMA Interrupt Status
+ * - GPDMA_STAT_INTTC: GPDMA Interrupt Terminal Count Request Status
+ * - GPDMA_STAT_INTERR: GPDMA Interrupt Error Status
+ * - GPDMA_STAT_RAWINTTC: GPDMA Raw Interrupt Terminal Count Status
+ * - GPDMA_STAT_RAWINTERR: GPDMA Raw Error Interrupt Status
+ * - GPDMA_STAT_ENABLED_CH:GPDMA Enabled Channel Status
+ * @param[in] channel GPDMA channel, should be in range from 0 to 7
+ * @return IntStatus status of DMA channel interrupt after masking
+ * Should be:
+ * - SET: the corresponding channel has no active interrupt request
+ * - RESET: the corresponding channel does have an active interrupt request
+ **********************************************************************/
+IntStatus GPDMA_IntGetStatus(GPDMA_Status_Type type, uint8_t channel)
+{
+ CHECK_PARAM(PARAM_GPDMA_STAT(type));
+ CHECK_PARAM(PARAM_GPDMA_CHANNEL(channel));
+
+ switch (type)
+ {
+ case GPDMA_STAT_INT: //check status of DMA channel interrupts
+ if (LPC_GPDMA->DMACIntStat & (GPDMA_DMACIntStat_Ch(channel)))
+ return SET;
+ return RESET;
+ case GPDMA_STAT_INTTC: // check terminal count interrupt request status for DMA
+ if (LPC_GPDMA->DMACIntTCStat & GPDMA_DMACIntTCStat_Ch(channel))
+ return SET;
+ return RESET;
+ case GPDMA_STAT_INTERR: //check interrupt status for DMA channels
+ if (LPC_GPDMA->DMACIntErrStat & GPDMA_DMACIntTCClear_Ch(channel))
+ return SET;
+ return RESET;
+ case GPDMA_STAT_RAWINTTC: //check status of the terminal count interrupt for DMA channels
+ if (LPC_GPDMA->DMACRawIntErrStat & GPDMA_DMACRawIntTCStat_Ch(channel))
+ return SET;
+ return RESET;
+ case GPDMA_STAT_RAWINTERR: //check status of the error interrupt for DMA channels
+ if (LPC_GPDMA->DMACRawIntTCStat & GPDMA_DMACRawIntErrStat_Ch(channel))
+ return SET;
+ return RESET;
+ default: //check enable status for DMA channels
+ if (LPC_GPDMA->DMACEnbldChns & GPDMA_DMACEnbldChns_Ch(channel))
+ return SET;
+ return RESET;
+ }
+}
+
+/*********************************************************************//**
+ * @brief Clear one or more interrupt requests on DMA channels
+ * @param[in] type type of interrupt request, should be:
+ * - GPDMA_STATCLR_INTTC: GPDMA Interrupt Terminal Count Request Clear
+ * - GPDMA_STATCLR_INTERR: GPDMA Interrupt Error Clear
+ * @param[in] channel GPDMA channel, should be in range from 0 to 7
+ * @return None
+ **********************************************************************/
+void GPDMA_ClearIntPending(GPDMA_StateClear_Type type, uint8_t channel)
+{
+ CHECK_PARAM(PARAM_GPDMA_STATCLR(type));
+ CHECK_PARAM(PARAM_GPDMA_CHANNEL(channel));
+
+ if (type == GPDMA_STATCLR_INTTC) // clears the terminal count interrupt request on DMA channel
+ LPC_GPDMA->DMACIntTCClear = GPDMA_DMACIntTCClear_Ch(channel);
+ else // clear the error interrupt request
+ LPC_GPDMA->DMACIntErrClr = GPDMA_DMACIntErrClr_Ch(channel);
+}
+
+/**
+ * @}
+ */
+
+#endif /* _GPDMA */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
+
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_gpio.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_gpio.c
new file mode 100644
index 0000000..8c037c6
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_gpio.c
@@ -0,0 +1,749 @@
+/***********************************************************************//**
+ * @file lpc17xx_gpio.c
+ * @brief Contains all functions support for GPIO firmware library on LPC17xx
+ * @version 2.0
+ * @date 21. May. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup GPIO
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_gpio.h"
+
+/* If this source file built with example, the LPC17xx FW library configuration
+ * file in each example directory ("lpc17xx_libcfg.h") must be included,
+ * otherwise the default FW library configuration file must be included instead
+ */
+#ifdef __BUILD_WITH_EXAMPLE__
+#include "lpc17xx_libcfg.h"
+#else
+#include "lpc17xx_libcfg_default.h"
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+
+#ifdef _GPIO
+
+/* Private Functions ---------------------------------------------------------- */
+
+static LPC_GPIO_TypeDef *GPIO_GetPointer(uint8_t portNum);
+static GPIO_HalfWord_TypeDef *FIO_HalfWordGetPointer(uint8_t portNum);
+static GPIO_Byte_TypeDef *FIO_ByteGetPointer(uint8_t portNum);
+
+/*********************************************************************//**
+ * @brief Get pointer to GPIO peripheral due to GPIO port
+ * @param[in] portNum Port Number value, should be in range from 0 to 4.
+ * @return Pointer to GPIO peripheral
+ **********************************************************************/
+static LPC_GPIO_TypeDef *GPIO_GetPointer(uint8_t portNum)
+{
+ LPC_GPIO_TypeDef *pGPIO = NULL;
+
+ switch (portNum) {
+ case 0:
+ pGPIO = LPC_GPIO0;
+ break;
+ case 1:
+ pGPIO = LPC_GPIO1;
+ break;
+ case 2:
+ pGPIO = LPC_GPIO2;
+ break;
+ case 3:
+ pGPIO = LPC_GPIO3;
+ break;
+ case 4:
+ pGPIO = LPC_GPIO4;
+ break;
+ default:
+ break;
+ }
+
+ return pGPIO;
+}
+
+/*********************************************************************//**
+ * @brief Get pointer to FIO peripheral in halfword accessible style
+ * due to FIO port
+ * @param[in] portNum Port Number value, should be in range from 0 to 4.
+ * @return Pointer to FIO peripheral
+ **********************************************************************/
+static GPIO_HalfWord_TypeDef *FIO_HalfWordGetPointer(uint8_t portNum)
+{
+ GPIO_HalfWord_TypeDef *pFIO = NULL;
+
+ switch (portNum) {
+ case 0:
+ pFIO = GPIO0_HalfWord;
+ break;
+ case 1:
+ pFIO = GPIO1_HalfWord;
+ break;
+ case 2:
+ pFIO = GPIO2_HalfWord;
+ break;
+ case 3:
+ pFIO = GPIO3_HalfWord;
+ break;
+ case 4:
+ pFIO = GPIO4_HalfWord;
+ break;
+ default:
+ break;
+ }
+
+ return pFIO;
+}
+
+/*********************************************************************//**
+ * @brief Get pointer to FIO peripheral in byte accessible style
+ * due to FIO port
+ * @param[in] portNum Port Number value, should be in range from 0 to 4.
+ * @return Pointer to FIO peripheral
+ **********************************************************************/
+static GPIO_Byte_TypeDef *FIO_ByteGetPointer(uint8_t portNum)
+{
+ GPIO_Byte_TypeDef *pFIO = NULL;
+
+ switch (portNum) {
+ case 0:
+ pFIO = GPIO0_Byte;
+ break;
+ case 1:
+ pFIO = GPIO1_Byte;
+ break;
+ case 2:
+ pFIO = GPIO2_Byte;
+ break;
+ case 3:
+ pFIO = GPIO3_Byte;
+ break;
+ case 4:
+ pFIO = GPIO4_Byte;
+ break;
+ default:
+ break;
+ }
+
+ return pFIO;
+}
+
+/* End of Private Functions --------------------------------------------------- */
+
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup GPIO_Public_Functions
+ * @{
+ */
+
+
+/* GPIO ------------------------------------------------------------------------------ */
+
+/*********************************************************************//**
+ * @brief Set Direction for GPIO port.
+ * @param[in] portNum Port Number value, should be in range from 0 to 4
+ * @param[in] bitValue Value that contains all bits to set direction,
+ * in range from 0 to 0xFFFFFFFF.
+ * example: value 0x5 to set direction for bit 0 and bit 1.
+ * @param[in] dir Direction value, should be:
+ * - 0: Input.
+ * - 1: Output.
+ * @return None
+ *
+ * Note: All remaining bits that are not activated in bitValue (value '0')
+ * will not be effected by this function.
+ **********************************************************************/
+void GPIO_SetDir(uint8_t portNum, uint32_t bitValue, uint8_t dir)
+{
+ LPC_GPIO_TypeDef *pGPIO = GPIO_GetPointer(portNum);
+
+ if (pGPIO != NULL) {
+ // Enable Output
+ if (dir) {
+ pGPIO->FIODIR |= bitValue;
+ }
+ // Enable Input
+ else {
+ pGPIO->FIODIR &= ~bitValue;
+ }
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Set Value for bits that have output direction on GPIO port.
+ * @param[in] portNum Port number value, should be in range from 0 to 4
+ * @param[in] bitValue Value that contains all bits on GPIO to set,
+ * in range from 0 to 0xFFFFFFFF.
+ * example: value 0x5 to set bit 0 and bit 1.
+ * @return None
+ *
+ * Note:
+ * - For all bits that has been set as input direction, this function will
+ * not effect.
+ * - For all remaining bits that are not activated in bitValue (value '0')
+ * will not be effected by this function.
+ **********************************************************************/
+void GPIO_SetValue(uint8_t portNum, uint32_t bitValue)
+{
+ LPC_GPIO_TypeDef *pGPIO = GPIO_GetPointer(portNum);
+
+ if (pGPIO != NULL) {
+ pGPIO->FIOSET = bitValue;
+ }
+}
+
+/*********************************************************************//**
+ * @brief Clear Value for bits that have output direction on GPIO port.
+ * @param[in] portNum Port number value, should be in range from 0 to 4
+ * @param[in] bitValue Value that contains all bits on GPIO to clear,
+ * in range from 0 to 0xFFFFFFFF.
+ * example: value 0x5 to clear bit 0 and bit 1.
+ * @return None
+ *
+ * Note:
+ * - For all bits that has been set as input direction, this function will
+ * not effect.
+ * - For all remaining bits that are not activated in bitValue (value '0')
+ * will not be effected by this function.
+ **********************************************************************/
+void GPIO_ClearValue(uint8_t portNum, uint32_t bitValue)
+{
+ LPC_GPIO_TypeDef *pGPIO = GPIO_GetPointer(portNum);
+
+ if (pGPIO != NULL) {
+ pGPIO->FIOCLR = bitValue;
+ }
+}
+
+/*********************************************************************//**
+ * @brief Read Current state on port pin that have input direction of GPIO
+ * @param[in] portNum Port number to read value, in range from 0 to 4
+ * @return Current value of GPIO port.
+ *
+ * Note: Return value contain state of each port pin (bit) on that GPIO regardless
+ * its direction is input or output.
+ **********************************************************************/
+uint32_t GPIO_ReadValue(uint8_t portNum)
+{
+ LPC_GPIO_TypeDef *pGPIO = GPIO_GetPointer(portNum);
+
+ if (pGPIO != NULL) {
+ return pGPIO->FIOPIN;
+ }
+
+ return (0);
+}
+
+/*********************************************************************//**
+ * @brief Enable GPIO interrupt (just used for P0.0-P0.30, P2.0-P2.13)
+ * @param[in] portNum Port number to read value, should be: 0 or 2
+ * @param[in] bitValue Value that contains all bits on GPIO to enable,
+ * in range from 0 to 0xFFFFFFFF.
+ * @param[in] edgeState state of edge, should be:
+ * - 0: Rising edge
+ * - 1: Falling edge
+ * @return None
+ **********************************************************************/
+void GPIO_IntCmd(uint8_t portNum, uint32_t bitValue, uint8_t edgeState)
+{
+ if((portNum == 0)&&(edgeState == 0))
+ LPC_GPIOINT->IO0IntEnR = bitValue;
+ else if ((portNum == 2)&&(edgeState == 0))
+ LPC_GPIOINT->IO2IntEnR = bitValue;
+ else if ((portNum == 0)&&(edgeState == 1))
+ LPC_GPIOINT->IO0IntEnF = bitValue;
+ else if ((portNum == 2)&&(edgeState == 1))
+ LPC_GPIOINT->IO2IntEnF = bitValue;
+ else
+ //Error
+ while(1);
+}
+
+/*********************************************************************//**
+ * @brief Get GPIO Interrupt Status (just used for P0.0-P0.30, P2.0-P2.13)
+ * @param[in] portNum Port number to read value, should be: 0 or 2
+ * @param[in] pinNum Pin number, should be: 0..30(with port 0) and 0..13
+ * (with port 2)
+ * @param[in] edgeState state of edge, should be:
+ * - 0: Rising edge
+ * - 1: Falling edge
+ * @return Bool could be:
+ * - ENABLE: Interrupt has been generated due to a rising
+ * edge on P0.0
+ * - DISABLE: A rising edge has not been detected on P0.0
+ **********************************************************************/
+FunctionalState GPIO_GetIntStatus(uint8_t portNum, uint32_t pinNum, uint8_t edgeState)
+{
+ if((portNum == 0) && (edgeState == 0))//Rising Edge
+ return (((LPC_GPIOINT->IO0IntStatR)>>pinNum)& 0x1);
+ else if ((portNum == 2) && (edgeState == 0))
+ return (((LPC_GPIOINT->IO2IntStatR)>>pinNum)& 0x1);
+ else if ((portNum == 0) && (edgeState == 1))//Falling Edge
+ return (((LPC_GPIOINT->IO0IntStatF)>>pinNum)& 0x1);
+ else if ((portNum == 2) && (edgeState == 1))
+ return (((LPC_GPIOINT->IO2IntStatF)>>pinNum)& 0x1);
+ else
+ //Error
+ while(1);
+}
+/*********************************************************************//**
+ * @brief Clear GPIO interrupt (just used for P0.0-P0.30, P2.0-P2.13)
+ * @param[in] portNum Port number to read value, should be: 0 or 2
+ * @param[in] bitValue Value that contains all bits on GPIO to enable,
+ * in range from 0 to 0xFFFFFFFF.
+ * @return None
+ **********************************************************************/
+void GPIO_ClearInt(uint8_t portNum, uint32_t bitValue)
+{
+ if(portNum == 0)
+ LPC_GPIOINT->IO0IntClr = bitValue;
+ else if (portNum == 2)
+ LPC_GPIOINT->IO2IntClr = bitValue;
+ else
+ //Invalid portNum
+ while(1);
+}
+
+/* FIO word accessible ----------------------------------------------------------------- */
+/* Stub function for FIO (word-accessible) style */
+
+/**
+ * @brief The same with GPIO_SetDir()
+ */
+void FIO_SetDir(uint8_t portNum, uint32_t bitValue, uint8_t dir)
+{
+ GPIO_SetDir(portNum, bitValue, dir);
+}
+
+/**
+ * @brief The same with GPIO_SetValue()
+ */
+void FIO_SetValue(uint8_t portNum, uint32_t bitValue)
+{
+ GPIO_SetValue(portNum, bitValue);
+}
+
+/**
+ * @brief The same with GPIO_ClearValue()
+ */
+void FIO_ClearValue(uint8_t portNum, uint32_t bitValue)
+{
+ GPIO_ClearValue(portNum, bitValue);
+}
+
+/**
+ * @brief The same with GPIO_ReadValue()
+ */
+uint32_t FIO_ReadValue(uint8_t portNum)
+{
+ return (GPIO_ReadValue(portNum));
+}
+
+/**
+ * @brief The same with GPIO_IntCmd()
+ */
+void FIO_IntCmd(uint8_t portNum, uint32_t bitValue, uint8_t edgeState)
+{
+ GPIO_IntCmd(portNum, bitValue, edgeState);
+}
+
+/**
+ * @brief The same with GPIO_GetIntStatus()
+ */
+FunctionalState FIO_GetIntStatus(uint8_t portNum, uint32_t pinNum, uint8_t edgeState)
+{
+ return (GPIO_GetIntStatus(portNum, pinNum, edgeState));
+}
+
+/**
+ * @brief The same with GPIO_ClearInt()
+ */
+void FIO_ClearInt(uint8_t portNum, uint32_t bitValue)
+{
+ GPIO_ClearInt(portNum, bitValue);
+}
+/*********************************************************************//**
+ * @brief Set mask value for bits in FIO port
+ * @param[in] portNum Port number, in range from 0 to 4
+ * @param[in] bitValue Value that contains all bits in to set,
+ * in range from 0 to 0xFFFFFFFF.
+ * @param[in] maskValue Mask value contains state value for each bit:
+ * - 0: not mask.
+ * - 1: mask.
+ * @return None
+ *
+ * Note:
+ * - All remaining bits that are not activated in bitValue (value '0')
+ * will not be effected by this function.
+ * - After executing this function, in mask register, value '0' on each bit
+ * enables an access to the corresponding physical pin via a read or write access,
+ * while value '1' on bit (masked) that corresponding pin will not be changed
+ * with write access and if read, will not be reflected in the updated pin.
+ **********************************************************************/
+void FIO_SetMask(uint8_t portNum, uint32_t bitValue, uint8_t maskValue)
+{
+ LPC_GPIO_TypeDef *pFIO = GPIO_GetPointer(portNum);
+ if(pFIO != NULL) {
+ // Mask
+ if (maskValue){
+ pFIO->FIOMASK |= bitValue;
+ }
+ // Un-mask
+ else {
+ pFIO->FIOMASK &= ~bitValue;
+ }
+ }
+}
+
+
+/* FIO halfword accessible ------------------------------------------------------------- */
+
+/*********************************************************************//**
+ * @brief Set direction for FIO port in halfword accessible style
+ * @param[in] portNum Port number, in range from 0 to 4
+ * @param[in] halfwordNum HalfWord part number, should be 0 (lower) or 1(upper)
+ * @param[in] bitValue Value that contains all bits in to set direction,
+ * in range from 0 to 0xFFFF.
+ * @param[in] dir Direction value, should be:
+ * - 0: Input.
+ * - 1: Output.
+ * @return None
+ *
+ * Note: All remaining bits that are not activated in bitValue (value '0')
+ * will not be effected by this function.
+ **********************************************************************/
+void FIO_HalfWordSetDir(uint8_t portNum, uint8_t halfwordNum, uint16_t bitValue, uint8_t dir)
+{
+ GPIO_HalfWord_TypeDef *pFIO = FIO_HalfWordGetPointer(portNum);
+ if(pFIO != NULL) {
+ // Output direction
+ if (dir) {
+ // Upper
+ if(halfwordNum) {
+ pFIO->FIODIRU |= bitValue;
+ }
+ // lower
+ else {
+ pFIO->FIODIRL |= bitValue;
+ }
+ }
+ // Input direction
+ else {
+ // Upper
+ if(halfwordNum) {
+ pFIO->FIODIRU &= ~bitValue;
+ }
+ // lower
+ else {
+ pFIO->FIODIRL &= ~bitValue;
+ }
+ }
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Set mask value for bits in FIO port in halfword accessible style
+ * @param[in] portNum Port number, in range from 0 to 4
+ * @param[in] halfwordNum HalfWord part number, should be 0 (lower) or 1(upper)
+ * @param[in] bitValue Value that contains all bits in to set,
+ * in range from 0 to 0xFFFF.
+ * @param[in] maskValue Mask value contains state value for each bit:
+ * - 0: not mask.
+ * - 1: mask.
+ * @return None
+ *
+ * Note:
+ * - All remaining bits that are not activated in bitValue (value '0')
+ * will not be effected by this function.
+ * - After executing this function, in mask register, value '0' on each bit
+ * enables an access to the corresponding physical pin via a read or write access,
+ * while value '1' on bit (masked) that corresponding pin will not be changed
+ * with write access and if read, will not be reflected in the updated pin.
+ **********************************************************************/
+void FIO_HalfWordSetMask(uint8_t portNum, uint8_t halfwordNum, uint16_t bitValue, uint8_t maskValue)
+{
+ GPIO_HalfWord_TypeDef *pFIO = FIO_HalfWordGetPointer(portNum);
+ if(pFIO != NULL) {
+ // Mask
+ if (maskValue){
+ // Upper
+ if(halfwordNum) {
+ pFIO->FIOMASKU |= bitValue;
+ }
+ // lower
+ else {
+ pFIO->FIOMASKL |= bitValue;
+ }
+ }
+ // Un-mask
+ else {
+ // Upper
+ if(halfwordNum) {
+ pFIO->FIOMASKU &= ~bitValue;
+ }
+ // lower
+ else {
+ pFIO->FIOMASKL &= ~bitValue;
+ }
+ }
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Set bits for FIO port in halfword accessible style
+ * @param[in] portNum Port number, in range from 0 to 4
+ * @param[in] halfwordNum HalfWord part number, should be 0 (lower) or 1(upper)
+ * @param[in] bitValue Value that contains all bits in to set,
+ * in range from 0 to 0xFFFF.
+ * @return None
+ *
+ * Note:
+ * - For all bits that has been set as input direction, this function will
+ * not effect.
+ * - For all remaining bits that are not activated in bitValue (value '0')
+ * will not be effected by this function.
+ **********************************************************************/
+void FIO_HalfWordSetValue(uint8_t portNum, uint8_t halfwordNum, uint16_t bitValue)
+{
+ GPIO_HalfWord_TypeDef *pFIO = FIO_HalfWordGetPointer(portNum);
+ if(pFIO != NULL) {
+ // Upper
+ if(halfwordNum) {
+ pFIO->FIOSETU = bitValue;
+ }
+ // lower
+ else {
+ pFIO->FIOSETL = bitValue;
+ }
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Clear bits for FIO port in halfword accessible style
+ * @param[in] portNum Port number, in range from 0 to 4
+ * @param[in] halfwordNum HalfWord part number, should be 0 (lower) or 1(upper)
+ * @param[in] bitValue Value that contains all bits in to clear,
+ * in range from 0 to 0xFFFF.
+ * @return None
+ *
+ * Note:
+ * - For all bits that has been set as input direction, this function will
+ * not effect.
+ * - For all remaining bits that are not activated in bitValue (value '0')
+ * will not be effected by this function.
+ **********************************************************************/
+void FIO_HalfWordClearValue(uint8_t portNum, uint8_t halfwordNum, uint16_t bitValue)
+{
+ GPIO_HalfWord_TypeDef *pFIO = FIO_HalfWordGetPointer(portNum);
+ if(pFIO != NULL) {
+ // Upper
+ if(halfwordNum) {
+ pFIO->FIOCLRU = bitValue;
+ }
+ // lower
+ else {
+ pFIO->FIOCLRL = bitValue;
+ }
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Read Current state on port pin that have input direction of GPIO
+ * in halfword accessible style.
+ * @param[in] portNum Port number, in range from 0 to 4
+ * @param[in] halfwordNum HalfWord part number, should be 0 (lower) or 1(upper)
+ * @return Current value of FIO port pin of specified halfword.
+ * Note: Return value contain state of each port pin (bit) on that FIO regardless
+ * its direction is input or output.
+ **********************************************************************/
+uint16_t FIO_HalfWordReadValue(uint8_t portNum, uint8_t halfwordNum)
+{
+ GPIO_HalfWord_TypeDef *pFIO = FIO_HalfWordGetPointer(portNum);
+ if(pFIO != NULL) {
+ // Upper
+ if(halfwordNum) {
+ return (pFIO->FIOPINU);
+ }
+ // lower
+ else {
+ return (pFIO->FIOPINL);
+ }
+ }
+ return (0);
+}
+
+
+/* FIO Byte accessible ------------------------------------------------------------ */
+
+/*********************************************************************//**
+ * @brief Set direction for FIO port in byte accessible style
+ * @param[in] portNum Port number, in range from 0 to 4
+ * @param[in] byteNum Byte part number, should be in range from 0 to 3
+ * @param[in] bitValue Value that contains all bits in to set direction,
+ * in range from 0 to 0xFF.
+ * @param[in] dir Direction value, should be:
+ * - 0: Input.
+ * - 1: Output.
+ * @return None
+ *
+ * Note: All remaining bits that are not activated in bitValue (value '0')
+ * will not be effected by this function.
+ **********************************************************************/
+void FIO_ByteSetDir(uint8_t portNum, uint8_t byteNum, uint8_t bitValue, uint8_t dir)
+{
+ GPIO_Byte_TypeDef *pFIO = FIO_ByteGetPointer(portNum);
+ if(pFIO != NULL) {
+ // Output direction
+ if (dir) {
+ if ((byteNum >= 0) && (byteNum <= 3)) {
+ pFIO->FIODIR[byteNum] |= bitValue;
+ }
+ }
+ // Input direction
+ else {
+ if ((byteNum >= 0) && (byteNum <= 3)) {
+ pFIO->FIODIR[byteNum] &= ~bitValue;
+ }
+ }
+ }
+}
+
+/*********************************************************************//**
+ * @brief Set mask value for bits in FIO port in byte accessible style
+ * @param[in] portNum Port number, in range from 0 to 4
+ * @param[in] byteNum Byte part number, should be in range from 0 to 3
+ * @param[in] bitValue Value that contains all bits in to set mask,
+ * in range from 0 to 0xFF.
+ * @param[in] maskValue Mask value contains state value for each bit:
+ * - 0: not mask.
+ * - 1: mask.
+ * @return None
+ *
+ * Note:
+ * - All remaining bits that are not activated in bitValue (value '0')
+ * will not be effected by this function.
+ * - After executing this function, in mask register, value '0' on each bit
+ * enables an access to the corresponding physical pin via a read or write access,
+ * while value '1' on bit (masked) that corresponding pin will not be changed
+ * with write access and if read, will not be reflected in the updated pin.
+ **********************************************************************/
+void FIO_ByteSetMask(uint8_t portNum, uint8_t byteNum, uint8_t bitValue, uint8_t maskValue)
+{
+ GPIO_Byte_TypeDef *pFIO = FIO_ByteGetPointer(portNum);
+ if(pFIO != NULL) {
+ // Mask
+ if (maskValue) {
+ if ((byteNum >= 0) && (byteNum <= 3)) {
+ pFIO->FIOMASK[byteNum] |= bitValue;
+ }
+ }
+ // Un-mask
+ else {
+ if ((byteNum >= 0) && (byteNum <= 3)) {
+ pFIO->FIOMASK[byteNum] &= ~bitValue;
+ }
+ }
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Set bits for FIO port in byte accessible style
+ * @param[in] portNum Port number, in range from 0 to 4
+ * @param[in] byteNum Byte part number, should be in range from 0 to 3
+ * @param[in] bitValue Value that contains all bits in to set,
+ * in range from 0 to 0xFF.
+ * @return None
+ *
+ * Note:
+ * - For all bits that has been set as input direction, this function will
+ * not effect.
+ * - For all remaining bits that are not activated in bitValue (value '0')
+ * will not be effected by this function.
+ **********************************************************************/
+void FIO_ByteSetValue(uint8_t portNum, uint8_t byteNum, uint8_t bitValue)
+{
+ GPIO_Byte_TypeDef *pFIO = FIO_ByteGetPointer(portNum);
+ if (pFIO != NULL) {
+ if ((byteNum >= 0) && (byteNum <= 3)){
+ pFIO->FIOSET[byteNum] = bitValue;
+ }
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Clear bits for FIO port in byte accessible style
+ * @param[in] portNum Port number, in range from 0 to 4
+ * @param[in] byteNum Byte part number, should be in range from 0 to 3
+ * @param[in] bitValue Value that contains all bits in to clear,
+ * in range from 0 to 0xFF.
+ * @return None
+ *
+ * Note:
+ * - For all bits that has been set as input direction, this function will
+ * not effect.
+ * - For all remaining bits that are not activated in bitValue (value '0')
+ * will not be effected by this function.
+ **********************************************************************/
+void FIO_ByteClearValue(uint8_t portNum, uint8_t byteNum, uint8_t bitValue)
+{
+ GPIO_Byte_TypeDef *pFIO = FIO_ByteGetPointer(portNum);
+ if (pFIO != NULL) {
+ if ((byteNum >= 0) && (byteNum <= 3)){
+ pFIO->FIOCLR[byteNum] = bitValue;
+ }
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Read Current state on port pin that have input direction of GPIO
+ * in byte accessible style.
+ * @param[in] portNum Port number, in range from 0 to 4
+ * @param[in] byteNum Byte part number, should be in range from 0 to 3
+ * @return Current value of FIO port pin of specified byte part.
+ * Note: Return value contain state of each port pin (bit) on that FIO regardless
+ * its direction is input or output.
+ **********************************************************************/
+uint8_t FIO_ByteReadValue(uint8_t portNum, uint8_t byteNum)
+{
+ GPIO_Byte_TypeDef *pFIO = FIO_ByteGetPointer(portNum);
+ if (pFIO != NULL) {
+ if ((byteNum >= 0) && (byteNum <= 3)){
+ return (pFIO->FIOPIN[byteNum]);
+ }
+ }
+ return (0);
+}
+
+/**
+ * @}
+ */
+
+#endif /* _GPIO */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_i2c.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_i2c.c
new file mode 100644
index 0000000..9b54228
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_i2c.c
@@ -0,0 +1,1373 @@
+/***********************************************************************//**
+ * @file lpc17xx_i2c.c
+ * @brief Contains all functions support for I2C firmware library on LPC17xx
+ * @version 2.0
+ * @date 21. May. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup I2C
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_i2c.h"
+#include "lpc17xx_clkpwr.h"
+#include "lpc17xx_pinsel.h"
+
+
+/* If this source file built with example, the LPC17xx FW library configuration
+ * file in each example directory ("lpc17xx_libcfg.h") must be included,
+ * otherwise the default FW library configuration file must be included instead
+ */
+#ifdef __BUILD_WITH_EXAMPLE__
+#include "lpc17xx_libcfg.h"
+#else
+#include "lpc17xx_libcfg_default.h"
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+
+#ifdef _I2C
+
+
+/* Private Types -------------------------------------------------------------- */
+/** @defgroup I2C_Private_Types I2C Private Types
+ * @{
+ */
+
+/**
+ * @brief I2C device configuration structure type
+ */
+typedef struct
+{
+ uint32_t txrx_setup; /* Transmission setup */
+ int32_t dir; /* Current direction phase, 0 - write, 1 - read */
+} I2C_CFG_T;
+
+/**
+ * @}
+ */
+
+/* Private Variables ---------------------------------------------------------- */
+/**
+ * @brief II2C driver data for I2C0, I2C1 and I2C2
+ */
+static I2C_CFG_T i2cdat[3];
+
+static uint32_t I2C_MasterComplete[3];
+static uint32_t I2C_SlaveComplete[3];
+
+static uint32_t I2C_MonitorBufferIndex;
+
+/* Private Functions ---------------------------------------------------------- */
+
+/* Get I2C number */
+static int32_t I2C_getNum(LPC_I2C_TypeDef *I2Cx);
+
+/* Generate a start condition on I2C bus (in master mode only) */
+static uint32_t I2C_Start (LPC_I2C_TypeDef *I2Cx);
+
+/* Generate a stop condition on I2C bus (in master mode only) */
+static void I2C_Stop (LPC_I2C_TypeDef *I2Cx);
+
+/* I2C send byte subroutine */
+static uint32_t I2C_SendByte (LPC_I2C_TypeDef *I2Cx, uint8_t databyte);
+
+/* I2C get byte subroutine */
+static uint32_t I2C_GetByte (LPC_I2C_TypeDef *I2Cx, uint8_t *retdat, Bool ack);
+
+/* I2C set clock (hz) */
+static void I2C_SetClock (LPC_I2C_TypeDef *I2Cx, uint32_t target_clock);
+
+/*--------------------------------------------------------------------------------*/
+/********************************************************************//**
+ * @brief Convert from I2C peripheral to number
+ * @param[in] I2Cx: I2C peripheral selected, should be:
+ * - LPC_I2C0
+ * - LPC_I2C1
+ * - LPC_I2C2
+ * @return I2C number, could be: 0..2
+ *********************************************************************/
+static int32_t I2C_getNum(LPC_I2C_TypeDef *I2Cx){
+ if (I2Cx == LPC_I2C0) {
+ return (0);
+ } else if (I2Cx == LPC_I2C1) {
+ return (1);
+ } else if (I2Cx == LPC_I2C2) {
+ return (2);
+ }
+ return (-1);
+}
+
+/********************************************************************//**
+ * @brief Generate a start condition on I2C bus (in master mode only)
+ * @param[in] I2Cx: I2C peripheral selected, should be:
+ * - LPC_I2C0
+ * - LPC_I2C1
+ * - LPC_I2C2
+ * @return value of I2C status register after generate a start condition
+ *********************************************************************/
+static uint32_t I2C_Start (LPC_I2C_TypeDef *I2Cx)
+{
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ I2Cx->I2CONSET = I2C_I2CONSET_STA;
+
+ // Wait for complete
+ while (!(I2Cx->I2CONSET & I2C_I2CONSET_SI));
+ I2Cx->I2CONCLR = I2C_I2CONCLR_STAC;
+ return (I2Cx->I2STAT & I2C_STAT_CODE_BITMASK);
+}
+
+/********************************************************************//**
+ * @brief Generate a stop condition on I2C bus (in master mode only)
+ * @param[in] I2Cx: I2C peripheral selected, should be:
+ * - LPC_I2C0
+ * - LPC_I2C1
+ * - LPC_I2C2
+ * @return None
+ *********************************************************************/
+static void I2C_Stop (LPC_I2C_TypeDef *I2Cx)
+{
+
+ /* Make sure start bit is not active */
+ if (I2Cx->I2CONSET & I2C_I2CONSET_STA)
+ {
+ I2Cx->I2CONCLR = I2C_I2CONCLR_STAC;
+ }
+ I2Cx->I2CONSET = I2C_I2CONSET_STO;
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+}
+
+/********************************************************************//**
+ * @brief Send a byte
+ * @param[in] I2Cx: I2C peripheral selected, should be:
+ * - LPC_I2C0
+ * - LPC_I2C1
+ * - LPC_I2C2
+ * @param[in] databyte: number of byte
+ * @return value of I2C status register after sending
+ *********************************************************************/
+static uint32_t I2C_SendByte (LPC_I2C_TypeDef *I2Cx, uint8_t databyte)
+{
+ /* Make sure start bit is not active */
+ if (I2Cx->I2CONSET & I2C_I2CONSET_STA)
+ {
+ I2Cx->I2CONCLR = I2C_I2CONCLR_STAC;
+ }
+ I2Cx->I2DAT = databyte & I2C_I2DAT_BITMASK;
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+
+ while (!(I2Cx->I2CONSET & I2C_I2CONSET_SI));
+ return (I2Cx->I2STAT & I2C_STAT_CODE_BITMASK);
+}
+
+/********************************************************************//**
+ * @brief Get a byte
+ * @param[in] I2Cx: I2C peripheral selected, should be:
+ * - LPC_I2C0
+ * - LPC_I2C1
+ * - LPC_I2C2
+ * @param[out] retdat pointer to return data
+ * @param[in] ack assert acknowledge or not, should be: TRUE/FALSE
+ * @return value of I2C status register after sending
+ *********************************************************************/
+static uint32_t I2C_GetByte (LPC_I2C_TypeDef *I2Cx, uint8_t *retdat, Bool ack)
+{
+ if (ack == TRUE)
+ {
+ I2Cx->I2CONSET = I2C_I2CONSET_AA;
+ }
+ else
+ {
+ I2Cx->I2CONCLR = I2C_I2CONCLR_AAC;
+ }
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+
+ while (!(I2Cx->I2CONSET & I2C_I2CONSET_SI));
+ *retdat = (uint8_t) (I2Cx->I2DAT & I2C_I2DAT_BITMASK);
+ return (I2Cx->I2STAT & I2C_STAT_CODE_BITMASK);
+}
+
+/*********************************************************************//**
+ * @brief Setup clock rate for I2C peripheral
+ * @param[in] I2Cx I2C peripheral selected, should be:
+ * - LPC_I2C0
+ * - LPC_I2C1
+ * - LPC_I2C2
+ * @param[in] target_clock : clock of SSP (Hz)
+ * @return None
+ ***********************************************************************/
+static void I2C_SetClock (LPC_I2C_TypeDef *I2Cx, uint32_t target_clock)
+{
+ uint32_t temp;
+
+ CHECK_PARAM(PARAM_I2Cx(I2Cx));
+
+ // Get PCLK of I2C controller
+ if (I2Cx == LPC_I2C0)
+ {
+ temp = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_I2C0) / target_clock;
+ }
+ else if (I2Cx == LPC_I2C1)
+ {
+ temp = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_I2C1) / target_clock;
+ }
+ else if (I2Cx == LPC_I2C2)
+ {
+ temp = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_I2C1) / target_clock;
+ }
+
+ /* Set the I2C clock value to register */
+ I2Cx->I2SCLH = (uint32_t)(temp / 2);
+ I2Cx->I2SCLL = (uint32_t)(temp - I2Cx->I2SCLH);
+}
+/* End of Private Functions --------------------------------------------------- */
+
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup I2C_Public_Functions
+ * @{
+ */
+
+/********************************************************************//**
+ * @brief Initializes the I2Cx peripheral with specified parameter.
+ * @param[in] I2Cx I2C peripheral selected, should be
+ * - LPC_I2C0
+ * - LPC_I2C1
+ * - LPC_I2C2
+ * @param[in] clockrate Target clock rate value to initialized I2C
+ * peripheral (Hz)
+ * @return None
+ *********************************************************************/
+void I2C_Init(LPC_I2C_TypeDef *I2Cx, uint32_t clockrate)
+{
+ CHECK_PARAM(PARAM_I2Cx(I2Cx));
+
+ if (I2Cx==LPC_I2C0)
+ {
+ /* Set up clock and power for I2C0 module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCI2C0, ENABLE);
+ /* As default, peripheral clock for I2C0 module
+ * is set to FCCLK / 2 */
+ CLKPWR_SetPCLKDiv(CLKPWR_PCLKSEL_I2C0, CLKPWR_PCLKSEL_CCLK_DIV_2);
+ }
+ else if (I2Cx==LPC_I2C1)
+ {
+ /* Set up clock and power for I2C1 module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCI2C1, ENABLE);
+ /* As default, peripheral clock for I2C1 module
+ * is set to FCCLK / 2 */
+ CLKPWR_SetPCLKDiv(CLKPWR_PCLKSEL_I2C1, CLKPWR_PCLKSEL_CCLK_DIV_2);
+ }
+ else if (I2Cx==LPC_I2C2)
+ {
+ /* Set up clock and power for I2C2 module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCI2C2, ENABLE);
+ /* As default, peripheral clock for I2C2 module
+ * is set to FCCLK / 2 */
+ CLKPWR_SetPCLKDiv(CLKPWR_PCLKSEL_I2C2, CLKPWR_PCLKSEL_CCLK_DIV_2);
+ }
+ else {
+ // Up-Support this device
+ return;
+ }
+
+ /* Set clock rate */
+ I2C_SetClock(I2Cx, clockrate);
+ /* Set I2C operation to default */
+ I2Cx->I2CONCLR = (I2C_I2CONCLR_AAC | I2C_I2CONCLR_STAC | I2C_I2CONCLR_I2ENC);
+}
+
+/*********************************************************************//**
+ * @brief De-initializes the I2C peripheral registers to their
+ * default reset values.
+ * @param[in] I2Cx I2C peripheral selected, should be
+ * - LPC_I2C0
+ * - LPC_I2C1
+ * - LPC_I2C2
+ * @return None
+ **********************************************************************/
+void I2C_DeInit(LPC_I2C_TypeDef* I2Cx)
+{
+ CHECK_PARAM(PARAM_I2Cx(I2Cx));
+
+ /* Disable I2C control */
+ I2Cx->I2CONCLR = I2C_I2CONCLR_I2ENC;
+
+ if (I2Cx==LPC_I2C0)
+ {
+ /* Disable power for I2C0 module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCI2C0, DISABLE);
+ }
+ else if (I2Cx==LPC_I2C1)
+ {
+ /* Disable power for I2C1 module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCI2C1, DISABLE);
+ }
+ else if (I2Cx==LPC_I2C2)
+ {
+ /* Disable power for I2C2 module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCI2C2, DISABLE);
+ }
+}
+
+/*********************************************************************//**
+ * @brief Enable or disable I2C peripheral's operation
+ * @param[in] I2Cx I2C peripheral selected, should be
+ * - LPC_I2C0
+ * - LPC_I2C1
+ * - LPC_I2C2
+ * @param[in] NewState New State of I2Cx peripheral's operation
+ * @return none
+ **********************************************************************/
+void I2C_Cmd(LPC_I2C_TypeDef* I2Cx, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+ CHECK_PARAM(PARAM_I2Cx(I2Cx));
+
+ if (NewState == ENABLE)
+ {
+ I2Cx->I2CONSET = I2C_I2CONSET_I2EN;
+ }
+ else
+ {
+ I2Cx->I2CONCLR = I2C_I2CONCLR_I2ENC;
+ }
+}
+
+/*********************************************************************//**
+ * @brief Enable/Disable interrupt for I2C peripheral
+ * @param[in] I2Cx I2C peripheral selected, should be:
+ * - LPC_I2C0
+ * - LPC_I2C1
+ * - LPC_I2C2
+ * @param[in] NewState New State of I2C peripheral interrupt in NVIC core
+ * should be:
+ * - ENABLE: enable interrupt for this I2C peripheral
+ * - DISABLE: disable interrupt for this I2C peripheral
+ * @return None
+ **********************************************************************/
+void I2C_IntCmd (LPC_I2C_TypeDef *I2Cx, Bool NewState)
+{
+ if (NewState)
+ {
+ if(I2Cx == LPC_I2C0)
+ {
+ NVIC_EnableIRQ(I2C0_IRQn);
+ }
+ else if (I2Cx == LPC_I2C1)
+ {
+ NVIC_EnableIRQ(I2C1_IRQn);
+ }
+ else if (I2Cx == LPC_I2C2)
+ {
+ NVIC_EnableIRQ(I2C2_IRQn);
+ }
+ }
+ else
+ {
+ if(I2Cx == LPC_I2C0)
+ {
+ NVIC_DisableIRQ(I2C0_IRQn);
+ }
+ else if (I2Cx == LPC_I2C1)
+ {
+ NVIC_DisableIRQ(I2C1_IRQn);
+ }
+ else if (I2Cx == LPC_I2C2)
+ {
+ NVIC_DisableIRQ(I2C2_IRQn);
+ }
+ }
+ return;
+}
+
+
+/*********************************************************************//**
+ * @brief General Master Interrupt handler for I2C peripheral
+ * @param[in] I2Cx I2C peripheral selected, should be:
+ * - LPC_I2C
+ * - LPC_I2C1
+ * - LPC_I2C2
+ * @return None
+ **********************************************************************/
+void I2C_MasterHandler (LPC_I2C_TypeDef *I2Cx)
+{
+ int32_t tmp;
+ uint8_t returnCode;
+ I2C_M_SETUP_Type *txrx_setup;
+
+ tmp = I2C_getNum(I2Cx);
+ txrx_setup = (I2C_M_SETUP_Type *) i2cdat[tmp].txrx_setup;
+
+ returnCode = (I2Cx->I2STAT & I2C_STAT_CODE_BITMASK);
+ // Save current status
+ txrx_setup->status = returnCode;
+ // there's no relevant information
+ if (returnCode == I2C_I2STAT_NO_INF){
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ return;
+ }
+
+ /* ----------------------------- TRANSMIT PHASE --------------------------*/
+ if (i2cdat[tmp].dir == 0){
+ switch (returnCode)
+ {
+ /* A start/repeat start condition has been transmitted -------------------*/
+ case I2C_I2STAT_M_TX_START:
+ case I2C_I2STAT_M_TX_RESTART:
+ I2Cx->I2CONCLR = I2C_I2CONCLR_STAC;
+ /*
+ * If there's any transmit data, then start to
+ * send SLA+W right now, otherwise check whether if there's
+ * any receive data for next state.
+ */
+ if ((txrx_setup->tx_data != NULL) && (txrx_setup->tx_length != 0)){
+ I2Cx->I2DAT = (txrx_setup->sl_addr7bit << 1);
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ } else {
+ goto next_stage;
+ }
+ break;
+
+ /* SLA+W has been transmitted, ACK has been received ----------------------*/
+ case I2C_I2STAT_M_TX_SLAW_ACK:
+ /* Data has been transmitted, ACK has been received */
+ case I2C_I2STAT_M_TX_DAT_ACK:
+ /* Send more data */
+ if ((txrx_setup->tx_count < txrx_setup->tx_length) \
+ && (txrx_setup->tx_data != NULL)){
+ I2Cx->I2DAT = *(uint8_t *)(txrx_setup->tx_data + txrx_setup->tx_count);
+ txrx_setup->tx_count++;
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ }
+ // no more data, switch to next stage
+ else {
+next_stage:
+ // change direction
+ i2cdat[tmp].dir = 1;
+ // Check if any data to receive
+ if ((txrx_setup->rx_length != 0) && (txrx_setup->rx_data != NULL)){
+ // check whether if we need to issue an repeat start
+ if ((txrx_setup->tx_length != 0) && (txrx_setup->tx_data != NULL)){
+ // Send out an repeat start command
+ I2Cx->I2CONSET = I2C_I2CONSET_STA;
+ I2Cx->I2CONCLR = I2C_I2CONCLR_AAC | I2C_I2CONCLR_SIC;
+ }
+ // Don't need issue an repeat start, just goto send SLA+R
+ else {
+ goto send_slar;
+ }
+ }
+ // no more data send, the go to end stage now
+ else {
+ // success, goto end stage
+ txrx_setup->status |= I2C_SETUP_STATUS_DONE;
+ goto end_stage;
+ }
+ }
+ break;
+
+ /* SLA+W has been transmitted, NACK has been received ----------------------*/
+ case I2C_I2STAT_M_TX_SLAW_NACK:
+ /* Data has been transmitted, NACK has been received -----------------------*/
+ case I2C_I2STAT_M_TX_DAT_NACK:
+ // update status
+ txrx_setup->status |= I2C_SETUP_STATUS_NOACKF;
+ goto retry;
+ /* Arbitration lost in SLA+R/W or Data bytes -------------------------------*/
+ case I2C_I2STAT_M_TX_ARB_LOST:
+ // update status
+ txrx_setup->status |= I2C_SETUP_STATUS_ARBF;
+ default:
+ goto retry;
+ }
+ }
+
+ /* ----------------------------- RECEIVE PHASE --------------------------*/
+ else if (i2cdat[tmp].dir == 1){
+ switch (returnCode){
+ /* A start/repeat start condition has been transmitted ---------------------*/
+ case I2C_I2STAT_M_RX_START:
+ case I2C_I2STAT_M_RX_RESTART:
+ I2Cx->I2CONCLR = I2C_I2CONCLR_STAC;
+ /*
+ * If there's any receive data, then start to
+ * send SLA+R right now, otherwise check whether if there's
+ * any receive data for end of state.
+ */
+ if ((txrx_setup->rx_data != NULL) && (txrx_setup->rx_length != 0)){
+send_slar:
+ I2Cx->I2DAT = (txrx_setup->sl_addr7bit << 1) | 0x01;
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ } else {
+ // Success, goto end stage
+ txrx_setup->status |= I2C_SETUP_STATUS_DONE;
+ goto end_stage;
+ }
+ break;
+
+ /* SLA+R has been transmitted, ACK has been received -----------------*/
+ case I2C_I2STAT_M_RX_SLAR_ACK:
+ if (txrx_setup->rx_count < (txrx_setup->rx_length - 1)) {
+ /*Data will be received, ACK will be return*/
+ I2Cx->I2CONSET = I2C_I2CONSET_AA;
+ }
+ else {
+ /*Last data will be received, NACK will be return*/
+ I2Cx->I2CONCLR = I2C_I2CONSET_AA;
+ }
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ break;
+
+ /* Data has been received, ACK has been returned ----------------------*/
+ case I2C_I2STAT_M_RX_DAT_ACK:
+ // Note save data and increase counter first, then check later
+ /* Save data */
+ if ((txrx_setup->rx_data != NULL) && (txrx_setup->rx_count < txrx_setup->rx_length)){
+ *(uint8_t *)(txrx_setup->rx_data + txrx_setup->rx_count) = (I2Cx->I2DAT & I2C_I2DAT_BITMASK);
+ txrx_setup->rx_count++;
+ }
+ if (txrx_setup->rx_count < (txrx_setup->rx_length - 1)) {
+ /*Data will be received, ACK will be return*/
+ I2Cx->I2CONSET = I2C_I2CONSET_AA;
+ }
+ else {
+ /*Last data will be received, NACK will be return*/
+ I2Cx->I2CONCLR = I2C_I2CONSET_AA;
+ }
+
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ break;
+
+ /* Data has been received, NACK has been return -------------------------*/
+ case I2C_I2STAT_M_RX_DAT_NACK:
+ /* Save the last data */
+ if ((txrx_setup->rx_data != NULL) && (txrx_setup->rx_count < txrx_setup->rx_length)){
+ *(uint8_t *)(txrx_setup->rx_data + txrx_setup->rx_count) = (I2Cx->I2DAT & I2C_I2DAT_BITMASK);
+ txrx_setup->rx_count++;
+ }
+ // success, go to end stage
+ txrx_setup->status |= I2C_SETUP_STATUS_DONE;
+ goto end_stage;
+
+ /* SLA+R has been transmitted, NACK has been received ------------------*/
+ case I2C_I2STAT_M_RX_SLAR_NACK:
+ // update status
+ txrx_setup->status |= I2C_SETUP_STATUS_NOACKF;
+ goto retry;
+
+ /* Arbitration lost ----------------------------------------------------*/
+ case I2C_I2STAT_M_RX_ARB_LOST:
+ // update status
+ txrx_setup->status |= I2C_SETUP_STATUS_ARBF;
+ default:
+retry:
+ // check if retransmission is available
+ if (txrx_setup->retransmissions_count < txrx_setup->retransmissions_max){
+ // Clear tx count
+ txrx_setup->tx_count = 0;
+ I2Cx->I2CONSET = I2C_I2CONSET_STA;
+ I2Cx->I2CONCLR = I2C_I2CONCLR_AAC | I2C_I2CONCLR_SIC;
+ txrx_setup->retransmissions_count++;
+ }
+ // End of stage
+ else {
+end_stage:
+ // Disable interrupt
+ I2C_IntCmd(I2Cx, 0);
+ // Send stop
+ I2C_Stop(I2Cx);
+
+ I2C_MasterComplete[tmp] = TRUE;
+ }
+ break;
+ }
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief General Slave Interrupt handler for I2C peripheral
+ * @param[in] I2Cx I2C peripheral selected, should be:
+ * - LPC_I2C0
+ * - LPC_I2C1
+ * - LPC_I2C2
+ * @return None
+ **********************************************************************/
+void I2C_SlaveHandler (LPC_I2C_TypeDef *I2Cx)
+{
+ int32_t tmp;
+ uint8_t returnCode;
+ I2C_S_SETUP_Type *txrx_setup;
+ uint32_t timeout;
+
+ tmp = I2C_getNum(I2Cx);
+ txrx_setup = (I2C_S_SETUP_Type *) i2cdat[tmp].txrx_setup;
+
+ returnCode = (I2Cx->I2STAT & I2C_STAT_CODE_BITMASK);
+ // Save current status
+ txrx_setup->status = returnCode;
+ // there's no relevant information
+ if (returnCode == I2C_I2STAT_NO_INF){
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ return;
+ }
+
+
+ switch (returnCode)
+ {
+
+ /* No status information */
+ case I2C_I2STAT_NO_INF:
+ I2Cx->I2CONSET = I2C_I2CONSET_AA;
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ break;
+
+ /* Reading phase -------------------------------------------------------- */
+ /* Own SLA+R has been received, ACK has been returned */
+ case I2C_I2STAT_S_RX_SLAW_ACK:
+ /* General call address has been received, ACK has been returned */
+ case I2C_I2STAT_S_RX_GENCALL_ACK:
+ I2Cx->I2CONSET = I2C_I2CONSET_AA;
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ break;
+
+ /* Previously addressed with own SLA;
+ * DATA byte has been received;
+ * ACK has been returned */
+ case I2C_I2STAT_S_RX_PRE_SLA_DAT_ACK:
+ /* DATA has been received, ACK hasn been return */
+ case I2C_I2STAT_S_RX_PRE_GENCALL_DAT_ACK:
+ /*
+ * All data bytes that over-flow the specified receive
+ * data length, just ignore them.
+ */
+ if ((txrx_setup->rx_count < txrx_setup->rx_length) \
+ && (txrx_setup->rx_data != NULL)){
+ *(uint8_t *)(txrx_setup->rx_data + txrx_setup->rx_count) = (uint8_t)I2Cx->I2DAT;
+ txrx_setup->rx_count++;
+ }
+ I2Cx->I2CONSET = I2C_I2CONSET_AA;
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ break;
+
+ /* Previously addressed with own SLA;
+ * DATA byte has been received;
+ * NOT ACK has been returned */
+ case I2C_I2STAT_S_RX_PRE_SLA_DAT_NACK:
+ /* DATA has been received, NOT ACK has been returned */
+ case I2C_I2STAT_S_RX_PRE_GENCALL_DAT_NACK:
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ break;
+
+ /*
+ * Note that: Return code only let us know a stop condition mixed
+ * with a repeat start condition in the same code value.
+ * So we should provide a time-out. In case this is really a stop
+ * condition, this will return back after time out condition. Otherwise,
+ * next session that is slave receive data will be completed.
+ */
+
+ /* A Stop or a repeat start condition */
+ case I2C_I2STAT_S_RX_STA_STO_SLVREC_SLVTRX:
+ // Temporally lock the interrupt for timeout condition
+ I2C_IntCmd(I2Cx, 0);
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ // enable time out
+ timeout = I2C_SLAVE_TIME_OUT;
+ while(1){
+ if (I2Cx->I2CONSET & I2C_I2CONSET_SI){
+ // re-Enable interrupt
+ I2C_IntCmd(I2Cx, 1);
+ break;
+ } else {
+ timeout--;
+ if (timeout == 0){
+ // timeout occur, it's really a stop condition
+ txrx_setup->status |= I2C_SETUP_STATUS_DONE;
+ goto s_int_end;
+ }
+ }
+ }
+ break;
+
+ /* Writing phase -------------------------------------------------------- */
+ /* Own SLA+R has been received, ACK has been returned */
+ case I2C_I2STAT_S_TX_SLAR_ACK:
+ /* Data has been transmitted, ACK has been received */
+ case I2C_I2STAT_S_TX_DAT_ACK:
+ /*
+ * All data bytes that over-flow the specified receive
+ * data length, just ignore them.
+ */
+ if ((txrx_setup->tx_count < txrx_setup->tx_length) \
+ && (txrx_setup->tx_data != NULL)){
+ I2Cx->I2DAT = *(uint8_t *) (txrx_setup->tx_data + txrx_setup->tx_count);
+ txrx_setup->tx_count++;
+ }
+ I2Cx->I2CONSET = I2C_I2CONSET_AA;
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ break;
+
+ /* Data has been transmitted, NACK has been received,
+ * that means there's no more data to send, exit now */
+ /*
+ * Note: Don't wait for stop event since in slave transmit mode,
+ * since there no proof lets us know when a stop signal has been received
+ * on slave side.
+ */
+ case I2C_I2STAT_S_TX_DAT_NACK:
+ I2Cx->I2CONSET = I2C_I2CONSET_AA;
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ txrx_setup->status |= I2C_SETUP_STATUS_DONE;
+ goto s_int_end;
+
+ // Other status must be captured
+ default:
+s_int_end:
+ // Disable interrupt
+ I2C_IntCmd(I2Cx, 0);
+ I2Cx->I2CONCLR = I2C_I2CONCLR_AAC | I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC;
+ I2C_SlaveComplete[tmp] = TRUE;
+ break;
+ }
+}
+
+/*********************************************************************//**
+ * @brief Transmit and Receive data in master mode
+ * @param[in] I2Cx I2C peripheral selected, should be:
+ * - LPC_I2C0
+ * - LPC_I2C1
+ * - LPC_I2C2
+ * @param[in] TransferCfg Pointer to a I2C_M_SETUP_Type structure that
+ * contains specified information about the
+ * configuration for master transfer.
+ * @param[in] Opt a I2C_TRANSFER_OPT_Type type that selected for
+ * interrupt or polling mode.
+ * @return SUCCESS or ERROR
+ *
+ * Note:
+ * - In case of using I2C to transmit data only, either transmit length set to 0
+ * or transmit data pointer set to NULL.
+ * - In case of using I2C to receive data only, either receive length set to 0
+ * or receive data pointer set to NULL.
+ * - In case of using I2C to transmit followed by receive data, transmit length,
+ * transmit data pointer, receive length and receive data pointer should be set
+ * corresponding.
+ **********************************************************************/
+Status I2C_MasterTransferData(LPC_I2C_TypeDef *I2Cx, I2C_M_SETUP_Type *TransferCfg, \
+ I2C_TRANSFER_OPT_Type Opt)
+{
+ uint8_t *txdat;
+ uint8_t *rxdat;
+ uint32_t CodeStatus;
+ uint8_t tmp;
+
+ // reset all default state
+ txdat = (uint8_t *) TransferCfg->tx_data;
+ rxdat = (uint8_t *) TransferCfg->rx_data;
+ // Reset I2C setup value to default state
+ TransferCfg->tx_count = 0;
+ TransferCfg->rx_count = 0;
+ TransferCfg->status = 0;
+
+ if (Opt == I2C_TRANSFER_POLLING){
+
+ /* First Start condition -------------------------------------------------------------- */
+ TransferCfg->retransmissions_count = 0;
+retry:
+ // reset all default state
+ txdat = (uint8_t *) TransferCfg->tx_data;
+ rxdat = (uint8_t *) TransferCfg->rx_data;
+ // Reset I2C setup value to default state
+ TransferCfg->tx_count = 0;
+ TransferCfg->rx_count = 0;
+ CodeStatus = 0;
+
+ // Start command
+ CodeStatus = I2C_Start(I2Cx);
+ if ((CodeStatus != I2C_I2STAT_M_TX_START) \
+ && (CodeStatus != I2C_I2STAT_M_TX_RESTART)){
+ TransferCfg->retransmissions_count++;
+ if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){
+ // save status
+ TransferCfg->status = CodeStatus;
+ goto error;
+ } else {
+ goto retry;
+ }
+ }
+
+ /* In case of sending data first --------------------------------------------------- */
+ if ((TransferCfg->tx_length != 0) && (TransferCfg->tx_data != NULL)){
+
+ /* Send slave address + WR direction bit = 0 ----------------------------------- */
+ CodeStatus = I2C_SendByte(I2Cx, (TransferCfg->sl_addr7bit << 1));
+ if (CodeStatus != I2C_I2STAT_M_TX_SLAW_ACK){
+ TransferCfg->retransmissions_count++;
+ if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){
+ // save status
+ TransferCfg->status = CodeStatus | I2C_SETUP_STATUS_NOACKF;
+ goto error;
+ } else {
+ goto retry;
+ }
+ }
+
+ /* Send a number of data bytes ---------------------------------------- */
+ while (TransferCfg->tx_count < TransferCfg->tx_length)
+ {
+ CodeStatus = I2C_SendByte(I2Cx, *txdat);
+ if (CodeStatus != I2C_I2STAT_M_TX_DAT_ACK){
+ TransferCfg->retransmissions_count++;
+ if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){
+ // save status
+ TransferCfg->status = CodeStatus | I2C_SETUP_STATUS_NOACKF;
+ goto error;
+ } else {
+ goto retry;
+ }
+ }
+
+ txdat++;
+ TransferCfg->tx_count++;
+ }
+ }
+
+ /* Second Start condition (Repeat Start) ------------------------------------------- */
+ if ((TransferCfg->tx_length != 0) && (TransferCfg->tx_data != NULL) \
+ && (TransferCfg->rx_length != 0) && (TransferCfg->rx_data != NULL)){
+
+ CodeStatus = I2C_Start(I2Cx);
+ if ((CodeStatus != I2C_I2STAT_M_RX_START) \
+ && (CodeStatus != I2C_I2STAT_M_RX_RESTART)){
+ TransferCfg->retransmissions_count++;
+ if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){
+ // Update status
+ TransferCfg->status = CodeStatus;
+ goto error;
+ } else {
+ goto retry;
+ }
+ }
+ }
+
+ /* Then, start reading after sending data -------------------------------------- */
+ if ((TransferCfg->rx_length != 0) && (TransferCfg->rx_data != NULL)){
+ /* Send slave address + RD direction bit = 1 ----------------------------------- */
+
+ CodeStatus = I2C_SendByte(I2Cx, ((TransferCfg->sl_addr7bit << 1) | 0x01));
+ if (CodeStatus != I2C_I2STAT_M_RX_SLAR_ACK){
+ TransferCfg->retransmissions_count++;
+ if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){
+ // update status
+ TransferCfg->status = CodeStatus | I2C_SETUP_STATUS_NOACKF;
+ goto error;
+ } else {
+ goto retry;
+ }
+ }
+
+ /* Receive a number of data bytes ------------------------------------------------- */
+ while (TransferCfg->rx_count < TransferCfg->rx_length){
+
+ /*
+ * Note that: if data length is only one, the master should not
+ * issue an ACK signal on bus after reading to avoid of next data frame
+ * on slave side
+ */
+ if (TransferCfg->rx_count < (TransferCfg->rx_length - 1)){
+ // Issue an ACK signal for next data frame
+ CodeStatus = I2C_GetByte(I2Cx, &tmp, 1);
+ if (CodeStatus != I2C_I2STAT_M_RX_DAT_ACK){
+ TransferCfg->retransmissions_count++;
+ if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){
+ // update status
+ TransferCfg->status = CodeStatus;
+ goto error;
+ } else {
+ goto retry;
+ }
+ }
+ } else {
+ // Do not issue an ACK signal
+ CodeStatus = I2C_GetByte(I2Cx, &tmp, 0);
+ if (CodeStatus != I2C_I2STAT_M_RX_DAT_NACK){
+ TransferCfg->retransmissions_count++;
+ if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){
+ // update status
+ TransferCfg->status = CodeStatus;
+ goto error;
+ } else {
+ goto retry;
+ }
+ }
+ }
+ *rxdat++ = tmp;
+ TransferCfg->rx_count++;
+ }
+ }
+
+ /* Send STOP condition ------------------------------------------------- */
+ I2C_Stop(I2Cx);
+ return SUCCESS;
+
+error:
+ // Send stop condition
+ I2C_Stop(I2Cx);
+ return ERROR;
+ }
+
+ else if (Opt == I2C_TRANSFER_INTERRUPT){
+ // Setup tx_rx data, callback and interrupt handler
+ tmp = I2C_getNum(I2Cx);
+ i2cdat[tmp].txrx_setup = (uint32_t) TransferCfg;
+ // Set direction phase, write first
+ i2cdat[tmp].dir = 0;
+
+ /* First Start condition -------------------------------------------------------------- */
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ I2Cx->I2CONSET = I2C_I2CONSET_STA;
+ I2C_IntCmd(I2Cx, 1);
+
+ return (SUCCESS);
+ }
+
+ return ERROR;
+}
+
+/*********************************************************************//**
+ * @brief Receive and Transmit data in slave mode
+ * @param[in] I2Cx I2C peripheral selected, should be
+ * - LPC_I2C0
+ * - LPC_I2C1
+ * - LPC_I2C2
+ * @param[in] TransferCfg Pointer to a I2C_S_SETUP_Type structure that
+ * contains specified information about the
+ * configuration for master transfer.
+ * @param[in] Opt I2C_TRANSFER_OPT_Type type that selected for
+ * interrupt or polling mode.
+ * @return SUCCESS or ERROR
+ *
+ * Note:
+ * The mode of slave's operation depends on the command sent from master on
+ * the I2C bus. If the master send a SLA+W command, this sub-routine will
+ * use receive data length and receive data pointer. If the master send a SLA+R
+ * command, this sub-routine will use transmit data length and transmit data
+ * pointer.
+ * If the master issue an repeat start command or a stop command, the slave will
+ * enable an time out condition, during time out condition, if there's no activity
+ * on I2C bus, the slave will exit, otherwise (i.e. the master send a SLA+R/W),
+ * the slave then switch to relevant operation mode. The time out should be used
+ * because the return status code can not show difference from stop and repeat
+ * start command in slave operation.
+ * In case of the expected data length from master is greater than data length
+ * that slave can support:
+ * - In case of reading operation (from master): slave will return I2C_I2DAT_IDLE_CHAR
+ * value.
+ * - In case of writing operation (from master): slave will ignore remain data from master.
+ **********************************************************************/
+Status I2C_SlaveTransferData(LPC_I2C_TypeDef *I2Cx, I2C_S_SETUP_Type *TransferCfg, \
+ I2C_TRANSFER_OPT_Type Opt)
+{
+ uint8_t *txdat;
+ uint8_t *rxdat;
+ uint32_t CodeStatus;
+ uint32_t timeout;
+ int32_t time_en;
+ int32_t tmp;
+
+ // reset all default state
+ txdat = (uint8_t *) TransferCfg->tx_data;
+ rxdat = (uint8_t *) TransferCfg->rx_data;
+ // Reset I2C setup value to default state
+ TransferCfg->tx_count = 0;
+ TransferCfg->rx_count = 0;
+ TransferCfg->status = 0;
+
+
+ // Polling option
+ if (Opt == I2C_TRANSFER_POLLING){
+
+ /* Set AA bit to ACK command on I2C bus */
+ I2Cx->I2CONSET = I2C_I2CONSET_AA;
+ /* Clear SI bit to be ready ... */
+ I2Cx->I2CONCLR = (I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC);
+
+ time_en = 0;
+ timeout = 0;
+
+ while (1)
+ {
+ /* Check SI flag ready */
+ if (I2Cx->I2CONSET & I2C_I2CONSET_SI)
+ {
+ time_en = 0;
+
+ switch (CodeStatus = (I2Cx->I2STAT & I2C_STAT_CODE_BITMASK))
+ {
+
+ /* No status information */
+ case I2C_I2STAT_NO_INF:
+ I2Cx->I2CONSET = I2C_I2CONSET_AA;
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ break;
+
+ /* Reading phase -------------------------------------------------------- */
+ /* Own SLA+R has been received, ACK has been returned */
+ case I2C_I2STAT_S_RX_SLAW_ACK:
+ /* General call address has been received, ACK has been returned */
+ case I2C_I2STAT_S_RX_GENCALL_ACK:
+ I2Cx->I2CONSET = I2C_I2CONSET_AA;
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ break;
+
+ /* Previously addressed with own SLA;
+ * DATA byte has been received;
+ * ACK has been returned */
+ case I2C_I2STAT_S_RX_PRE_SLA_DAT_ACK:
+ /* DATA has been received, ACK hasn been return */
+ case I2C_I2STAT_S_RX_PRE_GENCALL_DAT_ACK:
+ /*
+ * All data bytes that over-flow the specified receive
+ * data length, just ignore them.
+ */
+ if ((TransferCfg->rx_count < TransferCfg->rx_length) \
+ && (TransferCfg->rx_data != NULL)){
+ *rxdat++ = (uint8_t)I2Cx->I2DAT;
+ TransferCfg->rx_count++;
+ }
+ I2Cx->I2CONSET = I2C_I2CONSET_AA;
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ break;
+
+ /* Previously addressed with own SLA;
+ * DATA byte has been received;
+ * NOT ACK has been returned */
+ case I2C_I2STAT_S_RX_PRE_SLA_DAT_NACK:
+ /* DATA has been received, NOT ACK has been returned */
+ case I2C_I2STAT_S_RX_PRE_GENCALL_DAT_NACK:
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ break;
+
+ /*
+ * Note that: Return code only let us know a stop condition mixed
+ * with a repeat start condition in the same code value.
+ * So we should provide a time-out. In case this is really a stop
+ * condition, this will return back after time out condition. Otherwise,
+ * next session that is slave receive data will be completed.
+ */
+
+ /* A Stop or a repeat start condition */
+ case I2C_I2STAT_S_RX_STA_STO_SLVREC_SLVTRX:
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ // enable time out
+ time_en = 1;
+ timeout = 0;
+ break;
+
+ /* Writing phase -------------------------------------------------------- */
+ /* Own SLA+R has been received, ACK has been returned */
+ case I2C_I2STAT_S_TX_SLAR_ACK:
+ /* Data has been transmitted, ACK has been received */
+ case I2C_I2STAT_S_TX_DAT_ACK:
+ /*
+ * All data bytes that over-flow the specified receive
+ * data length, just ignore them.
+ */
+ if ((TransferCfg->tx_count < TransferCfg->tx_length) \
+ && (TransferCfg->tx_data != NULL)){
+ I2Cx->I2DAT = *txdat++;
+ TransferCfg->tx_count++;
+ }
+ I2Cx->I2CONSET = I2C_I2CONSET_AA;
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ break;
+
+ /* Data has been transmitted, NACK has been received,
+ * that means there's no more data to send, exit now */
+ /*
+ * Note: Don't wait for stop event since in slave transmit mode,
+ * since there no proof lets us know when a stop signal has been received
+ * on slave side.
+ */
+ case I2C_I2STAT_S_TX_DAT_NACK:
+ I2Cx->I2CONSET = I2C_I2CONSET_AA;
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ // enable time out
+ time_en = 1;
+ timeout = 0;
+ break;
+
+ // Other status must be captured
+ default:
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+ goto s_error;
+ }
+ } else if (time_en){
+ if (timeout++ > I2C_SLAVE_TIME_OUT){
+ // it's really a stop condition, goto end stage
+ goto s_end_stage;
+ }
+ }
+ }
+
+s_end_stage:
+ /* Clear AA bit to disable ACK on I2C bus */
+ I2Cx->I2CONCLR = I2C_I2CONCLR_AAC;
+ // Check if there's no error during operation
+ // Update status
+ TransferCfg->status = CodeStatus | I2C_SETUP_STATUS_DONE;
+ return SUCCESS;
+
+s_error:
+ /* Clear AA bit to disable ACK on I2C bus */
+ I2Cx->I2CONCLR = I2C_I2CONCLR_AAC;
+ // Update status
+ TransferCfg->status = CodeStatus;
+ return ERROR;
+ }
+
+ else if (Opt == I2C_TRANSFER_INTERRUPT){
+ // Setup tx_rx data, callback and interrupt handler
+ tmp = I2C_getNum(I2Cx);
+ i2cdat[tmp].txrx_setup = (uint32_t) TransferCfg;
+ // Set direction phase, read first
+ i2cdat[tmp].dir = 1;
+
+ // Enable AA
+ I2Cx->I2CONSET = I2C_I2CONSET_AA;
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC;
+ I2C_IntCmd(I2Cx, 1);
+
+ return (SUCCESS);
+ }
+
+ return ERROR;
+}
+
+/*********************************************************************//**
+ * @brief Set Own slave address in I2C peripheral corresponding to
+ * parameter specified in OwnSlaveAddrConfigStruct.
+ * @param[in] I2Cx I2C peripheral selected, should be
+ * - LPC_I2C0
+ * - LPC_I2C1
+ * - LPC_I2C2
+ * @param[in] OwnSlaveAddrConfigStruct Pointer to a I2C_OWNSLAVEADDR_CFG_Type
+ * structure that contains the configuration information for the
+* specified I2C slave address.
+ * @return None
+ **********************************************************************/
+void I2C_SetOwnSlaveAddr(LPC_I2C_TypeDef *I2Cx, I2C_OWNSLAVEADDR_CFG_Type *OwnSlaveAddrConfigStruct)
+{
+ uint32_t tmp;
+ CHECK_PARAM(PARAM_I2Cx(I2Cx));
+ CHECK_PARAM(PARAM_I2C_SLAVEADDR_CH(OwnSlaveAddrConfigStruct->SlaveAddrChannel));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(OwnSlaveAddrConfigStruct->GeneralCallState));
+
+ tmp = (((uint32_t)(OwnSlaveAddrConfigStruct->SlaveAddr_7bit << 1)) \
+ | ((OwnSlaveAddrConfigStruct->GeneralCallState == ENABLE) ? 0x01 : 0x00))& I2C_I2ADR_BITMASK;
+ switch (OwnSlaveAddrConfigStruct->SlaveAddrChannel)
+ {
+ case 0:
+ I2Cx->I2ADR0 = tmp;
+ I2Cx->I2MASK0 = I2C_I2MASK_MASK((uint32_t) \
+ (OwnSlaveAddrConfigStruct->SlaveAddrMaskValue));
+ break;
+ case 1:
+ I2Cx->I2ADR1 = tmp;
+ I2Cx->I2MASK1 = I2C_I2MASK_MASK((uint32_t) \
+ (OwnSlaveAddrConfigStruct->SlaveAddrMaskValue));
+ break;
+ case 2:
+ I2Cx->I2ADR2 = tmp;
+ I2Cx->I2MASK2 = I2C_I2MASK_MASK((uint32_t) \
+ (OwnSlaveAddrConfigStruct->SlaveAddrMaskValue));
+ break;
+ case 3:
+ I2Cx->I2ADR3 = tmp;
+ I2Cx->I2MASK3 = I2C_I2MASK_MASK((uint32_t) \
+ (OwnSlaveAddrConfigStruct->SlaveAddrMaskValue));
+ break;
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Configures functionality in I2C monitor mode
+ * @param[in] I2Cx I2C peripheral selected, should be
+ * - LPC_I2C0
+ * - LPC_I2C1
+ * - LPC_I2C2
+ * @param[in] MonitorCfgType Monitor Configuration type, should be:
+ * - I2C_MONITOR_CFG_SCL_OUTPUT: I2C module can 'stretch'
+ * the clock line (hold it low) until it has had time to
+ * respond to an I2C interrupt.
+ * - I2C_MONITOR_CFG_MATCHALL: When this bit is set to '1'
+ * and the I2C is in monitor mode, an interrupt will be
+ * generated on ANY address received.
+ * @param[in] NewState New State of this function, should be:
+ * - ENABLE: Enable this function.
+ * - DISABLE: Disable this function.
+ * @return None
+ **********************************************************************/
+void I2C_MonitorModeConfig(LPC_I2C_TypeDef *I2Cx, uint32_t MonitorCfgType, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_I2Cx(I2Cx));
+ CHECK_PARAM(PARAM_I2C_MONITOR_CFG(MonitorCfgType));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ if (NewState == ENABLE)
+ {
+ I2Cx->MMCTRL |= MonitorCfgType;
+ }
+ else
+ {
+ I2Cx->MMCTRL &= (~MonitorCfgType) & I2C_I2MMCTRL_BITMASK;
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Enable/Disable I2C monitor mode
+ * @param[in] I2Cx I2C peripheral selected, should be
+ * - LPC_I2C0
+ * - LPC_I2C1
+ * - LPC_I2C2
+ * @param[in] NewState New State of this function, should be:
+ * - ENABLE: Enable monitor mode.
+ * - DISABLE: Disable monitor mode.
+ * @return None
+ **********************************************************************/
+void I2C_MonitorModeCmd(LPC_I2C_TypeDef *I2Cx, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_I2Cx(I2Cx));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ if (NewState == ENABLE)
+ {
+ I2Cx->MMCTRL |= I2C_I2MMCTRL_MM_ENA;
+ I2Cx->I2CONSET = I2C_I2CONSET_AA;
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC;
+ }
+ else
+ {
+ I2Cx->MMCTRL &= (~I2C_I2MMCTRL_MM_ENA) & I2C_I2MMCTRL_BITMASK;
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC | I2C_I2CONCLR_AAC;
+ }
+ I2C_MonitorBufferIndex = 0;
+}
+
+
+/*********************************************************************//**
+ * @brief Get data from I2C data buffer in monitor mode.
+ * @param[in] I2Cx I2C peripheral selected, should be
+ * - LPC_I2C0
+ * - LPC_I2C1
+ * - LPC_I2C2
+ * @return None
+ * Note: In monitor mode, the I2C module may lose the ability to stretch
+ * the clock (stall the bus) if the ENA_SCL bit is not set. This means that
+ * the processor will have a limited amount of time to read the contents of
+ * the data received on the bus. If the processor reads the I2DAT shift
+ * register, as it ordinarily would, it could have only one bit-time to
+ * respond to the interrupt before the received data is overwritten by
+ * new data.
+ **********************************************************************/
+uint8_t I2C_MonitorGetDatabuffer(LPC_I2C_TypeDef *I2Cx)
+{
+ CHECK_PARAM(PARAM_I2Cx(I2Cx));
+ return ((uint8_t)(I2Cx->I2DATA_BUFFER));
+}
+
+/*********************************************************************//**
+ * @brief Get data from I2C data buffer in monitor mode.
+ * @param[in] I2Cx I2C peripheral selected, should be
+ * - LPC_I2C0
+ * - LPC_I2C1
+ * - LPC_I2C2
+ * @return None
+ * Note: In monitor mode, the I2C module may lose the ability to stretch
+ * the clock (stall the bus) if the ENA_SCL bit is not set. This means that
+ * the processor will have a limited amount of time to read the contents of
+ * the data received on the bus. If the processor reads the I2DAT shift
+ * register, as it ordinarily would, it could have only one bit-time to
+ * respond to the interrupt before the received data is overwritten by
+ * new data.
+ **********************************************************************/
+BOOL_8 I2C_MonitorHandler(LPC_I2C_TypeDef *I2Cx, uint8_t *buffer, uint32_t size)
+{
+ BOOL_8 ret=FALSE;
+
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+
+ buffer[I2C_MonitorBufferIndex] = (uint8_t)(I2Cx->I2DATA_BUFFER);
+ I2C_MonitorBufferIndex++;
+ if(I2C_MonitorBufferIndex >= size)
+ {
+ ret = TRUE;
+ }
+ return ret;
+}
+/*********************************************************************//**
+ * @brief Get status of Master Transfer
+ * @param[in] I2Cx I2C peripheral selected, should be:
+ * - LPC_I2C0
+ * - LPC_I2C1
+ * - LPC_I2C2
+ * @return Master transfer status, could be:
+ * - TRUE master transfer completed
+ * - FALSE master transfer have not completed yet
+ **********************************************************************/
+uint32_t I2C_MasterTransferComplete(LPC_I2C_TypeDef *I2Cx)
+{
+ uint32_t retval, tmp;
+ tmp = I2C_getNum(I2Cx);
+ retval = I2C_MasterComplete[tmp];
+ I2C_MasterComplete[tmp] = FALSE;
+ return retval;
+}
+
+/*********************************************************************//**
+ * @brief Get status of Slave Transfer
+ * @param[in] I2Cx I2C peripheral selected, should be:
+ * - LPC_I2C0
+ * - LPC_I2C1
+ * - LPC_I2C2
+ * @return Complete status, could be: TRUE/FALSE
+ **********************************************************************/
+uint32_t I2C_SlaveTransferComplete(LPC_I2C_TypeDef *I2Cx)
+{
+ uint32_t retval, tmp;
+ tmp = I2C_getNum(I2Cx);
+ retval = I2C_SlaveComplete[tmp];
+ I2C_SlaveComplete[tmp] = FALSE;
+ return retval;
+}
+
+
+
+/**
+ * @}
+ */
+
+#endif /* _I2C */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_i2s.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_i2s.c
new file mode 100644
index 0000000..e151edb
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_i2s.c
@@ -0,0 +1,642 @@
+/***********************************************************************//**
+ * @file lpc17xx_i2s.c
+ * @brief Contains all functions support for I2S firmware library on LPC17xx
+ * @version 3.0
+ * @date 18. June. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup I2S
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_i2s.h"
+#include "lpc17xx_clkpwr.h"
+
+
+/* If this source file built with example, the LPC17xx FW library configuration
+ * file in each example directory ("lpc17xx_libcfg.h") must be included,
+ * otherwise the default FW library configuration file must be included instead
+ */
+#ifdef __BUILD_WITH_EXAMPLE__
+#include "lpc17xx_libcfg.h"
+#else
+#include "lpc17xx_libcfg_default.h"
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+
+#ifdef _I2S
+
+/* Private Functions ---------------------------------------------------------- */
+
+static uint8_t i2s_GetWordWidth(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode);
+static uint8_t i2s_GetChannel(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode);
+
+/********************************************************************//**
+ * @brief Get I2S wordwidth value
+ * @param[in] I2Sx I2S peripheral selected, should be: LPC_I2S
+ * @param[in] TRMode is the I2S mode, should be:
+ * - I2S_TX_MODE = 0: transmit mode
+ * - I2S_RX_MODE = 1: receive mode
+ * @return The wordwidth value, should be: 8,16 or 32
+ *********************************************************************/
+static uint8_t i2s_GetWordWidth(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode) {
+ uint8_t value;
+
+ CHECK_PARAM(PARAM_I2Sx(I2Sx));
+ CHECK_PARAM(PARAM_I2S_TRX(TRMode));
+
+ if (TRMode == I2S_TX_MODE) {
+ value = (I2Sx->I2SDAO) & 0x03; /* get wordwidth bit */
+ } else {
+ value = (I2Sx->I2SDAI) & 0x03; /* get wordwidth bit */
+ }
+ switch (value) {
+ case I2S_WORDWIDTH_8:
+ return 8;
+ case I2S_WORDWIDTH_16:
+ return 16;
+ default:
+ return 32;
+ }
+}
+
+/********************************************************************//**
+ * @brief Get I2S channel value
+ * @param[in] I2Sx I2S peripheral selected, should be: LPC_I2S
+ * @param[in] TRMode is the I2S mode, should be:
+ * - I2S_TX_MODE = 0: transmit mode
+ * - I2S_RX_MODE = 1: receive mode
+ * @return The channel value, should be: 1(mono) or 2(stereo)
+ *********************************************************************/
+static uint8_t i2s_GetChannel(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode) {
+ uint8_t value;
+
+ CHECK_PARAM(PARAM_I2Sx(I2Sx));
+ CHECK_PARAM(PARAM_I2S_TRX(TRMode));
+
+ if (TRMode == I2S_TX_MODE) {
+ value = (I2Sx->I2SDAO) & 0x04; /* get bit[2] */
+ } else {
+ value = (I2Sx->I2SDAI) & 0x04; /* get bit[2] */
+ }
+ if(value == I2S_MONO) return 1;
+ return 2;
+}
+
+/* End of Private Functions --------------------------------------------------- */
+
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup I2S_Public_Functions
+ * @{
+ */
+
+/********************************************************************//**
+ * @brief Initialize I2S
+ * - Turn on power and clock
+ * @param[in] I2Sx I2S peripheral selected, should be: LPC_I2S
+ * @return none
+ *********************************************************************/
+void I2S_Init(LPC_I2S_TypeDef *I2Sx) {
+ CHECK_PARAM(PARAM_I2Sx(I2Sx));
+
+ // Turn on power and clock
+ CLKPWR_ConfigPPWR(CLKPWR_PCONP_PCI2S, ENABLE);
+ LPC_I2S->I2SDAI = LPC_I2S->I2SDAO = 0x00;
+}
+
+/********************************************************************//**
+ * @brief Configuration I2S, setting:
+ * - master/slave mode
+ * - wordwidth value
+ * - channel mode
+ * @param[in] I2Sx I2S peripheral selected, should be: LPC_I2S
+ * @param[in] TRMode transmit/receive mode, should be:
+ * - I2S_TX_MODE = 0: transmit mode
+ * - I2S_RX_MODE = 1: receive mode
+ * @param[in] ConfigStruct pointer to I2S_CFG_Type structure
+ * which will be initialized.
+ * @return none
+ *********************************************************************/
+void I2S_Config(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode, I2S_CFG_Type* ConfigStruct)
+{
+ uint32_t bps, config;
+
+ CHECK_PARAM(PARAM_I2Sx(I2Sx));
+
+ CHECK_PARAM(PARAM_I2S_WORDWIDTH(ConfigStruct->wordwidth));
+ CHECK_PARAM(PARAM_I2S_CHANNEL(ConfigStruct->mono));
+ CHECK_PARAM(PARAM_I2S_STOP(ConfigStruct->stop));
+ CHECK_PARAM(PARAM_I2S_RESET(ConfigStruct->reset));
+ CHECK_PARAM(PARAM_I2S_WS_SEL(ConfigStruct->ws_sel));
+ CHECK_PARAM(PARAM_I2S_MUTE(ConfigStruct->mute));
+
+ /* Setup clock */
+ bps = (ConfigStruct->wordwidth +1)*8;
+
+ /* Calculate audio config */
+ config = (bps - 1)<<6 | (ConfigStruct->ws_sel)<<5 | (ConfigStruct->reset)<<4 |
+ (ConfigStruct->stop)<<3 | (ConfigStruct->mono)<<2 | (ConfigStruct->wordwidth);
+
+ if(TRMode == I2S_RX_MODE){
+ LPC_I2S->I2SDAI = config;
+ }else{
+ LPC_I2S->I2SDAO = config;
+ }
+}
+
+/********************************************************************//**
+ * @brief DeInitial both I2S transmit or receive
+ * @param[in] I2Sx I2S peripheral selected, should be: LPC_I2S
+ * @return none
+ *********************************************************************/
+void I2S_DeInit(LPC_I2S_TypeDef *I2Sx) {
+ CHECK_PARAM(PARAM_I2Sx(I2Sx));
+
+ // Turn off power and clock
+ CLKPWR_ConfigPPWR(CLKPWR_PCONP_PCI2S, DISABLE);
+}
+
+/********************************************************************//**
+ * @brief Get I2S Buffer Level
+ * @param[in] I2Sx I2S peripheral selected, should be: LPC_I2S
+ * @param[in] TRMode Transmit/receive mode, should be:
+ * - I2S_TX_MODE = 0: transmit mode
+ * - I2S_RX_MODE = 1: receive mode
+ * @return current level of Transmit/Receive Buffer
+ *********************************************************************/
+uint8_t I2S_GetLevel(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode)
+{
+ CHECK_PARAM(PARAM_I2Sx(I2Sx));
+ CHECK_PARAM(PARAM_I2S_TRX(TRMode));
+
+ if(TRMode == I2S_TX_MODE)
+ {
+ return ((I2Sx->I2SSTATE >> 16) & 0xFF);
+ }
+ else
+ {
+ return ((I2Sx->I2SSTATE >> 8) & 0xFF);
+ }
+}
+
+/********************************************************************//**
+ * @brief I2S Start: clear all STOP,RESET and MUTE bit, ready to operate
+ * @param[in] I2Sx I2S peripheral selected, should be: LPC_I2S
+ * @return none
+ *********************************************************************/
+void I2S_Start(LPC_I2S_TypeDef *I2Sx)
+{
+ //Clear STOP,RESET and MUTE bit
+ I2Sx->I2SDAO &= ~I2S_DAI_RESET;
+ I2Sx->I2SDAI &= ~I2S_DAI_RESET;
+ I2Sx->I2SDAO &= ~I2S_DAI_STOP;
+ I2Sx->I2SDAI &= ~I2S_DAI_STOP;
+ I2Sx->I2SDAO &= ~I2S_DAI_MUTE;
+}
+
+/********************************************************************//**
+ * @brief I2S Send data
+ * @param[in] I2Sx I2S peripheral selected, should be: LPC_I2S
+ * @param[in] BufferData pointer to uint32_t is the data will be send
+ * @return none
+ *********************************************************************/
+void I2S_Send(LPC_I2S_TypeDef *I2Sx, uint32_t BufferData) {
+ CHECK_PARAM(PARAM_I2Sx(I2Sx));
+
+ I2Sx->I2STXFIFO = BufferData;
+}
+
+/********************************************************************//**
+ * @brief I2S Receive Data
+ * @param[in] I2Sx pointer to LPC_I2S_TypeDef
+ * @return received value
+ *********************************************************************/
+uint32_t I2S_Receive(LPC_I2S_TypeDef* I2Sx) {
+ CHECK_PARAM(PARAM_I2Sx(I2Sx));
+
+ return (I2Sx->I2SRXFIFO);
+
+}
+
+/********************************************************************//**
+ * @brief I2S Pause
+ * @param[in] I2Sx I2S peripheral selected, should be: LPC_I2S
+ * @param[in] TRMode is transmit/receive mode, should be:
+ * - I2S_TX_MODE = 0: transmit mode
+ * - I2S_RX_MODE = 1: receive mode
+ * @return none
+ *********************************************************************/
+void I2S_Pause(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode) {
+ CHECK_PARAM(PARAM_I2Sx(I2Sx));
+ CHECK_PARAM(PARAM_I2S_TRX(TRMode));
+
+ if (TRMode == I2S_TX_MODE) //Transmit mode
+ {
+ I2Sx->I2SDAO |= I2S_DAO_STOP;
+ } else //Receive mode
+ {
+ I2Sx->I2SDAI |= I2S_DAI_STOP;
+ }
+}
+
+/********************************************************************//**
+ * @brief I2S Mute
+ * @param[in] I2Sx I2S peripheral selected, should be: LPC_I2S
+ * @param[in] TRMode is transmit/receive mode, should be:
+ * - I2S_TX_MODE = 0: transmit mode
+ * - I2S_RX_MODE = 1: receive mode
+ * @return none
+ *********************************************************************/
+void I2S_Mute(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode) {
+ CHECK_PARAM(PARAM_I2Sx(I2Sx));
+ CHECK_PARAM(PARAM_I2S_TRX(TRMode));
+
+ if (TRMode == I2S_TX_MODE) //Transmit mode
+ {
+ I2Sx->I2SDAO |= I2S_DAO_MUTE;
+ } else //Receive mode
+ {
+ I2Sx->I2SDAI |= I2S_DAI_MUTE;
+ }
+}
+
+/********************************************************************//**
+ * @brief I2S Stop
+ * @param[in] I2Sx I2S peripheral selected, should be: LPC_I2S
+ * @param[in] TRMode is transmit/receive mode, should be:
+ * - I2S_TX_MODE = 0: transmit mode
+ * - I2S_RX_MODE = 1: receive mode
+ * @return none
+ *********************************************************************/
+void I2S_Stop(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode) {
+ CHECK_PARAM(PARAM_I2Sx(I2Sx));
+ CHECK_PARAM(PARAM_I2S_TRX(TRMode));
+
+ if (TRMode == I2S_TX_MODE) //Transmit mode
+ {
+ I2Sx->I2SDAO &= ~I2S_DAO_MUTE;
+ I2Sx->I2SDAO |= I2S_DAO_STOP;
+ I2Sx->I2SDAO |= I2S_DAO_RESET;
+ } else //Receive mode
+ {
+ I2Sx->I2SDAI |= I2S_DAI_STOP;
+ I2Sx->I2SDAI |= I2S_DAI_RESET;
+ }
+}
+
+/********************************************************************//**
+ * @brief Set frequency for I2S
+ * @param[in] I2Sx I2S peripheral selected, should be: LPC_I2S
+ * @param[in] Freq is the frequency for I2S will be set. It can range
+ * from 16-96 kHz(16, 22.05, 32, 44.1, 48, 96kHz)
+ * @param[in] TRMode is transmit/receive mode, should be:
+ * - I2S_TX_MODE = 0: transmit mode
+ * - I2S_RX_MODE = 1: receive mode
+ * @return Status: ERROR or SUCCESS
+ *********************************************************************/
+Status I2S_FreqConfig(LPC_I2S_TypeDef *I2Sx, uint32_t Freq, uint8_t TRMode) {
+
+ /* Calculate bit rate
+ * The formula is:
+ * bit_rate = channel*wordwidth - 1
+ * 48kHz sample rate for 16 bit stereo date requires
+ * a bit rate of 48000*16*2=1536MHz (MCLK)
+ */
+ uint32_t i2sPclk;
+ uint64_t divider;
+ uint8_t bitrate, channel, wordwidth;
+ uint32_t x, y;
+ uint16_t dif;
+ uint16_t error;
+ uint8_t x_divide, y_divide;
+ uint16_t ErrorOptimal = 0xFFFF;
+
+ CHECK_PARAM(PARAM_I2Sx(I2Sx));
+ CHECK_PARAM(PRAM_I2S_FREQ(Freq));
+ CHECK_PARAM(PARAM_I2S_TRX(TRMode));
+
+ i2sPclk = CLKPWR_GetPCLK(CLKPWR_PCLKSEL_I2S);
+ if(TRMode == I2S_TX_MODE)
+ {
+ channel = i2s_GetChannel(I2Sx,I2S_TX_MODE);
+ wordwidth = i2s_GetWordWidth(I2Sx,I2S_TX_MODE);
+ }
+ else
+ {
+ channel = i2s_GetChannel(I2Sx,I2S_RX_MODE);
+ wordwidth = i2s_GetWordWidth(I2Sx,I2S_RX_MODE);
+ }
+ bitrate = channel * wordwidth - 1;
+ if (TRMode == I2S_TX_MODE)// Transmitter
+ {
+ I2Sx->I2STXBITRATE = bitrate;
+ } else //Receiver
+ {
+ I2Sx->I2SRXBITRATE = bitrate;
+ }
+ /* Calculate X and Y divider
+ * The MCLK rate for the I2S transmitter is determined by the value
+ * in the I2STXRATE/I2SRXRATE register. The required I2STXRATE/I2SRXRATE
+ * setting depends on the desired audio sample rate desired, the format
+ * (stereo/mono) used, and the data size.
+ * The formula is:
+ * I2S_MCLK = PCLK * (X/Y) / 2
+ * We have:
+ * I2S_MCLK = Freq * bit_rate;
+ * So: (X/Y) = (Freq * bit_rate)/PCLK*2
+ * We use a loop function to chose the most suitable X,Y value
+ */
+
+ divider = ((uint64_t)(Freq *( bitrate+1)* 2)<<16) / i2sPclk;
+ for (y = 255; y > 0; y--) {
+ x = y * divider;
+ dif = x & 0xFFFF;
+ if(dif>0x8000) error = 0x10000-dif;
+ else error = dif;
+ if (error == 0)
+ {
+ y_divide = y;
+ break;
+ }
+ else if (error < ErrorOptimal)
+ {
+ ErrorOptimal = error;
+ y_divide = y;
+ }
+ }
+ x_divide = (y_divide * Freq *( bitrate+1)* 2)/i2sPclk;
+ if (TRMode == I2S_TX_MODE)// Transmitter
+ {
+ I2Sx->I2STXRATE = y_divide | (x_divide << 8);
+ } else //Receiver
+ {
+ I2Sx->I2SRXRATE = y_divide | (x_divide << 8);
+ }
+ return SUCCESS;
+}
+
+/********************************************************************//**
+ * @brief I2S set bitrate
+ * @param[in] I2Sx I2S peripheral selected, should be: LPC_I2S
+ * @param[in] bitrate value will be set, it can be calculate as follows:
+ * bitrate = channel * wordwidth - 1
+ * bitrate value should be in range: 0 .. 63
+ * @param[in] TRMode is transmit/receive mode, should be:
+ * - I2S_TX_MODE = 0: transmit mode
+ * - I2S_RX_MODE = 1: receive mode
+ * @return none
+ *********************************************************************/
+void I2S_SetBitRate(LPC_I2S_TypeDef *I2Sx, uint8_t bitrate, uint8_t TRMode)
+{
+ CHECK_PARAM(PARAM_I2Sx(I2Sx));
+ CHECK_PARAM(PARAM_I2S_BITRATE(bitrate));
+ CHECK_PARAM(PARAM_I2S_TRX(TRMode));
+
+ if(TRMode == I2S_TX_MODE)
+ {
+ I2Sx->I2STXBITRATE = bitrate;
+ }
+ else
+ {
+ I2Sx->I2SRXBITRATE = bitrate;
+ }
+}
+
+/********************************************************************//**
+ * @brief Configuration operating mode for I2S
+ * @param[in] I2Sx I2S peripheral selected, should be: LPC_I2S
+ * @param[in] ModeConfig pointer to I2S_MODEConf_Type will be used to
+ * configure
+ * @param[in] TRMode is transmit/receive mode, should be:
+ * - I2S_TX_MODE = 0: transmit mode
+ * - I2S_RX_MODE = 1: receive mode
+ * @return none
+ *********************************************************************/
+void I2S_ModeConfig(LPC_I2S_TypeDef *I2Sx, I2S_MODEConf_Type* ModeConfig,
+ uint8_t TRMode)
+{
+ CHECK_PARAM(PARAM_I2Sx(I2Sx));
+ CHECK_PARAM(PARAM_I2S_CLKSEL(ModeConfig->clksel));
+ CHECK_PARAM(PARAM_I2S_4PIN(ModeConfig->fpin));
+ CHECK_PARAM(PARAM_I2S_MCLK(ModeConfig->mcena));
+ CHECK_PARAM(PARAM_I2S_TRX(TRMode));
+
+ if (TRMode == I2S_TX_MODE) {
+ I2Sx->I2STXMODE &= ~0x0F; //clear bit 3:0 in I2STXMODE register
+ if (ModeConfig->clksel == I2S_CLKSEL_MCLK) {
+ I2Sx->I2STXMODE |= 0x02;
+ }
+ if (ModeConfig->fpin == I2S_4PIN_ENABLE) {
+ I2Sx->I2STXMODE |= (1 << 2);
+ }
+ if (ModeConfig->mcena == I2S_MCLK_ENABLE) {
+ I2Sx->I2STXMODE |= (1 << 3);
+ }
+ } else {
+ I2Sx->I2SRXMODE &= ~0x0F; //clear bit 3:0 in I2STXMODE register
+ if (ModeConfig->clksel == I2S_CLKSEL_MCLK) {
+ I2Sx->I2SRXMODE |= 0x02;
+ }
+ if (ModeConfig->fpin == I2S_4PIN_ENABLE) {
+ I2Sx->I2SRXMODE |= (1 << 2);
+ }
+ if (ModeConfig->mcena == I2S_MCLK_ENABLE) {
+ I2Sx->I2SRXMODE |= (1 << 3);
+ }
+ }
+}
+
+/********************************************************************//**
+ * @brief Configure DMA operation for I2S
+ * @param[in] I2Sx I2S peripheral selected, should be: LPC_I2S
+ * @param[in] DMAConfig pointer to I2S_DMAConf_Type will be used to configure
+ * @param[in] TRMode is transmit/receive mode, should be:
+ * - I2S_TX_MODE = 0: transmit mode
+ * - I2S_RX_MODE = 1: receive mode
+ * @return none
+ *********************************************************************/
+void I2S_DMAConfig(LPC_I2S_TypeDef *I2Sx, I2S_DMAConf_Type* DMAConfig,
+ uint8_t TRMode)
+{
+ CHECK_PARAM(PARAM_I2Sx(I2Sx));
+ CHECK_PARAM(PARAM_I2S_DMA(DMAConfig->DMAIndex));
+ CHECK_PARAM(PARAM_I2S_DMA_DEPTH(DMAConfig->depth));
+ CHECK_PARAM(PARAM_I2S_TRX(TRMode));
+
+ if (TRMode == I2S_RX_MODE) {
+ if (DMAConfig->DMAIndex == I2S_DMA_1) {
+ LPC_I2S->I2SDMA1 = (DMAConfig->depth) << 8;
+ } else {
+ LPC_I2S->I2SDMA2 = (DMAConfig->depth) << 8;
+ }
+ } else {
+ if (DMAConfig->DMAIndex == I2S_DMA_1) {
+ LPC_I2S->I2SDMA1 = (DMAConfig->depth) << 16;
+ } else {
+ LPC_I2S->I2SDMA2 = (DMAConfig->depth) << 16;
+ }
+ }
+}
+
+/********************************************************************//**
+ * @brief Enable/Disable DMA operation for I2S
+ * @param[in] I2Sx: I2S peripheral selected, should be: LPC_I2S
+ * @param[in] DMAIndex chose what DMA is used, should be:
+ * - I2S_DMA_1 = 0: DMA1
+ * - I2S_DMA_2 = 1: DMA2
+ * @param[in] TRMode is transmit/receive mode, should be:
+ * - I2S_TX_MODE = 0: transmit mode
+ * - I2S_RX_MODE = 1: receive mode
+ * @param[in] NewState is new state of DMA operation, should be:
+ * - ENABLE
+ * - DISABLE
+ * @return none
+ *********************************************************************/
+void I2S_DMACmd(LPC_I2S_TypeDef *I2Sx, uint8_t DMAIndex, uint8_t TRMode,
+ FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_I2Sx(I2Sx));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+ CHECK_PARAM(PARAM_I2S_DMA(DMAIndex));
+ CHECK_PARAM(PARAM_I2S_TRX(TRMode));
+
+ if (TRMode == I2S_RX_MODE) {
+ if (DMAIndex == I2S_DMA_1) {
+ if (NewState == ENABLE)
+ I2Sx->I2SDMA1 |= 0x01;
+ else
+ I2Sx->I2SDMA1 &= ~0x01;
+ } else {
+ if (NewState == ENABLE)
+ I2Sx->I2SDMA2 |= 0x01;
+ else
+ I2Sx->I2SDMA2 &= ~0x01;
+ }
+ } else {
+ if (DMAIndex == I2S_DMA_1) {
+ if (NewState == ENABLE)
+ I2Sx->I2SDMA1 |= 0x02;
+ else
+ I2Sx->I2SDMA1 &= ~0x02;
+ } else {
+ if (NewState == ENABLE)
+ I2Sx->I2SDMA2 |= 0x02;
+ else
+ I2Sx->I2SDMA2 &= ~0x02;
+ }
+ }
+}
+
+/********************************************************************//**
+ * @brief Configure IRQ for I2S
+ * @param[in] I2Sx I2S peripheral selected, should be: LPC_I2S
+ * @param[in] TRMode is transmit/receive mode, should be:
+ * - I2S_TX_MODE = 0: transmit mode
+ * - I2S_RX_MODE = 1: receive mode
+ * @param[in] level is the FIFO level that triggers IRQ request
+ * @return none
+ *********************************************************************/
+void I2S_IRQConfig(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode, uint8_t level) {
+ CHECK_PARAM(PARAM_I2Sx(I2Sx));
+ CHECK_PARAM(PARAM_I2S_TRX(TRMode));
+ CHECK_PARAM(PARAM_I2S_IRQ_LEVEL(level));
+
+ if (TRMode == I2S_RX_MODE) {
+ I2Sx->I2SIRQ |= (level << 8);
+ } else {
+ I2Sx->I2SIRQ |= (level << 16);
+ }
+}
+
+/********************************************************************//**
+ * @brief Enable/Disable IRQ for I2S
+ * @param[in] I2Sx I2S peripheral selected, should be: LPC_I2S
+ * @param[in] TRMode is transmit/receive mode, should be:
+ * - I2S_TX_MODE = 0: transmit mode
+ * - I2S_RX_MODE = 1: receive mode
+ * @param[in] NewState is new state of DMA operation, should be:
+ * - ENABLE
+ * - DISABLE
+ * @return none
+ *********************************************************************/
+void I2S_IRQCmd(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode, FunctionalState NewState) {
+ CHECK_PARAM(PARAM_I2Sx(I2Sx));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ if (TRMode == I2S_RX_MODE) {
+ if (NewState == ENABLE)
+ I2Sx->I2SIRQ |= 0x01;
+ else
+ I2Sx->I2SIRQ &= ~0x01;
+ //Enable DMA
+
+ } else {
+ if (NewState == ENABLE)
+ I2Sx->I2SIRQ |= 0x02;
+ else
+ I2Sx->I2SIRQ &= ~0x02;
+ }
+}
+
+/********************************************************************//**
+ * @brief Get I2S interrupt status
+ * @param[in] I2Sx I2S peripheral selected, should be: LPC_I2S
+ * @param[in] TRMode is transmit/receive mode, should be:
+ * - I2S_TX_MODE = 0: transmit mode
+ * - I2S_RX_MODE = 1: receive mode
+ * @return FunctionState should be:
+ * - ENABLE: interrupt is enable
+ * - DISABLE: interrupt is disable
+ *********************************************************************/
+FunctionalState I2S_GetIRQStatus(LPC_I2S_TypeDef *I2Sx,uint8_t TRMode)
+{
+ CHECK_PARAM(PARAM_I2Sx(I2Sx));
+ if(TRMode == I2S_TX_MODE)
+ return ((I2Sx->I2SIRQ >> 1)&0x01);
+ else
+ return ((I2Sx->I2SIRQ)&0x01);
+}
+
+/********************************************************************//**
+ * @brief Get I2S interrupt depth
+ * @param[in] I2Sx I2S peripheral selected, should be: LPC_I2S
+ * @param[in] TRMode is transmit/receive mode, should be:
+ * - I2S_TX_MODE = 0: transmit mode
+ * - I2S_RX_MODE = 1: receive mode
+ * @return depth of FIFO level on which to create an irq request
+ *********************************************************************/
+uint8_t I2S_GetIRQDepth(LPC_I2S_TypeDef *I2Sx,uint8_t TRMode)
+{
+ CHECK_PARAM(PARAM_I2Sx(I2Sx));
+ if(TRMode == I2S_TX_MODE)
+ return (((I2Sx->I2SIRQ)>>16)&0xFF);
+ else
+ return (((I2Sx->I2SIRQ)>>8)&0xFF);
+}
+/**
+ * @}
+ */
+
+#endif /* _I2S */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
+
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_libcfg_default.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_libcfg_default.c
new file mode 100644
index 0000000..8c7542f
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_libcfg_default.c
@@ -0,0 +1,64 @@
+/***********************************************************************//**
+ * @file lpc17xx_libcfg_default.c
+ * @brief Library configuration source file (default),
+ * used to build library without examples.
+ * @version 2.0
+ * @date 21. May. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **************************************************************************/
+
+/* Library group ----------------------------------------------------------- */
+/** @addtogroup LIBCFG_DEFAULT
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_libcfg_default.h"
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup LIBCFG_DEFAULT_Public_Functions
+ * @{
+ */
+
+#ifndef __BUILD_WITH_EXAMPLE__
+
+#ifdef DEBUG
+/*******************************************************************************
+* @brief Reports the name of the source file and the source line number
+* where the CHECK_PARAM error has occurred.
+* @param[in] file Pointer to the source file name
+* @param[in] line assert_param error line source number
+* @return None
+*******************************************************************************/
+void check_failed(uint8_t *file, uint32_t line)
+{
+ /* User can add his own implementation to report the file name and line number,
+ ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
+
+ /* Infinite loop */
+ while(1);
+}
+#endif /* DEBUG */
+
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_mcpwm.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_mcpwm.c
new file mode 100644
index 0000000..d4692d1
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_mcpwm.c
@@ -0,0 +1,497 @@
+/***********************************************************************//**
+ * @file lpc17xx_mcpwm.c
+ * @brief Contains all functions support for Motor Control PWM firmware
+ * library on LPC17xx
+ * @version 2.0
+ * @date 21. May. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup MCPWM
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_mcpwm.h"
+#include "lpc17xx_clkpwr.h"
+
+/* If this source file built with example, the LPC17xx FW library configuration
+ * file in each example directory ("lpc17xx_libcfg.h") must be included,
+ * otherwise the default FW library configuration file must be included instead
+ */
+#ifdef __BUILD_WITH_EXAMPLE__
+#include "lpc17xx_libcfg.h"
+#else
+#include "lpc17xx_libcfg_default.h"
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+
+#ifdef _MCPWM
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup MCPWM_Public_Functions
+ * @{
+ */
+
+/*********************************************************************//**
+ * @brief Initializes the MCPWM peripheral
+ * @param[in] MCPWMx Motor Control PWM peripheral selected,
+ * Should be: LPC_MCPWM
+ * @return None
+ **********************************************************************/
+void MCPWM_Init(LPC_MCPWM_TypeDef *MCPWMx)
+{
+
+ /* Turn On MCPWM PCLK */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCMC, ENABLE);
+ /* As default, peripheral clock for MCPWM module
+ * is set to FCCLK / 2 */
+ // CLKPWR_SetPCLKDiv(CLKPWR_PCLKSEL_MC, CLKPWR_PCLKSEL_CCLK_DIV_2);
+
+ MCPWMx->MCCAP_CLR = MCPWM_CAPCLR_CAP(0) | MCPWM_CAPCLR_CAP(1) | MCPWM_CAPCLR_CAP(2);
+ MCPWMx->MCINTFLAG_CLR = MCPWM_INT_ILIM(0) | MCPWM_INT_ILIM(1) | MCPWM_INT_ILIM(2) \
+ | MCPWM_INT_IMAT(0) | MCPWM_INT_IMAT(1) | MCPWM_INT_IMAT(2) \
+ | MCPWM_INT_ICAP(0) | MCPWM_INT_ICAP(1) | MCPWM_INT_ICAP(2);
+ MCPWMx->MCINTEN_CLR = MCPWM_INT_ILIM(0) | MCPWM_INT_ILIM(1) | MCPWM_INT_ILIM(2) \
+ | MCPWM_INT_IMAT(0) | MCPWM_INT_IMAT(1) | MCPWM_INT_IMAT(2) \
+ | MCPWM_INT_ICAP(0) | MCPWM_INT_ICAP(1) | MCPWM_INT_ICAP(2);
+}
+
+
+/*********************************************************************//**
+ * @brief Configures each channel in MCPWM peripheral according to the
+ * specified parameters in the MCPWM_CHANNEL_CFG_Type.
+ * @param[in] MCPWMx Motor Control PWM peripheral selected
+ * should be: LPC_MCPWM
+ * @param[in] channelNum Channel number, should be: 0..2.
+ * @param[in] channelSetup Pointer to a MCPWM_CHANNEL_CFG_Type structure
+* that contains the configuration information for the
+* specified MCPWM channel.
+ * @return None
+ **********************************************************************/
+void MCPWM_ConfigChannel(LPC_MCPWM_TypeDef *MCPWMx, uint32_t channelNum,
+ MCPWM_CHANNEL_CFG_Type * channelSetup)
+{
+ if ((channelNum >= 0) && (channelNum <= 2)) {
+ if (channelNum == 0) {
+ MCPWMx->MCTIM0 = channelSetup->channelTimercounterValue;
+ MCPWMx->MCPER0 = channelSetup->channelPeriodValue;
+ MCPWMx->MCPW0 = channelSetup->channelPulsewidthValue;
+ } else if (channelNum == 1) {
+ MCPWMx->MCTIM1 = channelSetup->channelTimercounterValue;
+ MCPWMx->MCPER1 = channelSetup->channelPeriodValue;
+ MCPWMx->MCPW1 = channelSetup->channelPulsewidthValue;
+ } else if (channelNum == 2) {
+ MCPWMx->MCTIM2 = channelSetup->channelTimercounterValue;
+ MCPWMx->MCPER2 = channelSetup->channelPeriodValue;
+ MCPWMx->MCPW2 = channelSetup->channelPulsewidthValue;
+ } else {
+ return;
+ }
+
+ if (channelSetup->channelType /* == MCPWM_CHANNEL_CENTER_MODE */){
+ MCPWMx->MCCON_SET = MCPWM_CON_CENTER(channelNum);
+ } else {
+ MCPWMx->MCCON_CLR = MCPWM_CON_CENTER(channelNum);
+ }
+
+ if (channelSetup->channelPolarity /* == MCPWM_CHANNEL_PASSIVE_HI */){
+ MCPWMx->MCCON_SET = MCPWM_CON_POLAR(channelNum);
+ } else {
+ MCPWMx->MCCON_CLR = MCPWM_CON_POLAR(channelNum);
+ }
+
+ if (channelSetup->channelDeadtimeEnable /* == ENABLE */){
+ MCPWMx->MCCON_SET = MCPWM_CON_DTE(channelNum);
+ MCPWMx->MCDEADTIME &= ~(MCPWM_DT(channelNum, 0x3FF));
+ MCPWMx->MCDEADTIME |= MCPWM_DT(channelNum, channelSetup->channelDeadtimeValue);
+ } else {
+ MCPWMx->MCCON_CLR = MCPWM_CON_DTE(channelNum);
+ }
+
+ if (channelSetup->channelUpdateEnable /* == ENABLE */){
+ MCPWMx->MCCON_CLR = MCPWM_CON_DISUP(channelNum);
+ } else {
+ MCPWMx->MCCON_SET = MCPWM_CON_DISUP(channelNum);
+ }
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Write to MCPWM shadow registers - Update the value for period
+ * and pulse width in MCPWM peripheral.
+ * @param[in] MCPWMx Motor Control PWM peripheral selected
+ * Should be: LPC_MCPWM
+ * @param[in] channelNum Channel Number, should be: 0..2.
+ * @param[in] channelSetup Pointer to a MCPWM_CHANNEL_CFG_Type structure
+* that contains the configuration information for the
+* specified MCPWM channel.
+ * @return None
+ **********************************************************************/
+void MCPWM_WriteToShadow(LPC_MCPWM_TypeDef *MCPWMx, uint32_t channelNum,
+ MCPWM_CHANNEL_CFG_Type *channelSetup)
+{
+ if (channelNum == 0){
+ MCPWMx->MCPER0 = channelSetup->channelPeriodValue;
+ MCPWMx->MCPW0 = channelSetup->channelPulsewidthValue;
+ } else if (channelNum == 1) {
+ MCPWMx->MCPER1 = channelSetup->channelPeriodValue;
+ MCPWMx->MCPW1 = channelSetup->channelPulsewidthValue;
+ } else if (channelNum == 2) {
+ MCPWMx->MCPER2 = channelSetup->channelPeriodValue;
+ MCPWMx->MCPW2 = channelSetup->channelPulsewidthValue;
+ }
+}
+
+
+
+/*********************************************************************//**
+ * @brief Configures capture function in MCPWM peripheral
+ * @param[in] MCPWMx Motor Control PWM peripheral selected
+ * Should be: LPC_MCPWM
+ * @param[in] channelNum MCI (Motor Control Input pin) number
+ * Should be: 0..2
+ * @param[in] captureConfig Pointer to a MCPWM_CAPTURE_CFG_Type structure
+* that contains the configuration information for the
+* specified MCPWM capture.
+ * @return
+ **********************************************************************/
+void MCPWM_ConfigCapture(LPC_MCPWM_TypeDef *MCPWMx, uint32_t channelNum,
+ MCPWM_CAPTURE_CFG_Type *captureConfig)
+{
+ if ((channelNum >= 0) && (channelNum <= 2)) {
+
+ if (captureConfig->captureFalling /* == ENABLE */) {
+ MCPWMx->MCCAPCON_SET = MCPWM_CAPCON_CAPMCI_FE(captureConfig->captureChannel, channelNum);
+ } else {
+ MCPWMx->MCCAPCON_CLR = MCPWM_CAPCON_CAPMCI_FE(captureConfig->captureChannel, channelNum);
+ }
+
+ if (captureConfig->captureRising /* == ENABLE */) {
+ MCPWMx->MCCAPCON_SET = MCPWM_CAPCON_CAPMCI_RE(captureConfig->captureChannel, channelNum);
+ } else {
+ MCPWMx->MCCAPCON_CLR = MCPWM_CAPCON_CAPMCI_RE(captureConfig->captureChannel, channelNum);
+ }
+
+ if (captureConfig->timerReset /* == ENABLE */){
+ MCPWMx->MCCAPCON_SET = MCPWM_CAPCON_RT(captureConfig->captureChannel);
+ } else {
+ MCPWMx->MCCAPCON_CLR = MCPWM_CAPCON_RT(captureConfig->captureChannel);
+ }
+
+ if (captureConfig->hnfEnable /* == ENABLE */){
+ MCPWMx->MCCAPCON_SET = MCPWM_CAPCON_HNFCAP(channelNum);
+ } else {
+ MCPWMx->MCCAPCON_CLR = MCPWM_CAPCON_HNFCAP(channelNum);
+ }
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Clears current captured value in specified capture channel
+ * @param[in] MCPWMx Motor Control PWM peripheral selected
+ * Should be: LPC_MCPWM
+ * @param[in] captureChannel Capture channel number, should be: 0..2
+ * @return None
+ **********************************************************************/
+void MCPWM_ClearCapture(LPC_MCPWM_TypeDef *MCPWMx, uint32_t captureChannel)
+{
+ MCPWMx->MCCAP_CLR = MCPWM_CAPCLR_CAP(captureChannel);
+}
+
+/*********************************************************************//**
+ * @brief Get current captured value in specified capture channel
+ * @param[in] MCPWMx Motor Control PWM peripheral selected,
+ * Should be: LPC_MCPWM
+ * @param[in] captureChannel Capture channel number, should be: 0..2
+ * @return None
+ **********************************************************************/
+uint32_t MCPWM_GetCapture(LPC_MCPWM_TypeDef *MCPWMx, uint32_t captureChannel)
+{
+ if (captureChannel == 0){
+ return (MCPWMx->MCCR0);
+ } else if (captureChannel == 1) {
+ return (MCPWMx->MCCR1);
+ } else if (captureChannel == 2) {
+ return (MCPWMx->MCCR2);
+ }
+ return (0);
+}
+
+
+/*********************************************************************//**
+ * @brief Configures Count control in MCPWM peripheral
+ * @param[in] MCPWMx Motor Control PWM peripheral selected
+ * Should be: LPC_MCPWM
+ * @param[in] channelNum Channel number, should be: 0..2
+ * @param[in] countMode Count mode, should be:
+ * - ENABLE: Enables count mode.
+ * - DISABLE: Disable count mode, the channel is in timer mode.
+ * @param[in] countConfig Pointer to a MCPWM_COUNT_CFG_Type structure
+* that contains the configuration information for the
+* specified MCPWM count control.
+ * @return None
+ **********************************************************************/
+void MCPWM_CountConfig(LPC_MCPWM_TypeDef *MCPWMx, uint32_t channelNum,
+ uint32_t countMode, MCPWM_COUNT_CFG_Type *countConfig)
+{
+ if ((channelNum >= 0) && (channelNum <= 2)) {
+ if (countMode /* == ENABLE */){
+ MCPWMx->MCCNTCON_SET = MCPWM_CNTCON_CNTR(channelNum);
+ if (countConfig->countFalling /* == ENABLE */) {
+ MCPWMx->MCCNTCON_SET = MCPWM_CNTCON_TCMCI_FE(countConfig->counterChannel,channelNum);
+ } else {
+ MCPWMx->MCCNTCON_CLR = MCPWM_CNTCON_TCMCI_FE(countConfig->counterChannel,channelNum);
+ }
+ if (countConfig->countRising /* == ENABLE */) {
+ MCPWMx->MCCNTCON_SET = MCPWM_CNTCON_TCMCI_RE(countConfig->counterChannel,channelNum);
+ } else {
+ MCPWMx->MCCNTCON_CLR = MCPWM_CNTCON_TCMCI_RE(countConfig->counterChannel,channelNum);
+ }
+ } else {
+ MCPWMx->MCCNTCON_CLR = MCPWM_CNTCON_CNTR(channelNum);
+ }
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Start MCPWM activity for each MCPWM channel
+ * @param[in] MCPWMx Motor Control PWM peripheral selected
+ * Should be: LPC_MCPWM
+ * @param[in] channel0 State of this command on channel 0:
+ * - ENABLE: 'Start' command will effect on channel 0
+ * - DISABLE: 'Start' command will not effect on channel 0
+ * @param[in] channel1 State of this command on channel 1:
+ * - ENABLE: 'Start' command will effect on channel 1
+ * - DISABLE: 'Start' command will not effect on channel 1
+ * @param[in] channel2 State of this command on channel 2:
+ * - ENABLE: 'Start' command will effect on channel 2
+ * - DISABLE: 'Start' command will not effect on channel 2
+ * @return None
+ **********************************************************************/
+void MCPWM_Start(LPC_MCPWM_TypeDef *MCPWMx, uint32_t channel0,
+ uint32_t channel1, uint32_t channel2)
+{
+ uint32_t regVal = 0;
+ regVal = (channel0 ? MCPWM_CON_RUN(0) : 0) | (channel1 ? MCPWM_CON_RUN(1) : 0) \
+ | (channel2 ? MCPWM_CON_RUN(2) : 0);
+ MCPWMx->MCCON_SET = regVal;
+}
+
+
+/*********************************************************************//**
+ * @brief Stop MCPWM activity for each MCPWM channel
+ * @param[in] MCPWMx Motor Control PWM peripheral selected
+ * Should be: LPC_MCPWM
+ * @param[in] channel0 State of this command on channel 0:
+ * - ENABLE: 'Stop' command will effect on channel 0
+ * - DISABLE: 'Stop' command will not effect on channel 0
+ * @param[in] channel1 State of this command on channel 1:
+ * - ENABLE: 'Stop' command will effect on channel 1
+ * - DISABLE: 'Stop' command will not effect on channel 1
+ * @param[in] channel2 State of this command on channel 2:
+ * - ENABLE: 'Stop' command will effect on channel 2
+ * - DISABLE: 'Stop' command will not effect on channel 2
+ * @return None
+ **********************************************************************/
+void MCPWM_Stop(LPC_MCPWM_TypeDef *MCPWMx, uint32_t channel0,
+ uint32_t channel1, uint32_t channel2)
+{
+ uint32_t regVal = 0;
+ regVal = (channel0 ? MCPWM_CON_RUN(0) : 0) | (channel1 ? MCPWM_CON_RUN(1) : 0) \
+ | (channel2 ? MCPWM_CON_RUN(2) : 0);
+ MCPWMx->MCCON_CLR = regVal;
+}
+
+
+/*********************************************************************//**
+ * @brief Enables/Disables 3-phase AC motor mode on MCPWM peripheral
+ * @param[in] MCPWMx Motor Control PWM peripheral selected
+ * Should be: LPC_MCPWM
+ * @param[in] acMode State of this command, should be:
+ * - ENABLE.
+ * - DISABLE.
+ * @return None
+ **********************************************************************/
+void MCPWM_ACMode(LPC_MCPWM_TypeDef *MCPWMx, uint32_t acMode)
+{
+ if (acMode){
+ MCPWMx->MCCON_SET = MCPWM_CON_ACMODE;
+ } else {
+ MCPWMx->MCCON_CLR = MCPWM_CON_ACMODE;
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Enables/Disables 3-phase DC motor mode on MCPWM peripheral
+ * @param[in] MCPWMx Motor Control PWM peripheral selected
+ * Should be: LPC_MCPWM
+ * @param[in] dcMode State of this command, should be:
+ * - ENABLE.
+ * - DISABLE.
+ * @param[in] outputInvered Polarity of the MCOB outputs for all 3 channels,
+ * should be:
+ * - ENABLE: The MCOB outputs have opposite polarity
+ * from the MCOA outputs.
+ * - DISABLE: The MCOB outputs have the same basic
+ * polarity as the MCOA outputs.
+ * @param[in] outputPattern A value contains bits that enables/disables the specified
+ * output pins route to the internal MCOA0 signal, should be:
+ - MCPWM_PATENT_A0: MCOA0 tracks internal MCOA0
+ - MCPWM_PATENT_B0: MCOB0 tracks internal MCOA0
+ - MCPWM_PATENT_A1: MCOA1 tracks internal MCOA0
+ - MCPWM_PATENT_B1: MCOB1 tracks internal MCOA0
+ - MCPWM_PATENT_A2: MCOA2 tracks internal MCOA0
+ - MCPWM_PATENT_B2: MCOB2 tracks internal MCOA0
+ * @return None
+ *
+ * Note: all these outputPatent values above can be ORed together for using as input parameter.
+ **********************************************************************/
+void MCPWM_DCMode(LPC_MCPWM_TypeDef *MCPWMx, uint32_t dcMode,
+ uint32_t outputInvered, uint32_t outputPattern)
+{
+ if (dcMode){
+ MCPWMx->MCCON_SET = MCPWM_CON_DCMODE;
+ } else {
+ MCPWMx->MCCON_CLR = MCPWM_CON_DCMODE;
+ }
+
+ if (outputInvered) {
+ MCPWMx->MCCON_SET = MCPWM_CON_INVBDC;
+ } else {
+ MCPWMx->MCCON_CLR = MCPWM_CON_INVBDC;
+ }
+
+ MCPWMx->MCCCP = outputPattern;
+}
+
+
+/*********************************************************************//**
+ * @brief Configures the specified interrupt in MCPWM peripheral
+ * @param[in] MCPWMx Motor Control PWM peripheral selected
+ * Should be: LPC_MCPWM
+ * @param[in] ulIntType Interrupt type, should be:
+ * - MCPWM_INTFLAG_LIM0: Limit interrupt for channel (0)
+ * - MCPWM_INTFLAG_MAT0: Match interrupt for channel (0)
+ * - MCPWM_INTFLAG_CAP0: Capture interrupt for channel (0)
+ * - MCPWM_INTFLAG_LIM1: Limit interrupt for channel (1)
+ * - MCPWM_INTFLAG_MAT1: Match interrupt for channel (1)
+ * - MCPWM_INTFLAG_CAP1: Capture interrupt for channel (1)
+ * - MCPWM_INTFLAG_LIM2: Limit interrupt for channel (2)
+ * - MCPWM_INTFLAG_MAT2: Match interrupt for channel (2)
+ * - MCPWM_INTFLAG_CAP2: Capture interrupt for channel (2)
+ * - MCPWM_INTFLAG_ABORT: Fast abort interrupt
+ * @param[in] NewState New State of this command, should be:
+ * - ENABLE.
+ * - DISABLE.
+ * @return None
+ *
+ * Note: all these ulIntType values above can be ORed together for using as input parameter.
+ **********************************************************************/
+void MCPWM_IntConfig(LPC_MCPWM_TypeDef *MCPWMx, uint32_t ulIntType, FunctionalState NewState)
+{
+ if (NewState) {
+ MCPWMx->MCINTEN_SET = ulIntType;
+ } else {
+ MCPWMx->MCINTEN_CLR = ulIntType;
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Sets/Forces the specified interrupt for MCPWM peripheral
+ * @param[in] MCPWMx Motor Control PWM peripheral selected
+ * Should be LPC_MCPWM
+ * @param[in] ulIntType Interrupt type, should be:
+ * - MCPWM_INTFLAG_LIM0: Limit interrupt for channel (0)
+ * - MCPWM_INTFLAG_MAT0: Match interrupt for channel (0)
+ * - MCPWM_INTFLAG_CAP0: Capture interrupt for channel (0)
+ * - MCPWM_INTFLAG_LIM1: Limit interrupt for channel (1)
+ * - MCPWM_INTFLAG_MAT1: Match interrupt for channel (1)
+ * - MCPWM_INTFLAG_CAP1: Capture interrupt for channel (1)
+ * - MCPWM_INTFLAG_LIM2: Limit interrupt for channel (2)
+ * - MCPWM_INTFLAG_MAT2: Match interrupt for channel (2)
+ * - MCPWM_INTFLAG_CAP2: Capture interrupt for channel (2)
+ * - MCPWM_INTFLAG_ABORT: Fast abort interrupt
+ * @return None
+ * Note: all these ulIntType values above can be ORed together for using as input parameter.
+ **********************************************************************/
+void MCPWM_IntSet(LPC_MCPWM_TypeDef *MCPWMx, uint32_t ulIntType)
+{
+ MCPWMx->MCINTFLAG_SET = ulIntType;
+}
+
+
+/*********************************************************************//**
+ * @brief Clear the specified interrupt pending for MCPWM peripheral
+ * @param[in] MCPWMx Motor Control PWM peripheral selected,
+ * should be: LPC_MCPWM
+ * @param[in] ulIntType Interrupt type, should be:
+ * - MCPWM_INTFLAG_LIM0: Limit interrupt for channel (0)
+ * - MCPWM_INTFLAG_MAT0: Match interrupt for channel (0)
+ * - MCPWM_INTFLAG_CAP0: Capture interrupt for channel (0)
+ * - MCPWM_INTFLAG_LIM1: Limit interrupt for channel (1)
+ * - MCPWM_INTFLAG_MAT1: Match interrupt for channel (1)
+ * - MCPWM_INTFLAG_CAP1: Capture interrupt for channel (1)
+ * - MCPWM_INTFLAG_LIM2: Limit interrupt for channel (2)
+ * - MCPWM_INTFLAG_MAT2: Match interrupt for channel (2)
+ * - MCPWM_INTFLAG_CAP2: Capture interrupt for channel (2)
+ * - MCPWM_INTFLAG_ABORT: Fast abort interrupt
+ * @return None
+ * Note: all these ulIntType values above can be ORed together for using as input parameter.
+ **********************************************************************/
+void MCPWM_IntClear(LPC_MCPWM_TypeDef *MCPWMx, uint32_t ulIntType)
+{
+ MCPWMx->MCINTFLAG_CLR = ulIntType;
+}
+
+
+/*********************************************************************//**
+ * @brief Check whether if the specified interrupt in MCPWM is set or not
+ * @param[in] MCPWMx Motor Control PWM peripheral selected,
+ * should be: LPC_MCPWM
+ * @param[in] ulIntType Interrupt type, should be:
+ * - MCPWM_INTFLAG_LIM0: Limit interrupt for channel (0)
+ * - MCPWM_INTFLAG_MAT0: Match interrupt for channel (0)
+ * - MCPWM_INTFLAG_CAP0: Capture interrupt for channel (0)
+ * - MCPWM_INTFLAG_LIM1: Limit interrupt for channel (1)
+ * - MCPWM_INTFLAG_MAT1: Match interrupt for channel (1)
+ * - MCPWM_INTFLAG_CAP1: Capture interrupt for channel (1)
+ * - MCPWM_INTFLAG_LIM2: Limit interrupt for channel (2)
+ * - MCPWM_INTFLAG_MAT2: Match interrupt for channel (2)
+ * - MCPWM_INTFLAG_CAP2: Capture interrupt for channel (2)
+ * - MCPWM_INTFLAG_ABORT: Fast abort interrupt
+ * @return None
+ **********************************************************************/
+FlagStatus MCPWM_GetIntStatus(LPC_MCPWM_TypeDef *MCPWMx, uint32_t ulIntType)
+{
+ return ((MCPWMx->MCINTFLAG & ulIntType) ? SET : RESET);
+}
+
+/**
+ * @}
+ */
+
+#endif /* _MCPWM */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_nvic.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_nvic.c
new file mode 100644
index 0000000..fba9177
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_nvic.c
@@ -0,0 +1,136 @@
+/***********************************************************************//**
+ * @file lpc17xx_nvic.c
+ * @brief Contains all expansion functions support for
+ * NVIC firmware library on LPC17xx. The main
+ * NVIC functions are defined in core_cm3.h
+ * @version 2.0
+ * @date 21. May. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup NVIC
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_nvic.h"
+
+
+/* Private Macros ------------------------------------------------------------- */
+/** @addtogroup NVIC_Private_Macros
+ * @{
+ */
+
+/* Vector table offset bit mask */
+#define NVIC_VTOR_MASK 0x3FFFFF80
+
+/**
+ * @}
+ */
+
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup NVIC_Public_Functions
+ * @{
+ */
+
+
+/*****************************************************************************//**
+ * @brief De-initializes the NVIC peripheral registers to their default
+ * reset values.
+ * @param None
+ * @return None
+ *
+ * These following NVIC peripheral registers will be de-initialized:
+ * - Disable Interrupt (32 IRQ interrupt sources that matched with LPC17xx)
+ * - Clear all Pending Interrupts (32 IRQ interrupt source that matched with LPC17xx)
+ * - Clear all Interrupt Priorities (32 IRQ interrupt source that matched with LPC17xx)
+ *******************************************************************************/
+void NVIC_DeInit(void)
+{
+ uint8_t tmp;
+
+ /* Disable all interrupts */
+ NVIC->ICER[0] = 0xFFFFFFFF;
+ NVIC->ICER[1] = 0x00000001;
+ /* Clear all pending interrupts */
+ NVIC->ICPR[0] = 0xFFFFFFFF;
+ NVIC->ICPR[1] = 0x00000001;
+
+ /* Clear all interrupt priority */
+ for (tmp = 0; tmp < 32; tmp++) {
+ NVIC->IP[tmp] = 0x00;
+ }
+}
+
+/*****************************************************************************//**
+ * @brief De-initializes the SCB peripheral registers to their default
+ * reset values.
+ * @param none
+ * @return none
+ *
+ * These following SCB NVIC peripheral registers will be de-initialized:
+ * - Interrupt Control State register
+ * - Interrupt Vector Table Offset register
+ * - Application Interrupt/Reset Control register
+ * - System Control register
+ * - Configuration Control register
+ * - System Handlers Priority Registers
+ * - System Handler Control and State Register
+ * - Configurable Fault Status Register
+ * - Hard Fault Status Register
+ * - Debug Fault Status Register
+ *******************************************************************************/
+void NVIC_SCBDeInit(void)
+{
+ uint8_t tmp;
+
+ SCB->ICSR = 0x0A000000;
+ SCB->VTOR = 0x00000000;
+ SCB->AIRCR = 0x05FA0000;
+ SCB->SCR = 0x00000000;
+ SCB->CCR = 0x00000000;
+
+ for (tmp = 0; tmp < 32; tmp++) {
+ SCB->SHP[tmp] = 0x00;
+ }
+
+ SCB->SHCSR = 0x00000000;
+ SCB->CFSR = 0xFFFFFFFF;
+ SCB->HFSR = 0xFFFFFFFF;
+ SCB->DFSR = 0xFFFFFFFF;
+}
+
+
+/*****************************************************************************//**
+ * @brief Set Vector Table Offset value
+ * @param offset Offset value
+ * @return None
+ *******************************************************************************/
+void NVIC_SetVTOR(uint32_t offset)
+{
+// SCB->VTOR = (offset & NVIC_VTOR_MASK);
+ SCB->VTOR = offset;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_pinsel.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_pinsel.c
new file mode 100644
index 0000000..8361ec4
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_pinsel.c
@@ -0,0 +1,306 @@
+/***********************************************************************//**
+ * @file lpc17xx_pinsel.c
+ * @brief Contains all functions support for Pin connect block firmware
+ * library on LPC17xx
+ * @version 2.0
+ * @date 21. May. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup PINSEL
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_pinsel.h"
+
+/* Public Functions ----------------------------------------------------------- */
+
+static void set_PinFunc ( uint8_t portnum, uint8_t pinnum, uint8_t funcnum);
+static void set_ResistorMode ( uint8_t portnum, uint8_t pinnum, uint8_t modenum);
+static void set_OpenDrainMode( uint8_t portnum, uint8_t pinnum, uint8_t modenum);
+
+/*********************************************************************//**
+ * @brief Setup the pin selection function
+ * @param[in] portnum PORT number,
+ * should be one of the following:
+ * - PINSEL_PORT_0 : Port 0
+ * - PINSEL_PORT_1 : Port 1
+ * - PINSEL_PORT_2 : Port 2
+ * - PINSEL_PORT_3 : Port 3
+ *
+ * @param[in] pinnum Pin number,
+ * should be one of the following:
+ - PINSEL_PIN_0 : Pin 0
+ - PINSEL_PIN_1 : Pin 1
+ - PINSEL_PIN_2 : Pin 2
+ - PINSEL_PIN_3 : Pin 3
+ - PINSEL_PIN_4 : Pin 4
+ - PINSEL_PIN_5 : Pin 5
+ - PINSEL_PIN_6 : Pin 6
+ - PINSEL_PIN_7 : Pin 7
+ - PINSEL_PIN_8 : Pin 8
+ - PINSEL_PIN_9 : Pin 9
+ - PINSEL_PIN_10 : Pin 10
+ - PINSEL_PIN_11 : Pin 11
+ - PINSEL_PIN_12 : Pin 12
+ - PINSEL_PIN_13 : Pin 13
+ - PINSEL_PIN_14 : Pin 14
+ - PINSEL_PIN_15 : Pin 15
+ - PINSEL_PIN_16 : Pin 16
+ - PINSEL_PIN_17 : Pin 17
+ - PINSEL_PIN_18 : Pin 18
+ - PINSEL_PIN_19 : Pin 19
+ - PINSEL_PIN_20 : Pin 20
+ - PINSEL_PIN_21 : Pin 21
+ - PINSEL_PIN_22 : Pin 22
+ - PINSEL_PIN_23 : Pin 23
+ - PINSEL_PIN_24 : Pin 24
+ - PINSEL_PIN_25 : Pin 25
+ - PINSEL_PIN_26 : Pin 26
+ - PINSEL_PIN_27 : Pin 27
+ - PINSEL_PIN_28 : Pin 28
+ - PINSEL_PIN_29 : Pin 29
+ - PINSEL_PIN_30 : Pin 30
+ - PINSEL_PIN_31 : Pin 31
+
+ * @param[in] funcnum Function number,
+ * should be one of the following:
+ * - PINSEL_FUNC_0 : default function
+ * - PINSEL_FUNC_1 : first alternate function
+ * - PINSEL_FUNC_2 : second alternate function
+ * - PINSEL_FUNC_3 : third alternate function
+ *
+ * @return None
+ **********************************************************************/
+static void set_PinFunc ( uint8_t portnum, uint8_t pinnum, uint8_t funcnum)
+{
+ uint32_t pinnum_t = pinnum;
+ uint32_t pinselreg_idx = 2 * portnum;
+ uint32_t *pPinCon = (uint32_t *)&LPC_PINCON->PINSEL0;
+
+ if (pinnum_t >= 16) {
+ pinnum_t -= 16;
+ pinselreg_idx++;
+ }
+ *(uint32_t *)(pPinCon + pinselreg_idx) &= ~(0x03UL << (pinnum_t * 2));
+ *(uint32_t *)(pPinCon + pinselreg_idx) |= ((uint32_t)funcnum) << (pinnum_t * 2);
+}
+
+/*********************************************************************//**
+ * @brief Setup resistor mode for each pin
+ * @param[in] portnum PORT number,
+ * should be one of the following:
+ * - PINSEL_PORT_0 : Port 0
+ * - PINSEL_PORT_1 : Port 1
+ * - PINSEL_PORT_2 : Port 2
+ * - PINSEL_PORT_3 : Port 3
+ * @param[in] pinnum Pin number,
+ * should be one of the following:
+ - PINSEL_PIN_0 : Pin 0
+ - PINSEL_PIN_1 : Pin 1
+ - PINSEL_PIN_2 : Pin 2
+ - PINSEL_PIN_3 : Pin 3
+ - PINSEL_PIN_4 : Pin 4
+ - PINSEL_PIN_5 : Pin 5
+ - PINSEL_PIN_6 : Pin 6
+ - PINSEL_PIN_7 : Pin 7
+ - PINSEL_PIN_8 : Pin 8
+ - PINSEL_PIN_9 : Pin 9
+ - PINSEL_PIN_10 : Pin 10
+ - PINSEL_PIN_11 : Pin 11
+ - PINSEL_PIN_12 : Pin 12
+ - PINSEL_PIN_13 : Pin 13
+ - PINSEL_PIN_14 : Pin 14
+ - PINSEL_PIN_15 : Pin 15
+ - PINSEL_PIN_16 : Pin 16
+ - PINSEL_PIN_17 : Pin 17
+ - PINSEL_PIN_18 : Pin 18
+ - PINSEL_PIN_19 : Pin 19
+ - PINSEL_PIN_20 : Pin 20
+ - PINSEL_PIN_21 : Pin 21
+ - PINSEL_PIN_22 : Pin 22
+ - PINSEL_PIN_23 : Pin 23
+ - PINSEL_PIN_24 : Pin 24
+ - PINSEL_PIN_25 : Pin 25
+ - PINSEL_PIN_26 : Pin 26
+ - PINSEL_PIN_27 : Pin 27
+ - PINSEL_PIN_28 : Pin 28
+ - PINSEL_PIN_29 : Pin 29
+ - PINSEL_PIN_30 : Pin 30
+ - PINSEL_PIN_31 : Pin 31
+
+ * @param[in] modenum: Mode number,
+ * should be one of the following:
+ - PINSEL_PINMODE_PULLUP : Internal pull-up resistor
+ - PINSEL_PINMODE_TRISTATE : Tri-state
+ - PINSEL_PINMODE_PULLDOWN : Internal pull-down resistor
+
+ * @return None
+ **********************************************************************/
+void set_ResistorMode ( uint8_t portnum, uint8_t pinnum, uint8_t modenum)
+{
+ uint32_t pinnum_t = pinnum;
+ uint32_t pinmodereg_idx = 2 * portnum;
+ uint32_t *pPinCon = (uint32_t *)&LPC_PINCON->PINMODE0;
+
+ if (pinnum_t >= 16) {
+ pinnum_t -= 16;
+ pinmodereg_idx++ ;
+ }
+
+ *(uint32_t *)(pPinCon + pinmodereg_idx) &= ~(0x03UL << (pinnum_t * 2));
+ *(uint32_t *)(pPinCon + pinmodereg_idx) |= ((uint32_t)modenum) << (pinnum_t * 2);
+}
+
+/*********************************************************************//**
+ * @brief Setup Open drain mode for each pin
+ * @param[in] portnum PORT number,
+ * should be one of the following:
+ * - PINSEL_PORT_0 : Port 0
+ * - PINSEL_PORT_1 : Port 1
+ * - PINSEL_PORT_2 : Port 2
+ * - PINSEL_PORT_3 : Port 3
+ *
+ * @param[in] pinnum Pin number,
+ * should be one of the following:
+ - PINSEL_PIN_0 : Pin 0
+ - PINSEL_PIN_1 : Pin 1
+ - PINSEL_PIN_2 : Pin 2
+ - PINSEL_PIN_3 : Pin 3
+ - PINSEL_PIN_4 : Pin 4
+ - PINSEL_PIN_5 : Pin 5
+ - PINSEL_PIN_6 : Pin 6
+ - PINSEL_PIN_7 : Pin 7
+ - PINSEL_PIN_8 : Pin 8
+ - PINSEL_PIN_9 : Pin 9
+ - PINSEL_PIN_10 : Pin 10
+ - PINSEL_PIN_11 : Pin 11
+ - PINSEL_PIN_12 : Pin 12
+ - PINSEL_PIN_13 : Pin 13
+ - PINSEL_PIN_14 : Pin 14
+ - PINSEL_PIN_15 : Pin 15
+ - PINSEL_PIN_16 : Pin 16
+ - PINSEL_PIN_17 : Pin 17
+ - PINSEL_PIN_18 : Pin 18
+ - PINSEL_PIN_19 : Pin 19
+ - PINSEL_PIN_20 : Pin 20
+ - PINSEL_PIN_21 : Pin 21
+ - PINSEL_PIN_22 : Pin 22
+ - PINSEL_PIN_23 : Pin 23
+ - PINSEL_PIN_24 : Pin 24
+ - PINSEL_PIN_25 : Pin 25
+ - PINSEL_PIN_26 : Pin 26
+ - PINSEL_PIN_27 : Pin 27
+ - PINSEL_PIN_28 : Pin 28
+ - PINSEL_PIN_29 : Pin 29
+ - PINSEL_PIN_30 : Pin 30
+ - PINSEL_PIN_31 : Pin 31
+
+ * @param[in] modenum Open drain mode number,
+ * should be one of the following:
+ * - PINSEL_PINMODE_NORMAL : Pin is in the normal (not open drain) mode
+ * - PINSEL_PINMODE_OPENDRAIN : Pin is in the open drain mode
+ *
+ * @return None
+ **********************************************************************/
+void set_OpenDrainMode( uint8_t portnum, uint8_t pinnum, uint8_t modenum)
+{
+ uint32_t *pPinCon = (uint32_t *)&LPC_PINCON->PINMODE_OD0;
+
+ if (modenum == PINSEL_PINMODE_OPENDRAIN){
+ *(uint32_t *)(pPinCon + portnum) |= (0x01UL << pinnum);
+ } else {
+ *(uint32_t *)(pPinCon + portnum) &= ~(0x01UL << pinnum);
+ }
+}
+
+/* End of Public Functions ---------------------------------------------------- */
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup PINSEL_Public_Functions
+ * @{
+ */
+/*********************************************************************//**
+ * @brief Configure trace function
+ * @param[in] NewState State of the Trace function configuration,
+ * should be one of the following:
+ * - ENABLE : Enable Trace Function
+ * - DISABLE : Disable Trace Function
+ *
+ * @return None
+ **********************************************************************/
+void PINSEL_ConfigTraceFunc(FunctionalState NewState)
+{
+ if (NewState == ENABLE) {
+ LPC_PINCON->PINSEL10 |= (0x01UL << 3);
+ } else if (NewState == DISABLE) {
+ LPC_PINCON->PINSEL10 &= ~(0x01UL << 3);
+ }
+}
+
+/*********************************************************************//**
+ * @brief Setup I2C0 pins
+ * @param[in] i2cPinMode I2C pin mode,
+ * should be one of the following:
+ * - PINSEL_I2C_Normal_Mode : The standard drive mode
+ * - PINSEL_I2C_Fast_Mode : Fast Mode Plus drive mode
+ *
+ * @param[in] filterSlewRateEnable should be:
+ * - ENABLE: Enable filter and slew rate.
+ * - DISABLE: Disable filter and slew rate.
+ *
+ * @return None
+ **********************************************************************/
+void PINSEL_SetI2C0Pins(uint8_t i2cPinMode, FunctionalState filterSlewRateEnable)
+{
+ uint32_t regVal;
+
+ if (i2cPinMode == PINSEL_I2C_Fast_Mode){
+ regVal = PINSEL_I2CPADCFG_SCLDRV0 | PINSEL_I2CPADCFG_SDADRV0;
+ }
+
+ if (filterSlewRateEnable == DISABLE){
+ regVal = PINSEL_I2CPADCFG_SCLI2C0 | PINSEL_I2CPADCFG_SDAI2C0;
+ }
+ LPC_PINCON->I2CPADCFG = regVal;
+}
+
+
+/*********************************************************************//**
+ * @brief Configure Pin corresponding to specified parameters passed
+ * in the PinCfg
+ * @param[in] PinCfg Pointer to a PINSEL_CFG_Type structure
+ * that contains the configuration information for the
+ * specified pin.
+ * @return None
+ **********************************************************************/
+void PINSEL_ConfigPin(PINSEL_CFG_Type *PinCfg)
+{
+ set_PinFunc(PinCfg->Portnum, PinCfg->Pinnum, PinCfg->Funcnum);
+ set_ResistorMode(PinCfg->Portnum, PinCfg->Pinnum, PinCfg->Pinmode);
+ set_OpenDrainMode(PinCfg->Portnum, PinCfg->Pinnum, PinCfg->OpenDrain);
+}
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_pwm.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_pwm.c
new file mode 100644
index 0000000..f11e99f
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_pwm.c
@@ -0,0 +1,533 @@
+/***********************************************************************//**
+ * @file lpc17xx_pwm.c
+ * @brief Contains all functions support for PWM firmware library on LPC17xx
+ * @version 2.0
+ * @date 21. May. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup PWM
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_pwm.h"
+#include "lpc17xx_clkpwr.h"
+
+/* If this source file built with example, the LPC17xx FW library configuration
+ * file in each example directory ("lpc17xx_libcfg.h") must be included,
+ * otherwise the default FW library configuration file must be included instead
+ */
+#ifdef __BUILD_WITH_EXAMPLE__
+#include "lpc17xx_libcfg.h"
+#else
+#include "lpc17xx_libcfg_default.h"
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+
+#ifdef _PWM
+
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup PWM_Public_Functions
+ * @{
+ */
+
+
+/*********************************************************************//**
+ * @brief Check whether specified interrupt flag in PWM is set or not
+ * @param[in] PWMx: PWM peripheral, should be LPC_PWM1
+ * @param[in] IntFlag: PWM interrupt flag, should be:
+ * - PWM_INTSTAT_MR0: Interrupt flag for PWM match channel 0
+ * - PWM_INTSTAT_MR1: Interrupt flag for PWM match channel 1
+ * - PWM_INTSTAT_MR2: Interrupt flag for PWM match channel 2
+ * - PWM_INTSTAT_MR3: Interrupt flag for PWM match channel 3
+ * - PWM_INTSTAT_MR4: Interrupt flag for PWM match channel 4
+ * - PWM_INTSTAT_MR5: Interrupt flag for PWM match channel 5
+ * - PWM_INTSTAT_MR6: Interrupt flag for PWM match channel 6
+ * - PWM_INTSTAT_CAP0: Interrupt flag for capture input 0
+ * - PWM_INTSTAT_CAP1: Interrupt flag for capture input 1
+ * @return New State of PWM interrupt flag (SET or RESET)
+ **********************************************************************/
+IntStatus PWM_GetIntStatus(LPC_PWM_TypeDef *PWMx, uint32_t IntFlag)
+{
+ CHECK_PARAM(PARAM_PWMx(PWMx));
+ CHECK_PARAM(PARAM_PWM_INTSTAT(IntFlag));
+
+ return ((PWMx->IR & IntFlag) ? SET : RESET);
+}
+
+
+
+/*********************************************************************//**
+ * @brief Clear specified PWM Interrupt pending
+ * @param[in] PWMx: PWM peripheral, should be LPC_PWM1
+ * @param[in] IntFlag: PWM interrupt flag, should be:
+ * - PWM_INTSTAT_MR0: Interrupt flag for PWM match channel 0
+ * - PWM_INTSTAT_MR1: Interrupt flag for PWM match channel 1
+ * - PWM_INTSTAT_MR2: Interrupt flag for PWM match channel 2
+ * - PWM_INTSTAT_MR3: Interrupt flag for PWM match channel 3
+ * - PWM_INTSTAT_MR4: Interrupt flag for PWM match channel 4
+ * - PWM_INTSTAT_MR5: Interrupt flag for PWM match channel 5
+ * - PWM_INTSTAT_MR6: Interrupt flag for PWM match channel 6
+ * - PWM_INTSTAT_CAP0: Interrupt flag for capture input 0
+ * - PWM_INTSTAT_CAP1: Interrupt flag for capture input 1
+ * @return None
+ **********************************************************************/
+void PWM_ClearIntPending(LPC_PWM_TypeDef *PWMx, uint32_t IntFlag)
+{
+ CHECK_PARAM(PARAM_PWMx(PWMx));
+ CHECK_PARAM(PARAM_PWM_INTSTAT(IntFlag));
+ PWMx->IR = IntFlag;
+}
+
+
+
+/*****************************************************************************//**
+* @brief Fills each PWM_InitStruct member with its default value:
+* - If PWMCounterMode = PWM_MODE_TIMER:
+* + PrescaleOption = PWM_TIMER_PRESCALE_USVAL
+* + PrescaleValue = 1
+* - If PWMCounterMode = PWM_MODE_COUNTER:
+* + CountInputSelect = PWM_COUNTER_PCAP1_0
+* + CounterOption = PWM_COUNTER_RISING
+* @param[in] PWMTimerCounterMode Timer or Counter mode, should be:
+* - PWM_MODE_TIMER: Counter of PWM peripheral is in Timer mode
+* - PWM_MODE_COUNTER: Counter of PWM peripheral is in Counter mode
+* @param[in] PWM_InitStruct Pointer to structure (PWM_TIMERCFG_Type or
+* PWM_COUNTERCFG_Type) which will be initialized.
+* @return None
+* Note: PWM_InitStruct pointer will be assigned to corresponding structure
+* (PWM_TIMERCFG_Type or PWM_COUNTERCFG_Type) due to PWMTimerCounterMode.
+*******************************************************************************/
+void PWM_ConfigStructInit(uint8_t PWMTimerCounterMode, void *PWM_InitStruct)
+{
+ PWM_TIMERCFG_Type *pTimeCfg;
+ PWM_COUNTERCFG_Type *pCounterCfg;
+ CHECK_PARAM(PARAM_PWM_TC_MODE(PWMTimerCounterMode));
+
+ pTimeCfg = (PWM_TIMERCFG_Type *) PWM_InitStruct;
+ pCounterCfg = (PWM_COUNTERCFG_Type *) PWM_InitStruct;
+
+ if (PWMTimerCounterMode == PWM_MODE_TIMER )
+ {
+ pTimeCfg->PrescaleOption = PWM_TIMER_PRESCALE_USVAL;
+ pTimeCfg->PrescaleValue = 1;
+ }
+ else if (PWMTimerCounterMode == PWM_MODE_COUNTER)
+ {
+ pCounterCfg->CountInputSelect = PWM_COUNTER_PCAP1_0;
+ pCounterCfg->CounterOption = PWM_COUNTER_RISING;
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Initializes the PWMx peripheral corresponding to the specified
+ * parameters in the PWM_ConfigStruct.
+ * @param[in] PWMx PWM peripheral, should be LPC_PWM1
+ * @param[in] PWMTimerCounterMode Timer or Counter mode, should be:
+ * - PWM_MODE_TIMER: Counter of PWM peripheral is in Timer mode
+ * - PWM_MODE_COUNTER: Counter of PWM peripheral is in Counter mode
+ * @param[in] PWM_ConfigStruct Pointer to structure (PWM_TIMERCFG_Type or
+ * PWM_COUNTERCFG_Type) which will be initialized.
+ * @return None
+ * Note: PWM_ConfigStruct pointer will be assigned to corresponding structure
+ * (PWM_TIMERCFG_Type or PWM_COUNTERCFG_Type) due to PWMTimerCounterMode.
+ **********************************************************************/
+void PWM_Init(LPC_PWM_TypeDef *PWMx, uint32_t PWMTimerCounterMode, void *PWM_ConfigStruct)
+{
+ PWM_TIMERCFG_Type *pTimeCfg;
+ PWM_COUNTERCFG_Type *pCounterCfg;
+ uint64_t clkdlycnt;
+
+ CHECK_PARAM(PARAM_PWMx(PWMx));
+ CHECK_PARAM(PARAM_PWM_TC_MODE(PWMTimerCounterMode));
+
+ pTimeCfg = (PWM_TIMERCFG_Type *)PWM_ConfigStruct;
+ pCounterCfg = (PWM_COUNTERCFG_Type *)PWM_ConfigStruct;
+
+
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCPWM1, ENABLE);
+ CLKPWR_SetPCLKDiv (CLKPWR_PCLKSEL_PWM1, CLKPWR_PCLKSEL_CCLK_DIV_4);
+ // Get peripheral clock of PWM1
+ clkdlycnt = (uint64_t) CLKPWR_GetPCLK (CLKPWR_PCLKSEL_PWM1);
+
+
+ // Clear all interrupts pending
+ PWMx->IR = 0xFF & PWM_IR_BITMASK;
+ PWMx->TCR = 0x00;
+ PWMx->CTCR = 0x00;
+ PWMx->MCR = 0x00;
+ PWMx->CCR = 0x00;
+ PWMx->PCR = 0x00;
+ PWMx->LER = 0x00;
+
+ if (PWMTimerCounterMode == PWM_MODE_TIMER)
+ {
+ CHECK_PARAM(PARAM_PWM_TIMER_PRESCALE(pTimeCfg->PrescaleOption));
+
+ /* Absolute prescale value */
+ if (pTimeCfg->PrescaleOption == PWM_TIMER_PRESCALE_TICKVAL)
+ {
+ PWMx->PR = pTimeCfg->PrescaleValue - 1;
+ }
+ /* uSecond prescale value */
+ else
+ {
+ clkdlycnt = (clkdlycnt * pTimeCfg->PrescaleValue) / 1000000;
+ PWMx->PR = ((uint32_t) clkdlycnt) - 1;
+ }
+
+ }
+ else if (PWMTimerCounterMode == PWM_MODE_COUNTER)
+ {
+ CHECK_PARAM(PARAM_PWM_COUNTER_INPUTSEL(pCounterCfg->CountInputSelect));
+ CHECK_PARAM(PARAM_PWM_COUNTER_EDGE(pCounterCfg->CounterOption));
+
+ PWMx->CTCR |= (PWM_CTCR_MODE((uint32_t)pCounterCfg->CounterOption)) \
+ | (PWM_CTCR_SELECT_INPUT((uint32_t)pCounterCfg->CountInputSelect));
+ }
+}
+
+/*********************************************************************//**
+ * @brief De-initializes the PWM peripheral registers to their
+* default reset values.
+ * @param[in] PWMx PWM peripheral selected, should be LPC_PWM1
+ * @return None
+ **********************************************************************/
+void PWM_DeInit (LPC_PWM_TypeDef *PWMx)
+{
+ CHECK_PARAM(PARAM_PWMx(PWMx));
+
+ // Disable PWM control (timer, counter and PWM)
+ PWMx->TCR = 0x00;
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCPWM1, DISABLE);
+
+}
+
+
+/*********************************************************************//**
+ * @brief Enable/Disable PWM peripheral
+ * @param[in] PWMx PWM peripheral selected, should be LPC_PWM1
+ * @param[in] NewState New State of this function, should be:
+ * - ENABLE: Enable PWM peripheral
+ * - DISABLE: Disable PWM peripheral
+ * @return None
+ **********************************************************************/
+void PWM_Cmd(LPC_PWM_TypeDef *PWMx, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_PWMx(PWMx));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ if (NewState == ENABLE)
+ {
+ PWMx->TCR |= PWM_TCR_PWM_ENABLE;
+ }
+ else
+ {
+ PWMx->TCR &= (~PWM_TCR_PWM_ENABLE) & PWM_TCR_BITMASK;
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Enable/Disable Counter in PWM peripheral
+ * @param[in] PWMx PWM peripheral selected, should be LPC_PWM1
+ * @param[in] NewState New State of this function, should be:
+ * - ENABLE: Enable Counter in PWM peripheral
+ * - DISABLE: Disable Counter in PWM peripheral
+ * @return None
+ **********************************************************************/
+void PWM_CounterCmd(LPC_PWM_TypeDef *PWMx, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_PWMx(PWMx));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+ if (NewState == ENABLE)
+ {
+ PWMx->TCR |= PWM_TCR_COUNTER_ENABLE;
+ }
+ else
+ {
+ PWMx->TCR &= (~PWM_TCR_COUNTER_ENABLE) & PWM_TCR_BITMASK;
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Reset Counter in PWM peripheral
+ * @param[in] PWMx PWM peripheral selected, should be LPC_PWM1
+ * @return None
+ **********************************************************************/
+void PWM_ResetCounter(LPC_PWM_TypeDef *PWMx)
+{
+ CHECK_PARAM(PARAM_PWMx(PWMx));
+ PWMx->TCR |= PWM_TCR_COUNTER_RESET;
+ PWMx->TCR &= (~PWM_TCR_COUNTER_RESET) & PWM_TCR_BITMASK;
+}
+
+
+/*********************************************************************//**
+ * @brief Configures match for PWM peripheral
+ * @param[in] PWMx PWM peripheral selected, should be LPC_PWM1
+ * @param[in] PWM_MatchConfigStruct Pointer to a PWM_MATCHCFG_Type structure
+* that contains the configuration information for the
+* specified PWM match function.
+ * @return None
+ **********************************************************************/
+void PWM_ConfigMatch(LPC_PWM_TypeDef *PWMx, PWM_MATCHCFG_Type *PWM_MatchConfigStruct)
+{
+ CHECK_PARAM(PARAM_PWMx(PWMx));
+ CHECK_PARAM(PARAM_PWM1_MATCH_CHANNEL(PWM_MatchConfigStruct->MatchChannel));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(PWM_MatchConfigStruct->IntOnMatch));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(PWM_MatchConfigStruct->ResetOnMatch));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(PWM_MatchConfigStruct->StopOnMatch));
+
+ //interrupt on MRn
+ if (PWM_MatchConfigStruct->IntOnMatch == ENABLE)
+ {
+ PWMx->MCR |= PWM_MCR_INT_ON_MATCH(PWM_MatchConfigStruct->MatchChannel);
+ }
+ else
+ {
+ PWMx->MCR &= (~PWM_MCR_INT_ON_MATCH(PWM_MatchConfigStruct->MatchChannel)) \
+ & PWM_MCR_BITMASK;
+ }
+
+ //reset on MRn
+ if (PWM_MatchConfigStruct->ResetOnMatch == ENABLE)
+ {
+ PWMx->MCR |= PWM_MCR_RESET_ON_MATCH(PWM_MatchConfigStruct->MatchChannel);
+ }
+ else
+ {
+ PWMx->MCR &= (~PWM_MCR_RESET_ON_MATCH(PWM_MatchConfigStruct->MatchChannel)) \
+ & PWM_MCR_BITMASK;
+ }
+
+ //stop on MRn
+ if (PWM_MatchConfigStruct->StopOnMatch == ENABLE)
+ {
+ PWMx->MCR |= PWM_MCR_STOP_ON_MATCH(PWM_MatchConfigStruct->MatchChannel);
+ }
+ else
+ {
+ PWMx->MCR &= (~PWM_MCR_STOP_ON_MATCH(PWM_MatchConfigStruct->MatchChannel)) \
+ & PWM_MCR_BITMASK;
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Configures capture input for PWM peripheral
+ * @param[in] PWMx PWM peripheral selected, should be LPC_PWM1
+ * @param[in] PWM_CaptureConfigStruct Pointer to a PWM_CAPTURECFG_Type structure
+* that contains the configuration information for the
+* specified PWM capture input function.
+ * @return None
+ **********************************************************************/
+void PWM_ConfigCapture(LPC_PWM_TypeDef *PWMx, PWM_CAPTURECFG_Type *PWM_CaptureConfigStruct)
+{
+ CHECK_PARAM(PARAM_PWMx(PWMx));
+ CHECK_PARAM(PARAM_PWM1_CAPTURE_CHANNEL(PWM_CaptureConfigStruct->CaptureChannel));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(PWM_CaptureConfigStruct->FallingEdge));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(PWM_CaptureConfigStruct->IntOnCaption));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(PWM_CaptureConfigStruct->RisingEdge));
+
+ if (PWM_CaptureConfigStruct->RisingEdge == ENABLE)
+ {
+ PWMx->CCR |= PWM_CCR_CAP_RISING(PWM_CaptureConfigStruct->CaptureChannel);
+ }
+ else
+ {
+ PWMx->CCR &= (~PWM_CCR_CAP_RISING(PWM_CaptureConfigStruct->CaptureChannel)) \
+ & PWM_CCR_BITMASK;
+ }
+
+ if (PWM_CaptureConfigStruct->FallingEdge == ENABLE)
+ {
+ PWMx->CCR |= PWM_CCR_CAP_FALLING(PWM_CaptureConfigStruct->CaptureChannel);
+ }
+ else
+ {
+ PWMx->CCR &= (~PWM_CCR_CAP_FALLING(PWM_CaptureConfigStruct->CaptureChannel)) \
+ & PWM_CCR_BITMASK;
+ }
+
+ if (PWM_CaptureConfigStruct->IntOnCaption == ENABLE)
+ {
+ PWMx->CCR |= PWM_CCR_INT_ON_CAP(PWM_CaptureConfigStruct->CaptureChannel);
+ }
+ else
+ {
+ PWMx->CCR &= (~PWM_CCR_INT_ON_CAP(PWM_CaptureConfigStruct->CaptureChannel)) \
+ & PWM_CCR_BITMASK;
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Read value of capture register PWM peripheral
+ * @param[in] PWMx PWM peripheral selected, should be LPC_PWM1
+ * @param[in] CaptureChannel: capture channel number, should be in
+ * range 0 to 1
+ * @return Value of capture register
+ **********************************************************************/
+uint32_t PWM_GetCaptureValue(LPC_PWM_TypeDef *PWMx, uint8_t CaptureChannel)
+{
+ CHECK_PARAM(PARAM_PWMx(PWMx));
+ CHECK_PARAM(PARAM_PWM1_CAPTURE_CHANNEL(CaptureChannel));
+
+ switch (CaptureChannel)
+ {
+ case 0:
+ return PWMx->CR0;
+
+ case 1:
+ return PWMx->CR1;
+
+ default:
+ return (0);
+ }
+}
+
+
+/********************************************************************//**
+ * @brief Update value for each PWM channel with update type option
+ * @param[in] PWMx PWM peripheral selected, should be LPC_PWM1
+ * @param[in] MatchChannel Match channel
+ * @param[in] MatchValue Match value
+ * @param[in] UpdateType Type of Update, should be:
+ * - PWM_MATCH_UPDATE_NOW: The update value will be updated for
+ * this channel immediately
+ * - PWM_MATCH_UPDATE_NEXT_RST: The update value will be updated for
+ * this channel on next reset by a PWM Match event.
+ * @return None
+ *********************************************************************/
+void PWM_MatchUpdate(LPC_PWM_TypeDef *PWMx, uint8_t MatchChannel, \
+ uint32_t MatchValue, uint8_t UpdateType)
+{
+ CHECK_PARAM(PARAM_PWMx(PWMx));
+ CHECK_PARAM(PARAM_PWM1_MATCH_CHANNEL(MatchChannel));
+ CHECK_PARAM(PARAM_PWM_MATCH_UPDATE(UpdateType));
+
+ switch (MatchChannel)
+ {
+ case 0:
+ PWMx->MR0 = MatchValue;
+ break;
+
+ case 1:
+ PWMx->MR1 = MatchValue;
+ break;
+
+ case 2:
+ PWMx->MR2 = MatchValue;
+ break;
+
+ case 3:
+ PWMx->MR3 = MatchValue;
+ break;
+
+ case 4:
+ PWMx->MR4 = MatchValue;
+ break;
+
+ case 5:
+ PWMx->MR5 = MatchValue;
+ break;
+
+ case 6:
+ PWMx->MR6 = MatchValue;
+ break;
+ }
+
+ // Write Latch register
+ PWMx->LER |= PWM_LER_EN_MATCHn_LATCH(MatchChannel);
+
+ // In case of update now
+ if (UpdateType == PWM_MATCH_UPDATE_NOW)
+ {
+ PWMx->TCR |= PWM_TCR_COUNTER_RESET;
+ PWMx->TCR &= (~PWM_TCR_COUNTER_RESET) & PWM_TCR_BITMASK;
+ }
+}
+
+
+/********************************************************************//**
+ * @brief Configure Edge mode for each PWM channel
+ * @param[in] PWMx PWM peripheral selected, should be LPC_PWM1
+ * @param[in] PWMChannel PWM channel, should be in range from 2 to 6
+ * @param[in] ModeOption PWM mode option, should be:
+ * - PWM_CHANNEL_SINGLE_EDGE: Single Edge mode
+ * - PWM_CHANNEL_DUAL_EDGE: Dual Edge mode
+ * @return None
+ * Note: PWM Channel 1 can not be selected for mode option
+ *********************************************************************/
+void PWM_ChannelConfig(LPC_PWM_TypeDef *PWMx, uint8_t PWMChannel, uint8_t ModeOption)
+{
+ CHECK_PARAM(PARAM_PWMx(PWMx));
+ CHECK_PARAM(PARAM_PWM1_EDGE_MODE_CHANNEL(PWMChannel));
+ CHECK_PARAM(PARAM_PWM_CHANNEL_EDGE(ModeOption));
+
+ // Single edge mode
+ if (ModeOption == PWM_CHANNEL_SINGLE_EDGE)
+ {
+ PWMx->PCR &= (~PWM_PCR_PWMSELn(PWMChannel)) & PWM_PCR_BITMASK;
+ }
+ // Double edge mode
+ else if (PWM_CHANNEL_DUAL_EDGE)
+ {
+ PWMx->PCR |= PWM_PCR_PWMSELn(PWMChannel);
+ }
+}
+
+
+
+/********************************************************************//**
+ * @brief Enable/Disable PWM channel output
+ * @param[in] PWMx PWM peripheral selected, should be LPC_PWM1
+ * @param[in] PWMChannel PWM channel, should be in range from 1 to 6
+ * @param[in] NewState New State of this function, should be:
+ * - ENABLE: Enable this PWM channel output
+ * - DISABLE: Disable this PWM channel output
+ * @return None
+ *********************************************************************/
+void PWM_ChannelCmd(LPC_PWM_TypeDef *PWMx, uint8_t PWMChannel, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_PWMx(PWMx));
+ CHECK_PARAM(PARAM_PWM1_CHANNEL(PWMChannel));
+
+ if (NewState == ENABLE)
+ {
+ PWMx->PCR |= PWM_PCR_PWMENAn(PWMChannel);
+ }
+ else
+ {
+ PWMx->PCR &= (~PWM_PCR_PWMENAn(PWMChannel)) & PWM_PCR_BITMASK;
+ }
+}
+
+/**
+ * @}
+ */
+
+#endif /* _PWM */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_qei.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_qei.c
new file mode 100644
index 0000000..b8c9926
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_qei.c
@@ -0,0 +1,502 @@
+/***********************************************************************//**
+ * @file lpc17xx_qei.c
+ * @brief Contains all functions support for QEI firmware library on LPC17xx
+ * @version 2.0
+ * @date 21. May. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup QEI
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_qei.h"
+#include "lpc17xx_clkpwr.h"
+
+
+/* If this source file built with example, the LPC17xx FW library configuration
+ * file in each example directory ("lpc17xx_libcfg.h") must be included,
+ * otherwise the default FW library configuration file must be included instead
+ */
+#ifdef __BUILD_WITH_EXAMPLE__
+#include "lpc17xx_libcfg.h"
+#else
+#include "lpc17xx_libcfg_default.h"
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+
+#ifdef _QEI
+
+/* Private Types -------------------------------------------------------------- */
+/** @defgroup QEI_Private_Types QEI Private Types
+ * @{
+ */
+
+/**
+ * @brief QEI configuration union type definition
+ */
+typedef union {
+ QEI_CFG_Type bmQEIConfig;
+ uint32_t ulQEIConfig;
+} QEI_CFGOPT_Type;
+
+/**
+ * @}
+ */
+
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup QEI_Public_Functions
+ * @{
+ */
+
+/*********************************************************************//**
+ * @brief Resets value for each type of QEI value, such as velocity,
+ * counter, position, etc..
+ * @param[in] QEIx QEI peripheral, should be LPC_QEI
+ * @param[in] ulResetType QEI Reset Type, should be one of the following:
+ * - QEI_RESET_POS: Reset Position Counter
+ * - QEI_RESET_POSOnIDX: Reset Position Counter on Index signal
+ * - QEI_RESET_VEL: Reset Velocity
+ * - QEI_RESET_IDX: Reset Index Counter
+ * @return None
+ **********************************************************************/
+void QEI_Reset(LPC_QEI_TypeDef *QEIx, uint32_t ulResetType)
+{
+ CHECK_PARAM(PARAM_QEIx(QEIx));
+ CHECK_PARAM(PARAM_QEI_RESET(ulResetType));
+
+ QEIx->QEICON = ulResetType;
+}
+
+/*********************************************************************//**
+ * @brief Initializes the QEI peripheral according to the specified
+* parameters in the QEI_ConfigStruct.
+ * @param[in] QEIx QEI peripheral, should be LPC_QEI
+ * @param[in] QEI_ConfigStruct Pointer to a QEI_CFG_Type structure
+* that contains the configuration information for the
+* specified QEI peripheral
+ * @return None
+ **********************************************************************/
+void QEI_Init(LPC_QEI_TypeDef *QEIx, QEI_CFG_Type *QEI_ConfigStruct)
+{
+
+ CHECK_PARAM(PARAM_QEIx(QEIx));
+ CHECK_PARAM(PARAM_QEI_DIRINV(QEI_ConfigStruct->DirectionInvert));
+ CHECK_PARAM(PARAM_QEI_SIGNALMODE(QEI_ConfigStruct->SignalMode));
+ CHECK_PARAM(PARAM_QEI_CAPMODE(QEI_ConfigStruct->CaptureMode));
+ CHECK_PARAM(PARAM_QEI_INVINX(QEI_ConfigStruct->InvertIndex));
+
+ /* Set up clock and power for QEI module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCQEI, ENABLE);
+
+ /* As default, peripheral clock for QEI module
+ * is set to FCCLK / 2 */
+ CLKPWR_SetPCLKDiv(CLKPWR_PCLKSEL_QEI, CLKPWR_PCLKSEL_CCLK_DIV_1);
+
+ // Reset all remaining value in QEI peripheral
+ QEIx->QEICON = QEI_CON_RESP | QEI_CON_RESV | QEI_CON_RESI;
+ QEIx->QEIMAXPOS = 0x00;
+ QEIx->CMPOS0 = 0x00;
+ QEIx->CMPOS1 = 0x00;
+ QEIx->CMPOS2 = 0x00;
+ QEIx->INXCMP = 0x00;
+ QEIx->QEILOAD = 0x00;
+ QEIx->VELCOMP = 0x00;
+ QEIx->FILTER = 0x00;
+ // Disable all Interrupt
+ QEIx->QEIIEC = QEI_IECLR_BITMASK;
+ // Clear all Interrupt pending
+ QEIx->QEICLR = QEI_INTCLR_BITMASK;
+ // Set QEI configuration value corresponding to its setting up value
+ QEIx->QEICONF = ((QEI_CFGOPT_Type *)QEI_ConfigStruct)->ulQEIConfig;
+}
+
+
+/*********************************************************************//**
+ * @brief De-initializes the QEI peripheral registers to their
+* default reset values.
+ * @param[in] QEIx QEI peripheral, should be LPC_QEI
+ * @return None
+ **********************************************************************/
+void QEI_DeInit(LPC_QEI_TypeDef *QEIx)
+{
+ CHECK_PARAM(PARAM_QEIx(QEIx));
+
+ /* Turn off clock and power for QEI module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCQEI, DISABLE);
+}
+
+
+/*****************************************************************************//**
+* @brief Fills each QIE_InitStruct member with its default value:
+* - DirectionInvert = QEI_DIRINV_NONE
+* - SignalMode = QEI_SIGNALMODE_QUAD
+* - CaptureMode = QEI_CAPMODE_4X
+* - InvertIndex = QEI_INVINX_NONE
+* @param[in] QIE_InitStruct Pointer to a QEI_CFG_Type structure
+* which will be initialized.
+* @return None
+*******************************************************************************/
+void QEI_ConfigStructInit(QEI_CFG_Type *QIE_InitStruct)
+{
+ QIE_InitStruct->CaptureMode = QEI_CAPMODE_4X;
+ QIE_InitStruct->DirectionInvert = QEI_DIRINV_NONE;
+ QIE_InitStruct->InvertIndex = QEI_INVINX_NONE;
+ QIE_InitStruct->SignalMode = QEI_SIGNALMODE_QUAD;
+}
+
+
+/*********************************************************************//**
+ * @brief Check whether if specified flag status is set or not
+ * @param[in] QEIx QEI peripheral, should be LPC_QEI
+ * @param[in] ulFlagType Status Flag Type, should be one of the following:
+ * - QEI_STATUS_DIR: Direction Status
+ * @return New Status of this status flag (SET or RESET)
+ **********************************************************************/
+FlagStatus QEI_GetStatus(LPC_QEI_TypeDef *QEIx, uint32_t ulFlagType)
+{
+ CHECK_PARAM(PARAM_QEIx(QEIx));
+ CHECK_PARAM(PARAM_QEI_STATUS(ulFlagType));
+ return ((QEIx->QEISTAT & ulFlagType) ? SET : RESET);
+}
+
+/*********************************************************************//**
+ * @brief Get current position value in QEI peripheral
+ * @param[in] QEIx QEI peripheral, should be LPC_QEI
+ * @return Current position value of QEI peripheral
+ **********************************************************************/
+uint32_t QEI_GetPosition(LPC_QEI_TypeDef *QEIx)
+{
+ CHECK_PARAM(PARAM_QEIx(QEIx));
+ return (QEIx->QEIPOS);
+}
+
+/*********************************************************************//**
+ * @brief Set max position value for QEI peripheral
+ * @param[in] QEIx QEI peripheral, should be LPC_QEI
+ * @param[in] ulMaxPos Max position value to set
+ * @return None
+ **********************************************************************/
+void QEI_SetMaxPosition(LPC_QEI_TypeDef *QEIx, uint32_t ulMaxPos)
+{
+ CHECK_PARAM(PARAM_QEIx(QEIx));
+ QEIx->QEIMAXPOS = ulMaxPos;
+}
+
+/*********************************************************************//**
+ * @brief Set position compare value for QEI peripheral
+ * @param[in] QEIx QEI peripheral, should be LPC_QEI
+ * @param[in] bPosCompCh Compare Position channel, should be:
+ * - QEI_COMPPOS_CH_0: QEI compare position channel 0
+ * - QEI_COMPPOS_CH_1: QEI compare position channel 1
+ * - QEI_COMPPOS_CH_2: QEI compare position channel 2
+ * @param[in] ulPosComp Compare Position value to set
+ * @return None
+ **********************************************************************/
+void QEI_SetPositionComp(LPC_QEI_TypeDef *QEIx, uint8_t bPosCompCh, uint32_t ulPosComp)
+{
+ uint32_t *tmp;
+
+ CHECK_PARAM(PARAM_QEIx(QEIx));
+ CHECK_PARAM(PARAM_QEI_COMPPOS_CH(bPosCompCh));
+ tmp = (uint32_t *) (&(QEIx->CMPOS0) + bPosCompCh * 4);
+ *tmp = ulPosComp;
+
+}
+
+/*********************************************************************//**
+ * @brief Get current index counter of QEI peripheral
+ * @param[in] QEIx QEI peripheral, should be LPC_QEI
+ * @return Current value of QEI index counter
+ **********************************************************************/
+uint32_t QEI_GetIndex(LPC_QEI_TypeDef *QEIx)
+{
+ CHECK_PARAM(PARAM_QEIx(QEIx));
+ return (QEIx->INXCNT);
+}
+
+/*********************************************************************//**
+ * @brief Set value for index compare in QEI peripheral
+ * @param[in] QEIx QEI peripheral, should be LPC_QEI
+ * @param[in] ulIndexComp Compare Index Value to set
+ * @return None
+ **********************************************************************/
+void QEI_SetIndexComp(LPC_QEI_TypeDef *QEIx, uint32_t ulIndexComp)
+{
+ CHECK_PARAM(PARAM_QEIx(QEIx));
+ QEIx->INXCMP = ulIndexComp;
+}
+
+/*********************************************************************//**
+ * @brief Set timer reload value for QEI peripheral. When the velocity timer is
+ * over-flow, the value that set for Timer Reload register will be loaded
+ * into the velocity timer for next period. The calculated velocity in RPM
+ * therefore will be affect by this value.
+ * @param[in] QEIx QEI peripheral, should be LPC_QEI
+ * @param[in] QEIReloadStruct QEI reload structure
+ * @return None
+ **********************************************************************/
+void QEI_SetTimerReload(LPC_QEI_TypeDef *QEIx, QEI_RELOADCFG_Type *QEIReloadStruct)
+{
+ uint64_t pclk;
+
+ CHECK_PARAM(PARAM_QEIx(QEIx));
+ CHECK_PARAM(PARAM_QEI_TIMERRELOAD(QEIReloadStruct->ReloadOption));
+
+ if (QEIReloadStruct->ReloadOption == QEI_TIMERRELOAD_TICKVAL) {
+ QEIx->QEILOAD = QEIReloadStruct->ReloadValue - 1;
+ } else {
+ pclk = (uint64_t)CLKPWR_GetPCLK(CLKPWR_PCLKSEL_QEI);
+ pclk = (pclk /(1000000/QEIReloadStruct->ReloadValue)) - 1;
+ QEIx->QEILOAD = (uint32_t)pclk;
+ }
+}
+
+/*********************************************************************//**
+ * @brief Get current timer counter in QEI peripheral
+ * @param[in] QEIx QEI peripheral, should be LPC_QEI
+ * @return Current timer counter in QEI peripheral
+ **********************************************************************/
+uint32_t QEI_GetTimer(LPC_QEI_TypeDef *QEIx)
+{
+ CHECK_PARAM(PARAM_QEIx(QEIx));
+ return (QEIx->QEITIME);
+}
+
+/*********************************************************************//**
+ * @brief Get current velocity pulse counter in current time period
+ * @param[in] QEIx QEI peripheral, should be LPC_QEI
+ * @return Current velocity pulse counter value
+ **********************************************************************/
+uint32_t QEI_GetVelocity(LPC_QEI_TypeDef *QEIx)
+{
+ CHECK_PARAM(PARAM_QEIx(QEIx));
+ return (QEIx->QEIVEL);
+}
+
+/*********************************************************************//**
+ * @brief Get the most recently measured velocity of the QEI. When
+ * the Velocity timer in QEI is over-flow, the current velocity
+ * value will be loaded into Velocity Capture register.
+ * @param[in] QEIx QEI peripheral, should be LPC_QEI
+ * @return The most recently measured velocity value
+ **********************************************************************/
+uint32_t QEI_GetVelocityCap(LPC_QEI_TypeDef *QEIx)
+{
+ CHECK_PARAM(PARAM_QEIx(QEIx));
+ return (QEIx->QEICAP);
+}
+
+/*********************************************************************//**
+ * @brief Set Velocity Compare value for QEI peripheral
+ * @param[in] QEIx QEI peripheral, should be LPC_QEI
+ * @param[in] ulVelComp Compare Velocity value to set
+ * @return None
+ **********************************************************************/
+void QEI_SetVelocityComp(LPC_QEI_TypeDef *QEIx, uint32_t ulVelComp)
+{
+ CHECK_PARAM(PARAM_QEIx(QEIx));
+ QEIx->VELCOMP = ulVelComp;
+}
+
+/*********************************************************************//**
+ * @brief Set value of sampling count for the digital filter in
+ * QEI peripheral
+ * @param[in] QEIx QEI peripheral, should be LPC_QEI
+ * @param[in] ulSamplingPulse Value of sampling count to set
+ * @return None
+ **********************************************************************/
+void QEI_SetDigiFilter(LPC_QEI_TypeDef *QEIx, uint32_t ulSamplingPulse)
+{
+ CHECK_PARAM(PARAM_QEIx(QEIx));
+ QEIx->FILTER = ulSamplingPulse;
+}
+
+/*********************************************************************//**
+ * @brief Check whether if specified interrupt flag status in QEI
+ * peripheral is set or not
+ * @param[in] QEIx QEI peripheral, should be LPC_QEI
+ * @param[in] ulIntType Interrupt Flag Status type, should be:
+ - QEI_INTFLAG_INX_Int: index pulse was detected interrupt
+ - QEI_INTFLAG_TIM_Int: Velocity timer over flow interrupt
+ - QEI_INTFLAG_VELC_Int: Capture velocity is less than compare interrupt
+ - QEI_INTFLAG_DIR_Int: Change of direction interrupt
+ - QEI_INTFLAG_ERR_Int: An encoder phase error interrupt
+ - QEI_INTFLAG_ENCLK_Int: An encoder clock pulse was detected interrupt
+ - QEI_INTFLAG_POS0_Int: position 0 compare value is equal to the
+ current position interrupt
+ - QEI_INTFLAG_POS1_Int: position 1 compare value is equal to the
+ current position interrupt
+ - QEI_INTFLAG_POS2_Int: position 2 compare value is equal to the
+ current position interrupt
+ - QEI_INTFLAG_REV_Int: Index compare value is equal to the current
+ index count interrupt
+ - QEI_INTFLAG_POS0REV_Int: Combined position 0 and revolution count interrupt
+ - QEI_INTFLAG_POS1REV_Int: Combined position 1 and revolution count interrupt
+ - QEI_INTFLAG_POS2REV_Int: Combined position 2 and revolution count interrupt
+ * @return New State of specified interrupt flag status (SET or RESET)
+ **********************************************************************/
+FlagStatus QEI_GetIntStatus(LPC_QEI_TypeDef *QEIx, uint32_t ulIntType)
+{
+ CHECK_PARAM(PARAM_QEIx(QEIx));
+ CHECK_PARAM(PARAM_QEI_INTFLAG(ulIntType));
+
+ return((QEIx->QEIINTSTAT & ulIntType) ? SET : RESET);
+}
+
+/*********************************************************************//**
+ * @brief Enable/Disable specified interrupt in QEI peripheral
+ * @param[in] QEIx QEI peripheral, should be LPC_QEI
+ * @param[in] ulIntType Interrupt Flag Status type, should be:
+ * - QEI_INTFLAG_INX_Int: index pulse was detected interrupt
+ * - QEI_INTFLAG_TIM_Int: Velocity timer over flow interrupt
+ * - QEI_INTFLAG_VELC_Int: Capture velocity is less than compare interrupt
+ * - QEI_INTFLAG_DIR_Int: Change of direction interrupt
+ * - QEI_INTFLAG_ERR_Int: An encoder phase error interrupt
+ * - QEI_INTFLAG_ENCLK_Int: An encoder clock pulse was detected interrupt
+ * - QEI_INTFLAG_POS0_Int: position 0 compare value is equal to the
+ * current position interrupt
+ * - QEI_INTFLAG_POS1_Int: position 1 compare value is equal to the
+ * current position interrupt
+ * - QEI_INTFLAG_POS2_Int: position 2 compare value is equal to the
+ * current position interrupt
+ * - QEI_INTFLAG_REV_Int: Index compare value is equal to the current
+ * index count interrupt
+ * - QEI_INTFLAG_POS0REV_Int: Combined position 0 and revolution count interrupt
+ * - QEI_INTFLAG_POS1REV_Int: Combined position 1 and revolution count interrupt
+ * - QEI_INTFLAG_POS2REV_Int: Combined position 2 and revolution count interrupt
+ * @param[in] NewState New function state, should be:
+ * - DISABLE
+ * - ENABLE
+ * @return None
+ **********************************************************************/
+void QEI_IntCmd(LPC_QEI_TypeDef *QEIx, uint32_t ulIntType, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_QEIx(QEIx));
+ CHECK_PARAM(PARAM_QEI_INTFLAG(ulIntType));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ if (NewState == ENABLE) {
+ QEIx->QEIIES = ulIntType;
+ } else {
+ QEIx->QEIIEC = ulIntType;
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Sets (forces) specified interrupt in QEI peripheral
+ * @param[in] QEIx QEI peripheral, should be LPC_QEI
+ * @param[in] ulIntType Interrupt Flag Status type, should be:
+ - QEI_INTFLAG_INX_Int: index pulse was detected interrupt
+ - QEI_INTFLAG_TIM_Int: Velocity timer over flow interrupt
+ - QEI_INTFLAG_VELC_Int: Capture velocity is less than compare interrupt
+ - QEI_INTFLAG_DIR_Int: Change of direction interrupt
+ - QEI_INTFLAG_ERR_Int: An encoder phase error interrupt
+ - QEI_INTFLAG_ENCLK_Int: An encoder clock pulse was detected interrupt
+ - QEI_INTFLAG_POS0_Int: position 0 compare value is equal to the
+ current position interrupt
+ - QEI_INTFLAG_POS1_Int: position 1 compare value is equal to the
+ current position interrupt
+ - QEI_INTFLAG_POS2_Int: position 2 compare value is equal to the
+ current position interrupt
+ - QEI_INTFLAG_REV_Int: Index compare value is equal to the current
+ index count interrupt
+ - QEI_INTFLAG_POS0REV_Int: Combined position 0 and revolution count interrupt
+ - QEI_INTFLAG_POS1REV_Int: Combined position 1 and revolution count interrupt
+ - QEI_INTFLAG_POS2REV_Int: Combined position 2 and revolution count interrupt
+ * @return None
+ **********************************************************************/
+void QEI_IntSet(LPC_QEI_TypeDef *QEIx, uint32_t ulIntType)
+{
+ CHECK_PARAM(PARAM_QEIx(QEIx));
+ CHECK_PARAM(PARAM_QEI_INTFLAG(ulIntType));
+
+ QEIx->QEISET = ulIntType;
+}
+
+/*********************************************************************//**
+ * @brief Clear (force) specified interrupt (pending) in QEI peripheral
+ * @param[in] QEIx QEI peripheral, should be LPC_QEI
+ * @param[in] ulIntType Interrupt Flag Status type, should be:
+ - QEI_INTFLAG_INX_Int: index pulse was detected interrupt
+ - QEI_INTFLAG_TIM_Int: Velocity timer over flow interrupt
+ - QEI_INTFLAG_VELC_Int: Capture velocity is less than compare interrupt
+ - QEI_INTFLAG_DIR_Int: Change of direction interrupt
+ - QEI_INTFLAG_ERR_Int: An encoder phase error interrupt
+ - QEI_INTFLAG_ENCLK_Int: An encoder clock pulse was detected interrupt
+ - QEI_INTFLAG_POS0_Int: position 0 compare value is equal to the
+ current position interrupt
+ - QEI_INTFLAG_POS1_Int: position 1 compare value is equal to the
+ current position interrupt
+ - QEI_INTFLAG_POS2_Int: position 2 compare value is equal to the
+ current position interrupt
+ - QEI_INTFLAG_REV_Int: Index compare value is equal to the current
+ index count interrupt
+ - QEI_INTFLAG_POS0REV_Int: Combined position 0 and revolution count interrupt
+ - QEI_INTFLAG_POS1REV_Int: Combined position 1 and revolution count interrupt
+ - QEI_INTFLAG_POS2REV_Int: Combined position 2 and revolution count interrupt
+ * @return None
+ **********************************************************************/
+void QEI_IntClear(LPC_QEI_TypeDef *QEIx, uint32_t ulIntType)
+{
+ CHECK_PARAM(PARAM_QEIx(QEIx));
+ CHECK_PARAM(PARAM_QEI_INTFLAG(ulIntType));
+
+ QEIx->QEICLR = ulIntType;
+}
+
+
+/*********************************************************************//**
+ * @brief Calculates the actual velocity in RPM passed via velocity
+ * capture value and Pulse Per Round (of the encoder) value
+ * parameter input.
+ * @param[in] QEIx QEI peripheral, should be LPC_QEI
+ * @param[in] ulVelCapValue Velocity capture input value that can
+ * be got from QEI_GetVelocityCap() function
+ * @param[in] ulPPR Pulse per round of encoder
+ * @return The actual value of velocity in RPM (Round per minute)
+ **********************************************************************/
+uint32_t QEI_CalculateRPM(LPC_QEI_TypeDef *QEIx, uint32_t ulVelCapValue, uint32_t ulPPR)
+{
+ uint64_t rpm, clock, Load, edges;
+
+ // Get current Clock rate for timer input
+ clock = (uint64_t)CLKPWR_GetPCLK(CLKPWR_PCLKSEL_QEI);
+ // Get Timer load value (velocity capture period)
+ Load = (uint64_t)(QEIx->QEILOAD + 1);
+ // Get Edge
+ edges = (uint64_t)((QEIx->QEICONF & QEI_CONF_CAPMODE) ? 4 : 2);
+ // Calculate RPM
+ rpm = ((clock * ulVelCapValue * 60) / (Load * ulPPR * edges));
+
+ return (uint32_t)(rpm);
+}
+
+
+/**
+ * @}
+ */
+
+#endif /* _QEI */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
+
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_rit.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_rit.c
new file mode 100644
index 0000000..4df19ac
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_rit.c
@@ -0,0 +1,187 @@
+/***********************************************************************//**
+ * @file lpc17xx_rit.c
+ * @brief Contains all functions support for RIT firmware library on LPC17xx
+ * @version 2.0
+ * @date 21. May. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup RIT
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_rit.h"
+#include "lpc17xx_clkpwr.h"
+
+/* If this source file built with example, the LPC17xx FW library configuration
+ * file in each example directory ("lpc17xx_libcfg.h") must be included,
+ * otherwise the default FW library configuration file must be included instead
+ */
+#ifdef __BUILD_WITH_EXAMPLE__
+#include "lpc17xx_libcfg.h"
+#else
+#include "lpc17xx_libcfg_default.h"
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+#ifdef _RIT
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup RIT_Public_Functions
+ * @{
+ */
+
+/******************************************************************************//*
+ * @brief Initial for RIT
+ * - Turn on power and clock
+ * - Setup default register values
+ * @param[in] RITx is RIT peripheral selected, should be: LPC_RIT
+ * @return None
+ *******************************************************************************/
+void RIT_Init(LPC_RIT_TypeDef *RITx)
+{
+ CHECK_PARAM(PARAM_RITx(RITx));
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCRIT, ENABLE);
+ //Set up default register values
+ RITx->RICOMPVAL = 0xFFFFFFFF;
+ RITx->RIMASK = 0x00000000;
+ RITx->RICTRL = 0x0C;
+ RITx->RICOUNTER = 0x00000000;
+ // Turn on power and clock
+
+}
+/******************************************************************************//*
+ * @brief DeInitial for RIT
+ * - Turn off power and clock
+ * - ReSetup default register values
+ * @param[in] RITx is RIT peripheral selected, should be: LPC_RIT
+ * @return None
+ *******************************************************************************/
+void RIT_DeInit(LPC_RIT_TypeDef *RITx)
+{
+ CHECK_PARAM(PARAM_RITx(RITx));
+
+ // Turn off power and clock
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCRIT, DISABLE);
+ //ReSetup default register values
+ RITx->RICOMPVAL = 0xFFFFFFFF;
+ RITx->RIMASK = 0x00000000;
+ RITx->RICTRL = 0x0C;
+ RITx->RICOUNTER = 0x00000000;
+}
+
+/******************************************************************************//*
+ * @brief Set compare value, mask value and time counter value
+ * @param[in] RITx is RIT peripheral selected, should be: LPC_RIT
+ * @param[in] time_interval: timer interval value (ms)
+ * @return None
+ *******************************************************************************/
+void RIT_TimerConfig(LPC_RIT_TypeDef *RITx, uint32_t time_interval)
+{
+ uint32_t clock_rate, cmp_value;
+ CHECK_PARAM(PARAM_RITx(RITx));
+
+ // Get PCLK value of RIT
+ clock_rate = CLKPWR_GetPCLK(CLKPWR_PCLKSEL_RIT);
+
+ /* calculate compare value for RIT to generate interrupt at
+ * specified time interval
+ * COMPVAL = (RIT_PCLK * time_interval)/1000
+ * (with time_interval unit is millisecond)
+ */
+ cmp_value = (clock_rate /1000) * time_interval;
+ RITx->RICOMPVAL = cmp_value;
+
+ /* Set timer enable clear bit to clear timer to 0 whenever
+ * counter value equals the contents of RICOMPVAL
+ */
+ RITx->RICTRL |= (1<<1);
+}
+
+
+/******************************************************************************//*
+ * @brief Enable/Disable Timer
+ * @param[in] RITx is RIT peripheral selected, should be: LPC_RIT
+ * @param[in] NewState New State of this function
+ * -ENABLE: Enable Timer
+ * -DISABLE: Disable Timer
+ * @return None
+ *******************************************************************************/
+void RIT_Cmd(LPC_RIT_TypeDef *RITx, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_RITx(RITx));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ //Enable or Disable Timer
+ if(NewState==ENABLE)
+ {
+ RITx->RICTRL |= RIT_CTRL_TEN;
+ }
+ else
+ {
+ RITx->RICTRL &= ~RIT_CTRL_TEN;
+ }
+}
+
+/******************************************************************************//*
+ * @brief Timer Enable/Disable on debug
+ * @param[in] RITx is RIT peripheral selected, should be: LPC_RIT
+ * @param[in] NewState New State of this function
+ * -ENABLE: The timer is halted whenever a hardware break condition occurs
+ * -DISABLE: Hardware break has no effect on the timer operation
+ * @return None
+ *******************************************************************************/
+void RIT_TimerDebugCmd(LPC_RIT_TypeDef *RITx, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_RITx(RITx));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ //Timer Enable/Disable on break
+ if(NewState==ENABLE)
+ {
+ RITx->RICTRL |= RIT_CTRL_ENBR;
+ }
+ else
+ {
+ RITx->RICTRL &= ~RIT_CTRL_ENBR;
+ }
+}
+/******************************************************************************//*
+ * @brief Check whether interrupt flag is set or not
+ * @param[in] RITx is RIT peripheral selected, should be: LPC_RIT
+ * @return Current interrupt status, could be: SET/RESET
+ *******************************************************************************/
+IntStatus RIT_GetIntStatus(LPC_RIT_TypeDef *RITx)
+{
+ uint8_t result;
+ CHECK_PARAM(PARAM_RITx(RITx));
+ if((RITx->RICTRL&RIT_CTRL_INTEN)==1) result= SET;
+ else return RESET;
+ //clear interrupt flag
+ RITx->RICTRL |= RIT_CTRL_INTEN;
+ return result;
+}
+
+/**
+ * @}
+ */
+
+#endif /* _RIT */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_rtc.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_rtc.c
new file mode 100644
index 0000000..c7c2cdb
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_rtc.c
@@ -0,0 +1,771 @@
+/***********************************************************************//**
+ * @file lpc17xx_rtc.c
+ * @brief Contains all functions support for RTC firmware library on LPC17xx
+ * @version 3.0
+ * @date 18. June. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup RTC
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_rtc.h"
+#include "lpc17xx_clkpwr.h"
+
+
+/* If this source file built with example, the LPC17xx FW library configuration
+ * file in each example directory ("lpc17xx_libcfg.h") must be included,
+ * otherwise the default FW library configuration file must be included instead
+ */
+#ifdef __BUILD_WITH_EXAMPLE__
+#include "lpc17xx_libcfg.h"
+#else
+#include "lpc17xx_libcfg_default.h"
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+
+#ifdef _RTC
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup RTC_Public_Functions
+ * @{
+ */
+
+/********************************************************************//**
+ * @brief Initializes the RTC peripheral.
+ * @param[in] RTCx RTC peripheral selected, should be LPC_RTC
+ * @return None
+ *********************************************************************/
+void RTC_Init (LPC_RTC_TypeDef *RTCx)
+{
+ CHECK_PARAM(PARAM_RTCx(RTCx));
+
+ /* Set up clock and power for RTC module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCRTC, ENABLE);
+
+ // Clear all register to be default
+ RTCx->ILR = 0x00;
+ RTCx->CCR = 0x00;
+ RTCx->CIIR = 0x00;
+ RTCx->AMR = 0xFF;
+ RTCx->CALIBRATION = 0x00;
+}
+
+
+/*********************************************************************//**
+ * @brief De-initializes the RTC peripheral registers to their
+* default reset values.
+ * @param[in] RTCx RTC peripheral selected, should be LPC_RTC
+ * @return None
+ **********************************************************************/
+void RTC_DeInit(LPC_RTC_TypeDef *RTCx)
+{
+ CHECK_PARAM(PARAM_RTCx(RTCx));
+
+ RTCx->CCR = 0x00;
+ // Disable power and clock for RTC module
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCRTC, DISABLE);
+}
+
+/*********************************************************************//**
+ * @brief Reset clock tick counter in RTC peripheral
+ * @param[in] RTCx RTC peripheral selected, should be LPC_RTC
+ * @return None
+ **********************************************************************/
+void RTC_ResetClockTickCounter(LPC_RTC_TypeDef *RTCx)
+{
+ CHECK_PARAM(PARAM_RTCx(RTCx));
+
+ RTCx->CCR |= RTC_CCR_CTCRST;
+ RTCx->CCR &= (~RTC_CCR_CTCRST) & RTC_CCR_BITMASK;
+}
+
+/*********************************************************************//**
+ * @brief Start/Stop RTC peripheral
+ * @param[in] RTCx RTC peripheral selected, should be LPC_RTC
+ * @param[in] NewState New State of this function, should be:
+ * - ENABLE: The time counters are enabled
+ * - DISABLE: The time counters are disabled
+ * @return None
+ **********************************************************************/
+void RTC_Cmd (LPC_RTC_TypeDef *RTCx, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_RTCx(RTCx));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ if (NewState == ENABLE)
+ {
+ RTCx->CCR |= RTC_CCR_CLKEN;
+ }
+ else
+ {
+ RTCx->CCR &= (~RTC_CCR_CLKEN) & RTC_CCR_BITMASK;
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Enable/Disable Counter increment interrupt for each time type
+ * in RTC peripheral
+ * @param[in] RTCx RTC peripheral selected, should be LPC_RTC
+ * @param[in] CntIncrIntType: Counter Increment Interrupt type,
+ * an increment of this type value below will generates
+ * an interrupt, should be:
+ * - RTC_TIMETYPE_SECOND
+ * - RTC_TIMETYPE_MINUTE
+ * - RTC_TIMETYPE_HOUR
+ * - RTC_TIMETYPE_DAYOFWEEK
+ * - RTC_TIMETYPE_DAYOFMONTH
+ * - RTC_TIMETYPE_DAYOFYEAR
+ * - RTC_TIMETYPE_MONTH
+ * - RTC_TIMETYPE_YEAR
+ * @param[in] NewState New State of this function, should be:
+ * - ENABLE: Counter Increment interrupt for this
+ * time type are enabled
+ * - DISABLE: Counter Increment interrupt for this
+ * time type are disabled
+ * @return None
+ **********************************************************************/
+void RTC_CntIncrIntConfig (LPC_RTC_TypeDef *RTCx, uint32_t CntIncrIntType, \
+ FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_RTCx(RTCx));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+ CHECK_PARAM(PARAM_RTC_TIMETYPE(CntIncrIntType));
+
+ if (NewState == ENABLE)
+ {
+ switch (CntIncrIntType)
+ {
+ case RTC_TIMETYPE_SECOND:
+ RTCx->CIIR |= RTC_CIIR_IMSEC;
+ break;
+ case RTC_TIMETYPE_MINUTE:
+ RTCx->CIIR |= RTC_CIIR_IMMIN;
+ break;
+ case RTC_TIMETYPE_HOUR:
+ RTCx->CIIR |= RTC_CIIR_IMHOUR;
+ break;
+ case RTC_TIMETYPE_DAYOFWEEK:
+ RTCx->CIIR |= RTC_CIIR_IMDOW;
+ break;
+ case RTC_TIMETYPE_DAYOFMONTH:
+ RTCx->CIIR |= RTC_CIIR_IMDOM;
+ break;
+ case RTC_TIMETYPE_DAYOFYEAR:
+ RTCx->CIIR |= RTC_CIIR_IMDOY;
+ break;
+ case RTC_TIMETYPE_MONTH:
+ RTCx->CIIR |= RTC_CIIR_IMMON;
+ break;
+ case RTC_TIMETYPE_YEAR:
+ RTCx->CIIR |= RTC_CIIR_IMYEAR;
+ break;
+ }
+ }
+ else
+ {
+ switch (CntIncrIntType)
+ {
+ case RTC_TIMETYPE_SECOND:
+ RTCx->CIIR &= (~RTC_CIIR_IMSEC) & RTC_CIIR_BITMASK;
+ break;
+ case RTC_TIMETYPE_MINUTE:
+ RTCx->CIIR &= (~RTC_CIIR_IMMIN) & RTC_CIIR_BITMASK;
+ break;
+ case RTC_TIMETYPE_HOUR:
+ RTCx->CIIR &= (~RTC_CIIR_IMHOUR) & RTC_CIIR_BITMASK;
+ break;
+ case RTC_TIMETYPE_DAYOFWEEK:
+ RTCx->CIIR &= (~RTC_CIIR_IMDOW) & RTC_CIIR_BITMASK;
+ break;
+ case RTC_TIMETYPE_DAYOFMONTH:
+ RTCx->CIIR &= (~RTC_CIIR_IMDOM) & RTC_CIIR_BITMASK;
+ break;
+ case RTC_TIMETYPE_DAYOFYEAR:
+ RTCx->CIIR &= (~RTC_CIIR_IMDOY) & RTC_CIIR_BITMASK;
+ break;
+ case RTC_TIMETYPE_MONTH:
+ RTCx->CIIR &= (~RTC_CIIR_IMMON) & RTC_CIIR_BITMASK;
+ break;
+ case RTC_TIMETYPE_YEAR:
+ RTCx->CIIR &= (~RTC_CIIR_IMYEAR) & RTC_CIIR_BITMASK;
+ break;
+ }
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Enable/Disable Alarm interrupt for each time type
+ * in RTC peripheral
+ * @param[in] RTCx RTC peripheral selected, should be LPC_RTC
+ * @param[in] AlarmTimeType: Alarm Time Interrupt type,
+ * an matching of this type value below with current time
+ * in RTC will generates an interrupt, should be:
+ * - RTC_TIMETYPE_SECOND
+ * - RTC_TIMETYPE_MINUTE
+ * - RTC_TIMETYPE_HOUR
+ * - RTC_TIMETYPE_DAYOFWEEK
+ * - RTC_TIMETYPE_DAYOFMONTH
+ * - RTC_TIMETYPE_DAYOFYEAR
+ * - RTC_TIMETYPE_MONTH
+ * - RTC_TIMETYPE_YEAR
+ * @param[in] NewState New State of this function, should be:
+ * - ENABLE: Alarm interrupt for this
+ * time type are enabled
+ * - DISABLE: Alarm interrupt for this
+ * time type are disabled
+ * @return None
+ **********************************************************************/
+void RTC_AlarmIntConfig (LPC_RTC_TypeDef *RTCx, uint32_t AlarmTimeType, \
+ FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_RTCx(RTCx));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+ CHECK_PARAM(PARAM_RTC_TIMETYPE(AlarmTimeType));
+
+ if (NewState == ENABLE)
+ {
+ switch (AlarmTimeType)
+ {
+ case RTC_TIMETYPE_SECOND:
+ RTCx->AMR &= (~RTC_AMR_AMRSEC) & RTC_AMR_BITMASK;
+ break;
+ case RTC_TIMETYPE_MINUTE:
+ RTCx->AMR &= (~RTC_AMR_AMRMIN) & RTC_AMR_BITMASK;
+ break;
+ case RTC_TIMETYPE_HOUR:
+ RTCx->AMR &= (~RTC_AMR_AMRHOUR) & RTC_AMR_BITMASK;
+ break;
+ case RTC_TIMETYPE_DAYOFWEEK:
+ RTCx->AMR &= (~RTC_AMR_AMRDOW) & RTC_AMR_BITMASK;
+ break;
+ case RTC_TIMETYPE_DAYOFMONTH:
+ RTCx->AMR &= (~RTC_AMR_AMRDOM) & RTC_AMR_BITMASK;
+ break;
+ case RTC_TIMETYPE_DAYOFYEAR:
+ RTCx->AMR &= (~RTC_AMR_AMRDOY) & RTC_AMR_BITMASK;
+ break;
+ case RTC_TIMETYPE_MONTH:
+ RTCx->AMR &= (~RTC_AMR_AMRMON) & RTC_AMR_BITMASK;
+ break;
+ case RTC_TIMETYPE_YEAR:
+ RTCx->AMR &= (~RTC_AMR_AMRYEAR) & RTC_AMR_BITMASK;
+ break;
+ }
+ }
+ else
+ {
+ switch (AlarmTimeType)
+ {
+ case RTC_TIMETYPE_SECOND:
+ RTCx->AMR |= (RTC_AMR_AMRSEC);
+ break;
+ case RTC_TIMETYPE_MINUTE:
+ RTCx->AMR |= (RTC_AMR_AMRMIN);
+ break;
+ case RTC_TIMETYPE_HOUR:
+ RTCx->AMR |= (RTC_AMR_AMRHOUR);
+ break;
+ case RTC_TIMETYPE_DAYOFWEEK:
+ RTCx->AMR |= (RTC_AMR_AMRDOW);
+ break;
+ case RTC_TIMETYPE_DAYOFMONTH:
+ RTCx->AMR |= (RTC_AMR_AMRDOM);
+ break;
+ case RTC_TIMETYPE_DAYOFYEAR:
+ RTCx->AMR |= (RTC_AMR_AMRDOY);
+ break;
+ case RTC_TIMETYPE_MONTH:
+ RTCx->AMR |= (RTC_AMR_AMRMON);
+ break;
+ case RTC_TIMETYPE_YEAR:
+ RTCx->AMR |= (RTC_AMR_AMRYEAR);
+ break;
+ }
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Set current time value for each time type in RTC peripheral
+ * @param[in] RTCx RTC peripheral selected, should be LPC_RTC
+ * @param[in] Timetype: Time Type, should be:
+ * - RTC_TIMETYPE_SECOND
+ * - RTC_TIMETYPE_MINUTE
+ * - RTC_TIMETYPE_HOUR
+ * - RTC_TIMETYPE_DAYOFWEEK
+ * - RTC_TIMETYPE_DAYOFMONTH
+ * - RTC_TIMETYPE_DAYOFYEAR
+ * - RTC_TIMETYPE_MONTH
+ * - RTC_TIMETYPE_YEAR
+ * @param[in] TimeValue Time value to set
+ * @return None
+ **********************************************************************/
+void RTC_SetTime (LPC_RTC_TypeDef *RTCx, uint32_t Timetype, uint32_t TimeValue)
+{
+ CHECK_PARAM(PARAM_RTCx(RTCx));
+ CHECK_PARAM(PARAM_RTC_TIMETYPE(Timetype));
+
+ switch ( Timetype)
+ {
+ case RTC_TIMETYPE_SECOND:
+ CHECK_PARAM(TimeValue < RTC_SECOND_MAX);
+
+ RTCx->SEC = TimeValue & RTC_SEC_MASK;
+ break;
+
+ case RTC_TIMETYPE_MINUTE:
+ CHECK_PARAM(TimeValue < RTC_MINUTE_MAX);
+
+ RTCx->MIN = TimeValue & RTC_MIN_MASK;
+ break;
+
+ case RTC_TIMETYPE_HOUR:
+ CHECK_PARAM(TimeValue < RTC_HOUR_MAX);
+
+ RTCx->HOUR = TimeValue & RTC_HOUR_MASK;
+ break;
+
+ case RTC_TIMETYPE_DAYOFWEEK:
+ CHECK_PARAM(TimeValue < RTC_DAYOFWEEK_MAX);
+
+ RTCx->DOW = TimeValue & RTC_DOW_MASK;
+ break;
+
+ case RTC_TIMETYPE_DAYOFMONTH:
+ CHECK_PARAM((TimeValue < RTC_DAYOFMONTH_MAX) \
+ && (TimeValue > RTC_DAYOFMONTH_MIN));
+
+ RTCx->DOM = TimeValue & RTC_DOM_MASK;
+ break;
+
+ case RTC_TIMETYPE_DAYOFYEAR:
+ CHECK_PARAM((TimeValue > RTC_DAYOFYEAR_MIN) \
+ && (TimeValue < RTC_DAYOFYEAR_MAX));
+
+ RTCx->DOY = TimeValue & RTC_DOY_MASK;
+ break;
+
+ case RTC_TIMETYPE_MONTH:
+ CHECK_PARAM((TimeValue > RTC_MONTH_MIN) \
+ && (TimeValue < RTC_MONTH_MAX));
+
+ RTCx->MONTH = TimeValue & RTC_MONTH_MASK;
+ break;
+
+ case RTC_TIMETYPE_YEAR:
+ CHECK_PARAM(TimeValue < RTC_YEAR_MAX);
+
+ RTCx->YEAR = TimeValue & RTC_YEAR_MASK;
+ break;
+ }
+}
+
+/*********************************************************************//**
+ * @brief Get current time value for each type time type
+ * @param[in] RTCx RTC peripheral selected, should be LPC_RTC
+ * @param[in] Timetype: Time Type, should be:
+ * - RTC_TIMETYPE_SECOND
+ * - RTC_TIMETYPE_MINUTE
+ * - RTC_TIMETYPE_HOUR
+ * - RTC_TIMETYPE_DAYOFWEEK
+ * - RTC_TIMETYPE_DAYOFMONTH
+ * - RTC_TIMETYPE_DAYOFYEAR
+ * - RTC_TIMETYPE_MONTH
+ * - RTC_TIMETYPE_YEAR
+ * @return Value of time according to specified time type
+ **********************************************************************/
+uint32_t RTC_GetTime(LPC_RTC_TypeDef *RTCx, uint32_t Timetype)
+{
+ CHECK_PARAM(PARAM_RTCx(RTCx));
+ CHECK_PARAM(PARAM_RTC_TIMETYPE(Timetype));
+
+ switch (Timetype)
+ {
+ case RTC_TIMETYPE_SECOND:
+ return (RTCx->SEC & RTC_SEC_MASK);
+ case RTC_TIMETYPE_MINUTE:
+ return (RTCx->MIN & RTC_MIN_MASK);
+ case RTC_TIMETYPE_HOUR:
+ return (RTCx->HOUR & RTC_HOUR_MASK);
+ case RTC_TIMETYPE_DAYOFWEEK:
+ return (RTCx->DOW & RTC_DOW_MASK);
+ case RTC_TIMETYPE_DAYOFMONTH:
+ return (RTCx->DOM & RTC_DOM_MASK);
+ case RTC_TIMETYPE_DAYOFYEAR:
+ return (RTCx->DOY & RTC_DOY_MASK);
+ case RTC_TIMETYPE_MONTH:
+ return (RTCx->MONTH & RTC_MONTH_MASK);
+ case RTC_TIMETYPE_YEAR:
+ return (RTCx->YEAR & RTC_YEAR_MASK);
+ default:
+ return (0);
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Set full of time in RTC peripheral
+ * @param[in] RTCx RTC peripheral selected, should be LPC_RTC
+ * @param[in] pFullTime Pointer to a RTC_TIME_Type structure that
+ * contains time value in full.
+ * @return None
+ **********************************************************************/
+void RTC_SetFullTime (LPC_RTC_TypeDef *RTCx, RTC_TIME_Type *pFullTime)
+{
+ CHECK_PARAM(PARAM_RTCx(RTCx));
+
+ RTCx->DOM = pFullTime->DOM & RTC_DOM_MASK;
+ RTCx->DOW = pFullTime->DOW & RTC_DOW_MASK;
+ RTCx->DOY = pFullTime->DOY & RTC_DOY_MASK;
+ RTCx->HOUR = pFullTime->HOUR & RTC_HOUR_MASK;
+ RTCx->MIN = pFullTime->MIN & RTC_MIN_MASK;
+ RTCx->SEC = pFullTime->SEC & RTC_SEC_MASK;
+ RTCx->MONTH = pFullTime->MONTH & RTC_MONTH_MASK;
+ RTCx->YEAR = pFullTime->YEAR & RTC_YEAR_MASK;
+}
+
+
+/*********************************************************************//**
+ * @brief Get full of time in RTC peripheral
+ * @param[in] RTCx RTC peripheral selected, should be LPC_RTC
+ * @param[in] pFullTime Pointer to a RTC_TIME_Type structure that
+ * will be stored time in full.
+ * @return None
+ **********************************************************************/
+void RTC_GetFullTime (LPC_RTC_TypeDef *RTCx, RTC_TIME_Type *pFullTime)
+{
+ CHECK_PARAM(PARAM_RTCx(RTCx));
+
+ pFullTime->DOM = RTCx->DOM & RTC_DOM_MASK;
+ pFullTime->DOW = RTCx->DOW & RTC_DOW_MASK;
+ pFullTime->DOY = RTCx->DOY & RTC_DOY_MASK;
+ pFullTime->HOUR = RTCx->HOUR & RTC_HOUR_MASK;
+ pFullTime->MIN = RTCx->MIN & RTC_MIN_MASK;
+ pFullTime->SEC = RTCx->SEC & RTC_SEC_MASK;
+ pFullTime->MONTH = RTCx->MONTH & RTC_MONTH_MASK;
+ pFullTime->YEAR = RTCx->YEAR & RTC_YEAR_MASK;
+}
+
+
+/*********************************************************************//**
+ * @brief Set alarm time value for each time type
+ * @param[in] RTCx RTC peripheral selected, should be LPC_RTC
+ * @param[in] Timetype: Time Type, should be:
+ * - RTC_TIMETYPE_SECOND
+ * - RTC_TIMETYPE_MINUTE
+ * - RTC_TIMETYPE_HOUR
+ * - RTC_TIMETYPE_DAYOFWEEK
+ * - RTC_TIMETYPE_DAYOFMONTH
+ * - RTC_TIMETYPE_DAYOFYEAR
+ * - RTC_TIMETYPE_MONTH
+ * - RTC_TIMETYPE_YEAR
+ * @param[in] ALValue Alarm time value to set
+ * @return None
+ **********************************************************************/
+void RTC_SetAlarmTime (LPC_RTC_TypeDef *RTCx, uint32_t Timetype, uint32_t ALValue)
+{
+ CHECK_PARAM(PARAM_RTCx(RTCx));
+
+ switch (Timetype)
+ {
+ case RTC_TIMETYPE_SECOND:
+ CHECK_PARAM(ALValue < RTC_SECOND_MAX);
+
+ RTCx->ALSEC = ALValue & RTC_SEC_MASK;
+ break;
+
+ case RTC_TIMETYPE_MINUTE:
+ CHECK_PARAM(ALValue < RTC_MINUTE_MAX);
+
+ RTCx->ALMIN = ALValue & RTC_MIN_MASK;
+ break;
+
+ case RTC_TIMETYPE_HOUR:
+ CHECK_PARAM(ALValue < RTC_HOUR_MAX);
+
+ RTCx->ALHOUR = ALValue & RTC_HOUR_MASK;
+ break;
+
+ case RTC_TIMETYPE_DAYOFWEEK:
+ CHECK_PARAM(ALValue < RTC_DAYOFWEEK_MAX);
+
+ RTCx->ALDOW = ALValue & RTC_DOW_MASK;
+ break;
+
+ case RTC_TIMETYPE_DAYOFMONTH:
+ CHECK_PARAM((ALValue < RTC_DAYOFMONTH_MAX) \
+ && (ALValue > RTC_DAYOFMONTH_MIN));
+
+ RTCx->ALDOM = ALValue & RTC_DOM_MASK;
+ break;
+
+ case RTC_TIMETYPE_DAYOFYEAR:
+ CHECK_PARAM((ALValue > RTC_DAYOFYEAR_MIN) \
+ && (ALValue < RTC_DAYOFYEAR_MAX));
+
+ RTCx->ALDOY = ALValue & RTC_DOY_MASK;
+ break;
+
+ case RTC_TIMETYPE_MONTH:
+ CHECK_PARAM((ALValue > RTC_MONTH_MIN) \
+ && (ALValue < RTC_MONTH_MAX));
+
+ RTCx->ALMON = ALValue & RTC_MONTH_MASK;
+ break;
+
+ case RTC_TIMETYPE_YEAR:
+ CHECK_PARAM(ALValue < RTC_YEAR_MAX);
+
+ RTCx->ALYEAR = ALValue & RTC_YEAR_MASK;
+ break;
+ }
+}
+
+
+
+/*********************************************************************//**
+ * @brief Get alarm time value for each time type
+ * @param[in] RTCx RTC peripheral selected, should be LPC_RTC
+ * @param[in] Timetype: Time Type, should be:
+ * - RTC_TIMETYPE_SECOND
+ * - RTC_TIMETYPE_MINUTE
+ * - RTC_TIMETYPE_HOUR
+ * - RTC_TIMETYPE_DAYOFWEEK
+ * - RTC_TIMETYPE_DAYOFMONTH
+ * - RTC_TIMETYPE_DAYOFYEAR
+ * - RTC_TIMETYPE_MONTH
+ * - RTC_TIMETYPE_YEAR
+ * @return Value of Alarm time according to specified time type
+ **********************************************************************/
+uint32_t RTC_GetAlarmTime (LPC_RTC_TypeDef *RTCx, uint32_t Timetype)
+{
+ switch (Timetype)
+ {
+ case RTC_TIMETYPE_SECOND:
+ return (RTCx->ALSEC & RTC_SEC_MASK);
+ case RTC_TIMETYPE_MINUTE:
+ return (RTCx->ALMIN & RTC_MIN_MASK);
+ case RTC_TIMETYPE_HOUR:
+ return (RTCx->ALHOUR & RTC_HOUR_MASK);
+ case RTC_TIMETYPE_DAYOFWEEK:
+ return (RTCx->ALDOW & RTC_DOW_MASK);
+ case RTC_TIMETYPE_DAYOFMONTH:
+ return (RTCx->ALDOM & RTC_DOM_MASK);
+ case RTC_TIMETYPE_DAYOFYEAR:
+ return (RTCx->ALDOY & RTC_DOY_MASK);
+ case RTC_TIMETYPE_MONTH:
+ return (RTCx->ALMON & RTC_MONTH_MASK);
+ case RTC_TIMETYPE_YEAR:
+ return (RTCx->ALYEAR & RTC_YEAR_MASK);
+ default:
+ return (0);
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Set full of alarm time in RTC peripheral
+ * @param[in] RTCx RTC peripheral selected, should be LPC_RTC
+ * @param[in] pFullTime Pointer to a RTC_TIME_Type structure that
+ * contains alarm time value in full.
+ * @return None
+ **********************************************************************/
+void RTC_SetFullAlarmTime (LPC_RTC_TypeDef *RTCx, RTC_TIME_Type *pFullTime)
+{
+ CHECK_PARAM(PARAM_RTCx(RTCx));
+
+ RTCx->ALDOM = pFullTime->DOM & RTC_DOM_MASK;
+ RTCx->ALDOW = pFullTime->DOW & RTC_DOW_MASK;
+ RTCx->ALDOY = pFullTime->DOY & RTC_DOY_MASK;
+ RTCx->ALHOUR = pFullTime->HOUR & RTC_HOUR_MASK;
+ RTCx->ALMIN = pFullTime->MIN & RTC_MIN_MASK;
+ RTCx->ALSEC = pFullTime->SEC & RTC_SEC_MASK;
+ RTCx->ALMON = pFullTime->MONTH & RTC_MONTH_MASK;
+ RTCx->ALYEAR = pFullTime->YEAR & RTC_YEAR_MASK;
+}
+
+
+/*********************************************************************//**
+ * @brief Get full of alarm time in RTC peripheral
+ * @param[in] RTCx RTC peripheral selected, should be LPC_RTC
+ * @param[in] pFullTime Pointer to a RTC_TIME_Type structure that
+ * will be stored alarm time in full.
+ * @return None
+ **********************************************************************/
+void RTC_GetFullAlarmTime (LPC_RTC_TypeDef *RTCx, RTC_TIME_Type *pFullTime)
+{
+ CHECK_PARAM(PARAM_RTCx(RTCx));
+
+ pFullTime->DOM = RTCx->ALDOM & RTC_DOM_MASK;
+ pFullTime->DOW = RTCx->ALDOW & RTC_DOW_MASK;
+ pFullTime->DOY = RTCx->ALDOY & RTC_DOY_MASK;
+ pFullTime->HOUR = RTCx->ALHOUR & RTC_HOUR_MASK;
+ pFullTime->MIN = RTCx->ALMIN & RTC_MIN_MASK;
+ pFullTime->SEC = RTCx->ALSEC & RTC_SEC_MASK;
+ pFullTime->MONTH = RTCx->ALMON & RTC_MONTH_MASK;
+ pFullTime->YEAR = RTCx->ALYEAR & RTC_YEAR_MASK;
+}
+
+
+/*********************************************************************//**
+ * @brief Check whether if specified Location interrupt in
+ * RTC peripheral is set or not
+ * @param[in] RTCx RTC peripheral selected, should be LPC_RTC
+ * @param[in] IntType Interrupt location type, should be:
+ * - RTC_INT_COUNTER_INCREASE: Counter Increment Interrupt
+ * block generated an interrupt.
+ * - RTC_INT_ALARM: Alarm generated an
+ * interrupt.
+ * @return New state of specified Location interrupt in RTC peripheral
+ * (SET or RESET)
+ **********************************************************************/
+IntStatus RTC_GetIntPending (LPC_RTC_TypeDef *RTCx, uint32_t IntType)
+{
+ CHECK_PARAM(PARAM_RTCx(RTCx));
+ CHECK_PARAM(PARAM_RTC_INT(IntType));
+
+ return ((RTCx->ILR & IntType) ? SET : RESET);
+}
+
+
+/*********************************************************************//**
+ * @brief Clear specified Location interrupt pending in
+ * RTC peripheral
+ * @param[in] RTCx RTC peripheral selected, should be LPC_RTC
+ * @param[in] IntType Interrupt location type, should be:
+ * - RTC_INT_COUNTER_INCREASE: Clear Counter Increment
+ * Interrupt pending.
+ * - RTC_INT_ALARM: Clear alarm interrupt pending
+ * @return None
+ **********************************************************************/
+void RTC_ClearIntPending (LPC_RTC_TypeDef *RTCx, uint32_t IntType)
+{
+ CHECK_PARAM(PARAM_RTCx(RTCx));
+ CHECK_PARAM(PARAM_RTC_INT(IntType));
+
+ RTCx->ILR |= IntType;
+}
+
+/*********************************************************************//**
+ * @brief Enable/Disable calibration counter in RTC peripheral
+ * @param[in] RTCx RTC peripheral selected, should be LPC_RTC
+ * @param[in] NewState New State of this function, should be:
+ * - ENABLE: The calibration counter is enabled and counting
+ * - DISABLE: The calibration counter is disabled and reset to zero
+ * @return None
+ **********************************************************************/
+void RTC_CalibCounterCmd(LPC_RTC_TypeDef *RTCx, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_RTCx(RTCx));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ if (NewState == ENABLE)
+ {
+ RTCx->CCR &= (~RTC_CCR_CCALEN) & RTC_CCR_BITMASK;
+ }
+ else
+ {
+ RTCx->CCR |= RTC_CCR_CCALEN;
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Configures Calibration in RTC peripheral
+ * @param[in] RTCx RTC peripheral selected, should be LPC_RTC
+ * @param[in] CalibValue Calibration value, should be in range from
+ * 0 to 131,072
+ * @param[in] CalibDir Calibration Direction, should be:
+ * - RTC_CALIB_DIR_FORWARD: Forward calibration
+ * - RTC_CALIB_DIR_BACKWARD: Backward calibration
+ * @return None
+ **********************************************************************/
+void RTC_CalibConfig(LPC_RTC_TypeDef *RTCx, uint32_t CalibValue, uint8_t CalibDir)
+{
+ CHECK_PARAM(PARAM_RTCx(RTCx));
+ CHECK_PARAM(PARAM_RTC_CALIB_DIR(CalibDir));
+ CHECK_PARAM(CalibValue < RTC_CALIBRATION_MAX);
+
+ RTCx->CALIBRATION = ((CalibValue - 1) & RTC_CALIBRATION_CALVAL_MASK) \
+ | ((CalibDir == RTC_CALIB_DIR_BACKWARD) ? RTC_CALIBRATION_LIBDIR : 0);
+}
+
+
+/*********************************************************************//**
+ * @brief Write value to General purpose registers
+ * @param[in] RTCx RTC peripheral selected, should be LPC_RTC
+ * @param[in] Channel General purpose registers Channel number,
+ * should be in range from 0 to 4.
+ * @param[in] Value Value to write
+ * @return None
+ * Note: These General purpose registers can be used to store important
+ * information when the main power supply is off. The value in these
+ * registers is not affected by chip reset.
+ **********************************************************************/
+void RTC_WriteGPREG (LPC_RTC_TypeDef *RTCx, uint8_t Channel, uint32_t Value)
+{
+ uint32_t *preg;
+
+ CHECK_PARAM(PARAM_RTCx(RTCx));
+ CHECK_PARAM(PARAM_RTC_GPREG_CH(Channel));
+
+ preg = (uint32_t *)&RTCx->GPREG0;
+ preg += Channel;
+ *preg = Value;
+}
+
+
+/*********************************************************************//**
+ * @brief Read value from General purpose registers
+ * @param[in] RTCx RTC peripheral selected, should be LPC_RTC
+ * @param[in] Channel General purpose registers Channel number,
+ * should be in range from 0 to 4.
+ * @return Read Value
+ * Note: These General purpose registers can be used to store important
+ * information when the main power supply is off. The value in these
+ * registers is not affected by chip reset.
+ **********************************************************************/
+uint32_t RTC_ReadGPREG (LPC_RTC_TypeDef *RTCx, uint8_t Channel)
+{
+ uint32_t *preg;
+ uint32_t value;
+
+ CHECK_PARAM(PARAM_RTCx(RTCx));
+ CHECK_PARAM(PARAM_RTC_GPREG_CH(Channel));
+
+ preg = (uint32_t *)&RTCx->GPREG0;
+ preg += Channel;
+ value = *preg;
+ return (value);
+}
+
+/**
+ * @}
+ */
+
+#endif /* _RTC */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
+
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_spi.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_spi.c
new file mode 100644
index 0000000..7643de7
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_spi.c
@@ -0,0 +1,431 @@
+/***********************************************************************//**
+ * @file lpc17xx_spi.c
+ * @brief Contains all functions support for SPI firmware library on LPC17xx
+ * @version 2.0
+ * @date 21. May. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup SPI
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_spi.h"
+#include "lpc17xx_clkpwr.h"
+
+/* If this source file built with example, the LPC17xx FW library configuration
+ * file in each example directory ("lpc17xx_libcfg.h") must be included,
+ * otherwise the default FW library configuration file must be included instead
+ */
+#ifdef __BUILD_WITH_EXAMPLE__
+#include "lpc17xx_libcfg.h"
+#else
+#include "lpc17xx_libcfg_default.h"
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+#ifdef _SPI
+
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup SPI_Public_Functions
+ * @{
+ */
+
+/*********************************************************************//**
+ * @brief Setup clock rate for SPI device
+ * @param[in] SPIx SPI peripheral definition, should be LPC_SPI
+ * @param[in] target_clock : clock of SPI (Hz)
+ * @return None
+ ***********************************************************************/
+void SPI_SetClock (LPC_SPI_TypeDef *SPIx, uint32_t target_clock)
+{
+ uint32_t spi_pclk;
+ uint32_t prescale, temp;
+
+ CHECK_PARAM(PARAM_SPIx(SPIx));
+
+ if (SPIx == LPC_SPI){
+ spi_pclk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_SPI);
+ } else {
+ return;
+ }
+
+ prescale = 8;
+ // Find closest clock to target clock
+ while (1){
+ temp = target_clock * prescale;
+ if (temp >= spi_pclk){
+ break;
+ }
+ prescale += 2;
+ if(prescale >= 254){
+ break;
+ }
+ }
+
+ // Write to register
+ SPIx->SPCCR = SPI_SPCCR_COUNTER(prescale);
+}
+
+
+/*********************************************************************//**
+ * @brief De-initializes the SPIx peripheral registers to their
+* default reset values.
+ * @param[in] SPIx SPI peripheral selected, should be LPC_SPI
+ * @return None
+ **********************************************************************/
+void SPI_DeInit(LPC_SPI_TypeDef *SPIx)
+{
+ CHECK_PARAM(PARAM_SPIx(SPIx));
+
+ if (SPIx == LPC_SPI){
+ /* Set up clock and power for SPI module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCSPI, DISABLE);
+ }
+}
+
+/*********************************************************************//**
+ * @brief Get data bit size per transfer
+ * @param[in] SPIx SPI peripheral selected, should be LPC_SPI
+ * @return number of bit per transfer, could be 8-16
+ **********************************************************************/
+uint8_t SPI_GetDataSize (LPC_SPI_TypeDef *SPIx)
+{
+ CHECK_PARAM(PARAM_SPIx(SPIx));
+ return ((SPIx->SPCR)>>8 & 0xF);
+}
+
+/********************************************************************//**
+ * @brief Initializes the SPIx peripheral according to the specified
+* parameters in the UART_ConfigStruct.
+ * @param[in] SPIx SPI peripheral selected, should be LPC_SPI
+ * @param[in] SPI_ConfigStruct Pointer to a SPI_CFG_Type structure
+* that contains the configuration information for the
+* specified SPI peripheral.
+ * @return None
+ *********************************************************************/
+void SPI_Init(LPC_SPI_TypeDef *SPIx, SPI_CFG_Type *SPI_ConfigStruct)
+{
+ uint32_t tmp;
+
+ CHECK_PARAM(PARAM_SPIx(SPIx));
+
+ if(SPIx == LPC_SPI){
+ /* Set up clock and power for UART module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCSPI, ENABLE);
+ } else {
+ return;
+ }
+
+ // Configure SPI, interrupt is disable as default
+ tmp = ((SPI_ConfigStruct->CPHA) | (SPI_ConfigStruct->CPOL) \
+ | (SPI_ConfigStruct->DataOrder) | (SPI_ConfigStruct->Databit) \
+ | (SPI_ConfigStruct->Mode) | SPI_SPCR_BIT_EN) & SPI_SPCR_BITMASK;
+ // write back to SPI control register
+ SPIx->SPCR = tmp;
+
+ // Set clock rate for SPI peripheral
+ SPI_SetClock(SPIx, SPI_ConfigStruct->ClockRate);
+
+ // If interrupt flag is set, Write '1' to Clear interrupt flag
+ if (SPIx->SPINT & SPI_SPINT_INTFLAG){
+ SPIx->SPINT = SPI_SPINT_INTFLAG;
+ }
+}
+
+
+
+/*****************************************************************************//**
+* @brief Fills each SPI_InitStruct member with its default value:
+* - CPHA = SPI_CPHA_FIRST
+* - CPOL = SPI_CPOL_HI
+* - ClockRate = 1000000
+* - DataOrder = SPI_DATA_MSB_FIRST
+* - Databit = SPI_DATABIT_8
+* - Mode = SPI_MASTER_MODE
+* @param[in] SPI_InitStruct Pointer to a SPI_CFG_Type structure
+* which will be initialized.
+* @return None
+*******************************************************************************/
+void SPI_ConfigStructInit(SPI_CFG_Type *SPI_InitStruct)
+{
+ SPI_InitStruct->CPHA = SPI_CPHA_FIRST;
+ SPI_InitStruct->CPOL = SPI_CPOL_HI;
+ SPI_InitStruct->ClockRate = 1000000;
+ SPI_InitStruct->DataOrder = SPI_DATA_MSB_FIRST;
+ SPI_InitStruct->Databit = SPI_DATABIT_8;
+ SPI_InitStruct->Mode = SPI_MASTER_MODE;
+}
+
+/*********************************************************************//**
+ * @brief Transmit a single data through SPIx peripheral
+ * @param[in] SPIx SPI peripheral selected, should be LPC_SPI
+ * @param[in] Data Data to transmit (must be 16 or 8-bit long,
+ * this depend on SPI data bit number configured)
+ * @return none
+ **********************************************************************/
+void SPI_SendData(LPC_SPI_TypeDef* SPIx, uint16_t Data)
+{
+ CHECK_PARAM(PARAM_SPIx(SPIx));
+
+ SPIx->SPDR = Data & SPI_SPDR_BITMASK;
+}
+
+
+
+/*********************************************************************//**
+ * @brief Receive a single data from SPIx peripheral
+ * @param[in] SPIx SPI peripheral selected, should be LPC_SPI
+ * @return Data received (16-bit long)
+ **********************************************************************/
+uint16_t SPI_ReceiveData(LPC_SPI_TypeDef* SPIx)
+{
+ CHECK_PARAM(PARAM_SPIx(SPIx));
+
+ return ((uint16_t) (SPIx->SPDR & SPI_SPDR_BITMASK));
+}
+
+/*********************************************************************//**
+ * @brief SPI Read write data function
+ * @param[in] SPIx Pointer to SPI peripheral, should be LPC_SPI
+ * @param[in] dataCfg Pointer to a SPI_DATA_SETUP_Type structure that
+ * contains specified information about transmit
+ * data configuration.
+ * @param[in] xfType Transfer type, should be:
+ * - SPI_TRANSFER_POLLING: Polling mode
+ * - SPI_TRANSFER_INTERRUPT: Interrupt mode
+ * @return Actual Data length has been transferred in polling mode.
+ * In interrupt mode, always return (0)
+ * Return (-1) if error.
+ * Note: This function can be used in both master and slave mode.
+ ***********************************************************************/
+int32_t SPI_ReadWrite (LPC_SPI_TypeDef *SPIx, SPI_DATA_SETUP_Type *dataCfg, \
+ SPI_TRANSFER_Type xfType)
+{
+ uint8_t *rdata8;
+ uint8_t *wdata8;
+ uint16_t *rdata16;
+ uint16_t *wdata16;
+ uint32_t stat;
+ uint32_t temp;
+ uint8_t dataword;
+
+ //read for empty buffer
+ temp = SPIx->SPDR;
+ //dummy to clear status
+ temp = SPIx->SPSR;
+ dataCfg->counter = 0;
+ dataCfg->status = 0;
+
+ if(SPI_GetDataSize (SPIx) == 8)
+ dataword = 0;
+ else dataword = 1;
+ if (xfType == SPI_TRANSFER_POLLING){
+
+ if (dataword == 0){
+ rdata8 = (uint8_t *)dataCfg->rx_data;
+ wdata8 = (uint8_t *)dataCfg->tx_data;
+ } else {
+ rdata16 = (uint16_t *)dataCfg->rx_data;
+ wdata16 = (uint16_t *)dataCfg->tx_data;
+ }
+
+ while(dataCfg->counter < dataCfg->length)
+ {
+ // Write data to buffer
+ if(dataCfg->tx_data == NULL){
+ if (dataword == 0){
+ SPI_SendData(SPIx, 0xFF);
+ } else {
+ SPI_SendData(SPIx, 0xFFFF);
+ }
+ } else {
+ if (dataword == 0){
+ SPI_SendData(SPIx, *wdata8);
+ wdata8++;
+ } else {
+ SPI_SendData(SPIx, *wdata16);
+ wdata16++;
+ }
+ }
+ // Wait for transfer complete
+ while (!((stat = SPIx->SPSR) & SPI_SPSR_SPIF));
+ // Check for error
+ if (stat & (SPI_SPSR_ABRT | SPI_SPSR_MODF | SPI_SPSR_ROVR | SPI_SPSR_WCOL)){
+ // save status
+ dataCfg->status = stat | SPI_STAT_ERROR;
+ return (dataCfg->counter);
+ }
+ // Read data from SPI dat
+ temp = (uint32_t) SPI_ReceiveData(SPIx);
+
+ // Store data to destination
+ if (dataCfg->rx_data != NULL)
+ {
+ if (dataword == 0){
+ *(rdata8) = (uint8_t) temp;
+ rdata8++;
+ } else {
+ *(rdata16) = (uint16_t) temp;
+ rdata16++;
+ }
+ }
+ // Increase counter
+ if (dataword == 0){
+ dataCfg->counter++;
+ } else {
+ dataCfg->counter += 2;
+ }
+ }
+
+ // Return length of actual data transferred
+ // save status
+ dataCfg->status = stat | SPI_STAT_DONE;
+ return (dataCfg->counter);
+ }
+ // Interrupt mode
+ else {
+
+ // Check if interrupt flag is already set
+ if(SPIx->SPINT & SPI_SPINT_INTFLAG){
+ SPIx->SPINT = SPI_SPINT_INTFLAG;
+ }
+ if (dataCfg->counter < dataCfg->length){
+ // Write data to buffer
+ if(dataCfg->tx_data == NULL){
+ if (dataword == 0){
+ SPI_SendData(SPIx, 0xFF);
+ } else {
+ SPI_SendData(SPIx, 0xFFFF);
+ }
+ } else {
+ if (dataword == 0){
+ SPI_SendData(SPIx, (*(uint8_t *)dataCfg->tx_data));
+ } else {
+ SPI_SendData(SPIx, (*(uint16_t *)dataCfg->tx_data));
+ }
+ }
+ SPI_IntCmd(SPIx, ENABLE);
+ } else {
+ // Save status
+ dataCfg->status = SPI_STAT_DONE;
+ }
+ return (0);
+ }
+}
+
+
+/********************************************************************//**
+ * @brief Enable or disable SPIx interrupt.
+ * @param[in] SPIx SPI peripheral selected, should be LPC_SPI
+ * @param[in] NewState New state of specified UART interrupt type,
+ * should be:
+ * - ENALBE: Enable this SPI interrupt.
+* - DISALBE: Disable this SPI interrupt.
+ * @return None
+ *********************************************************************/
+void SPI_IntCmd(LPC_SPI_TypeDef *SPIx, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_SPIx(SPIx));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ if (NewState == ENABLE)
+ {
+ SPIx->SPCR |= SPI_SPCR_SPIE;
+ }
+ else
+ {
+ SPIx->SPCR &= (~SPI_SPCR_SPIE) & SPI_SPCR_BITMASK;
+ }
+}
+
+
+/********************************************************************//**
+ * @brief Checks whether the SPI interrupt flag is set or not.
+ * @param[in] SPIx SPI peripheral selected, should be LPC_SPI
+ * @return The new state of SPI Interrupt Flag (SET or RESET)
+ *********************************************************************/
+IntStatus SPI_GetIntStatus (LPC_SPI_TypeDef *SPIx)
+{
+ CHECK_PARAM(PARAM_SPIx(SPIx));
+
+ return ((SPIx->SPINT & SPI_SPINT_INTFLAG) ? SET : RESET);
+}
+
+/********************************************************************//**
+ * @brief Clear SPI interrupt flag.
+ * @param[in] SPIx SPI peripheral selected, should be LPC_SPI
+ * @return None
+ *********************************************************************/
+void SPI_ClearIntPending(LPC_SPI_TypeDef *SPIx)
+{
+ CHECK_PARAM(PARAM_SPIx(SPIx));
+
+ SPIx->SPINT = SPI_SPINT_INTFLAG;
+}
+
+/********************************************************************//**
+ * @brief Get current value of SPI Status register in SPIx peripheral.
+ * @param[in] SPIx SPI peripheral selected, should be LPC_SPI
+ * @return Current value of SPI Status register in SPI peripheral.
+ * Note: The return value of this function must be used with
+ * SPI_CheckStatus() to determine current flag status
+ * corresponding to each SPI status type. Because some flags in
+ * SPI Status register will be cleared after reading, the next reading
+ * SPI Status register could not be correct. So this function used to
+ * read SPI status register in one time only, then the return value
+ * used to check all flags.
+ *********************************************************************/
+uint32_t SPI_GetStatus(LPC_SPI_TypeDef* SPIx)
+{
+ CHECK_PARAM(PARAM_SPIx(SPIx));
+
+ return (SPIx->SPSR & SPI_SPSR_BITMASK);
+}
+
+/********************************************************************//**
+ * @brief Checks whether the specified SPI Status flag is set or not
+ * via inputSPIStatus parameter.
+ * @param[in] inputSPIStatus Value to check status of each flag type.
+ * This value is the return value from SPI_GetStatus().
+ * @param[in] SPIStatus Specifies the SPI status flag to check,
+ * should be one of the following:
+ - SPI_STAT_ABRT: Slave abort.
+ - SPI_STAT_MODF: Mode fault.
+ - SPI_STAT_ROVR: Read overrun.
+ - SPI_STAT_WCOL: Write collision.
+ - SPI_STAT_SPIF: SPI transfer complete.
+ * @return The new state of SPIStatus (SET or RESET)
+ *********************************************************************/
+FlagStatus SPI_CheckStatus (uint32_t inputSPIStatus, uint8_t SPIStatus)
+{
+ CHECK_PARAM(PARAM_SPI_STAT(SPIStatus));
+
+ return ((inputSPIStatus & SPIStatus) ? SET : RESET);
+}
+
+
+/**
+ * @}
+ */
+
+#endif /* _SPI */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_ssp.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_ssp.c
new file mode 100644
index 0000000..bbf03a6
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_ssp.c
@@ -0,0 +1,682 @@
+/***********************************************************************//**
+ * @file lpc17xx_ssp.c
+ * @brief Contains all functions support for SSP firmware library on LPC17xx
+ * @version 3.0
+ * @date 18. June. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup SSP
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_ssp.h"
+#include "lpc17xx_clkpwr.h"
+
+
+/* If this source file built with example, the LPC17xx FW library configuration
+ * file in each example directory ("lpc17xx_libcfg.h") must be included,
+ * otherwise the default FW library configuration file must be included instead
+ */
+#ifdef __BUILD_WITH_EXAMPLE__
+#include "lpc17xx_libcfg.h"
+#else
+#include "lpc17xx_libcfg_default.h"
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+
+#ifdef _SSP
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup SSP_Public_Functions
+ * @{
+ */
+static void setSSPclock (LPC_SSP_TypeDef *SSPx, uint32_t target_clock);
+
+/*********************************************************************//**
+ * @brief Setup clock rate for SSP device
+ * @param[in] SSPx SSP peripheral definition, should be:
+ * - LPC_SSP0: SSP0 peripheral
+ * - LPC_SSP1: SSP1 peripheral
+ * @param[in] target_clock : clock of SSP (Hz)
+ * @return None
+ ***********************************************************************/
+static void setSSPclock (LPC_SSP_TypeDef *SSPx, uint32_t target_clock)
+{
+ uint32_t prescale, cr0_div, cmp_clk, ssp_clk;
+
+ CHECK_PARAM(PARAM_SSPx(SSPx));
+
+ /* The SSP clock is derived from the (main system oscillator / 2),
+ so compute the best divider from that clock */
+ if (SSPx == LPC_SSP0){
+ ssp_clk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_SSP0);
+ } else if (SSPx == LPC_SSP1) {
+ ssp_clk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_SSP1);
+ } else {
+ return;
+ }
+
+ /* Find closest divider to get at or under the target frequency.
+ Use smallest prescale possible and rely on the divider to get
+ the closest target frequency */
+ cr0_div = 0;
+ cmp_clk = 0xFFFFFFFF;
+ prescale = 2;
+ while (cmp_clk > target_clock)
+ {
+ cmp_clk = ssp_clk / ((cr0_div + 1) * prescale);
+ if (cmp_clk > target_clock)
+ {
+ cr0_div++;
+ if (cr0_div > 0xFF)
+ {
+ cr0_div = 0;
+ prescale += 2;
+ }
+ }
+ }
+
+ /* Write computed prescaler and divider back to register */
+ SSPx->CR0 &= (~SSP_CR0_SCR(0xFF)) & SSP_CR0_BITMASK;
+ SSPx->CR0 |= (SSP_CR0_SCR(cr0_div)) & SSP_CR0_BITMASK;
+ SSPx->CPSR = prescale & SSP_CPSR_BITMASK;
+}
+
+/**
+ * @}
+ */
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup SSP_Public_Functions
+ * @{
+ */
+
+/********************************************************************//**
+ * @brief Initializes the SSPx peripheral according to the specified
+* parameters in the SSP_ConfigStruct.
+ * @param[in] SSPx SSP peripheral selected, should be:
+ * - LPC_SSP0: SSP0 peripheral
+ * - LPC_SSP1: SSP1 peripheral
+ * @param[in] SSP_ConfigStruct Pointer to a SSP_CFG_Type structure
+* that contains the configuration information for the
+* specified SSP peripheral.
+ * @return None
+ *********************************************************************/
+void SSP_Init(LPC_SSP_TypeDef *SSPx, SSP_CFG_Type *SSP_ConfigStruct)
+{
+ uint32_t tmp;
+
+ CHECK_PARAM(PARAM_SSPx(SSPx));
+
+ if(SSPx == LPC_SSP0) {
+ /* Set up clock and power for SSP0 module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCSSP0, ENABLE);
+ } else if(SSPx == LPC_SSP1) {
+ /* Set up clock and power for SSP1 module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCSSP1, ENABLE);
+ } else {
+ return;
+ }
+
+ /* Configure SSP, interrupt is disable, LoopBack mode is disable,
+ * SSP is disable, Slave output is disable as default
+ */
+ tmp = ((SSP_ConfigStruct->CPHA) | (SSP_ConfigStruct->CPOL) \
+ | (SSP_ConfigStruct->FrameFormat) | (SSP_ConfigStruct->Databit))
+ & SSP_CR0_BITMASK;
+ // write back to SSP control register
+ SSPx->CR0 = tmp;
+
+ tmp = SSP_ConfigStruct->Mode & SSP_CR1_BITMASK;
+ // Write back to CR1
+ SSPx->CR1 = tmp;
+
+ // Set clock rate for SSP peripheral
+ setSSPclock(SSPx, SSP_ConfigStruct->ClockRate);
+}
+
+/*********************************************************************//**
+ * @brief De-initializes the SSPx peripheral registers to their
+* default reset values.
+ * @param[in] SSPx SSP peripheral selected, should be:
+ * - LPC_SSP0: SSP0 peripheral
+ * - LPC_SSP1: SSP1 peripheral
+ * @return None
+ **********************************************************************/
+void SSP_DeInit(LPC_SSP_TypeDef* SSPx)
+{
+ CHECK_PARAM(PARAM_SSPx(SSPx));
+
+ if (SSPx == LPC_SSP0){
+ /* Set up clock and power for SSP0 module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCSSP0, DISABLE);
+ } else if (SSPx == LPC_SSP1) {
+ /* Set up clock and power for SSP1 module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCSSP1, DISABLE);
+ }
+}
+
+/*****************************************************************************//**
+* @brief Get data size bit selected
+* @param[in] SSPx pointer to LPC_SSP_TypeDef structure, should be:
+* - LPC_SSP0: SSP0 peripheral
+* - LPC_SSP1: SSP1 peripheral
+* @return Data size, could be:
+* - SSP_DATABIT_4: 4 bit transfer
+* - SSP_DATABIT_5: 5 bit transfer
+* ...
+* - SSP_DATABIT_16: 16 bit transfer
+*******************************************************************************/
+uint8_t SSP_GetDataSize(LPC_SSP_TypeDef* SSPx)
+{
+ CHECK_PARAM(PARAM_SSPx(SSPx));
+ return (SSPx->CR0 & (0xF));
+}
+
+/*****************************************************************************//**
+* @brief Fills each SSP_InitStruct member with its default value:
+* - CPHA = SSP_CPHA_FIRST
+* - CPOL = SSP_CPOL_HI
+* - ClockRate = 1000000
+* - Databit = SSP_DATABIT_8
+* - Mode = SSP_MASTER_MODE
+* - FrameFormat = SSP_FRAME_SSP
+* @param[in] SSP_InitStruct Pointer to a SSP_CFG_Type structure
+* which will be initialized.
+* @return None
+*******************************************************************************/
+void SSP_ConfigStructInit(SSP_CFG_Type *SSP_InitStruct)
+{
+ SSP_InitStruct->CPHA = SSP_CPHA_FIRST;
+ SSP_InitStruct->CPOL = SSP_CPOL_HI;
+ SSP_InitStruct->ClockRate = 1000000;
+ SSP_InitStruct->Databit = SSP_DATABIT_8;
+ SSP_InitStruct->Mode = SSP_MASTER_MODE;
+ SSP_InitStruct->FrameFormat = SSP_FRAME_SPI;
+}
+
+
+/*********************************************************************//**
+ * @brief Enable or disable SSP peripheral's operation
+ * @param[in] SSPx SSP peripheral, should be:
+ * - LPC_SSP0: SSP0 peripheral
+ * - LPC_SSP1: SSP1 peripheral
+ * @param[in] NewState New State of SSPx peripheral's operation
+ * @return none
+ **********************************************************************/
+void SSP_Cmd(LPC_SSP_TypeDef* SSPx, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_SSPx(SSPx));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ if (NewState == ENABLE)
+ {
+ SSPx->CR1 |= SSP_CR1_SSP_EN;
+ }
+ else
+ {
+ SSPx->CR1 &= (~SSP_CR1_SSP_EN) & SSP_CR1_BITMASK;
+ }
+}
+
+/*********************************************************************//**
+ * @brief Enable or disable Loop Back mode function in SSP peripheral
+ * @param[in] SSPx SSP peripheral selected, should be:
+ * - LPC_SSP0: SSP0 peripheral
+ * - LPC_SSP1: SSP1 peripheral
+ * @param[in] NewState New State of Loop Back mode, should be:
+ * - ENABLE: Enable this function
+ * - DISABLE: Disable this function
+ * @return None
+ **********************************************************************/
+void SSP_LoopBackCmd(LPC_SSP_TypeDef* SSPx, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_SSPx(SSPx));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ if (NewState == ENABLE)
+ {
+ SSPx->CR1 |= SSP_CR1_LBM_EN;
+ }
+ else
+ {
+ SSPx->CR1 &= (~SSP_CR1_LBM_EN) & SSP_CR1_BITMASK;
+ }
+}
+
+/*********************************************************************//**
+ * @brief Enable or disable Slave Output function in SSP peripheral
+ * @param[in] SSPx SSP peripheral selected, should be:
+ * - LPC_SSP0: SSP0 peripheral
+ * - LPC_SSP1: SSP1 peripheral
+ * @param[in] NewState New State of Slave Output function, should be:
+ * - ENABLE: Slave Output in normal operation
+ * - DISABLE: Slave Output is disabled. This blocks
+ * SSP controller from driving the transmit data
+ * line (MISO)
+ * Note: This function is available when SSP peripheral in Slave mode
+ * @return None
+ **********************************************************************/
+void SSP_SlaveOutputCmd(LPC_SSP_TypeDef* SSPx, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_SSPx(SSPx));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ if (NewState == ENABLE)
+ {
+ SSPx->CR1 &= (~SSP_CR1_SO_DISABLE) & SSP_CR1_BITMASK;
+ }
+ else
+ {
+ SSPx->CR1 |= SSP_CR1_SO_DISABLE;
+ }
+}
+
+
+
+/*********************************************************************//**
+ * @brief Transmit a single data through SSPx peripheral
+ * @param[in] SSPx SSP peripheral selected, should be:
+ * - LPC_SSP0: SSP0 peripheral
+ * - LPC_SSP1: SSP1 peripheral
+ * @param[in] Data Data to transmit (must be 16 or 8-bit long,
+ * this depend on SSP data bit number configured)
+ * @return none
+ **********************************************************************/
+void SSP_SendData(LPC_SSP_TypeDef* SSPx, uint16_t Data)
+{
+ CHECK_PARAM(PARAM_SSPx(SSPx));
+
+ SSPx->DR = SSP_DR_BITMASK(Data);
+}
+
+
+
+/*********************************************************************//**
+ * @brief Receive a single data from SSPx peripheral
+ * @param[in] SSPx SSP peripheral selected, should be
+ * - LPC_SSP0: SSP0 peripheral
+ * - LPC_SSP1: SSP1 peripheral
+ * @return Data received (16-bit long)
+ **********************************************************************/
+uint16_t SSP_ReceiveData(LPC_SSP_TypeDef* SSPx)
+{
+ CHECK_PARAM(PARAM_SSPx(SSPx));
+
+ return ((uint16_t) (SSP_DR_BITMASK(SSPx->DR)));
+}
+
+/*********************************************************************//**
+ * @brief SSP Read write data function
+ * @param[in] SSPx Pointer to SSP peripheral, should be
+ * - LPC_SSP0: SSP0 peripheral
+ * - LPC_SSP1: SSP1 peripheral
+ * @param[in] dataCfg Pointer to a SSP_DATA_SETUP_Type structure that
+ * contains specified information about transmit
+ * data configuration.
+ * @param[in] xfType Transfer type, should be:
+ * - SSP_TRANSFER_POLLING: Polling mode
+ * - SSP_TRANSFER_INTERRUPT: Interrupt mode
+ * @return Actual Data length has been transferred in polling mode.
+ * In interrupt mode, always return (0)
+ * Return (-1) if error.
+ * Note: This function can be used in both master and slave mode.
+ ***********************************************************************/
+int32_t SSP_ReadWrite (LPC_SSP_TypeDef *SSPx, SSP_DATA_SETUP_Type *dataCfg, \
+ SSP_TRANSFER_Type xfType)
+{
+ uint8_t *rdata8;
+ uint8_t *wdata8;
+ uint16_t *rdata16;
+ uint16_t *wdata16;
+ uint32_t stat;
+ uint32_t tmp;
+ int32_t dataword;
+
+ dataCfg->rx_cnt = 0;
+ dataCfg->tx_cnt = 0;
+ dataCfg->status = 0;
+
+
+ /* Clear all remaining data in RX FIFO */
+ while (SSPx->SR & SSP_SR_RNE){
+ tmp = (uint32_t) SSP_ReceiveData(SSPx);
+ }
+
+ // Clear status
+ SSPx->ICR = SSP_ICR_BITMASK;
+ if(SSP_GetDataSize(SSPx)>8)
+ dataword = 1;
+ else dataword = 0;
+
+ // Polling mode ----------------------------------------------------------------------
+ if (xfType == SSP_TRANSFER_POLLING){
+ if (dataword == 0){
+ rdata8 = (uint8_t *)dataCfg->rx_data;
+ wdata8 = (uint8_t *)dataCfg->tx_data;
+ } else {
+ rdata16 = (uint16_t *)dataCfg->rx_data;
+ wdata16 = (uint16_t *)dataCfg->tx_data;
+ }
+ while ((dataCfg->tx_cnt != dataCfg->length) || (dataCfg->rx_cnt != dataCfg->length)){
+ if ((SSPx->SR & SSP_SR_TNF) && (dataCfg->tx_cnt != dataCfg->length)){
+ // Write data to buffer
+ if(dataCfg->tx_data == NULL){
+ if (dataword == 0){
+ SSP_SendData(SSPx, 0xFF);
+ dataCfg->tx_cnt++;
+ } else {
+ SSP_SendData(SSPx, 0xFFFF);
+ dataCfg->tx_cnt += 2;
+ }
+ } else {
+ if (dataword == 0){
+ SSP_SendData(SSPx, *wdata8);
+ wdata8++;
+ dataCfg->tx_cnt++;
+ } else {
+ SSP_SendData(SSPx, *wdata16);
+ wdata16++;
+ dataCfg->tx_cnt += 2;
+ }
+ }
+ }
+
+ // Check overrun error
+ if ((stat = SSPx->RIS) & SSP_RIS_ROR){
+ // save status and return
+ dataCfg->status = stat | SSP_STAT_ERROR;
+ return (-1);
+ }
+
+ // Check for any data available in RX FIFO
+ while ((SSPx->SR & SSP_SR_RNE) && (dataCfg->rx_cnt != dataCfg->length)){
+ // Read data from SSP data
+ tmp = SSP_ReceiveData(SSPx);
+
+ // Store data to destination
+ if (dataCfg->rx_data != NULL)
+ {
+ if (dataword == 0){
+ *(rdata8) = (uint8_t) tmp;
+ rdata8++;
+ } else {
+ *(rdata16) = (uint16_t) tmp;
+ rdata16++;
+ }
+ }
+ // Increase counter
+ if (dataword == 0){
+ dataCfg->rx_cnt++;
+ } else {
+ dataCfg->rx_cnt += 2;
+ }
+ }
+ }
+
+ // save status
+ dataCfg->status = SSP_STAT_DONE;
+
+ if (dataCfg->tx_data != NULL){
+ return dataCfg->tx_cnt;
+ } else if (dataCfg->rx_data != NULL){
+ return dataCfg->rx_cnt;
+ } else {
+ return (0);
+ }
+ }
+
+ // Interrupt mode ----------------------------------------------------------------------
+ else if (xfType == SSP_TRANSFER_INTERRUPT){
+
+ while ((SSPx->SR & SSP_SR_TNF) && (dataCfg->tx_cnt != dataCfg->length)){
+ // Write data to buffer
+ if(dataCfg->tx_data == NULL){
+ if (dataword == 0){
+ SSP_SendData(SSPx, 0xFF);
+ dataCfg->tx_cnt++;
+ } else {
+ SSP_SendData(SSPx, 0xFFFF);
+ dataCfg->tx_cnt += 2;
+ }
+ } else {
+ if (dataword == 0){
+ SSP_SendData(SSPx, (*(uint8_t *)((uint32_t)dataCfg->tx_data + dataCfg->tx_cnt)));
+ dataCfg->tx_cnt++;
+ } else {
+ SSP_SendData(SSPx, (*(uint16_t *)((uint32_t)dataCfg->tx_data + dataCfg->tx_cnt)));
+ dataCfg->tx_cnt += 2;
+ }
+ }
+
+ // Check error
+ if ((stat = SSPx->RIS) & SSP_RIS_ROR){
+ // save status and return
+ dataCfg->status = stat | SSP_STAT_ERROR;
+ return (-1);
+ }
+
+ // Check for any data available in RX FIFO
+ while ((SSPx->SR & SSP_SR_RNE) && (dataCfg->rx_cnt != dataCfg->length)){
+ // Read data from SSP data
+ tmp = SSP_ReceiveData(SSPx);
+
+ // Store data to destination
+ if (dataCfg->rx_data != NULL)
+ {
+ if (dataword == 0){
+ *(uint8_t *)((uint32_t)dataCfg->rx_data + dataCfg->rx_cnt) = (uint8_t) tmp;
+ } else {
+ *(uint16_t *)((uint32_t)dataCfg->rx_data + dataCfg->rx_cnt) = (uint16_t) tmp;
+ }
+ }
+ // Increase counter
+ if (dataword == 0){
+ dataCfg->rx_cnt++;
+ } else {
+ dataCfg->rx_cnt += 2;
+ }
+ }
+ }
+
+ // If there more data to sent or receive
+ if ((dataCfg->rx_cnt != dataCfg->length) || (dataCfg->tx_cnt != dataCfg->length)){
+ // Enable all interrupt
+ SSPx->IMSC = SSP_IMSC_BITMASK;
+ } else {
+ // Save status
+ dataCfg->status = SSP_STAT_DONE;
+ }
+ return (0);
+ }
+
+ return (-1);
+}
+
+/*********************************************************************//**
+ * @brief Checks whether the specified SSP status flag is set or not
+ * @param[in] SSPx SSP peripheral selected, should be:
+ * - LPC_SSP0: SSP0 peripheral
+ * - LPC_SSP1: SSP1 peripheral
+ * @param[in] FlagType Type of flag to check status, should be one
+ * of following:
+ * - SSP_STAT_TXFIFO_EMPTY: TX FIFO is empty
+ * - SSP_STAT_TXFIFO_NOTFULL: TX FIFO is not full
+ * - SSP_STAT_RXFIFO_NOTEMPTY: RX FIFO is not empty
+ * - SSP_STAT_RXFIFO_FULL: RX FIFO is full
+ * - SSP_STAT_BUSY: SSP peripheral is busy
+ * @return New State of specified SSP status flag
+ **********************************************************************/
+FlagStatus SSP_GetStatus(LPC_SSP_TypeDef* SSPx, uint32_t FlagType)
+{
+ CHECK_PARAM(PARAM_SSPx(SSPx));
+ CHECK_PARAM(PARAM_SSP_STAT(FlagType));
+
+ return ((SSPx->SR & FlagType) ? SET : RESET);
+}
+
+/*********************************************************************//**
+ * @brief Enable or disable specified interrupt type in SSP peripheral
+ * @param[in] SSPx SSP peripheral selected, should be:
+ * - LPC_SSP0: SSP0 peripheral
+ * - LPC_SSP1: SSP1 peripheral
+ * @param[in] IntType Interrupt type in SSP peripheral, should be:
+ * - SSP_INTCFG_ROR: Receive Overrun interrupt
+ * - SSP_INTCFG_RT: Receive Time out interrupt
+ * - SSP_INTCFG_RX: RX FIFO is at least half full interrupt
+ * - SSP_INTCFG_TX: TX FIFO is at least half empty interrupt
+ * @param[in] NewState New State of specified interrupt type, should be:
+ * - ENABLE: Enable this interrupt type
+ * - DISABLE: Disable this interrupt type
+ * @return None
+ * Note: We can enable/disable multi-interrupt type by OR multi value
+ **********************************************************************/
+void SSP_IntConfig(LPC_SSP_TypeDef *SSPx, uint32_t IntType, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_SSPx(SSPx));
+
+ if (NewState == ENABLE)
+ {
+ SSPx->IMSC |= IntType;
+ }
+ else
+ {
+ SSPx->IMSC &= (~IntType) & SSP_IMSC_BITMASK;
+ }
+}
+
+/*********************************************************************//**
+ * @brief Check whether the specified Raw interrupt status flag is
+ * set or not
+ * @param[in] SSPx SSP peripheral selected, should be:
+ * - LPC_SSP0: SSP0 peripheral
+ * - LPC_SSP1: SSP1 peripheral
+ * @param[in] RawIntType Raw Interrupt Type, should be:
+ * - SSP_INTSTAT_RAW_ROR: Receive Overrun interrupt
+ * - SSP_INTSTAT_RAW_RT: Receive Time out interrupt
+ * - SSP_INTSTAT_RAW_RX: RX FIFO is at least half full interrupt
+ * - SSP_INTSTAT_RAW_TX: TX FIFO is at least half empty interrupt
+ * @return New State of specified Raw interrupt status flag in SSP peripheral
+ * Note: Enabling/Disabling specified interrupt in SSP peripheral does not
+ * effect to Raw Interrupt Status flag.
+ **********************************************************************/
+IntStatus SSP_GetRawIntStatus(LPC_SSP_TypeDef *SSPx, uint32_t RawIntType)
+{
+ CHECK_PARAM(PARAM_SSPx(SSPx));
+ CHECK_PARAM(PARAM_SSP_INTSTAT_RAW(RawIntType));
+
+ return ((SSPx->RIS & RawIntType) ? SET : RESET);
+}
+
+/*********************************************************************//**
+ * @brief Get Raw Interrupt Status register
+ * @param[in] SSPx SSP peripheral selected, should be:
+ * - LPC_SSP0: SSP0 peripheral
+ * - LPC_SSP1: SSP1 peripheral
+ * @return Raw Interrupt Status (RIS) register value
+ **********************************************************************/
+uint32_t SSP_GetRawIntStatusReg(LPC_SSP_TypeDef *SSPx)
+{
+ CHECK_PARAM(PARAM_SSPx(SSPx));
+ return (SSPx->RIS);
+}
+
+/*********************************************************************//**
+ * @brief Check whether the specified interrupt status flag is
+ * set or not
+ * @param[in] SSPx SSP peripheral selected, should be:
+ * - LPC_SSP0: SSP0 peripheral
+ * - LPC_SSP1: SSP1 peripheral
+ * @param[in] IntType Raw Interrupt Type, should be:
+ * - SSP_INTSTAT_ROR: Receive Overrun interrupt
+ * - SSP_INTSTAT_RT: Receive Time out interrupt
+ * - SSP_INTSTAT_RX: RX FIFO is at least half full interrupt
+ * - SSP_INTSTAT_TX: TX FIFO is at least half empty interrupt
+ * @return New State of specified interrupt status flag in SSP peripheral
+ * Note: Enabling/Disabling specified interrupt in SSP peripheral effects
+ * to Interrupt Status flag.
+ **********************************************************************/
+IntStatus SSP_GetIntStatus (LPC_SSP_TypeDef *SSPx, uint32_t IntType)
+{
+ CHECK_PARAM(PARAM_SSPx(SSPx));
+ CHECK_PARAM(PARAM_SSP_INTSTAT(IntType));
+
+ return ((SSPx->MIS & IntType) ? SET :RESET);
+}
+
+/*********************************************************************//**
+ * @brief Clear specified interrupt pending in SSP peripheral
+ * @param[in] SSPx SSP peripheral selected, should be:
+ * - LPC_SSP0: SSP0 peripheral
+ * - LPC_SSP1: SSP1 peripheral
+ * @param[in] IntType Interrupt pending to clear, should be:
+ * - SSP_INTCLR_ROR: clears the "frame was received when
+ * RxFIFO was full" interrupt.
+ * - SSP_INTCLR_RT: clears the "Rx FIFO was not empty and
+ * has not been read for a timeout period" interrupt.
+ * @return None
+ **********************************************************************/
+void SSP_ClearIntPending(LPC_SSP_TypeDef *SSPx, uint32_t IntType)
+{
+ CHECK_PARAM(PARAM_SSPx(SSPx));
+ CHECK_PARAM(PARAM_SSP_INTCLR(IntType));
+
+ SSPx->ICR = IntType;
+}
+
+/*********************************************************************//**
+ * @brief Enable/Disable DMA function for SSP peripheral
+ * @param[in] SSPx SSP peripheral selected, should be:
+ * - LPC_SSP0: SSP0 peripheral
+ * - LPC_SSP1: SSP1 peripheral
+ * @param[in] DMAMode Type of DMA, should be:
+ * - SSP_DMA_TX: DMA for the transmit FIFO
+ * - SSP_DMA_RX: DMA for the Receive FIFO
+ * @param[in] NewState New State of DMA function on SSP peripheral,
+ * should be:
+ * - ENALBE: Enable this function
+ * - DISABLE: Disable this function
+ * @return None
+ **********************************************************************/
+void SSP_DMACmd(LPC_SSP_TypeDef *SSPx, uint32_t DMAMode, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_SSPx(SSPx));
+ CHECK_PARAM(PARAM_SSP_DMA(DMAMode));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ if (NewState == ENABLE)
+ {
+ SSPx->DMACR |= DMAMode;
+ }
+ else
+ {
+ SSPx->DMACR &= (~DMAMode) & SSP_DMA_BITMASK;
+ }
+}
+
+/**
+ * @}
+ */
+
+#endif /* _SSP */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
+
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_systick.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_systick.c
new file mode 100644
index 0000000..5112679
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_systick.c
@@ -0,0 +1,180 @@
+/***********************************************************************//**
+ * @file lpc17xx_systick.c
+ * @brief Contains all functions support for SYSTICK firmware library on LPC17xx
+ * @version 2.0
+ * @date 21. May. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup SYSTICK
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_systick.h"
+#include "lpc17xx_clkpwr.h"
+
+/* If this source file built with example, the LPC17xx FW library configuration
+ * file in each example directory ("lpc17xx_libcfg.h") must be included,
+ * otherwise the default FW library configuration file must be included instead
+ */
+#ifdef __BUILD_WITH_EXAMPLE__
+#include "lpc17xx_libcfg.h"
+#else
+#include "lpc17xx_libcfg_default.h"
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+
+#ifdef _SYSTICK
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup SYSTICK_Public_Functions
+ * @{
+ */
+/*********************************************************************//**
+ * @brief Initial System Tick with using internal CPU clock source
+ * @param[in] time time interval(ms)
+ * @return None
+ **********************************************************************/
+void SYSTICK_InternalInit(uint32_t time)
+{
+ uint32_t cclk;
+ float maxtime;
+
+ cclk = SystemCoreClock;
+ /* With internal CPU clock frequency for LPC17xx is 'SystemCoreClock'
+ * And limit 24 bit for RELOAD value
+ * So the maximum time can be set:
+ * 1/SystemCoreClock * (2^24) * 1000 (ms)
+ */
+ //check time value is available or not
+ maxtime = (1<<24)/(SystemCoreClock / 1000) ;
+ if(time > maxtime)
+ //Error loop
+ while(1);
+ else
+ {
+ //Select CPU clock is System Tick clock source
+ SysTick->CTRL |= ST_CTRL_CLKSOURCE;
+ /* Set RELOAD value
+ * RELOAD = (SystemCoreClock/1000) * time - 1
+ * with time base is millisecond
+ */
+ SysTick->RELOAD = (cclk/1000)*time - 1;
+ }
+}
+
+/*********************************************************************//**
+ * @brief Initial System Tick with using external clock source
+ * @param[in] freq external clock frequency(Hz)
+ * @param[in] time time interval(ms)
+ * @return None
+ **********************************************************************/
+void SYSTICK_ExternalInit(uint32_t freq, uint32_t time)
+{
+ float maxtime;
+
+ /* With external clock frequency for LPC17xx is 'freq'
+ * And limit 24 bit for RELOAD value
+ * So the maximum time can be set:
+ * 1/freq * (2^24) * 1000 (ms)
+ */
+ //check time value is available or not
+ maxtime = (1<<24)/(freq / 1000) ;
+ if (time>maxtime)
+ //Error Loop
+ while(1);
+ else
+ {
+ //Select external clock is System Tick clock source
+ SysTick->CTRL &= ~ ST_CTRL_CLKSOURCE;
+ /* Set RELOAD value
+ * RELOAD = (freq/1000) * time - 1
+ * with time base is millisecond
+ */
+ maxtime = (freq/1000)*time - 1;
+ SysTick->RELOAD = (freq/1000)*time - 1;
+ }
+}
+
+/*********************************************************************//**
+ * @brief Enable/disable System Tick counter
+ * @param[in] NewState System Tick counter status, should be:
+ * - ENABLE
+ * - DISABLE
+ * @return None
+ **********************************************************************/
+void SYSTICK_Cmd(FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ if(NewState == ENABLE)
+ //Enable System Tick counter
+ SysTick->CTRL |= ST_CTRL_ENABLE;
+ else
+ //Disable System Tick counter
+ SysTick->CTRL &= ~ST_CTRL_ENABLE;
+}
+
+/*********************************************************************//**
+ * @brief Enable/disable System Tick interrupt
+ * @param[in] NewState System Tick interrupt status, should be:
+ * - ENABLE
+ * - DISABLE
+ * @return None
+ **********************************************************************/
+void SYSTICK_IntCmd(FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ if(NewState == ENABLE)
+ //Enable System Tick counter
+ SysTick->CTRL |= ST_CTRL_TICKINT;
+ else
+ //Disable System Tick counter
+ SysTick->CTRL &= ~ST_CTRL_TICKINT;
+}
+
+/*********************************************************************//**
+ * @brief Get current value of System Tick counter
+ * @param[in] None
+ * @return current value of System Tick counter
+ **********************************************************************/
+uint32_t SYSTICK_GetCurrentValue(void)
+{
+ return (SysTick->CURR);
+}
+
+/*********************************************************************//**
+ * @brief Clear Counter flag
+ * @param[in] None
+ * @return None
+ **********************************************************************/
+void SYSTICK_ClearCounterFlag(void)
+{
+ SysTick->CTRL &= ~ST_CTRL_COUNTFLAG;
+}
+/**
+ * @}
+ */
+
+#endif /* _SYSTICK */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
+
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_timer.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_timer.c
new file mode 100644
index 0000000..163cccd
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_timer.c
@@ -0,0 +1,591 @@
+/***********************************************************************//**
+ * @file lpc17xx_timer.c
+ * @brief Contains all functions support for Timer firmware library on LPC17xx
+ * @version 3.0
+ * @date 18. June. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup TIM
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_timer.h"
+#include "lpc17xx_clkpwr.h"
+#include "lpc17xx_pinsel.h"
+
+/* If this source file built with example, the LPC17xx FW library configuration
+ * file in each example directory ("lpc17xx_libcfg.h") must be included,
+ * otherwise the default FW library configuration file must be included instead
+ */
+#ifdef __BUILD_WITH_EXAMPLE__
+#include "lpc17xx_libcfg.h"
+#else
+#include "lpc17xx_libcfg_default.h"
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+#ifdef _TIM
+
+/* Private Functions ---------------------------------------------------------- */
+
+static uint32_t getPClock (uint32_t timernum);
+static uint32_t converUSecToVal (uint32_t timernum, uint32_t usec);
+static uint32_t converPtrToTimeNum (LPC_TIM_TypeDef *TIMx);
+
+
+/*********************************************************************//**
+ * @brief Get peripheral clock of each timer controller
+ * @param[in] timernum Timer number
+ * @return Peripheral clock of timer
+ **********************************************************************/
+static uint32_t getPClock (uint32_t timernum)
+{
+ uint32_t clkdlycnt;
+ switch (timernum)
+ {
+ case 0:
+ clkdlycnt = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_TIMER0);
+ break;
+
+ case 1:
+ clkdlycnt = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_TIMER1);
+ break;
+
+ case 2:
+ clkdlycnt = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_TIMER2);
+ break;
+
+ case 3:
+ clkdlycnt = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_TIMER3);
+ break;
+ }
+ return clkdlycnt;
+}
+
+
+/*********************************************************************//**
+ * @brief Convert a time to a timer count value
+ * @param[in] timernum Timer number
+ * @param[in] usec Time in microseconds
+ * @return The number of required clock ticks to give the time delay
+ **********************************************************************/
+uint32_t converUSecToVal (uint32_t timernum, uint32_t usec)
+{
+ uint64_t clkdlycnt;
+
+ // Get Pclock of timer
+ clkdlycnt = (uint64_t) getPClock(timernum);
+
+ clkdlycnt = (clkdlycnt * usec) / 1000000;
+ return (uint32_t) clkdlycnt;
+}
+
+
+/*********************************************************************//**
+ * @brief Convert a timer register pointer to a timer number
+ * @param[in] TIMx Pointer to LPC_TIM_TypeDef, should be:
+ * - LPC_TIM0: TIMER0 peripheral
+ * - LPC_TIM1: TIMER1 peripheral
+ * - LPC_TIM2: TIMER2 peripheral
+ * - LPC_TIM3: TIMER3 peripheral
+ * @return The timer number (0 to 3) or -1 if register pointer is bad
+ **********************************************************************/
+uint32_t converPtrToTimeNum (LPC_TIM_TypeDef *TIMx)
+{
+ uint32_t tnum = -1;
+
+ if (TIMx == LPC_TIM0)
+ {
+ tnum = 0;
+ }
+ else if (TIMx == LPC_TIM1)
+ {
+ tnum = 1;
+ }
+ else if (TIMx == LPC_TIM2)
+ {
+ tnum = 2;
+ }
+ else if (TIMx == LPC_TIM3)
+ {
+ tnum = 3;
+ }
+
+ return tnum;
+}
+
+/* End of Private Functions ---------------------------------------------------- */
+
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup TIM_Public_Functions
+ * @{
+ */
+
+/*********************************************************************//**
+ * @brief Get Interrupt Status
+ * @param[in] TIMx Timer selection, should be:
+ * - LPC_TIM0: TIMER0 peripheral
+ * - LPC_TIM1: TIMER1 peripheral
+ * - LPC_TIM2: TIMER2 peripheral
+ * - LPC_TIM3: TIMER3 peripheral
+ * @param[in] IntFlag: interrupt type, should be:
+ * - TIM_MR0_INT: Interrupt for Match channel 0
+ * - TIM_MR1_INT: Interrupt for Match channel 1
+ * - TIM_MR2_INT: Interrupt for Match channel 2
+ * - TIM_MR3_INT: Interrupt for Match channel 3
+ * - TIM_CR0_INT: Interrupt for Capture channel 0
+ * - TIM_CR1_INT: Interrupt for Capture channel 1
+ * @return FlagStatus
+ * - SET : interrupt
+ * - RESET : no interrupt
+ **********************************************************************/
+FlagStatus TIM_GetIntStatus(LPC_TIM_TypeDef *TIMx, TIM_INT_TYPE IntFlag)
+{
+ uint8_t temp;
+ CHECK_PARAM(PARAM_TIMx(TIMx));
+ CHECK_PARAM(PARAM_TIM_INT_TYPE(IntFlag));
+ temp = (TIMx->IR)& TIM_IR_CLR(IntFlag);
+ if (temp)
+ return SET;
+
+ return RESET;
+
+}
+/*********************************************************************//**
+ * @brief Get Capture Interrupt Status
+ * @param[in] TIMx Timer selection, should be:
+ * - LPC_TIM0: TIMER0 peripheral
+ * - LPC_TIM1: TIMER1 peripheral
+ * - LPC_TIM2: TIMER2 peripheral
+ * - LPC_TIM3: TIMER3 peripheral
+ * @param[in] IntFlag: interrupt type, should be:
+ * - TIM_MR0_INT: Interrupt for Match channel 0
+ * - TIM_MR1_INT: Interrupt for Match channel 1
+ * - TIM_MR2_INT: Interrupt for Match channel 2
+ * - TIM_MR3_INT: Interrupt for Match channel 3
+ * - TIM_CR0_INT: Interrupt for Capture channel 0
+ * - TIM_CR1_INT: Interrupt for Capture channel 1
+ * @return FlagStatus
+ * - SET : interrupt
+ * - RESET : no interrupt
+ **********************************************************************/
+FlagStatus TIM_GetIntCaptureStatus(LPC_TIM_TypeDef *TIMx, TIM_INT_TYPE IntFlag)
+{
+ uint8_t temp;
+ CHECK_PARAM(PARAM_TIMx(TIMx));
+ CHECK_PARAM(PARAM_TIM_INT_TYPE(IntFlag));
+ temp = (TIMx->IR) & (1<<(4+IntFlag));
+ if(temp)
+ return SET;
+ return RESET;
+}
+/*********************************************************************//**
+ * @brief Clear Interrupt pending
+ * @param[in] TIMx Timer selection, should be:
+ * - LPC_TIM0: TIMER0 peripheral
+ * - LPC_TIM1: TIMER1 peripheral
+ * - LPC_TIM2: TIMER2 peripheral
+ * - LPC_TIM3: TIMER3 peripheral
+ * @param[in] IntFlag: interrupt type, should be:
+ * - TIM_MR0_INT: Interrupt for Match channel 0
+ * - TIM_MR1_INT: Interrupt for Match channel 1
+ * - TIM_MR2_INT: Interrupt for Match channel 2
+ * - TIM_MR3_INT: Interrupt for Match channel 3
+ * - TIM_CR0_INT: Interrupt for Capture channel 0
+ * - TIM_CR1_INT: Interrupt for Capture channel 1
+ * @return None
+ **********************************************************************/
+void TIM_ClearIntPending(LPC_TIM_TypeDef *TIMx, TIM_INT_TYPE IntFlag)
+{
+ CHECK_PARAM(PARAM_TIMx(TIMx));
+ CHECK_PARAM(PARAM_TIM_INT_TYPE(IntFlag));
+ TIMx->IR |= TIM_IR_CLR(IntFlag);
+}
+
+/*********************************************************************//**
+ * @brief Clear Capture Interrupt pending
+ * @param[in] TIMx Timer selection, should be
+ * - LPC_TIM0: TIMER0 peripheral
+ * - LPC_TIM1: TIMER1 peripheral
+ * - LPC_TIM2: TIMER2 peripheral
+ * - LPC_TIM3: TIMER3 peripheral
+ * @param[in] IntFlag interrupt type, should be:
+ * - TIM_MR0_INT: Interrupt for Match channel 0
+ * - TIM_MR1_INT: Interrupt for Match channel 1
+ * - TIM_MR2_INT: Interrupt for Match channel 2
+ * - TIM_MR3_INT: Interrupt for Match channel 3
+ * - TIM_CR0_INT: Interrupt for Capture channel 0
+ * - TIM_CR1_INT: Interrupt for Capture channel 1
+ * @return None
+ **********************************************************************/
+void TIM_ClearIntCapturePending(LPC_TIM_TypeDef *TIMx, TIM_INT_TYPE IntFlag)
+{
+ CHECK_PARAM(PARAM_TIMx(TIMx));
+ CHECK_PARAM(PARAM_TIM_INT_TYPE(IntFlag));
+ TIMx->IR |= (1<<(4+IntFlag));
+}
+
+/*********************************************************************//**
+ * @brief Configuration for Timer at initial time
+ * @param[in] TimerCounterMode timer counter mode, should be:
+ * - TIM_TIMER_MODE: Timer mode
+ * - TIM_COUNTER_RISING_MODE: Counter rising mode
+ * - TIM_COUNTER_FALLING_MODE: Counter falling mode
+ * - TIM_COUNTER_ANY_MODE:Counter on both edges
+ * @param[in] TIM_ConfigStruct pointer to TIM_TIMERCFG_Type or
+ * TIM_COUNTERCFG_Type
+ * @return None
+ **********************************************************************/
+void TIM_ConfigStructInit(TIM_MODE_OPT TimerCounterMode, void *TIM_ConfigStruct)
+{
+ if (TimerCounterMode == TIM_TIMER_MODE )
+ {
+ TIM_TIMERCFG_Type * pTimeCfg = (TIM_TIMERCFG_Type *)TIM_ConfigStruct;
+ pTimeCfg->PrescaleOption = TIM_PRESCALE_USVAL;
+ pTimeCfg->PrescaleValue = 1;
+ }
+ else
+ {
+ TIM_COUNTERCFG_Type * pCounterCfg = (TIM_COUNTERCFG_Type *)TIM_ConfigStruct;
+ pCounterCfg->CountInputSelect = TIM_COUNTER_INCAP0;
+ }
+}
+
+/*********************************************************************//**
+ * @brief Initial Timer/Counter device
+ * Set Clock frequency for Timer
+ * Set initial configuration for Timer
+ * @param[in] TIMx Timer selection, should be:
+ * - LPC_TIM0: TIMER0 peripheral
+ * - LPC_TIM1: TIMER1 peripheral
+ * - LPC_TIM2: TIMER2 peripheral
+ * - LPC_TIM3: TIMER3 peripheral
+ * @param[in] TimerCounterMode Timer counter mode, should be:
+ * - TIM_TIMER_MODE: Timer mode
+ * - TIM_COUNTER_RISING_MODE: Counter rising mode
+ * - TIM_COUNTER_FALLING_MODE: Counter falling mode
+ * - TIM_COUNTER_ANY_MODE:Counter on both edges
+ * @param[in] TIM_ConfigStruct pointer to TIM_TIMERCFG_Type
+ * that contains the configuration information for the
+ * specified Timer peripheral.
+ * @return None
+ **********************************************************************/
+void TIM_Init(LPC_TIM_TypeDef *TIMx, TIM_MODE_OPT TimerCounterMode, void *TIM_ConfigStruct)
+{
+ TIM_TIMERCFG_Type *pTimeCfg;
+ TIM_COUNTERCFG_Type *pCounterCfg;
+
+ CHECK_PARAM(PARAM_TIMx(TIMx));
+ CHECK_PARAM(PARAM_TIM_MODE_OPT(TimerCounterMode));
+
+ //set power
+ if (TIMx== LPC_TIM0)
+ {
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCTIM0, ENABLE);
+ CLKPWR_SetPCLKDiv (CLKPWR_PCLKSEL_TIMER0, CLKPWR_PCLKSEL_CCLK_DIV_4);
+ }
+ else if (TIMx== LPC_TIM1)
+ {
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCTIM1, ENABLE);
+ CLKPWR_SetPCLKDiv (CLKPWR_PCLKSEL_TIMER1, CLKPWR_PCLKSEL_CCLK_DIV_4);
+
+ }
+
+ else if (TIMx== LPC_TIM2)
+ {
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCTIM2, ENABLE);
+ CLKPWR_SetPCLKDiv (CLKPWR_PCLKSEL_TIMER2, CLKPWR_PCLKSEL_CCLK_DIV_4);
+ }
+ else if (TIMx== LPC_TIM3)
+ {
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCTIM3, ENABLE);
+ CLKPWR_SetPCLKDiv (CLKPWR_PCLKSEL_TIMER3, CLKPWR_PCLKSEL_CCLK_DIV_4);
+
+ }
+
+ TIMx->CCR &= ~TIM_CTCR_MODE_MASK;
+ TIMx->CCR |= TIM_TIMER_MODE;
+
+ TIMx->TC =0;
+ TIMx->PC =0;
+ TIMx->PR =0;
+ TIMx->TCR |= (1<<1); //Reset Counter
+ TIMx->TCR &= ~(1<<1); //release reset
+ if (TimerCounterMode == TIM_TIMER_MODE )
+ {
+ pTimeCfg = (TIM_TIMERCFG_Type *)TIM_ConfigStruct;
+ if (pTimeCfg->PrescaleOption == TIM_PRESCALE_TICKVAL)
+ {
+ TIMx->PR = pTimeCfg->PrescaleValue -1 ;
+ }
+ else
+ {
+ TIMx->PR = converUSecToVal (converPtrToTimeNum(TIMx),pTimeCfg->PrescaleValue)-1;
+ }
+ }
+ else
+ {
+
+ pCounterCfg = (TIM_COUNTERCFG_Type *)TIM_ConfigStruct;
+ TIMx->CCR &= ~TIM_CTCR_INPUT_MASK;
+ if (pCounterCfg->CountInputSelect == TIM_COUNTER_INCAP1)
+ TIMx->CCR |= _BIT(2);
+ }
+
+ // Clear interrupt pending
+ TIMx->IR = 0xFFFFFFFF;
+
+}
+
+/*********************************************************************//**
+ * @brief Close Timer/Counter device
+ * @param[in] TIMx Pointer to timer device, should be:
+ * - LPC_TIM0: TIMER0 peripheral
+ * - LPC_TIM1: TIMER1 peripheral
+ * - LPC_TIM2: TIMER2 peripheral
+ * - LPC_TIM3: TIMER3 peripheral
+ * @return None
+ **********************************************************************/
+void TIM_DeInit (LPC_TIM_TypeDef *TIMx)
+{
+ CHECK_PARAM(PARAM_TIMx(TIMx));
+ // Disable timer/counter
+ TIMx->TCR = 0x00;
+
+ // Disable power
+ if (TIMx== LPC_TIM0)
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCTIM0, DISABLE);
+
+ else if (TIMx== LPC_TIM1)
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCTIM1, DISABLE);
+
+ else if (TIMx== LPC_TIM2)
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCTIM2, DISABLE);
+
+ else if (TIMx== LPC_TIM3)
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCTIM2, DISABLE);
+
+}
+
+/*********************************************************************//**
+ * @brief Start/Stop Timer/Counter device
+ * @param[in] TIMx Pointer to timer device, should be:
+ * - LPC_TIM0: TIMER0 peripheral
+ * - LPC_TIM1: TIMER1 peripheral
+ * - LPC_TIM2: TIMER2 peripheral
+ * - LPC_TIM3: TIMER3 peripheral
+ * @param[in] NewState
+ * - ENABLE : set timer enable
+ * - DISABLE : disable timer
+ * @return None
+ **********************************************************************/
+void TIM_Cmd(LPC_TIM_TypeDef *TIMx, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_TIMx(TIMx));
+ if (NewState == ENABLE)
+ {
+ TIMx->TCR |= TIM_ENABLE;
+ }
+ else
+ {
+ TIMx->TCR &= ~TIM_ENABLE;
+ }
+}
+
+/*********************************************************************//**
+ * @brief Reset Timer/Counter device,
+ * Make TC and PC are synchronously reset on the next
+ * positive edge of PCLK
+ * @param[in] TIMx Pointer to timer device, should be:
+ * - LPC_TIM0: TIMER0 peripheral
+ * - LPC_TIM1: TIMER1 peripheral
+ * - LPC_TIM2: TIMER2 peripheral
+ * - LPC_TIM3: TIMER3 peripheral
+ * @return None
+ **********************************************************************/
+void TIM_ResetCounter(LPC_TIM_TypeDef *TIMx)
+{
+ CHECK_PARAM(PARAM_TIMx(TIMx));
+ TIMx->TCR |= TIM_RESET;
+ TIMx->TCR &= ~TIM_RESET;
+}
+
+/*********************************************************************//**
+ * @brief Configuration for Match register
+ * @param[in] TIMx Pointer to timer device, should be:
+ * - LPC_TIM0: TIMER0 peripheral
+ * - LPC_TIM1: TIMER1 peripheral
+ * - LPC_TIM2: TIMER2 peripheral
+ * - LPC_TIM3: TIMER3 peripheral
+ * @param[in] TIM_MatchConfigStruct Pointer to TIM_MATCHCFG_Type
+ * - MatchChannel : choose channel 0 or 1
+ * - IntOnMatch : if SET, interrupt will be generated when MRxx match
+ * the value in TC
+ * - StopOnMatch : if SET, TC and PC will be stopped whenM Rxx match
+ * the value in TC
+ * - ResetOnMatch : if SET, Reset on MR0 when MRxx match
+ * the value in TC
+ * -ExtMatchOutputType: Select output for external match
+ * + 0: Do nothing for external output pin if match
+ * + 1: Force external output pin to low if match
+ * + 2: Force external output pin to high if match
+ * + 3: Toggle external output pin if match
+ * MatchValue: Set the value to be compared with TC value
+ * @return None
+ **********************************************************************/
+void TIM_ConfigMatch(LPC_TIM_TypeDef *TIMx, TIM_MATCHCFG_Type *TIM_MatchConfigStruct)
+{
+
+ CHECK_PARAM(PARAM_TIMx(TIMx));
+ CHECK_PARAM(PARAM_TIM_EXTMATCH_OPT(TIM_MatchConfigStruct->ExtMatchOutputType));
+
+ switch(TIM_MatchConfigStruct->MatchChannel)
+ {
+ case 0:
+ TIMx->MR0 = TIM_MatchConfigStruct->MatchValue;
+ break;
+ case 1:
+ TIMx->MR1 = TIM_MatchConfigStruct->MatchValue;
+ break;
+ case 2:
+ TIMx->MR2 = TIM_MatchConfigStruct->MatchValue;
+ break;
+ case 3:
+ TIMx->MR3 = TIM_MatchConfigStruct->MatchValue;
+ break;
+ default:
+ //Error match value
+ //Error loop
+ while(1);
+ }
+ //interrupt on MRn
+ TIMx->MCR &=~TIM_MCR_CHANNEL_MASKBIT(TIM_MatchConfigStruct->MatchChannel);
+
+ if (TIM_MatchConfigStruct->IntOnMatch)
+ TIMx->MCR |= TIM_INT_ON_MATCH(TIM_MatchConfigStruct->MatchChannel);
+
+ //reset on MRn
+ if (TIM_MatchConfigStruct->ResetOnMatch)
+ TIMx->MCR |= TIM_RESET_ON_MATCH(TIM_MatchConfigStruct->MatchChannel);
+
+ //stop on MRn
+ if (TIM_MatchConfigStruct->StopOnMatch)
+ TIMx->MCR |= TIM_STOP_ON_MATCH(TIM_MatchConfigStruct->MatchChannel);
+
+ // match output type
+
+ TIMx->EMR &= ~TIM_EM_MASK(TIM_MatchConfigStruct->MatchChannel);
+ TIMx->EMR |= TIM_EM_SET(TIM_MatchConfigStruct->MatchChannel,TIM_MatchConfigStruct->ExtMatchOutputType);
+}
+/*********************************************************************//**
+ * @brief Update Match value
+ * @param[in] TIMx Pointer to timer device, should be:
+ * - LPC_TIM0: TIMER0 peripheral
+ * - LPC_TIM1: TIMER1 peripheral
+ * - LPC_TIM2: TIMER2 peripheral
+ * - LPC_TIM3: TIMER3 peripheral
+ * @param[in] MatchChannel Match channel, should be: 0..3
+ * @param[in] MatchValue updated match value
+ * @return None
+ **********************************************************************/
+void TIM_UpdateMatchValue(LPC_TIM_TypeDef *TIMx,uint8_t MatchChannel, uint32_t MatchValue)
+{
+ CHECK_PARAM(PARAM_TIMx(TIMx));
+ switch(MatchChannel)
+ {
+ case 0:
+ TIMx->MR0 = MatchValue;
+ break;
+ case 1:
+ TIMx->MR1 = MatchValue;
+ break;
+ case 2:
+ TIMx->MR2 = MatchValue;
+ break;
+ case 3:
+ TIMx->MR3 = MatchValue;
+ break;
+ default:
+ //Error Loop
+ while(1);
+ }
+
+}
+/*********************************************************************//**
+ * @brief Configuration for Capture register
+ * @param[in] TIMx Pointer to timer device, should be:
+ * - LPC_TIM0: TIMER0 peripheral
+ * - LPC_TIM1: TIMER1 peripheral
+ * - LPC_TIM2: TIMER2 peripheral
+ * - LPC_TIM3: TIMER3 peripheral
+ * - CaptureChannel: set the channel to capture data
+ * - RisingEdge : if SET, Capture at rising edge
+ * - FallingEdge : if SET, Capture at falling edge
+ * - IntOnCaption : if SET, Capture generate interrupt
+ * @param[in] TIM_CaptureConfigStruct Pointer to TIM_CAPTURECFG_Type
+ * @return None
+ **********************************************************************/
+void TIM_ConfigCapture(LPC_TIM_TypeDef *TIMx, TIM_CAPTURECFG_Type *TIM_CaptureConfigStruct)
+{
+
+ CHECK_PARAM(PARAM_TIMx(TIMx));
+ TIMx->CCR &= ~TIM_CCR_CHANNEL_MASKBIT(TIM_CaptureConfigStruct->CaptureChannel);
+
+ if (TIM_CaptureConfigStruct->RisingEdge)
+ TIMx->CCR |= TIM_CAP_RISING(TIM_CaptureConfigStruct->CaptureChannel);
+
+ if (TIM_CaptureConfigStruct->FallingEdge)
+ TIMx->CCR |= TIM_CAP_FALLING(TIM_CaptureConfigStruct->CaptureChannel);
+
+ if (TIM_CaptureConfigStruct->IntOnCaption)
+ TIMx->CCR |= TIM_INT_ON_CAP(TIM_CaptureConfigStruct->CaptureChannel);
+}
+
+/*********************************************************************//**
+ * @brief Read value of capture register in timer/counter device
+ * @param[in] TIMx Pointer to timer/counter device, should be:
+ * - LPC_TIM0: TIMER0 peripheral
+ * - LPC_TIM1: TIMER1 peripheral
+ * - LPC_TIM2: TIMER2 peripheral
+ * - LPC_TIM3: TIMER3 peripheral
+ * @param[in] CaptureChannel: capture channel number, should be:
+ * - TIM_COUNTER_INCAP0: CAPn.0 input pin for TIMERn
+ * - TIM_COUNTER_INCAP1: CAPn.1 input pin for TIMERn
+ * @return Value of capture register
+ **********************************************************************/
+uint32_t TIM_GetCaptureValue(LPC_TIM_TypeDef *TIMx, TIM_COUNTER_INPUT_OPT CaptureChannel)
+{
+ CHECK_PARAM(PARAM_TIMx(TIMx));
+ CHECK_PARAM(PARAM_TIM_COUNTER_INPUT_OPT(CaptureChannel));
+
+ if(CaptureChannel==0)
+ return TIMx->CR0;
+ else
+ return TIMx->CR1;
+}
+
+/**
+ * @}
+ */
+
+#endif /* _TIMER */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_uart.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_uart.c
new file mode 100644
index 0000000..5f4ee0c
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_uart.c
@@ -0,0 +1,1366 @@
+/***********************************************************************//**
+ * @file lpc17xx_uart.c
+ * @brief Contains all functions support for UART firmware library on LPC17xx
+ * @version 3.0
+ * @date 18. June. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup UART
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_uart.h"
+#include "lpc17xx_clkpwr.h"
+
+/* If this source file built with example, the LPC17xx FW library configuration
+ * file in each example directory ("lpc17xx_libcfg.h") must be included,
+ * otherwise the default FW library configuration file must be included instead
+ */
+#ifdef __BUILD_WITH_EXAMPLE__
+#include "lpc17xx_libcfg.h"
+#else
+#include "lpc17xx_libcfg_default.h"
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+
+#ifdef _UART
+
+/* Private Functions ---------------------------------------------------------- */
+
+static Status uart_set_divisors(LPC_UART_TypeDef *UARTx, uint32_t baudrate);
+
+
+/*********************************************************************//**
+ * @brief Determines best dividers to get a target clock rate
+ * @param[in] UARTx Pointer to selected UART peripheral, should be:
+ * - LPC_UART0: UART0 peripheral
+ * - LPC_UART1: UART1 peripheral
+ * - LPC_UART2: UART2 peripheral
+ * - LPC_UART3: UART3 peripheral
+ * @param[in] baudrate Desired UART baud rate.
+ * @return Error status, could be:
+ * - SUCCESS
+ * - ERROR
+ **********************************************************************/
+static Status uart_set_divisors(LPC_UART_TypeDef *UARTx, uint32_t baudrate)
+{
+ Status errorStatus = ERROR;
+
+ uint32_t uClk;
+ uint32_t calcBaudrate = 0;
+ uint32_t temp = 0;
+
+ uint32_t mulFracDiv, dividerAddFracDiv;
+ uint32_t diviser = 0 ;
+ uint32_t mulFracDivOptimal = 1;
+ uint32_t dividerAddOptimal = 0;
+ uint32_t diviserOptimal = 0;
+
+ uint32_t relativeError = 0;
+ uint32_t relativeOptimalError = 100000;
+
+ /* get UART block clock */
+ if (UARTx == LPC_UART0)
+ {
+ uClk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_UART0);
+ }
+ else if (UARTx == (LPC_UART_TypeDef *)LPC_UART1)
+ {
+ uClk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_UART1);
+ }
+ else if (UARTx == LPC_UART2)
+ {
+ uClk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_UART2);
+ }
+ else if (UARTx == LPC_UART3)
+ {
+ uClk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_UART3);
+ }
+
+
+ uClk = uClk >> 4; /* div by 16 */
+ /* In the Uart IP block, baud rate is calculated using FDR and DLL-DLM registers
+ * The formula is :
+ * BaudRate= uClk * (mulFracDiv/(mulFracDiv+dividerAddFracDiv) / (16 * (DLL)
+ * It involves floating point calculations. That's the reason the formulae are adjusted with
+ * Multiply and divide method.*/
+ /* The value of mulFracDiv and dividerAddFracDiv should comply to the following expressions:
+ * 0 < mulFracDiv <= 15, 0 <= dividerAddFracDiv <= 15 */
+ for (mulFracDiv = 1 ; mulFracDiv <= 15 ;mulFracDiv++)
+ {
+ for (dividerAddFracDiv = 0 ; dividerAddFracDiv <= 15 ;dividerAddFracDiv++)
+ {
+ temp = (mulFracDiv * uClk) / ((mulFracDiv + dividerAddFracDiv));
+
+ diviser = temp / baudrate;
+ if ((temp % baudrate) > (baudrate / 2))
+ diviser++;
+
+ if (diviser > 2 && diviser < 65536)
+ {
+ calcBaudrate = temp / diviser;
+
+ if (calcBaudrate <= baudrate)
+ relativeError = baudrate - calcBaudrate;
+ else
+ relativeError = calcBaudrate - baudrate;
+
+ if ((relativeError < relativeOptimalError))
+ {
+ mulFracDivOptimal = mulFracDiv ;
+ dividerAddOptimal = dividerAddFracDiv;
+ diviserOptimal = diviser;
+ relativeOptimalError = relativeError;
+ if (relativeError == 0)
+ break;
+ }
+ } /* End of if */
+ } /* end of inner for loop */
+ if (relativeError == 0)
+ break;
+ } /* end of outer for loop */
+
+ if (relativeOptimalError < ((baudrate * UART_ACCEPTED_BAUDRATE_ERROR)/100))
+ {
+ if (((LPC_UART1_TypeDef *)UARTx) == LPC_UART1)
+ {
+ ((LPC_UART1_TypeDef *)UARTx)->LCR |= UART_LCR_DLAB_EN;
+ ((LPC_UART1_TypeDef *)UARTx)->/*DLIER.*/DLM = UART_LOAD_DLM(diviserOptimal);
+ ((LPC_UART1_TypeDef *)UARTx)->/*RBTHDLR.*/DLL = UART_LOAD_DLL(diviserOptimal);
+ /* Then reset DLAB bit */
+ ((LPC_UART1_TypeDef *)UARTx)->LCR &= (~UART_LCR_DLAB_EN) & UART_LCR_BITMASK;
+ ((LPC_UART1_TypeDef *)UARTx)->FDR = (UART_FDR_MULVAL(mulFracDivOptimal) \
+ | UART_FDR_DIVADDVAL(dividerAddOptimal)) & UART_FDR_BITMASK;
+ }
+ else
+ {
+ UARTx->LCR |= UART_LCR_DLAB_EN;
+ UARTx->/*DLIER.*/DLM = UART_LOAD_DLM(diviserOptimal);
+ UARTx->/*RBTHDLR.*/DLL = UART_LOAD_DLL(diviserOptimal);
+ /* Then reset DLAB bit */
+ UARTx->LCR &= (~UART_LCR_DLAB_EN) & UART_LCR_BITMASK;
+ UARTx->FDR = (UART_FDR_MULVAL(mulFracDivOptimal) \
+ | UART_FDR_DIVADDVAL(dividerAddOptimal)) & UART_FDR_BITMASK;
+ }
+ errorStatus = SUCCESS;
+ }
+
+ return errorStatus;
+}
+
+/* End of Private Functions ---------------------------------------------------- */
+
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup UART_Public_Functions
+ * @{
+ */
+/* UART Init/DeInit functions -------------------------------------------------*/
+/********************************************************************//**
+ * @brief Initializes the UARTx peripheral according to the specified
+ * parameters in the UART_ConfigStruct.
+ * @param[in] UARTx UART peripheral selected, should be:
+ * - LPC_UART0: UART0 peripheral
+ * - LPC_UART1: UART1 peripheral
+ * - LPC_UART2: UART2 peripheral
+ * - LPC_UART3: UART3 peripheral
+ * @param[in] UART_ConfigStruct Pointer to a UART_CFG_Type structure
+* that contains the configuration information for the
+* specified UART peripheral.
+ * @return None
+ *********************************************************************/
+void UART_Init(LPC_UART_TypeDef *UARTx, UART_CFG_Type *UART_ConfigStruct)
+{
+ uint32_t tmp;
+
+ // For debug mode
+ CHECK_PARAM(PARAM_UARTx(UARTx));
+ CHECK_PARAM(PARAM_UART_DATABIT(UART_ConfigStruct->Databits));
+ CHECK_PARAM(PARAM_UART_STOPBIT(UART_ConfigStruct->Stopbits));
+ CHECK_PARAM(PARAM_UART_PARITY(UART_ConfigStruct->Parity));
+
+#ifdef _UART0
+ if(UARTx == LPC_UART0)
+ {
+ /* Set up clock and power for UART module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCUART0, ENABLE);
+ }
+#endif
+
+#ifdef _UART1
+ if(((LPC_UART1_TypeDef *)UARTx) == LPC_UART1)
+ {
+ /* Set up clock and power for UART module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCUART1, ENABLE);
+ }
+#endif
+
+#ifdef _UART2
+ if(UARTx == LPC_UART2)
+ {
+ /* Set up clock and power for UART module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCUART2, ENABLE);
+ }
+#endif
+
+#ifdef _UART3
+ if(UARTx == LPC_UART3)
+ {
+ /* Set up clock and power for UART module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCUART3, ENABLE);
+ }
+#endif
+
+ if (((LPC_UART1_TypeDef *)UARTx) == LPC_UART1)
+ {
+ /* FIFOs are empty */
+ ((LPC_UART1_TypeDef *)UARTx)->/*IIFCR.*/FCR = ( UART_FCR_FIFO_EN \
+ | UART_FCR_RX_RS | UART_FCR_TX_RS);
+ // Disable FIFO
+ ((LPC_UART1_TypeDef *)UARTx)->/*IIFCR.*/FCR = 0;
+
+ // Dummy reading
+ while (((LPC_UART1_TypeDef *)UARTx)->LSR & UART_LSR_RDR)
+ {
+ tmp = ((LPC_UART1_TypeDef *)UARTx)->/*RBTHDLR.*/RBR;
+ }
+
+ ((LPC_UART1_TypeDef *)UARTx)->TER = UART_TER_TXEN;
+ // Wait for current transmit complete
+ while (!(((LPC_UART1_TypeDef *)UARTx)->LSR & UART_LSR_THRE));
+ // Disable Tx
+ ((LPC_UART1_TypeDef *)UARTx)->TER = 0;
+
+ // Disable interrupt
+ ((LPC_UART1_TypeDef *)UARTx)->/*DLIER.*/IER = 0;
+ // Set LCR to default state
+ ((LPC_UART1_TypeDef *)UARTx)->LCR = 0;
+ // Set ACR to default state
+ ((LPC_UART1_TypeDef *)UARTx)->ACR = 0;
+ // Set Modem Control to default state
+ ((LPC_UART1_TypeDef *)UARTx)->MCR = 0;
+ // Set RS485 control to default state
+ ((LPC_UART1_TypeDef *)UARTx)->RS485CTRL = 0;
+ // Set RS485 delay timer to default state
+ ((LPC_UART1_TypeDef *)UARTx)->RS485DLY = 0;
+ // Set RS485 addr match to default state
+ ((LPC_UART1_TypeDef *)UARTx)->ADRMATCH = 0;
+ //Dummy Reading to Clear Status
+ tmp = ((LPC_UART1_TypeDef *)UARTx)->MSR;
+ tmp = ((LPC_UART1_TypeDef *)UARTx)->LSR;
+ }
+ else
+ {
+ /* FIFOs are empty */
+ UARTx->/*IIFCR.*/FCR = ( UART_FCR_FIFO_EN | UART_FCR_RX_RS | UART_FCR_TX_RS);
+ // Disable FIFO
+ UARTx->/*IIFCR.*/FCR = 0;
+
+ // Dummy reading
+ while (UARTx->LSR & UART_LSR_RDR)
+ {
+ tmp = UARTx->/*RBTHDLR.*/RBR;
+ }
+
+ UARTx->TER = UART_TER_TXEN;
+ // Wait for current transmit complete
+ while (!(UARTx->LSR & UART_LSR_THRE));
+ // Disable Tx
+ UARTx->TER = 0;
+
+ // Disable interrupt
+ UARTx->/*DLIER.*/IER = 0;
+ // Set LCR to default state
+ UARTx->LCR = 0;
+ // Set ACR to default state
+ UARTx->ACR = 0;
+ // Dummy reading
+ tmp = UARTx->LSR;
+ }
+
+ if (UARTx == LPC_UART3)
+ {
+ // Set IrDA to default state
+ UARTx->ICR = 0;
+ }
+
+ // Set Line Control register ----------------------------
+
+ uart_set_divisors(UARTx, (UART_ConfigStruct->Baud_rate));
+
+ if (((LPC_UART1_TypeDef *)UARTx) == LPC_UART1)
+ {
+ tmp = (((LPC_UART1_TypeDef *)UARTx)->LCR & (UART_LCR_DLAB_EN | UART_LCR_BREAK_EN)) \
+ & UART_LCR_BITMASK;
+ }
+ else
+ {
+ tmp = (UARTx->LCR & (UART_LCR_DLAB_EN | UART_LCR_BREAK_EN)) & UART_LCR_BITMASK;
+ }
+
+ switch (UART_ConfigStruct->Databits){
+ case UART_DATABIT_5:
+ tmp |= UART_LCR_WLEN5;
+ break;
+ case UART_DATABIT_6:
+ tmp |= UART_LCR_WLEN6;
+ break;
+ case UART_DATABIT_7:
+ tmp |= UART_LCR_WLEN7;
+ break;
+ case UART_DATABIT_8:
+ default:
+ tmp |= UART_LCR_WLEN8;
+ break;
+ }
+
+ if (UART_ConfigStruct->Parity == UART_PARITY_NONE)
+ {
+ // Do nothing...
+ }
+ else
+ {
+ tmp |= UART_LCR_PARITY_EN;
+ switch (UART_ConfigStruct->Parity)
+ {
+ case UART_PARITY_ODD:
+ tmp |= UART_LCR_PARITY_ODD;
+ break;
+
+ case UART_PARITY_EVEN:
+ tmp |= UART_LCR_PARITY_EVEN;
+ break;
+
+ case UART_PARITY_SP_1:
+ tmp |= UART_LCR_PARITY_F_1;
+ break;
+
+ case UART_PARITY_SP_0:
+ tmp |= UART_LCR_PARITY_F_0;
+ break;
+ default:
+ break;
+ }
+ }
+
+ switch (UART_ConfigStruct->Stopbits){
+ case UART_STOPBIT_2:
+ tmp |= UART_LCR_STOPBIT_SEL;
+ break;
+ case UART_STOPBIT_1:
+ default:
+ // Do no thing
+ break;
+ }
+
+
+ // Write back to LCR, configure FIFO and Disable Tx
+ if (((LPC_UART1_TypeDef *)UARTx) == LPC_UART1)
+ {
+ ((LPC_UART1_TypeDef *)UARTx)->LCR = (uint8_t)(tmp & UART_LCR_BITMASK);
+ }
+ else
+ {
+ UARTx->LCR = (uint8_t)(tmp & UART_LCR_BITMASK);
+ }
+}
+
+/*********************************************************************//**
+ * @brief De-initializes the UARTx peripheral registers to their
+ * default reset values.
+ * @param[in] UARTx UART peripheral selected, should be:
+ * - LPC_UART0: UART0 peripheral
+ * - LPC_UART1: UART1 peripheral
+ * - LPC_UART2: UART2 peripheral
+ * - LPC_UART3: UART3 peripheral
+ * @return None
+ **********************************************************************/
+void UART_DeInit(LPC_UART_TypeDef* UARTx)
+{
+ // For debug mode
+ CHECK_PARAM(PARAM_UARTx(UARTx));
+
+ UART_TxCmd(UARTx, DISABLE);
+
+#ifdef _UART0
+ if (UARTx == LPC_UART0)
+ {
+ /* Set up clock and power for UART module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCUART0, DISABLE);
+ }
+#endif
+
+#ifdef _UART1
+ if (((LPC_UART1_TypeDef *)UARTx) == LPC_UART1)
+ {
+ /* Set up clock and power for UART module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCUART1, DISABLE);
+ }
+#endif
+
+#ifdef _UART2
+ if (UARTx == LPC_UART2)
+ {
+ /* Set up clock and power for UART module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCUART2, DISABLE);
+ }
+#endif
+
+#ifdef _UART3
+ if (UARTx == LPC_UART3)
+ {
+ /* Set up clock and power for UART module */
+ CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCUART3, DISABLE);
+ }
+#endif
+}
+
+/*****************************************************************************//**
+* @brief Fills each UART_InitStruct member with its default value:
+* - 9600 bps
+* - 8-bit data
+* - 1 Stopbit
+* - None Parity
+* @param[in] UART_InitStruct Pointer to a UART_CFG_Type structure
+* which will be initialized.
+* @return None
+*******************************************************************************/
+void UART_ConfigStructInit(UART_CFG_Type *UART_InitStruct)
+{
+ UART_InitStruct->Baud_rate = 9600;
+ UART_InitStruct->Databits = UART_DATABIT_8;
+ UART_InitStruct->Parity = UART_PARITY_NONE;
+ UART_InitStruct->Stopbits = UART_STOPBIT_1;
+}
+
+/* UART Send/Recieve functions -------------------------------------------------*/
+/*********************************************************************//**
+ * @brief Transmit a single data through UART peripheral
+ * @param[in] UARTx UART peripheral selected, should be:
+ * - LPC_UART0: UART0 peripheral
+ * - LPC_UART1: UART1 peripheral
+ * - LPC_UART2: UART2 peripheral
+ * - LPC_UART3: UART3 peripheral
+ * @param[in] Data Data to transmit (must be 8-bit long)
+ * @return None
+ **********************************************************************/
+void UART_SendByte(LPC_UART_TypeDef* UARTx, uint8_t Data)
+{
+ CHECK_PARAM(PARAM_UARTx(UARTx));
+
+ if (((LPC_UART1_TypeDef *)UARTx) == LPC_UART1)
+ {
+ ((LPC_UART1_TypeDef *)UARTx)->/*RBTHDLR.*/THR = Data & UART_THR_MASKBIT;
+ }
+ else
+ {
+ UARTx->/*RBTHDLR.*/THR = Data & UART_THR_MASKBIT;
+ }
+
+}
+
+
+/*********************************************************************//**
+ * @brief Receive a single data from UART peripheral
+ * @param[in] UARTx UART peripheral selected, should be:
+ * - LPC_UART0: UART0 peripheral
+ * - LPC_UART1: UART1 peripheral
+ * - LPC_UART2: UART2 peripheral
+ * - LPC_UART3: UART3 peripheral
+ * @return Data received
+ **********************************************************************/
+uint8_t UART_ReceiveByte(LPC_UART_TypeDef* UARTx)
+{
+ CHECK_PARAM(PARAM_UARTx(UARTx));
+
+ if (((LPC_UART1_TypeDef *)UARTx) == LPC_UART1)
+ {
+ return (((LPC_UART1_TypeDef *)UARTx)->/*RBTHDLR.*/RBR & UART_RBR_MASKBIT);
+ }
+ else
+ {
+ return (UARTx->/*RBTHDLR.*/RBR & UART_RBR_MASKBIT);
+ }
+}
+
+/*********************************************************************//**
+ * @brief Send a block of data via UART peripheral
+ * @param[in] UARTx Selected UART peripheral used to send data, should be:
+ * - LPC_UART0: UART0 peripheral
+ * - LPC_UART1: UART1 peripheral
+ * - LPC_UART2: UART2 peripheral
+ * - LPC_UART3: UART3 peripheral
+ * @param[in] txbuf Pointer to Transmit buffer
+ * @param[in] buflen Length of Transmit buffer
+ * @param[in] flag Flag used in UART transfer, should be
+ * NONE_BLOCKING or BLOCKING
+ * @return Number of bytes sent.
+ *
+ * Note: when using UART in BLOCKING mode, a time-out condition is used
+ * via defined symbol UART_BLOCKING_TIMEOUT.
+ **********************************************************************/
+uint32_t UART_Send(LPC_UART_TypeDef *UARTx, uint8_t *txbuf,
+ uint32_t buflen, TRANSFER_BLOCK_Type flag)
+{
+ uint32_t bToSend, bSent, timeOut, fifo_cnt;
+ uint8_t *pChar = txbuf;
+
+ bToSend = buflen;
+
+ // blocking mode
+ if (flag == BLOCKING) {
+ bSent = 0;
+ while (bToSend){
+ timeOut = UART_BLOCKING_TIMEOUT;
+ // Wait for THR empty with timeout
+ while (!(UARTx->LSR & UART_LSR_THRE)) {
+ if (timeOut == 0) break;
+ timeOut--;
+ }
+ // Time out!
+ if(timeOut == 0) break;
+ fifo_cnt = UART_TX_FIFO_SIZE;
+ while (fifo_cnt && bToSend){
+ UART_SendByte(UARTx, (*pChar++));
+ fifo_cnt--;
+ bToSend--;
+ bSent++;
+ }
+ }
+ }
+ // None blocking mode
+ else {
+ bSent = 0;
+ while (bToSend) {
+ if (!(UARTx->LSR & UART_LSR_THRE)){
+ break;
+ }
+ fifo_cnt = UART_TX_FIFO_SIZE;
+ while (fifo_cnt && bToSend) {
+ UART_SendByte(UARTx, (*pChar++));
+ bToSend--;
+ fifo_cnt--;
+ bSent++;
+ }
+ }
+ }
+ return bSent;
+}
+
+/*********************************************************************//**
+ * @brief Receive a block of data via UART peripheral
+ * @param[in] UARTx Selected UART peripheral used to send data,
+ * should be:
+ * - LPC_UART0: UART0 peripheral
+ * - LPC_UART1: UART1 peripheral
+ * - LPC_UART2: UART2 peripheral
+ * - LPC_UART3: UART3 peripheral
+ * @param[out] rxbuf Pointer to Received buffer
+ * @param[in] buflen Length of Received buffer
+ * @param[in] flag Flag mode, should be NONE_BLOCKING or BLOCKING
+
+ * @return Number of bytes received
+ *
+ * Note: when using UART in BLOCKING mode, a time-out condition is used
+ * via defined symbol UART_BLOCKING_TIMEOUT.
+ **********************************************************************/
+uint32_t UART_Receive(LPC_UART_TypeDef *UARTx, uint8_t *rxbuf, \
+ uint32_t buflen, TRANSFER_BLOCK_Type flag)
+{
+ uint32_t bToRecv, bRecv, timeOut;
+ uint8_t *pChar = rxbuf;
+
+ bToRecv = buflen;
+
+ // Blocking mode
+ if (flag == BLOCKING) {
+ bRecv = 0;
+ while (bToRecv){
+ timeOut = UART_BLOCKING_TIMEOUT;
+ while (!(UARTx->LSR & UART_LSR_RDR)){
+ if (timeOut == 0) break;
+ timeOut--;
+ }
+ // Time out!
+ if(timeOut == 0) break;
+ // Get data from the buffer
+ (*pChar++) = UART_ReceiveByte(UARTx);
+ bToRecv--;
+ bRecv++;
+ }
+ }
+ // None blocking mode
+ else {
+ bRecv = 0;
+ while (bToRecv) {
+ if (!(UARTx->LSR & UART_LSR_RDR)) {
+ break;
+ } else {
+ (*pChar++) = UART_ReceiveByte(UARTx);
+ bRecv++;
+ bToRecv--;
+ }
+ }
+ }
+ return bRecv;
+}
+
+/*********************************************************************//**
+ * @brief Force BREAK character on UART line, output pin UARTx TXD is
+ forced to logic 0.
+ * @param[in] UARTx UART peripheral selected, should be:
+ * - LPC_UART0: UART0 peripheral
+ * - LPC_UART1: UART1 peripheral
+ * - LPC_UART2: UART2 peripheral
+ * - LPC_UART3: UART3 peripheral
+ * @return None
+ **********************************************************************/
+void UART_ForceBreak(LPC_UART_TypeDef* UARTx)
+{
+ CHECK_PARAM(PARAM_UARTx(UARTx));
+
+ if (((LPC_UART1_TypeDef *)UARTx) == LPC_UART1)
+ {
+ ((LPC_UART1_TypeDef *)UARTx)->LCR |= UART_LCR_BREAK_EN;
+ }
+ else
+ {
+ UARTx->LCR |= UART_LCR_BREAK_EN;
+ }
+}
+
+
+/********************************************************************//**
+ * @brief Enable or disable specified UART interrupt.
+ * @param[in] UARTx UART peripheral selected, should be
+ * - LPC_UART0: UART0 peripheral
+ * - LPC_UART1: UART1 peripheral
+ * - LPC_UART2: UART2 peripheral
+ * - LPC_UART3: UART3 peripheral
+ * @param[in] UARTIntCfg Specifies the interrupt flag,
+ * should be one of the following:
+ - UART_INTCFG_RBR : RBR Interrupt enable
+ - UART_INTCFG_THRE : THR Interrupt enable
+ - UART_INTCFG_RLS : RX line status interrupt enable
+ - UART1_INTCFG_MS : Modem status interrupt enable (UART1 only)
+ - UART1_INTCFG_CTS : CTS1 signal transition interrupt enable (UART1 only)
+ - UART_INTCFG_ABEO : Enables the end of auto-baud interrupt
+ - UART_INTCFG_ABTO : Enables the auto-baud time-out interrupt
+ * @param[in] NewState New state of specified UART interrupt type,
+ * should be:
+ * - ENALBE: Enable this UART interrupt type.
+* - DISALBE: Disable this UART interrupt type.
+ * @return None
+ *********************************************************************/
+void UART_IntConfig(LPC_UART_TypeDef *UARTx, UART_INT_Type UARTIntCfg, FunctionalState NewState)
+{
+ uint32_t tmp;
+
+ CHECK_PARAM(PARAM_UARTx(UARTx));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ switch(UARTIntCfg){
+ case UART_INTCFG_RBR:
+ tmp = UART_IER_RBRINT_EN;
+ break;
+ case UART_INTCFG_THRE:
+ tmp = UART_IER_THREINT_EN;
+ break;
+ case UART_INTCFG_RLS:
+ tmp = UART_IER_RLSINT_EN;
+ break;
+ case UART1_INTCFG_MS:
+ tmp = UART1_IER_MSINT_EN;
+ break;
+ case UART1_INTCFG_CTS:
+ tmp = UART1_IER_CTSINT_EN;
+ break;
+ case UART_INTCFG_ABEO:
+ tmp = UART_IER_ABEOINT_EN;
+ break;
+ case UART_INTCFG_ABTO:
+ tmp = UART_IER_ABTOINT_EN;
+ break;
+ }
+
+ if ((LPC_UART1_TypeDef *) UARTx == LPC_UART1)
+ {
+ CHECK_PARAM((PARAM_UART_INTCFG(UARTIntCfg)) || (PARAM_UART1_INTCFG(UARTIntCfg)));
+ }
+ else
+ {
+ CHECK_PARAM(PARAM_UART_INTCFG(UARTIntCfg));
+ }
+
+ if (NewState == ENABLE)
+ {
+ if ((LPC_UART1_TypeDef *) UARTx == LPC_UART1)
+ {
+ ((LPC_UART1_TypeDef *)UARTx)->/*DLIER.*/IER |= tmp;
+ }
+ else
+ {
+ UARTx->/*DLIER.*/IER |= tmp;
+ }
+ }
+ else
+ {
+ if ((LPC_UART1_TypeDef *) UARTx == LPC_UART1)
+ {
+ ((LPC_UART1_TypeDef *)UARTx)->/*DLIER.*/IER &= (~tmp) & UART1_IER_BITMASK;
+ }
+ else
+ {
+ UARTx->/*DLIER.*/IER &= (~tmp) & UART_IER_BITMASK;
+ }
+ }
+}
+
+
+/********************************************************************//**
+ * @brief Get current value of Line Status register in UART peripheral.
+ * @param[in] UARTx UART peripheral selected, should be:
+ * - LPC_UART0: UART0 peripheral
+ * - LPC_UART1: UART1 peripheral
+ * - LPC_UART2: UART2 peripheral
+ * - LPC_UART3: UART3 peripheral
+ * @return Current value of Line Status register in UART peripheral.
+ * Note: The return value of this function must be ANDed with each member in
+ * UART_LS_Type enumeration to determine current flag status
+ * corresponding to each Line status type. Because some flags in
+ * Line Status register will be cleared after reading, the next reading
+ * Line Status register could not be correct. So this function used to
+ * read Line status register in one time only, then the return value
+ * used to check all flags.
+ *********************************************************************/
+uint8_t UART_GetLineStatus(LPC_UART_TypeDef* UARTx)
+{
+ CHECK_PARAM(PARAM_UARTx(UARTx));
+
+ if (((LPC_UART1_TypeDef *)UARTx) == LPC_UART1)
+ {
+ return ((((LPC_UART1_TypeDef *)LPC_UART1)->LSR) & UART_LSR_BITMASK);
+ }
+ else
+ {
+ return ((UARTx->LSR) & UART_LSR_BITMASK);
+ }
+}
+
+/********************************************************************//**
+ * @brief Get Interrupt Identification value
+ * @param[in] UARTx UART peripheral selected, should be:
+ * - LPC_UART0: UART0 peripheral
+ * - LPC_UART1: UART1 peripheral
+ * - LPC_UART2: UART2 peripheral
+ * - LPC_UART3: UART3 peripheral
+ * @return Current value of UART UIIR register in UART peripheral.
+ *********************************************************************/
+uint32_t UART_GetIntId(LPC_UART_TypeDef* UARTx)
+{
+ CHECK_PARAM(PARAM_UARTx(UARTx));
+ return (UARTx->IIR & 0x03CF);
+}
+
+/*********************************************************************//**
+ * @brief Check whether if UART is busy or not
+ * @param[in] UARTx UART peripheral selected, should be:
+ * - LPC_UART0: UART0 peripheral
+ * - LPC_UART1: UART1 peripheral
+ * - LPC_UART2: UART2 peripheral
+ * - LPC_UART3: UART3 peripheral
+ * @return RESET if UART is not busy, otherwise return SET.
+ **********************************************************************/
+FlagStatus UART_CheckBusy(LPC_UART_TypeDef *UARTx)
+{
+ if (UARTx->LSR & UART_LSR_TEMT){
+ return RESET;
+ } else {
+ return SET;
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Configure FIFO function on selected UART peripheral
+ * @param[in] UARTx UART peripheral selected, should be:
+ * - LPC_UART0: UART0 peripheral
+ * - LPC_UART1: UART1 peripheral
+ * - LPC_UART2: UART2 peripheral
+ * - LPC_UART3: UART3 peripheral
+ * @param[in] FIFOCfg Pointer to a UART_FIFO_CFG_Type Structure that
+ * contains specified information about FIFO configuration
+ * @return none
+ **********************************************************************/
+void UART_FIFOConfig(LPC_UART_TypeDef *UARTx, UART_FIFO_CFG_Type *FIFOCfg)
+{
+ uint8_t tmp = 0;
+
+ CHECK_PARAM(PARAM_UARTx(UARTx));
+ CHECK_PARAM(PARAM_UART_FIFO_LEVEL(FIFOCfg->FIFO_Level));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(FIFOCfg->FIFO_DMAMode));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(FIFOCfg->FIFO_ResetRxBuf));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(FIFOCfg->FIFO_ResetTxBuf));
+
+ tmp |= UART_FCR_FIFO_EN;
+ switch (FIFOCfg->FIFO_Level){
+ case UART_FIFO_TRGLEV0:
+ tmp |= UART_FCR_TRG_LEV0;
+ break;
+ case UART_FIFO_TRGLEV1:
+ tmp |= UART_FCR_TRG_LEV1;
+ break;
+ case UART_FIFO_TRGLEV2:
+ tmp |= UART_FCR_TRG_LEV2;
+ break;
+ case UART_FIFO_TRGLEV3:
+ default:
+ tmp |= UART_FCR_TRG_LEV3;
+ break;
+ }
+
+ if (FIFOCfg->FIFO_ResetTxBuf == ENABLE)
+ {
+ tmp |= UART_FCR_TX_RS;
+ }
+ if (FIFOCfg->FIFO_ResetRxBuf == ENABLE)
+ {
+ tmp |= UART_FCR_RX_RS;
+ }
+ if (FIFOCfg->FIFO_DMAMode == ENABLE)
+ {
+ tmp |= UART_FCR_DMAMODE_SEL;
+ }
+
+
+ //write to FIFO control register
+ if (((LPC_UART1_TypeDef *)UARTx) == LPC_UART1)
+ {
+ ((LPC_UART1_TypeDef *)UARTx)->/*IIFCR.*/FCR = tmp & UART_FCR_BITMASK;
+ }
+ else
+ {
+ UARTx->/*IIFCR.*/FCR = tmp & UART_FCR_BITMASK;
+ }
+}
+
+/*****************************************************************************//**
+* @brief Fills each UART_FIFOInitStruct member with its default value:
+* - FIFO_DMAMode = DISABLE
+* - FIFO_Level = UART_FIFO_TRGLEV0
+* - FIFO_ResetRxBuf = ENABLE
+* - FIFO_ResetTxBuf = ENABLE
+* - FIFO_State = ENABLE
+
+* @param[in] UART_FIFOInitStruct Pointer to a UART_FIFO_CFG_Type structure
+* which will be initialized.
+* @return None
+*******************************************************************************/
+void UART_FIFOConfigStructInit(UART_FIFO_CFG_Type *UART_FIFOInitStruct)
+{
+ UART_FIFOInitStruct->FIFO_DMAMode = DISABLE;
+ UART_FIFOInitStruct->FIFO_Level = UART_FIFO_TRGLEV0;
+ UART_FIFOInitStruct->FIFO_ResetRxBuf = ENABLE;
+ UART_FIFOInitStruct->FIFO_ResetTxBuf = ENABLE;
+}
+
+
+/*********************************************************************//**
+ * @brief Start/Stop Auto Baudrate activity
+ * @param[in] UARTx UART peripheral selected, should be
+ * - LPC_UART0: UART0 peripheral
+ * - LPC_UART1: UART1 peripheral
+ * - LPC_UART2: UART2 peripheral
+ * - LPC_UART3: UART3 peripheral
+ * @param[in] ABConfigStruct A pointer to UART_AB_CFG_Type structure that
+ * contains specified information about UART
+ * auto baudrate configuration
+ * @param[in] NewState New State of Auto baudrate activity, should be:
+ * - ENABLE: Start this activity
+ * - DISABLE: Stop this activity
+ * Note: Auto-baudrate mode enable bit will be cleared once this mode
+ * completed.
+ * @return none
+ **********************************************************************/
+void UART_ABCmd(LPC_UART_TypeDef *UARTx, UART_AB_CFG_Type *ABConfigStruct, \
+ FunctionalState NewState)
+{
+ uint32_t tmp;
+
+ CHECK_PARAM(PARAM_UARTx(UARTx));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ tmp = 0;
+ if (NewState == ENABLE) {
+ if (ABConfigStruct->ABMode == UART_AUTOBAUD_MODE1){
+ tmp |= UART_ACR_MODE;
+ }
+ if (ABConfigStruct->AutoRestart == ENABLE){
+ tmp |= UART_ACR_AUTO_RESTART;
+ }
+ }
+
+ if (((LPC_UART1_TypeDef *)UARTx) == LPC_UART1)
+ {
+ if (NewState == ENABLE)
+ {
+ // Clear DLL and DLM value
+ ((LPC_UART1_TypeDef *)UARTx)->LCR |= UART_LCR_DLAB_EN;
+ ((LPC_UART1_TypeDef *)UARTx)->DLL = 0;
+ ((LPC_UART1_TypeDef *)UARTx)->DLM = 0;
+ ((LPC_UART1_TypeDef *)UARTx)->LCR &= ~UART_LCR_DLAB_EN;
+ // FDR value must be reset to default value
+ ((LPC_UART1_TypeDef *)UARTx)->FDR = 0x10;
+ ((LPC_UART1_TypeDef *)UARTx)->ACR = UART_ACR_START | tmp;
+ }
+ else
+ {
+ ((LPC_UART1_TypeDef *)UARTx)->ACR = 0;
+ }
+ }
+ else
+ {
+ if (NewState == ENABLE)
+ {
+ // Clear DLL and DLM value
+ UARTx->LCR |= UART_LCR_DLAB_EN;
+ UARTx->DLL = 0;
+ UARTx->DLM = 0;
+ UARTx->LCR &= ~UART_LCR_DLAB_EN;
+ // FDR value must be reset to default value
+ UARTx->FDR = 0x10;
+ UARTx->ACR = UART_ACR_START | tmp;
+ }
+ else
+ {
+ UARTx->ACR = 0;
+ }
+ }
+}
+
+/*********************************************************************//**
+ * @brief Clear Autobaud Interrupt Pending
+ * @param[in] UARTx UART peripheral selected, should be
+ * - LPC_UART0: UART0 peripheral
+ * - LPC_UART1: UART1 peripheral
+ * - LPC_UART2: UART2 peripheral
+ * - LPC_UART3: UART3 peripheral
+ * @param[in] ABIntType type of auto-baud interrupt, should be:
+ * - UART_AUTOBAUD_INTSTAT_ABEO: End of Auto-baud interrupt
+ * - UART_AUTOBAUD_INTSTAT_ABTO: Auto-baud time out interrupt
+ * @return none
+ **********************************************************************/
+void UART_ABClearIntPending(LPC_UART_TypeDef *UARTx, UART_ABEO_Type ABIntType)
+{
+ CHECK_PARAM(PARAM_UARTx(UARTx));
+ if (((LPC_UART1_TypeDef *)UARTx) == LPC_UART1)
+ {
+ UARTx->ACR |= ABIntType;
+ }
+ else
+ UARTx->ACR |= ABIntType;
+}
+
+/*********************************************************************//**
+ * @brief Enable/Disable transmission on UART TxD pin
+ * @param[in] UARTx UART peripheral selected, should be:
+ * - LPC_UART0: UART0 peripheral
+ * - LPC_UART1: UART1 peripheral
+ * - LPC_UART2: UART2 peripheral
+ * - LPC_UART3: UART3 peripheral
+ * @param[in] NewState New State of Tx transmission function, should be:
+ * - ENABLE: Enable this function
+ - DISABLE: Disable this function
+ * @return none
+ **********************************************************************/
+void UART_TxCmd(LPC_UART_TypeDef *UARTx, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_UARTx(UARTx));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ if (NewState == ENABLE)
+ {
+ if (((LPC_UART1_TypeDef *)UARTx) == LPC_UART1)
+ {
+ ((LPC_UART1_TypeDef *)UARTx)->TER |= UART_TER_TXEN;
+ }
+ else
+ {
+ UARTx->TER |= UART_TER_TXEN;
+ }
+ }
+ else
+ {
+ if (((LPC_UART1_TypeDef *)UARTx) == LPC_UART1)
+ {
+ ((LPC_UART1_TypeDef *)UARTx)->TER &= (~UART_TER_TXEN) & UART_TER_BITMASK;
+ }
+ else
+ {
+ UARTx->TER &= (~UART_TER_TXEN) & UART_TER_BITMASK;
+ }
+ }
+}
+
+/* UART IrDA functions ---------------------------------------------------*/
+
+#ifdef _UART3
+
+/*********************************************************************//**
+ * @brief Enable or disable inverting serial input function of IrDA
+ * on UART peripheral.
+ * @param[in] UARTx UART peripheral selected, should be LPC_UART3 (only)
+ * @param[in] NewState New state of inverting serial input, should be:
+ * - ENABLE: Enable this function.
+ * - DISABLE: Disable this function.
+ * @return none
+ **********************************************************************/
+void UART_IrDAInvtInputCmd(LPC_UART_TypeDef* UARTx, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_UART_IrDA(UARTx));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ if (NewState == ENABLE)
+ {
+ UARTx->ICR |= UART_ICR_IRDAINV;
+ }
+ else if (NewState == DISABLE)
+ {
+ UARTx->ICR &= (~UART_ICR_IRDAINV) & UART_ICR_BITMASK;
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Enable or disable IrDA function on UART peripheral.
+ * @param[in] UARTx UART peripheral selected, should be LPC_UART3 (only)
+ * @param[in] NewState New state of IrDA function, should be:
+ * - ENABLE: Enable this function.
+ * - DISABLE: Disable this function.
+ * @return none
+ **********************************************************************/
+void UART_IrDACmd(LPC_UART_TypeDef* UARTx, FunctionalState NewState)
+{
+ CHECK_PARAM(PARAM_UART_IrDA(UARTx));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ if (NewState == ENABLE)
+ {
+ UARTx->ICR |= UART_ICR_IRDAEN;
+ }
+ else
+ {
+ UARTx->ICR &= (~UART_ICR_IRDAEN) & UART_ICR_BITMASK;
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Configure Pulse divider for IrDA function on UART peripheral.
+ * @param[in] UARTx UART peripheral selected, should be LPC_UART3 (only)
+ * @param[in] PulseDiv Pulse Divider value from Peripheral clock,
+ * should be one of the following:
+ - UART_IrDA_PULSEDIV2 : Pulse width = 2 * Tpclk
+ - UART_IrDA_PULSEDIV4 : Pulse width = 4 * Tpclk
+ - UART_IrDA_PULSEDIV8 : Pulse width = 8 * Tpclk
+ - UART_IrDA_PULSEDIV16 : Pulse width = 16 * Tpclk
+ - UART_IrDA_PULSEDIV32 : Pulse width = 32 * Tpclk
+ - UART_IrDA_PULSEDIV64 : Pulse width = 64 * Tpclk
+ - UART_IrDA_PULSEDIV128 : Pulse width = 128 * Tpclk
+ - UART_IrDA_PULSEDIV256 : Pulse width = 256 * Tpclk
+
+ * @return none
+ **********************************************************************/
+void UART_IrDAPulseDivConfig(LPC_UART_TypeDef *UARTx, UART_IrDA_PULSE_Type PulseDiv)
+{
+ uint32_t tmp, tmp1;
+ CHECK_PARAM(PARAM_UART_IrDA(UARTx));
+ CHECK_PARAM(PARAM_UART_IrDA_PULSEDIV(PulseDiv));
+
+ tmp1 = UART_ICR_PULSEDIV(PulseDiv);
+ tmp = UARTx->ICR & (~UART_ICR_PULSEDIV(7));
+ tmp |= tmp1 | UART_ICR_FIXPULSE_EN;
+ UARTx->ICR = tmp & UART_ICR_BITMASK;
+}
+
+#endif
+
+
+/* UART1 FullModem function ---------------------------------------------*/
+
+#ifdef _UART1
+
+/*********************************************************************//**
+ * @brief Force pin DTR/RTS corresponding to given state (Full modem mode)
+ * @param[in] UARTx LPC_UART1 (only)
+ * @param[in] Pin Pin that NewState will be applied to, should be:
+ * - UART1_MODEM_PIN_DTR: DTR pin.
+ * - UART1_MODEM_PIN_RTS: RTS pin.
+ * @param[in] NewState New State of DTR/RTS pin, should be:
+ * - INACTIVE: Force the pin to inactive signal.
+ - ACTIVE: Force the pin to active signal.
+ * @return none
+ **********************************************************************/
+void UART_FullModemForcePinState(LPC_UART1_TypeDef *UARTx, UART_MODEM_PIN_Type Pin, \
+ UART1_SignalState NewState)
+{
+ uint8_t tmp = 0;
+
+ CHECK_PARAM(PARAM_UART1_MODEM(UARTx));
+ CHECK_PARAM(PARAM_UART1_MODEM_PIN(Pin));
+ CHECK_PARAM(PARAM_UART1_SIGNALSTATE(NewState));
+
+ switch (Pin){
+ case UART1_MODEM_PIN_DTR:
+ tmp = UART1_MCR_DTR_CTRL;
+ break;
+ case UART1_MODEM_PIN_RTS:
+ tmp = UART1_MCR_RTS_CTRL;
+ break;
+ default:
+ break;
+ }
+
+ if (NewState == ACTIVE){
+ UARTx->MCR |= tmp;
+ } else {
+ UARTx->MCR &= (~tmp) & UART1_MCR_BITMASK;
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Configure Full Modem mode for UART peripheral
+ * @param[in] UARTx LPC_UART1 (only)
+ * @param[in] Mode Full Modem mode, should be:
+ * - UART1_MODEM_MODE_LOOPBACK: Loop back mode.
+ * - UART1_MODEM_MODE_AUTO_RTS: Auto-RTS mode.
+ * - UART1_MODEM_MODE_AUTO_CTS: Auto-CTS mode.
+ * @param[in] NewState New State of this mode, should be:
+ * - ENABLE: Enable this mode.
+ - DISABLE: Disable this mode.
+ * @return none
+ **********************************************************************/
+void UART_FullModemConfigMode(LPC_UART1_TypeDef *UARTx, UART_MODEM_MODE_Type Mode, \
+ FunctionalState NewState)
+{
+ uint8_t tmp;
+
+ CHECK_PARAM(PARAM_UART1_MODEM(UARTx));
+ CHECK_PARAM(PARAM_UART1_MODEM_MODE(Mode));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+ switch(Mode){
+ case UART1_MODEM_MODE_LOOPBACK:
+ tmp = UART1_MCR_LOOPB_EN;
+ break;
+ case UART1_MODEM_MODE_AUTO_RTS:
+ tmp = UART1_MCR_AUTO_RTS_EN;
+ break;
+ case UART1_MODEM_MODE_AUTO_CTS:
+ tmp = UART1_MCR_AUTO_CTS_EN;
+ break;
+ default:
+ break;
+ }
+
+ if (NewState == ENABLE)
+ {
+ UARTx->MCR |= tmp;
+ }
+ else
+ {
+ UARTx->MCR &= (~tmp) & UART1_MCR_BITMASK;
+ }
+}
+
+
+/*********************************************************************//**
+ * @brief Get current status of modem status register
+ * @param[in] UARTx LPC_UART1 (only)
+ * @return Current value of modem status register
+ * Note: The return value of this function must be ANDed with each member
+ * UART_MODEM_STAT_type enumeration to determine current flag status
+ * corresponding to each modem flag status. Because some flags in
+ * modem status register will be cleared after reading, the next reading
+ * modem register could not be correct. So this function used to
+ * read modem status register in one time only, then the return value
+ * used to check all flags.
+ **********************************************************************/
+uint8_t UART_FullModemGetStatus(LPC_UART1_TypeDef *UARTx)
+{
+ CHECK_PARAM(PARAM_UART1_MODEM(UARTx));
+ return ((UARTx->MSR) & UART1_MSR_BITMASK);
+}
+
+
+/* UART RS485 functions --------------------------------------------------------------*/
+
+/*********************************************************************//**
+ * @brief Configure UART peripheral in RS485 mode according to the specified
+* parameters in the RS485ConfigStruct.
+ * @param[in] UARTx LPC_UART1 (only)
+ * @param[in] RS485ConfigStruct Pointer to a UART1_RS485_CTRLCFG_Type structure
+* that contains the configuration information for specified UART
+* in RS485 mode.
+ * @return None
+ **********************************************************************/
+void UART_RS485Config(LPC_UART1_TypeDef *UARTx, UART1_RS485_CTRLCFG_Type *RS485ConfigStruct)
+{
+ uint32_t tmp;
+
+ CHECK_PARAM(PARAM_UART1_MODEM(UARTx));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(RS485ConfigStruct->AutoAddrDetect_State));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(RS485ConfigStruct->AutoDirCtrl_State));
+ CHECK_PARAM(PARAM_UART1_RS485_CFG_DELAYVALUE(RS485ConfigStruct->DelayValue));
+ CHECK_PARAM(PARAM_SETSTATE(RS485ConfigStruct->DirCtrlPol_Level));
+ CHECK_PARAM(PARAM_UART_RS485_DIRCTRL_PIN(RS485ConfigStruct->DirCtrlPin));
+ CHECK_PARAM(PARAM_UART1_RS485_CFG_MATCHADDRVALUE(RS485ConfigStruct->MatchAddrValue));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(RS485ConfigStruct->NormalMultiDropMode_State));
+ CHECK_PARAM(PARAM_FUNCTIONALSTATE(RS485ConfigStruct->Rx_State));
+
+ tmp = 0;
+ // If Auto Direction Control is enabled - This function is used in Master mode
+ if (RS485ConfigStruct->AutoDirCtrl_State == ENABLE)
+ {
+ tmp |= UART1_RS485CTRL_DCTRL_EN;
+
+ // Set polar
+ if (RS485ConfigStruct->DirCtrlPol_Level == SET)
+ {
+ tmp |= UART1_RS485CTRL_OINV_1;
+ }
+
+ // Set pin according to
+ if (RS485ConfigStruct->DirCtrlPin == UART1_RS485_DIRCTRL_DTR)
+ {
+ tmp |= UART1_RS485CTRL_SEL_DTR;
+ }
+
+ // Fill delay time
+ UARTx->RS485DLY = RS485ConfigStruct->DelayValue & UART1_RS485DLY_BITMASK;
+ }
+
+ // MultiDrop mode is enable
+ if (RS485ConfigStruct->NormalMultiDropMode_State == ENABLE)
+ {
+ tmp |= UART1_RS485CTRL_NMM_EN;
+ }
+
+ // Auto Address Detect function
+ if (RS485ConfigStruct->AutoAddrDetect_State == ENABLE)
+ {
+ tmp |= UART1_RS485CTRL_AADEN;
+ // Fill Match Address
+ UARTx->ADRMATCH = RS485ConfigStruct->MatchAddrValue & UART1_RS485ADRMATCH_BITMASK;
+ }
+
+
+ // Receiver is disable
+ if (RS485ConfigStruct->Rx_State == DISABLE)
+ {
+ tmp |= UART1_RS485CTRL_RX_DIS;
+ }
+
+ // write back to RS485 control register
+ UARTx->RS485CTRL = tmp & UART1_RS485CTRL_BITMASK;
+
+ // Enable Parity function and leave parity in stick '0' parity as default
+ UARTx->LCR |= (UART_LCR_PARITY_F_0 | UART_LCR_PARITY_EN);
+}
+
+/*********************************************************************//**
+ * @brief Enable/Disable receiver in RS485 module in UART1
+ * @param[in] UARTx LPC_UART1 (only)
+ * @param[in] NewState New State of command, should be:
+ * - ENABLE: Enable this function.
+ * - DISABLE: Disable this function.
+ * @return None
+ **********************************************************************/
+void UART_RS485ReceiverCmd(LPC_UART1_TypeDef *UARTx, FunctionalState NewState)
+{
+ if (NewState == ENABLE){
+ UARTx->RS485CTRL &= ~UART1_RS485CTRL_RX_DIS;
+ } else {
+ UARTx->RS485CTRL |= UART1_RS485CTRL_RX_DIS;
+ }
+}
+
+/*********************************************************************//**
+ * @brief Send data on RS485 bus with specified parity stick value (9-bit mode).
+ * @param[in] UARTx LPC_UART1 (only)
+ * @param[in] pDatFrm Pointer to data frame.
+ * @param[in] size Size of data.
+ * @param[in] ParityStick Parity Stick value, should be 0 or 1.
+ * @return None
+ **********************************************************************/
+uint32_t UART_RS485Send(LPC_UART1_TypeDef *UARTx, uint8_t *pDatFrm, \
+ uint32_t size, uint8_t ParityStick)
+{
+ uint8_t tmp, save;
+ uint32_t cnt;
+
+ if (ParityStick){
+ save = tmp = UARTx->LCR & UART_LCR_BITMASK;
+ tmp &= ~(UART_LCR_PARITY_EVEN);
+ UARTx->LCR = tmp;
+ cnt = UART_Send((LPC_UART_TypeDef *)UARTx, pDatFrm, size, BLOCKING);
+ while (!(UARTx->LSR & UART_LSR_TEMT));
+ UARTx->LCR = save;
+ } else {
+ cnt = UART_Send((LPC_UART_TypeDef *)UARTx, pDatFrm, size, BLOCKING);
+ while (!(UARTx->LSR & UART_LSR_TEMT));
+ }
+ return cnt;
+}
+
+/*********************************************************************//**
+ * @brief Send Slave address frames on RS485 bus.
+ * @param[in] UARTx LPC_UART1 (only)
+ * @param[in] SlvAddr Slave Address.
+ * @return None
+ **********************************************************************/
+void UART_RS485SendSlvAddr(LPC_UART1_TypeDef *UARTx, uint8_t SlvAddr)
+{
+ UART_RS485Send(UARTx, &SlvAddr, 1, 1);
+}
+
+/*********************************************************************//**
+ * @brief Send Data frames on RS485 bus.
+ * @param[in] UARTx LPC_UART1 (only)
+ * @param[in] pData Pointer to data to be sent.
+ * @param[in] size Size of data frame to be sent.
+ * @return None
+ **********************************************************************/
+uint32_t UART_RS485SendData(LPC_UART1_TypeDef *UARTx, uint8_t *pData, uint32_t size)
+{
+ return (UART_RS485Send(UARTx, pData, size, 0));
+}
+
+#endif /* _UART1 */
+
+#endif /* _UART */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/* --------------------------------- End Of File ------------------------------ */
+
diff --git a/arch/arm/lpc17xx/Drivers/source/lpc17xx_wdt.c b/arch/arm/lpc17xx/Drivers/source/lpc17xx_wdt.c
new file mode 100644
index 0000000..1d8b407
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/lpc17xx_wdt.c
@@ -0,0 +1,261 @@
+/***********************************************************************//**
+ * @file lpc17xx_wdt.c
+ * @brief Contains all functions support for WDT firmware library on LPC17xx
+ * @version 2.0
+ * @date 21. May. 2010
+ * @author NXP MCU SW Application Team
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup WDT
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_wdt.h"
+#include "lpc17xx_clkpwr.h"
+#include "lpc17xx_pinsel.h"
+
+
+/* If this source file built with example, the LPC17xx FW library configuration
+ * file in each example directory ("lpc17xx_libcfg.h") must be included,
+ * otherwise the default FW library configuration file must be included instead
+ */
+#ifdef __BUILD_WITH_EXAMPLE__
+#include "lpc17xx_libcfg.h"
+#else
+#include "lpc17xx_libcfg_default.h"
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+
+#ifdef _WDT
+
+/* Private Functions ---------------------------------------------------------- */
+
+static uint8_t WDT_SetTimeOut (uint8_t clk_source, uint32_t timeout);
+
+/********************************************************************//**
+ * @brief Set WDT time out value and WDT mode
+ * @param[in] clk_source select Clock source for WDT device
+ * @param[in] timeout value of time-out for WDT (us)
+ * @return None
+ *********************************************************************/
+static uint8_t WDT_SetTimeOut (uint8_t clk_source, uint32_t timeout)
+{
+
+ uint32_t pclk_wdt = 0;
+ uint32_t tempval = 0;
+
+ switch ((WDT_CLK_OPT) clk_source)
+ {
+ case WDT_CLKSRC_IRC:
+ pclk_wdt = 4000000;
+ // Calculate TC in WDT
+ tempval = (((pclk_wdt) / WDT_US_INDEX) * (timeout / 4));
+ // Check if it valid
+ if ((tempval >= WDT_TIMEOUT_MIN) && (tempval <= WDT_TIMEOUT_MAX))
+ {
+ LPC_WDT->WDTC = tempval;
+ return SUCCESS;
+ }
+
+ break;
+
+ case WDT_CLKSRC_PCLK:
+
+ // Get WDT clock with CCLK divider = 4
+ pclk_wdt = SystemCoreClock / 4;
+ // Calculate TC in WDT
+ tempval = (((pclk_wdt) / WDT_US_INDEX) * (timeout / 4));
+
+ if ((tempval >= WDT_TIMEOUT_MIN) && (tempval <= WDT_TIMEOUT_MAX))
+ {
+ CLKPWR_SetPCLKDiv (CLKPWR_PCLKSEL_WDT, CLKPWR_PCLKSEL_CCLK_DIV_4);
+ LPC_WDT->WDTC = (uint32_t) tempval;
+ return SUCCESS;
+ }
+
+ // Get WDT clock with CCLK divider = 2
+ pclk_wdt = SystemCoreClock / 2;
+ // Calculate TC in WDT
+ tempval = (((pclk_wdt) / WDT_US_INDEX) * (timeout / 4));
+
+ if ((tempval >= WDT_TIMEOUT_MIN) && (tempval <= WDT_TIMEOUT_MAX))
+ {
+ CLKPWR_SetPCLKDiv (CLKPWR_PCLKSEL_WDT, CLKPWR_PCLKSEL_CCLK_DIV_2);
+ LPC_WDT->WDTC = (uint32_t) tempval;
+ return SUCCESS;
+ }
+
+ // Get WDT clock with CCLK divider = 1
+ pclk_wdt = SystemCoreClock;
+ // Calculate TC in WDT
+ tempval = (((pclk_wdt) / WDT_US_INDEX) * (timeout / 4));
+
+ if ((tempval >= WDT_TIMEOUT_MIN) && (tempval <= WDT_TIMEOUT_MAX))
+ {
+ CLKPWR_SetPCLKDiv (CLKPWR_PCLKSEL_WDT, CLKPWR_PCLKSEL_CCLK_DIV_1);
+ LPC_WDT->WDTC = (uint32_t) tempval;
+ return SUCCESS;
+ }
+ break ;
+
+
+ case WDT_CLKSRC_RTC:
+ pclk_wdt = 32768;
+ // Calculate TC in WDT
+ tempval = (((pclk_wdt) / WDT_US_INDEX) * (timeout / 4));
+ // Check if it valid
+ if ((tempval >= WDT_TIMEOUT_MIN) && (tempval <= WDT_TIMEOUT_MAX))
+ {
+ LPC_WDT->WDTC = (uint32_t) tempval;
+ return SUCCESS;
+ }
+
+ break;
+
+// Error parameter
+ default:
+ break;
+}
+
+ return ERROR;
+}
+
+/* End of Private Functions --------------------------------------------------- */
+
+
+/* Public Functions ----------------------------------------------------------- */
+/** @addtogroup WDT_Public_Functions
+ * @{
+ */
+
+
+/*********************************************************************//**
+* @brief Initial for Watchdog function
+* Clock source = RTC ,
+* @param[in] ClkSrc Select clock source, should be:
+* - WDT_CLKSRC_IRC: Clock source from Internal RC oscillator
+* - WDT_CLKSRC_PCLK: Selects the APB peripheral clock (PCLK)
+* - WDT_CLKSRC_RTC: Selects the RTC oscillator
+* @param[in] WDTMode WDT mode, should be:
+* - WDT_MODE_INT_ONLY: Use WDT to generate interrupt only
+* - WDT_MODE_RESET: Use WDT to generate interrupt and reset MCU
+* @return None
+ **********************************************************************/
+void WDT_Init (WDT_CLK_OPT ClkSrc, WDT_MODE_OPT WDTMode)
+{
+ CHECK_PARAM(PARAM_WDT_CLK_OPT(ClkSrc));
+ CHECK_PARAM(PARAM_WDT_MODE_OPT(WDTMode));
+ CLKPWR_SetPCLKDiv (CLKPWR_PCLKSEL_WDT, CLKPWR_PCLKSEL_CCLK_DIV_4);
+
+ //Set clock source
+ LPC_WDT->WDCLKSEL &= ~WDT_WDCLKSEL_MASK;
+ LPC_WDT->WDCLKSEL |= ClkSrc;
+ //Set WDT mode
+ if (WDTMode == WDT_MODE_RESET){
+ LPC_WDT->WDMOD |= WDT_WDMOD(WDTMode);
+ }
+}
+
+/*********************************************************************//**
+* @brief Start WDT activity with given timeout value
+* @param[in] TimeOut WDT reset after timeout if it is not feed
+* @return None
+ **********************************************************************/
+void WDT_Start(uint32_t TimeOut)
+{
+ uint32_t ClkSrc;
+
+ ClkSrc = LPC_WDT->WDCLKSEL;
+ ClkSrc &=WDT_WDCLKSEL_MASK;
+ WDT_SetTimeOut(ClkSrc,TimeOut);
+ //enable watchdog
+ LPC_WDT->WDMOD |= WDT_WDMOD_WDEN;
+ WDT_Feed();
+}
+
+/********************************************************************//**
+ * @brief Read WDT Time out flag
+ * @param[in] None
+ * @return Time out flag status of WDT
+ *********************************************************************/
+FlagStatus WDT_ReadTimeOutFlag (void)
+{
+ return ((FlagStatus)((LPC_WDT->WDMOD & WDT_WDMOD_WDTOF) >>2));
+}
+
+/********************************************************************//**
+ * @brief Clear WDT Time out flag
+ * @param[in] None
+ * @return None
+ *********************************************************************/
+void WDT_ClrTimeOutFlag (void)
+{
+ LPC_WDT->WDMOD &=~WDT_WDMOD_WDTOF;
+}
+
+/********************************************************************//**
+ * @brief Update WDT timeout value and feed
+ * @param[in] TimeOut TimeOut value to be updated
+ * @return None
+ *********************************************************************/
+void WDT_UpdateTimeOut ( uint32_t TimeOut)
+{
+ uint32_t ClkSrc;
+ ClkSrc = LPC_WDT->WDCLKSEL;
+ ClkSrc &=WDT_WDCLKSEL_MASK;
+ WDT_SetTimeOut(ClkSrc,TimeOut);
+ WDT_Feed();
+}
+
+
+/********************************************************************//**
+ * @brief After set WDTEN, call this function to start Watchdog
+ * or reload the Watchdog timer
+ * @param[in] None
+ *
+ * @return None
+ *********************************************************************/
+void WDT_Feed (void)
+{
+ // Disable irq interrupt
+ __disable_irq();
+ LPC_WDT->WDFEED = 0xAA;
+ LPC_WDT->WDFEED = 0x55;
+ // Then enable irq interrupt
+ __enable_irq();
+}
+
+/********************************************************************//**
+ * @brief Get the current value of WDT
+ * @param[in] None
+ * @return current value of WDT
+ *********************************************************************/
+uint32_t WDT_GetCurrentCount(void)
+{
+ return LPC_WDT->WDTV;
+}
+
+/**
+ * @}
+ */
+
+#endif /* _WDT */
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
diff --git a/arch/arm/lpc17xx/Drivers/source/makefile b/arch/arm/lpc17xx/Drivers/source/makefile
new file mode 100644
index 0000000..8cf581c
--- /dev/null
+++ b/arch/arm/lpc17xx/Drivers/source/makefile
@@ -0,0 +1,84 @@
+########################################################################
+# $Id:: makefile 814 2008-06-19 19:57:32Z pdurgesh $
+#
+# Project: Standard compile makefile
+#
+# Description:
+# Makefile
+#
+########################################################################
+# Software that is described herein is for illustrative purposes only
+# which provides customers with programming information regarding the
+# products. This software is supplied "AS IS" without any warranties.
+# NXP Semiconductors assumes no responsibility or liability for the
+# use of the software, conveys no license or title under any patent,
+# copyright, or mask work right to the product. NXP Semiconductors
+# reserves the right to make changes in the software without
+# notification. NXP Semiconductors also make no representation or
+# warranty that such application will be suitable for the specified
+# use without further testing or modification.
+########################################################################
+
+########################################################################
+#
+# Pick up the configuration file in make section
+#
+########################################################################
+include ../../makesection/makeconfig
+
+########################################################################
+#
+# Pick up the default build rules
+#
+########################################################################
+
+include $(PROJ_ROOT)/makesection/makerule/$(DEVICE)/make.$(DEVICE).$(TOOL)
+
+########################################################################
+#
+# Pick up the assembler and C source files in the directory
+#
+########################################################################
+include $(PROJ_ROOT)\makesection\makerule\common\make.rules.ftypes
+AFLAGS +=-I../include
+CFLAGS +=-I../include
+
+
+########################################################################
+#
+# Build the library
+#
+########################################################################
+
+$(TARGET_FWLIB_LIB) : .vias $(OBJS) $(FWLIB_LIB_DIR)
+ $(ECHO) "creating" $(FWLIB) "Firmware support package library"
+ $(AR) $@ $(OBJS)
+
+$(FWLIB_LIB_DIR):
+ $(MKDIR) $(FWLIB_LIB_DIR)
+
+# delete all targets this Makefile can make
+lib_clean:
+ -@$(RM) $(TARGET_FWLIB_LIB)
+
+# delete all targets this Makefile can make and all built libraries
+# linked in
+lib_realclean:
+ -@$(RM) $(FWLIB_LIB_DIR)/*.a
+ -@$(RMDIR) $(FWLIB_LIB_DIR)
+
+clean: lib_clean
+realclean: lib_realclean
+
+########################################################################
+#
+# Compile the code base
+#
+########################################################################
+
+include $(PROJ_ROOT)/makesection/makerule/common/make.rules.build
+
+.PHONY: all lib_clean lib_realclean
+
+
+