diff --git a/fatfs/diskio.c b/fatfs/diskio.c index 0c65b432..5e1763fd 100644 --- a/fatfs/diskio.c +++ b/fatfs/diskio.c @@ -10,6 +10,16 @@ #include "diskio.h" /* FatFs lower layer API */ #include +#ifdef CFG_HAVE_SD +#ifndef CORE_M4 +#define CORE_M4 +#endif +#include +#include +#include +#include +#endif // CFG_HAVE_SD + /* Definitions of physical drive number for each drive */ #define FLASH 0 /* Example: Map ATA harddisk to physical drive 0 */ #define SD 1 /* Example: Map MMC/SD card to physical drive 1 */ @@ -23,7 +33,7 @@ DSTATUS disk_status ( ) { DSTATUS stat; - int result; + int __attribute__ ((unused)) result; #ifdef CFG_HAVE_SD switch (pdrv) { @@ -33,9 +43,9 @@ DSTATUS disk_status ( return RES_OK; #ifdef CFG_HAVE_SD case SD : - result = MMC_disk_status(); - // translate the reslut code here - return stat; + result = Chip_SDMMC_GetState(LPC_SDMMC); + //TODO: translate the reslut code here + return RES_OK; } #endif return STA_NOINIT; @@ -63,11 +73,12 @@ DSTATUS disk_initialize ( #ifdef CFG_HAVE_SD case SD : - result = MMC_disk_initialize(); + sdmmc_setup(); + uint32_t res = sdmmc_acquire(); // translate the reslut code here - return stat; + return (res == 1) ? RES_OK : RES_ERROR; } #endif return STA_NOINIT; @@ -98,13 +109,10 @@ DRESULT disk_read ( #ifdef CFG_HAVE_SD case SD : - // translate the arguments here - - result = MMC_disk_read(buff, sector, count); + result = Chip_SDMMC_ReadBlocks(LPC_SDMMC, buff, sector, count); - // translate the reslut code here - - return res; + return (result == count*512) ? RES_OK : RES_ERROR; + } #endif return RES_PARERR; @@ -137,13 +145,9 @@ DRESULT disk_write ( #ifdef CFG_HAVE_SD case SD : - // translate the arguments here - - result = MMC_disk_write(buff, sector, count); + result = Chip_SDMMC_WriteBlocks(LPC_SDMMC, (uint8_t*) buff, sector, count); - // translate the reslut code here - - return res; + return (result == count*512) ? RES_OK : RES_ERROR; } #endif diff --git a/fatfs/ffconf.h b/fatfs/ffconf.h index 3ea56e5b..0ead5394 100644 --- a/fatfs/ffconf.h +++ b/fatfs/ffconf.h @@ -141,7 +141,11 @@ / Drive/Volume Configurations /---------------------------------------------------------------------------*/ +#ifndef CFG_HAVE_SD #define _VOLUMES 1 +#else +#define _VOLUMES 2 +#endif /* Number of volumes (logical drives) to be used. */ diff --git a/lpcapi/cguccu_18xx_43xx.h b/lpcapi/cguccu_18xx_43xx.h new file mode 100644 index 00000000..396fbb89 --- /dev/null +++ b/lpcapi/cguccu_18xx_43xx.h @@ -0,0 +1,114 @@ +/* + * @brief CGU/CCU registers and control functions + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __CGUCCU_18XX_43XX_H_ +#define __CGUCCU_18XX_43XX_H_ + +#include "chip_clocks.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @ingroup CLOCK_18XX_43XX + * @{ + */ + +/** + * Audio or USB PLL selection + */ +typedef enum CHIP_CGU_USB_AUDIO_PLL { + CGU_USB_PLL, + CGU_AUDIO_PLL +} CHIP_CGU_USB_AUDIO_PLL_T; + +/** + * PLL register block + */ +typedef struct { + __I uint32_t PLL_STAT; /*!< PLL status register */ + __IO uint32_t PLL_CTRL; /*!< PLL control register */ + __IO uint32_t PLL_MDIV; /*!< PLL M-divider register */ + __IO uint32_t PLL_NP_DIV; /*!< PLL N/P-divider register */ +} CGU_PLL_REG_T; + +/** + * @brief LPC18XX/43XX CGU register block structure + */ +typedef struct { /*!< (@ 0x40050000) CGU Structure */ + __I uint32_t RESERVED0[5]; + __IO uint32_t FREQ_MON; /*!< (@ 0x40050014) Frequency monitor register */ + __IO uint32_t XTAL_OSC_CTRL; /*!< (@ 0x40050018) Crystal oscillator control register */ + CGU_PLL_REG_T PLL[CGU_AUDIO_PLL + 1]; /*!< (@ 0x4005001C) USB and audio PLL blocks */ + __IO uint32_t PLL0AUDIO_FRAC; /*!< (@ 0x4005003C) PLL0 (audio) */ + __I uint32_t PLL1_STAT; /*!< (@ 0x40050040) PLL1 status register */ + __IO uint32_t PLL1_CTRL; /*!< (@ 0x40050044) PLL1 control register */ + __IO uint32_t IDIV_CTRL[CLK_IDIV_LAST];/*!< (@ 0x40050048) Integer divider A-E control registers */ + __IO uint32_t BASE_CLK[CLK_BASE_LAST]; /*!< (@ 0x4005005C) Start of base clock registers */ +} LPC_CGU_T; + +/** + * @brief CCU clock config/status register pair + */ +typedef struct { + __IO uint32_t CFG; /*!< CCU clock configuration register */ + __I uint32_t STAT; /*!< CCU clock status register */ +} CCU_CFGSTAT_T; + +/** + * @brief CCU1 register block structure + */ +typedef struct { /*!< (@ 0x40051000) CCU1 Structure */ + __IO uint32_t PM; /*!< (@ 0x40051000) CCU1 power mode register */ + __I uint32_t BASE_STAT; /*!< (@ 0x40051004) CCU1 base clocks status register */ + __I uint32_t RESERVED0[62]; + CCU_CFGSTAT_T CLKCCU[CLK_CCU1_LAST]; /*!< (@ 0x40051100) Start of CCU1 clock registers */ +} LPC_CCU1_T; + +/** + * @brief CCU2 register block structure + */ +typedef struct { /*!< (@ 0x40052000) CCU2 Structure */ + __IO uint32_t PM; /*!< (@ 0x40052000) Power mode register */ + __I uint32_t BASE_STAT; /*!< (@ 0x40052004) CCU base clocks status register */ + __I uint32_t RESERVED0[62]; + CCU_CFGSTAT_T CLKCCU[CLK_CCU2_LAST - CLK_CCU1_LAST]; /*!< (@ 0x40052100) Start of CCU2 clock registers */ +} LPC_CCU2_T; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CGUCCU_18XX_43XX_H_ */ diff --git a/lpcapi/chip.h b/lpcapi/chip.h new file mode 100644 index 00000000..1396c813 --- /dev/null +++ b/lpcapi/chip.h @@ -0,0 +1,163 @@ +/* + * @brief Chip inclusion selector file + * + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __CHIP_H_ +#define __CHIP_H_ + +#include "sys_config.h" +#include "cmsis.h" + +#if defined(CHIP_LPC18XX) +#include "chip_lpc18xx.h" + +#elif defined(CHIP_LPC43XX) +#include "chip_lpc43xx.h" + +#else +#error CHIP_LPC18XX or CHIP_LPC43XX must be defined +#endif + +/* Aliasing for Chip_USB_Init */ +#define Chip_USB_Init Chip_USB0_Init + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @ingroup CHIP_18XX_43XX_DRIVER_OPTIONS + * @{ + */ + +/** + * @brief System oscillator rate + * This value is defined externally to the chip layer and contains + * the value in Hz for the external oscillator for the board. If using the + * internal oscillator, this rate can be 0. + */ +extern const uint32_t OscRateIn; + +/** + * @brief Clock rate on the CLKIN pin + * This value is defined externally to the chip layer and contains + * the value in Hz for the CLKIN pin for the board. If this pin isn't used, + * this rate can be 0. + */ +extern const uint32_t ExtRateIn; + +/** + * @} + */ + +/** @defgroup SUPPORT_18XX_43XX_FUNC CHIP: LPC18xx/43xx support functions + * @ingroup CHIP_18XX_43XX_Drivers + * @{ + */ + +/** + * @brief Current system clock rate, mainly used for sysTick + */ +extern uint32_t SystemCoreClock; + +/** + * @brief Update system core clock rate, should be called if the + * system has a clock rate change + * @return None + */ +void SystemCoreClockUpdate(void); + +/** + * @brief USB0 Pin and clock initialization + * Calling this function will initialize the USB0 pins and the clock + * @note This function will assume that the chip is clocked by an + * external crystal oscillator of frequency 12MHz + */ +void Chip_USB0_Init(void); + +/** + * @brief USB1 Pin and clock initialization + * Calling this function will initialize the USB0 pins and the clock + * @note This function will assume that the chip is clocked by an + * external crystal oscillator of frequency 12MHz + */ +void Chip_USB1_Init(void); + +/** + * @brief Set up and initialize hardware prior to call to main() + * @return None + * @note Chip_SystemInit() is called prior to the application and sets up + * system clocking prior to the application starting. + */ +void Chip_SystemInit(void); + +/** + * @brief Clock and PLL initialization based input given in @a clkin + * @param clkin : Input reference clock to PLL1 (MAINPLL) see #CHIP_CGU_CLKIN_T + * @param core_freq : Desired output frequency of the PLL1 (Base clock to CPU Core) + * @param setbase : Setup default base clock of peripherals (see notes) + * @return None + * @note This API will initialize the MAINPLL (PLL1) to the frequency given by + * @a core_freq, and will use this PLL's output as the base clock for CPU + * Core. If @a clkin is #CLKIN_CRYSTAL then External Crystal Oscillator + * of frequency 12MHz will be used as the input reference clock to PLL1.
+ * Parameter @a setbase if true will set APB[1,3], SSP[0,1], UART[0,1,2,3], + * SPI base clocks to MAINPLL's output clock. If @a setbase is false then + * the base clock settings for the peripherals will not be modified, only + * CPU Core's base clock will be updated to use clock generated by PLL1. + */ +void Chip_SetupCoreClock(CHIP_CGU_CLKIN_T clkin, uint32_t core_freq, bool setbase); + +/** + * @brief Clock and PLL initialization based on the external oscillator + * @return None + * @note This API will initialize the MAINPLL (PLL1) to the maximum + * frequency (180MHz[LPC18xx] or 204MHz[LPC43xx]) and uses this + * PLL's output as the base clock for CPU Core. External Crystal Oscillator + * of frequency 12MHz will be used as the input reference clock to PLL1. + */ +void Chip_SetupXtalClocking(void); + +/** + * @brief Clock and PLL initialization based on the internal oscillator + * @return None + * @note This API will initialize the MAINPLL (PLL1) to the maximum + * frequency (180MHz[LPC18xx] or 204MHz[LPC43xx]) and uses this + * PLL's output as the base clock for CPU Core. Internal RC Oscillator + * will be used as the input reference clock to PLL1. + */ +void Chip_SetupIrcClocking(void); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CHIP_H_ */ diff --git a/lpcapi/chip_clocks.h b/lpcapi/chip_clocks.h new file mode 100644 index 00000000..6313a768 --- /dev/null +++ b/lpcapi/chip_clocks.h @@ -0,0 +1,252 @@ +/* + * @brief LPC18xx/43xx chip clock list used by CGU and CCU drivers + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __CHIP_CLOCKS_H_ +#define __CHIP_CLOCKS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @ingroup CLOCK_18XX_43XX + * @{ + */ + +/** + * @brief CGU clock input list + * These are possible input clocks for the CGU and can come + * from both external (crystal) and internal (PLL) sources. These + * clock inputs can be routed to the base clocks (@ref CHIP_CGU_BASE_CLK_T). + */ +typedef enum CHIP_CGU_CLKIN { + CLKIN_32K, /*!< External 32KHz input */ + CLKIN_IRC, /*!< Internal IRC (12MHz) input */ + CLKIN_ENET_RX, /*!< External ENET_RX pin input */ + CLKIN_ENET_TX, /*!< External ENET_TX pin input */ + CLKIN_CLKIN, /*!< External GPCLKIN pin input */ + CLKIN_RESERVED1, + CLKIN_CRYSTAL, /*!< External (main) crystal pin input */ + CLKIN_USBPLL, /*!< Internal USB PLL input */ + CLKIN_AUDIOPLL, /*!< Internal Audio PLL input */ + CLKIN_MAINPLL, /*!< Internal Main PLL input */ + CLKIN_RESERVED2, + CLKIN_RESERVED3, + CLKIN_IDIVA, /*!< Internal divider A input */ + CLKIN_IDIVB, /*!< Internal divider B input */ + CLKIN_IDIVC, /*!< Internal divider C input */ + CLKIN_IDIVD, /*!< Internal divider D input */ + CLKIN_IDIVE, /*!< Internal divider E input */ + CLKINPUT_PD /*!< External 32KHz input */ +} CHIP_CGU_CLKIN_T; + +/** + * @brief CGU base clocks + * CGU base clocks are clocks that are associated with a single input clock + * and are routed out to 1 or more peripherals. For example, the CLK_BASE_PERIPH + * clock can be configured to use the CLKIN_MAINPLL input clock, which will in + * turn route that clock to the CLK_PERIPH_BUS, CLK_PERIPH_CORE, and + * CLK_PERIPH_SGPIO periphral clocks. + */ +typedef enum CHIP_CGU_BASE_CLK { + CLK_BASE_SAFE, /*!< Base clock for WDT oscillator, IRC input only */ + CLK_BASE_USB0, /*!< Base USB clock for USB0, USB PLL input only */ +#if defined(CHIP_LPC43XX) + CLK_BASE_PERIPH, /*!< Base clock for SGPIO */ +#else + CLK_BASE_RESERVED1, +#endif + CLK_BASE_USB1, /*!< Base USB clock for USB1 */ + CLK_BASE_MX, /*!< Base clock for CPU core */ + CLK_BASE_SPIFI, /*!< Base clock for SPIFI */ +#if defined(CHIP_LPC43XX) + CLK_BASE_SPI, /*!< Base clock for SPI */ +#else + CLK_BASE_RESERVED2, +#endif + CLK_BASE_PHY_RX, /*!< Base clock for PHY RX */ + CLK_BASE_PHY_TX, /*!< Base clock for PHY TX */ + CLK_BASE_APB1, /*!< Base clock for APB1 group */ + CLK_BASE_APB3, /*!< Base clock for APB3 group */ + CLK_BASE_LCD, /*!< Base clock for LCD pixel clock */ +#if defined(CHIP_LPC43XX) + CLK_BASE_ADCHS, /*!< Base clock for ADCHS */ +#else + CLK_BASE_RESERVED3, +#endif + CLK_BASE_SDIO, /*!< Base clock for SDIO */ + CLK_BASE_SSP0, /*!< Base clock for SSP0 */ + CLK_BASE_SSP1, /*!< Base clock for SSP1 */ + CLK_BASE_UART0, /*!< Base clock for UART0 */ + CLK_BASE_UART1, /*!< Base clock for UART1 */ + CLK_BASE_UART2, /*!< Base clock for UART2 */ + CLK_BASE_UART3, /*!< Base clock for UART3 */ + CLK_BASE_OUT, /*!< Base clock for CLKOUT pin */ + CLK_BASE_RESERVED4, + CLK_BASE_RESERVED5, + CLK_BASE_RESERVED6, + CLK_BASE_RESERVED7, + CLK_BASE_APLL, /*!< Base clock for audio PLL */ + CLK_BASE_CGU_OUT0, /*!< Base clock for CGUOUT0 pin */ + CLK_BASE_CGU_OUT1, /*!< Base clock for CGUOUT1 pin */ + CLK_BASE_LAST, + CLK_BASE_NONE = CLK_BASE_LAST +} CHIP_CGU_BASE_CLK_T; + +/** + * @brief CGU dividers + * CGU dividers provide an extra clock state where a specific clock can be + * divided before being routed to a peripheral group. A divider accepts an + * input clock and then divides it. To use the divided clock for a base clock + * group, use the divider as the input clock for the base clock (for example, + * use CLKIN_IDIVB, where CLKIN_MAINPLL might be the input into the divider). + */ +typedef enum CHIP_CGU_IDIV { + CLK_IDIV_A, /*!< CGU clock divider A */ + CLK_IDIV_B, /*!< CGU clock divider B */ + CLK_IDIV_C, /*!< CGU clock divider A */ + CLK_IDIV_D, /*!< CGU clock divider D */ + CLK_IDIV_E, /*!< CGU clock divider E */ + CLK_IDIV_LAST +} CHIP_CGU_IDIV_T; + +#define CHIP_CGU_IDIV_MASK(x) ("\x03\x0F\x0F\x0F\xFF"[x]) + +/** + * @brief Peripheral clocks + * Peripheral clocks are individual clocks routed to peripherals. Although + * multiple peripherals may share a same base clock, each peripheral's clock + * can be enabled or disabled individually. Some peripheral clocks also have + * additional dividers associated with them. + */ +typedef enum CHIP_CCU_CLK { + /* CCU1 clocks */ + CLK_APB3_BUS, /*!< APB3 bus clock from base clock CLK_BASE_APB3 */ + CLK_APB3_I2C1, /*!< I2C1 register/perigheral clock from base clock CLK_BASE_APB3 */ + CLK_APB3_DAC, /*!< DAC peripheral clock from base clock CLK_BASE_APB3 */ + CLK_APB3_ADC0, /*!< ADC0 register/perigheral clock from base clock CLK_BASE_APB3 */ + CLK_APB3_ADC1, /*!< ADC1 register/perigheral clock from base clock CLK_BASE_APB3 */ + CLK_APB3_CAN0, /*!< CAN0 register/perigheral clock from base clock CLK_BASE_APB3 */ + CLK_APB1_BUS = 32, /*!< APB1 bus clock clock from base clock CLK_BASE_APB1 */ + CLK_APB1_MOTOCON, /*!< Motor controller register/perigheral clock from base clock CLK_BASE_APB1 */ + CLK_APB1_I2C0, /*!< I2C0 register/perigheral clock from base clock CLK_BASE_APB1 */ + CLK_APB1_I2S, /*!< I2S register/perigheral clock from base clock CLK_BASE_APB1 */ + CLK_APB1_CAN1, /*!< CAN1 register/perigheral clock from base clock CLK_BASE_APB1 */ + CLK_SPIFI = 64, /*!< SPIFI SCKI input clock from base clock CLK_BASE_SPIFI */ + CLK_MX_BUS = 96, /*!< M3/M4 BUS core clock from base clock CLK_BASE_MX */ + CLK_MX_SPIFI, /*!< SPIFI register clock from base clock CLK_BASE_MX */ + CLK_MX_GPIO, /*!< GPIO register clock from base clock CLK_BASE_MX */ + CLK_MX_LCD, /*!< LCD register clock from base clock CLK_BASE_MX */ + CLK_MX_ETHERNET, /*!< ETHERNET register clock from base clock CLK_BASE_MX */ + CLK_MX_USB0, /*!< USB0 register clock from base clock CLK_BASE_MX */ + CLK_MX_EMC, /*!< EMC clock from base clock CLK_BASE_MX */ + CLK_MX_SDIO, /*!< SDIO register clock from base clock CLK_BASE_MX */ + CLK_MX_DMA, /*!< DMA register clock from base clock CLK_BASE_MX */ + CLK_MX_MXCORE, /*!< M3/M4 CPU core clock from base clock CLK_BASE_MX */ + RESERVED_ALIGN = CLK_MX_MXCORE + 3, + CLK_MX_SCT, /*!< SCT register clock from base clock CLK_BASE_MX */ + CLK_MX_USB1, /*!< USB1 register clock from base clock CLK_BASE_MX */ + CLK_MX_EMC_DIV, /*!< ENC divider clock from base clock CLK_BASE_MX */ + CLK_MX_FLASHA, /*!< FLASHA bank clock from base clock CLK_BASE_MX */ + CLK_MX_FLASHB, /*!< FLASHB bank clock from base clock CLK_BASE_MX */ +#if defined(CHIP_LPC43XX) + CLK_M4_M0APP, /*!< M0 app CPU core clock from base clock CLK_BASE_MX */ + CLK_MX_ADCHS, /*!< ADCHS clock from base clock CLK_BASE_ADCHS */ +#else + CLK_RESERVED1, + CLK_RESERVED2, +#endif + CLK_MX_EEPROM, /*!< EEPROM clock from base clock CLK_BASE_MX */ + CLK_MX_WWDT = 128, /*!< WWDT register clock from base clock CLK_BASE_MX */ + CLK_MX_UART0, /*!< UART0 register clock from base clock CLK_BASE_MX */ + CLK_MX_UART1, /*!< UART1 register clock from base clock CLK_BASE_MX */ + CLK_MX_SSP0, /*!< SSP0 register clock from base clock CLK_BASE_MX */ + CLK_MX_TIMER0, /*!< TIMER0 register/perigheral clock from base clock CLK_BASE_MX */ + CLK_MX_TIMER1, /*!< TIMER1 register/perigheral clock from base clock CLK_BASE_MX */ + CLK_MX_SCU, /*!< SCU register/perigheral clock from base clock CLK_BASE_MX */ + CLK_MX_CREG, /*!< CREG clock from base clock CLK_BASE_MX */ + CLK_MX_RITIMER = 160, /*!< RITIMER register/perigheral clock from base clock CLK_BASE_MX */ + CLK_MX_UART2, /*!< UART3 register clock from base clock CLK_BASE_MX */ + CLK_MX_UART3, /*!< UART4 register clock from base clock CLK_BASE_MX */ + CLK_MX_TIMER2, /*!< TIMER2 register/perigheral clock from base clock CLK_BASE_MX */ + CLK_MX_TIMER3, /*!< TIMER3 register/perigheral clock from base clock CLK_BASE_MX */ + CLK_MX_SSP1, /*!< SSP1 register clock from base clock CLK_BASE_MX */ + CLK_MX_QEI, /*!< QEI register/perigheral clock from base clock CLK_BASE_MX */ +#if defined(CHIP_LPC43XX) + CLK_PERIPH_BUS = 192, /*!< Peripheral bus clock from base clock CLK_BASE_PERIPH */ + CLK_RESERVED3, + CLK_PERIPH_CORE, /*!< Peripheral core clock from base clock CLK_BASE_PERIPH */ + CLK_PERIPH_SGPIO, /*!< SGPIO clock from base clock CLK_BASE_PERIPH */ +#else + CLK_RESERVED3 = 192, + CLK_RESERVED3A, + CLK_RESERVED4, + CLK_RESERVED5, +#endif + CLK_USB0 = 224, /*!< USB0 clock from base clock CLK_BASE_USB0 */ + CLK_USB1 = 256, /*!< USB1 clock from base clock CLK_BASE_USB1 */ +#if defined(CHIP_LPC43XX) + CLK_SPI = 288, /*!< SPI clock from base clock CLK_BASE_SPI */ + CLK_ADCHS = 320, /*!< ADCHS clock from base clock CLK_BASE_ADCHS */ +#else + CLK_RESERVED7 = 320, + CLK_RESERVED8, +#endif + CLK_CCU1_LAST, + + /* CCU2 clocks */ + CLK_CCU2_START, + CLK_APLL = CLK_CCU2_START, /*!< Audio PLL clock from base clock CLK_BASE_APLL */ + RESERVED_ALIGNB = CLK_CCU2_START + 31, + CLK_APB2_UART3, /*!< UART3 clock from base clock CLK_BASE_UART3 */ + RESERVED_ALIGNC = CLK_CCU2_START + 63, + CLK_APB2_UART2, /*!< UART2 clock from base clock CLK_BASE_UART2 */ + RESERVED_ALIGND = CLK_CCU2_START + 95, + CLK_APB0_UART1, /*!< UART1 clock from base clock CLK_BASE_UART1 */ + RESERVED_ALIGNE = CLK_CCU2_START + 127, + CLK_APB0_UART0, /*!< UART0 clock from base clock CLK_BASE_UART0 */ + RESERVED_ALIGNF = CLK_CCU2_START + 159, + CLK_APB2_SSP1, /*!< SSP1 clock from base clock CLK_BASE_SSP1 */ + RESERVED_ALIGNG = CLK_CCU2_START + 191, + CLK_APB0_SSP0, /*!< SSP0 clock from base clock CLK_BASE_SSP0 */ + RESERVED_ALIGNH = CLK_CCU2_START + 223, + CLK_APB2_SDIO, /*!< SDIO clock from base clock CLK_BASE_SDIO */ + CLK_CCU2_LAST +} CHIP_CCU_CLK_T; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CHIP_CLOCKS_H_ */ diff --git a/lpcapi/chip_lpc43xx.h b/lpcapi/chip_lpc43xx.h new file mode 100644 index 00000000..d0c8b505 --- /dev/null +++ b/lpcapi/chip_lpc43xx.h @@ -0,0 +1,220 @@ +/* + * @brief LPC43xx basic chip inclusion file + * + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __CHIP_LPC43XX_H_ +#define __CHIP_LPC43XX_H_ + +#include "lpc_types.h" +#include "sys_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(CORE_M4) && !defined(CORE_M0) +#error CORE_M4 or CORE_M0 is not defined for the LPC43xx architecture +#error CORE_M4 or CORE_M0 should be defined as part of your compiler define list +#endif + +#ifndef CHIP_LPC43XX +#error The LPC43XX Chip include path is used for this build, but +#error CHIP_LPC43XX is not defined! +#endif + +/** @defgroup PERIPH_43XX_BASE CHIP: LPC43xx Peripheral addresses and register set declarations + * @ingroup CHIP_18XX_43XX_Drivers + * @{ + */ + +#define LPC_SCT_BASE 0x40000000 +#define LPC_GPDMA_BASE 0x40002000 +#define LPC_SPIFI_BASE 0x40003000 +#define LPC_SDMMC_BASE 0x40004000 +#define LPC_EMC_BASE 0x40005000 +#define LPC_USB0_BASE 0x40006000 +#define LPC_USB1_BASE 0x40007000 +#define LPC_LCD_BASE 0x40008000 +#define LPC_FMCA_BASE 0x4000C000 +#define LPC_FMCB_BASE 0x4000D000 +#define LPC_ETHERNET_BASE 0x40010000 +#define LPC_ATIMER_BASE 0x40040000 +#define LPC_REGFILE_BASE 0x40041000 +#define LPC_PMC_BASE 0x40042000 +#define LPC_CREG_BASE 0x40043000 +#define LPC_EVRT_BASE 0x40044000 +#define LPC_RTC_BASE 0x40046000 +#define LPC_CGU_BASE 0x40050000 +#define LPC_CCU1_BASE 0x40051000 +#define LPC_CCU2_BASE 0x40052000 +#define LPC_RGU_BASE 0x40053000 +#define LPC_WWDT_BASE 0x40080000 +#define LPC_USART0_BASE 0x40081000 +#define LPC_USART2_BASE 0x400C1000 +#define LPC_USART3_BASE 0x400C2000 +#define LPC_UART1_BASE 0x40082000 +#define LPC_SSP0_BASE 0x40083000 +#define LPC_SSP1_BASE 0x400C5000 +#define LPC_TIMER0_BASE 0x40084000 +#define LPC_TIMER1_BASE 0x40085000 +#define LPC_TIMER2_BASE 0x400C3000 +#define LPC_TIMER3_BASE 0x400C4000 +#define LPC_SCU_BASE 0x40086000 +#define LPC_PIN_INT_BASE 0x40087000 +#define LPC_GPIO_GROUP_INT0_BASE 0x40088000 +#define LPC_GPIO_GROUP_INT1_BASE 0x40089000 +#define LPC_MCPWM_BASE 0x400A0000 +#define LPC_I2C0_BASE 0x400A1000 +#define LPC_I2C1_BASE 0x400E0000 +#define LPC_I2S0_BASE 0x400A2000 +#define LPC_I2S1_BASE 0x400A3000 +#define LPC_C_CAN1_BASE 0x400A4000 +#define LPC_RITIMER_BASE 0x400C0000 +#define LPC_QEI_BASE 0x400C6000 +#define LPC_GIMA_BASE 0x400C7000 +#define LPC_DAC_BASE 0x400E1000 +#define LPC_C_CAN0_BASE 0x400E2000 +#define LPC_ADC0_BASE 0x400E3000 +#define LPC_ADC1_BASE 0x400E4000 +#define LPC_ADCHS_BASE 0x400F0000 +#define LPC_GPIO_PORT_BASE 0x400F4000 +#define LPC_SPI_BASE 0x40100000 +#define LPC_SGPIO_BASE 0x40101000 +#define LPC_EEPROM_BASE 0x4000E000 +#define LPC_ROM_API_BASE 0x10400100 + +#define LPC_SCT ((LPC_SCT_T *) LPC_SCT_BASE) +#define LPC_GPDMA ((LPC_GPDMA_T *) LPC_GPDMA_BASE) +#define LPC_SDMMC ((LPC_SDMMC_T *) LPC_SDMMC_BASE) +#define LPC_EMC ((LPC_EMC_T *) LPC_EMC_BASE) +#define LPC_USB0 ((LPC_USBHS_T *) LPC_USB0_BASE) +#define LPC_USB1 ((LPC_USBHS_T *) LPC_USB1_BASE) +#define LPC_LCD ((LPC_LCD_T *) LPC_LCD_BASE) +#define LPC_ETHERNET ((LPC_ENET_T *) LPC_ETHERNET_BASE) +#define LPC_ATIMER ((LPC_ATIMER_T *) LPC_ATIMER_BASE) +#define LPC_REGFILE ((LPC_REGFILE_T *) LPC_REGFILE_BASE) +#define LPC_PMC ((LPC_PMC_T *) LPC_PMC_BASE) +#define LPC_EVRT ((LPC_EVRT_T *) LPC_EVRT_BASE) +#define LPC_RTC ((LPC_RTC_T *) LPC_RTC_BASE) +#define LPC_CGU ((LPC_CGU_T *) LPC_CGU_BASE) +#define LPC_CCU1 ((LPC_CCU1_T *) LPC_CCU1_BASE) +#define LPC_CCU2 ((LPC_CCU2_T *) LPC_CCU2_BASE) +#define LPC_CREG ((LPC_CREG_T *) LPC_CREG_BASE) +#define LPC_RGU ((LPC_RGU_T *) LPC_RGU_BASE) +#define LPC_WWDT ((LPC_WWDT_T *) LPC_WWDT_BASE) +#define LPC_USART0 ((LPC_USART_T *) LPC_USART0_BASE) +#define LPC_USART2 ((LPC_USART_T *) LPC_USART2_BASE) +#define LPC_USART3 ((LPC_USART_T *) LPC_USART3_BASE) +#define LPC_UART1 ((LPC_USART_T *) LPC_UART1_BASE) +#define LPC_SSP0 ((LPC_SSP_T *) LPC_SSP0_BASE) +#define LPC_SSP1 ((LPC_SSP_T *) LPC_SSP1_BASE) +#define LPC_TIMER0 ((LPC_TIMER_T *) LPC_TIMER0_BASE) +#define LPC_TIMER1 ((LPC_TIMER_T *) LPC_TIMER1_BASE) +#define LPC_TIMER2 ((LPC_TIMER_T *) LPC_TIMER2_BASE) +#define LPC_TIMER3 ((LPC_TIMER_T *) LPC_TIMER3_BASE) +#define LPC_SCU ((LPC_SCU_T *) LPC_SCU_BASE) +#define LPC_GPIO_PIN_INT ((LPC_PIN_INT_T *) LPC_PIN_INT_BASE) +#define LPC_GPIOGROUP ((LPC_GPIOGROUPINT_T *) LPC_GPIO_GROUP_INT0_BASE) +#define LPC_MCPWM ((LPC_MCPWM_T *) LPC_MCPWM_BASE) +#define LPC_I2C0 ((LPC_I2C_T *) LPC_I2C0_BASE) +#define LPC_I2C1 ((LPC_I2C_T *) LPC_I2C1_BASE) +#define LPC_I2S0 ((LPC_I2S_T *) LPC_I2S0_BASE) +#define LPC_I2S1 ((LPC_I2S_T *) LPC_I2S1_BASE) +#define LPC_C_CAN1 ((LPC_CCAN_T *) LPC_C_CAN1_BASE) +#define LPC_RITIMER ((LPC_RITIMER_T *) LPC_RITIMER_BASE) +#define LPC_QEI ((LPC_QEI_T *) LPC_QEI_BASE) +#define LPC_GIMA ((LPC_GIMA_T *) LPC_GIMA_BASE) +#define LPC_DAC ((LPC_DAC_T *) LPC_DAC_BASE) +#define LPC_C_CAN0 ((LPC_CCAN_T *) LPC_C_CAN0_BASE) +#define LPC_ADC0 ((LPC_ADC_T *) LPC_ADC0_BASE) +#define LPC_ADC1 ((LPC_ADC_T *) LPC_ADC1_BASE) +#define LPC_ADCHS ((LPC_HSADC_T *) LPC_ADCHS_BASE) +#define LPC_GPIO_PORT ((LPC_GPIO_T *) LPC_GPIO_PORT_BASE) +#define LPC_SPI ((LPC_SPI_T *) LPC_SPI_BASE) +#define LPC_SGPIO ((LPC_SGPIO_T *) LPC_SGPIO_BASE) +#define LPC_EEPROM ((LPC_EEPROM_T *) LPC_EEPROM_BASE) +#define LPC_FMCA ((LPC_FMC_T *) LPC_FMCA_BASE) +#define LPC_FMC ((LPC_FMC_T * *) LPC_FMCA_BASE) +#define LPC_FMCB ((LPC_FMC_T *) LPC_FMCB_BASE) +#define LPC_ROM_API ((LPC_ROM_API_T *) LPC_ROM_API_BASE) + +/** + * @} + */ + +//#include "scu_18xx_43xx.h" +#include "clock_18xx_43xx.h" +//#include "rgu_18xx_43xx.h" +#include "creg_18xx_43xx.h" +//#include "evrt_18xx_43xx.h" +//#include "otp_18xx_43xx.h" +#include "sdif_18xx_43xx.h" +//#include "adc_18xx_43xx.h" +//#include "hsadc_18xx_43xx.h" +//#include "atimer_18xx_43xx.h" +//#include "aes_18xx_43xx.h" +//#include "ccan_18xx_43xx.h" +//#include "dac_18xx_43xx.h" +//#include "eeprom_18xx_43xx.h" +//#include "emc_18xx_43xx.h" +//#include "enet_18xx_43xx.h" +//#include "fmc_18xx_43xx.h" +//#include "i2c_18xx_43xx.h" +//#include "i2s_18xx_43xx.h" +//#include "gima_18xx_43xx.h" +//#include "gpdma_18xx_43xx.h" +//#include "gpio_18xx_43xx.h" +//#include "pinint_18xx_43xx.h" +//#include "gpiogroup_18xx_43xx.h" +//#include "lcd_18xx_43xx.h" +//#include "mcpwm_18xx_43xx.h" +//#include "pmc_18xx_43xx.h" +//#include "qei_18xx_43xx.h" +//#include "ritimer_18xx_43xx.h" +//#include "rtc_18xx_43xx.h" +//#include "sct_18xx_43xx.h" +//#include "sct_pwm_18xx_43xx.h" +#include "sdmmc_18xx_43xx.h" +//#include "sgpio_18xx_43xx.h" +//#include "spi_18xx_43xx.h" +//#include "ssp_18xx_43xx.h" +//#include "timer_18xx_43xx.h" +//#include "uart_18xx_43xx.h" +//#include "usbhs_18xx_43xx.h" +//#include "wwdt_18xx_43xx.h" +//#include "romapi_18xx_43xx.h" +//#include "i2cm_18xx_43xx.h" + +#if defined(CORE_M4) +#include "fpu_init.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __CHIP_LPC43XX_H_ */ diff --git a/lpcapi/clock_18xx_43xx.c b/lpcapi/clock_18xx_43xx.c new file mode 100644 index 00000000..157b49ea --- /dev/null +++ b/lpcapi/clock_18xx_43xx.c @@ -0,0 +1,708 @@ +/* + * @brief LPC18xx/43xx clock driver + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licenser disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/* Maps a peripheral clock to it's base clock */ +typedef struct { + CHIP_CCU_CLK_T clkstart; + CHIP_CCU_CLK_T clkend; + CHIP_CGU_BASE_CLK_T clkbase; +} CLK_PERIPH_TO_BASE_T; +static const CLK_PERIPH_TO_BASE_T periph_to_base[] = { + {CLK_APB3_BUS, CLK_APB3_CAN0, CLK_BASE_APB3}, + {CLK_APB1_BUS, CLK_APB1_CAN1, CLK_BASE_APB1}, + {CLK_SPIFI, CLK_SPIFI, CLK_BASE_SPIFI}, + {CLK_MX_BUS, CLK_MX_QEI, CLK_BASE_MX}, +#if defined(CHIP_LPC43XX) + {CLK_PERIPH_BUS, CLK_PERIPH_SGPIO, CLK_BASE_PERIPH}, +#endif + {CLK_USB0, CLK_USB0, CLK_BASE_USB0}, + {CLK_USB1, CLK_USB1, CLK_BASE_USB1}, +#if defined(CHIP_LPC43XX) + {CLK_SPI, CLK_SPI, CLK_BASE_SPI}, + {CLK_ADCHS, CLK_ADCHS, CLK_BASE_ADCHS}, +#endif + {CLK_APLL, CLK_APLL, CLK_BASE_APLL}, + {CLK_APB2_UART3, CLK_APB2_UART3, CLK_BASE_UART3}, + {CLK_APB2_UART2, CLK_APB2_UART2, CLK_BASE_UART2}, + {CLK_APB0_UART1, CLK_APB0_UART1, CLK_BASE_UART1}, + {CLK_APB0_UART0, CLK_APB0_UART0, CLK_BASE_UART0}, + {CLK_APB2_SSP1, CLK_APB2_SSP1, CLK_BASE_SSP1}, + {CLK_APB0_SSP0, CLK_APB0_SSP0, CLK_BASE_SSP0}, + {CLK_APB2_SDIO, CLK_APB2_SDIO, CLK_BASE_SDIO}, + {CLK_CCU2_LAST, CLK_CCU2_LAST, CLK_BASE_NONE} +}; + +#define CRYSTAL_32K_FREQ_IN (32 * 1024) + +/* Variables to use audio and usb pll frequency */ +static uint32_t audio_usb_pll_freq[CGU_AUDIO_PLL+1]; + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/* Test PLL input values for a specific frequency range */ +static uint32_t Chip_Clock_TestMainPLLMultiplier(uint32_t InputHz, uint32_t TestMult, uint32_t MinHz, uint32_t MaxHz) +{ + uint32_t TestHz = TestMult * InputHz; + + if ((TestHz < MinHz) || (TestHz > MAX_CLOCK_FREQ) || (TestHz > MaxHz)) { + TestHz = 0; + } + + return TestHz; +} + +/* Returns clock rate out of a divider */ +static uint32_t Chip_Clock_GetDivRate(CHIP_CGU_CLKIN_T clock, CHIP_CGU_IDIV_T divider) +{ + CHIP_CGU_CLKIN_T input; + uint32_t div; + + input = Chip_Clock_GetDividerSource(divider); + div = Chip_Clock_GetDividerDivisor(divider); + return Chip_Clock_GetClockInputHz(input) / (div + 1); +} + +/* Finds the base clock for the peripheral clock */ +static CHIP_CGU_BASE_CLK_T Chip_Clock_FindBaseClock(CHIP_CCU_CLK_T clk) +{ + CHIP_CGU_BASE_CLK_T baseclk = CLK_BASE_NONE; + int i = 0; + + while ((baseclk == CLK_BASE_NONE) && (periph_to_base[i].clkbase != baseclk)) { + if ((clk >= periph_to_base[i].clkstart) && (clk <= periph_to_base[i].clkend)) { + baseclk = periph_to_base[i].clkbase; + } + else { + i++; + } + } + + return baseclk; +} + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Enables the crystal oscillator */ +void Chip_Clock_EnableCrystal(void) +{ + volatile uint32_t delay = 1000; + + uint32_t OldCrystalConfig = LPC_CGU->XTAL_OSC_CTRL; + + /* Clear bypass mode */ + OldCrystalConfig &= (~2); + if (OldCrystalConfig != LPC_CGU->XTAL_OSC_CTRL) { + LPC_CGU->XTAL_OSC_CTRL = OldCrystalConfig; + } + + /* Enable crystal oscillator */ + OldCrystalConfig &= (~1); + if (OscRateIn >= 20000000) { + OldCrystalConfig |= 4; /* Set high frequency mode */ + + } + LPC_CGU->XTAL_OSC_CTRL = OldCrystalConfig; + + /* Delay for 250uSec */ + while(delay--) {} +} + +/* Disables the crystal oscillator */ +void Chip_Clock_DisableCrystal(void) +{ + /* Disable crystal oscillator */ + LPC_CGU->XTAL_OSC_CTRL |= 1; +} + +/* Configures the main PLL */ +uint32_t Chip_Clock_SetupMainPLLHz(CHIP_CGU_CLKIN_T Input, uint32_t MinHz, uint32_t DesiredHz, uint32_t MaxHz) +{ + uint32_t freqin = Chip_Clock_GetClockInputHz(Input); + uint32_t Mult, LastMult, MultEnd; + uint32_t freqout, freqout2; + + if (DesiredHz != 0xFFFFFFFF) { + /* Test DesiredHz rounded down */ + Mult = DesiredHz / freqin; + freqout = Chip_Clock_TestMainPLLMultiplier(freqin, Mult, MinHz, MaxHz); + + /* Test DesiredHz rounded up */ + Mult++; + freqout2 = Chip_Clock_TestMainPLLMultiplier(freqin, Mult, MinHz, MaxHz); + + if (freqout && !freqout2) { /* rounding up is no good? set first multiplier */ + Mult--; + return Chip_Clock_SetupMainPLLMult(Input, Mult); + } + if (!freqout && freqout2) { /* didn't work until rounded up? set 2nd multiplier */ + return Chip_Clock_SetupMainPLLMult(Input, Mult); + } + + if (freqout && freqout2) { /* either multiplier okay? choose closer one */ + if ((DesiredHz - freqout) > (freqout2 - DesiredHz)) { + Mult--; + return Chip_Clock_SetupMainPLLMult(Input, Mult); + } + else { + return Chip_Clock_SetupMainPLLMult(Input, Mult); + } + } + } + + /* Neither multiplier okay? Try to start at MinHz and increment. + This should find the highest multiplier that is still good */ + Mult = MinHz / freqin; + MultEnd = MaxHz / freqin; + LastMult = 0; + while (1) { + freqout = Chip_Clock_TestMainPLLMultiplier(freqin, Mult, MinHz, MaxHz); + + if (freqout) { + LastMult = Mult; + } + + if (Mult >= MultEnd) { + break; + } + Mult++; + } + + if (LastMult) { + return Chip_Clock_SetupMainPLLMult(Input, LastMult); + } + + return 0; +} + +/* Directly set the PLL multipler */ +uint32_t Chip_Clock_SetupMainPLLMult(CHIP_CGU_CLKIN_T Input, uint32_t mult) +{ + volatile uint32_t delay = 250; + uint32_t freq = Chip_Clock_GetClockInputHz(Input); + uint32_t msel = 0, nsel = 0, psel = 0, pval = 1; + uint32_t PLLReg = LPC_CGU->PLL1_CTRL; + + freq *= mult; + msel = mult - 1; + + PLLReg &= ~(0x1F << 24);/* clear input source bits */ + PLLReg |= Input << 24; /* set input source bits to parameter */ + + /* Clear other PLL input bits */ + PLLReg &= ~((1 << 6) | /* FBSEL */ + (1 << 1) | /* BYPASS */ + (1 << 7) | /* DIRECT */ + (0x03 << 8) | (0xFF << 16) | (0x03 << 12)); /* PSEL, MSEL, NSEL- divider ratios */ + + if (freq < 156000000) { + /* psel is encoded such that 0=1, 1=2, 2=4, 3=8 */ + while ((2 * (pval) * freq) < 156000000) { + psel++; + pval *= 2; + } + + PLLReg |= (msel << 16) | (nsel << 12) | (psel << 8) | (1 << 6); /* dividers + FBSEL */ + } + else if (freq < 320000000) { + PLLReg |= (msel << 16) | (nsel << 12) | (psel << 8) | (1 << 7) | (1 << 6); /* dividers + DIRECT + FBSEL */ + } + else { + Chip_Clock_DisableMainPLL(); + return 0; + } + LPC_CGU->PLL1_CTRL = PLLReg & ~(1 << 0); + + /* Wait for 50uSec */ + while(delay--) {} + + return freq; +} + +/* Returns the frequency of the main PLL */ +uint32_t Chip_Clock_GetMainPLLHz(void) +{ + uint32_t PLLReg = LPC_CGU->PLL1_CTRL; + uint32_t freq = Chip_Clock_GetClockInputHz((CHIP_CGU_CLKIN_T) ((PLLReg >> 24) & 0xF)); + uint32_t msel, nsel, psel, direct, fbsel; + uint32_t m, n, p; + const uint8_t ptab[] = {1, 2, 4, 8}; + + /* No lock? */ + if (!(LPC_CGU->PLL1_STAT & 1)) { + return 0; + } + + msel = (PLLReg >> 16) & 0xFF; + nsel = (PLLReg >> 12) & 0x3; + psel = (PLLReg >> 8) & 0x3; + direct = (PLLReg >> 7) & 0x1; + fbsel = (PLLReg >> 6) & 0x1; + + m = msel + 1; + n = nsel + 1; + p = ptab[psel]; + + if (direct || fbsel) { + return m * (freq / n); + } + + return (m / (2 * p)) * (freq / n); +} + +/* Disables the main PLL */ +void Chip_Clock_DisableMainPLL(void) +{ + /* power down main PLL */ + LPC_CGU->PLL1_CTRL |= 1; +} + +/* Disables the main PLL */ +void Chip_Clock_EnableMainPLL(void) +{ + /* power down main PLL */ + LPC_CGU->PLL1_CTRL &= ~1; +} + +/* Returns the lock status of the main PLL */ +bool Chip_Clock_MainPLLLocked(void) +{ + /* Return true if locked */ + return (bool) (LPC_CGU->PLL1_STAT & 1); +} + +/* Sets up a CGU clock divider and it's input clock */ +void Chip_Clock_SetDivider(CHIP_CGU_IDIV_T Divider, CHIP_CGU_CLKIN_T Input, uint32_t Divisor) +{ + uint32_t reg = LPC_CGU->IDIV_CTRL[Divider]; + + Divisor--; + + if (Input != CLKINPUT_PD) { + /* Mask off bits that need to changes */ + reg &= ~((0x1F << 24) | 1 | (CHIP_CGU_IDIV_MASK(Divider) << 2)); + + /* Enable autoblocking, clear PD, and set clock source & divisor */ + LPC_CGU->IDIV_CTRL[Divider] = reg | (1 << 11) | (Input << 24) | (Divisor << 2); + } + else { + LPC_CGU->IDIV_CTRL[Divider] = reg | 1; /* Power down this divider */ + } +} + +/* Gets a CGU clock divider source */ +CHIP_CGU_CLKIN_T Chip_Clock_GetDividerSource(CHIP_CGU_IDIV_T Divider) +{ + uint32_t reg = LPC_CGU->IDIV_CTRL[Divider]; + + if (reg & 1) { /* divider is powered down */ + return CLKINPUT_PD; + } + + return (CHIP_CGU_CLKIN_T) ((reg >> 24) & 0x1F); +} + +/* Gets a CGU clock divider divisor */ +uint32_t Chip_Clock_GetDividerDivisor(CHIP_CGU_IDIV_T Divider) +{ + return (CHIP_CGU_CLKIN_T) ((LPC_CGU->IDIV_CTRL[Divider] >> 2) & CHIP_CGU_IDIV_MASK(Divider)); +} + +/* Returns the frequency of the specified input clock source */ +uint32_t Chip_Clock_GetClockInputHz(CHIP_CGU_CLKIN_T input) +{ + uint32_t rate = 0; + + switch (input) { + case CLKIN_32K: + rate = CRYSTAL_32K_FREQ_IN; + break; + + case CLKIN_IRC: + rate = CGU_IRC_FREQ; + break; + + case CLKIN_ENET_RX: + if ((LPC_CREG->CREG6 & 0x07) != 0x4) { + /* MII mode requires 25MHz clock */ + rate = 25000000; + } + break; + + case CLKIN_ENET_TX: + if ((LPC_CREG->CREG6 & 0x07) != 0x4) { + rate = 25000000; /* MII uses 25 MHz */ + } else { + rate = 50000000; /* RMII uses 50 MHz */ + } + break; + + case CLKIN_CLKIN: + rate = ExtRateIn; + break; + + case CLKIN_CRYSTAL: + rate = OscRateIn; + break; + + case CLKIN_USBPLL: + rate = audio_usb_pll_freq[CGU_USB_PLL]; + break; + + case CLKIN_AUDIOPLL: + rate = audio_usb_pll_freq[CGU_AUDIO_PLL]; + break; + + case CLKIN_MAINPLL: + rate = Chip_Clock_GetMainPLLHz(); + break; + + case CLKIN_IDIVA: + rate = Chip_Clock_GetDivRate(input, CLK_IDIV_A); + break; + + case CLKIN_IDIVB: + rate = Chip_Clock_GetDivRate(input, CLK_IDIV_B); + break; + + case CLKIN_IDIVC: + rate = Chip_Clock_GetDivRate(input, CLK_IDIV_C); + break; + + case CLKIN_IDIVD: + rate = Chip_Clock_GetDivRate(input, CLK_IDIV_D); + break; + + case CLKIN_IDIVE: + rate = Chip_Clock_GetDivRate(input, CLK_IDIV_E); + break; + + case CLKINPUT_PD: + rate = 0; + break; + + default: + break; + } + + return rate; +} + +/* Returns the frequency of the specified base clock source */ +uint32_t Chip_Clock_GetBaseClocktHz(CHIP_CGU_BASE_CLK_T clock) +{ + return Chip_Clock_GetClockInputHz(Chip_Clock_GetBaseClock(clock)); +} + +/* Sets a CGU Base Clock clock source */ +void Chip_Clock_SetBaseClock(CHIP_CGU_BASE_CLK_T BaseClock, CHIP_CGU_CLKIN_T Input, bool autoblocken, bool powerdn) +{ + uint32_t reg = LPC_CGU->BASE_CLK[BaseClock]; + + if (BaseClock < CLK_BASE_NONE) { + if (Input != CLKINPUT_PD) { + /* Mask off fields we plan to update */ + reg &= ~((0x1F << 24) | 1 | (1 << 11)); + + if (autoblocken) { + reg |= (1 << 11); + } + if (powerdn) { + reg |= (1 << 0); + } + + /* Set clock source */ + reg |= (Input << 24); + + LPC_CGU->BASE_CLK[BaseClock] = reg; + } + } + else { + LPC_CGU->BASE_CLK[BaseClock] = reg | 1; /* Power down this base clock */ + } +} + +/* Reads CGU Base Clock clock source information */ +void Chip_Clock_GetBaseClockOpts(CHIP_CGU_BASE_CLK_T BaseClock, CHIP_CGU_CLKIN_T *Input, bool *autoblocken, + bool *powerdn) +{ + uint32_t reg = LPC_CGU->BASE_CLK[BaseClock]; + CHIP_CGU_CLKIN_T ClkIn = (CHIP_CGU_CLKIN_T) ((reg >> 24) & 0x1F ); + + if (BaseClock < CLK_BASE_NONE) { + /* Get settings */ + *Input = ClkIn; + *autoblocken = (reg & (1 << 11)) ? true : false; + *powerdn = (reg & (1 << 0)) ? true : false; + } + else { + *Input = CLKINPUT_PD; + *powerdn = true; + *autoblocken = true; + } +} + +/*Enables a base clock source */ +void Chip_Clock_EnableBaseClock(CHIP_CGU_BASE_CLK_T BaseClock) +{ + if (BaseClock < CLK_BASE_NONE) { + LPC_CGU->BASE_CLK[BaseClock] &= ~1; + } +} + +/* Disables a base clock source */ +void Chip_Clock_DisableBaseClock(CHIP_CGU_BASE_CLK_T BaseClock) +{ + if (BaseClock < CLK_BASE_NONE) { + LPC_CGU->BASE_CLK[BaseClock] |= 1; + } +} + +/* Returns base clock enable state */ +bool Chip_Clock_IsBaseClockEnabled(CHIP_CGU_BASE_CLK_T BaseClock) +{ + bool enabled; + + if (BaseClock < CLK_BASE_NONE) { + enabled = (bool) ((LPC_CGU->BASE_CLK[BaseClock] & 1) == 0); + } + else { + enabled = false; + } + + return enabled; +} + +/* Gets a CGU Base Clock clock source */ +CHIP_CGU_CLKIN_T Chip_Clock_GetBaseClock(CHIP_CGU_BASE_CLK_T BaseClock) +{ + uint32_t reg; + + if (BaseClock >= CLK_BASE_NONE) { + return CLKINPUT_PD; + } + + reg = LPC_CGU->BASE_CLK[BaseClock]; + + /* base clock is powered down? */ + if (reg & 1) { + return CLKINPUT_PD; + } + + return (CHIP_CGU_CLKIN_T) ((reg >> 24) & 0x1F); +} + +/* Enables a peripheral clock and sets clock states */ +void Chip_Clock_EnableOpts(CHIP_CCU_CLK_T clk, bool autoen, bool wakeupen, int div) +{ + uint32_t reg = 1; + + if (autoen) { + reg |= (1 << 1); + } + if (wakeupen) { + reg |= (1 << 2); + } + + /* Not all clocks support a divider, but we won't check that here. Only + dividers of 1 and 2 are allowed. Assume 1 if not 2 */ + if (div == 2) { + reg |= (1 << 5); + } + + /* Setup peripheral clock and start running */ + if (clk >= CLK_CCU2_START) { + LPC_CCU2->CLKCCU[clk - CLK_CCU2_START].CFG = reg; + } + else { + LPC_CCU1->CLKCCU[clk].CFG = reg; + } +} + +/* Enables a peripheral clock */ +void Chip_Clock_Enable(CHIP_CCU_CLK_T clk) +{ + /* Start peripheral clock running */ + if (clk >= CLK_CCU2_START) { + LPC_CCU2->CLKCCU[clk - CLK_CCU2_START].CFG |= 1; + } + else { + LPC_CCU1->CLKCCU[clk].CFG |= 1; + } +} + +/* Enable RTC Clock */ +void Chip_Clock_RTCEnable(void) +{ + LPC_CREG->CREG0 &= ~((1 << 3) | (1 << 2)); /* Reset 32Khz oscillator */ + LPC_CREG->CREG0 |= (1 << 1) | (1 << 0); /* Enable 32 kHz & 1 kHz on osc32k and release reset */ +} + +/* Disables a peripheral clock */ +void Chip_Clock_Disable(CHIP_CCU_CLK_T clk) +{ + /* Stop peripheral clock */ + if (clk >= CLK_CCU2_START) { + LPC_CCU2->CLKCCU[clk - CLK_CCU2_START].CFG &= ~1; + } + else { + LPC_CCU1->CLKCCU[clk].CFG &= ~1; + } +} + +/** + * Disable all branch output clocks with wake up mechanism enabled. + * Only the clocks with wake up mechanism enabled will be disabled & + * power down sequence started + */ +void Chip_Clock_StartPowerDown(void) +{ + /* Set Power Down bit */ + LPC_CCU1->PM = 1; + LPC_CCU2->PM = 1; +} + +/** + * Enable all branch output clocks after the wake up event. + * Only the clocks with wake up mechanism enabled will be enabled + */ +void Chip_Clock_ClearPowerDown(void) +{ + /* Clear Power Down bit */ + LPC_CCU1->PM = 0; + LPC_CCU2->PM = 0; +} + +/* Returns a peripheral clock rate */ +uint32_t Chip_Clock_GetRate(CHIP_CCU_CLK_T clk) +{ + CHIP_CGU_BASE_CLK_T baseclk; + uint32_t reg, div, rate; + + /* Get CCU config register for clock */ + if (clk >= CLK_CCU2_START) { + reg = LPC_CCU2->CLKCCU[clk - CLK_CCU2_START].CFG; + } + else { + reg = LPC_CCU1->CLKCCU[clk].CFG; + } + + /* Is the clock enabled? */ + if (reg & 1) { + /* Get base clock for this peripheral clock */ + baseclk = Chip_Clock_FindBaseClock(clk); + + /* Get base clock rate */ + rate = Chip_Clock_GetBaseClocktHz(baseclk); + + /* Get divider for this clock */ + if (((reg >> 5) & 0x7) == 0) { + div = 1; + } + else { + div = 2;/* No other dividers supported */ + + } + rate = rate / div; + } + else { + rate = 0; + } + + return rate; +} + +/* Get EMC Clock Rate */ +uint32_t Chip_Clock_GetEMCRate(void) + +{ + uint32_t ClkFreq; + uint32_t EMCDiv; + ClkFreq = Chip_Clock_GetRate(CLK_MX_EMC); + + /* EMC Divider readback at pos 27 + TODO: just checked but dont mention in UM */ + EMCDiv = (LPC_CCU1->CLKCCU[CLK_MX_EMC_DIV].CFG >> 27) & 0x07; + + /* Check EMC Divider to get real EMC clock out */ + if ((EMCDiv == 1) && (LPC_CREG->CREG6 & (1 << 16))) { + ClkFreq >>= 1; + } + return ClkFreq; +} + +/* Sets up the audio or USB PLL */ +void Chip_Clock_SetupPLL(CHIP_CGU_CLKIN_T Input, CHIP_CGU_USB_AUDIO_PLL_T pllnum, + const CGU_USBAUDIO_PLL_SETUP_T *pPLLSetup) +{ + uint32_t reg = pPLLSetup->ctrl | (Input << 24); + + /* Setup from passed values */ + LPC_CGU->PLL[pllnum].PLL_CTRL = reg; + LPC_CGU->PLL[pllnum].PLL_MDIV = pPLLSetup->mdiv; + LPC_CGU->PLL[pllnum].PLL_NP_DIV = pPLLSetup->ndiv; + + /* Fractional divider is for audio PLL only */ + if (pllnum == CGU_AUDIO_PLL) { + LPC_CGU->PLL0AUDIO_FRAC = pPLLSetup->fract; + } + audio_usb_pll_freq[pllnum] = pPLLSetup->freq; +} + +/* Enables the audio or USB PLL */ +void Chip_Clock_EnablePLL(CHIP_CGU_USB_AUDIO_PLL_T pllnum) +{ + LPC_CGU->PLL[pllnum].PLL_CTRL &= ~1; +} + +/* Disables the audio or USB PLL */ +void Chip_Clock_DisablePLL(CHIP_CGU_USB_AUDIO_PLL_T pllnum) +{ + LPC_CGU->PLL[pllnum].PLL_CTRL |= 1; +} + +/* Returns the PLL status */ +uint32_t Chip_Clock_GetPLLStatus(CHIP_CGU_USB_AUDIO_PLL_T pllnum) +{ + return LPC_CGU->PLL[pllnum].PLL_STAT; +} diff --git a/lpcapi/clock_18xx_43xx.h b/lpcapi/clock_18xx_43xx.h new file mode 100644 index 00000000..2e8c8b04 --- /dev/null +++ b/lpcapi/clock_18xx_43xx.h @@ -0,0 +1,341 @@ +/* + * @brief LPC18xx/43xx clock driver + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licenser disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __CLOCK_18XX_43XX_H_ +#define __CLOCK_18XX_43XX_H_ + +#include "cguccu_18xx_43xx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup CLOCK_18XX_43XX CHIP: LPC18xx/43xx Clock Driver + * @ingroup CHIP_18XX_43XX_Drivers + * @{ + */ + +/** @defgroup CLOCK_18XX_43XX_OPTIONS CHIP: LPC18xx/43xx Clock Driver driver options + * @ingroup CLOCK_18XX_43XX CHIP_18XX_43XX_DRIVER_OPTIONS + * The clock driver has options that configure it's operation at build-time.
+ * + * MAX_CLOCK_FREQ
+ * This macro defines the maximum frequency supported by the Chip [204MHz for LPC43xx + * 180MHz for LPC18xx]. API Chip_SetupXtalClocking() and Chip_SetupIrcClocking() will + * use this macro to set the CPU Core frequency to the maximum supported.
+ * To set a Core frequency other than the maximum frequency Chip_SetupCoreClock() API + * must be used. Using this macro to set the Core freqency is not recommended. + * @{ + */ + +/** + * @} + */ + +/* Internal oscillator frequency */ +#define CGU_IRC_FREQ (12000000) + +#ifndef MAX_CLOCK_FREQ +#if defined(CHIP_LPC43XX) +#define MAX_CLOCK_FREQ (204000000) +#else +#define MAX_CLOCK_FREQ (180000000) +#endif +#endif + +/** + * @brief Enables the crystal oscillator + * @return Nothing + */ +void Chip_Clock_EnableCrystal(void); + +/** + * @brief Disables the crystal oscillator + * @return Nothing + */ +void Chip_Clock_DisableCrystal(void); + +/** + * @brief Configures the main PLL + * @param Input : Which clock input to use as the PLL input + * @param MinHz : Minimum allowable PLL output frequency + * @param DesiredHz : Desired PLL output frequency + * @param MaxHz : Maximum allowable PLL output frequency + * @return Frequency of the PLL in Hz + * Returns the configured PLL frequency or zero if the PLL can not be configured between MinHz + * and MaxHz. This will not wait for PLL lock. Call Chip_Clock_MainPLLLocked() to determine if + * the PLL is locked. + */ +uint32_t Chip_Clock_SetupMainPLLHz(CHIP_CGU_CLKIN_T Input, uint32_t MinHz, uint32_t DesiredHz, uint32_t MaxHz); + +/** + * @brief Directly set the PLL multipler + * @param Input : Which clock input to use as the PLL input + * @param mult : How many times to multiply the input clock + * @return Frequency of the PLL in Hz + */ +uint32_t Chip_Clock_SetupMainPLLMult(CHIP_CGU_CLKIN_T Input, uint32_t mult); + +/** + * @brief Returns the frequency of the main PLL + * @return Frequency of the PLL in Hz + * Returns zero if the main PLL is not running. + */ +uint32_t Chip_Clock_GetMainPLLHz(void); + +/** + * @brief Disables the main PLL + * @return none + * Make sure the main PLL is not needed to clock the part before disabling it. + * Saves power if the main PLL is not needed. + */ +void Chip_Clock_DisableMainPLL(void); + +/** + * @brief Enbles the main PLL + * @return none + * Make sure the main PLL is enabled. + */ +void Chip_Clock_EnableMainPLL(void); + +/** + * @brief Returns the lock status of the main PLL + * @return true if the PLL is locked, otherwise false + * The main PLL should be locked prior to using it as a clock input for a base clock. + */ +bool Chip_Clock_MainPLLLocked(void); + +/** + * @brief Sets up a CGU clock divider and it's input clock + * @param Divider : CHIP_CGU_IDIV_T value indicating which divider to configure + * @param Input : CHIP_CGU_CLKIN_T value indicating which clock source to use or CLOCKINPUT_PD to power down divider + * @param Divisor : value to divide Input clock by + * @return Nothing + * Maximum divider on A = 4, B/C/D = 16, E = 256. + * See the user manual for allowable combinations for input clock. + */ +void Chip_Clock_SetDivider(CHIP_CGU_IDIV_T Divider, CHIP_CGU_CLKIN_T Input, uint32_t Divisor); + +/** + * @brief Gets a CGU clock divider source + * @param Divider : CHIP_CGU_IDIV_T value indicating which divider to get the source of + * @return CHIP_CGU_CLKIN_T indicating which clock source is set or CLOCKINPUT_PD + */ +CHIP_CGU_CLKIN_T Chip_Clock_GetDividerSource(CHIP_CGU_IDIV_T Divider); + +/** + * @brief Gets a CGU clock divider divisor + * @param Divider : CHIP_CGU_IDIV_T value indicating which divider to get the source of + * @return the divider value for the divider + */ +uint32_t Chip_Clock_GetDividerDivisor(CHIP_CGU_IDIV_T Divider); + +/** + * @brief Returns the frequency of the specified input clock source + * @param input : Which clock input to return the frequency of + * @return Frequency of input source in Hz + * This function returns an ideal frequency and not the actual frequency. Returns + * zero if the clock source is disabled. + */ +uint32_t Chip_Clock_GetClockInputHz(CHIP_CGU_CLKIN_T input); + +/** + * @brief Returns the frequency of the specified base clock source + * @param clock : which base clock to return the frequency of. + * @return Frequency of base source in Hz + * This function returns an ideal frequency and not the actual frequency. Returns + * zero if the clock source is disabled. + */ +uint32_t Chip_Clock_GetBaseClocktHz(CHIP_CGU_BASE_CLK_T clock); + +/** + * @brief Sets a CGU Base Clock clock source + * @param BaseClock : CHIP_CGU_BASE_CLK_T value indicating which base clock to set + * @param Input : CHIP_CGU_CLKIN_T value indicating which clock source to use or CLOCKINPUT_PD to power down base clock + * @param autoblocken : Enables autoblocking during frequency change if true + * @param powerdn : The clock base is setup, but powered down if true + * @return Nothing + */ +void Chip_Clock_SetBaseClock(CHIP_CGU_BASE_CLK_T BaseClock, CHIP_CGU_CLKIN_T Input, bool autoblocken, bool powerdn); + +/** + * @brief Get CGU Base Clock clock source information + * @param BaseClock : CHIP_CGU_BASE_CLK_T value indicating which base clock to get + * @param Input : Pointer to CHIP_CGU_CLKIN_T value of the base clock + * @param autoblocken : Pointer to autoblocking value of the base clock + * @param powerdn : Pointer to power down flag + * @return Nothing + */ +void Chip_Clock_GetBaseClockOpts(CHIP_CGU_BASE_CLK_T BaseClock, CHIP_CGU_CLKIN_T *Input, bool *autoblocken, + bool *powerdn); + +/** + * @brief Gets a CGU Base Clock clock source + * @param BaseClock : CHIP_CGU_BASE_CLK_T value indicating which base clock to get inpuot clock for + * @return CHIP_CGU_CLKIN_T indicating which clock source is set or CLOCKINPUT_PD + */ +CHIP_CGU_CLKIN_T Chip_Clock_GetBaseClock(CHIP_CGU_BASE_CLK_T BaseClock); + +/** + * @brief Enables a base clock source + * @param BaseClock : CHIP_CGU_BASE_CLK_T value indicating which base clock to enable + * @return Nothing + */ +void Chip_Clock_EnableBaseClock(CHIP_CGU_BASE_CLK_T BaseClock); + +/** + * @brief Disables a base clock source + * @param BaseClock : CHIP_CGU_BASE_CLK_T value indicating which base clock to disable + * @return Nothing + */ +void Chip_Clock_DisableBaseClock(CHIP_CGU_BASE_CLK_T BaseClock); + +/** + * @brief Returns base clock enable state + * @param BaseClock : CHIP_CGU_BASE_CLK_T value indicating which base clock to check + * @return true if the base clock is enabled, false if disabled + */ +bool Chip_Clock_IsBaseClockEnabled(CHIP_CGU_BASE_CLK_T BaseClock); + +/** + * @brief Enables a peripheral clock and sets clock states + * @param clk : CHIP_CCU_CLK_T value indicating which clock to enable + * @param autoen : true to enable autoblocking on a clock rate change, false to disable + * @param wakeupen : true to enable wakeup mechanism, false to disable + * @param div : Divider for the clock, must be 1 for most clocks, 2 supported on others + * @return Nothing + */ +void Chip_Clock_EnableOpts(CHIP_CCU_CLK_T clk, bool autoen, bool wakeupen, int div); + +/** + * @brief Enables a peripheral clock + * @param clk : CHIP_CCU_CLK_T value indicating which clock to enable + * @return Nothing + */ +void Chip_Clock_Enable(CHIP_CCU_CLK_T clk); + +/** + * @brief Enables RTCclock + * @return Nothing + */ +void Chip_Clock_RTCEnable(void); + +/** + * @brief Disables a peripheral clock + * @param clk : CHIP_CCU_CLK_T value indicating which clock to disable + * @return Nothing + */ +void Chip_Clock_Disable(CHIP_CCU_CLK_T clk); + +/** + * @brief Returns a peripheral clock rate + * @param clk : CHIP_CCU_CLK_T value indicating which clock to get rate for + * @return 0 if the clock is disabled, or the rate of the clock + */ +uint32_t Chip_Clock_GetRate(CHIP_CCU_CLK_T clk); + +/** + * @brief Returns EMC clock rate + * @return 0 if the clock is disabled, or the rate of the clock + */ +uint32_t Chip_Clock_GetEMCRate(void); + +/** + * @brief Start the power down sequence by disabling the branch output + * clocks with wake up mechanism (Only the clocks which + * wake up mechanism bit enabled will be disabled) + * @return Nothing + */ +void Chip_Clock_StartPowerDown(void); + +/** + * @brief Clear the power down mode bit & proceed normal operation of branch output + * clocks (Only the clocks which wake up mechanism bit enabled will be + * enabled after the wake up event) + * @return Nothing + */ +void Chip_Clock_ClearPowerDown(void); + +/** + * Structure for setting up the USB or audio PLL + */ +typedef struct { + uint32_t ctrl; /* Default control word for PLL */ + uint32_t mdiv; /* Default M-divider value for PLL */ + uint32_t ndiv; /* Default NP-divider value for PLL */ + uint32_t fract; /* Default fractional value for audio PLL only */ + uint32_t freq; /* Output frequency of the pll */ +} CGU_USBAUDIO_PLL_SETUP_T; + +/** + * @brief Sets up the audio or USB PLL + * @param Input : Input clock + * @param pllnum : PLL identifier + * @param pPLLSetup : Pointer to PLL setup structure + * @return Nothing + * Sets up the PLL with the passed structure values. + */ +void Chip_Clock_SetupPLL(CHIP_CGU_CLKIN_T Input, CHIP_CGU_USB_AUDIO_PLL_T pllnum, + const CGU_USBAUDIO_PLL_SETUP_T *pPLLSetup); + +/** + * @brief Enables the audio or USB PLL + * @param pllnum : PLL identifier + * @return Nothing + */ +void Chip_Clock_EnablePLL(CHIP_CGU_USB_AUDIO_PLL_T pllnum); + +/** + * @brief Disables the audio or USB PLL + * @param pllnum : PLL identifier + * @return Nothing + */ +void Chip_Clock_DisablePLL(CHIP_CGU_USB_AUDIO_PLL_T pllnum); + +#define CGU_PLL_LOCKED (1 << 0) /* PLL locked status */ +#define CGU_PLL_FR (1 << 1) /* PLL free running indicator status */ + +/** + * @brief Returns the PLL status + * @param pllnum : PLL identifier + * @return An OR'ed value of CGU_PLL_LOCKED or CGU_PLL_FR + */ +uint32_t Chip_Clock_GetPLLStatus(CHIP_CGU_USB_AUDIO_PLL_T pllnum); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CLOCK_18XX_43XX_H_ */ diff --git a/lpcapi/cmsis.h b/lpcapi/cmsis.h new file mode 100644 index 00000000..cc30e966 --- /dev/null +++ b/lpcapi/cmsis.h @@ -0,0 +1,63 @@ +/* + * @brief LPC11xx selective CMSIS inclusion file + * + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __CMSIS_H_ +#define __CMSIS_H_ + +#include "lpc_types.h" +#include "sys_config.h" + +/* Select correct CMSIS include file based on CHIP_* definition */ +#if defined(CHIP_LPC43XX) + +#ifdef CORE_M4 +#include "cmsis_43xx.h" + +#elif defined(CORE_M0) +#if defined(LPC43XX_CORE_M0APP) +#include "cmsis_43xx_m0app.h" + +#elif (defined(LPC43XX_CORE_M0SUB)) +#include "cmsis_43xx_m0sub.h" + +#else +#error "LPC43XX_CORE_M0APP or LPC43XX_CORE_M0SUB must be defined" +#endif + +#else +#error "CORE_M0 or CORE_M4 must be defined for CHIP_LPC43XX" +#endif + +#elif defined(CHIP_LPC18XX) +#include "cmsis_18xx.h" + +#else +#error "No CHIP_* definition is defined" +#endif + +#endif /* __CMSIS_H_ */ diff --git a/lpcapi/cmsis_43xx.h b/lpcapi/cmsis_43xx.h new file mode 100644 index 00000000..dc6b81c9 --- /dev/null +++ b/lpcapi/cmsis_43xx.h @@ -0,0 +1,167 @@ +/* + * @brief Basic CMSIS include file for LPC43XX + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __CMSIS_43XX_M0_H_ +#define __CMSIS_43XX_M0_H_ + +#ifndef __CMSIS_H_ +#error "cmsis_43xx.h should not be included directly use cmsis.h instead" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup CMSIS_43XX CHIP: LPC43xx CMSIS include file + * @ingroup CHIP_18XX_43XX_Drivers + * @{ + */ + +#if defined(__ARMCC_VERSION) + #pragma diag_suppress 2525 + #pragma push + #pragma anon_unions +#elif defined(__CWCC__) + #pragma push + #pragma cpp_extensions on +#elif defined(__GNUC__) +/* anonymous unions are enabled by default */ +#elif defined(__IAR_SYSTEMS_ICC__) + #pragma language=extended +#else + #error Not supported compiler type +#endif + +/** @defgroup CMSIS_43XX_COMMON CHIP: LPC43xx Cortex CMSIS definitions + * @{ + */ + +#define __CM4_REV 0x0001 /*!< Cortex-M4 Core Revision */ +#define __MPU_PRESENT 1 /*!< MPU present or not */ +#define __NVIC_PRIO_BITS 3 /*!< Number of Bits used for Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ +#define __FPU_PRESENT 1 /*!< FPU present or not */ + +/** + * @} + */ + +/** @defgroup CMSIS_43XX_IRQ CHIP: LPC43xx peripheral interrupt numbers + * @{ + */ + +typedef enum { + /* ------------------------- Cortex-M4 Processor Exceptions Numbers ----------------------------- */ + Reset_IRQn = -15,/*!< 1 Reset Vector, invoked on Power up and warm reset */ + NonMaskableInt_IRQn = -14,/*!< 2 Non maskable Interrupt, cannot be stopped or preempted */ + HardFault_IRQn = -13,/*!< 3 Hard Fault, all classes of Fault */ + MemoryManagement_IRQn = -12,/*!< 4 Memory Management, MPU mismatch, including Access Violation and No Match */ + BusFault_IRQn = -11,/*!< 5 Bus Fault, Pre-Fetch-, Memory Access Fault, other address/memory related Fault */ + UsageFault_IRQn = -10,/*!< 6 Usage Fault, i.e. Undef Instruction, Illegal State Transition */ + SVCall_IRQn = -5,/*!< 11 System Service Call via SVC instruction */ + DebugMonitor_IRQn = -4,/*!< 12 Debug Monitor */ + PendSV_IRQn = -2,/*!< 14 Pendable request for system service */ + SysTick_IRQn = -1,/*!< 15 System Tick Timer */ + + /* --------------------------- LPC18xx/43xx Specific Interrupt Numbers ------------------------------- */ + DAC_IRQn = 0,/*!< 0 DAC */ + M0APP_IRQn = 1,/*!< 1 M0APP Core interrupt */ + DMA_IRQn = 2,/*!< 2 DMA */ + RESERVED1_IRQn = 3,/*!< 3 EZH/EDM */ + RESERVED2_IRQn = 4, + ETHERNET_IRQn = 5,/*!< 5 ETHERNET */ + SDIO_IRQn = 6,/*!< 6 SDIO */ + LCD_IRQn = 7,/*!< 7 LCD */ + USB0_IRQn = 8,/*!< 8 USB0 */ + USB1_IRQn = 9,/*!< 9 USB1 */ + SCT_IRQn = 10,/*!< 10 SCT */ + RITIMER_IRQn = 11,/*!< 11 RITIMER */ + TIMER0_IRQn = 12,/*!< 12 TIMER0 */ + TIMER1_IRQn = 13,/*!< 13 TIMER1 */ + TIMER2_IRQn = 14,/*!< 14 TIMER2 */ + TIMER3_IRQn = 15,/*!< 15 TIMER3 */ + MCPWM_IRQn = 16,/*!< 16 MCPWM */ + ADC0_IRQn = 17,/*!< 17 ADC0 */ + I2C0_IRQn = 18,/*!< 18 I2C0 */ + I2C1_IRQn = 19,/*!< 19 I2C1 */ + SPI_INT_IRQn = 20,/*!< 20 SPI_INT */ + ADC1_IRQn = 21,/*!< 21 ADC1 */ + SSP0_IRQn = 22,/*!< 22 SSP0 */ + SSP1_IRQn = 23,/*!< 23 SSP1 */ + USART0_IRQn = 24,/*!< 24 USART0 */ + UART1_IRQn = 25,/*!< 25 UART1 */ + USART2_IRQn = 26,/*!< 26 USART2 */ + USART3_IRQn = 27,/*!< 27 USART3 */ + I2S0_IRQn = 28,/*!< 28 I2S0 */ + I2S1_IRQn = 29,/*!< 29 I2S1 */ + RESERVED4_IRQn = 30, + SGPIO_INT_IRQn = 31,/*!< 31 SGPIO_IINT */ + PIN_INT0_IRQn = 32,/*!< 32 PIN_INT0 */ + PIN_INT1_IRQn = 33,/*!< 33 PIN_INT1 */ + PIN_INT2_IRQn = 34,/*!< 34 PIN_INT2 */ + PIN_INT3_IRQn = 35,/*!< 35 PIN_INT3 */ + PIN_INT4_IRQn = 36,/*!< 36 PIN_INT4 */ + PIN_INT5_IRQn = 37,/*!< 37 PIN_INT5 */ + PIN_INT6_IRQn = 38,/*!< 38 PIN_INT6 */ + PIN_INT7_IRQn = 39,/*!< 39 PIN_INT7 */ + GINT0_IRQn = 40,/*!< 40 GINT0 */ + GINT1_IRQn = 41,/*!< 41 GINT1 */ + EVENTROUTER_IRQn = 42,/*!< 42 EVENTROUTER */ + C_CAN1_IRQn = 43,/*!< 43 C_CAN1 */ + RESERVED6_IRQn = 44, + ADCHS_IRQn = 45,/*!< 45 ADCHS interrupt */ + ATIMER_IRQn = 46,/*!< 46 ATIMER */ + RTC_IRQn = 47,/*!< 47 RTC */ + RESERVED8_IRQn = 48, + WWDT_IRQn = 49,/*!< 49 WWDT */ + M0SUB_IRQn = 50,/*!< 50 M0SUB core interrupt */ + C_CAN0_IRQn = 51,/*!< 51 C_CAN0 */ + QEI_IRQn = 52,/*!< 52 QEI */ +} LPC43XX_IRQn_Type; + +/** + * @} + */ + +typedef LPC43XX_IRQn_Type IRQn_Type; + +/* Cortex-M4 processor and core peripherals */ +#include "core_cm4.h" + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ifndef __CMSIS_43XX_M0_H_ */ diff --git a/lpcapi/core_cm4.h b/lpcapi/core_cm4.h new file mode 100644 index 00000000..6309bf79 --- /dev/null +++ b/lpcapi/core_cm4.h @@ -0,0 +1,1796 @@ +/**************************************************************************//** + * @file core_cm4.h + * @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File + * @version V3.20 + * @date 25. February 2013 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2013 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + +// rad1o codebase integration: +#include + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef __CORE_CM4_H_GENERIC +#define __CORE_CM4_H_GENERIC + +/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** \ingroup Cortex_M4 + @{ + */ + +/* CMSIS CM4 definitions */ +#define __CM4_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */ +#define __CM4_CMSIS_VERSION_SUB (0x20) /*!< [15:0] CMSIS HAL sub version */ +#define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16) | \ + __CM4_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x04) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#endif + +/** __FPU_USED indicates whether an FPU is used or not. For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1 + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0 + #endif + #else + #define __FPU_USED 0 + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1 + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0 + #endif + #else + #define __FPU_USED 0 + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1 + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0 + #endif + #else + #define __FPU_USED 0 + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1 + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0 + #endif + #else + #define __FPU_USED 0 + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1 + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0 + #endif + #else + #define __FPU_USED 0 + #endif +#endif + +#include /* standard types definitions */ +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ +#include "core_cm4_simd.h" /* Compiler specific SIMD Intrinsics */ + +#endif /* __CORE_CM4_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM4_H_DEPENDANT +#define __CORE_CM4_H_DEPENDANT + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM4_REV + #define __CM4_REV 0x0000 + #warning "__CM4_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0 + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0 + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 4 + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0 + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifndef __I +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ +#endif +/*@} end of group Cortex_M4 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core FPU Register + ******************************************************************************/ +/** \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ +#else + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ +#endif + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + + +/** \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + + +/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ +#else + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ +#endif + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + + +/** \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/*@} end of group CMSIS_CORE */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IO uint32_t ISER[8]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24]; + __IO uint32_t ICER[8]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24]; + __IO uint32_t ISPR[8]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24]; + __IO uint32_t ICPR[8]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24]; + __IO uint32_t IABR[8]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56]; + __IO uint8_t IP[240]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644]; + __O uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0 /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL << NVIC_STIR_INTID_Pos) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IO uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IO uint8_t SHP[12]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IO uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IO uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IO uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IO uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IO uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IO uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __I uint32_t PFR[2]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __I uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __I uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __I uint32_t MMFR[4]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __I uint32_t ISAR[5]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5]; + __IO uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11 /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8 /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0 /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL << SCB_AIRCR_VECTRESET_Pos) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */ +#undef SCB_SCR_SLEEPDEEP_Msk +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8 /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4 /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1 /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0 /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL << SCB_CCR_NONBASETHRDENA_Pos) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18 /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17 /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16 /*!< SCB SHCSR: MEMFAULTENA Position */ +#undef SCB_SHCSR_MEMFAULTENA_Msk +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14 /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13 /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12 /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11 /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10 /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8 /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7 /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3 /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1 /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0 /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL << SCB_SHCSR_MEMFAULTACT_Pos) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Registers Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16 /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8 /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0 /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL << SCB_CFSR_MEMFAULTSR_Pos) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Registers Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31 /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30 /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1 /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4 /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3 /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2 /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1 /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0 /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL << SCB_DFSR_HALTED_Pos) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1]; + __I uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IO uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0 /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL << SCnSCB_ICTR_INTLINESNUM_Pos) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISOOFP_Pos 9 /*!< ACTLR: DISOOFP Position */ +#define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */ + +#define SCnSCB_ACTLR_DISFPCA_Pos 8 /*!< ACTLR: DISFPCA Position */ +#define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2 /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1 /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0 /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL << SCnSCB_ACTLR_DISMCYCINT_Pos) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __O union + { + __O uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __O uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __O uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864]; + __IO uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15]; + __IO uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15]; + __IO uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29]; + __O uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __I uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IO uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43]; + __O uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __I uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6]; + __I uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __I uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __I uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __I uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __I uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __I uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __I uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __I uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __I uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __I uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __I uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __I uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0 /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL << ITM_TPR_PRIVMASK_Pos) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23 /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16 /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10 /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8 /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4 /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3 /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2 /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1 /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0 /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL << ITM_TCR_ITMENA_Pos) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0 /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL << ITM_IWR_ATVALIDM_Pos) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0 /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL << ITM_IRR_ATREADYM_Pos) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0 /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL << ITM_IMCR_INTEGRATION_Pos) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2 /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1 /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0 /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL << ITM_LSR_Present_Pos) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IO uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IO uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IO uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IO uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IO uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IO uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __I uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IO uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IO uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IO uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1]; + __IO uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IO uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IO uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1]; + __IO uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IO uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IO uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1]; + __IO uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IO uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IO uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28 /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27 /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26 /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25 /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24 /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22 /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21 /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20 /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19 /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18 /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17 /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16 /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12 /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10 /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9 /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5 /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1 /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0 /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL << DWT_CTRL_CYCCNTENA_Pos) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0 /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL << DWT_CPICNT_CPICNT_Pos) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0 /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL << DWT_EXCCNT_EXCCNT_Pos) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0 /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL << DWT_SLEEPCNT_SLEEPCNT_Pos) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0 /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL << DWT_LSUCNT_LSUCNT_Pos) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0 /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL << DWT_FOLDCNT_FOLDCNT_Pos) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0 /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL << DWT_MASK_MASK_Pos) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24 /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16 /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12 /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10 /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9 /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8 /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7 /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5 /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0 /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL << DWT_FUNCTION_FUNCTION_Pos) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IO uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IO uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2]; + __IO uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55]; + __IO uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131]; + __I uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IO uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __I uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759]; + __I uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __I uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __I uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1]; + __I uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __I uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IO uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39]; + __IO uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IO uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8]; + __I uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __I uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0 /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL << TPI_ACPR_PRESCALER_Pos) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0 /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL << TPI_SPPR_TXMODE_Pos) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3 /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2 /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1 /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0 /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL << TPI_FFSR_FlInProg_Pos) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8 /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1 /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0 /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL << TPI_TRIGGER_TRIGGER_Pos) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29 /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27 /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26 /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24 /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16 /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8 /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0 /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL << TPI_FIFO0_ETM0_Pos) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0 /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL << TPI_ITATBCTR2_ATREADY_Pos) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29 /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27 /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26 /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24 /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16 /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8 /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0 /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL << TPI_FIFO1_ITM0_Pos) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0 /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL << TPI_ITATBCTR0_ATREADY_Pos) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0 /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL << TPI_ITCTRL_Mode_Pos) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11 /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10 /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9 /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6 /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5 /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0 /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL << TPI_DEVID_NrTraceInput_Pos) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 0 /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL << TPI_DEVTYPE_SubType_Pos) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 4 /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1) +/** \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __I uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IO uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IO uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IO uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IO uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IO uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IO uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IO uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IO uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IO uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IO uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register */ +#define MPU_TYPE_IREGION_Pos 16 /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8 /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0 /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL << MPU_TYPE_SEPARATE_Pos) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register */ +#define MPU_CTRL_PRIVDEFENA_Pos 2 /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1 /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0 /*!< MPU CTRL: ENABLE Position */ +#undef MPU_CTRL_ENABLE_Msk +#define MPU_CTRL_ENABLE_Msk (1UL << MPU_CTRL_ENABLE_Pos) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register */ +#define MPU_RNR_REGION_Pos 0 /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL << MPU_RNR_REGION_Pos) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register */ +#define MPU_RBAR_ADDR_Pos 5 /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4 /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0 /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL << MPU_RBAR_REGION_Pos) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register */ +#define MPU_RASR_ATTRS_Pos 16 /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#undef MPU_RASR_XN_Pos +#define MPU_RASR_XN_Pos 28 /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#undef MPU_RASR_AP_Pos +#define MPU_RASR_AP_Pos 24 /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#undef MPU_RASR_TEX_Pos +#define MPU_RASR_TEX_Pos 19 /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#undef MPU_RASR_S_Pos +#define MPU_RASR_S_Pos 18 /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#undef MPU_RASR_C_Pos +#define MPU_RASR_C_Pos 17 /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#undef MPU_RASR_B_Pos +#define MPU_RASR_B_Pos 16 /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#undef MPU_RASR_SRD_Pos +#define MPU_RASR_SRD_Pos 8 /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#undef MPU_RASR_SIZE_Pos +#define MPU_RASR_SIZE_Pos 1 /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0 /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL << MPU_RASR_ENABLE_Pos) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if (__FPU_PRESENT == 1) +/** \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1]; + __IO uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IO uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IO uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __I uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __I uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ +} FPU_Type; + +/* Floating-Point Context Control Register */ +#define FPU_FPCCR_ASPEN_Pos 31 /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30 /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8 /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6 /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5 /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4 /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3 /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_USER_Pos 1 /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0 /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL << FPU_FPCCR_LSPACT_Pos) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register */ +#define FPU_FPCAR_ADDRESS_Pos 3 /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register */ +#define FPU_FPDSCR_AHP_Pos 26 /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25 /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24 /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22 /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28 /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24 /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20 /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16 /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12 /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8 /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4 /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0 /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL << FPU_MVFR0_A_SIMD_registers_Pos) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28 /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24 /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4 /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0 /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL << FPU_MVFR1_FtZ_mode_Pos) /*!< MVFR1: FtZ mode bits Mask */ + +/*@} end of group CMSIS_FPU */ +#endif + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IO uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __O uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IO uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IO uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16 /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25 /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24 /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19 /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18 /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17 /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16 /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5 /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3 /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2 /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1 /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0 /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#undef CoreDebug_DHCSR_C_DEBUGEN_Msk +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL << CoreDebug_DHCSR_C_DEBUGEN_Pos) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register */ +#define CoreDebug_DCRSR_REGWnR_Pos 16 /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0 /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL << CoreDebug_DCRSR_REGSEL_Pos) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register */ +#define CoreDebug_DEMCR_TRCENA_Pos 24 /*!< CoreDebug DEMCR: TRCENA Position */ +#undef CoreDebug_DEMCR_TRCENA_Msk +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19 /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18 /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17 /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16 /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10 /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9 /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8 /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7 /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6 /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5 /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4 /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0 /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL << CoreDebug_DEMCR_VC_CORERESET_Pos) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M4 Hardware */ +//rad1o:off #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +//rad1o:off #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +//rad1o:off #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +//rad1o:off #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +//rad1o:off #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#undef SCB +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#undef SysTick +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#undef ITM +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#undef CoreDebug +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ +#undef MPU + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +#if (__FPU_PRESENT == 1) + #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ + #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** \brief Set Priority Grouping + + The function sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FA << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8)); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** \brief Get Priority Grouping + + The function reads the priority grouping field from the NVIC Interrupt Controller. + + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos); /* read priority grouping field */ +} + + +#if 0 +/** \brief Enable External Interrupt + + The function enables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ +/* NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); enable interrupt */ + NVIC->ISER[(uint32_t)((int32_t)IRQn) >> 5] = (uint32_t)(1 << ((uint32_t)((int32_t)IRQn) & (uint32_t)0x1F)); /* enable interrupt */ +} + + +/** \brief Disable External Interrupt + + The function disables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* disable interrupt */ +} +#endif + +/** \brief Get Pending Interrupt + + The function reads the pending register in the NVIC and returns the pending bit + for the specified interrupt. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t) ((NVIC->ISPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if pending else 0 */ +} + + +/** \brief Set Pending Interrupt + + The function sets the pending bit of an external interrupt. + + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* set interrupt pending */ +} + +#if 0 +/** \brief Clear Pending Interrupt + + The function clears the pending bit of an external interrupt. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */ +} +#endif + +/** \brief Get Active Interrupt + + The function reads the active register in NVIC and returns the active bit. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)((NVIC->IABR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if active else 0 */ +} + + +/** \brief Set Interrupt Priority + + The function sets the priority of an interrupt. + + \note The priority cannot be set for every core interrupt. + + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if(IRQn < 0) { + SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M System Interrupts */ + else { + NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for device specific Interrupts */ +} + + +/** \brief Get Interrupt Priority + + The function reads the priority of an interrupt. The interrupt + number can be positive to specify an external (device specific) + interrupt, or negative to specify an internal (core) interrupt. + + + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented + priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if(IRQn < 0) { + return((uint32_t)(SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M system interrupts */ + else { + return((uint32_t)(NVIC->IP[(uint32_t)(IRQn)] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */ +} + + +/** \brief Encode Priority + + The function encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the samllest possible priority group is set. + + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + return ( + ((PreemptPriority & ((1 << (PreemptPriorityBits)) - 1)) << SubPriorityBits) | + ((SubPriority & ((1 << (SubPriorityBits )) - 1))) + ); +} + + +/** \brief Decode Priority + + The function decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set. + + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* pPreemptPriority, uint32_t* pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + *pPreemptPriority = (Priority >> SubPriorityBits) & ((1 << (PreemptPriorityBits)) - 1); + *pSubPriority = (Priority ) & ((1 << (SubPriorityBits )) - 1); +} + + +/** \brief System Reset + + The function initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + while(1); /* wait until reset */ +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if 0 +#if (__Vendor_SysTickConfig == 0) + +/** \brief System Tick Configuration + + The function initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + + \param [in] ticks Number of ticks between two interrupts. + + \return 0 Function succeeded. + \return 1 Function failed. + + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ + + SysTick->LOAD = ticks - 1; /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0); /* Function successful */ +} + +#endif +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5 /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** \brief ITM Send Character + + The function transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + + \param [in] ch Character to transmit. + + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if ((ITM->TCR & ITM_TCR_ITMENA_Msk) && /* ITM enabled */ + (ITM->TER & (1UL << 0) ) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0].u32 == 0); + ITM->PORT[0].u8 = (uint8_t) ch; + } + return (ch); +} + + +/** \brief ITM Receive Character + + The function inputs a character via the external variable \ref ITM_RxBuffer. + + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) { + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** \brief ITM Check Character + + The function checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) { + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { + return (0); /* no character available */ + } else { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + +#endif /* __CORE_CM4_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ + +#ifdef __cplusplus +} +#endif diff --git a/lpcapi/core_cm4_simd.h b/lpcapi/core_cm4_simd.h new file mode 100644 index 00000000..af1831ee --- /dev/null +++ b/lpcapi/core_cm4_simd.h @@ -0,0 +1,673 @@ +/**************************************************************************//** + * @file core_cm4_simd.h + * @brief CMSIS Cortex-M4 SIMD Header File + * @version V3.20 + * @date 25. February 2013 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2013 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef __CORE_CM4_SIMD_H +#define __CORE_CM4_SIMD_H + + +/******************************************************************************* + * Hardware Abstraction Layer + ******************************************************************************/ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/ +#define __SADD8 __sadd8 +#define __QADD8 __qadd8 +#define __SHADD8 __shadd8 +#define __UADD8 __uadd8 +#define __UQADD8 __uqadd8 +#define __UHADD8 __uhadd8 +#define __SSUB8 __ssub8 +#define __QSUB8 __qsub8 +#define __SHSUB8 __shsub8 +#define __USUB8 __usub8 +#define __UQSUB8 __uqsub8 +#define __UHSUB8 __uhsub8 +#define __SADD16 __sadd16 +#define __QADD16 __qadd16 +#define __SHADD16 __shadd16 +#define __UADD16 __uadd16 +#define __UQADD16 __uqadd16 +#define __UHADD16 __uhadd16 +#define __SSUB16 __ssub16 +#define __QSUB16 __qsub16 +#define __SHSUB16 __shsub16 +#define __USUB16 __usub16 +#define __UQSUB16 __uqsub16 +#define __UHSUB16 __uhsub16 +#define __SASX __sasx +#define __QASX __qasx +#define __SHASX __shasx +#define __UASX __uasx +#define __UQASX __uqasx +#define __UHASX __uhasx +#define __SSAX __ssax +#define __QSAX __qsax +#define __SHSAX __shsax +#define __USAX __usax +#define __UQSAX __uqsax +#define __UHSAX __uhsax +#define __USAD8 __usad8 +#define __USADA8 __usada8 +#define __SSAT16 __ssat16 +#define __USAT16 __usat16 +#define __UXTB16 __uxtb16 +#define __UXTAB16 __uxtab16 +#define __SXTB16 __sxtb16 +#define __SXTAB16 __sxtab16 +#define __SMUAD __smuad +#define __SMUADX __smuadx +#define __SMLAD __smlad +#define __SMLADX __smladx +#define __SMLALD __smlald +#define __SMLALDX __smlaldx +#define __SMUSD __smusd +#define __SMUSDX __smusdx +#define __SMLSD __smlsd +#define __SMLSDX __smlsdx +#define __SMLSLD __smlsld +#define __SMLSLDX __smlsldx +#define __SEL __sel +#define __QADD __qadd +#define __QSUB __qsub + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \ + ((int64_t)(ARG3) << 32) ) >> 32)) + +/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/ + + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/ +#include + +/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/ + + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/ +#include + +/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/ + + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SMLALD(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((uint64_t)(ARG3) >> 32), __ARG3_L = (uint32_t)((uint64_t)(ARG3) & 0xFFFFFFFFUL); \ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \ + (uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \ + }) + +#define __SMLALDX(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((uint64_t)(ARG3) >> 32), __ARG3_L = (uint32_t)((uint64_t)(ARG3) & 0xFFFFFFFFUL); \ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \ + (uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \ + }) + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SMLSLD(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((ARG3) >> 32), __ARG3_L = (uint32_t)((ARG3) & 0xFFFFFFFFUL); \ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \ + (uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \ + }) + +#define __SMLSLDX(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((ARG3) >> 32), __ARG3_L = (uint32_t)((ARG3) & 0xFFFFFFFFUL); \ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \ + (uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \ + }) + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +#define __PKHBT(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +#define __PKHTB(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + if (ARG3 == 0) \ + __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ + else \ + __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/ + + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + + +/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/ +/* not yet supported */ +/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/ + + +#endif + +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CORE_CM4_SIMD_H */ + +#ifdef __cplusplus +} +#endif diff --git a/lpcapi/core_cmFunc.h b/lpcapi/core_cmFunc.h new file mode 100644 index 00000000..ff3106bf --- /dev/null +++ b/lpcapi/core_cmFunc.h @@ -0,0 +1,636 @@ +/**************************************************************************//** + * @file core_cmFunc.h + * @brief CMSIS Cortex-M Core Function Access Header File + * @version V3.20 + * @date 25. February 2013 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2013 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#ifndef __CORE_CMFUNC_H +#define __CORE_CMFUNC_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + +/* intrinsic void __enable_irq(); */ +/* intrinsic void __disable_irq(); */ + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xff); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/** \brief Enable IRQ Interrupts + + This function enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +//__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) +//{ +// __ASM volatile ("cpsie i" : : : "memory"); +//} + + +/** \brief Disable IRQ Interrupts + + This function disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +//__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) +//{ +// __ASM volatile ("cpsid i" : : : "memory"); +//} + + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp"); +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp"); +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_max" : "=r" (result) ); + return(result); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + uint32_t result; + + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + __ASM volatile (""); + return(result); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); + __ASM volatile (""); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all instrinsics, + * Including the CMSIS ones. + */ + +#endif + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +#endif /* __CORE_CMFUNC_H */ diff --git a/lpcapi/core_cmInstr.h b/lpcapi/core_cmInstr.h new file mode 100644 index 00000000..fbeeb9d6 --- /dev/null +++ b/lpcapi/core_cmInstr.h @@ -0,0 +1,688 @@ +/**************************************************************************//** + * @file core_cmInstr.h + * @brief CMSIS Cortex-M Core Instruction Access Header File + * @version V3.20 + * @date 05. March 2013 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2013 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#ifndef __CORE_CMINSTR_H +#define __CORE_CMINSTR_H + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +//#define __WFI __wfi + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __wfe + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +#define __ISB() __isb(0xF) + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __dsb(0xF) + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __dmb(0xF) + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} +#endif + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) +{ + revsh r0, r0 + bx lr +} +#endif + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +/** \brief Breakpoint + + This function causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __breakpoint(value) + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __rbit + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW(value, ptr) __strex(value, ptr) + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +#define __CLREX __clrex + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + +#endif /* (__CORTEX_M >= 0x03) */ + + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constrant "l" + * Otherwise, use general registers, specified by constrant "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void) +{ + __ASM volatile ("nop"); +} + + +///** \brief Wait For Interrupt +// +// Wait For Interrupt is a hint instruction that suspends execution +// until one of a number of events occurs. +// */ +//__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void) +//{ +// __ASM volatile ("wfi"); +//} + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void) +{ + __ASM volatile ("wfe"); +} + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void) +{ + __ASM volatile ("sev"); +} + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void) +{ + __ASM volatile ("isb"); +} + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void) +{ + __ASM volatile ("dsb"); +} + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void) +{ + __ASM volatile ("dmb"); +} + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + return __builtin_bswap32(value); +#else + uint32_t result; + + __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +#endif +} + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + return (short)__builtin_bswap16(value); +#else + uint32_t result; + + __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +#endif +} + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + return (op1 >> op2) | (op1 << (32 - op2)); +} + + +/** \brief Breakpoint + + This function causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return(result); +} + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return(result); +} + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void) +{ + __ASM volatile ("clrex" ::: "memory"); +} + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +//__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value) +//{ +// uint32_t result; +// +// __ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) ); +// return(result); +//} + +#endif /* (__CORTEX_M >= 0x03) */ + + + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +#endif + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + +#endif /* __CORE_CMINSTR_H */ diff --git a/lpcapi/creg_18xx_43xx.h b/lpcapi/creg_18xx_43xx.h new file mode 100644 index 00000000..a8beb1be --- /dev/null +++ b/lpcapi/creg_18xx_43xx.h @@ -0,0 +1,238 @@ +/* + * @brief LPC18XX/43XX CREG control functions + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __CREG_18XX_43XX_H_ +#define __CREG_18XX_43XX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup CREG_18XX_43XX CHIP: LPC18xx/43xx CREG driver + * @ingroup CHIP_18XX_43XX_Drivers + * @{ + */ + +/** + * @brief CREG Register Block + */ +typedef struct { /*!< CREG Structure */ + __I uint32_t RESERVED0; + __IO uint32_t CREG0; /*!< Chip configuration register 32 kHz oscillator output and BOD control register. */ + __I uint32_t RESERVED1[62]; + __IO uint32_t MXMEMMAP; /*!< ARM Cortex-M3/M4 memory mapping */ +#if defined(CHIP_LPC18XX) + __I uint32_t RESERVED2[5]; +#else + __I uint32_t RESERVED2; + __I uint32_t CREG1; /*!< Configuration Register 1 */ + __I uint32_t CREG2; /*!< Configuration Register 2 */ + __I uint32_t CREG3; /*!< Configuration Register 3 */ + __I uint32_t CREG4; /*!< Configuration Register 4 */ +#endif + __IO uint32_t CREG5; /*!< Chip configuration register 5. Controls JTAG access. */ + __IO uint32_t DMAMUX; /*!< DMA muxing control */ + __IO uint32_t FLASHCFGA; /*!< Flash accelerator configuration register for flash bank A */ + __IO uint32_t FLASHCFGB; /*!< Flash accelerator configuration register for flash bank B */ + __IO uint32_t ETBCFG; /*!< ETB RAM configuration */ + __IO uint32_t CREG6; /*!< Chip configuration register 6. */ +#if defined(CHIP_LPC18XX) + __I uint32_t RESERVED4[52]; +#else + __IO uint32_t M4TXEVENT; /*!< M4 IPC event register */ + __I uint32_t RESERVED4[51]; +#endif + __I uint32_t CHIPID; /*!< Part ID */ +#if defined(CHIP_LPC18XX) + __I uint32_t RESERVED5[191]; +#else + __I uint32_t RESERVED5[65]; + __IO uint32_t M0SUBMEMMAP; /*!< M0SUB IPC Event memory mapping */ + __I uint32_t RESERVED6[2]; + __IO uint32_t M0SUBTXEVENT; /*!< M0SUB IPC Event register */ + __I uint32_t RESERVED7[58]; + __IO uint32_t M0APPTXEVENT; /*!< M0APP IPC Event register */ + __IO uint32_t M0APPMEMMAP; /*!< ARM Cortex M0APP memory mapping */ + __I uint32_t RESERVED8[62]; +#endif + __IO uint32_t USB0FLADJ; /*!< USB0 frame length adjust register */ + __I uint32_t RESERVED9[63]; + __IO uint32_t USB1FLADJ; /*!< USB1 frame length adjust register */ +} LPC_CREG_T; + +/** + * @brief Identifies whether on-chip flash is present + * @return true if on chip flash is available, otherwise false + */ +STATIC INLINE uint32_t Chip_CREG_OnChipFlashIsPresent(void) +{ + return LPC_CREG->CHIPID != 0x3284E02B; +} + +/** + * @brief Configures the onboard Flash Accelerator in flash-based LPC18xx/LPC43xx parts. + * @param Hz : Current frequency in Hz of the CPU + * @return Nothing + * This function should be called with the higher frequency before the clock frequency is + * increased and it should be called with the new lower value after the clock frequency is + * decreased. + */ +STATIC INLINE void Chip_CREG_SetFlashAcceleration(uint32_t Hz) +{ + uint32_t FAValue = Hz / 21510000; + + LPC_CREG->FLASHCFGA = (LPC_CREG->FLASHCFGA & (~(0xF << 12))) | (FAValue << 12); + LPC_CREG->FLASHCFGB = (LPC_CREG->FLASHCFGB & (~(0xF << 12))) | (FAValue << 12); +} + +/** + * @brief FLASH Access time definitions + */ +typedef enum { + FLASHTIM_20MHZ_CPU = 0, /*!< Flash accesses use 1 CPU clocks. Use for up to 20 MHz CPU clock */ + FLASHTIM_40MHZ_CPU = 1, /*!< Flash accesses use 2 CPU clocks. Use for up to 40 MHz CPU clock */ + FLASHTIM_60MHZ_CPU = 2, /*!< Flash accesses use 3 CPU clocks. Use for up to 60 MHz CPU clock */ + FLASHTIM_80MHZ_CPU = 3, /*!< Flash accesses use 4 CPU clocks. Use for up to 80 MHz CPU clock */ + FLASHTIM_100MHZ_CPU = 4, /*!< Flash accesses use 5 CPU clocks. Use for up to 100 MHz CPU clock */ + FLASHTIM_120MHZ_CPU = 5, /*!< Flash accesses use 6 CPU clocks. Use for up to 120 MHz CPU clock */ + FLASHTIM_150MHZ_CPU = 6, /*!< Flash accesses use 7 CPU clocks. Use for up to 150 Mhz CPU clock */ + FLASHTIM_170MHZ_CPU = 7, /*!< Flash accesses use 8 CPU clocks. Use for up to 170 MHz CPU clock */ + FLASHTIM_190MHZ_CPU = 8, /*!< Flash accesses use 9 CPU clocks. Use for up to 190 MHz CPU clock */ + FLASHTIM_SAFE_SETTING = 9, /*!< Flash accesses use 10 CPU clocks. Safe setting for any allowed conditions */ +} CREG_FLASHTIM_T; + +/** + * @brief Set FLASH memory access time in clocks + * @param clks : FLASH access speed rating + * @return Nothing + */ +STATIC INLINE void Chip_CREG_SetFLASHAccess(CREG_FLASHTIM_T clks) +{ + uint32_t tmpA, tmpB; + + /* Don't alter lower bits */ + tmpA = LPC_CREG->FLASHCFGA & ~(0xF << 12); + LPC_CREG->FLASHCFGA = tmpA | ((uint32_t) clks << 12); + tmpB = LPC_CREG->FLASHCFGB & ~(0xF << 12); + LPC_CREG->FLASHCFGB = tmpB | ((uint32_t) clks << 12); +} + +/** + * @brief Enables the USB0 high-speed PHY on LPC18xx/LPC43xx parts + * @return Nothing + * @note The USB0 PLL & clock should be configured before calling this function. This function + * should be called before the USB0 registers are accessed. + */ +STATIC INLINE void Chip_CREG_EnableUSB0Phy(void) +{ + LPC_CREG->CREG0 &= ~(1 << 5); +} + +/** + * @brief Disable the USB0 high-speed PHY on LPC18xx/LPC43xx parts + * @return Nothing + * @note The USB0 PLL & clock should be configured before calling this function. This function + * should be called before the USB0 registers are accessed. + */ +STATIC INLINE void Chip_CREG_DisableUSB0Phy(void) +{ + LPC_CREG->CREG0 |= (1 << 5); +} + +/** + * @brief Configures the BOD and Reset on LPC18xx/LPC43xx parts. + * @param BODVL : Brown-Out Detect voltage level (0-3) + * @param BORVL : Brown-Out Reset voltage level (0-3) + * @return Nothing + */ +STATIC INLINE void Chip_CREG_ConfigureBODaR(uint32_t BODVL, uint32_t BORVL) +{ + LPC_CREG->CREG0 = (LPC_CREG->CREG0 & ~((3 << 8) | (3 << 10))) | (BODVL << 8) | (BORVL << 10); +} + +#if (defined(CHIP_LPC43XX) && defined(LPC_CREG)) +/** + * @brief Configures base address of image to be run in the Cortex M0APP Core. + * @param memaddr : Address of the image (must be aligned to 4K) + * @return Nothing + */ +STATIC INLINE void Chip_CREG_SetM0AppMemMap(uint32_t memaddr) +{ + LPC_CREG->M0APPMEMMAP = memaddr & ~0xFFF; +} + +/** + * @brief Configures base address of image to be run in the Cortex M0SUB Core. + * @param memaddr : Address of the image (must be aligned to 4K) + * @return Nothing + */ +STATIC INLINE void Chip_CREG_SetM0SubMemMap(uint32_t memaddr) +{ + LPC_CREG->M0SUBMEMMAP = memaddr & ~0xFFF; +} + +/** + * @brief Clear M4 IPC Event + * @return Nothing + */ +STATIC INLINE void Chip_CREG_ClearM4Event(void) +{ + LPC_CREG->M4TXEVENT = 0; +} + +/** + * @brief Clear M0APP IPC Event + * @return Nothing + */ +STATIC INLINE void Chip_CREG_ClearM0AppEvent(void) +{ + LPC_CREG->M0APPTXEVENT = 0; +} + +/** + * @brief Clear M0APP IPC Event + * @return Nothing + */ +STATIC INLINE void Chip_CREG_ClearM0SubEvent(void) +{ + LPC_CREG->M0SUBTXEVENT = 0; +} +#endif + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CREG_18XX_43XX_H_ */ diff --git a/lpcapi/fpu_init.h b/lpcapi/fpu_init.h new file mode 100644 index 00000000..687e64b4 --- /dev/null +++ b/lpcapi/fpu_init.h @@ -0,0 +1,52 @@ +/* + * @brief FPU init code + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __FPU_INIT_H_ +#define __FPU_INIT_H_ + +/** + * @defgroup CHIP_FPU_CMX CHIP: FPU initialization + * @ingroup CHIP_Common + * Cortex FPU initialization + * @{ + */ + +/** + * @brief Early initialization of the FPU + * @return Nothing + */ +void fpuInit(void); + +/** + * @} + */ + +#endif /* __FPU_INIT_H_ */ diff --git a/lpcapi/lpc_types.h b/lpcapi/lpc_types.h new file mode 100644 index 00000000..772143e5 --- /dev/null +++ b/lpcapi/lpc_types.h @@ -0,0 +1,216 @@ +/* + * @brief Common types used in LPC functions + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __LPC_TYPES_H_ +#define __LPC_TYPES_H_ + +#include +#include + +/** @defgroup LPC_Types CHIP: LPC Common Types + * @ingroup CHIP_Common + * @{ + */ + +/** @defgroup LPC_Types_Public_Types LPC Public Types + * @{ + */ + +/** + * @brief Boolean Type definition + */ +typedef enum {FALSE = 0, TRUE = !FALSE} Bool; + +/** + * @brief Boolean Type definition + */ +#if !defined(__cplusplus) +// typedef enum {false = 0, true = !false} bool; +#endif + +/** + * @brief Flag Status and Interrupt Flag Status type definition + */ +typedef enum {RESET = 0, SET = !RESET} FlagStatus, IntStatus, SetState; +#define PARAM_SETSTATE(State) ((State == RESET) || (State == SET)) + +/** + * @brief Functional State Definition + */ +typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; +#define PARAM_FUNCTIONALSTATE(State) ((State == DISABLE) || (State == ENABLE)) + +/** + * @ Status type definition + */ +typedef enum {ERROR = 0, SUCCESS = !ERROR} Status; + +/** + * Read/Write transfer type mode (Block or non-block) + */ +typedef enum { + NONE_BLOCKING = 0, /**< None Blocking type */ + BLOCKING, /**< Blocking type */ +} TRANSFER_BLOCK_T; + +/** Pointer to Function returning Void (any number of parameters) */ +typedef void (*PFV)(); + +/** Pointer to Function returning int32_t (any number of parameters) */ +typedef int32_t (*PFI)(); + +/** + * @} + */ + +/** @defgroup LPC_Types_Public_Macros LPC Public Macros + * @{ + */ + +/* _BIT(n) sets the bit at position "n" + * _BIT(n) is intended to be used in "OR" and "AND" expressions: + * e.g., "(_BIT(3) | _BIT(7))". + */ +#undef _BIT +/* Set bit macro */ +#define _BIT(n) (1 << (n)) + +/* _SBF(f,v) sets the bit field starting at position "f" to value "v". + * _SBF(f,v) is intended to be used in "OR" and "AND" expressions: + * e.g., "((_SBF(5,7) | _SBF(12,0xF)) & 0xFFFF)" + */ +#undef _SBF +/* Set bit field macro */ +#define _SBF(f, v) ((v) << (f)) + +/* _BITMASK constructs a symbol with 'field_width' least significant + * bits set. + * e.g., _BITMASK(5) constructs '0x1F', _BITMASK(16) == 0xFFFF + * The symbol is intended to be used to limit the bit field width + * thusly: + * = (any_expression) & _BITMASK(x), where 0 < x <= 32. + * If "any_expression" results in a value that is larger than can be + * contained in 'x' bits, the bits above 'x - 1' are masked off. When + * used with the _SBF example above, the example would be written: + * a_reg = ((_SBF(5,7) | _SBF(12,0xF)) & _BITMASK(16)) + * This ensures that the value written to a_reg is no wider than + * 16 bits, and makes the code easier to read and understand. + */ +#undef _BITMASK +/* Bitmask creation macro */ +#define _BITMASK(field_width) ( _BIT(field_width) - 1) + +/* NULL pointer */ +#ifndef NULL +#define NULL ((void *) 0) +#endif + +/* Number of elements in an array */ +#define NELEMENTS(array) (sizeof(array) / sizeof(array[0])) + +/* Static data/function define */ +#define STATIC static +/* External data/function define */ +#define EXTERN extern + +#if !defined(MAX) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif +#if !defined(MIN) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +/** + * @} + */ + +/* Old Type Definition compatibility */ +/** @addtogroup LPC_Types_Public_Types + * @{ + */ + +/** LPC type for character type */ +typedef char CHAR; + +/** LPC type for 8 bit unsigned value */ +typedef uint8_t UNS_8; + +/** LPC type for 8 bit signed value */ +typedef int8_t INT_8; + +/** LPC type for 16 bit unsigned value */ +typedef uint16_t UNS_16; + +/** LPC type for 16 bit signed value */ +typedef int16_t INT_16; + +/** LPC type for 32 bit unsigned value */ +typedef uint32_t UNS_32; + +/** LPC type for 32 bit signed value */ +typedef int32_t INT_32; + +/** LPC type for 64 bit signed value */ +typedef int64_t INT_64; + +/** LPC type for 64 bit unsigned value */ +typedef uint64_t UNS_64; + +#ifdef __CODE_RED +#define BOOL_32 bool +#define BOOL_16 bool +#define BOOL_8 bool +#else +/** 32 bit boolean type */ +typedef bool BOOL_32; + +/** 16 bit boolean type */ +typedef bool BOOL_16; + +/** 8 bit boolean type */ +typedef bool BOOL_8; +#endif + +#ifdef __CC_ARM +#define INLINE __inline +#else +#define INLINE inline +#endif + +/** + * @} + */ + +/** + * @} + */ + +#endif /* __LPC_TYPES_H_ */ diff --git a/lpcapi/sdif_18xx_43xx.c b/lpcapi/sdif_18xx_43xx.c new file mode 100644 index 00000000..663d889c --- /dev/null +++ b/lpcapi/sdif_18xx_43xx.c @@ -0,0 +1,223 @@ +/* + * @brief LPC18xx/43xx SD/SDIO driver + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" +#include "string.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Initializes the SD/MMC controller */ +void Chip_SDIF_Init(LPC_SDMMC_T *pSDMMC) +{ + /* Enable SDIO module clock */ + Chip_Clock_EnableOpts(CLK_MX_SDIO, true, true, 1); + + /* Software reset */ + pSDMMC->BMOD = MCI_BMOD_SWR; + + /* reset all blocks */ + pSDMMC->CTRL = MCI_CTRL_RESET | MCI_CTRL_FIFO_RESET | MCI_CTRL_DMA_RESET; + while (pSDMMC->CTRL & (MCI_CTRL_RESET | MCI_CTRL_FIFO_RESET | MCI_CTRL_DMA_RESET)) {} + + /* Internal DMA setup for control register */ + pSDMMC->CTRL = MCI_CTRL_USE_INT_DMAC | MCI_CTRL_INT_ENABLE; + pSDMMC->INTMASK = 0; + + /* Clear the interrupts for the host controller */ + pSDMMC->RINTSTS = 0xFFFFFFFF; + + /* Put in max timeout */ + pSDMMC->TMOUT = 0xFFFFFFFF; + + /* FIFO threshold settings for DMA, DMA burst of 4, FIFO watermark at 16 */ + pSDMMC->FIFOTH = MCI_FIFOTH_DMA_MTS_4 | MCI_FIFOTH_RX_WM((SD_FIFO_SZ / 2) - 1) | MCI_FIFOTH_TX_WM(SD_FIFO_SZ / 2); + + /* Enable internal DMA, burst size of 4, fixed burst */ + pSDMMC->BMOD = MCI_BMOD_DE | MCI_BMOD_PBL4 | MCI_BMOD_DSL(4); + + /* disable clock to CIU (needs latch) */ + pSDMMC->CLKENA = 0; + pSDMMC->CLKSRC = 0; +} + +/* Shutdown the SD/MMC controller */ +void Chip_SDIF_DeInit(LPC_SDMMC_T *pSDMMC) +{ + /* Disable the clock */ + Chip_Clock_Disable(CLK_MX_SDIO); +} + +/* Function to send command to Card interface unit (CIU) */ +int32_t Chip_SDIF_SendCmd(LPC_SDMMC_T *pSDMMC, uint32_t cmd, uint32_t arg) +{ + volatile int32_t tmo = 50; + volatile int delay; + + /* set command arg reg*/ + pSDMMC->CMDARG = arg; + pSDMMC->CMD = MCI_CMD_START | cmd; + + /* poll untill command is accepted by the CIU */ + while (--tmo && (pSDMMC->CMD & MCI_CMD_START)) { + if (tmo & 1) { + delay = 50; + } + else { + delay = 18000; + } + + while (--delay > 1) {} + } + + return (tmo < 1) ? 1 : 0; +} + +/* Read the response from the last command */ +void Chip_SDIF_GetResponse(LPC_SDMMC_T *pSDMMC, uint32_t *resp) +{ + /* on this chip response is not a fifo so read all 4 regs */ + resp[0] = pSDMMC->RESP0; + resp[1] = pSDMMC->RESP1; + resp[2] = pSDMMC->RESP2; + resp[3] = pSDMMC->RESP3; +} + +/* Sets the SD bus clock speed */ +void Chip_SDIF_SetClock(LPC_SDMMC_T *pSDMMC, uint32_t clk_rate, uint32_t speed) +{ + /* compute SD/MMC clock dividers */ + uint32_t div; + + div = ((clk_rate / speed) + 2) >> 1; + + if ((div == pSDMMC->CLKDIV) && pSDMMC->CLKENA) { + return; /* Closest speed is already set */ + + } + /* disable clock */ + pSDMMC->CLKENA = 0; + + /* User divider 0 */ + pSDMMC->CLKSRC = MCI_CLKSRC_CLKDIV0; + + /* inform CIU */ + Chip_SDIF_SendCmd(pSDMMC, MCI_CMD_UPD_CLK | MCI_CMD_PRV_DAT_WAIT, 0); + + /* set divider 0 to desired value */ + pSDMMC->CLKDIV = MCI_CLOCK_DIVIDER(0, div); + + /* inform CIU */ + Chip_SDIF_SendCmd(pSDMMC, MCI_CMD_UPD_CLK | MCI_CMD_PRV_DAT_WAIT, 0); + + /* enable clock */ + pSDMMC->CLKENA = MCI_CLKEN_ENABLE; + + /* inform CIU */ + Chip_SDIF_SendCmd(pSDMMC, MCI_CMD_UPD_CLK | MCI_CMD_PRV_DAT_WAIT, 0); +} + +/* Function to clear interrupt & FIFOs */ +void Chip_SDIF_SetClearIntFifo(LPC_SDMMC_T *pSDMMC) +{ + /* reset all blocks */ + pSDMMC->CTRL |= MCI_CTRL_FIFO_RESET; + + /* wait till resets clear */ + while (pSDMMC->CTRL & MCI_CTRL_FIFO_RESET) {} + + /* Clear interrupt status */ + pSDMMC->RINTSTS = 0xFFFFFFFF; +} + +/* Setup DMA descriptors */ +void Chip_SDIF_DmaSetup(LPC_SDMMC_T *pSDMMC, sdif_device *psdif_dev, uint32_t addr, uint32_t size) +{ + int i = 0; + uint32_t ctrl, maxs; + + /* Reset DMA */ + pSDMMC->CTRL |= MCI_CTRL_DMA_RESET | MCI_CTRL_FIFO_RESET; + while (pSDMMC->CTRL & MCI_CTRL_DMA_RESET) {} + + /* Build a descriptor list using the chained DMA method */ + while (size > 0) { + /* Limit size of the transfer to maximum buffer size */ + maxs = size; + if (maxs > MCI_DMADES1_MAXTR) { + maxs = MCI_DMADES1_MAXTR; + } + size -= maxs; + + /* Set buffer size */ + psdif_dev->mci_dma_dd[i].des1 = MCI_DMADES1_BS1(maxs); + + /* Setup buffer address (chained) */ + psdif_dev->mci_dma_dd[i].des2 = addr + (i * MCI_DMADES1_MAXTR); + + /* Setup basic control */ + ctrl = MCI_DMADES0_OWN | MCI_DMADES0_CH; + if (i == 0) { + ctrl |= MCI_DMADES0_FS; /* First DMA buffer */ + + } + /* No more data? Then this is the last descriptor */ + if (!size) { + ctrl |= MCI_DMADES0_LD; + } + else { + ctrl |= MCI_DMADES0_DIC; + } + + /* Another descriptor is needed */ + psdif_dev->mci_dma_dd[i].des3 = (uint32_t) &psdif_dev->mci_dma_dd[i + 1]; + psdif_dev->mci_dma_dd[i].des0 = ctrl; + + i++; + } + + /* Set DMA derscriptor base address */ + pSDMMC->DBADDR = (uint32_t) &psdif_dev->mci_dma_dd[0]; +} + diff --git a/lpcapi/sdif_18xx_43xx.h b/lpcapi/sdif_18xx_43xx.h new file mode 100644 index 00000000..c2de7344 --- /dev/null +++ b/lpcapi/sdif_18xx_43xx.h @@ -0,0 +1,481 @@ +/* + * @brief LPC18xx/43xx SD/SDIO driver + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __SDIF_18XX_43XX_H_ +#define __SDIF_18XX_43XX_H_ + +#include "cmsis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup SDIF_18XX_43XX CHIP: LPC18xx/43xx SD/SDIO driver + * @ingroup CHIP_18XX_43XX_Drivers + * @{ + */ + +/** + * @brief SD/MMC & SDIO register block structure + */ +typedef struct { /*!< SDMMC Structure */ + __IO uint32_t CTRL; /*!< Control Register */ + __IO uint32_t PWREN; /*!< Power Enable Register */ + __IO uint32_t CLKDIV; /*!< Clock Divider Register */ + __IO uint32_t CLKSRC; /*!< SD Clock Source Register */ + __IO uint32_t CLKENA; /*!< Clock Enable Register */ + __IO uint32_t TMOUT; /*!< Timeout Register */ + __IO uint32_t CTYPE; /*!< Card Type Register */ + __IO uint32_t BLKSIZ; /*!< Block Size Register */ + __IO uint32_t BYTCNT; /*!< Byte Count Register */ + __IO uint32_t INTMASK; /*!< Interrupt Mask Register */ + __IO uint32_t CMDARG; /*!< Command Argument Register */ + __IO uint32_t CMD; /*!< Command Register */ + __I uint32_t RESP0; /*!< Response Register 0 */ + __I uint32_t RESP1; /*!< Response Register 1 */ + __I uint32_t RESP2; /*!< Response Register 2 */ + __I uint32_t RESP3; /*!< Response Register 3 */ + __I uint32_t MINTSTS; /*!< Masked Interrupt Status Register */ + __IO uint32_t RINTSTS; /*!< Raw Interrupt Status Register */ + __I uint32_t STATUS; /*!< Status Register */ + __IO uint32_t FIFOTH; /*!< FIFO Threshold Watermark Register */ + __I uint32_t CDETECT; /*!< Card Detect Register */ + __I uint32_t WRTPRT; /*!< Write Protect Register */ + __IO uint32_t GPIO; /*!< General Purpose Input/Output Register */ + __I uint32_t TCBCNT; /*!< Transferred CIU Card Byte Count Register */ + __I uint32_t TBBCNT; /*!< Transferred Host to BIU-FIFO Byte Count Register */ + __IO uint32_t DEBNCE; /*!< Debounce Count Register */ + __IO uint32_t USRID; /*!< User ID Register */ + __I uint32_t VERID; /*!< Version ID Register */ + __I uint32_t RESERVED0; + __IO uint32_t UHS_REG; /*!< UHS-1 Register */ + __IO uint32_t RST_N; /*!< Hardware Reset */ + __I uint32_t RESERVED1; + __IO uint32_t BMOD; /*!< Bus Mode Register */ + __O uint32_t PLDMND; /*!< Poll Demand Register */ + __IO uint32_t DBADDR; /*!< Descriptor List Base Address Register */ + __IO uint32_t IDSTS; /*!< Internal DMAC Status Register */ + __IO uint32_t IDINTEN; /*!< Internal DMAC Interrupt Enable Register */ + __I uint32_t DSCADDR; /*!< Current Host Descriptor Address Register */ + __I uint32_t BUFADDR; /*!< Current Buffer Descriptor Address Register */ +} LPC_SDMMC_T; + +/** @brief SDIO DMA descriptor control (des0) register defines + */ +#define MCI_DMADES0_OWN (1UL << 31) /*!< DMA owns descriptor bit */ +#define MCI_DMADES0_CES (1 << 30) /*!< Card Error Summary bit */ +#define MCI_DMADES0_ER (1 << 5) /*!< End of descriptopr ring bit */ +#define MCI_DMADES0_CH (1 << 4) /*!< Second address chained bit */ +#define MCI_DMADES0_FS (1 << 3) /*!< First descriptor bit */ +#define MCI_DMADES0_LD (1 << 2) /*!< Last descriptor bit */ +#define MCI_DMADES0_DIC (1 << 1) /*!< Disable interrupt on completion bit */ + +/** @brief SDIO DMA descriptor size (des1) register defines + */ +#define MCI_DMADES1_BS1(x) (x) /*!< Size of buffer 1 */ +#define MCI_DMADES1_BS2(x) ((x) << 13) /*!< Size of buffer 2 */ +#define MCI_DMADES1_MAXTR 4096 /*!< Max transfer size per buffer */ + +/** @brief SDIO control register defines + */ +#define MCI_CTRL_USE_INT_DMAC (1 << 25) /*!< Use internal DMA */ +#define MCI_CTRL_CARDV_MASK (0x7 << 16) /*!< SD_VOLT[2:0} pins output state mask */ +#define MCI_CTRL_CEATA_INT_EN (1 << 11) /*!< Enable CE-ATA interrupts */ +#define MCI_CTRL_SEND_AS_CCSD (1 << 10) /*!< Send auto-stop */ +#define MCI_CTRL_SEND_CCSD (1 << 9) /*!< Send CCSD */ +#define MCI_CTRL_ABRT_READ_DATA (1 << 8) /*!< Abort read data */ +#define MCI_CTRL_SEND_IRQ_RESP (1 << 7) /*!< Send auto-IRQ response */ +#define MCI_CTRL_READ_WAIT (1 << 6) /*!< Assert read-wait for SDIO */ +#define MCI_CTRL_INT_ENABLE (1 << 4) /*!< Global interrupt enable */ +#define MCI_CTRL_DMA_RESET (1 << 2) /*!< Reset internal DMA */ +#define MCI_CTRL_FIFO_RESET (1 << 1) /*!< Reset data FIFO pointers */ +#define MCI_CTRL_RESET (1 << 0) /*!< Reset controller */ + +/** @brief SDIO Power Enable register defines + */ +#define MCI_POWER_ENABLE 0x1 /*!< Enable slot power signal (SD_POW) */ + +/** @brief SDIO Clock divider register defines + */ +#define MCI_CLOCK_DIVIDER(dn, d2) ((d2) << ((dn) * 8)) /*!< Set cklock divider */ + +/** @brief SDIO Clock source register defines + */ +#define MCI_CLKSRC_CLKDIV0 0 +#define MCI_CLKSRC_CLKDIV1 1 +#define MCI_CLKSRC_CLKDIV2 2 +#define MCI_CLKSRC_CLKDIV3 3 +#define MCI_CLK_SOURCE(clksrc) (clksrc) /*!< Set cklock divider source */ + +/** @brief SDIO Clock Enable register defines + */ +#define MCI_CLKEN_LOW_PWR (1 << 16) /*!< Enable clock idle for slot */ +#define MCI_CLKEN_ENABLE (1 << 0) /*!< Enable slot clock */ + +/** @brief SDIO time-out register defines + */ +#define MCI_TMOUT_DATA(clks) ((clks) << 8) /*!< Data timeout clocks */ +#define MCI_TMOUT_DATA_MSK 0xFFFFFF00 +#define MCI_TMOUT_RESP(clks) ((clks) & 0xFF) /*!< Response timeout clocks */ +#define MCI_TMOUT_RESP_MSK 0xFF + +/** @brief SDIO card-type register defines + */ +#define MCI_CTYPE_8BIT (1 << 16) /*!< Enable 4-bit mode */ +#define MCI_CTYPE_4BIT (1 << 0) /*!< Enable 8-bit mode */ + +/** @brief SDIO Interrupt status & mask register defines + */ +#define MCI_INT_SDIO (1 << 16) /*!< SDIO interrupt */ +#define MCI_INT_EBE (1 << 15) /*!< End-bit error */ +#define MCI_INT_ACD (1 << 14) /*!< Auto command done */ +#define MCI_INT_SBE (1 << 13) /*!< Start bit error */ +#define MCI_INT_HLE (1 << 12) /*!< Hardware locked error */ +#define MCI_INT_FRUN (1 << 11) /*!< FIFO overrun/underrun error */ +#define MCI_INT_HTO (1 << 10) /*!< Host data starvation error */ +#define MCI_INT_DTO (1 << 9) /*!< Data timeout error */ +#define MCI_INT_RTO (1 << 8) /*!< Response timeout error */ +#define MCI_INT_DCRC (1 << 7) /*!< Data CRC error */ +#define MCI_INT_RCRC (1 << 6) /*!< Response CRC error */ +#define MCI_INT_RXDR (1 << 5) /*!< RX data ready */ +#define MCI_INT_TXDR (1 << 4) /*!< TX data needed */ +#define MCI_INT_DATA_OVER (1 << 3) /*!< Data transfer over */ +#define MCI_INT_CMD_DONE (1 << 2) /*!< Command done */ +#define MCI_INT_RESP_ERR (1 << 1) /*!< Command response error */ +#define MCI_INT_CD (1 << 0) /*!< Card detect */ + +/** @brief SDIO Command register defines + */ +#define MCI_CMD_START (1UL << 31) /*!< Start command */ +#define MCI_CMD_VOLT_SWITCH (1 << 28) /*!< Voltage switch bit */ +#define MCI_CMD_BOOT_MODE (1 << 27) /*!< Boot mode */ +#define MCI_CMD_DISABLE_BOOT (1 << 26) /*!< Disable boot */ +#define MCI_CMD_EXPECT_BOOT_ACK (1 << 25) /*!< Expect boot ack */ +#define MCI_CMD_ENABLE_BOOT (1 << 24) /*!< Enable boot */ +#define MCI_CMD_CCS_EXP (1 << 23) /*!< CCS expected */ +#define MCI_CMD_CEATA_RD (1 << 22) /*!< CE-ATA read in progress */ +#define MCI_CMD_UPD_CLK (1 << 21) /*!< Update clock register only */ +#define MCI_CMD_INIT (1 << 15) /*!< Send init sequence */ +#define MCI_CMD_STOP (1 << 14) /*!< Stop/abort command */ +#define MCI_CMD_PRV_DAT_WAIT (1 << 13) /*!< Wait before send */ +#define MCI_CMD_SEND_STOP (1 << 12) /*!< Send auto-stop */ +#define MCI_CMD_STRM_MODE (1 << 11) /*!< Stream transfer mode */ +#define MCI_CMD_DAT_WR (1 << 10) /*!< Read(0)/Write(1) selection */ +#define MCI_CMD_DAT_EXP (1 << 9) /*!< Data expected */ +#define MCI_CMD_RESP_CRC (1 << 8) /*!< Check response CRC */ +#define MCI_CMD_RESP_LONG (1 << 7) /*!< Response length */ +#define MCI_CMD_RESP_EXP (1 << 6) /*!< Response expected */ +#define MCI_CMD_INDX(n) ((n) & 0x1F) + +/** @brief SDIO status register definess + */ +#define MCI_STS_GET_FCNT(x) (((x) >> 17) & 0x1FF) + +/** @brief SDIO FIFO threshold defines + */ +#define MCI_FIFOTH_TX_WM(x) ((x) & 0xFFF) +#define MCI_FIFOTH_RX_WM(x) (((x) & 0xFFF) << 16) +#define MCI_FIFOTH_DMA_MTS_1 (0UL << 28) +#define MCI_FIFOTH_DMA_MTS_4 (1UL << 28) +#define MCI_FIFOTH_DMA_MTS_8 (2UL << 28) +#define MCI_FIFOTH_DMA_MTS_16 (3UL << 28) +#define MCI_FIFOTH_DMA_MTS_32 (4UL << 28) +#define MCI_FIFOTH_DMA_MTS_64 (5UL << 28) +#define MCI_FIFOTH_DMA_MTS_128 (6UL << 28) +#define MCI_FIFOTH_DMA_MTS_256 (7UL << 28) + +/** @brief Bus mode register defines + */ +#define MCI_BMOD_PBL1 (0 << 8) /*!< Burst length = 1 */ +#define MCI_BMOD_PBL4 (1 << 8) /*!< Burst length = 4 */ +#define MCI_BMOD_PBL8 (2 << 8) /*!< Burst length = 8 */ +#define MCI_BMOD_PBL16 (3 << 8) /*!< Burst length = 16 */ +#define MCI_BMOD_PBL32 (4 << 8) /*!< Burst length = 32 */ +#define MCI_BMOD_PBL64 (5 << 8) /*!< Burst length = 64 */ +#define MCI_BMOD_PBL128 (6 << 8) /*!< Burst length = 128 */ +#define MCI_BMOD_PBL256 (7 << 8) /*!< Burst length = 256 */ +#define MCI_BMOD_DE (1 << 7) /*!< Enable internal DMAC */ +#define MCI_BMOD_DSL(len) ((len) << 2) /*!< Descriptor skip length */ +#define MCI_BMOD_FB (1 << 1) /*!< Fixed bursts */ +#define MCI_BMOD_SWR (1 << 0) /*!< Software reset of internal registers */ + +/** @brief Commonly used definitions + */ +#define SD_FIFO_SZ 32 /*!< Size of SDIO FIFOs (32-bit wide) */ + +/** Function prototype for SD interface IRQ callback */ +typedef uint32_t (*MCI_IRQ_CB_FUNC_T)(uint32_t); + +/** Function prototype for SD detect and write protect status check */ +typedef int32_t (*PSCHECK_FUNC_T)(void); + +/** Function prototype for SD slot power enable or slot reset */ +typedef void (*PS_POWER_FUNC_T)(int32_t enable); + +/** @brief SDIO chained DMA descriptor + */ +typedef struct { + volatile uint32_t des0; /*!< Control and status */ + volatile uint32_t des1; /*!< Buffer size(s) */ + volatile uint32_t des2; /*!< Buffer address pointer 1 */ + volatile uint32_t des3; /*!< Buffer address pointer 2 */ +} pSDMMC_DMA_T; + +/** @brief SDIO device type + */ +typedef struct _sdif_device { + /* MCI_IRQ_CB_FUNC_T irq_cb; */ + pSDMMC_DMA_T mci_dma_dd[1 + (0x10000 / MCI_DMADES1_MAXTR)]; + /* uint32_t sdio_clk_rate; */ + /* uint32_t sdif_slot_clk_rate; */ + /* int32_t clock_enabled; */ +} sdif_device; + +/** @brief Setup options for the SDIO driver + */ +#define US_TIMEOUT 1000000 /*!< give 1 atleast 1 sec for the card to respond */ +#define MS_ACQUIRE_DELAY (10) /*!< inter-command acquire oper condition delay in msec*/ +#define INIT_OP_RETRIES 50 /*!< initial OP_COND retries */ +#define SET_OP_RETRIES 1000 /*!< set OP_COND retries */ +#define SDIO_BUS_WIDTH 4 /*!< Max bus width supported */ +#define SD_MMC_ENUM_CLOCK 400000 /*!< Typical enumeration clock rate */ +#define MMC_MAX_CLOCK 20000000 /*!< Max MMC clock rate */ +#define MMC_LOW_BUS_MAX_CLOCK 26000000 /*!< Type 0 MMC card max clock rate */ +#define MMC_HIGH_BUS_MAX_CLOCK 52000000 /*!< Type 1 MMC card max clock rate */ +#define SD_MAX_CLOCK 25000000 /*!< Max SD clock rate */ + +/** + * @brief Set block size for the transfer + * @param pSDMMC : SDMMC peripheral selected + * @param bytes : block size in bytes + * @return None + */ +STATIC INLINE void Chip_SDIF_SetBlkSize(LPC_SDMMC_T *pSDMMC, uint32_t bytes) +{ + pSDMMC->BLKSIZ = bytes; +} + +/** + * @brief Reset card in slot + * @param pSDMMC : SDMMC peripheral selected + * @param reset : Sets SD_RST to passed state + * @return None + * @note Reset card in slot, must manually de-assert reset after assertion + * (Uses SD_RST pin, set per reset parameter state) + */ +STATIC INLINE void Chip_SDIF_Reset(LPC_SDMMC_T *pSDMMC, int32_t reset) +{ + if (reset) { + pSDMMC->RST_N = 1; + } + else { + pSDMMC->RST_N = 0; + } +} + +/** + * @brief Detect if an SD card is inserted + * @param pSDMMC : SDMMC peripheral selected + * @return Returns 0 if a card is detected, otherwise 1 + * @note Detect if an SD card is inserted + * (uses SD_CD pin, returns 0 on card detect) + */ +STATIC INLINE int32_t Chip_SDIF_CardNDetect(LPC_SDMMC_T *pSDMMC) +{ + return (pSDMMC->CDETECT & 1); +} + +/** + * @brief Detect if write protect is enabled + * @param pSDMMC : SDMMC peripheral selected + * @return Returns 1 if card is write protected, otherwise 0 + * @note Detect if write protect is enabled + * (uses SD_WP pin, returns 1 if card is write protected) + */ +STATIC INLINE int32_t Chip_SDIF_CardWpOn(LPC_SDMMC_T *pSDMMC) +{ + return (pSDMMC->WRTPRT & 1); +} + +/** + * @brief Disable slot power + * @param pSDMMC : SDMMC peripheral selected + * @return None + * @note Uses SD_POW pin, set to low. + */ +STATIC INLINE void Chip_SDIF_PowerOff(LPC_SDMMC_T *pSDMMC) +{ + pSDMMC->PWREN = 0; +} + +/** + * @brief Enable slot power + * @param pSDMMC : SDMMC peripheral selected + * @return None + * @note Uses SD_POW pin, set to high. + */ +STATIC INLINE void Chip_SDIF_PowerOn(LPC_SDMMC_T *pSDMMC) +{ + pSDMMC->PWREN = 1; +} + +/** + * @brief Function to set card type + * @param pSDMMC : SDMMC peripheral selected + * @param ctype : card type + * @return None + */ +STATIC INLINE void Chip_SDIF_SetCardType(LPC_SDMMC_T *pSDMMC, uint32_t ctype) +{ + pSDMMC->CTYPE = ctype; +} + +/** + * @brief Returns the raw SD interface interrupt status + * @param pSDMMC : SDMMC peripheral selected + * @return Current pending interrupt status of Or'ed values MCI_INT_* + */ +STATIC INLINE uint32_t Chip_SDIF_GetIntStatus(LPC_SDMMC_T *pSDMMC) +{ + return pSDMMC->RINTSTS; +} + +/** + * @brief Clears the raw SD interface interrupt status + * @param pSDMMC : SDMMC peripheral selected + * @param iVal : Interrupts to be cleared, Or'ed values MCI_INT_* + * @return None + */ +STATIC INLINE void Chip_SDIF_ClrIntStatus(LPC_SDMMC_T *pSDMMC, uint32_t iVal) +{ + pSDMMC->RINTSTS = iVal; +} + +/** + * @brief Sets the SD interface interrupt mask + * @param pSDMMC : SDMMC peripheral selected + * @param iVal : Interrupts to enable, Or'ed values MCI_INT_* + * @return None + */ +STATIC INLINE void Chip_SDIF_SetIntMask(LPC_SDMMC_T *pSDMMC, uint32_t iVal) +{ + pSDMMC->INTMASK = iVal; +} + +/** + * @brief Set block size and byte count for transfer + * @param pSDMMC : SDMMC peripheral selected + * @param blk_size: block size and byte count in bytes + * @return None + */ +STATIC INLINE void Chip_SDIF_SetBlkSizeByteCnt(LPC_SDMMC_T *pSDMMC, uint32_t blk_size) +{ + pSDMMC->BLKSIZ = blk_size; + pSDMMC->BYTCNT = blk_size; +} + +/** + * @brief Set byte count for transfer + * @param pSDMMC : SDMMC peripheral selected + * @param bytes : block size and byte count in bytes + * @return None + */ +STATIC INLINE void Chip_SDIF_SetByteCnt(LPC_SDMMC_T *pSDMMC, uint32_t bytes) +{ + pSDMMC->BYTCNT = bytes; +} + +/** + * @brief Initializes the SD/MMC card controller + * @param pSDMMC : SDMMC peripheral selected + * @return None + */ +void Chip_SDIF_Init(LPC_SDMMC_T *pSDMMC); + +/** + * @brief Shutdown the SD/MMC card controller + * @param pSDMMC : SDMMC peripheral selected + * @return None + */ +void Chip_SDIF_DeInit(LPC_SDMMC_T *pSDMMC); + +/** + * @brief Function to send command to Card interface unit (CIU) + * @param pSDMMC : SDMMC peripheral selected + * @param cmd : Command with all flags set + * @param arg : Argument for the command + * @return TRUE on times-out, otherwise FALSE + */ +int32_t Chip_SDIF_SendCmd(LPC_SDMMC_T *pSDMMC, uint32_t cmd, uint32_t arg); + +/** + * @brief Read the response from the last command + * @param pSDMMC : SDMMC peripheral selected + * @param resp : Pointer to response array to fill + * @return None + */ +void Chip_SDIF_GetResponse(LPC_SDMMC_T *pSDMMC, uint32_t *resp); + +/** + * @brief Sets the SD bus clock speed + * @param pSDMMC : SDMMC peripheral selected + * @param clk_rate : Input clock rate into the IP block + * @param speed : Desired clock speed to the card + * @return None + */ +void Chip_SDIF_SetClock(LPC_SDMMC_T *pSDMMC, uint32_t clk_rate, uint32_t speed); + +/** + * @brief Function to clear interrupt & FIFOs + * @param pSDMMC : SDMMC peripheral selected + * @return None + */ +void Chip_SDIF_SetClearIntFifo(LPC_SDMMC_T *pSDMMC); + +/** + * @brief Setup DMA descriptors + * @param pSDMMC : SDMMC peripheral selected + * @param psdif_dev : SD interface device + * @param addr : Address of buffer (source or destination) + * @param size : size of buffer in bytes (64K max) + * @return None + */ +void Chip_SDIF_DmaSetup(LPC_SDMMC_T *pSDMMC, sdif_device *psdif_dev, uint32_t addr, uint32_t size); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __SDIF_18XX_43XX_H_ */ diff --git a/lpcapi/sdmmc.h b/lpcapi/sdmmc.h new file mode 100644 index 00000000..6c0fd182 --- /dev/null +++ b/lpcapi/sdmmc.h @@ -0,0 +1,450 @@ +/* + * @brief Common definitions used in SD/MMC cards + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __SDMMC_H +#define __SDMMC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup CHIP_SDMMC_Definitions CHIP: Common SD/MMC definitions + * @ingroup CHIP_Common + * @{ + */ + +/** + * @brief OCR Register definitions + */ +/** Support voltage range 2.0-2.1 (this bit is reserved in SDC)*/ +#define SDC_OCR_20_21 (((uint32_t) 1) << 8) +/** Support voltage range 2.1-2.2 (this bit is reserved in SDC)*/ +#define SDC_OCR_21_22 (((uint32_t) 1) << 9) +/** Support voltage range 2.2-2.3 (this bit is reserved in SDC)*/ +#define SDC_OCR_22_23 (((uint32_t) 1) << 10) +/** Support voltage range 2.3-2.4 (this bit is reserved in SDC)*/ +#define SDC_OCR_23_24 (((uint32_t) 1) << 11) +/** Support voltage range 2.4-2.5 (this bit is reserved in SDC)*/ +#define SDC_OCR_24_25 (((uint32_t) 1) << 12) +/** Support voltage range 2.5-2.6 (this bit is reserved in SDC)*/ +#define SDC_OCR_25_26 (((uint32_t) 1) << 13) +/** Support voltage range 2.6-2.7 (this bit is reserved in SDC)*/ +#define SDC_OCR_26_27 (((uint32_t) 1) << 14) +/** Support voltage range 2.7-2.8 */ +#define SDC_OCR_27_28 (((uint32_t) 1) << 15) +/** Support voltage range 2.8-2.9*/ +#define SDC_OCR_28_29 (((uint32_t) 1) << 16) +/** Support voltage range 2.9-3.0 */ +#define SDC_OCR_29_30 (((uint32_t) 1) << 17) +/** Support voltage range 3.0-3.1 */ +#define SDC_OCR_30_31 (((uint32_t) 1) << 18) +/** Support voltage range 3.1-3.2 */ +#define SDC_OCR_31_32 (((uint32_t) 1) << 19) +/** Support voltage range 3.2-3.3 */ +#define SDC_OCR_32_33 (((uint32_t) 1) << 20) +/** Support voltage range 3.3-3.4 */ +#define SDC_OCR_33_34 (((uint32_t) 1) << 21) +/** Support voltage range 3.4-3.5 */ +#define SDC_OCR_34_35 (((uint32_t) 1) << 22) +/** Support voltage range 3.5-3.6 */ +#define SDC_OCR_35_36 (((uint32_t) 1) << 23) +/** Support voltage range 2.7-3.6 */ +#define SDC_OCR_27_36 ((uint32_t) 0x00FF8000) +/** Card Capacity Status (CCS). (this bit is reserved in MMC) */ +#define SDC_OCR_HC_CCS (((uint32_t) 1) << 30) +/** Card power up status bit */ +#define SDC_OCR_IDLE (((uint32_t) 1) << 31) +#define SDC_OCR_BUSY (((uint32_t) 0) << 31) + +/* SD/MMC commands - this matrix shows the command, response types, and + supported card type for that command. + Command Number Resp SD MMC + ----------------------- ------ ----- --- --- + Reset (go idle) CMD0 NA x x + Send op condition CMD1 R3 x + All send CID CMD2 R2 x x + Send relative address CMD3 R1 x + Send relative address CMD3 R6 x + Program DSR CMD4 NA x + Select/deselect card CMD7 R1b x + Select/deselect card CMD7 R1 x + Send CSD CMD9 R2 x x + Send CID CMD10 R2 x x + Read data until stop CMD11 R1 x x + Stop transmission CMD12 R1/b x x + Send status CMD13 R1 x x + Go inactive state CMD15 NA x x + Set block length CMD16 R1 x x + Read single block CMD17 R1 x x + Read multiple blocks CMD18 R1 x x + Write data until stop CMD20 R1 x + Setblock count CMD23 R1 x + Write single block CMD24 R1 x x + Write multiple blocks CMD25 R1 x x + Program CID CMD26 R1 x + Program CSD CMD27 R1 x x + Set write protection CMD28 R1b x x + Clear write protection CMD29 R1b x x + Send write protection CMD30 R1 x x + Erase block start CMD32 R1 x + Erase block end CMD33 R1 x + Erase block start CMD35 R1 x + Erase block end CMD36 R1 x + Erase blocks CMD38 R1b x + Fast IO CMD39 R4 x + Go IRQ state CMD40 R5 x + Lock/unlock CMD42 R1b x + Application command CMD55 R1 x + General command CMD56 R1b x + + *** SD card application commands - these must be preceded with *** + *** MMC CMD55 application specific command first *** + Set bus width ACMD6 R1 x + Send SD status ACMD13 R1 x + Send number WR blocks ACMD22 R1 x + Set WR block erase cnt ACMD23 R1 x + Send op condition ACMD41 R3 x + Set clear card detect ACMD42 R1 x + Send CSR ACMD51 R1 x */ + +/** + * @brief SD/MMC application specific commands for SD cards only - these + * must be preceded by the SDMMC CMD55 to work correctly + */ +typedef enum { + SD_SET_BUS_WIDTH, /*!< Set the SD bus width */ + SD_SEND_STATUS, /*!< Send the SD card status */ + SD_SEND_WR_BLOCKS, /*!< Send the number of written clocks */ + SD_SET_ERASE_COUNT, /*!< Set the number of blocks to pre-erase */ + SD_SENDOP_COND, /*!< Send the OCR register (init) */ + SD_CLEAR_CARD_DET, /*!< Set or clear the 50K detect pullup */ + SD_SEND_SCR, /*!< Send the SD configuration register */ + SD_INVALID_APP_CMD /*!< Invalid SD application command */ +} SD_APP_CMD_T; + +/** + * @brief Possible SDMMC response types + */ +typedef enum { + SDMMC_RESPONSE_R1, /*!< Typical status */ + SDMMC_RESPONSE_R1B, /*!< Typical status with busy */ + SDMMC_RESPONSE_R2, /*!< CID/CSD registers (CMD2 and CMD10) */ + SDMMC_RESPONSE_R3, /*!< OCR register (CMD1, ACMD41) */ + SDMMC_RESPONSE_R4, /*!< Fast IO response word */ + SDMMC_RESPONSE_R5, /*!< Go IRQ state response word */ + SDMMC_RESPONSE_R6, /*!< Published RCA response */ + SDMMC_RESPONSE_NONE /*!< No response expected */ +} SDMMC_RESPONSE_T; + +/** + * @brief Possible SDMMC card state types + */ +typedef enum { + SDMMC_IDLE_ST = 0, /*!< Idle state */ + SDMMC_READY_ST, /*!< Ready state */ + SDMMC_IDENT_ST, /*!< Identification State */ + SDMMC_STBY_ST, /*!< standby state */ + SDMMC_TRAN_ST, /*!< transfer state */ + SDMMC_DATA_ST, /*!< Sending-data State */ + SDMMC_RCV_ST, /*!< Receive-data State */ + SDMMC_PRG_ST, /*!< Programming State */ + SDMMC_DIS_ST /*!< Disconnect State */ +} SDMMC_STATE_T; + +/* Function prototype for event setup function */ +typedef void (*SDMMC_EVSETUP_FUNC_T)(void *); + +/* Function prototype for wait for event function */ +typedef uint32_t (*SDMMC_EVWAIT_FUNC_T)(void); + +/* Function prototype for milliSecond delay function */ +typedef void (*SDMMC_MSDELAY_FUNC_T)(uint32_t); + +/** + * @brief SD/MMC Card specific setup data structure + */ +typedef struct { + uint32_t response[4]; /*!< Most recent response */ + uint32_t cid[4]; /*!< CID of acquired card */ + uint32_t csd[4]; /*!< CSD of acquired card */ + uint32_t ext_csd[512 / 4]; /*!< Ext CSD */ + uint32_t card_type; /*!< Card Type */ + uint16_t rca; /*!< Relative address assigned to card */ + uint32_t speed; /*!< Speed */ + uint32_t block_len; /*!< Card sector size */ + uint32_t device_size; /*!< Device Size */ + uint32_t blocknr; /*!< Block Number */ + uint32_t clk_rate; /*! Clock rate */ + SDMMC_EVSETUP_FUNC_T evsetup_cb; /*!< Function to setup event information */ + SDMMC_EVWAIT_FUNC_T waitfunc_cb; /*!< Function to wait for event */ + SDMMC_MSDELAY_FUNC_T msdelay_func; /*!< Function to sleep in ms */ +} SDMMC_CARD_T; + +/** + * @brief SD/MMC commands, arguments and responses + * Standard SD/MMC commands (3.1) type argument response + */ +/* class 1 */ +#define MMC_GO_IDLE_STATE 0 /* bc */ +#define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */ +#define MMC_ALL_SEND_CID 2 /* bcr R2 */ +#define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */ +#define MMC_SET_DSR 4 /* bc [31:16] RCA */ +#define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */ +#define MMC_SEND_EXT_CSD 8 /* bc R1 */ +#define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */ +#define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */ +#define MMC_STOP_TRANSMISSION 12 /* ac R1b */ +#define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */ +#define MMC_GO_INACTIVE_STATE 15 /* ac [31:16] RCA */ + +/* class 2 */ +#define MMC_SET_BLOCKLEN 16 /* ac [31:0] block len R1 */ +#define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */ +#define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */ + +/* class 3 */ +#define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */ + +/* class 4 */ +#define MMC_SET_BLOCK_COUNT 23 /* adtc [31:0] data addr R1 */ +#define MMC_WRITE_BLOCK 24 /* adtc [31:0] data addr R1 */ +#define MMC_WRITE_MULTIPLE_BLOCK 25 /* adtc R1 */ +#define MMC_PROGRAM_CID 26 /* adtc R1 */ +#define MMC_PROGRAM_CSD 27 /* adtc R1 */ + +/* class 6 */ +#define MMC_SET_WRITE_PROT 28 /* ac [31:0] data addr R1b */ +#define MMC_CLR_WRITE_PROT 29 /* ac [31:0] data addr R1b */ +#define MMC_SEND_WRITE_PROT 30 /* adtc [31:0] wpdata addr R1 */ + +/* class 5 */ +#define MMC_ERASE_GROUP_START 35 /* ac [31:0] data addr R1 */ +#define MMC_ERASE_GROUP_END 36 /* ac [31:0] data addr R1 */ +#define MMC_ERASE 37 /* ac R1b */ +#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */ +#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */ +#define SD_ERASE 38 /* ac R1b */ + +/* class 9 */ +#define MMC_FAST_IO 39 /* ac R4 */ +#define MMC_GO_IRQ_STATE 40 /* bcr R5 */ + +/* class 7 */ +#define MMC_LOCK_UNLOCK 42 /* adtc R1b */ + +/* class 8 */ +#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */ +#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1b */ + +/* SD commands type argument response */ +/* class 8 */ +/* This is basically the same command as for MMC with some quirks. */ +#define SD_SEND_RELATIVE_ADDR 3 /* ac R6 */ +#define SD_CMD8 8 /* bcr [31:0] OCR R3 */ + +/* Application commands */ +#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */ +#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R1 (R4) */ +#define SD_APP_SEND_SCR 51 /* adtc R1 */ + +/** + * @brief MMC status in R1
+ * Type
+ * e : error bit
+ * s : status bit
+ * r : detected and set for the actual command response
+ * x : detected and set during command execution. the host must poll + * the card by sending status command in order to read these bits. + * Clear condition
+ * a : according to the card state
+ * b : always related to the previous command. Reception of + * a valid command will clear it (with a delay of one command)
+ * c : clear by read
+ */ + +#define R1_OUT_OF_RANGE (1UL << 31) /* er, c */ +#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */ +#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */ +#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */ +#define R1_ERASE_PARAM (1 << 27) /* ex, c */ +#define R1_WP_VIOLATION (1 << 26) /* erx, c */ +#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */ +#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */ +#define R1_COM_CRC_ERROR (1 << 23) /* er, b */ +#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */ +#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */ +#define R1_CC_ERROR (1 << 20) /* erx, c */ +#define R1_ERROR (1 << 19) /* erx, c */ +#define R1_UNDERRUN (1 << 18) /* ex, c */ +#define R1_OVERRUN (1 << 17) /* ex, c */ +#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */ +#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */ +#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */ +#define R1_ERASE_RESET (1 << 13) /* sr, c */ +#define R1_STATUS(x) (x & 0xFFFFE000) +#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */ +#define R1_READY_FOR_DATA (1 << 8) /* sx, a */ +#define R1_APP_CMD (1 << 5) /* sr, c */ + +/** + * @brief SD/MMC card OCR register bits + */ +#define OCR_ALL_READY (1UL << 31) /* Card Power up status bit */ +#define OCR_HC_CCS (1 << 30) /* High capacity card */ +#define OCR_VOLTAGE_RANGE_MSK (0x00FF8000) + +#define SD_SEND_IF_ARG 0x000001AA +#define SD_SEND_IF_ECHO_MSK 0x000000FF +#define SD_SEND_IF_RESP 0x000000AA + +/** + * @brief R3 response definitions + */ +#define CMDRESP_R3_OCR_VAL(n) (((uint32_t) n) & 0xFFFFFF) +#define CMDRESP_R3_S18A (((uint32_t) 1 ) << 24) +#define CMDRESP_R3_HC_CCS (((uint32_t) 1 ) << 30) +#define CMDRESP_R3_INIT_COMPLETE (((uint32_t) 1 ) << 31) + +/** + * @brief R6 response definitions + */ +#define CMDRESP_R6_RCA_VAL(n) (((uint32_t) (n >> 16)) & 0xFFFF) +#define CMDRESP_R6_CARD_STATUS(n) (((uint32_t) (n & 0x1FFF)) | \ + ((n & (1 << 13)) ? (1 << 19) : 0) | \ + ((n & (1 << 14)) ? (1 << 22) : 0) | \ + ((n & (1 << 15)) ? (1 << 23) : 0)) + +/** + * @brief R7 response definitions + */ +/** Echo-back of check-pattern */ +#define CMDRESP_R7_CHECK_PATTERN(n) (((uint32_t) n ) & 0xFF) +/** Voltage accepted */ +#define CMDRESP_R7_VOLTAGE_ACCEPTED (((uint32_t) 1 ) << 8) + +/** + * @brief CMD3 command definitions + */ +/** Card Address */ +#define CMD3_RCA(n) (((uint32_t) (n & 0xFFFF) ) << 16) + +/** + * @brief CMD7 command definitions + */ +/** Card Address */ +#define CMD7_RCA(n) (((uint32_t) (n & 0xFFFF) ) << 16) + +/** + * @brief CMD8 command definitions + */ +/** Check pattern */ +#define CMD8_CHECKPATTERN(n) (((uint32_t) (n & 0xFF) ) << 0) +/** Recommended pattern */ +#define CMD8_DEF_PATTERN (0xAA) +/** Voltage supplied.*/ +#define CMD8_VOLTAGESUPPLIED_27_36 (((uint32_t) 1 ) << 8) + +/** + * @brief CMD9 command definitions + */ +#define CMD9_RCA(n) (((uint32_t) (n & 0xFFFF) ) << 16) + +/** + * @brief CMD13 command definitions + */ +#define CMD13_RCA(n) (((uint32_t) (n & 0xFFFF) ) << 16) + +/** + * @brief APP_CMD command definitions + */ +#define CMD55_RCA(n) (((uint32_t) (n & 0xFFFF) ) << 16) + +/** + * @brief ACMD41 command definitions + */ +#define ACMD41_OCR(n) (((uint32_t) n) & 0xFFFFFF) +#define ACMD41_S18R (((uint32_t) 1 ) << 24) +#define ACMD41_XPC (((uint32_t) 1 ) << 28) +#define ACMD41_HCS (((uint32_t) 1 ) << 30) + +/** + * @brief ACMD6 command definitions + */ +#define ACMD6_BUS_WIDTH(n) ((uint32_t) n & 0x03) +#define ACMD6_BUS_WIDTH_1 (0) +#define ACMD6_BUS_WIDTH_4 (2) + +/** @brief Card type defines + */ +#define CARD_TYPE_SD (1 << 0) +#define CARD_TYPE_4BIT (1 << 1) +#define CARD_TYPE_8BIT (1 << 2) +#define CARD_TYPE_HC (OCR_HC_CCS)/*!< high capacity card > 2GB */ + +/** + * @brief SD/MMC sector size in bytes + */ +#define MMC_SECTOR_SIZE 512 + +/** + * @brief Typical enumeration clock rate + */ +#define SD_MMC_ENUM_CLOCK 400000 + +/** + * @brief Max MMC clock rate + */ +#define MMC_MAX_CLOCK 20000000 + +/** + * @brief Type 0 MMC card max clock rate + */ +#define MMC_LOW_BUS_MAX_CLOCK 26000000 + +/** + * @brief Type 1 MMC card max clock rate + */ +#define MMC_HIGH_BUS_MAX_CLOCK 52000000 + +/** + * @brief Max SD clock rate + */ +#define SD_MAX_CLOCK 25000000 + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* __SDMMC_H */ diff --git a/lpcapi/sdmmc_18xx_43xx.c b/lpcapi/sdmmc_18xx_43xx.c new file mode 100644 index 00000000..8a954f71 --- /dev/null +++ b/lpcapi/sdmmc_18xx_43xx.c @@ -0,0 +1,596 @@ +/* + * @brief LPC18xx/43xx SD/SDIO driver + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "sdmmc_18xx_43xx.h" +#include "string.h" + +// we lie here so the value calculated doesn't exceed 255. Should still be +// exact enough (~0.5% off) +#define CLK_SPEED 203000000 + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/* Global instance of the current card */ +static mci_card_struct *g_card_info; + +/* Helper definition: all SD error conditions in the status word */ +#define SD_INT_ERROR (MCI_INT_RESP_ERR | MCI_INT_RCRC | MCI_INT_DCRC | \ + MCI_INT_RTO | MCI_INT_DTO | MCI_INT_HTO | MCI_INT_FRUN | MCI_INT_HLE | \ + MCI_INT_SBE | MCI_INT_EBE) + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/* Function to execute a command */ +static int32_t sdmmc_execute_command(LPC_SDMMC_T *pSDMMC, uint32_t cmd, uint32_t arg, uint32_t wait_status) +{ + int32_t step = (cmd & CMD_BIT_APP) ? 2 : 1; + int32_t status = 0; + uint32_t cmd_reg = 0; + + if (!wait_status) { + wait_status = (cmd & CMD_MASK_RESP) ? MCI_INT_CMD_DONE : MCI_INT_DATA_OVER; + } + + /* Clear the interrupts & FIFOs*/ + if (cmd & CMD_BIT_DATA) { + Chip_SDIF_SetClearIntFifo(pSDMMC); + } + + /* also check error conditions */ + wait_status |= MCI_INT_EBE | MCI_INT_SBE | MCI_INT_HLE | MCI_INT_RTO | MCI_INT_RCRC | MCI_INT_RESP_ERR; + if (wait_status & MCI_INT_DATA_OVER) { + wait_status |= MCI_INT_FRUN | MCI_INT_HTO | MCI_INT_DTO | MCI_INT_DCRC; + } + + while (step) { + Chip_SDIF_SetClock(pSDMMC, CLK_SPEED, g_card_info->card_info.speed); + + /* Clear the interrupts */ + Chip_SDIF_ClrIntStatus(pSDMMC, 0xFFFFFFFF); + + g_card_info->card_info.evsetup_cb((void *) &wait_status); + + switch (step) { + case 1: /* Execute command */ + cmd_reg = ((cmd & CMD_MASK_CMD) >> CMD_SHIFT_CMD) | + ((cmd & CMD_BIT_INIT) ? MCI_CMD_INIT : 0) | + ((cmd & CMD_BIT_DATA) ? (MCI_CMD_DAT_EXP | MCI_CMD_PRV_DAT_WAIT) : 0) | + (((cmd & CMD_MASK_RESP) == CMD_RESP_R2) ? MCI_CMD_RESP_LONG : 0) | + ((cmd & CMD_MASK_RESP) ? MCI_CMD_RESP_EXP : 0) | + ((cmd & CMD_BIT_WRITE) ? MCI_CMD_DAT_WR : 0) | + ((cmd & CMD_BIT_STREAM) ? MCI_CMD_STRM_MODE : 0) | + ((cmd & CMD_BIT_BUSY) ? MCI_CMD_STOP : 0) | + ((cmd & CMD_BIT_AUTO_STOP) ? MCI_CMD_SEND_STOP : 0) | + MCI_CMD_START; + + /* wait for previos data finsh for select/deselect commands */ + if (((cmd & CMD_MASK_CMD) >> CMD_SHIFT_CMD) == MMC_SELECT_CARD) { + cmd_reg |= MCI_CMD_PRV_DAT_WAIT; + } + + /* wait for command to be accepted by CIU */ + if (Chip_SDIF_SendCmd(pSDMMC, cmd_reg, arg) == 0) { + --step; + } + break; + + case 0: + return 0; + + case 2: /* APP prefix */ + cmd_reg = MMC_APP_CMD | MCI_CMD_RESP_EXP | + ((cmd & CMD_BIT_INIT) ? MCI_CMD_INIT : 0) | + MCI_CMD_START; + + if (Chip_SDIF_SendCmd(pSDMMC, cmd_reg, g_card_info->card_info.rca << 16) == 0) { + --step; + } + break; + } + + /* wait for command response */ + status = g_card_info->card_info.waitfunc_cb(); + + /* We return an error if there is a timeout, even if we've fetched a response */ + if (status & SD_INT_ERROR) { + return status; + } + + if (status & MCI_INT_CMD_DONE) { + switch (cmd & CMD_MASK_RESP) { + case 0: + break; + + case CMD_RESP_R1: + case CMD_RESP_R3: + case CMD_RESP_R2: + Chip_SDIF_GetResponse(pSDMMC, &g_card_info->card_info.response[0]); + break; + } + } + } + + return 0; +} + +/* Checks whether card is acquired properly or not */ +static int32_t prv_card_acquired(void) +{ + return g_card_info->card_info.cid[0] != 0; +} + +/* Helper function to get a bit field withing multi-word buffer. Used to get + fields with-in CSD & EXT-CSD */ +static uint32_t prv_get_bits(int32_t start, int32_t end, uint32_t *data) +{ + uint32_t v; + uint32_t i = end >> 5; + uint32_t j = start & 0x1f; + + if (i == (start >> 5)) { + v = (data[i] >> j); + } + else { + v = ((data[i] << (32 - j)) | (data[start >> 5] >> j)); + } + + return v & ((1 << (end - start + 1)) - 1); +} + +/* Function to process the CSD & EXT-CSD of the card */ +static void prv_process_csd(LPC_SDMMC_T *pSDMMC) +{ + int32_t status = 0; + int32_t c_size = 0; + int32_t c_size_mult = 0; + int32_t mult = 0; + + /* compute block length based on CSD response */ + g_card_info->card_info.block_len = 1 << prv_get_bits(80, 83, g_card_info->card_info.csd); + + if ((g_card_info->card_info.card_type & CARD_TYPE_HC) && (g_card_info->card_info.card_type & CARD_TYPE_SD)) { + /* See section 5.3.3 CSD Register (CSD Version 2.0) of SD2.0 spec an explanation for the calculation of these values */ + c_size = prv_get_bits(48, 63, (uint32_t *) g_card_info->card_info.csd) + 1; + g_card_info->card_info.blocknr = c_size << 10; /* 512 byte blocks */ + } + else { + /* See section 5.3 of the 4.1 revision of the MMC specs for an explanation for the calculation of these values */ + c_size = prv_get_bits(62, 73, (uint32_t *) g_card_info->card_info.csd); + c_size_mult = prv_get_bits(47, 49, (uint32_t *) g_card_info->card_info.csd); + mult = 1 << (c_size_mult + 2); + g_card_info->card_info.blocknr = (c_size + 1) * mult; + + /* adjust blocknr to 512/block */ + if (g_card_info->card_info.block_len > MMC_SECTOR_SIZE) { + g_card_info->card_info.blocknr = g_card_info->card_info.blocknr * (g_card_info->card_info.block_len >> 9); + } + + /* get extended CSD for newer MMC cards CSD spec >= 4.0*/ + if (((g_card_info->card_info.card_type & CARD_TYPE_SD) == 0) && + (prv_get_bits(122, 125, (uint32_t *) g_card_info->card_info.csd) >= 4)) { + /* put card in trans state */ + status = sdmmc_execute_command(pSDMMC, CMD_SELECT_CARD, g_card_info->card_info.rca << 16, 0); + + /* set block size and byte count */ + Chip_SDIF_SetBlkSizeByteCnt(pSDMMC, MMC_SECTOR_SIZE); + + /* send EXT_CSD command */ + Chip_SDIF_DmaSetup(pSDMMC, + &g_card_info->sdif_dev, + (uint32_t) g_card_info->card_info.ext_csd, + MMC_SECTOR_SIZE); + + status = sdmmc_execute_command(pSDMMC, CMD_SEND_EXT_CSD, 0, 0 | MCI_INT_DATA_OVER); + if ((status & SD_INT_ERROR) == 0) { + /* check EXT_CSD_VER is greater than 1.1 */ + if ((g_card_info->card_info.ext_csd[48] & 0xFF) > 1) { + g_card_info->card_info.blocknr = g_card_info->card_info.ext_csd[53];/* bytes 212:215 represent sec count */ + + } + /* switch to 52MHz clock if card type is set to 1 or else set to 26MHz */ + if ((g_card_info->card_info.ext_csd[49] & 0xFF) == 1) { + /* for type 1 MMC cards high speed is 52MHz */ + g_card_info->card_info.speed = MMC_HIGH_BUS_MAX_CLOCK; + } + else { + /* for type 0 MMC cards high speed is 26MHz */ + g_card_info->card_info.speed = MMC_LOW_BUS_MAX_CLOCK; + } + } + } + } + + g_card_info->card_info.device_size = g_card_info->card_info.blocknr << 9; /* blocknr * 512 */ +} + +/* Puts current selected card in trans state */ +static int32_t prv_set_trans_state(LPC_SDMMC_T *pSDMMC) +{ + uint32_t status; + + /* get current state of the card */ + status = sdmmc_execute_command(pSDMMC, CMD_SEND_STATUS, g_card_info->card_info.rca << 16, 0); + if (status & MCI_INT_RTO) { + /* unable to get the card state. So return immediatly. */ + return -1; + } + + /* check card state in response */ + status = R1_CURRENT_STATE(g_card_info->card_info.response[0]); + switch (status) { + case SDMMC_STBY_ST: + /* put card in 'Trans' state */ + status = sdmmc_execute_command(pSDMMC, CMD_SELECT_CARD, g_card_info->card_info.rca << 16, 0); + if (status != 0) { + /* unable to put the card in Trans state. So return immediatly. */ + return -1; + } + break; + + case SDMMC_TRAN_ST: + /*do nothing */ + break; + + default: + /* card shouldn't be in other states so return */ + return -1; + } + + return 0; +} + +/* Sets card data width and block size */ +static int32_t prv_set_card_params(LPC_SDMMC_T *pSDMMC) +{ + int32_t status; + +#if SDIO_BUS_WIDTH > 1 + if (g_card_info->card_info.card_type & CARD_TYPE_SD) { + status = sdmmc_execute_command(pSDMMC, CMD_SD_SET_WIDTH, 2, 0); + if (status != 0) { + return -1; + } + + /* if positive response */ + Chip_SDIF_SetCardType(pSDMMC, MCI_CTYPE_4BIT); + } +#elif SDIO_BUS_WIDTH > 4 +#error 8-bit mode not supported yet! +#endif + + /* set block length */ + Chip_SDIF_SetBlkSize(pSDMMC, MMC_SECTOR_SIZE); + status = sdmmc_execute_command(pSDMMC, CMD_SET_BLOCKLEN, MMC_SECTOR_SIZE, 0); + if (status != 0) { + return -1; + } + + return 0; +} + +/***************************************************************************** + * Public functions + ****************************************************************************/ +/* Get card's current state (idle, transfer, program, etc.) */ +int32_t Chip_SDMMC_GetState(LPC_SDMMC_T *pSDMMC) +{ + uint32_t status; + + /* get current state of the card */ + status = sdmmc_execute_command(pSDMMC, CMD_SEND_STATUS, g_card_info->card_info.rca << 16, 0); + if (status & MCI_INT_RTO) { + return -1; + } + + /* check card state in response */ + return (int32_t) R1_CURRENT_STATE(g_card_info->card_info.response[0]); +} + +/* Function to enumerate the SD/MMC/SDHC/MMC+ cards */ +uint32_t Chip_SDMMC_Acquire(LPC_SDMMC_T *pSDMMC, mci_card_struct *pcardinfo) +{ + int32_t status; + int32_t tries = 0; + uint32_t ocr = OCR_VOLTAGE_RANGE_MSK; + uint32_t r; + int32_t state = 0; + uint32_t command = 0; + + g_card_info = pcardinfo; + + /* clear card type */ + Chip_SDIF_SetCardType(pSDMMC, 0); + + /* set high speed for the card as 20MHz */ + g_card_info->card_info.speed = MMC_MAX_CLOCK; + + status = sdmmc_execute_command(pSDMMC, CMD_IDLE, 0, MCI_INT_CMD_DONE); + + while (state < 100) { + switch (state) { + case 0: /* Setup for SD */ + /* check if it is SDHC card */ + status = sdmmc_execute_command(pSDMMC, CMD_SD_SEND_IF_COND, SD_SEND_IF_ARG, 0); + if (!(status & MCI_INT_RTO)) { + /* check response has same echo pattern */ + if ((g_card_info->card_info.response[0] & SD_SEND_IF_ECHO_MSK) == SD_SEND_IF_RESP) { + ocr |= OCR_HC_CCS; + } + } + + ++state; + command = CMD_SD_OP_COND; + tries = INIT_OP_RETRIES; + + /* assume SD card */ + g_card_info->card_info.card_type |= CARD_TYPE_SD; + g_card_info->card_info.speed = SD_MAX_CLOCK; + break; + + case 10: /* Setup for MMC */ + /* start fresh for MMC crds */ + g_card_info->card_info.card_type &= ~CARD_TYPE_SD; + status = sdmmc_execute_command(pSDMMC, CMD_IDLE, 0, MCI_INT_CMD_DONE); + command = CMD_MMC_OP_COND; + tries = INIT_OP_RETRIES; + ocr |= OCR_HC_CCS; + ++state; + + /* for MMC cards high speed is 20MHz */ + g_card_info->card_info.speed = MMC_MAX_CLOCK; + break; + + case 1: + case 11: + status = sdmmc_execute_command(pSDMMC, command, 0, 0); + if (status & MCI_INT_RTO) { + state += 9; /* Mode unavailable */ + } + else { + ++state; + } + break; + + case 2: /* Initial OCR check */ + case 12: + ocr = g_card_info->card_info.response[0] | (ocr & OCR_HC_CCS); + if (ocr & OCR_ALL_READY) { + ++state; + } + else { + state += 2; + } + break; + + case 3: /* Initial wait for OCR clear */ + case 13: + while ((ocr & OCR_ALL_READY) && --tries > 0) { + g_card_info->card_info.msdelay_func(MS_ACQUIRE_DELAY); + status = sdmmc_execute_command(pSDMMC, command, 0, 0); + ocr = g_card_info->card_info.response[0] | (ocr & OCR_HC_CCS); + } + if (ocr & OCR_ALL_READY) { + state += 7; + } + else { + ++state; + } + break; + + case 14: + /* for MMC cards set high capacity bit */ + ocr |= OCR_HC_CCS; + + case 4: /* Assign OCR */ + tries = SET_OP_RETRIES; + ocr &= OCR_VOLTAGE_RANGE_MSK | OCR_HC_CCS; /* Mask for the bits we care about */ + do { + g_card_info->card_info.msdelay_func(MS_ACQUIRE_DELAY); + status = sdmmc_execute_command(pSDMMC, command, ocr, 0); + r = g_card_info->card_info.response[0]; + } while (!(r & OCR_ALL_READY) && --tries > 0); + + if (r & OCR_ALL_READY) { + /* is it high capacity card */ + g_card_info->card_info.card_type |= (r & OCR_HC_CCS); + ++state; + } + else { + state += 6; + } + break; + + case 5: /* CID polling */ + case 15: + status = sdmmc_execute_command(pSDMMC, CMD_ALL_SEND_CID, 0, 0); + memcpy(&g_card_info->card_info.cid, &g_card_info->card_info.response[0], 16); + ++state; + break; + + case 6: /* RCA send, for SD get RCA */ + status = sdmmc_execute_command(pSDMMC, CMD_SD_SEND_RCA, 0, 0); + g_card_info->card_info.rca = (g_card_info->card_info.response[0]) >> 16; + ++state; + break; + + case 16: /* RCA assignment for MMC set to 1 */ + g_card_info->card_info.rca = 1; + status = sdmmc_execute_command(pSDMMC, CMD_MMC_SET_RCA, g_card_info->card_info.rca << 16, 0); + ++state; + break; + + case 7: + case 17: + status = sdmmc_execute_command(pSDMMC, CMD_SEND_CSD, g_card_info->card_info.rca << 16, 0); + memcpy(&g_card_info->card_info.csd, &g_card_info->card_info.response[0], 16); + state = 100; + break; + + default: + state += 100; /* break from while loop */ + break; + } + } + + /* Compute card size, block size and no. of blocks based on CSD response recived. */ + if (prv_card_acquired()) { + prv_process_csd(pSDMMC); + + /* Setup card data width and block size (once) */ + if (prv_set_trans_state(pSDMMC) != 0) { + return 0; + } + if (prv_set_card_params(pSDMMC) != 0) { + return 0; + } + } + + return prv_card_acquired(); +} + +/* Get the device size of SD/MMC card (after enumeration) */ +int32_t Chip_SDMMC_GetDeviceSize(LPC_SDMMC_T *pSDMMC) +{ + return g_card_info->card_info.device_size; +} + +/* Get the number of blocks in SD/MMC card (after enumeration) */ +int32_t Chip_SDMMC_GetDeviceBlocks(LPC_SDMMC_T *pSDMMC) +{ + return g_card_info->card_info.blocknr; +} + +/* Performs the read of data from the SD/MMC card */ +int32_t Chip_SDMMC_ReadBlocks(LPC_SDMMC_T *pSDMMC, void *buffer, int32_t start_block, int32_t num_blocks) +{ + int32_t cbRead = (num_blocks) * MMC_SECTOR_SIZE; + int32_t status = 0; + int32_t index; + + /* if card is not acquired return immediately */ + if (( start_block < 0) || ( (start_block + num_blocks) > g_card_info->card_info.blocknr) ) { + return 0; + } + + /* put card in trans state */ + if (prv_set_trans_state(pSDMMC) != 0) { + return 0; + } + + /* set number of bytes to read */ + Chip_SDIF_SetByteCnt(pSDMMC, cbRead); + + /* if high capacity card use block indexing */ + if (g_card_info->card_info.card_type & CARD_TYPE_HC) { + index = start_block; + } + else { /*fix at 512 bytes*/ + index = start_block << 9; // \* g_card_info->card_info.block_len; + + } + Chip_SDIF_DmaSetup(pSDMMC, &g_card_info->sdif_dev, (uint32_t) buffer, cbRead); + + /* Select single or multiple read based on number of blocks */ + if (num_blocks == 1) { + status = sdmmc_execute_command(pSDMMC, CMD_READ_SINGLE, index, 0 | MCI_INT_DATA_OVER); + } + else { + status = sdmmc_execute_command(pSDMMC, CMD_READ_MULTIPLE, index, 0 | MCI_INT_DATA_OVER); + } + + if (status != 0) { + cbRead = 0; + } + /*Wait for card program to finish*/ + while (Chip_SDMMC_GetState(pSDMMC) != SDMMC_TRAN_ST) {} + + return cbRead; +} + +/* Performs write of data to the SD/MMC card */ +int32_t Chip_SDMMC_WriteBlocks(LPC_SDMMC_T *pSDMMC, void *buffer, int32_t start_block, int32_t num_blocks) +{ + int32_t cbWrote = num_blocks * MMC_SECTOR_SIZE; + int32_t status; + int32_t index; + + /* if card is not acquired return immediately */ + if (( start_block < 0) || ( (start_block + num_blocks) > g_card_info->card_info.blocknr) ) { + return 0; + } + + /*Wait for card program to finish*/ + while (Chip_SDMMC_GetState(pSDMMC) != SDMMC_TRAN_ST) {} + + /* put card in trans state */ + if (prv_set_trans_state(pSDMMC) != 0) { + return 0; + } + + /* set number of bytes to write */ + Chip_SDIF_SetByteCnt(pSDMMC, cbWrote); + + /* if high capacity card use block indexing */ + if (g_card_info->card_info.card_type & CARD_TYPE_HC) { + index = start_block; + } + else { /*fix at 512 bytes*/ + index = start_block << 9; // * g_card_info->card_info.block_len; + + } + + Chip_SDIF_DmaSetup(pSDMMC, &g_card_info->sdif_dev, (uint32_t) buffer, cbWrote); + + /* Select single or multiple write based on number of blocks */ + if (num_blocks == 1) { + status = sdmmc_execute_command(pSDMMC, CMD_WRITE_SINGLE, index, 0 | MCI_INT_DATA_OVER); + } + else { + status = sdmmc_execute_command(pSDMMC, CMD_WRITE_MULTIPLE, index, 0 | MCI_INT_DATA_OVER); + } + + /*Wait for card program to finish*/ + while (Chip_SDMMC_GetState(pSDMMC) != SDMMC_TRAN_ST) {} + + if (status != 0) { + cbWrote = 0; + } + + return cbWrote; +} diff --git a/lpcapi/sdmmc_18xx_43xx.h b/lpcapi/sdmmc_18xx_43xx.h new file mode 100644 index 00000000..68ceec08 --- /dev/null +++ b/lpcapi/sdmmc_18xx_43xx.h @@ -0,0 +1,153 @@ +/* + * @brief LPC18xx/43xx SD/MMC card driver + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __SDMMC_18XX_43XX_H_ +#define __SDMMC_18XX_43XX_H_ + +#include +#include "sdmmc.h" +#include "sdif_18xx_43xx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup SDMMC_18XX_43XX CHIP: LPC18xx/43xx SD/MMC driver + * @ingroup CHIP_18XX_43XX_Drivers + * @{ + */ + +#define CMD_MASK_RESP (0x3UL << 28) +#define CMD_RESP(r) (((r) & 0x3) << 28) +#define CMD_RESP_R0 (0 << 28) +#define CMD_RESP_R1 (1 << 28) +#define CMD_RESP_R2 (2 << 28) +#define CMD_RESP_R3 (3 << 28) +#define CMD_BIT_AUTO_STOP (1 << 24) +#define CMD_BIT_APP (1 << 23) +#define CMD_BIT_INIT (1 << 22) +#define CMD_BIT_BUSY (1 << 21) +#define CMD_BIT_LS (1 << 20) /* Low speed, used during acquire */ +#define CMD_BIT_DATA (1 << 19) +#define CMD_BIT_WRITE (1 << 18) +#define CMD_BIT_STREAM (1 << 17) +#define CMD_MASK_CMD (0xff) +#define CMD_SHIFT_CMD (0) + +#define CMD(c, r) ( ((c) & CMD_MASK_CMD) | CMD_RESP((r)) ) + +#define CMD_IDLE CMD(MMC_GO_IDLE_STATE, 0) | CMD_BIT_LS | CMD_BIT_INIT +#define CMD_SD_OP_COND CMD(SD_APP_OP_COND, 1) | CMD_BIT_LS | CMD_BIT_APP +#define CMD_SD_SEND_IF_COND CMD(SD_CMD8, 1) | CMD_BIT_LS +#define CMD_MMC_OP_COND CMD(MMC_SEND_OP_COND, 3) | CMD_BIT_LS | CMD_BIT_INIT +#define CMD_ALL_SEND_CID CMD(MMC_ALL_SEND_CID, 2) | CMD_BIT_LS +#define CMD_MMC_SET_RCA CMD(MMC_SET_RELATIVE_ADDR, 1) | CMD_BIT_LS +#define CMD_SD_SEND_RCA CMD(SD_SEND_RELATIVE_ADDR, 1) | CMD_BIT_LS +#define CMD_SEND_CSD CMD(MMC_SEND_CSD, 2) | CMD_BIT_LS +#define CMD_SEND_EXT_CSD CMD(MMC_SEND_EXT_CSD, 1) | CMD_BIT_LS | CMD_BIT_DATA +#define CMD_DESELECT_CARD CMD(MMC_SELECT_CARD, 0) +#define CMD_SELECT_CARD CMD(MMC_SELECT_CARD, 1) +#define CMD_SET_BLOCKLEN CMD(MMC_SET_BLOCKLEN, 1) +#define CMD_SEND_STATUS CMD(MMC_SEND_STATUS, 1) +#define CMD_READ_SINGLE CMD(MMC_READ_SINGLE_BLOCK, 1) | CMD_BIT_DATA +#define CMD_READ_MULTIPLE CMD(MMC_READ_MULTIPLE_BLOCK, 1) | CMD_BIT_DATA | CMD_BIT_AUTO_STOP +#define CMD_SD_SET_WIDTH CMD(SD_APP_SET_BUS_WIDTH, 1) | CMD_BIT_APP +#define CMD_STOP CMD(MMC_STOP_TRANSMISSION, 1) | CMD_BIT_BUSY +#define CMD_WRITE_SINGLE CMD(MMC_WRITE_BLOCK, 1) | CMD_BIT_DATA | CMD_BIT_WRITE +#define CMD_WRITE_MULTIPLE CMD(MMC_WRITE_MULTIPLE_BLOCK, 1) | CMD_BIT_DATA | CMD_BIT_WRITE | CMD_BIT_AUTO_STOP + +/* Card specific setup data */ +typedef struct _mci_card_struct { + sdif_device sdif_dev; + SDMMC_CARD_T card_info; +} mci_card_struct; + +/** + * @brief Get card's current state (idle, transfer, program, etc.) + * @param pSDMMC : SDMMC peripheral selected + * @return Current SD card transfer state + */ +int32_t Chip_SDMMC_GetState(LPC_SDMMC_T *pSDMMC); + +/** + * @brief Function to enumerate the SD/MMC/SDHC/MMC+ cards + * @param pSDMMC : SDMMC peripheral selected + * @param pcardinfo : Pointer to pre-allocated card info structure + * @return 1 if a card is acquired, otherwise 0 + */ +uint32_t Chip_SDMMC_Acquire(LPC_SDMMC_T *pSDMMC, mci_card_struct *pcardinfo); + +/** + * @brief Get the device size of SD/MMC card (after enumeration) + * @param pSDMMC : SDMMC peripheral selected + * @return Card size in number of bytes (capacity) + */ +int32_t Chip_SDMMC_GetDeviceSize(LPC_SDMMC_T *pSDMMC); + +/** + * @brief Get the number of device blocks of SD/MMC card (after enumeration) + * Since Chip_SDMMC_GetDeviceSize is limited to 32 bits cards with greater than + * 2 GBytes of data will not be correct, in such cases users can use this function + * to get the size of the card in blocks. + * @param pSDMMC : SDMMC peripheral selected + * @return Number of 512 bytes blocks in the card + */ +int32_t Chip_SDMMC_GetDeviceBlocks(LPC_SDMMC_T *pSDMMC); + +/** + * @brief Performs the read of data from the SD/MMC card + * @param pSDMMC : SDMMC peripheral selected + * @param buffer : Pointer to data buffer to copy to + * @param start_block : Start block number + * @param num_blocks : Number of block to read + * @return Bytes read, or 0 on error + */ +int32_t Chip_SDMMC_ReadBlocks(LPC_SDMMC_T *pSDMMC, void *buffer, int32_t start_block, int32_t num_blocks); + +/** + * @brief Performs write of data to the SD/MMC card + * @param pSDMMC : SDMMC peripheral selected + * @param buffer : Pointer to data buffer to copy to + * @param start_block : Start block number + * @param num_blocks : Number of block to write + * @return Number of bytes actually written, or 0 on error + */ +int32_t Chip_SDMMC_WriteBlocks(LPC_SDMMC_T *pSDMMC, void *buffer, int32_t start_block, int32_t num_blocks); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __SDMMC_18XX_43XX_H_ */ diff --git a/lpcapi/sys_config.h b/lpcapi/sys_config.h new file mode 100644 index 00000000..0c77935a --- /dev/null +++ b/lpcapi/sys_config.h @@ -0,0 +1,36 @@ +/* + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __SYS_CONFIG_H_ +#define __SYS_CONFIG_H_ + +/* LPC43xx chip family */ +#define CHIP_LPC43XX + +#endif /* __SYS_CONFIG_H_ */ diff --git a/rad1olib/pins.h b/rad1olib/pins.h index 453e2de1..963246c8 100644 --- a/rad1olib/pins.h +++ b/rad1olib/pins.h @@ -98,4 +98,14 @@ #define UART0_TXD P2_0, SCU_CONF_FUNCTION1|SCU_UART_RX_TX #define UART0_RXD P2_1, SCU_CONF_FUNCTION1|SCU_UART_RX_TX +#define SD_CD P1_13, SCU_GPIO_PUP|SCU_CONF_FUNCTION7 +//unused? +//#define SD_POW P1_5, +#define SD_CMD P1_6, SCU_GPIO_FAST|SCU_CONF_FUNCTION7 +#define SD_CLK CLK0, SCU_CLK_OUT|SCU_CONF_FUNCTION4 +#define SD_DAT0 P1_9, SCU_GPIO_PUP|SCU_CONF_FUNCTION7 +#define SD_DAT1 P1_10, SCU_GPIO_PUP|SCU_CONF_FUNCTION7 +#define SD_DAT2 P1_11, SCU_GPIO_PUP|SCU_CONF_FUNCTION7 +#define SD_DAT3 P1_12, SCU_GPIO_PUP|SCU_CONF_FUNCTION7 + #endif /* _PIN_H */ diff --git a/rad1olib/sdmmc.c b/rad1olib/sdmmc.c new file mode 100644 index 00000000..dc410b44 --- /dev/null +++ b/rad1olib/sdmmc.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include +#include +#include + +static volatile int32_t sdio_wait_exit = 0; + +/** + * @brief SDIO controller interrupt handler + * @return Nothing + */ +void sdio_isr(void) +{ + /* All SD based register handling is done in the callback + function. The SDIO interrupt is not enabled as part of this + driver and needs to be enabled/disabled in the callbacks or + application as needed. This is to allow flexibility with IRQ + handling for applicaitons and RTOSes. */ + /* Set wait exit flag to tell wait function we are ready. In an RTOS, + this would trigger wakeup of a thread waiting for the IRQ. */ + NVIC_DisableIRQ(SDIO_IRQn); + sdio_wait_exit = 1; +} + +/* Delay callback for timed SDIF/SDMMC functions */ +static void sdmmc_waitms(uint32_t time) +{ + delayms(time); + return; +} + +/** + * @brief Sets up the SD event driven wakeup + * @param bits : Status bits to poll for command completion + * @return Nothing + */ +static void sdmmc_setup_wakeup(void *bits) +{ + uint32_t bit_mask = *((uint32_t *)bits); + /* Wait for IRQ - for an RTOS, you would pend on an event here with a IRQ based wakeup. */ + NVIC_ClearPendingIRQ(SDIO_IRQn); + sdio_wait_exit = 0; + Chip_SDIF_SetIntMask(LPC_SDMMC, bit_mask); + NVIC_EnableIRQ(SDIO_IRQn); +} + +/** + * @brief A better wait callback for SDMMC driven by the IRQ flag + * @return 0 on success, or failure condition (-1) + */ +static uint32_t sdmmc_irq_driven_wait(void) +{ + uint32_t status; + + /* Wait for event, would be nice to have a timeout, but keep it simple */ + while (sdio_wait_exit == 0) {} + + /* Get status and clear interrupts */ + status = Chip_SDIF_GetIntStatus(LPC_SDMMC); + Chip_SDIF_ClrIntStatus(LPC_SDMMC, status); + Chip_SDIF_SetIntMask(LPC_SDMMC, 0); + + return status; +} + +void sdmmc_setup(void) { + SETUPpin(SD_CD); + SETUPpin(SD_CLK); + SETUPpin(SD_CMD); + SETUPpin(SD_DAT0); + SETUPpin(SD_DAT1); + SETUPpin(SD_DAT2); + SETUPpin(SD_DAT3); + + // enable clock line for SD/MMC block + CGU_BASE_SDIO_CLK = CGU_BASE_SDIO_CLK_AUTOBLOCK(1) | + CGU_BASE_SDIO_CLK_CLK_SEL(CGU_SRC_PLL1); + + NVIC_DisableIRQ(SDIO_IRQn); + /* Enable SD/MMC Interrupt */ + NVIC_EnableIRQ(SDIO_IRQn); + + Chip_SDIF_Init(LPC_SDMMC); +} + +static mci_card_struct sdcardinfo; + +uint32_t sdmmc_acquire(void) { + memset(&sdcardinfo, 0, sizeof(sdcardinfo)); + sdcardinfo.card_info.evsetup_cb = sdmmc_setup_wakeup; + sdcardinfo.card_info.waitfunc_cb = sdmmc_irq_driven_wait; + sdcardinfo.card_info.msdelay_func = sdmmc_waitms; + return Chip_SDMMC_Acquire(LPC_SDMMC, &sdcardinfo); +} diff --git a/rad1olib/sdmmc.h b/rad1olib/sdmmc.h new file mode 100644 index 00000000..a8474d51 --- /dev/null +++ b/rad1olib/sdmmc.h @@ -0,0 +1,6 @@ +#ifndef _SDMMC_RAD1O_H +#define _SDMMC_RAD1O_H + +void sdmmc_setup(void); +uint32_t sdmmc_acquire(void); +#endif // _SDMMC_RAD1O_H diff --git a/sdapp/Makefile b/sdapp/Makefile new file mode 100644 index 00000000..08012e0b --- /dev/null +++ b/sdapp/Makefile @@ -0,0 +1,74 @@ +APP=sdapp + +# our code +OBJS = +OBJS += ../rad1olib/setup.o +OBJS += ../r0ketlib/display.o +OBJS += ../r0ketlib/render.o +OBJS += ../r0ketlib/fonts/smallfonts.o +OBJS += ../r0ketlib/fonts/orbitron14.o +OBJS += ../r0ketlib/fonts/ubuntu18.o +OBJS += ../r0ketlib/decoder.o +OBJS += ../r0ketlib/print.o +OBJS += ../r0ketlib/itoa.o +OBJS += ../r0ketlib/keyin.o +OBJS += ../r0ketlib/menu.o +OBJS += ../rad1olib/spi-flash.o +OBJS += ../rad1olib/assert.o +OBJS += ../rad1olib/systick.o +OBJS += ../fatfs/diskio.o +OBJS += ../fatfs/ff.o +OBJS += ../r0ketlib/select.o +OBJS += ../r0ketlib/idle.o +OBJS += ../r0ketlib/fs_util.o +OBJS += ../r0ketlib/execute.o +OBJS += ../r0ketlib/config.o +OBJS += ../r0ketlib/stringin.o +OBJS += ../r0ketlib/colorin.o +OBJS += ../r0ketlib/intin.o +OBJS += ../r0ketlib/random.o +OBJS += ../r0ketlib/image.o +OBJS += ../r0ketlib/mesh.o +OBJS += ../r0ketlib/night.o +OBJS += ../hackrf/firmware/common/w25q80bv.o +OBJS += ../lpcapi/msc/msc_desc.o +OBJS += ../lpcapi/msc/msc_main.o +#OBJS += ../lpcapi/msc/msc_ram.o +OBJS += ../lpcapi/usbd_common.o # MUST be before hackrf usb.o, because of USB0_IRQ selection +OBJS += ../hackrf/firmware/common/usb.o +#OBJS += ../lpcapi/cdc/cdc_desc.o +#OBJS += ../lpcapi/cdc/cdc_main.o +#OBJS += ../lpcapi/cdc/cdc_vcom.o +OBJS += ../rad1olib/light_ws2812_cortex.o +OBJS += ../rad1olib/battery.o +OBJS += ../rad1olib/draw.o +OBJS += ../rad1olib/colorspace.o + + +SRCS = $(wildcard *.c) +SOBJS = $(foreach mod,$(SRCS),$(subst .c,.o,$(mod))) + +OBJS += $(SOBJS) + +CFLAGS=-Wno-unused-variable -DRAD1O -DLPC43XX_M4 -DCORE_M4 -I. + +CFLAGS+=-DCFG_HAVE_SD +OBJS += ../rad1olib/sdmmc.o +OBJS += ../lpcapi/clock_18xx_43xx.o +OBJS += ../lpcapi/sdif_18xx_43xx.o +OBJS += ../lpcapi/sdmmc_18xx_43xx.o + +CFLAGS+=-I../hackrf/firmware/common +LIBS += -lm + +LDSCRIPT=../ld/app.ld +RPATH=.. +include ../Makefile.inc + +main.o: main.gen + +main.gen: $(SRCS) + ../tools/mkfirmware.pl $(SRCS) > main.gen + +clean:: + $(RM) main.gen diff --git a/sdapp/main.c b/sdapp/main.c new file mode 100644 index 00000000..38563df5 --- /dev/null +++ b/sdapp/main.c @@ -0,0 +1,59 @@ +/* + * This file is part of rad1o + * + */ + + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "main.gen" + +void sys_tick_handler(void){ + incTimer(); + generated_tick(); +}; + +int main(void) { + cpuClockInit(); /* CPU Clock is now 104 MHz */ + systickInit(); + +// cpu_clock_set(204); + + SETUPgout(EN_VDD); + SETUPgout(EN_1V8); + SETUPgout(MIXER_EN); + SETUPgout(MIC_AMP_DIS); + + SETUPgout(LED1); + SETUPgout(LED2); + SETUPgout(LED3); + SETUPgout(LED4); + + inputInit(); + lcdInit(); + fsInit(); + lcdFill(0xff); + readConfig(); + + generated_init(); + + while(1){ +// if(getInput()){ + handleMenu(&menu_main); + getInputWaitRelease(); +// }; +// fancyNickname(); + }; + return 0; +} diff --git a/sdapp/msc_main.c b/sdapp/msc_main.c new file mode 100644 index 00000000..75704060 --- /dev/null +++ b/sdapp/msc_main.c @@ -0,0 +1,93 @@ +/* + * @brief This file contains a USB MSC RAM example using USB ROM Drivers. + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int SD_MSCenable(void){ + USBD_API_INIT_PARAM_T usb_param; + USB_CORE_DESCS_T desc; + ErrorCode_t ret = LPC_OK; + USB_CORE_CTRL_T *pCtrl; + + usb_clock_init(); + + usb_phy_enable(); + + /* Init USB API structure */ + g_pUsbApi = (const USBD_API_T *) LPC_ROM_API->usbdApiBase; + + /* initialize call back structures */ + memset((void *) &usb_param, 0, sizeof(USBD_API_INIT_PARAM_T)); + usb_param.usb_reg_base = LPC_USB_BASE; + usb_param.mem_base = USB_STACK_MEM_BASE; + usb_param.mem_size = USB_STACK_MEM_SIZE; + usb_param.max_num_ep = 2; + + /* Set the USB descriptors */ + desc.device_desc = (uint8_t *) USB_msc_DeviceDescriptor; + desc.string_desc = (uint8_t *) USB_msc_StringDescriptor; + + desc.high_speed_desc = USB_msc_HsConfigDescriptor; + desc.full_speed_desc = USB_msc_FsConfigDescriptor; + desc.device_qualifier = (uint8_t *) USB_msc_DeviceQualifier; + + /* USB Initialization */ + ret = USBD_API->hw->Init(&g_hUsb, &desc, &usb_param); + if (ret == LPC_OK) { + /* WORKAROUND for artf45032 ROM driver BUG: + Due to a race condition there is the chance that a second NAK event will + occur before the default endpoint0 handler has completed its preparation + of the DMA engine for the first NAK event. This can cause certain fields + in the DMA descriptors to be in an invalid state when the USB controller + reads them, thereby causing a hang. + */ + pCtrl = (USB_CORE_CTRL_T *) g_hUsb; /* convert the handle to control structure */ + g_Ep0BaseHdlr = pCtrl->ep_event_hdlr[0];/* retrieve the default EP0_OUT handler */ + pCtrl->ep_event_hdlr[0] = EP0_patch;/* set our patch routine as EP0_OUT handler */ + + ret = sd_msc_init(g_hUsb, &desc, &usb_param); + if (ret == LPC_OK) { + /* enable USB interrrupts */ + nvic_enable_irq(NVIC_USB0_IRQ); + /* now connect */ + USBD_API->hw->Connect(g_hUsb, 1); + return 0; + } + } + return 1; +} diff --git a/sdapp/msc_main.h b/sdapp/msc_main.h new file mode 100644 index 00000000..c1afc27d --- /dev/null +++ b/sdapp/msc_main.h @@ -0,0 +1,4 @@ +#ifndef _SDCARD_MSC_MAIN_H +#define _SDCARD_MSC_MAIN_H +int SD_MSCenable(void); +#endif // _SDCARD_MSC_MAIN_H diff --git a/sdapp/msc_sdcard.c b/sdapp/msc_sdcard.c new file mode 100644 index 00000000..e90df27d --- /dev/null +++ b/sdapp/msc_sdcard.c @@ -0,0 +1,169 @@ +/* vim: set ts=4 sw=4 expandtab: */ +/* + * @brief File contains callback to MSC driver backed by a memory disk. + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ +static const uint8_t g_InquiryStr[] = {'R', 'A', 'D', '1', 'O', ' ', ' ', ' ', \ + 'S', 'D', ' ', 'M', 'M', 'C', ' ', ' ', \ + 'D', 'i', 's', 'k', ' ', ' ', ' ', ' ', \ + '1', '.', '0', ' ', }; +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ +static uint8_t *disk_buffer = (uint8_t *) BUFFER_BASE; + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/* USB device mass storage class read callback routine */ +static void sd_rd(uint32_t offset, uint8_t * *buff_adr, uint32_t length, uint32_t hi_offset) +{ + uint8_t buf[512]; + if(((offset & 0x1FF) == 0) && ((length & 0x1FF) == 0)) { +#ifdef I_FIXED_THE_BROKEN_64BIT_OFFSETS + const int64_t o64 = (int64_t)offset | ((int64_t)hi_offset << 32); +#else + const int64_t o64 = (int64_t)offset; +#endif + const uint32_t block = o64>>9; + TOGGLE(LED2); + Chip_SDMMC_ReadBlocks(LPC_SDMMC, *buff_adr, block, length>>9); + TOGGLE(LED2); + //*buff_adr = disk_buffer; + } else { + TOGGLE(LED4); + } +} + +/* USB device mass storage class write callback routine */ +static void sd_wr(uint32_t offset, uint8_t * *buff_adr, uint32_t length, uint32_t hi_offset) +{ + if(((offset & 0x1FF) == 0) && ((length & 0x1FF) == 0)) { +#ifdef I_FIXED_THE_BROKEN_64BIT_OFFSETS + const int64_t o64 = (int64_t)offset | ((int64_t)hi_offset << 32); +#else + const int64_t o64 = (int64_t)offset; +#endif + const uint32_t block = o64>>9; + TOGGLE(LED2); + Chip_SDMMC_WriteBlocks(LPC_SDMMC, *buff_adr, block, length>>9); + TOGGLE(LED2); + } else { + TOGGLE(LED4); + } +} + +/* USB device mass storage class verify callback routine */ +static ErrorCode_t sd_verify(uint32_t offset, uint8_t *src, uint32_t length, uint32_t hi_offset) +{ + uint8_t buf[512]; + if(((offset & 0x1FF) == 0) && ((length & 0x1FF) == 0)) { +#ifdef I_FIXED_THE_BROKEN_64BIT_OFFSETS + int64_t o64 = (int64_t)offset | ((int64_t)hi_offset << 32); +#else + int64_t o64 = (int64_t)offset; +#endif + while(length > 0) { + const uint32_t block = o64>>9; + TOGGLE(LED2); + Chip_SDMMC_ReadBlocks(LPC_SDMMC, buf, o64>>9, 1); + TOGGLE(LED2); + if (memcmp((void *) buf, src, 512)) { + return ERR_FAILED; + } + length -= 512; + o64 += 512; + src += 512; + } + return LPC_OK; + } else { + return ERR_FAILED; + } +} + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Memory storage based MSC_Disk init routine */ +ErrorCode_t sd_msc_init(USBD_HANDLE_T hUsb, USB_CORE_DESCS_T *pDesc, USBD_API_INIT_PARAM_T *pUsbParam) +{ + USBD_MSC_INIT_PARAM_T msc_param; + ErrorCode_t ret = LPC_OK; + + memset((void *) &msc_param, 0, sizeof(USBD_MSC_INIT_PARAM_T)); + msc_param.mem_base = pUsbParam->mem_base; + msc_param.mem_size = pUsbParam->mem_size; + /* mass storage paramas */ + msc_param.InquiryStr = (uint8_t *) g_InquiryStr; + msc_param.BlockSize = 512; + uint32_t blocks = Chip_SDMMC_GetDeviceBlocks(LPC_SDMMC); +#ifdef I_FIXED_THE_BROKEN_64BIT_OFFSETS + msc_param.MemorySize = (blocks < (1<<23)) ? blocks<<9 : 0xFFFFFFFF; + msc_param.MemorySize64 = 512ULL * blocks; + msc_param.BlockCount = blocks; +#else + msc_param.MemorySize = (blocks < (1<<23)) ? blocks<<9 : 0xFFFFFE00; + msc_param.BlockCount = (blocks < (1<<23)) ? blocks : ((1<<23)-1); +#endif + /* Install memory storage callback routines */ + msc_param.MSC_Write = sd_wr; + msc_param.MSC_Read = sd_rd; + msc_param.MSC_Verify = sd_verify; + msc_param.MSC_GetWriteBuf = NULL; + msc_param.intf_desc = (uint8_t *) find_IntfDesc(pDesc->high_speed_desc, USB_DEVICE_CLASS_STORAGE); + + ret = USBD_API->msc->init(hUsb, &msc_param); + /* update memory variables */ + pUsbParam->mem_base = msc_param.mem_base; + pUsbParam->mem_size = msc_param.mem_size; + + return ret; +} diff --git a/sdapp/msc_sdcard.h b/sdapp/msc_sdcard.h new file mode 100644 index 00000000..de5b0183 --- /dev/null +++ b/sdapp/msc_sdcard.h @@ -0,0 +1,66 @@ +/* + * @brief Programming API used with MSC disk + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __MSC_SDCARD_H_ +#define __MSC_SDCARD_H_ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @ingroup EXAMPLES_USBDROM_18XX43XX_MSC_RAM + * @{ + */ + +/* Mass Storage Memory Layout */ +#define BUFFER_BASE 0x2000C000 + +/** + * @brief MSC disk init routine + * @param hUsb : Handle to USBD stack instance + * @param pDesc : Pointer to configuration descriptor + * @param pUsbParam : Pointer USB param structure returned by previous init call + * @return Always returns LPC_OK. + */ +ErrorCode_t sd_msc_init(USBD_HANDLE_T hUsb, USB_CORE_DESCS_T *pDesc, USBD_API_INIT_PARAM_T *pUsbParam); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __MSC_DISK_H_ */ diff --git a/sdapp/perf.c b/sdapp/perf.c new file mode 100644 index 00000000..ef8f3d4a --- /dev/null +++ b/sdapp/perf.c @@ -0,0 +1,101 @@ +#include +#include +#include +#include + +#include + +#include +#include + +static FATFS SDFatFs; /* File system object for logical drive */ +static uint8_t buf[1024]; +//# MENU perf +void menu_perf(void){ + lcdClear(); + + lcdPrintln("Mounting FAT FS"); + lcdDisplay(); + + FRESULT res; + res=f_mount(&SDFatFs,"1:",1); + if(res != FR_OK){ + lcdPrintln("FS init error"); + lcdPrintln(f_get_rc_string(res)); + lcdDisplay(); + getInputWait(); + return; + }; + + FIL file; + UINT bytes; + + res=f_open(&file, "1:perf.tst", FA_CREATE_ALWAYS|FA_WRITE); + if(res){ + lcdPrintln("f_open error"); + lcdPrintln(f_get_rc_string(res)); + lcdDisplay(); + getInputWait(); + return; + }; + + lcdPrintln("testing write perf"); + lcdDisplay(); + uint32_t write_t = _timectr; + + for(int i=100*1024; i>0; i--) { + res = f_write(&file, buf, 1024, &bytes); + if(res){ + lcdPrintln("f_write error"); + lcdPrintln(f_get_rc_string(res)); + lcdDisplay(); + getInputWait(); + return; + }; + } + write_t = _timectr - write_t; + f_close(&file); + + lcdPrintln("ms to write 100MB:"); + lcdPrintln(IntToStr(write_t, 10, 0)); + lcdDisplay(); + + res=f_open(&file, "1:perf.tst", FA_OPEN_EXISTING|FA_READ); + if(res){ + lcdPrintln("f_open error"); + lcdPrintln(f_get_rc_string(res)); + lcdDisplay(); + getInputWait(); + return; + }; + + lcdPrintln("testing read perf"); + lcdDisplay(); + uint32_t read_t = _timectr; + + for(int i=100*1024; i>0; i--) { + res = f_read(&file, buf, 1024, &bytes); + if(res){ + lcdPrintln("f_read error"); + lcdPrintln(f_get_rc_string(res)); + lcdDisplay(); + getInputWait(); + return; + }; + } + write_t = _timectr - write_t; + f_close(&file); + + lcdPrintln("ms to read 100MB:"); + lcdPrintln(IntToStr(write_t, 10, 0)); + lcdPrintln("Done, press button"); + lcdDisplay(); + + while(getInputRaw()==BTN_NONE){ + /* wait */ + __asm__ volatile ("nop"); + }; + + lcdPrintln("goodbye!"); + lcdDisplay(); +} diff --git a/sdapp/rawperf.c b/sdapp/rawperf.c new file mode 100644 index 00000000..4954d7a1 --- /dev/null +++ b/sdapp/rawperf.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +static uint8_t buf[4096]; +//# MENU rawperf +void menu_rawperf(void){ + lcdClear(); + + sdmmc_setup(); + uint32_t r = sdmmc_acquire(); + + if(!r) { + lcdPrintln("No SD card found."); + lcdDisplay(); + getInputWait(); + return; + } + lcdPrintln("SD card raw perf:"); + lcdPrintln("expect to lose the"); + lcdPrintln("first 100 MB and"); + lcdPrintln("press btn to cont."); + lcdDisplay(); + getInputWait(); + + lcdPrintln("ms to write 100MB:"); + lcdDisplay(); + uint32_t write_t = _timectr; + for(int i=100*1024*1024/4096; i>0; i--) { + if(i%1024 == 0) TOGGLE(LED2); + Chip_SDMMC_WriteBlocks(LPC_SDMMC, buf, 4+(i*8), 8); + } + write_t = _timectr - write_t; + + lcdPrintln(IntToStr(write_t, 10, 0)); + lcdPrintln("ms to read 100MB:"); + lcdDisplay(); + uint32_t read_t = _timectr; + for(int i=100*1024*1024/4096; i>0; i--) { + if(i%1024 == 0) TOGGLE(LED2); + Chip_SDMMC_ReadBlocks(LPC_SDMMC, buf, 4+(i*8), 8); + } + read_t = _timectr - read_t; + + lcdPrintln(IntToStr(read_t, 10, 0)); + lcdPrintln("press button"); + lcdDisplay(); + getInputWait(); + + lcdPrintln("goodbye!"); + lcdDisplay(); +} diff --git a/sdapp/sdcard.c b/sdapp/sdcard.c new file mode 100644 index 00000000..c369f3ba --- /dev/null +++ b/sdapp/sdcard.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "msc_main.h" +#include + +//# MENU SD_USB +void menu_sdcard(void){ + lcdClear(); + + sdmmc_setup(); + uint32_t r = sdmmc_acquire(); + + if(r) { + lcdPrintln("SD card found."); + lcdPrintln("No. of blocks:"); + lcdPrintln(IntToStr(Chip_SDMMC_GetDeviceBlocks(LPC_SDMMC), 10, 0)); + lcdPrintln("in USB MSC mode"); + // SD I/O needs higher interrupt prio than USB so it works within + // the USB callbacks + NVIC_SetPriority(USB0_IRQn, 2); + NVIC_SetPriority(SDIO_IRQn, 0); + SD_MSCenable(); + } else { + lcdPrintln("No SD card found."); + } + lcdDisplay(); + while(getInputRaw()==BTN_NONE){ + /* wait */ + __asm__ volatile ("nop"); + }; + + lcdPrintln("goodbye!"); + lcdDisplay(); + MSCdisable(); + Chip_SDIF_DeInit(LPC_SDMMC); +} diff --git a/sdapp/wrfile.c b/sdapp/wrfile.c new file mode 100644 index 00000000..acd18986 --- /dev/null +++ b/sdapp/wrfile.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include + +#include +#include + +static FATFS SDFatFs; /* File system object for logical drive */ + +//# MENU wrfile +void menu_wrfile(void){ + lcdClear(); + + lcdPrintln("Mounting FAT FS"); + lcdDisplay(); + + FRESULT res; + res=f_mount(&SDFatFs,"1:",1); + if(res != FR_OK){ + lcdPrintln("FS init error"); + lcdPrintln(f_get_rc_string(res)); + lcdDisplay(); + getInputWait(); + return; + }; + + lcdPrintln("Writing test file"); + lcdDisplay(); + + writeFile("1:test.txt", "Hello World!", 12); + + lcdPrintln("Done, press button"); + lcdDisplay(); + + while(getInputRaw()==BTN_NONE){ + /* wait */ + __asm__ volatile ("nop"); + }; + + lcdPrintln("goodbye!"); + lcdDisplay(); +}