From 6638e6b4c8fedb43e849a81d8f4a0844580b4339 Mon Sep 17 00:00:00 2001 From: Hans-Werner Hilse Date: Fri, 25 Dec 2015 18:49:10 +0100 Subject: [PATCH 1/7] added SD card API to rad1olib/lpcapi This introduces the SD card interface from LPCopen. It includes rad1o-specific setup code and a few minor changes to the LPCopen codebase to be able to properly include only the needed parts. All code provided by LPCopen is in the lpcapi subfolder. --- lpcapi/cguccu_18xx_43xx.h | 114 +++ lpcapi/chip.h | 163 ++++ lpcapi/chip_clocks.h | 252 ++++++ lpcapi/chip_lpc43xx.h | 220 +++++ lpcapi/clock_18xx_43xx.c | 708 +++++++++++++++ lpcapi/clock_18xx_43xx.h | 341 +++++++ lpcapi/cmsis.h | 63 ++ lpcapi/cmsis_43xx.h | 167 ++++ lpcapi/core_cm4.h | 1774 +++++++++++++++++++++++++++++++++++++ lpcapi/core_cm4_simd.h | 673 ++++++++++++++ lpcapi/core_cmFunc.h | 636 +++++++++++++ lpcapi/core_cmInstr.h | 688 ++++++++++++++ lpcapi/creg_18xx_43xx.h | 238 +++++ lpcapi/fpu_init.h | 52 ++ lpcapi/lpc_types.h | 216 +++++ lpcapi/sdif_18xx_43xx.c | 223 +++++ lpcapi/sdif_18xx_43xx.h | 481 ++++++++++ lpcapi/sdmmc.h | 450 ++++++++++ lpcapi/sdmmc_18xx_43xx.c | 596 +++++++++++++ lpcapi/sdmmc_18xx_43xx.h | 153 ++++ lpcapi/sys_config.h | 36 + rad1olib/pins.h | 10 + rad1olib/sdmmc.c | 96 ++ rad1olib/sdmmc.h | 6 + sdapp/Makefile | 72 ++ sdapp/main.c | 59 ++ sdapp/sdcard.c | 29 + 27 files changed, 8516 insertions(+) create mode 100644 lpcapi/cguccu_18xx_43xx.h create mode 100644 lpcapi/chip.h create mode 100644 lpcapi/chip_clocks.h create mode 100644 lpcapi/chip_lpc43xx.h create mode 100644 lpcapi/clock_18xx_43xx.c create mode 100644 lpcapi/clock_18xx_43xx.h create mode 100644 lpcapi/cmsis.h create mode 100644 lpcapi/cmsis_43xx.h create mode 100644 lpcapi/core_cm4.h create mode 100644 lpcapi/core_cm4_simd.h create mode 100644 lpcapi/core_cmFunc.h create mode 100644 lpcapi/core_cmInstr.h create mode 100644 lpcapi/creg_18xx_43xx.h create mode 100644 lpcapi/fpu_init.h create mode 100644 lpcapi/lpc_types.h create mode 100644 lpcapi/sdif_18xx_43xx.c create mode 100644 lpcapi/sdif_18xx_43xx.h create mode 100644 lpcapi/sdmmc.h create mode 100644 lpcapi/sdmmc_18xx_43xx.c create mode 100644 lpcapi/sdmmc_18xx_43xx.h create mode 100644 lpcapi/sys_config.h create mode 100644 rad1olib/sdmmc.c create mode 100644 rad1olib/sdmmc.h create mode 100644 sdapp/Makefile create mode 100644 sdapp/main.c create mode 100644 sdapp/sdcard.c 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..568a7354 --- /dev/null +++ b/lpcapi/core_cm4.h @@ -0,0 +1,1774 @@ +/**************************************************************************//** + * @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. +*/ +#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 */ + +/*@} 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 */ +#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 */ +#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 */ +#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 */ + +#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 */ + +#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 */ + +#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 */ + +#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 */ + +#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 */ + +#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 */ + +#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 */ + +#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 */ +#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 */ +#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 */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#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 */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #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 */ +} + + +/** \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 */ +} + + +/** \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 */ +} + + +/** \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 */ +} + + +/** \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 (__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 + +/*@} 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..139bc3c5 --- /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..8946c2c4 --- /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..344b593d --- /dev/null +++ b/rad1olib/sdmmc.c @@ -0,0 +1,96 @@ +#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..18b07508 --- /dev/null +++ b/sdapp/Makefile @@ -0,0 +1,72 @@ +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 += ../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 + +OBJS += ../rad1olib/sdmmc.o +OBJS += ../lpcapi/clock_18xx_43xx.o +OBJS += ../lpcapi/sdif_18xx_43xx.o +OBJS += ../lpcapi/sdmmc_18xx_43xx.o + +SRCS = $(wildcard *.c) +SOBJS = $(foreach mod,$(SRCS),$(subst .c,.o,$(mod))) + +OBJS += $(SOBJS) + +CFLAGS=-Wno-unused-variable -DRAD1O -DLPC43XX_M4 -DCORE_M4 -I. +OBJS += ../hackrf/firmware/common/w25q80bv.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/sdcard.c b/sdapp/sdcard.c new file mode 100644 index 00000000..64ea546a --- /dev/null +++ b/sdapp/sdcard.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +#include +#include +#include +#include + +//# MENU sdcard +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)); + } else { + lcdPrintln("No SD card found."); + } + lcdDisplay(); + while(getInputRaw()==BTN_NONE){ /* wait */ }; + + Chip_SDIF_DeInit(LPC_SDMMC); +} From d0e70484273bb58b11086af086925bb531edab62 Mon Sep 17 00:00:00 2001 From: Hans-Werner Hilse Date: Sat, 26 Dec 2015 00:06:11 +0100 Subject: [PATCH 2/7] sdmmc: avoid collisions between lpcopen and libopencm3 This is mainly about the generic platform headers. --- lpcapi/core_cm4.h | 30 ++++++++++++++++++++++++++---- lpcapi/core_cmFunc.h | 16 ++++++++-------- lpcapi/core_cmInstr.h | 34 +++++++++++++++++----------------- rad1olib/sdmmc.c | 1 + 4 files changed, 52 insertions(+), 29 deletions(-) diff --git a/lpcapi/core_cm4.h b/lpcapi/core_cm4.h index 568a7354..6309bf79 100644 --- a/lpcapi/core_cm4.h +++ b/lpcapi/core_cm4.h @@ -215,6 +215,7 @@ \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 @@ -222,7 +223,7 @@ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ - +#endif /*@} end of group Cortex_M4 */ @@ -470,6 +471,7 @@ typedef struct #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 */ @@ -502,6 +504,7 @@ typedef struct #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 */ @@ -1105,6 +1108,7 @@ typedef struct #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 */ @@ -1125,27 +1129,35 @@ typedef struct #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 */ @@ -1313,6 +1325,7 @@ typedef struct #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 */ @@ -1324,6 +1337,7 @@ typedef struct /* 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 */ @@ -1382,16 +1396,21 @@ typedef struct //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 @@ -1460,6 +1479,7 @@ __STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) } +#if 0 /** \brief Enable External Interrupt The function enables a device-specific interrupt in the NVIC interrupt controller. @@ -1483,7 +1503,7 @@ __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 @@ -1512,7 +1532,7 @@ __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. @@ -1523,7 +1543,7 @@ __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 @@ -1659,6 +1679,7 @@ __STATIC_INLINE void NVIC_SystemReset(void) @{ */ +#if 0 #if (__Vendor_SysTickConfig == 0) /** \brief System Tick Configuration @@ -1689,6 +1710,7 @@ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) return (0); /* Function successful */ } +#endif #endif /*@} end of CMSIS_Core_SysTickFunctions */ diff --git a/lpcapi/core_cmFunc.h b/lpcapi/core_cmFunc.h index 139bc3c5..ff3106bf 100644 --- a/lpcapi/core_cmFunc.h +++ b/lpcapi/core_cmFunc.h @@ -326,10 +326,10 @@ __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) 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"); -} +//__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) +//{ +// __ASM volatile ("cpsie i" : : : "memory"); +//} /** \brief Disable IRQ Interrupts @@ -337,10 +337,10 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) 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"); -} +//__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) +//{ +// __ASM volatile ("cpsid i" : : : "memory"); +//} /** \brief Get Control Register diff --git a/lpcapi/core_cmInstr.h b/lpcapi/core_cmInstr.h index 8946c2c4..fbeeb9d6 100644 --- a/lpcapi/core_cmInstr.h +++ b/lpcapi/core_cmInstr.h @@ -65,7 +65,7 @@ Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. */ -#define __WFI __wfi +//#define __WFI __wfi /** \brief Wait For Event @@ -328,15 +328,15 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void) } -/** \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 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 @@ -659,13 +659,13 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void) \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); -} +//__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) */ diff --git a/rad1olib/sdmmc.c b/rad1olib/sdmmc.c index 344b593d..dc410b44 100644 --- a/rad1olib/sdmmc.c +++ b/rad1olib/sdmmc.c @@ -3,6 +3,7 @@ #include #include #include +#include #include static volatile int32_t sdio_wait_exit = 0; From ece39c29c3e7116f69b8c8b5d2582e8f515f85b7 Mon Sep 17 00:00:00 2001 From: Hans-Werner Hilse Date: Sat, 26 Dec 2015 00:09:27 +0100 Subject: [PATCH 3/7] sdapp: SD card example, also: USB-MSC access to the SD card allows to access the SD card (in fact: the first 4GB of it!) via USB mass storage. Don't expect speed records. --- sdapp/Makefile | 8 +-- sdapp/msc_main.c | 93 +++++++++++++++++++++++++ sdapp/msc_main.h | 4 ++ sdapp/msc_sdcard.c | 169 +++++++++++++++++++++++++++++++++++++++++++++ sdapp/msc_sdcard.h | 66 ++++++++++++++++++ sdapp/sdcard.c | 19 ++++- 6 files changed, 353 insertions(+), 6 deletions(-) create mode 100644 sdapp/msc_main.c create mode 100644 sdapp/msc_main.h create mode 100644 sdapp/msc_sdcard.c create mode 100644 sdapp/msc_sdcard.h diff --git a/sdapp/Makefile b/sdapp/Makefile index 18b07508..293e8d89 100644 --- a/sdapp/Makefile +++ b/sdapp/Makefile @@ -30,11 +30,11 @@ OBJS += ../r0ketlib/random.o OBJS += ../r0ketlib/image.o OBJS += ../r0ketlib/mesh.o OBJS += ../r0ketlib/night.o -#OBJS += ../lpcapi/msc/msc_desc.o -#OBJS += ../lpcapi/msc/msc_main.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/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 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/sdcard.c b/sdapp/sdcard.c index 64ea546a..c369f3ba 100644 --- a/sdapp/sdcard.c +++ b/sdapp/sdcard.c @@ -8,7 +8,10 @@ #include #include -//# MENU sdcard +#include "msc_main.h" +#include + +//# MENU SD_USB void menu_sdcard(void){ lcdClear(); @@ -19,11 +22,23 @@ void menu_sdcard(void){ 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 */ }; + while(getInputRaw()==BTN_NONE){ + /* wait */ + __asm__ volatile ("nop"); + }; + lcdPrintln("goodbye!"); + lcdDisplay(); + MSCdisable(); Chip_SDIF_DeInit(LPC_SDMMC); } From b140aaebc288adc911ad6b74ebb81c9efc608f98 Mon Sep 17 00:00:00 2001 From: Hans-Werner Hilse Date: Tue, 29 Dec 2015 13:39:02 +0100 Subject: [PATCH 4/7] fatfs: add support for SD card This adds support for accessing a FAT filesystem on the SD card. Only one partition is supported (auto-detect mode). While partitions larger than 4GB might work, it is not suggested for now. Especially as the demo app for USB MSC access does not work on sectors over 4GB. Just use the USB MSC mode, then fdisk/mkfs on the host PC. --- fatfs/diskio.c | 40 ++++++++++++++++++++++------------------ fatfs/ffconf.h | 4 ++++ 2 files changed, 26 insertions(+), 18 deletions(-) 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. */ From da520f9d5d6e4da65c9bc61628a712267b5aa6e6 Mon Sep 17 00:00:00 2001 From: Hans-Werner Hilse Date: Tue, 29 Dec 2015 13:40:57 +0100 Subject: [PATCH 5/7] sdapp: add example for writing files using FAT filesystem This also adds the necessary objects and a single define to enable SD support in fatfs. Use this as an example to make your rad1o app use files on an SD card. --- sdapp/Makefile | 12 +++++++----- sdapp/wrfile.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 sdapp/wrfile.c diff --git a/sdapp/Makefile b/sdapp/Makefile index 293e8d89..08012e0b 100644 --- a/sdapp/Makefile +++ b/sdapp/Makefile @@ -30,6 +30,7 @@ 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 @@ -43,10 +44,6 @@ OBJS += ../rad1olib/battery.o OBJS += ../rad1olib/draw.o OBJS += ../rad1olib/colorspace.o -OBJS += ../rad1olib/sdmmc.o -OBJS += ../lpcapi/clock_18xx_43xx.o -OBJS += ../lpcapi/sdif_18xx_43xx.o -OBJS += ../lpcapi/sdmmc_18xx_43xx.o SRCS = $(wildcard *.c) SOBJS = $(foreach mod,$(SRCS),$(subst .c,.o,$(mod))) @@ -54,7 +51,12 @@ SOBJS = $(foreach mod,$(SRCS),$(subst .c,.o,$(mod))) OBJS += $(SOBJS) CFLAGS=-Wno-unused-variable -DRAD1O -DLPC43XX_M4 -DCORE_M4 -I. -OBJS += ../hackrf/firmware/common/w25q80bv.o + +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 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(); +} From 318584d658015175cd55ced5c890dafd6b52f68b Mon Sep 17 00:00:00 2001 From: Hans-Werner Hilse Date: Tue, 29 Dec 2015 14:17:41 +0100 Subject: [PATCH 6/7] sdapp: add performance tester Tests FAT FS performance, not raw SD I/O. --- sdapp/perf.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 sdapp/perf.c 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(); +} From e6135986209395964323bac5d3c85a3b170ec322 Mon Sep 17 00:00:00 2001 From: Hans-Werner Hilse Date: Tue, 29 Dec 2015 15:00:55 +0100 Subject: [PATCH 7/7] sdapp: tool to measure raw block I/O performance will destructively write to the first 100 MB (+2048 byte offset) of the SD card. --- sdapp/rawperf.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 sdapp/rawperf.c 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(); +}