Merge pull request #1118 from logost/LPC2460

Introduction of new platform LPC2460 MCU
pull/1121/head
Martin Kojtal 2015-06-01 10:52:03 +01:00
commit 6f7f37eec7
78 changed files with 12815 additions and 16 deletions

View File

@ -30,6 +30,7 @@ NXP:
* [mbed LPC11U24](http://developer.mbed.org/platforms/mbed-LPC11U24/) (Cortex-M0)
* [EA LPC11U35](http://developer.mbed.org/platforms/EA-LPC11U35/) (Cortex-M0)
* mbed LPC2368 (ARM7TDMI-S)
* LPC2460 (ARM7TDMI-S)
* LPC810 (Cortex-M0+)
* [LPC812](http://developer.mbed.org/platforms/NXP-LPC800-MAX/) (Cortex-M0+)
* [EA LPC4088](http://developer.mbed.org/platforms/EA-LPC4088/) (Cortex-M4F)

View File

@ -37,7 +37,7 @@ typedef enum {
} EP_STATUS;
/* Include configuration for specific target */
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM)
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC4088) || defined(TARGET_LPC2460) || defined(TARGET_LPC4088_DM)
#include "USBEndpoints_LPC17_LPC23.h"
#elif defined(TARGET_LPC11UXX) || defined(TARGET_LPC1347) || defined (TARGET_LPC11U6X) || defined (TARGET_LPC1549)
#include "USBEndpoints_LPC11U.h"

View File

@ -16,7 +16,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC2460)
#include "USBHAL.h"

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
#if defined(TARGET_LPC1768)
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2460)
#include "mbed.h"
#include "USBHALHost.h"

View File

@ -0,0 +1,972 @@
/* mbed Microcontroller Library - LPC24xx CMSIS-like structs
* Copyright (C) 2009-2015 ARM Limited. All rights reserved.
*
* An LPC24xx header file, based on LPC23xx.h
*/
#ifndef __LPC24xx_H
#define __LPC24xx_H
#ifdef __cplusplus
extern "C" {
#endif
/*
* ==========================================================================
* ---------- Interrupt Number Definition -----------------------------------
* ==========================================================================
*/
typedef enum IRQn
{
/****** LPC23xx Specific Interrupt Numbers *******************************************************/
WDT_IRQn = 0, /*!< Watchdog Timer Interrupt */
TIMER0_IRQn = 4, /*!< Timer0 Interrupt */
TIMER1_IRQn = 5, /*!< Timer1 Interrupt */
UART0_IRQn = 6, /*!< UART0 Interrupt */
UART1_IRQn = 7, /*!< UART1 Interrupt */
PWM0_IRQn = 8, /*!< PWM0 Interrupt */
PWM1_IRQn = 8, /*!< PWM1 Interrupt */
I2C0_IRQn = 9, /*!< I2C0 Interrupt */
SPI_IRQn = 10, /*!< SPI Interrupt */
SSP0_IRQn = 10, /*!< SSP0 Interrupt */
SSP1_IRQn = 11, /*!< SSP1 Interrupt */
PLL0_IRQn = 12, /*!< PLL0 Lock (Main PLL) Interrupt */
RTC_IRQn = 13, /*!< Real Time Clock Interrupt */
EINT0_IRQn = 14, /*!< External Interrupt 0 Interrupt */
EINT1_IRQn = 15, /*!< External Interrupt 1 Interrupt */
EINT2_IRQn = 16, /*!< External Interrupt 2 Interrupt */
EINT3_IRQn = 17, /*!< External Interrupt 3 Interrupt */
ADC_IRQn = 18, /*!< A/D Converter Interrupt */
I2C1_IRQn = 19, /*!< I2C1 Interrupt */
BOD_IRQn = 20, /*!< Brown-Out Detect Interrupt */
ENET_IRQn = 21, /*!< Ethernet Interrupt */
USB_IRQn = 22, /*!< USB Interrupt */
CAN_IRQn = 23, /*!< CAN Interrupt */
SDMMC_IRQn = 24, /*!< SD/MMC Interrupt */
DMA_IRQn = 25, /*!< General Purpose DMA Interrupt */
TIMER2_IRQn = 26, /*!< Timer2 Interrupt */
TIMER3_IRQn = 27, /*!< Timer3 Interrupt */
UART2_IRQn = 28, /*!< UART2 Interrupt */
UART3_IRQn = 29, /*!< UART3 Interrupt */
I2C2_IRQn = 30, /*!< I2C2 Interrupt */
I2S_IRQn = 31, /*!< I2S Interrupt */
} IRQn_Type;
/*
* ==========================================================================
* ----------- Processor and Core Peripheral Section ------------------------
* ==========================================================================
*/
/* Configuration of the ARM7 Processor and Core Peripherals */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 4 /*!< Number of Bits used for Priority Levels */
#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */
#include <core_arm7.h>
#include "system_LPC24xx.h" /* System Header */
/******************************************************************************/
/* Device Specific Peripheral registers structures */
/******************************************************************************/
#if defined ( __CC_ARM )
#pragma anon_unions
#endif
/*------------- Vector Interupt Controler (VIC) ------------------------------*/
typedef struct
{
__I uint32_t IRQStatus;
__I uint32_t FIQStatus;
__I uint32_t RawIntr;
__IO uint32_t IntSelect;
__IO uint32_t IntEnable;
__O uint32_t IntEnClr;
__IO uint32_t SoftInt;
__O uint32_t SoftIntClr;
__IO uint32_t Protection;
__IO uint32_t SWPriorityMask;
__IO uint32_t RESERVED0[54];
__IO uint32_t VectAddr[32];
__IO uint32_t RESERVED1[32];
__IO uint32_t VectPriority[32];
__IO uint32_t RESERVED2[800];
__IO uint32_t Address;
} LPC_VIC_TypeDef;
/*------------- System Control (SC) ------------------------------------------*/
typedef struct
{
__IO uint32_t MAMCR;
__IO uint32_t MAMTIM;
uint32_t RESERVED0[14];
__IO uint32_t MEMMAP;
uint32_t RESERVED1[15];
__IO uint32_t PLL0CON; /* Clocking and Power Control */
__IO uint32_t PLL0CFG;
__I uint32_t PLL0STAT;
__O uint32_t PLL0FEED;
uint32_t RESERVED2[12];
__IO uint32_t PCON;
__IO uint32_t PCONP;
uint32_t RESERVED3[15];
__IO uint32_t CCLKCFG;
__IO uint32_t USBCLKCFG;
__IO uint32_t CLKSRCSEL;
uint32_t RESERVED4[12];
__IO uint32_t EXTINT; /* External Interrupts */
__IO uint32_t INTWAKE;
__IO uint32_t EXTMODE;
__IO uint32_t EXTPOLAR;
uint32_t RESERVED6[12];
__IO uint32_t RSID; /* Reset */
__IO uint32_t CSPR;
__IO uint32_t AHBCFG1;
__IO uint32_t AHBCFG2;
uint32_t RESERVED7[4];
__IO uint32_t SCS; /* Syscon Miscellaneous Registers */
__IO uint32_t IRCTRIM; /* Clock Dividers */
__IO uint32_t PCLKSEL0;
__IO uint32_t PCLKSEL1;
uint32_t RESERVED8[4];
__IO uint32_t USBIntSt; /* USB Device/OTG Interrupt Register */
uint32_t RESERVED9;
// __IO uint32_t CLKOUTCFG; /* Clock Output Configuration */
} LPC_SC_TypeDef;
/*------------- Pin Connect Block (PINCON) -----------------------------------*/
typedef struct
{
__IO uint32_t PINSEL0;
__IO uint32_t PINSEL1;
__IO uint32_t PINSEL2;
__IO uint32_t PINSEL3;
__IO uint32_t PINSEL4;
__IO uint32_t PINSEL5;
__IO uint32_t PINSEL6;
__IO uint32_t PINSEL7;
__IO uint32_t PINSEL8;
__IO uint32_t PINSEL9;
__IO uint32_t PINSEL10;
uint32_t RESERVED0[5];
__IO uint32_t PINMODE0;
__IO uint32_t PINMODE1;
__IO uint32_t PINMODE2;
__IO uint32_t PINMODE3;
__IO uint32_t PINMODE4;
__IO uint32_t PINMODE5;
__IO uint32_t PINMODE6;
__IO uint32_t PINMODE7;
__IO uint32_t PINMODE8;
__IO uint32_t PINMODE9;
__IO uint32_t PINMODE_OD0;
__IO uint32_t PINMODE_OD1;
__IO uint32_t PINMODE_OD2;
__IO uint32_t PINMODE_OD3;
__IO uint32_t PINMODE_OD4;
} LPC_PINCON_TypeDef;
#define PCTIM0 1
#define PCTIM1 2
#define PCUART0 3
#define PCUART1 4
#define PCPWM1 6
#define PCI2C0 7
#define PCSPI 8
#define PCRTC 9
#define PCSSP1 10
#define PCEMC 11
#define PCADC 12
#define PCAN1 13
#define PCAN2 14
#define PCI2C1 19
#define PCSSP0 21
#define PCTIM2 22
#define PCTIM3 23
#define PCUART2 24
#define PCUART3 25
#define PCI2C2 26
#define PCI2S 27
#define PCSDC 28
#define PCGPDMA 29
#define PCENET 30
#define PCUSB 31
/*------------- General Purpose Input/Output (GPIO) --------------------------*/
typedef struct
{
__IO uint32_t FIODIR;
uint32_t RESERVED0[3];
__IO uint32_t FIOMASK;
__IO uint32_t FIOPIN;
__IO uint32_t FIOSET;
__O uint32_t FIOCLR;
} LPC_GPIO_TypeDef;
typedef struct
{
__I uint32_t IntStatus;
__I uint32_t IO0IntStatR;
__I uint32_t IO0IntStatF;
__O uint32_t IO0IntClr;
__IO uint32_t IO0IntEnR;
__IO uint32_t IO0IntEnF;
uint32_t RESERVED0[3];
__I uint32_t IO2IntStatR;
__I uint32_t IO2IntStatF;
__O uint32_t IO2IntClr;
__IO uint32_t IO2IntEnR;
__IO uint32_t IO2IntEnF;
} LPC_GPIOINT_TypeDef;
/*------------- Timer (TIM) --------------------------------------------------*/
typedef struct
{
__IO uint32_t IR;
__IO uint32_t TCR;
__IO uint32_t TC;
__IO uint32_t PR;
__IO uint32_t PC;
__IO uint32_t MCR;
__IO uint32_t MR0;
__IO uint32_t MR1;
__IO uint32_t MR2;
__IO uint32_t MR3;
__IO uint32_t CCR;
__I uint32_t CR0;
__I uint32_t CR1;
uint32_t RESERVED0[2];
__IO uint32_t EMR;
uint32_t RESERVED1[12];
__IO uint32_t CTCR;
} LPC_TIM_TypeDef;
/*------------- Pulse-Width Modulation (PWM) ---------------------------------*/
typedef struct
{
__IO uint32_t IR;
__IO uint32_t TCR;
__IO uint32_t TC;
__IO uint32_t PR;
__IO uint32_t PC;
__IO uint32_t MCR;
__IO uint32_t MR0;
__IO uint32_t MR1;
__IO uint32_t MR2;
__IO uint32_t MR3;
__IO uint32_t CCR;
__I uint32_t CR0;
__I uint32_t CR1;
__I uint32_t CR2;
__I uint32_t CR3;
uint32_t RESERVED0;
__IO uint32_t MR4;
__IO uint32_t MR5;
__IO uint32_t MR6;
__IO uint32_t PCR;
__IO uint32_t LER;
uint32_t RESERVED1[7];
__IO uint32_t CTCR;
} LPC_PWM_TypeDef;
/*------------- Universal Asynchronous Receiver Transmitter (UART) -----------*/
typedef struct
{
union {
__I uint8_t RBR;
__O uint8_t THR;
__IO uint8_t DLL;
uint32_t RESERVED0;
};
union {
__IO uint8_t DLM;
__IO uint32_t IER;
};
union {
__I uint32_t IIR;
__O uint8_t FCR;
};
__IO uint8_t LCR;
uint8_t RESERVED1[7];
__IO uint8_t LSR;
uint8_t RESERVED2[7];
__IO uint8_t SCR;
uint8_t RESERVED3[3];
__IO uint32_t ACR;
__IO uint8_t ICR;
uint8_t RESERVED4[3];
__IO uint8_t FDR;
uint8_t RESERVED5[7];
__IO uint8_t TER;
uint8_t RESERVED6[27];
__IO uint8_t RS485CTRL;
uint8_t RESERVED7[3];
__IO uint8_t ADRMATCH;
} LPC_UART_TypeDef;
typedef struct
{
union {
__I uint8_t RBR;
__O uint8_t THR;
__IO uint8_t DLL;
uint32_t RESERVED0;
};
union {
__IO uint8_t DLM;
__IO uint32_t IER;
};
union {
__I uint32_t IIR;
__O uint8_t FCR;
};
__IO uint8_t LCR;
uint8_t RESERVED1[3];
__IO uint8_t MCR;
uint8_t RESERVED2[3];
__IO uint8_t LSR;
uint8_t RESERVED3[3];
__IO uint8_t MSR;
uint8_t RESERVED4[3];
__IO uint8_t SCR;
uint8_t RESERVED5[3];
__IO uint32_t ACR;
uint32_t RESERVED6;
__IO uint32_t FDR;
uint32_t RESERVED7;
__IO uint8_t TER;
uint8_t RESERVED8[27];
__IO uint8_t RS485CTRL;
uint8_t RESERVED9[3];
__IO uint8_t ADRMATCH;
uint8_t RESERVED10[3];
__IO uint8_t RS485DLY;
} LPC_UART1_TypeDef;
/*------------- Serial Peripheral Interface (SPI) ----------------------------*/
typedef struct
{
__IO uint32_t SPCR;
__I uint32_t SPSR;
__IO uint32_t SPDR;
__IO uint32_t SPCCR;
uint32_t RESERVED0[3];
__IO uint32_t SPINT;
} LPC_SPI_TypeDef;
/*------------- Synchronous Serial Communication (SSP) -----------------------*/
typedef struct
{
__IO uint32_t CR0;
__IO uint32_t CR1;
__IO uint32_t DR;
__I uint32_t SR;
__IO uint32_t CPSR;
__IO uint32_t IMSC;
__IO uint32_t RIS;
__IO uint32_t MIS;
__IO uint32_t ICR;
__IO uint32_t DMACR;
} LPC_SSP_TypeDef;
/*------------- Inter-Integrated Circuit (I2C) -------------------------------*/
typedef struct
{
__IO uint32_t I2CONSET;
__I uint32_t I2STAT;
__IO uint32_t I2DAT;
__IO uint32_t I2ADR0;
__IO uint32_t I2SCLH;
__IO uint32_t I2SCLL;
__O uint32_t I2CONCLR;
__IO uint32_t MMCTRL;
__IO uint32_t I2ADR1;
__IO uint32_t I2ADR2;
__IO uint32_t I2ADR3;
__I uint32_t I2DATA_BUFFER;
__IO uint32_t I2MASK0;
__IO uint32_t I2MASK1;
__IO uint32_t I2MASK2;
__IO uint32_t I2MASK3;
} LPC_I2C_TypeDef;
/*------------- Inter IC Sound (I2S) -----------------------------------------*/
typedef struct
{
__IO uint32_t I2SDAO;
__I uint32_t I2SDAI;
__O uint32_t I2STXFIFO;
__I uint32_t I2SRXFIFO;
__I uint32_t I2SSTATE;
__IO uint32_t I2SDMA1;
__IO uint32_t I2SDMA2;
__IO uint32_t I2SIRQ;
__IO uint32_t I2STXRATE;
__IO uint32_t I2SRXRATE;
__IO uint32_t I2STXBITRATE;
__IO uint32_t I2SRXBITRATE;
__IO uint32_t I2STXMODE;
__IO uint32_t I2SRXMODE;
} LPC_I2S_TypeDef;
/*------------- Real-Time Clock (RTC) ----------------------------------------*/
typedef struct
{
__IO uint8_t ILR;
uint8_t RESERVED0[3];
__IO uint8_t CTC;
uint8_t RESERVED1[3];
__IO uint8_t CCR;
uint8_t RESERVED2[3];
__IO uint8_t CIIR;
uint8_t RESERVED3[3];
__IO uint8_t AMR;
uint8_t RESERVED4[3];
__I uint32_t CTIME0;
__I uint32_t CTIME1;
__I uint32_t CTIME2;
__IO uint8_t SEC;
uint8_t RESERVED5[3];
__IO uint8_t MIN;
uint8_t RESERVED6[3];
__IO uint8_t HOUR;
uint8_t RESERVED7[3];
__IO uint8_t DOM;
uint8_t RESERVED8[3];
__IO uint8_t DOW;
uint8_t RESERVED9[3];
__IO uint16_t DOY;
uint16_t RESERVED10;
__IO uint8_t MONTH;
uint8_t RESERVED11[3];
__IO uint16_t YEAR;
uint16_t RESERVED12;
__IO uint32_t CALIBRATION;
__IO uint32_t GPREG0;
__IO uint32_t GPREG1;
__IO uint32_t GPREG2;
__IO uint32_t GPREG3;
__IO uint32_t GPREG4;
__IO uint8_t WAKEUPDIS;
uint8_t RESERVED13[3];
__IO uint8_t PWRCTRL;
uint8_t RESERVED14[3];
__IO uint8_t ALSEC;
uint8_t RESERVED15[3];
__IO uint8_t ALMIN;
uint8_t RESERVED16[3];
__IO uint8_t ALHOUR;
uint8_t RESERVED17[3];
__IO uint8_t ALDOM;
uint8_t RESERVED18[3];
__IO uint8_t ALDOW;
uint8_t RESERVED19[3];
__IO uint16_t ALDOY;
uint16_t RESERVED20;
__IO uint8_t ALMON;
uint8_t RESERVED21[3];
__IO uint16_t ALYEAR;
uint16_t RESERVED22;
} LPC_RTC_TypeDef;
/*------------- Watchdog Timer (WDT) -----------------------------------------*/
typedef struct
{
__IO uint8_t WDMOD;
uint8_t RESERVED0[3];
__IO uint32_t WDTC;
__O uint8_t WDFEED;
uint8_t RESERVED1[3];
__I uint32_t WDTV;
__IO uint32_t WDCLKSEL;
} LPC_WDT_TypeDef;
/*------------- Analog-to-Digital Converter (ADC) ----------------------------*/
typedef struct
{
__IO uint32_t ADCR;
__IO uint32_t ADGDR;
uint32_t RESERVED0;
__IO uint32_t ADINTEN;
__I uint32_t ADDR0;
__I uint32_t ADDR1;
__I uint32_t ADDR2;
__I uint32_t ADDR3;
__I uint32_t ADDR4;
__I uint32_t ADDR5;
__I uint32_t ADDR6;
__I uint32_t ADDR7;
__I uint32_t ADSTAT;
__IO uint32_t ADTRM;
} LPC_ADC_TypeDef;
/*------------- Digital-to-Analog Converter (DAC) ----------------------------*/
typedef struct
{
__IO uint32_t DACR;
__IO uint32_t DACCTRL;
__IO uint16_t DACCNTVAL;
} LPC_DAC_TypeDef;
/*------------- Multimedia Card Interface (MCI) ------------------------------*/
typedef struct
{
__IO uint32_t MCIPower; /* Power control */
__IO uint32_t MCIClock; /* Clock control */
__IO uint32_t MCIArgument;
__IO uint32_t MMCCommand;
__I uint32_t MCIRespCmd;
__I uint32_t MCIResponse0;
__I uint32_t MCIResponse1;
__I uint32_t MCIResponse2;
__I uint32_t MCIResponse3;
__IO uint32_t MCIDataTimer;
__IO uint32_t MCIDataLength;
__IO uint32_t MCIDataCtrl;
__I uint32_t MCIDataCnt;
__I uint32_t MCIStatus;
__O uint32_t MCIClear;
__IO uint32_t MCIMask0;
uint32_t RESERVED1[2];
__I uint32_t MCIFifoCnt;
uint32_t RESERVED2[13];
__IO uint32_t MCIFIFO[16];
} LPC_MCI_TypeDef;
/*------------- Controller Area Network (CAN) --------------------------------*/
typedef struct
{
__IO uint32_t mask[512]; /* ID Masks */
} LPC_CANAF_RAM_TypeDef;
typedef struct /* Acceptance Filter Registers */
{
__IO uint32_t AFMR;
__IO uint32_t SFF_sa;
__IO uint32_t SFF_GRP_sa;
__IO uint32_t EFF_sa;
__IO uint32_t EFF_GRP_sa;
__IO uint32_t ENDofTable;
__I uint32_t LUTerrAd;
__I uint32_t LUTerr;
__IO uint32_t FCANIE;
__IO uint32_t FCANIC0;
__IO uint32_t FCANIC1;
} LPC_CANAF_TypeDef;
typedef struct /* Central Registers */
{
__I uint32_t CANTxSR;
__I uint32_t CANRxSR;
__I uint32_t CANMSR;
} LPC_CANCR_TypeDef;
typedef struct /* Controller Registers */
{
__IO uint32_t MOD;
__O uint32_t CMR;
__IO uint32_t GSR;
__I uint32_t ICR;
__IO uint32_t IER;
__IO uint32_t BTR;
__IO uint32_t EWL;
__I uint32_t SR;
__IO uint32_t RFS;
__IO uint32_t RID;
__IO uint32_t RDA;
__IO uint32_t RDB;
__IO uint32_t TFI1;
__IO uint32_t TID1;
__IO uint32_t TDA1;
__IO uint32_t TDB1;
__IO uint32_t TFI2;
__IO uint32_t TID2;
__IO uint32_t TDA2;
__IO uint32_t TDB2;
__IO uint32_t TFI3;
__IO uint32_t TID3;
__IO uint32_t TDA3;
__IO uint32_t TDB3;
} LPC_CAN_TypeDef;
/*------------- General Purpose Direct Memory Access (GPDMA) -----------------*/
typedef struct /* Common Registers */
{
__I uint32_t DMACIntStat;
__I uint32_t DMACIntTCStat;
__O uint32_t DMACIntTCClear;
__I uint32_t DMACIntErrStat;
__O uint32_t DMACIntErrClr;
__I uint32_t DMACRawIntTCStat;
__I uint32_t DMACRawIntErrStat;
__I uint32_t DMACEnbldChns;
__IO uint32_t DMACSoftBReq;
__IO uint32_t DMACSoftSReq;
__IO uint32_t DMACSoftLBReq;
__IO uint32_t DMACSoftLSReq;
__IO uint32_t DMACConfig;
__IO uint32_t DMACSync;
} LPC_GPDMA_TypeDef;
typedef struct /* Channel Registers */
{
__IO uint32_t DMACCSrcAddr;
__IO uint32_t DMACCDestAddr;
__IO uint32_t DMACCLLI;
__IO uint32_t DMACCControl;
__IO uint32_t DMACCConfig;
} LPC_GPDMACH_TypeDef;
/*------------- Universal Serial Bus (USB) -----------------------------------*/
typedef struct
{
__I uint32_t HcRevision; /* USB Host Registers */
__IO uint32_t HcControl;
__IO uint32_t HcCommandStatus;
__IO uint32_t HcInterruptStatus;
__IO uint32_t HcInterruptEnable;
__IO uint32_t HcInterruptDisable;
__IO uint32_t HcHCCA;
__I uint32_t HcPeriodCurrentED;
__IO uint32_t HcControlHeadED;
__IO uint32_t HcControlCurrentED;
__IO uint32_t HcBulkHeadED;
__IO uint32_t HcBulkCurrentED;
__I uint32_t HcDoneHead;
__IO uint32_t HcFmInterval;
__I uint32_t HcFmRemaining;
__I uint32_t HcFmNumber;
__IO uint32_t HcPeriodicStart;
__IO uint32_t HcLSTreshold;
__IO uint32_t HcRhDescriptorA;
__IO uint32_t HcRhDescriptorB;
__IO uint32_t HcRhStatus;
__IO uint32_t HcRhPortStatus1;
__IO uint32_t HcRhPortStatus2;
uint32_t RESERVED0[40];
__I uint32_t Module_ID;
__I uint32_t OTGIntSt; /* USB On-The-Go Registers */
__IO uint32_t OTGIntEn;
__O uint32_t OTGIntSet;
__O uint32_t OTGIntClr;
__IO uint32_t OTGStCtrl;
__IO uint32_t OTGTmr;
uint32_t RESERVED1[58];
__I uint32_t USBDevIntSt; /* USB Device Interrupt Registers */
__IO uint32_t USBDevIntEn;
__O uint32_t USBDevIntClr;
__O uint32_t USBDevIntSet;
__O uint32_t USBCmdCode; /* USB Device SIE Command Registers */
__I uint32_t USBCmdData;
__I uint32_t USBRxData; /* USB Device Transfer Registers */
__O uint32_t USBTxData;
__I uint32_t USBRxPLen;
__O uint32_t USBTxPLen;
__IO uint32_t USBCtrl;
__O uint32_t USBDevIntPri;
__I uint32_t USBEpIntSt; /* USB Device Endpoint Interrupt Regs */
__IO uint32_t USBEpIntEn;
__O uint32_t USBEpIntClr;
__O uint32_t USBEpIntSet;
__O uint32_t USBEpIntPri;
__IO uint32_t USBReEp; /* USB Device Endpoint Realization Reg*/
__O uint32_t USBEpInd;
__IO uint32_t USBMaxPSize;
__I uint32_t USBDMARSt; /* USB Device DMA Registers */
__O uint32_t USBDMARClr;
__O uint32_t USBDMARSet;
uint32_t RESERVED2[9];
__IO uint32_t USBUDCAH;
__I uint32_t USBEpDMASt;
__O uint32_t USBEpDMAEn;
__O uint32_t USBEpDMADis;
__I uint32_t USBDMAIntSt;
__IO uint32_t USBDMAIntEn;
uint32_t RESERVED3[2];
__I uint32_t USBEoTIntSt;
__O uint32_t USBEoTIntClr;
__O uint32_t USBEoTIntSet;
__I uint32_t USBNDDRIntSt;
__O uint32_t USBNDDRIntClr;
__O uint32_t USBNDDRIntSet;
__I uint32_t USBSysErrIntSt;
__O uint32_t USBSysErrIntClr;
__O uint32_t USBSysErrIntSet;
uint32_t RESERVED4[15];
__I uint32_t I2C_RX; /* USB OTG I2C Registers */
__O uint32_t I2C_WO;
__I uint32_t I2C_STS;
__IO uint32_t I2C_CTL;
__IO uint32_t I2C_CLKHI;
__O uint32_t I2C_CLKLO;
uint32_t RESERVED5[823];
union {
__IO uint32_t USBClkCtrl; /* USB Clock Control Registers */
__IO uint32_t OTGClkCtrl;
};
union {
__I uint32_t USBClkSt;
__I uint32_t OTGClkSt;
};
} LPC_USB_TypeDef;
/*------------- Ethernet Media Access Controller (EMAC) ----------------------*/
typedef struct
{
__IO uint32_t MAC1; /* MAC Registers */
__IO uint32_t MAC2;
__IO uint32_t IPGT;
__IO uint32_t IPGR;
__IO uint32_t CLRT;
__IO uint32_t MAXF;
__IO uint32_t SUPP;
__IO uint32_t TEST;
__IO uint32_t MCFG;
__IO uint32_t MCMD;
__IO uint32_t MADR;
__O uint32_t MWTD;
__I uint32_t MRDD;
__I uint32_t MIND;
uint32_t RESERVED0[2];
__IO uint32_t SA0;
__IO uint32_t SA1;
__IO uint32_t SA2;
uint32_t RESERVED1[45];
__IO uint32_t Command; /* Control Registers */
__I uint32_t Status;
__IO uint32_t RxDescriptor;
__IO uint32_t RxStatus;
__IO uint32_t RxDescriptorNumber;
__I uint32_t RxProduceIndex;
__IO uint32_t RxConsumeIndex;
__IO uint32_t TxDescriptor;
__IO uint32_t TxStatus;
__IO uint32_t TxDescriptorNumber;
__IO uint32_t TxProduceIndex;
__I uint32_t TxConsumeIndex;
uint32_t RESERVED2[10];
__I uint32_t TSV0;
__I uint32_t TSV1;
__I uint32_t RSV;
uint32_t RESERVED3[3];
__IO uint32_t FlowControlCounter;
__I uint32_t FlowControlStatus;
uint32_t RESERVED4[34];
__IO uint32_t RxFilterCtrl; /* Rx Filter Registers */
__IO uint32_t RxFilterWoLStatus;
__IO uint32_t RxFilterWoLClear;
uint32_t RESERVED5;
__IO uint32_t HashFilterL;
__IO uint32_t HashFilterH;
uint32_t RESERVED6[882];
__I uint32_t IntStatus; /* Module Control Registers */
__IO uint32_t IntEnable;
__O uint32_t IntClear;
__O uint32_t IntSet;
uint32_t RESERVED7;
__IO uint32_t PowerDown;
uint32_t RESERVED8;
__IO uint32_t Module_ID;
} LPC_EMAC_TypeDef;
/*-------------------- External Memory Controller (EMC) ----------------------*/
typedef struct
{
__IO uint32_t EMCControl;
__I uint32_t EMCStatus;
__IO uint32_t EMCConfig;
uint32_t RESERVED1[5];
__IO uint32_t EMCDynamicControl;
__IO uint32_t EMCDynamicRefresh;
__IO uint32_t EMCDynamicReadConfig;
uint32_t RESERVED2;
__IO uint32_t EMCDynamicRP;
__IO uint32_t EMCDynamicRAS;
__IO uint32_t EMCDynamicSREX;
__IO uint32_t EMCDynamicAPR;
__IO uint32_t EMCDynamicDAL;
__IO uint32_t EMCDynamicWR;
__IO uint32_t EMCDynamicRC;
__IO uint32_t EMCDynamicRFC;
__IO uint32_t EMCDynamicXSR;
__IO uint32_t EMCDynamicRRD;
__IO uint32_t EMCDynamicMRD;
uint32_t RESERVED3[9];
__IO uint32_t EMCStaticExtendedWait;
uint32_t RESERVED4[31];
__IO uint32_t EMCDynamicConfig0;
__IO uint32_t EMCDynamicRasCas0;
uint32_t RESERVED5[6];
__IO uint32_t EMCDynamicConfig1;
__IO uint32_t EMCDynamicRasCas1;
uint32_t RESERVED6[6];
__IO uint32_t EMCDynamicConfic2;
__IO uint32_t EMCDynamicRasCas2;
uint32_t RESERVED7[6];
__IO uint32_t EMCDynamicConfig3;
__IO uint32_t EMCDynamicRasCas3;
uint32_t RESERVED8[38];
__IO uint32_t EMCStaticConfig0;
__IO uint32_t EMCStaticWaitWen0;
__IO uint32_t EMCStaticWaitOen0;
__IO uint32_t EMCStaticWaitRd0;
__IO uint32_t EMCStaticWaitPage0;
__IO uint32_t EMCStaticWaitWr0;
__IO uint32_t EMCStaticWaitTurn0;
uint32_t RESERVED9;
__IO uint32_t EMCStaticConfig1;
__IO uint32_t EMCStaticWaitWen1;
__IO uint32_t EMCStaticWaitOen1;
__IO uint32_t EMCStaticWaitRd1;
__IO uint32_t EMCStaticWaitPage1;
__IO uint32_t EMCStaticWaitWr1;
__IO uint32_t EMCStaticWaitTurn1;
uint32_t RESERVED10;
__IO uint32_t EMCStaticConfig2;
__IO uint32_t EMCStaticWaitWen2;
__IO uint32_t EMCStaticWaitOen2;
__IO uint32_t EMCStaticWaitRd2;
__IO uint32_t EMCStaticWaitPage2;
__IO uint32_t EMCStaticWaitWr2;
__IO uint32_t EMCStaticWaitTurn2;
uint32_t RESERVED11;
__IO uint32_t EMCStaticConfig3;
__IO uint32_t EMCStaticWaitWen3;
__IO uint32_t EMCStaticWaitOen3;
__IO uint32_t EMCStaticWaitRd3;
__IO uint32_t EMCStaticWaitPage3;
__IO uint32_t EMCStaticWaitWr3;
__IO uint32_t EMCStaticWaitTurn3;
} LPC_EMC_TypeDef;
#if defined ( __CC_ARM )
#pragma no_anon_unions
#endif
/******************************************************************************/
/* Peripheral memory map */
/******************************************************************************/
/* Base addresses */
/* AHB Peripheral # 0 */
/*
#define FLASH_BASE (0x00000000UL)
#define RAM_BASE (0x10000000UL)
#define GPIO_BASE (0x2009C000UL)
#define APB0_BASE (0x40000000UL)
#define APB1_BASE (0x40080000UL)
#define AHB_BASE (0x50000000UL)
#define CM3_BASE (0xE0000000UL)
*/
// TODO - #define VIC_BASE_ADDR 0xFFFFF000
#define LPC_WDT_BASE (0xE0000000)
#define LPC_TIM0_BASE (0xE0004000)
#define LPC_TIM1_BASE (0xE0008000)
#define LPC_UART0_BASE (0xE000C000)
#define LPC_UART1_BASE (0xE0010000)
#define LPC_PWM1_BASE (0xE0018000)
#define LPC_I2C0_BASE (0xE001C000)
#define LPC_SPI_BASE (0xE0020000)
#define LPC_RTC_BASE (0xE0024000)
#define LPC_GPIOINT_BASE (0xE0028080)
#define LPC_PINCON_BASE (0xE002C000)
#define LPC_SSP1_BASE (0xE0030000)
#define LPC_ADC_BASE (0xE0034000)
#define LPC_CANAF_RAM_BASE (0xE0038000)
#define LPC_CANAF_BASE (0xE003C000)
#define LPC_CANCR_BASE (0xE0040000)
#define LPC_CAN1_BASE (0xE0044000)
#define LPC_CAN2_BASE (0xE0048000)
#define LPC_I2C1_BASE (0xE005C000)
#define LPC_SSP0_BASE (0xE0068000)
#define LPC_DAC_BASE (0xE006C000)
#define LPC_TIM2_BASE (0xE0070000)
#define LPC_TIM3_BASE (0xE0074000)
#define LPC_UART2_BASE (0xE0078000)
#define LPC_UART3_BASE (0xE007C000)
#define LPC_I2C2_BASE (0xE0080000)
#define LPC_I2S_BASE (0xE0088000)
#define LPC_MCI_BASE (0xE008C000)
#define LPC_SC_BASE (0xE01FC000)
#define LPC_EMAC_BASE (0xFFE00000)
#define LPC_GPDMA_BASE (0xFFE04000)
#define LPC_GPDMACH0_BASE (0xFFE04100)
#define LPC_GPDMACH1_BASE (0xFFE04120)
#define LPC_EMC_BASE (0xFFE08000)
#define LPC_USB_BASE (0xFFE0C000)
#define LPC_VIC_BASE (0xFFFFF000)
/* GPIOs */
#define LPC_GPIO0_BASE (0x3FFFC000)
#define LPC_GPIO1_BASE (0x3FFFC020)
#define LPC_GPIO2_BASE (0x3FFFC040)
#define LPC_GPIO3_BASE (0x3FFFC060)
#define LPC_GPIO4_BASE (0x3FFFC080)
/******************************************************************************/
/* Peripheral declaration */
/******************************************************************************/
#define LPC_SC (( LPC_SC_TypeDef *) LPC_SC_BASE)
#define LPC_GPIO0 (( LPC_GPIO_TypeDef *) LPC_GPIO0_BASE)
#define LPC_GPIO1 (( LPC_GPIO_TypeDef *) LPC_GPIO1_BASE)
#define LPC_GPIO2 (( LPC_GPIO_TypeDef *) LPC_GPIO2_BASE)
#define LPC_GPIO3 (( LPC_GPIO_TypeDef *) LPC_GPIO3_BASE)
#define LPC_GPIO4 (( LPC_GPIO_TypeDef *) LPC_GPIO4_BASE)
#define LPC_WDT (( LPC_WDT_TypeDef *) LPC_WDT_BASE)
#define LPC_TIM0 (( LPC_TIM_TypeDef *) LPC_TIM0_BASE)
#define LPC_TIM1 (( LPC_TIM_TypeDef *) LPC_TIM1_BASE)
#define LPC_TIM2 (( LPC_TIM_TypeDef *) LPC_TIM2_BASE)
#define LPC_TIM3 (( LPC_TIM_TypeDef *) LPC_TIM3_BASE)
#define LPC_UART0 (( LPC_UART_TypeDef *) LPC_UART0_BASE)
#define LPC_UART1 (( LPC_UART1_TypeDef *) LPC_UART1_BASE)
#define LPC_UART2 (( LPC_UART_TypeDef *) LPC_UART2_BASE)
#define LPC_UART3 (( LPC_UART_TypeDef *) LPC_UART3_BASE)
#define LPC_PWM1 (( LPC_PWM_TypeDef *) LPC_PWM1_BASE)
#define LPC_I2C0 (( LPC_I2C_TypeDef *) LPC_I2C0_BASE)
#define LPC_I2C1 (( LPC_I2C_TypeDef *) LPC_I2C1_BASE)
#define LPC_I2C2 (( LPC_I2C_TypeDef *) LPC_I2C2_BASE)
#define LPC_I2S (( LPC_I2S_TypeDef *) LPC_I2S_BASE)
#define LPC_SPI (( LPC_SPI_TypeDef *) LPC_SPI_BASE)
#define LPC_RTC (( LPC_RTC_TypeDef *) LPC_RTC_BASE)
#define LPC_GPIOINT (( LPC_GPIOINT_TypeDef *) LPC_GPIOINT_BASE)
#define LPC_PINCON (( LPC_PINCON_TypeDef *) LPC_PINCON_BASE)
#define LPC_SSP0 (( LPC_SSP_TypeDef *) LPC_SSP0_BASE)
#define LPC_SSP1 (( LPC_SSP_TypeDef *) LPC_SSP1_BASE)
#define LPC_ADC (( LPC_ADC_TypeDef *) LPC_ADC_BASE)
#define LPC_DAC (( LPC_DAC_TypeDef *) LPC_DAC_BASE)
#define LPC_CANAF_RAM ((LPC_CANAF_RAM_TypeDef *) LPC_CANAF_RAM_BASE)
#define LPC_CANAF (( LPC_CANAF_TypeDef *) LPC_CANAF_BASE)
#define LPC_CANCR (( LPC_CANCR_TypeDef *) LPC_CANCR_BASE)
#define LPC_CAN1 (( LPC_CAN_TypeDef *) LPC_CAN1_BASE)
#define LPC_CAN2 (( LPC_CAN_TypeDef *) LPC_CAN2_BASE)
#define LPC_MCI (( LPC_MCI_TypeDef *) LPC_MCI_BASE)
#define LPC_EMAC (( LPC_EMAC_TypeDef *) LPC_EMAC_BASE)
#define LPC_GPDMA (( LPC_GPDMA_TypeDef *) LPC_GPDMA_BASE)
#define LPC_GPDMACH0 (( LPC_GPDMACH_TypeDef *) LPC_GPDMACH0_BASE)
#define LPC_GPDMACH1 (( LPC_GPDMACH_TypeDef *) LPC_GPDMACH1_BASE)
#define LPC_USB (( LPC_USB_TypeDef *) LPC_USB_BASE)
#define LPC_VIC (( LPC_VIC_TypeDef *) LPC_VIC_BASE)
#define LPC_EMC (( LPC_EMC_TypeDef *) LPC_EMC_BASE)
#ifdef __cplusplus
}
#endif
#endif // __LPC24xx_H

View File

@ -0,0 +1,210 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(vectors)
/* Memory Definitions: */
MEMORY
{
Flash (rx) : ORIGIN = 0xA0001000, LENGTH = 512k
Ram (rwx) : ORIGIN = 0x40000040, LENGTH = 64k - 0x40
UsbRam (rw) : ORIGIN = 0x7FD00000, LENGTH = 8k
EthRam (rw) : ORIGIN = 0x7FE00000, LENGTH = 16k
CanRam (rw) : ORIGIN = 0xE0038000, LENGTH = 2k
BatRam (rw) : ORIGIN = 0xE0084000, LENGTH = 2k
}
/* Stack sizes: */
UND_Stack_Size = 64;
SVC_Stack_Size = 64;
ABT_Stack_Size = 64;
FIQ_Stack_Size = 64;
IRQ_Stack_Size = 64;
User_Stack_Size = 4096;
Stack_Size_Total = UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + FIQ_Stack_Size + IRQ_Stack_Size + User_Stack_Size;
/* Stack tops for each mode: */
__und_stack_top__ = __stacks_top__;
__abt_stack_top__ = __und_stack_top__ - UND_Stack_Size ;
__fiq_stack_top__ = __abt_stack_top__ - ABT_Stack_Size ;
__irq_stack_top__ = __fiq_stack_top__ - FIQ_Stack_Size ;
__svc_stack_top__ = __irq_stack_top__ - IRQ_Stack_Size ;
__usr_stack_top__ = __svc_stack_top__ - User_Stack_Size ;
/* C-accessible symbols for memory address ranges: */
__FLASH_segment_start__ = ORIGIN( Flash );
__FLASH_segment_end__ = ORIGIN( Flash ) + LENGTH( Flash );
__SRAM_segment_start__ = ORIGIN( Ram );
__SRAM_segment_end__ = ORIGIN( Ram ) + LENGTH( Ram );
/* Stacks (full descending) at top of RAM, grows downward:
*
* __stack_min__ is used by the malloc implementation to ensure heap never collides
* with stack (assuming stack never grows beyond Stack_Size_Total in length) */
__stacks_top__ = __SRAM_segment_end__;
__stacks_min__ = __SRAM_segment_end__ - Stack_Size_Total;
SECTIONS
{
/* first section is .text which is used for code */
__text_start__ = . ;
.text : {
__privileged_code_start__ = . ;
KEEP( *( .vectors ) )
*( .privileged_code )
__privileged_code_end__ = .;
*( .text .text.* .gnu.linkonce.t.* )
*( .plt )
*( .gnu.warning )
*( .glue_7t ) *( .glue_7 ) *( .vfp11_veneer )
*( .rodata .rodata.* .gnu.linkonce.r.* )
*(.ARM.extab* .gnu.linkonce.armextab.*)
*(.gcc_except_table)
*(.eh_frame_hdr)
*(.eh_frame)
. = ALIGN( 4 ) ;
KEEP( *( .init ) )
. = ALIGN( 4 ) ;
__preinit_array_start = . ;
KEEP( *( .preinit_array ) )
__preinit_array_end = . ;
. = ALIGN( 4 ) ;
__init_array_start = . ;
KEEP( *( SORT( .init_array.* ) ) )
KEEP( *( .init_array ) )
__init_array_end = . ;
. = ALIGN( 4 ) ;
KEEP( *crtbegin.o( .ctors ) )
KEEP( *( EXCLUDE_FILE( *crtend.o ) .ctors ) )
KEEP( *( SORT( .ctors.* ) ) )
KEEP( *crtend.o( .ctors ) )
. = ALIGN( 4 ) ;
KEEP( *( .fini ) )
. = ALIGN( 4 ) ;
__fini_array_start = . ;
KEEP( *( .fini_array ) )
KEEP( *( SORT( .fini_array.* ) ) )
__fini_array_end = . ;
KEEP( *crtbegin.o( .dtors ) )
KEEP( *( EXCLUDE_FILE( *crtend.o ) .dtors ) )
KEEP( *( SORT( .dtors.* ) ) )
KEEP( *crtend.o( .dtors ) )
} >Flash
__exidx_start = . ;
.ARM.exidx : {
*( .ARM.exidx* .gnu.linkonce.armexidx.* )
} >Flash
__exidx_end = . ;
.text.align : { . = ALIGN( 8 ) ; } >Flash /* Alignment schenanigans */
__text_end__ = . ;
/* .bss section -- used for uninitialized data */
/* Located at the start of RAM */
.bss (NOLOAD) : {
__bss_start__ = . ;
*crt0.o( .ram_vectors )
__user_bss_start__ = . ;
*( .user_bss )
__user_bss_end__ = . ;
*( .shbss )
*( .bss .bss.* .gnu.linkonce.b.* )
*( COMMON )
*( .ram.b )
. = ALIGN( 8 ) ;
__bss_end__ = . ;
} >Ram AT>Flash
/* .data section -- used for initialized data */
.data : {
__data_start__ = . ;
KEEP( *( .jcr ) )
*( .got.plt ) *( .got )
*( .shdata )
*( .data .data.* .gnu.linkonce.d.* )
*( .ram )
. = ALIGN( 8 ) ;
__data_end__ = . ;
} >Ram AT>Flash
__data_init_start__ = LOADADDR( .data ) ;
/* Heap starts here and grows up in memory */
. = ALIGN( 8 ) ;
__heap_start__ = . ;
end = . ;
__end__ = . ;
.stab 0 (NOLOAD) : { *(.stab) }
.stabstr 0 (NOLOAD) : { *(.stabstr) }
/* DWARF debug sections. */
/* Symbols in the DWARF debugging sections are relative to the */
/* beginning of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* DWARF 3 */
.debug_pubtypes 0 : { *(.debug_pubtypes) }
.debug_ranges 0 : { *(.debug_ranges) }
.note.gnu.arm.ident 0 : { KEEP( *( .note.gnu.arm.ident ) ) }
.ARM.attributes 0 : {
KEEP( *( .ARM.attributes ) )
KEEP( *( .gnu.attributes ) )
}
/DISCARD/ : { *( .note.GNU-stack ) }
/* C data can be defined as being in special purpose RAMs using
* __attribute__ ((section ("ethram"))) for example. */
.usbram (NOLOAD):
{
*( .usbram )
*( .usbram.* )
} > UsbRam
.ethram (NOLOAD):
{
*( .ethram )
*( .ethram.* )
} > EthRam
.canram (NOLOAD):
{
*( .canram )
*( .canram.* )
} > CanRam
.batram (NOLOAD):
{
*( .batram )
*( .batram.* )
} > BatRam
}

View File

@ -0,0 +1,195 @@
/* .include "vector_defns.h" */
.section .privileged_code, "ax"
.arm
.weak __mbed_fiq
.weak __mbed_undef
.weak __mbed_prefetch_abort
.weak __mbed_data_abort
.weak __mbed_irq
.weak __mbed_swi
.weak __mbed_dcc_irq
.weak __mbed_reset
.global __mbed_init_realmonitor
.weak SVC_Handler
.weak IRQ_Handler
/* .global __mbed_init */
__mbed_fiq:
B __mbed_fiq
__mbed_undef:
LDR PC, =0x7fffffa0
__mbed_prefetch_abort:
LDR PC, =0x7fffffb0
__mbed_data_abort:
LDR PC, =0x7fffffc0
__mbed_irq:
/*
If RTOS is enabled then goto RTOS IRQ handler
*/
PUSH {R0}
LDR R0, =IRQ_Handler
CMP R0, #0
POP {R0}
BNE IRQ_Handler
/*
else use CMSIS IRQ handler
*/
MSR CPSR_c, #0x1F|0x80|0x40
STMDB sp!, {r0-r3,r12,lr}
MOV r0, #0xFFFFFF00
LDR r0, [r0]
MOV lr, pc
BX r0
MOV r0, #0xFFFFFF00
STR r0, [r0]
LDMFD sp!,{r0-r3,r12,lr}
MSR CPSR_c, #0x12|0x80|0x40
SUBS pc, lr, #4
__mbed_swi:
/*
If RTOS is enabled then goto RTOS SVC handler
*/
PUSH {R0}
LDR R0, =SVC_Handler
CMP R0, #0
POP {R0}
BNE SVC_Handler
/*
else use CMSIS SVC handler
*/
STMFD sp!, {a4, r4, ip, lr}
LDR r4, =0x40000040
LDR a4, =0x00940000
LDR PC, =0x7ffff820
__mbed_dcc_irq:
LDMFD sp!,{r0-r3,r12,lr}
MSR CPSR_c, #0x12|0x80|0x40
SUB lr, lr, #4
STMFD sp!, {ip,lr}
LDR LR, =0xfffff000
STR LR, [LR, #0xf00]
LDR PC, =0x7fffffe0
/*
__mbed_reset is called after reset
we setup the stacks and realmonitor, then call Reset_Handler like on M3
*/
.section .text, "ax"
.arm
.global Reset_handler
Reset_Handler:
.extern __libc_init_array
.extern SystemInit
.weak software_init_hook
LDR R0, =SystemInit
MOV LR, PC
BX R0
/* if (software_init_hook) // give control to the RTOS
software_init_hook(); // this will also call __libc_init_array
*/
LDR R0, =software_init_hook
CMP R0, #0
BEQ nortos
ORR R0,R0,#1 /* set thumb address */
BX R0
/* else */
nortos:
LDR R0, =__libc_init_array
MOV LR, PC
BX R0
MSR CPSR_c, #0x1F /* enable irq */
LDR R0, =main
BX R0
__mbed_reset:
LDR R0, =( __SRAM_segment_end__ )
MSR CPSR_c, #0x1B|0x80|0x40
MOV SP, R0
SUB R0, R0, #0x00000040
MSR CPSR_c, #0x17|0x80|0x40
MOV SP, R0
SUB R0, R0, #0x00000040
MSR CPSR_c, #0x11|0x80|0x40
MOV SP, R0
SUB R0, R0, #0x00000040
MSR CPSR_c, #0x12|0x80|0x40
MOV SP, R0
SUB R0, R0, #0x00000040
MSR CPSR_c, #0x13|0x80|0x40
MOV SP, R0
SUB R0, R0, #0x00000040
/*
MSR CPSR_c, #0x10|0x80|0x40
MOV SP, R0
*/
MSR CPSR_c, #0x1F|0x80|0x40
MOV SP, R0
MSR CPSR_c, #0x13|0x80|0x40 /* execute in Supervisor mode */
/* Relocate .data section (Copy from ROM to RAM) */
LDR R1, =__text_end__ /* _etext */
LDR R2, =__data_start__ /* _data */
LDR R3, =__data_end__ /* _edata */
CMP R2, R3
BEQ DataIsEmpty
LoopRel: CMP R2, R3
LDRLO R0, [R1], #4
STRLO R0, [R2], #4
BLO LoopRel
DataIsEmpty:
/* Clear .bss section (Zero init) */
MOV R0, #0
LDR R1, =__bss_start__
LDR R2, =__bss_end__
CMP R1,R2
BEQ BSSIsEmpty
LoopZI: CMP R1, R2
STRLO R0, [R1], #4
BLO LoopZI
BSSIsEmpty:
/* Init realmonitor */
/*
LDR R0, =__mbed_init_realmonitor
MOV LR, PC
BX R0
*/
/* Go to Reset_Handler */
LDR R0, =Reset_Handler
BX R0

View File

@ -0,0 +1,45 @@
# 1 "vector_table.s"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "vector_table.s"
;
# 1 "vector_defns.h" 1
# 7 "vector_table.s" 2
;
.section .vectors, "ax"
.arm
.global __main
.global __mbed_reset
.global __mbed_undef
.global __mbed_swi
.global __mbed_prefetch_abort
.global __mbed_data_abort
.global __mbed_irq
.global __mbed_fiq
;
_start:
LDR PC, =__mbed_reset
LDR PC, =__mbed_undef
LDR PC, =__mbed_swi
LDR PC, =__mbed_prefetch_abort
LDR PC, =__mbed_data_abort
NOP ;
LDR PC, =__mbed_irq
LDR PC, =__mbed_fiq

View File

@ -0,0 +1,13 @@
/* mbed Microcontroller Library - CMSIS
* Copyright (C) 2009-2015 ARM Limited. All rights reserved.
*
* A generic CMSIS include header, pulling in LPC2368 specifics
*/
#ifndef MBED_CMSIS_H
#define MBED_CMSIS_H
#include "LPC24xx.h"
#include "cmsis_nvic.h"
#endif

View File

@ -0,0 +1,40 @@
/* mbed Microcontroller Library
* CMSIS-style functionality to support dynamic vectors
*******************************************************************************
* Copyright (c) 2011-2015 ARM Limited. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of ARM Limited 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 THE COPYRIGHT HOLDER OR 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.
*******************************************************************************
*/
#include "cmsis_nvic.h"
void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) {
LPC_VIC->VectAddr[(int)IRQn] = vector;
}
uint32_t NVIC_GetVector(IRQn_Type IRQn) {
return LPC_VIC->VectAddr[(int)IRQn];
}

View File

@ -0,0 +1,51 @@
/* mbed Microcontroller Library
* CMSIS-style functionality to support dynamic vectors
*******************************************************************************
* Copyright (c) 2011-2015 ARM Limited. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of ARM Limited 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 THE COPYRIGHT HOLDER OR 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 MBED_CMSIS_NVIC_H
#define MBED_CMSIS_NVIC_H
#define NVIC_NUM_VECTORS 32
#define NVIC_USER_IRQ_OFFSET 0
#include "cmsis.h"
#ifdef __cplusplus
extern "C" {
#endif
void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector);
uint32_t NVIC_GetVector(IRQn_Type IRQn);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,44 @@
/* mbed Microcontroller Library
* Copyright (C) 2008-2015 ARM Limited. All rights reserved.
*
* ARM7 version of CMSIS-like functionality - not advised for use outside mbed!
* based on core_cm3.h, V1.20
*/
#include <stdint.h>
/* define compiler specific symbols */
#if defined ( __CC_ARM )
#define __ASM __asm /*!< asm keyword for armcc */
#define __INLINE __inline /*!< inline keyword for armcc */
#elif defined ( __ICCARM__ )
#define __ASM __asm /*!< asm keyword for iarcc */
#define __INLINE inline /*!< inline keyword for iarcc. Only avaiable in High optimization mode! */
#elif defined ( __GNUC__ )
#define __ASM __asm /*!< asm keyword for gcc */
#define __INLINE inline /*!< inline keyword for gcc */
#elif defined ( __TASKING__ )
#define __ASM __asm /*!< asm keyword for TASKING Compiler */
#define __INLINE inline /*!< inline keyword for TASKING Compiler */
#endif
#if defined ( __CC_ARM )
/**
* @brief Return the Main Stack Pointer (return current ARM7 stack)
*
* @param none
* @return uint32_t Main Stack Pointer
*
* Return the current value of the MSP (main stack pointer)
* Cortex processor register
*/
uint32_t __get_MSP(void)
{
return __current_sp();
}
#endif

View File

@ -0,0 +1,343 @@
/* mbed Microcontroller Library
* Copyright (C) 2008-2015 ARM Limited. All rights reserved.
*
* ARM7 version of CMSIS-like functionality - not advised for use outside mbed!
* based on core_cm3.h, V1.20
*/
#ifndef __ARM7_CORE_H__
#define __ARM7_CORE_H__
#include "vector_defns.h"
#ifdef __cplusplus
extern "C" {
#endif
//#include "cmsis_nvic.h"
#define __CM3_CMSIS_VERSION_MAIN (0x01) /*!< [31:16] CMSIS HAL main version */
#define __CM3_CMSIS_VERSION_SUB (0x20) /*!< [15:0] CMSIS HAL sub version */
#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16) | __CM3_CMSIS_VERSION_SUB) /*!< CMSIS HAL version number */
#define __CORTEX_M (0x00) /*!< Cortex core */
/**
* Lint configuration \n
* ----------------------- \n
*
* The following Lint messages will be suppressed and not shown: \n
* \n
* --- Error 10: --- \n
* register uint32_t __regBasePri __asm("basepri"); \n
* Error 10: Expecting ';' \n
* \n
* --- Error 530: --- \n
* return(__regBasePri); \n
* Warning 530: Symbol '__regBasePri' (line 264) not initialized \n
* \n
* --- Error 550: --- \n
* __regBasePri = (basePri & 0x1ff); \n
* } \n
* Warning 550: Symbol '__regBasePri' (line 271) not accessed \n
* \n
* --- Error 754: --- \n
* uint32_t RESERVED0[24]; \n
* Info 754: local structure member '<some, not used in the HAL>' (line 109, file ./cm3_core.h) not referenced \n
* \n
* --- Error 750: --- \n
* #define __CM3_CORE_H__ \n
* Info 750: local macro '__CM3_CORE_H__' (line 43, file./cm3_core.h) not referenced \n
* \n
* --- Error 528: --- \n
* static __INLINE void NVIC_DisableIRQ(uint32_t IRQn) \n
* Warning 528: Symbol 'NVIC_DisableIRQ(unsigned int)' (line 419, file ./cm3_core.h) not referenced \n
* \n
* --- Error 751: --- \n
* } InterruptType_Type; \n
* Info 751: local typedef 'InterruptType_Type' (line 170, file ./cm3_core.h) not referenced \n
* \n
* \n
* Note: To re-enable a Message, insert a space before 'lint' * \n
*
*/
/*lint -save */
/*lint -e10 */
/*lint -e530 */
/*lint -e550 */
/*lint -e754 */
/*lint -e750 */
/*lint -e528 */
/*lint -e751 */
#include <stdint.h> /* Include standard types */
#if defined ( __CC_ARM )
/**
* @brief Return the Main Stack Pointer (current ARM7 stack)
*
* @param none
* @return uint32_t Main Stack Pointer
*
* Return the current value of the MSP (main stack pointer)
* Cortex processor register
*/
extern uint32_t __get_MSP(void);
#endif
#if defined (__ICCARM__)
#include <intrinsics.h> /* IAR Intrinsics */
#endif
#ifndef __NVIC_PRIO_BITS
#define __NVIC_PRIO_BITS 4 /*!< standard definition for NVIC Priority Bits */
#endif
typedef struct
{
uint32_t IRQStatus;
uint32_t FIQStatus;
uint32_t RawIntr;
uint32_t IntSelect;
uint32_t IntEnable;
uint32_t IntEnClr;
uint32_t SoftInt;
uint32_t SoftIntClr;
uint32_t Protection;
uint32_t SWPriorityMask;
uint32_t RESERVED0[54];
uint32_t VectAddr[32];
uint32_t RESERVED1[32];
uint32_t VectPriority[32];
uint32_t RESERVED2[800];
uint32_t Address;
} NVIC_TypeDef;
#define NVIC_BASE (0xFFFFF000)
#define NVIC (( NVIC_TypeDef *) NVIC_BASE)
/**
* IO definitions
*
* define access restrictions to peripheral registers
*/
#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 */
#if defined ( __CC_ARM )
#define __ASM __asm /*!< asm keyword for ARM Compiler */
#define __INLINE __inline /*!< inline keyword for ARM Compiler */
#elif defined ( __ICCARM__ )
#define __ASM __asm /*!< asm keyword for IAR Compiler */
#define __INLINE inline /*!< inline keyword for IAR Compiler. Only avaiable in High optimization mode! */
#elif defined ( __GNUC__ )
#define __ASM __asm /*!< asm keyword for GNU Compiler */
#define __INLINE inline /*!< inline keyword for GNU Compiler */
#elif defined ( __TASKING__ )
#define __ASM __asm /*!< asm keyword for TASKING Compiler */
#define __INLINE inline /*!< inline keyword for TASKING Compiler */
#endif
/* ################### Compiler specific Intrinsics ########################### */
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
/* ARM armcc specific functions */
#define __enable_fault_irq __enable_fiq
#define __disable_fault_irq __disable_fiq
#define __NOP __nop
//#define __WFI __wfi
//#define __WFE __wfe
//#define __SEV __sev
//#define __ISB() __isb(0)
//#define __DSB() __dsb(0)
//#define __DMB() __dmb(0)
//#define __REV __rev
//#define __RBIT __rbit
#define __LDREXB(ptr) ((unsigned char ) __ldrex(ptr))
#define __LDREXH(ptr) ((unsigned short) __ldrex(ptr))
#define __LDREXW(ptr) ((unsigned int ) __ldrex(ptr))
#define __STREXB(value, ptr) __strex(value, ptr)
#define __STREXH(value, ptr) __strex(value, ptr)
#define __STREXW(value, ptr) __strex(value, ptr)
#define __disable_irq() unsigned tmp_IntEnable = LPC_VIC->IntEnable; \
LPC_VIC->IntEnClr = 0xffffffff
#define __enable_irq() LPC_VIC->IntEnable = tmp_IntEnable
#elif (defined (__ICCARM__)) /*------------------ ICC Compiler -------------------*/
#define __enable_irq __enable_interrupt /*!< global Interrupt enable */
#define __disable_irq __disable_interrupt /*!< global Interrupt disable */
#define __NOP __no_operation() /*!< no operation intrinsic in IAR Compiler */
#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/
static __INLINE void __enable_irq() {
unsigned long temp;
__asm__ __volatile__("mrs %0, cpsr\n"
"bic %0, %0, #0x80\n"
"msr cpsr_c, %0"
: "=r" (temp)
:
: "memory");
}
static __INLINE uint32_t __disable_irq() {
unsigned long old,temp;
__asm__ __volatile__("mrs %0, cpsr\n"
"orr %1, %0, #0xc0\n"
"msr cpsr_c, %1"
: "=r" (old), "=r" (temp)
:
: "memory");
return (old & 0x80) == 0;
}
static __INLINE void __NOP() { __ASM volatile ("nop"); }
/** \brief Get Control Bits of Status Register
This function returns the content of the Control Bits from the Program Status Register.
\return Control Bits value
*/
__attribute__( ( always_inline ) ) static inline uint32_t __get_CONTROL(void)
{
uint32_t result;
__asm__ __volatile__ ("MRS %0, CPSR \n"
"AND %0,%0,#31" : "=r" (result) );
return(result);
}
#define MODE_USER 0x10
#define MODE_FIQ 0x11
#define MODE_IRQ 0x12
#define MODE_SUPERVISOR 0x13
#define MODE_ABORT 0x17
#define MODE_UNDEFINED 0x1B
#define MODE_SYSTEM 0x1F
#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
/**
* @brief Enable Interrupt in NVIC Interrupt Controller
*
* @param IRQn_Type IRQn specifies the interrupt number
* @return none
*
* Enable a device specific interupt in the NVIC interrupt controller.
* The interrupt number cannot be a negative value.
*/
static __INLINE void NVIC_EnableIRQ(uint32_t IRQn)
{
NVIC->IntEnable = 1 << (uint32_t)IRQn;
}
/**
* @brief Disable the interrupt line for external interrupt specified
*
* @param IRQn_Type IRQn is the positive number of the external interrupt
* @return none
*
* Disable a device specific interupt in the NVIC interrupt controller.
* The interrupt number cannot be a negative value.
*/
static __INLINE void NVIC_DisableIRQ(uint32_t IRQn)
{
NVIC->IntEnClr = 1 << (uint32_t)IRQn;
}
/**
* @brief Pend Interrupt in NVIC Interrupt Controller
*
* @param IRQn_Type IRQn specifies the interrupt number
* @return none
*
* Force software a device specific interupt in the NVIC interrupt controller.
* The interrupt number cannot be a negative value.
*/
static __INLINE void NVIC_PendIRQ(uint32_t IRQn)
{
NVIC->SoftInt = 1 << (uint32_t)IRQn;
}
/**
* @brief Unpend the interrupt in NVIC Interrupt Controller
*
* @param IRQn_Type IRQn is the positive number of the external interrupt
* @return none
*
* Clear software device specific interupt in the NVIC interrupt controller.
* The interrupt number cannot be a negative value.
*/
static __INLINE void NVIC_UnpendIRQ(uint32_t IRQn)
{
NVIC->SoftIntClr = 1 << (uint32_t)IRQn;
}
/**
* @brief Is IRQ pending
*
* @param IRQn_Type IRQn is the positive number of the external interrupt
* @return 0 if IRQ is not pending
* 1 if IRQ is pending
*
* Returns software device specific interupt in the NVIC interrupt controller.
* The interrupt number cannot be a negative value.
*/
static __INLINE uint32_t NVIC_Pending(uint32_t IRQn)
{
return (NVIC->SoftInt & (1 << (uint32_t)IRQn)) != 0;
}
static __INLINE uint32_t __get_IPSR(void)
{
unsigned i;
for(i = 0; i < 32; i ++)
if(NVIC->Address == NVIC->VectAddr[i])
return i;
return 1; // 1 is an invalid entry in the interrupt table on LPC2460
}
#ifdef __cplusplus
}
#endif
#endif /* __ARM7_CORE_H__ */
/*lint -restore */

View File

@ -0,0 +1,164 @@
/* mbed Microcontroller Library
* Copyright (C) 2008-2015 ARM Limited. All rights reserved.
*
* ARM7 version of CMSIS-like functionality - not advised for use outside mbed!
*/
#include <stdint.h>
#include "LPC24xx.h"
#define CLOCK_SETUP 1
#define SCS_Val ((1<<4) | (1 << 5))
#define CLKSRCSEL_Val 0x00000001
#define PLL0_SETUP 1
#define PLL0CFG_Val 0x0000000B
#define CCLKCFG_Val 0x00000003
#define USBCLKCFG_Val 0x00000005
#define PCLKSEL0_Val 0x00000000
#define PCLKSEL1_Val 0x00000000
#define PCONP_Val (1 << PCEMC)
#define CLKOUTCFG_Val 0x00000000
#define MAMCR_Val 0x00000002
#define MAMTIM_Val 0x00000004
/*----------------------------------------------------------------------------
DEFINES
*----------------------------------------------------------------------------*/
#define XTAL (12000000UL) /* Oscillator frequency */
#define OSC_CLK ( XTAL) /* Main oscillator frequency */
#define RTC_CLK ( 32000UL) /* RTC oscillator frequency */
#define IRC_OSC ( 4000000UL) /* Internal RC oscillator frequency */
/* F_cco0 = (2 * M * F_in) / N */
#define __M (((PLL0CFG_Val ) & 0x7FFF) + 1)
#define __N (((PLL0CFG_Val >> 16) & 0x00FF) + 1)
#define __FCCO(__F_IN) ((2 * __M * __F_IN) / __N)
#define __CCLK_DIV (((CCLKCFG_Val ) & 0x00FF) + 1)
/* Determine core clock frequency according to settings */
#if (PLL0_SETUP)
#if ((CLKSRCSEL_Val & 0x03) == 1)
#define __CORE_CLK (__FCCO(OSC_CLK) / __CCLK_DIV)
#elif ((CLKSRCSEL_Val & 0x03) == 2)
#define __CORE_CLK (__FCCO(RTC_CLK) / __CCLK_DIV)
#else
#define __CORE_CLK (__FCCO(IRC_OSC) / __CCLK_DIV)
#endif
#endif
/*----------------------------------------------------------------------------
Clock Variable definitions
*----------------------------------------------------------------------------*/
uint32_t SystemCoreClock = __CORE_CLK;/*!< System Clock Frequency (Core Clock)*/
/*----------------------------------------------------------------------------
Clock functions
*----------------------------------------------------------------------------*/
void SystemCoreClockUpdate (void) /* Get Core Clock Frequency */
{
/* Determine clock frequency according to clock register values */
if (((LPC_SC->PLL0STAT >> 24) & 3) == 3) { /* If PLL0 enabled and connected */
switch (LPC_SC->CLKSRCSEL & 0x03) {
case 0: /* Int. RC oscillator => PLL0 */
case 3: /* Reserved, default to Int. RC */
SystemCoreClock = (IRC_OSC *
(((2 * ((LPC_SC->PLL0STAT & 0x7FFF) + 1))) /
(((LPC_SC->PLL0STAT >> 16) & 0xFF) + 1)) /
((LPC_SC->CCLKCFG & 0xFF)+ 1));
break;
case 1: /* Main oscillator => PLL0 */
SystemCoreClock = (OSC_CLK *
(((2 * ((LPC_SC->PLL0STAT & 0x7FFF) + 1))) /
(((LPC_SC->PLL0STAT >> 16) & 0xFF) + 1)) /
((LPC_SC->CCLKCFG & 0xFF)+ 1));
break;
case 2: /* RTC oscillator => PLL0 */
SystemCoreClock = (RTC_CLK *
(((2 * ((LPC_SC->PLL0STAT & 0x7FFF) + 1))) /
(((LPC_SC->PLL0STAT >> 16) & 0xFF) + 1)) /
((LPC_SC->CCLKCFG & 0xFF)+ 1));
break;
}
} else {
switch (LPC_SC->CLKSRCSEL & 0x03) {
case 0: /* Int. RC oscillator => PLL0 */
case 3: /* Reserved, default to Int. RC */
SystemCoreClock = IRC_OSC / ((LPC_SC->CCLKCFG & 0xFF)+ 1);
break;
case 1: /* Main oscillator => PLL0 */
SystemCoreClock = OSC_CLK / ((LPC_SC->CCLKCFG & 0xFF)+ 1);
break;
case 2: /* RTC oscillator => PLL0 */
SystemCoreClock = RTC_CLK / ((LPC_SC->CCLKCFG & 0xFF)+ 1);
break;
}
}
}
void vectorRemap()
{
#define ARM_VECTOR_REBASE (0x40000000)
extern unsigned long __privileged_code_start__; /* Startup code address from linker */
int i;
/* Copy ARM vector table into internal RAM */
for (i = 0; i <= 56; i+=2)
{
*(unsigned short *)(ARM_VECTOR_REBASE + i) = *(unsigned short *)((unsigned long)(&__privileged_code_start__) + i);
}
// *(unsigned long *)(ARM_VECTOR_REBASE) = (unsigned long)armUnexpReset;
/* Remap the interrupt vectors to RAM */
LPC_SC->MEMMAP = 2;
}
/**
* Initialize the system
*
* @param none
* @return none
*
* @brief Setup the microcontroller system.
* Initialize the System and update the SystemFrequency variable.
*/
void SystemInit (void)
{
LPC_WDT->WDMOD = 0; /* Disable internal watchdog */
#if (CLOCK_SETUP) /* Clock Setup */
LPC_SC->SCS = SCS_Val;
if (SCS_Val & (1 << 5)) { /* If Main Oscillator is enabled */
while ((LPC_SC->SCS & (1 << 6)) == 0); /* Wait for Oscillator to be ready */
}
LPC_SC->CCLKCFG = CCLKCFG_Val; /* Setup Clock Divider */
#if (PLL0_SETUP)
LPC_SC->CLKSRCSEL = CLKSRCSEL_Val; /* Select Clock Source for PLL0 */
LPC_SC->PLL0CFG = PLL0CFG_Val;
LPC_SC->PLL0CON = 0x01; /* PLL0 Enable */
LPC_SC->PLL0FEED = 0xAA;
LPC_SC->PLL0FEED = 0x55;
while (!(LPC_SC->PLL0STAT & (1 << 26))); /* Wait for PLOCK0 */
LPC_SC->PLL0CON = 0x03; /* PLL0 Enable & Connect */
LPC_SC->PLL0FEED = 0xAA;
LPC_SC->PLL0FEED = 0x55;
#endif
LPC_SC->USBCLKCFG = USBCLKCFG_Val; /* Setup USB Clock Divider */
#endif
LPC_SC->PCLKSEL0 = PCLKSEL0_Val; /* Peripheral Clock Selection */
LPC_SC->PCLKSEL1 = PCLKSEL1_Val;
LPC_SC->PCONP = PCONP_Val; /* Power Control for Peripherals */
// Setup MAM
LPC_SC->MAMTIM = MAMTIM_Val;
LPC_SC->MAMCR = MAMCR_Val;
vectorRemap();
}

View File

@ -0,0 +1,44 @@
/* mbed Microcontroller Library
* Copyright (C) 2008-2015 ARM Limited. All rights reserved.
*
* ARM7 version of CMSIS-like functionality - not advised for use outside mbed!
* based on cmsis system_LPC17xx.h
*/
#ifndef __SYSTEM_LPC24xx_H
#define __SYSTEM_LPC24xx_H
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
/**
* Initialize the system
*
* @param none
* @return none
*
* @brief Setup the microcontroller system.
* Initialize the System and update the SystemCoreClock variable.
*/
extern void SystemInit (void);
/**
* Update SystemCoreClock variable
*
* @param none
* @return none
*
* @brief Updates the SystemCoreClock with current core Clock
* retrieved from cpu registers.
*/
extern void SystemCoreClockUpdate (void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,77 @@
/* mbed Microcontroller Library - Vectors
* Copyright (c) 2006-2015 ARM Limited. All rights reserved.
*/
#ifndef MBED_VECTOR_DEFNS_H
#define MBED_VECTOR_DEFNS_H
// Assember Macros
#ifdef __ARMCC_VERSION
#define EXPORT(x) EXPORT x
#define WEAK_EXPORT(x) EXPORT x [WEAK]
#define IMPORT(x) IMPORT x
#define LABEL(x) x
#else
#define EXPORT(x) .global x
#define WEAK_EXPORT(x) .weak x
#define IMPORT(x) .global x
#define LABEL(x) x:
#endif
// RealMonitor
// Requires RAM (0x40000040-0x4000011F) to be allocated by the linker
// RealMonitor entry points
#define rm_init_entry 0x7fffff91
#define rm_undef_handler 0x7fffffa0
#define rm_prefetchabort_handler 0x7fffffb0
#define rm_dataabort_handler 0x7fffffc0
#define rm_irqhandler2 0x7fffffe0
//#define rm_RunningToStopped 0x7ffff808 // ARM - MBED64
#define rm_RunningToStopped 0x7ffff820 // ARM - PHAT40
// Unofficial RealMonitor entry points and variables
#define RM_MSG_SWI 0x00940000
#define StateP 0x40000040
// VIC register addresses
#define VIC_Base 0xfffff000
#define VICAddress_Offset 0xf00
#define VICVectAddr0_Offset 0x100
#define VICVectAddr2_Offset 0x108
#define VICVectAddr3_Offset 0x10c
#define VICVectAddr31_Offset 0x17c
#define VICIntEnClr_Offset 0x014
#define VICIntEnClr (*(volatile unsigned long *)(VIC_Base + 0x014))
#define VICVectAddr2 (*(volatile unsigned long *)(VIC_Base + 0x108))
#define VICVectAddr3 (*(volatile unsigned long *)(VIC_Base + 0x10C))
// ARM Mode bits and Interrupt flags in PSRs
#define Mode_USR 0x10
#define Mode_FIQ 0x11
#define Mode_IRQ 0x12
#define Mode_SVC 0x13
#define Mode_ABT 0x17
#define Mode_UND 0x1B
#define Mode_SYS 0x1F
#define I_Bit 0x80 // when I bit is set, IRQ is disabled
#define F_Bit 0x40 // when F bit is set, FIQ is disabled
// MCU RAM
#define LPC2460_RAM_ADDRESS 0x40000000 // RAM Base
#define LPC2460_RAM_SIZE 0x10000 // 64KB
// ISR Stack Allocation
#define UND_stack_size 0x00000040
#define SVC_stack_size 0x00000040
#define ABT_stack_size 0x00000040
#define FIQ_stack_size 0x00000000
#define IRQ_stack_size 0x00000040
#define ISR_stack_size (UND_stack_size + SVC_stack_size + ABT_stack_size + FIQ_stack_size + IRQ_stack_size)
// Full Descending Stack, so top-most stack points to just above the top of RAM
#define LPC2460_STACK_TOP (LPC2460_RAM_ADDRESS + LPC2460_RAM_SIZE)
#define USR_STACK_TOP (LPC2460_STACK_TOP - ISR_stack_size)
#endif

View File

@ -0,0 +1,22 @@
/* mbed Microcontroller Library - RealMonitor
* Copyright (c) 2006-2015 ARM Limited. All rights reserved.
*/
#include "vector_defns.h"
extern void __mbed_dcc_irq(void);
/* Function: __mbed_init_realmonitor
* Setup the RealMonitor DCC Interrupt Handlers
*/
void __mbed_init_realmonitor(void) __attribute__((weak));
void __mbed_init_realmonitor() {
// Disable all interrupts
VICIntEnClr = 0xffffffff;
// Set DCC interrupt vector addresses
VICVectAddr2 = (unsigned)&__mbed_dcc_irq;
VICVectAddr3 = (unsigned)&__mbed_dcc_irq;
// Initialise RealMonitor
((void (*)(void))rm_init_entry)();
}

View File

@ -0,0 +1,120 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_PERIPHERALNAMES_H
#define MBED_PERIPHERALNAMES_H
#include "cmsis.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
UART_0 = (int)LPC_UART0_BASE,
UART_1 = (int)LPC_UART1_BASE,
UART_2 = (int)LPC_UART2_BASE,
UART_3 = (int)LPC_UART3_BASE
} UARTName;
typedef enum {
ADC0_0 = 0,
ADC0_1,
ADC0_2,
ADC0_3,
ADC0_4,
ADC0_5,
ADC0_6,
ADC0_7
} ADCName;
typedef enum {
DAC_0 = 0
} DACName;
typedef enum {
SPI_0 = (int)LPC_SSP0_BASE,
SPI_1 = (int)LPC_SSP1_BASE
} SPIName;
typedef enum {
I2C_0 = (int)LPC_I2C0_BASE,
I2C_1 = (int)LPC_I2C1_BASE,
I2C_2 = (int)LPC_I2C2_BASE
} I2CName;
typedef enum {
PWM_1 = 1,
PWM_2,
PWM_3,
PWM_4,
PWM_5,
PWM_6
} PWMName;
typedef enum {
CAN_1 = (int)LPC_CAN1_BASE,
CAN_2 = (int)LPC_CAN2_BASE
} CANName;
#define STDIO_UART_TX USBTX
#define STDIO_UART_RX USBRX
#define STDIO_UART UART_2
// Default peripherals
#define MBED_SPI0 p5, p6, p7, p8
//#define MBED_SPI1 p11, p12, p13, p14
#define MBED_UART0 p9, p10
#define MBED_UART1 p13, p14
#define MBED_UART2 p15, p16
#define MBED_UARTUSB USBTX, USBRX
#define MBED_I2C0 p17, p18
//#define MBED_I2C1 p9, p10
#define MBED_CAN0 p19, p20
#define MBED_ANALOGOUT0 p21
#define MBED_ANALOGIN0 p22
#define MBED_ANALOGIN1 p23
//#define MBED_ANALOGIN2 p17
//#define MBED_ANALOGIN3 p18
//#define MBED_ANALOGIN4 p19
//#define MBED_ANALOGIN5 p20
#define MBED_PWMOUT0 p24
#define MBED_PWMOUT1 p25
#define MBED_PWMOUT2 p26
#define MBED_PWMOUT3 p27
//#define MBED_PWMOUT4 p22
//#define MBED_PWMOUT5 p21
#define MBED_USB_D_PLUS p28
#define MBED_USB_D_MINUS p29
#define MBED_MCICLK p30
#define MBED_MCICMD p31
#define MBED_MCIDAT0 p32
#define MBED_MCIDAT1 p33
#define MBED_MCIDAT2 p34
#define MBED_MCIDAT3 p35
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,112 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_PINNAMES_H
#define MBED_PINNAMES_H
#include "cmsis.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
PIN_INPUT,
PIN_OUTPUT
} PinDirection;
#define PORT_SHIFT 5
typedef enum {
// LPC Pin Names
P0_0 = LPC_GPIO0_BASE,
P0_1, P0_2, P0_3, P0_4, P0_5, P0_6, P0_7, P0_8, P0_9, P0_10, P0_11, P0_12, P0_13, P0_14, P0_15, P0_16, P0_17, P0_18, P0_19, P0_20, P0_21, P0_22, P0_23, P0_24, P0_25, P0_26, P0_27, P0_28, P0_29, P0_30, P0_31,
P1_0, P1_1, P1_2, P1_3, P1_4, P1_5, P1_6, P1_7, P1_8, P1_9, P1_10, P1_11, P1_12, P1_13, P1_14, P1_15, P1_16, P1_17, P1_18, P1_19, P1_20, P1_21, P1_22, P1_23, P1_24, P1_25, P1_26, P1_27, P1_28, P1_29, P1_30, P1_31,
P2_0, P2_1, P2_2, P2_3, P2_4, P2_5, P2_6, P2_7, P2_8, P2_9, P2_10, P2_11, P2_12, P2_13, P2_14, P2_15, P2_16, P2_17, P2_18, P2_19, P2_20, P2_21, P2_22, P2_23, P2_24, P2_25, P2_26, P2_27, P2_28, P2_29, P2_30, P2_31,
P3_0, P3_1, P3_2, P3_3, P3_4, P3_5, P3_6, P3_7, P3_8, P3_9, P3_10, P3_11, P3_12, P3_13, P3_14, P3_15, P3_16, P3_17, P3_18, P3_19, P3_20, P3_21, P3_22, P3_23, P3_24, P3_25, P3_26, P3_27, P3_28, P3_29, P3_30, P3_31,
P4_0, P4_1, P4_2, P4_3, P4_4, P4_5, P4_6, P4_7, P4_8, P4_9, P4_10, P4_11, P4_12, P4_13, P4_14, P4_15, P4_16, P4_17, P4_18, P4_19, P4_20, P4_21, P4_22, P4_23, P4_24, P4_25, P4_26, P4_27, P4_28, P4_29, P4_30, P4_31,
// mbed DIP Pin Names
p5 = P0_18,
p6 = P0_17,
p7 = P0_15,
p8 = P0_16,
p9 = P0_2,
p10 = P0_3,
p11 = P0_18,
p12 = P0_17,
p13 = P2_0,
p14 = P2_1,
p15 = P4_28,
p16 = P4_29,
p17 = P2_30,
p18 = P2_31,
p19 = P0_0,
p20 = P0_1,
p21 = P0_26,
p22 = P0_12,
p23 = P0_13,
p24 = P1_20,
p25 = P1_21,
p26 = P1_23,
p27 = P1_24,
p28 = P0_29,
p29 = P0_30,
p30 = P1_2,
p31 = P1_3,
p32 = P1_6,
p33 = P1_7,
p34 = P1_11,
p35 = P1_12,
// Other mbed Pin Names
LED1 = P1_19,
LED2 = P2_26,
LED3 = P2_27,
LED4 = P2_27,
USBTX = P2_8,
USBRX = P2_9,
EXT_WDT = P0_10,
// Not connected
NC = (int)0xFFFFFFFF
} PinName;
typedef enum {
PullUp = 0,
PullDown = 3,
PullNone = 2,
OpenDrain = 4,
PullDefault = PullDown
} PinMode;
// version of PINCON_TypeDef using register arrays
typedef struct {
__IO uint32_t PINSEL[11];
uint32_t RESERVED0[5];
__IO uint32_t PINMODE[10];
} PINCONARRAY_TypeDef;
#define PINCONARRAY ((PINCONARRAY_TypeDef *)LPC_PINCON_BASE)
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,38 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_PORTNAMES_H
#define MBED_PORTNAMES_H
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
Port0 = 0,
Port1 = 1,
Port2 = 2,
Port3 = 3,
Port4 = 4
} PortName;
#define PORT_0 Port0
#define PORT_1 Port1
#define PORT_2 Port2
#define PORT_3 Port3
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,125 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed_assert.h"
#include "analogin_api.h"
#include "cmsis.h"
#include "pinmap.h"
#define ANALOGIN_MEDIAN_FILTER 1
#define ADC_10BIT_RANGE 0x3FF
#define ADC_12BIT_RANGE 0xFFF
static inline int div_round_up(int x, int y) {
return (x + (y - 1)) / y;
}
static const PinMap PinMap_ADC[] = {
{P0_23, ADC0_0, 1},
{P0_24, ADC0_1, 1},
{P0_25, ADC0_2, 1},
{P0_26, ADC0_3, 1},
{P1_30, ADC0_4, 3},
{P1_31, ADC0_5, 3},
{P0_12, ADC0_6, 3},
{P0_13, ADC0_7, 3},
{NC, NC, 0}
};
#define ADC_RANGE ADC_10BIT_RANGE
void analogin_init(analogin_t *obj, PinName pin) {
obj->adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
MBED_ASSERT(obj->adc != (ADCName)NC);
// ensure power is turned on
LPC_SC->PCONP |= (1 << PCADC);
// set PCLK of ADC to /1
LPC_SC->PCLKSEL0 &= ~(0x3 << 24);
LPC_SC->PCLKSEL0 |= (0x1 << 24);
uint32_t PCLK = SystemCoreClock;
// calculate minimum clock divider
// clkdiv = divider - 1
uint32_t MAX_ADC_CLK = 4500000;
uint32_t clkdiv = div_round_up(PCLK, MAX_ADC_CLK) - 1;
// Set the generic software-controlled ADC settings
LPC_ADC->ADCR = (0 << 0) // SEL: 0 = no channels selected
| (clkdiv << 8) // CLKDIV: PCLK max ~= 25MHz, /25 to give safe 1MHz at fastest
| (0 << 16) // BURST: 0 = software control
| (0 << 17) // CLKS: not applicable
| (1 << 21) // PDN: 1 = operational
| (0 << 24) // START: 0 = no start
| (0 << 27); // EDGE: not applicable
pinmap_pinout(pin, PinMap_ADC);
}
static inline uint32_t adc_read(analogin_t *obj) {
// Select the appropriate channel and start conversion
LPC_ADC->ADCR &= ~0xFF;
LPC_ADC->ADCR |= 1 << (int)obj->adc;
LPC_ADC->ADCR |= 1 << 24;
// Repeatedly get the sample data until DONE bit
unsigned int data;
do {
data = LPC_ADC->ADGDR;
} while ((data & ((unsigned int)1 << 31)) == 0);
// Stop conversion
LPC_ADC->ADCR &= ~(1 << 24);
return (data >> 6) & ADC_RANGE; // 10 bit
}
static inline void order(uint32_t *a, uint32_t *b) {
if (*a > *b) {
uint32_t t = *a;
*a = *b;
*b = t;
}
}
static inline uint32_t adc_read_u32(analogin_t *obj) {
uint32_t value;
#if ANALOGIN_MEDIAN_FILTER
uint32_t v1 = adc_read(obj);
uint32_t v2 = adc_read(obj);
uint32_t v3 = adc_read(obj);
order(&v1, &v2);
order(&v2, &v3);
order(&v1, &v2);
value = v2;
#else
value = adc_read(obj);
#endif
return value;
}
uint16_t analogin_read_u16(analogin_t *obj) {
uint32_t value = adc_read_u32(obj);
return (value << 6) | ((value >> 4) & 0x003F); // 10 bit
}
float analogin_read(analogin_t *obj) {
uint32_t value = adc_read_u32(obj);
return (float)value * (1.0f / (float)ADC_RANGE);
}

View File

@ -0,0 +1,75 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed_assert.h"
#include "analogout_api.h"
#include "cmsis.h"
#include "pinmap.h"
static const PinMap PinMap_DAC[] = {
{P0_26, DAC_0, 2},
{NC , NC , 0}
};
void analogout_init(dac_t *obj, PinName pin) {
obj->dac = (DACName)pinmap_peripheral(pin, PinMap_DAC);
MBED_ASSERT(obj->dac != (DACName)NC);
// power is on by default, set DAC clk divider is /4
LPC_SC->PCLKSEL0 &= ~(0x3 << 22);
// map out (must be done before accessing registers)
pinmap_pinout(pin, PinMap_DAC);
analogout_write_u16(obj, 0);
}
void analogout_free(dac_t *obj) {}
static inline void dac_write(int value) {
value &= 0x3FF; // 10-bit
// Set the DAC output
LPC_DAC->DACR = (0 << 16) // bias = 0
| (value << 6);
}
static inline int dac_read() {
return (LPC_DAC->DACR >> 6) & 0x3FF;
}
void analogout_write(dac_t *obj, float value) {
if (value < 0.0f) {
dac_write(0);
} else if (value > 1.0f) {
dac_write(0x3FF);
} else {
dac_write(value * (float)0x3FF);
}
}
void analogout_write_u16(dac_t *obj, uint16_t value) {
dac_write(value >> 6); // 10-bit
}
float analogout_read(dac_t *obj) {
uint32_t value = dac_read();
return (float)value * (1.0f / (float)0x3FF);
}
uint16_t analogout_read_u16(dac_t *obj) {
uint32_t value = dac_read(); // 10-bit
return (value << 6) | ((value >> 4) & 0x003F);
}

View File

@ -0,0 +1,303 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed_assert.h"
#include "can_api.h"
#include "cmsis.h"
#include "pinmap.h"
#include <math.h>
#include <string.h>
/* Acceptance filter mode in AFMR register */
#define ACCF_OFF 0x01
#define ACCF_BYPASS 0x02
#define ACCF_ON 0x00
#define ACCF_FULLCAN 0x04
/* There are several bit timing calculators on the internet.
http://www.port.de/engl/canprod/sv_req_form.html
http://www.kvaser.com/can/index.htm
*/
static const PinMap PinMap_CAN_RD[] = {
{P0_0 , CAN_1, 1},
{P0_4 , CAN_2, 2},
{P0_21, CAN_1, 3},
{P2_7 , CAN_2, 1},
{NC , NC , 0}
};
static const PinMap PinMap_CAN_TD[] = {
{P0_1 , CAN_1, 1},
{P0_5 , CAN_2, 2},
{P0_22, CAN_1, 3},
{P2_8 , CAN_2, 1},
{NC , NC , 0}
};
// Type definition to hold a CAN message
struct CANMsg {
unsigned int reserved1 : 16;
unsigned int dlc : 4; // Bits 16..19: DLC - Data Length Counter
unsigned int reserved0 : 10;
unsigned int rtr : 1; // Bit 30: Set if this is a RTR message
unsigned int type : 1; // Bit 31: Set if this is a 29-bit ID message
unsigned int id; // CAN Message ID (11-bit or 29-bit)
unsigned char data[8]; // CAN Message Data Bytes 0-7
};
typedef struct CANMsg CANMsg;
static uint32_t can_disable(can_t *obj) {
uint32_t sm = obj->dev->MOD;
obj->dev->MOD |= 1;
return sm;
}
static inline void can_enable(can_t *obj) {
if (obj->dev->MOD & 1) {
obj->dev->MOD &= ~(1);
}
}
int can_mode(can_t *obj, CanMode mode) {
return 0; // not implemented
}
int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle) {
return 0; // not implemented
}
static int can_pclk(can_t *obj) {
int value = 0;
switch ((int)obj->dev) {
case CAN_1: value = (LPC_SC->PCLKSEL0 & (0x3 << 26)) >> 26; break;
case CAN_2: value = (LPC_SC->PCLKSEL0 & (0x3 << 28)) >> 28; break;
}
switch (value) {
case 1: return 1;
case 2: return 2;
case 3: return 6;
default: return 4;
}
}
// This table has the sampling points as close to 75% as possible. The first
// value is TSEG1, the second TSEG2.
static const int timing_pts[23][2] = {
{0x0, 0x0}, // 2, 50%
{0x1, 0x0}, // 3, 67%
{0x2, 0x0}, // 4, 75%
{0x3, 0x0}, // 5, 80%
{0x3, 0x1}, // 6, 67%
{0x4, 0x1}, // 7, 71%
{0x5, 0x1}, // 8, 75%
{0x6, 0x1}, // 9, 78%
{0x6, 0x2}, // 10, 70%
{0x7, 0x2}, // 11, 73%
{0x8, 0x2}, // 12, 75%
{0x9, 0x2}, // 13, 77%
{0x9, 0x3}, // 14, 71%
{0xA, 0x3}, // 15, 73%
{0xB, 0x3}, // 16, 75%
{0xC, 0x3}, // 17, 76%
{0xD, 0x3}, // 18, 78%
{0xD, 0x4}, // 19, 74%
{0xE, 0x4}, // 20, 75%
{0xF, 0x4}, // 21, 76%
{0xF, 0x5}, // 22, 73%
{0xF, 0x6}, // 23, 70%
{0xF, 0x7}, // 24, 67%
};
static unsigned int can_speed(unsigned int sclk, unsigned int pclk, unsigned int cclk, unsigned char psjw) {
uint32_t btr;
uint16_t brp = 0;
uint32_t calcbit;
uint32_t bitwidth;
int hit = 0;
int bits;
bitwidth = sclk / (pclk * cclk);
brp = bitwidth / 0x18;
while ((!hit) && (brp < bitwidth / 4)) {
brp++;
for (bits = 22; bits > 0; bits--) {
calcbit = (bits + 3) * (brp + 1);
if (calcbit == bitwidth) {
hit = 1;
break;
}
}
}
if (hit) {
btr = ((timing_pts[bits][1] << 20) & 0x00700000)
| ((timing_pts[bits][0] << 16) & 0x000F0000)
| ((psjw << 14) & 0x0000C000)
| ((brp << 0) & 0x000003FF);
} else {
btr = 0xFFFFFFFF;
}
return btr;
}
void can_init(can_t *obj, PinName rd, PinName td) {
CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD);
CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD);
obj->dev = (LPC_CAN_TypeDef *)pinmap_merge(can_rd, can_td);
MBED_ASSERT((int)obj->dev != NC);
switch ((int)obj->dev) {
case CAN_1: LPC_SC->PCONP |= 1 << PCAN1; break;
case CAN_2: LPC_SC->PCONP |= 1 << PCAN2; break;
}
pinmap_pinout(rd, PinMap_CAN_RD);
pinmap_pinout(td, PinMap_CAN_TD);
can_reset(obj);
obj->dev->IER = 0; // Disable Interrupts
can_frequency(obj, 100000);
LPC_CANAF->AFMR = ACCF_BYPASS; // Bypass Filter
}
void can_free(can_t *obj) {
switch ((int)obj->dev) {
case CAN_1: LPC_SC->PCONP &= ~(1 << PCAN1); break;
case CAN_2: LPC_SC->PCONP &= ~(1 << PCAN2); break;
}
}
int can_frequency(can_t *obj, int f) {
int pclk = can_pclk(obj);
int btr = can_speed(SystemCoreClock, pclk, (unsigned int)f, 1);
if (btr > 0) {
uint32_t modmask = can_disable(obj);
obj->dev->BTR = btr;
obj->dev->MOD = modmask;
return 1;
} else {
return 0;
}
}
int can_write(can_t *obj, CAN_Message msg, int cc) {
unsigned int CANStatus;
CANMsg m;
can_enable(obj);
m.id = msg.id ;
m.dlc = msg.len & 0xF;
m.rtr = msg.type;
m.type = msg.format;
memcpy(m.data, msg.data, msg.len);
const unsigned int *buf = (const unsigned int *)&m;
CANStatus = obj->dev->SR;
if (CANStatus & 0x00000004) {
obj->dev->TFI1 = buf[0] & 0xC00F0000;
obj->dev->TID1 = buf[1];
obj->dev->TDA1 = buf[2];
obj->dev->TDB1 = buf[3];
if (cc) {
obj->dev->CMR = 0x30;
} else {
obj->dev->CMR = 0x21;
}
return 1;
} else if (CANStatus & 0x00000400) {
obj->dev->TFI2 = buf[0] & 0xC00F0000;
obj->dev->TID2 = buf[1];
obj->dev->TDA2 = buf[2];
obj->dev->TDB2 = buf[3];
if (cc) {
obj->dev->CMR = 0x50;
} else {
obj->dev->CMR = 0x41;
}
return 1;
} else if (CANStatus & 0x00040000) {
obj->dev->TFI3 = buf[0] & 0xC00F0000;
obj->dev->TID3 = buf[1];
obj->dev->TDA3 = buf[2];
obj->dev->TDB3 = buf[3];
if (cc) {
obj->dev->CMR = 0x90;
} else {
obj->dev->CMR = 0x81;
}
return 1;
}
return 0;
}
int can_read(can_t *obj, CAN_Message *msg, int handle) {
CANMsg x;
unsigned int *i = (unsigned int *)&x;
can_enable(obj);
if (obj->dev->GSR & 0x1) {
*i++ = obj->dev->RFS; // Frame
*i++ = obj->dev->RID; // ID
*i++ = obj->dev->RDA; // Data A
*i++ = obj->dev->RDB; // Data B
obj->dev->CMR = 0x04; // release receive buffer
msg->id = x.id;
msg->len = x.dlc;
msg->format = (x.type)? CANExtended : CANStandard;
msg->type = (x.rtr)? CANRemote: CANData;
memcpy(msg->data,x.data,x.dlc);
return 1;
}
return 0;
}
void can_reset(can_t *obj) {
can_disable(obj);
obj->dev->GSR = 0; // Reset error counter when CAN1MOD is in reset
}
unsigned char can_rderror(can_t *obj) {
return (obj->dev->GSR >> 16) & 0xFF;
}
unsigned char can_tderror(can_t *obj) {
return (obj->dev->GSR >> 24) & 0xFF;
}
void can_monitor(can_t *obj, int silent) {
uint32_t mod_mask = can_disable(obj);
if (silent) {
obj->dev->MOD |= (1 << 1);
} else {
obj->dev->MOD &= ~(1 << 1);
}
if (!(mod_mask & 1)) {
can_enable(obj);
}
}

View File

@ -0,0 +1,59 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_DEVICE_H
#define MBED_DEVICE_H
#define DEVICE_PORTIN 1
#define DEVICE_PORTOUT 1
#define DEVICE_PORTINOUT 1
#define DEVICE_INTERRUPTIN 1
#define DEVICE_ANALOGIN 1
#define DEVICE_ANALOGOUT 1
#define DEVICE_SERIAL 1
#define DEVICE_I2C 1
#define DEVICE_I2CSLAVE 1
#define DEVICE_SPI 1
#define DEVICE_SPISLAVE 1
#define DEVICE_CAN 1
#define DEVICE_RTC 1
#define DEVICE_ETHERNET 1
#define DEVICE_PWMOUT 1
#define DEVICE_SEMIHOST 0
#define DEVICE_LOCALFILESYSTEM 0
#define DEVICE_ID_LENGTH 32
#define DEVICE_MAC_OFFSET 20
#define DEVICE_SLEEP 0
#define DEVICE_DEBUG_AWARENESS 0
#define DEVICE_STDIO_MESSAGES 1
#define DEVICE_ERROR_PATTERN 1
#include "objects.h"
#endif

View File

@ -0,0 +1,935 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string.h>
#include "ethernet_api.h"
#include "cmsis.h"
#include "mbed_interface.h"
#include "toolchain.h"
#include "mbed_error.h"
#define NEW_LOGIC 0
#define NEW_ETH_BUFFER 0
#if NEW_ETH_BUFFER
#define NUM_RX_FRAG 4 // Number of Rx Fragments (== packets)
#define NUM_TX_FRAG 3 // Number of Tx Fragments (== packets)
#define ETH_MAX_FLEN 1536 // Maximum Ethernet Frame Size
#define ETH_FRAG_SIZE ETH_MAX_FLEN // Packet Fragment size (same as packet length)
#else
// Memfree calculation:
// (16 * 1024) - ((2 * 4 * NUM_RX) + (2 * 4 * NUM_RX) + (0x300 * NUM_RX) +
// (2 * 4 * NUM_TX) + (1 * 4 * NUM_TX) + (0x300 * NUM_TX)) = 8556
/* EMAC Memory Buffer configuration for 16K Ethernet RAM. */
#define NUM_RX_FRAG 4 /* Num.of RX Fragments 4*1536= 6.0kB */
#define NUM_TX_FRAG 3 /* Num.of TX Fragments 3*1536= 4.6kB */
//#define ETH_FRAG_SIZE 1536 /* Packet Fragment size 1536 Bytes */
//#define ETH_MAX_FLEN 1536 /* Max. Ethernet Frame Size */
#define ETH_FRAG_SIZE 0x300 /* Packet Fragment size 1536/2 Bytes */
#define ETH_MAX_FLEN 0x300 /* Max. Ethernet Frame Size */
const int ethernet_MTU_SIZE = 0x300;
#endif
#define ETHERNET_ADDR_SIZE 6
PACKED struct RX_DESC_TypeDef { /* RX Descriptor struct */
unsigned int Packet;
unsigned int Ctrl;
};
typedef struct RX_DESC_TypeDef RX_DESC_TypeDef;
PACKED struct RX_STAT_TypeDef { /* RX Status struct */
unsigned int Info;
unsigned int HashCRC;
};
typedef struct RX_STAT_TypeDef RX_STAT_TypeDef;
PACKED struct TX_DESC_TypeDef { /* TX Descriptor struct */
unsigned int Packet;
unsigned int Ctrl;
};
typedef struct TX_DESC_TypeDef TX_DESC_TypeDef;
PACKED struct TX_STAT_TypeDef { /* TX Status struct */
unsigned int Info;
};
typedef struct TX_STAT_TypeDef TX_STAT_TypeDef;
/* MAC Configuration Register 1 */
#define MAC1_REC_EN 0x00000001 /* Receive Enable */
#define MAC1_PASS_ALL 0x00000002 /* Pass All Receive Frames */
#define MAC1_RX_FLOWC 0x00000004 /* RX Flow Control */
#define MAC1_TX_FLOWC 0x00000008 /* TX Flow Control */
#define MAC1_LOOPB 0x00000010 /* Loop Back Mode */
#define MAC1_RES_TX 0x00000100 /* Reset TX Logic */
#define MAC1_RES_MCS_TX 0x00000200 /* Reset MAC TX Control Sublayer */
#define MAC1_RES_RX 0x00000400 /* Reset RX Logic */
#define MAC1_RES_MCS_RX 0x00000800 /* Reset MAC RX Control Sublayer */
#define MAC1_SIM_RES 0x00004000 /* Simulation Reset */
#define MAC1_SOFT_RES 0x00008000 /* Soft Reset MAC */
/* MAC Configuration Register 2 */
#define MAC2_FULL_DUP 0x00000001 /* Full Duplex Mode */
#define MAC2_FRM_LEN_CHK 0x00000002 /* Frame Length Checking */
#define MAC2_HUGE_FRM_EN 0x00000004 /* Huge Frame Enable */
#define MAC2_DLY_CRC 0x00000008 /* Delayed CRC Mode */
#define MAC2_CRC_EN 0x00000010 /* Append CRC to every Frame */
#define MAC2_PAD_EN 0x00000020 /* Pad all Short Frames */
#define MAC2_VLAN_PAD_EN 0x00000040 /* VLAN Pad Enable */
#define MAC2_ADET_PAD_EN 0x00000080 /* Auto Detect Pad Enable */
#define MAC2_PPREAM_ENF 0x00000100 /* Pure Preamble Enforcement */
#define MAC2_LPREAM_ENF 0x00000200 /* Long Preamble Enforcement */
#define MAC2_NO_BACKOFF 0x00001000 /* No Backoff Algorithm */
#define MAC2_BACK_PRESSURE 0x00002000 /* Backoff Presurre / No Backoff */
#define MAC2_EXCESS_DEF 0x00004000 /* Excess Defer */
/* Back-to-Back Inter-Packet-Gap Register */
#define IPGT_FULL_DUP 0x00000015 /* Recommended value for Full Duplex */
#define IPGT_HALF_DUP 0x00000012 /* Recommended value for Half Duplex */
/* Non Back-to-Back Inter-Packet-Gap Register */
#define IPGR_DEF 0x00000012 /* Recommended value */
/* Collision Window/Retry Register */
#define CLRT_DEF 0x0000370F /* Default value */
/* PHY Support Register */
#define SUPP_SPEED 0x00000100 /* Reduced MII Logic Current Speed */
//#define SUPP_RES_RMII 0x00000800 /* Reset Reduced MII Logic */
#define SUPP_RES_RMII 0x00000000 /* Reset Reduced MII Logic */
/* Test Register */
#define TEST_SHCUT_PQUANTA 0x00000001 /* Shortcut Pause Quanta */
#define TEST_TST_PAUSE 0x00000002 /* Test Pause */
#define TEST_TST_BACKP 0x00000004 /* Test Back Pressure */
/* MII Management Configuration Register */
#define MCFG_SCAN_INC 0x00000001 /* Scan Increment PHY Address */
#define MCFG_SUPP_PREAM 0x00000002 /* Suppress Preamble */
#define MCFG_CLK_SEL 0x0000003C /* Clock Select Mask */
#define MCFG_RES_MII 0x00008000 /* Reset MII Management Hardware */
/* MII Management Command Register */
#define MCMD_READ 0x00000001 /* MII Read */
#define MCMD_SCAN 0x00000002 /* MII Scan continuously */
#define MII_WR_TOUT 0x00050000 /* MII Write timeout count */
#define MII_RD_TOUT 0x00050000 /* MII Read timeout count */
/* MII Management Address Register */
#define MADR_REG_ADR 0x0000001F /* MII Register Address Mask */
#define MADR_PHY_ADR 0x00001F00 /* PHY Address Mask */
/* MII Management Indicators Register */
#define MIND_BUSY 0x00000001 /* MII is Busy */
#define MIND_SCAN 0x00000002 /* MII Scanning in Progress */
#define MIND_NOT_VAL 0x00000004 /* MII Read Data not valid */
#define MIND_MII_LINK_FAIL 0x00000008 /* MII Link Failed */
/* Command Register */
#define CR_RX_EN 0x00000001 /* Enable Receive */
#define CR_TX_EN 0x00000002 /* Enable Transmit */
#define CR_REG_RES 0x00000008 /* Reset Host Registers */
#define CR_TX_RES 0x00000010 /* Reset Transmit Datapath */
#define CR_RX_RES 0x00000020 /* Reset Receive Datapath */
#define CR_PASS_RUNT_FRM 0x00000040 /* Pass Runt Frames */
#define CR_PASS_RX_FILT 0x00000080 /* Pass RX Filter */
#define CR_TX_FLOW_CTRL 0x00000100 /* TX Flow Control */
#define CR_RMII 0x00000200 /* Reduced MII Interface */
#define CR_FULL_DUP 0x00000400 /* Full Duplex */
/* Status Register */
#define SR_RX_EN 0x00000001 /* Enable Receive */
#define SR_TX_EN 0x00000002 /* Enable Transmit */
/* Transmit Status Vector 0 Register */
#define TSV0_CRC_ERR 0x00000001 /* CRC error */
#define TSV0_LEN_CHKERR 0x00000002 /* Length Check Error */
#define TSV0_LEN_OUTRNG 0x00000004 /* Length Out of Range */
#define TSV0_DONE 0x00000008 /* Tramsmission Completed */
#define TSV0_MCAST 0x00000010 /* Multicast Destination */
#define TSV0_BCAST 0x00000020 /* Broadcast Destination */
#define TSV0_PKT_DEFER 0x00000040 /* Packet Deferred */
#define TSV0_EXC_DEFER 0x00000080 /* Excessive Packet Deferral */
#define TSV0_EXC_COLL 0x00000100 /* Excessive Collision */
#define TSV0_LATE_COLL 0x00000200 /* Late Collision Occured */
#define TSV0_GIANT 0x00000400 /* Giant Frame */
#define TSV0_UNDERRUN 0x00000800 /* Buffer Underrun */
#define TSV0_BYTES 0x0FFFF000 /* Total Bytes Transferred */
#define TSV0_CTRL_FRAME 0x10000000 /* Control Frame */
#define TSV0_PAUSE 0x20000000 /* Pause Frame */
#define TSV0_BACK_PRESS 0x40000000 /* Backpressure Method Applied */
#define TSV0_VLAN 0x80000000 /* VLAN Frame */
/* Transmit Status Vector 1 Register */
#define TSV1_BYTE_CNT 0x0000FFFF /* Transmit Byte Count */
#define TSV1_COLL_CNT 0x000F0000 /* Transmit Collision Count */
/* Receive Status Vector Register */
#define RSV_BYTE_CNT 0x0000FFFF /* Receive Byte Count */
#define RSV_PKT_IGNORED 0x00010000 /* Packet Previously Ignored */
#define RSV_RXDV_SEEN 0x00020000 /* RXDV Event Previously Seen */
#define RSV_CARR_SEEN 0x00040000 /* Carrier Event Previously Seen */
#define RSV_REC_CODEV 0x00080000 /* Receive Code Violation */
#define RSV_CRC_ERR 0x00100000 /* CRC Error */
#define RSV_LEN_CHKERR 0x00200000 /* Length Check Error */
#define RSV_LEN_OUTRNG 0x00400000 /* Length Out of Range */
#define RSV_REC_OK 0x00800000 /* Frame Received OK */
#define RSV_MCAST 0x01000000 /* Multicast Frame */
#define RSV_BCAST 0x02000000 /* Broadcast Frame */
#define RSV_DRIB_NIBB 0x04000000 /* Dribble Nibble */
#define RSV_CTRL_FRAME 0x08000000 /* Control Frame */
#define RSV_PAUSE 0x10000000 /* Pause Frame */
#define RSV_UNSUPP_OPC 0x20000000 /* Unsupported Opcode */
#define RSV_VLAN 0x40000000 /* VLAN Frame */
/* Flow Control Counter Register */
#define FCC_MIRR_CNT 0x0000FFFF /* Mirror Counter */
#define FCC_PAUSE_TIM 0xFFFF0000 /* Pause Timer */
/* Flow Control Status Register */
#define FCS_MIRR_CNT 0x0000FFFF /* Mirror Counter Current */
/* Receive Filter Control Register */
#define RFC_UCAST_EN 0x00000001 /* Accept Unicast Frames Enable */
#define RFC_BCAST_EN 0x00000002 /* Accept Broadcast Frames Enable */
#define RFC_MCAST_EN 0x00000004 /* Accept Multicast Frames Enable */
#define RFC_UCAST_HASH_EN 0x00000008 /* Accept Unicast Hash Filter Frames */
#define RFC_MCAST_HASH_EN 0x00000010 /* Accept Multicast Hash Filter Fram.*/
#define RFC_PERFECT_EN 0x00000020 /* Accept Perfect Match Enable */
#define RFC_MAGP_WOL_EN 0x00001000 /* Magic Packet Filter WoL Enable */
#define RFC_PFILT_WOL_EN 0x00002000 /* Perfect Filter WoL Enable */
/* Receive Filter WoL Status/Clear Registers */
#define WOL_UCAST 0x00000001 /* Unicast Frame caused WoL */
#define WOL_BCAST 0x00000002 /* Broadcast Frame caused WoL */
#define WOL_MCAST 0x00000004 /* Multicast Frame caused WoL */
#define WOL_UCAST_HASH 0x00000008 /* Unicast Hash Filter Frame WoL */
#define WOL_MCAST_HASH 0x00000010 /* Multicast Hash Filter Frame WoL */
#define WOL_PERFECT 0x00000020 /* Perfect Filter WoL */
#define WOL_RX_FILTER 0x00000080 /* RX Filter caused WoL */
#define WOL_MAG_PACKET 0x00000100 /* Magic Packet Filter caused WoL */
/* Interrupt Status/Enable/Clear/Set Registers */
#define INT_RX_OVERRUN 0x00000001 /* Overrun Error in RX Queue */
#define INT_RX_ERR 0x00000002 /* Receive Error */
#define INT_RX_FIN 0x00000004 /* RX Finished Process Descriptors */
#define INT_RX_DONE 0x00000008 /* Receive Done */
#define INT_TX_UNDERRUN 0x00000010 /* Transmit Underrun */
#define INT_TX_ERR 0x00000020 /* Transmit Error */
#define INT_TX_FIN 0x00000040 /* TX Finished Process Descriptors */
#define INT_TX_DONE 0x00000080 /* Transmit Done */
#define INT_SOFT_INT 0x00001000 /* Software Triggered Interrupt */
#define INT_WAKEUP 0x00002000 /* Wakeup Event Interrupt */
/* Power Down Register */
#define PD_POWER_DOWN 0x80000000 /* Power Down MAC */
/* RX Descriptor Control Word */
#define RCTRL_SIZE 0x000007FF /* Buffer size mask */
#define RCTRL_INT 0x80000000 /* Generate RxDone Interrupt */
/* RX Status Hash CRC Word */
#define RHASH_SA 0x000001FF /* Hash CRC for Source Address */
#define RHASH_DA 0x001FF000 /* Hash CRC for Destination Address */
/* RX Status Information Word */
#define RINFO_SIZE 0x000007FF /* Data size in bytes */
#define RINFO_CTRL_FRAME 0x00040000 /* Control Frame */
#define RINFO_VLAN 0x00080000 /* VLAN Frame */
#define RINFO_FAIL_FILT 0x00100000 /* RX Filter Failed */
#define RINFO_MCAST 0x00200000 /* Multicast Frame */
#define RINFO_BCAST 0x00400000 /* Broadcast Frame */
#define RINFO_CRC_ERR 0x00800000 /* CRC Error in Frame */
#define RINFO_SYM_ERR 0x01000000 /* Symbol Error from PHY */
#define RINFO_LEN_ERR 0x02000000 /* Length Error */
#define RINFO_RANGE_ERR 0x04000000 /* Range Error (exceeded max. size) */
#define RINFO_ALIGN_ERR 0x08000000 /* Alignment Error */
#define RINFO_OVERRUN 0x10000000 /* Receive overrun */
#define RINFO_NO_DESCR 0x20000000 /* No new Descriptor available */
#define RINFO_LAST_FLAG 0x40000000 /* Last Fragment in Frame */
#define RINFO_ERR 0x80000000 /* Error Occured (OR of all errors) */
//#define RINFO_ERR_MASK (RINFO_FAIL_FILT | RINFO_CRC_ERR | RINFO_SYM_ERR | RINFO_LEN_ERR | RINFO_ALIGN_ERR | RINFO_OVERRUN)
#define RINFO_ERR_MASK (RINFO_FAIL_FILT | RINFO_SYM_ERR | \
RINFO_LEN_ERR | RINFO_ALIGN_ERR | RINFO_OVERRUN)
/* TX Descriptor Control Word */
#define TCTRL_SIZE 0x000007FF /* Size of data buffer in bytes */
#define TCTRL_OVERRIDE 0x04000000 /* Override Default MAC Registers */
#define TCTRL_HUGE 0x08000000 /* Enable Huge Frame */
#define TCTRL_PAD 0x10000000 /* Pad short Frames to 64 bytes */
#define TCTRL_CRC 0x20000000 /* Append a hardware CRC to Frame */
#define TCTRL_LAST 0x40000000 /* Last Descriptor for TX Frame */
#define TCTRL_INT 0x80000000 /* Generate TxDone Interrupt */
/* TX Status Information Word */
#define TINFO_COL_CNT 0x01E00000 /* Collision Count */
#define TINFO_DEFER 0x02000000 /* Packet Deferred (not an error) */
#define TINFO_EXCESS_DEF 0x04000000 /* Excessive Deferral */
#define TINFO_EXCESS_COL 0x08000000 /* Excessive Collision */
#define TINFO_LATE_COL 0x10000000 /* Late Collision Occured */
#define TINFO_UNDERRUN 0x20000000 /* Transmit Underrun */
#define TINFO_NO_DESCR 0x40000000 /* No new Descriptor available */
#define TINFO_ERR 0x80000000 /* Error Occured (OR of all errors) */
/* ENET Device Revision ID */
#define OLD_EMAC_MODULE_ID 0x39022000 /* Rev. ID for first rev '-' */
/* DP83848C PHY Registers */
#define PHY_REG_BMCR 0x00 /* Basic Mode Control Register */
#define PHY_REG_BMSR 0x01 /* Basic Mode Status Register */
#define PHY_REG_IDR1 0x02 /* PHY Identifier 1 */
#define PHY_REG_IDR2 0x03 /* PHY Identifier 2 */
#define PHY_REG_ANAR 0x04 /* Auto-Negotiation Advertisement */
#define PHY_REG_ANLPAR 0x05 /* Auto-Neg. Link Partner Abitily */
#define PHY_REG_ANER 0x06 /* Auto-Neg. Expansion Register */
#define PHY_REG_ANNPTR 0x07 /* Auto-Neg. Next Page TX */
/* PHY Extended Registers */
#define PHY_REG_STS 0x10 /* Status Register */
#define PHY_REG_MICR 0x11 /* MII Interrupt Control Register */
#define PHY_REG_MISR 0x12 /* MII Interrupt Status Register */
#define PHY_REG_FCSCR 0x14 /* False Carrier Sense Counter */
#define PHY_REG_RECR 0x15 /* Receive Error Counter */
#define PHY_REG_PCSR 0x16 /* PCS Sublayer Config. and Status */
#define PHY_REG_RBR 0x17 /* RMII and Bypass Register */
#define PHY_REG_LEDCR 0x18 /* LED Direct Control Register */
#define PHY_REG_PHYCR 0x19 /* PHY Control Register */
#define PHY_REG_10BTSCR 0x1A /* 10Base-T Status/Control Register */
#define PHY_REG_CDCTRL1 0x1B /* CD Test Control and BIST Extens. */
#define PHY_REG_EDCR 0x1D /* Energy Detect Control Register */
#define PHY_REG_SCSR 0x1F /* PHY Special Control/Status Register */
#define PHY_FULLD_100M 0x2100 /* Full Duplex 100Mbit */
#define PHY_HALFD_100M 0x2000 /* Half Duplex 100Mbit */
#define PHY_FULLD_10M 0x0100 /* Full Duplex 10Mbit */
#define PHY_HALFD_10M 0x0000 /* Half Duplex 10MBit */
#define PHY_AUTO_NEG 0x3000 /* Select Auto Negotiation */
#define DP83848C_DEF_ADR 0x0100 /* Default PHY device address */
#define DP83848C_ID 0x20005C90 /* PHY Identifier - DP83848C */
#define LAN8720_ID 0x0007C0F0 /* PHY Identifier - LAN8720 */
#define PHY_STS_LINK 0x0001 /* PHY Status Link Mask */
#define PHY_STS_SPEED 0x0002 /* PHY Status Speed Mask */
#define PHY_STS_DUPLEX 0x0004 /* PHY Status Duplex Mask */
#define PHY_BMCR_RESET 0x8000 /* PHY Reset */
#define PHY_BMSR_LINK 0x0004 /* PHY BMSR Link valid */
#define PHY_SCSR_100MBIT 0x0008 /* Speed: 1=100 MBit, 0=10Mbit */
#define PHY_SCSR_DUPLEX 0x0010 /* PHY Duplex Mask */
static int phy_read(unsigned int PhyReg);
static int phy_write(unsigned int PhyReg, unsigned short Data);
static void txdscr_init(void);
static void rxdscr_init(void);
#if defined (__ICCARM__)
# define AHBSRAM1
#elif defined(TOOLCHAIN_GCC_CR)
# define AHBSRAM1 __attribute__((section(".data.$RamPeriph32")))
#else
# define AHBSRAM1 __attribute__((section("AHBSRAM1"),aligned))
#endif
AHBSRAM1 volatile uint8_t rxbuf[NUM_RX_FRAG][ETH_FRAG_SIZE];
AHBSRAM1 volatile uint8_t txbuf[NUM_TX_FRAG][ETH_FRAG_SIZE];
AHBSRAM1 volatile RX_DESC_TypeDef rxdesc[NUM_RX_FRAG];
AHBSRAM1 volatile RX_STAT_TypeDef rxstat[NUM_RX_FRAG];
AHBSRAM1 volatile TX_DESC_TypeDef txdesc[NUM_TX_FRAG];
AHBSRAM1 volatile TX_STAT_TypeDef txstat[NUM_TX_FRAG];
#if NEW_LOGIC
static int rx_consume_offset = -1;
static int tx_produce_offset = -1;
#else
static int send_doff = 0;
static int send_idx = -1;
static int send_size = 0;
static int receive_soff = 0;
static int receive_idx = -1;
#endif
static uint32_t phy_id = 0;
static inline int rinc(int idx, int mod) {
++idx;
idx %= mod;
return idx;
}
//extern unsigned int SystemFrequency;
static inline unsigned int clockselect() {
if(SystemCoreClock < 10000000) {
return 1;
} else if(SystemCoreClock < 15000000) {
return 2;
} else if(SystemCoreClock < 20000000) {
return 3;
} else if(SystemCoreClock < 25000000) {
return 4;
} else if(SystemCoreClock < 35000000) {
return 5;
} else if(SystemCoreClock < 50000000) {
return 6;
} else if(SystemCoreClock < 70000000) {
return 7;
} else if(SystemCoreClock < 80000000) {
return 8;
} else if(SystemCoreClock < 90000000) {
return 9;
} else if(SystemCoreClock < 100000000) {
return 10;
} else if(SystemCoreClock < 120000000) {
return 11;
} else if(SystemCoreClock < 130000000) {
return 12;
} else if(SystemCoreClock < 140000000) {
return 13;
} else if(SystemCoreClock < 150000000) {
return 15;
} else if(SystemCoreClock < 160000000) {
return 16;
} else {
return 0;
}
}
#ifndef min
#define min(x, y) (((x)<(y))?(x):(y))
#endif
/*----------------------------------------------------------------------------
Ethernet Device initialize
*----------------------------------------------------------------------------*/
int ethernet_init() {
int regv, tout;
char mac[ETHERNET_ADDR_SIZE];
unsigned int clock = clockselect();
LPC_SC->PCONP |= 0x40000000; /* Power Up the EMAC controller. */
LPC_PINCON->PINSEL2 = 0x50150105; /* Enable P1 Ethernet Pins. */
LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & ~0x0000000F) | 0x00000005;
/* Reset all EMAC internal modules. */
LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX |
MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES;
LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES | CR_PASS_RUNT_FRM;
for(tout = 100; tout; tout--) __NOP(); /* A short delay after reset. */
LPC_EMAC->MAC1 = MAC1_PASS_ALL; /* Initialize MAC control registers. */
LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
LPC_EMAC->MAXF = ETH_MAX_FLEN;
LPC_EMAC->CLRT = CLRT_DEF;
LPC_EMAC->IPGR = IPGR_DEF;
LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM; /* Enable Reduced MII interface. */
LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL; /* Set clock */
LPC_EMAC->MCFG |= MCFG_RES_MII; /* and reset */
for(tout = 100; tout; tout--) __NOP(); /* A short delay */
LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL;
LPC_EMAC->MCMD = 0;
LPC_EMAC->SUPP = SUPP_RES_RMII; /* Reset Reduced MII Logic. */
for (tout = 100; tout; tout--) __NOP(); /* A short delay */
LPC_EMAC->SUPP = 0;
phy_write(PHY_REG_BMCR, PHY_BMCR_RESET); /* perform PHY reset */
for(tout = 0x20000; ; tout--) { /* Wait for hardware reset to end. */
regv = phy_read(PHY_REG_BMCR);
if(regv < 0 || tout == 0) {
return -1; /* Error */
}
if(!(regv & PHY_BMCR_RESET)) {
break; /* Reset complete. */
}
}
phy_id = (phy_read(PHY_REG_IDR1) << 16);
phy_id |= (phy_read(PHY_REG_IDR2) & 0XFFF0);
if (phy_id != DP83848C_ID && phy_id != LAN8720_ID) {
error("Unknown Ethernet PHY (%x)", (unsigned int)phy_id);
}
ethernet_set_link(-1, 0);
/* Set the Ethernet MAC Address registers */
ethernet_address(mac);
LPC_EMAC->SA0 = ((uint32_t)mac[5] << 8) | (uint32_t)mac[4];
LPC_EMAC->SA1 = ((uint32_t)mac[3] << 8) | (uint32_t)mac[2];
LPC_EMAC->SA2 = ((uint32_t)mac[1] << 8) | (uint32_t)mac[0];
txdscr_init(); /* initialize DMA TX Descriptor */
rxdscr_init(); /* initialize DMA RX Descriptor */
LPC_EMAC->RxFilterCtrl = RFC_UCAST_EN | RFC_MCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN;
/* Receive Broadcast, Perfect Match Packets */
LPC_EMAC->IntEnable = INT_RX_DONE | INT_TX_DONE; /* Enable EMAC interrupts. */
LPC_EMAC->IntClear = 0xFFFF; /* Reset all interrupts */
LPC_EMAC->Command |= (CR_RX_EN | CR_TX_EN); /* Enable receive and transmit mode of MAC Ethernet core */
LPC_EMAC->MAC1 |= MAC1_REC_EN;
#if NEW_LOGIC
rx_consume_offset = -1;
tx_produce_offset = -1;
#else
send_doff = 0;
send_idx = -1;
send_size = 0;
receive_soff = 0;
receive_idx = -1;
#endif
return 0;
}
/*----------------------------------------------------------------------------
Ethernet Device Uninitialize
*----------------------------------------------------------------------------*/
void ethernet_free() {
LPC_EMAC->IntEnable &= ~(INT_RX_DONE | INT_TX_DONE);
LPC_EMAC->IntClear = 0xFFFF;
LPC_SC->PCONP &= ~0x40000000; /* Power down the EMAC controller. */
LPC_PINCON->PINSEL2 &= ~0x50150105; /* Disable P1 ethernet pins. */
LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & ~0x0000000F) | 0x00000000;
}
// if(TxProduceIndex == TxConsumeIndex) buffer array is empty
// if(TxProduceIndex == TxConsumeIndex - 1) buffer is full, should not fill
// TxProduceIndex - The buffer that will/is being fileld by driver, s/w increment
// TxConsumeIndex - The buffer that will/is beign sent by hardware
int ethernet_write(const char *data, int slen) {
#if NEW_LOGIC
if(tx_produce_offset < 0) { // mark as active if not already
tx_produce_offset = 0;
}
int index = LPC_EMAC->TxProduceIndex;
int remaining = ETH_MAX_FLEN - tx_produce_offset - 4; // bytes written plus checksum
int requested = slen;
int ncopy = min(remaining, requested);
void *pdst = (void *)(txdesc[index].Packet + tx_produce_offset);
void *psrc = (void *)(data);
if(ncopy > 0 ){
if(data != NULL) {
memcpy(pdst, psrc, ncopy);
} else {
memset(pdst, 0, ncopy);
}
}
tx_produce_offset += ncopy;
return ncopy;
#else
void *pdst, *psrc;
const int dlen = ETH_FRAG_SIZE;
int copy = 0;
int soff = 0;
if(send_idx == -1) {
send_idx = LPC_EMAC->TxProduceIndex;
}
if(slen + send_doff > ethernet_MTU_SIZE) {
return -1;
}
do {
copy = min(slen - soff, dlen - send_doff);
pdst = (void *)(txdesc[send_idx].Packet + send_doff);
psrc = (void *)(data + soff);
if(send_doff + copy > ETH_FRAG_SIZE) {
txdesc[send_idx].Ctrl = (send_doff-1) | (TCTRL_INT);
send_idx = rinc(send_idx, NUM_TX_FRAG);
send_doff = 0;
}
if(data != NULL) {
memcpy(pdst, psrc, copy);
} else {
memset(pdst, 0, copy);
}
soff += copy;
send_doff += copy;
send_size += copy;
} while(soff != slen);
return soff;
#endif
}
int ethernet_send() {
#if NEW_LOGIC
if(tx_produce_offset < 0) { // no buffer active
return -1;
}
// ensure there is a link
if(!ethernet_link()) {
return -2;
}
// we have been writing in to a buffer, so finalise it
int size = tx_produce_offset;
int index = LPC_EMAC->TxProduceIndex;
txdesc[index].Ctrl = (tx_produce_offset-1) | (TCTRL_INT | TCTRL_LAST);
// Increment ProduceIndex to allow it to be sent
// We can only do this if the next slot is free
int next = rinc(index, NUM_TX_FRAG);
while(next == LPC_EMAC->TxConsumeIndex) {
for(int i=0; i<1000; i++) { __NOP(); }
}
LPC_EMAC->TxProduceIndex = next;
tx_produce_offset = -1;
return size;
#else
int s = send_size;
txdesc[send_idx].Ctrl = (send_doff-1) | (TCTRL_INT | TCTRL_LAST);
send_idx = rinc(send_idx, NUM_TX_FRAG);
LPC_EMAC->TxProduceIndex = send_idx;
send_doff = 0;
send_idx = -1;
send_size = 0;
return s;
#endif
}
// RxConsmeIndex - The index of buffer the driver will/is reading from. Driver should inc once read
// RxProduceIndex - The index of buffer that will/is being filled by MAC. H/w will inc once rxd
//
// if(RxConsumeIndex == RxProduceIndex) buffer array is empty
// if(RxConsumeIndex == RxProduceIndex + 1) buffer array is full
// Recevies an arrived ethernet packet.
// Receiving an ethernet packet will drop the last received ethernet packet
// and make a new ethernet packet ready to read.
// Returns size of packet, else 0 if nothing to receive
// We read from RxConsumeIndex from position rx_consume_offset
// if rx_consume_offset < 0, then we have not recieved the RxConsumeIndex packet for reading
// rx_consume_offset = -1 // no frame
// rx_consume_offset = 0 // start of frame
// Assumption: A fragment should alway be a whole frame
int ethernet_receive() {
#if NEW_LOGIC
// if we are currently reading a valid RxConsume buffer, increment to the next one
if(rx_consume_offset >= 0) {
LPC_EMAC->RxConsumeIndex = rinc(LPC_EMAC->RxConsumeIndex, NUM_RX_FRAG);
}
// if the buffer is empty, mark it as no valid buffer
if(LPC_EMAC->RxConsumeIndex == LPC_EMAC->RxProduceIndex) {
rx_consume_offset = -1;
return 0;
}
uint32_t info = rxstat[LPC_EMAC->RxConsumeIndex].Info;
rx_consume_offset = 0;
// check if it is not marked as last or for errors
if(!(info & RINFO_LAST_FLAG) || (info & RINFO_ERR_MASK)) {
return -1;
}
int size = (info & RINFO_SIZE) + 1;
return size - 4; // don't include checksum bytes
#else
if(receive_idx == -1) {
receive_idx = LPC_EMAC->RxConsumeIndex;
} else {
while(!(rxstat[receive_idx].Info & RINFO_LAST_FLAG) && ((uint32_t)receive_idx != LPC_EMAC->RxProduceIndex)) {
receive_idx = rinc(receive_idx, NUM_RX_FRAG);
}
unsigned int info = rxstat[receive_idx].Info;
int slen = (info & RINFO_SIZE) + 1;
if(slen > ethernet_MTU_SIZE || (info & RINFO_ERR_MASK)) {
/* Invalid frame, ignore it and free buffer. */
receive_idx = rinc(receive_idx, NUM_RX_FRAG);
}
receive_idx = rinc(receive_idx, NUM_RX_FRAG);
receive_soff = 0;
LPC_EMAC->RxConsumeIndex = receive_idx;
}
if((uint32_t)receive_idx == LPC_EMAC->RxProduceIndex) {
receive_idx = -1;
return 0;
}
return (rxstat[receive_idx].Info & RINFO_SIZE) - 3;
#endif
}
// Read from an recevied ethernet packet.
// After receive returnd a number bigger than 0 it is
// possible to read bytes from this packet.
// Read will write up to size bytes into data.
// It is possible to use read multible times.
// Each time read will start reading after the last read byte before.
int ethernet_read(char *data, int dlen) {
#if NEW_LOGIC
// Check we have a valid buffer to read
if(rx_consume_offset < 0) {
return 0;
}
// Assume 1 fragment block
uint32_t info = rxstat[LPC_EMAC->RxConsumeIndex].Info;
int size = (info & RINFO_SIZE) + 1 - 4; // exclude checksum
int remaining = size - rx_consume_offset;
int requested = dlen;
int ncopy = min(remaining, requested);
void *psrc = (void *)(rxdesc[LPC_EMAC->RxConsumeIndex].Packet + rx_consume_offset);
void *pdst = (void *)(data);
if(data != NULL && ncopy > 0) {
memcpy(pdst, psrc, ncopy);
}
rx_consume_offset += ncopy;
return ncopy;
#else
int slen;
int copy = 0;
unsigned int more;
unsigned int info;
void *pdst, *psrc;
int doff = 0;
if((uint32_t)receive_idx == LPC_EMAC->RxProduceIndex || receive_idx == -1) {
return 0;
}
do {
info = rxstat[receive_idx].Info;
more = !(info & RINFO_LAST_FLAG);
slen = (info & RINFO_SIZE) + 1;
if(slen > ethernet_MTU_SIZE || (info & RINFO_ERR_MASK)) {
/* Invalid frame, ignore it and free buffer. */
receive_idx = rinc(receive_idx, NUM_RX_FRAG);
} else {
copy = min(slen - receive_soff, dlen - doff);
psrc = (void *)(rxdesc[receive_idx].Packet + receive_soff);
pdst = (void *)(data + doff);
if(data != NULL) {
/* check if Buffer available */
memcpy(pdst, psrc, copy);
}
receive_soff += copy;
doff += copy;
if((more && (receive_soff == slen))) {
receive_idx = rinc(receive_idx, NUM_RX_FRAG);
receive_soff = 0;
}
}
} while(more && !(doff == dlen) && !receive_soff);
return doff;
#endif
}
int ethernet_link(void) {
if (phy_id == DP83848C_ID) {
return (phy_read(PHY_REG_STS) & PHY_STS_LINK);
}
else { // LAN8720_ID
return (phy_read(PHY_REG_BMSR) & PHY_BMSR_LINK);
}
}
static int phy_write(unsigned int PhyReg, unsigned short Data) {
unsigned int timeOut;
LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
LPC_EMAC->MWTD = Data;
for(timeOut = 0; timeOut < MII_WR_TOUT; timeOut++) { /* Wait until operation completed */
if((LPC_EMAC->MIND & MIND_BUSY) == 0) {
return 0;
}
}
return -1;
}
static int phy_read(unsigned int PhyReg) {
unsigned int timeOut;
LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
LPC_EMAC->MCMD = MCMD_READ;
for(timeOut = 0; timeOut < MII_RD_TOUT; timeOut++) { /* Wait until operation completed */
if((LPC_EMAC->MIND & MIND_BUSY) == 0) {
LPC_EMAC->MCMD = 0;
return LPC_EMAC->MRDD; /* Return a 16-bit value. */
}
}
return -1;
}
static void txdscr_init() {
int i;
for(i = 0; i < NUM_TX_FRAG; i++) {
txdesc[i].Packet = (uint32_t)&txbuf[i];
txdesc[i].Ctrl = 0;
txstat[i].Info = 0;
}
LPC_EMAC->TxDescriptor = (uint32_t)txdesc; /* Set EMAC Transmit Descriptor Registers. */
LPC_EMAC->TxStatus = (uint32_t)txstat;
LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAG-1;
LPC_EMAC->TxProduceIndex = 0; /* Tx Descriptors Point to 0 */
}
static void rxdscr_init() {
int i;
for(i = 0; i < NUM_RX_FRAG; i++) {
rxdesc[i].Packet = (uint32_t)&rxbuf[i];
rxdesc[i].Ctrl = RCTRL_INT | (ETH_FRAG_SIZE-1);
rxstat[i].Info = 0;
rxstat[i].HashCRC = 0;
}
LPC_EMAC->RxDescriptor = (uint32_t)rxdesc; /* Set EMAC Receive Descriptor Registers. */
LPC_EMAC->RxStatus = (uint32_t)rxstat;
LPC_EMAC->RxDescriptorNumber = NUM_RX_FRAG-1;
LPC_EMAC->RxConsumeIndex = 0; /* Rx Descriptors Point to 0 */
}
void ethernet_address(char *mac) {
mbed_mac_address(mac);
}
void ethernet_set_link(int speed, int duplex) {
unsigned short phy_data;
int tout;
if((speed < 0) || (speed > 1)) {
phy_data = PHY_AUTO_NEG;
} else {
phy_data = (((unsigned short) speed << 13) |
((unsigned short) duplex << 8));
}
phy_write(PHY_REG_BMCR, phy_data);
for(tout = 100; tout; tout--) { __NOP(); } /* A short delay */
switch(phy_id) {
case DP83848C_ID:
phy_data = phy_read(PHY_REG_STS);
if(phy_data & PHY_STS_DUPLEX) {
LPC_EMAC->MAC2 |= MAC2_FULL_DUP;
LPC_EMAC->Command |= CR_FULL_DUP;
LPC_EMAC->IPGT = IPGT_FULL_DUP;
} else {
LPC_EMAC->MAC2 &= ~MAC2_FULL_DUP;
LPC_EMAC->Command &= ~CR_FULL_DUP;
LPC_EMAC->IPGT = IPGT_HALF_DUP;
}
if(phy_data & PHY_STS_SPEED) {
LPC_EMAC->SUPP &= ~SUPP_SPEED;
} else {
LPC_EMAC->SUPP |= SUPP_SPEED;
}
break;
case LAN8720_ID:
phy_data = phy_read(PHY_REG_SCSR);
if (phy_data & PHY_SCSR_DUPLEX) {
LPC_EMAC->MAC2 |= MAC2_FULL_DUP;
LPC_EMAC->Command |= CR_FULL_DUP;
LPC_EMAC->IPGT = IPGT_FULL_DUP;
} else {
LPC_EMAC->Command &= ~CR_FULL_DUP;
LPC_EMAC->IPGT = IPGT_HALF_DUP;
}
if(phy_data & PHY_SCSR_100MBIT) {
LPC_EMAC->SUPP |= SUPP_SPEED;
} else {
LPC_EMAC->SUPP &= ~SUPP_SPEED;
}
break;
}
}

View File

@ -0,0 +1,57 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed_assert.h"
#include "gpio_api.h"
#include "pinmap.h"
uint32_t gpio_set(PinName pin) {
LPC_SC->SCS |= 1; // High speed GPIO is enabled on ports 0 and 1
pin_function(pin, 0);
return (1 << ((int)pin & 0x1F));
}
void gpio_init(gpio_t *obj, PinName pin) {
if (pin == (PinName)NC)
return;
obj->pin = pin;
if (pin == (PinName)NC)
return;
obj->mask = gpio_set(pin);
LPC_GPIO_TypeDef *port_reg = (LPC_GPIO_TypeDef *) ((int)pin & ~0x1F);
obj->reg_set = &port_reg->FIOSET;
obj->reg_mask = &port_reg->FIOMASK;
obj->reg_clr = &port_reg->FIOCLR;
obj->reg_in = &port_reg->FIOPIN;
obj->reg_dir = &port_reg->FIODIR;
}
void gpio_mode(gpio_t *obj, PinMode mode) {
pin_mode(obj->pin, mode);
}
void gpio_dir(gpio_t *obj, PinDirection direction) {
if (obj->pin == (PinName)NC)
return;
switch (direction) {
case PIN_INPUT : *obj->reg_dir &= ~obj->mask; break;
case PIN_OUTPUT: *obj->reg_dir |= obj->mask; break;
}
}

View File

@ -0,0 +1,154 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "gpio_irq_api.h"
#include "mbed_error.h"
#include <stddef.h>
#include "cmsis.h"
#define CHANNEL_NUM 48
static uint32_t channel_ids[CHANNEL_NUM] = {0};
static gpio_irq_handler irq_handler;
static void handle_interrupt_in(void) {
// Read in all current interrupt registers. We do this once as the
// GPIO interrupt registers are on the APB bus, and this is slow.
uint32_t rise0 = LPC_GPIOINT->IO0IntStatR;
uint32_t fall0 = LPC_GPIOINT->IO0IntStatF;
uint32_t rise2 = LPC_GPIOINT->IO2IntStatR;
uint32_t fall2 = LPC_GPIOINT->IO2IntStatF;
uint32_t mask0 = 0;
uint32_t mask2 = 0;
int i;
// P0.0-0.31
for (i = 0; i < 32; i++) {
uint32_t pmask = (1 << i);
if (rise0 & pmask) {
mask0 |= pmask;
if (channel_ids[i] != 0)
irq_handler(channel_ids[i], IRQ_RISE);
}
if (fall0 & pmask) {
mask0 |= pmask;
if (channel_ids[i] != 0)
irq_handler(channel_ids[i], IRQ_FALL);
}
}
// P2.0-2.15
for (i = 0; i < 16; i++) {
uint32_t pmask = (1 << i);
int channel_index = i + 32;
if (rise2 & pmask) {
mask2 |= pmask;
if (channel_ids[channel_index] != 0)
irq_handler(channel_ids[channel_index], IRQ_RISE);
}
if (fall2 & pmask) {
mask2 |= pmask;
if (channel_ids[channel_index] != 0)
irq_handler(channel_ids[channel_index], IRQ_FALL);
}
}
// Clear the interrupts we just handled
LPC_GPIOINT->IO0IntClr = mask0;
LPC_GPIOINT->IO2IntClr = mask2;
}
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) {
if (pin == NC) return -1;
irq_handler = handler;
obj->port = (int)pin & ~0x1F;
obj->pin = (int)pin & 0x1F;
// Interrupts available only on GPIO0 and GPIO2
if (obj->port != LPC_GPIO0_BASE && obj->port != LPC_GPIO2_BASE) {
error("pins on this port cannot generate interrupts");
}
// put us in the interrupt table
int index = (obj->port == LPC_GPIO0_BASE) ? obj->pin : obj->pin + 32;
channel_ids[index] = id;
obj->ch = index;
NVIC_SetVector(EINT3_IRQn, (uint32_t)handle_interrupt_in);
NVIC_EnableIRQ(EINT3_IRQn);
return 0;
}
void gpio_irq_free(gpio_irq_t *obj) {
channel_ids[obj->ch] = 0;
}
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) {
// ensure nothing is pending
switch (obj->port) {
case LPC_GPIO0_BASE: LPC_GPIOINT->IO0IntClr = 1 << obj->pin; break;
case LPC_GPIO2_BASE: LPC_GPIOINT->IO2IntClr = 1 << obj->pin; break;
}
// enable the pin interrupt
if (event == IRQ_RISE) {
switch (obj->port) {
case LPC_GPIO0_BASE:
if (enable) {
LPC_GPIOINT->IO0IntEnR |= 1 << obj->pin;
} else {
LPC_GPIOINT->IO0IntEnR &= ~(1 << obj->pin);
}
break;
case LPC_GPIO2_BASE:
if (enable) {
LPC_GPIOINT->IO2IntEnR |= 1 << obj->pin;
} else {
LPC_GPIOINT->IO2IntEnR &= ~(1 << obj->pin);
}
break;
}
} else {
switch (obj->port) {
case LPC_GPIO0_BASE:
if (enable) {
LPC_GPIOINT->IO0IntEnF |= 1 << obj->pin;
} else {
LPC_GPIOINT->IO0IntEnF &= ~(1 << obj->pin);
}
break;
case LPC_GPIO2_BASE:
if (enable) {
LPC_GPIOINT->IO2IntEnF |= 1 << obj->pin;
} else {
LPC_GPIOINT->IO2IntEnF &= ~(1 << obj->pin);
}
break;
}
}
}
void gpio_irq_enable(gpio_irq_t *obj) {
NVIC_EnableIRQ(EINT3_IRQn);
}
void gpio_irq_disable(gpio_irq_t *obj) {
NVIC_DisableIRQ(EINT3_IRQn);
}

View File

@ -0,0 +1,59 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_GPIO_OBJECT_H
#define MBED_GPIO_OBJECT_H
#include "mbed_assert.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
PinName pin;
uint32_t mask;
__IO uint32_t *reg_dir;
__IO uint32_t *reg_mask;
__IO uint32_t *reg_set;
__IO uint32_t *reg_clr;
__I uint32_t *reg_in;
} gpio_t;
static inline void gpio_write(gpio_t *obj, int value) {
MBED_ASSERT(obj->pin != (PinName)NC);
*obj->reg_mask &= ~obj->mask;
if (value)
*obj->reg_set = obj->mask;
else
*obj->reg_clr = obj->mask;
}
static inline int gpio_read(gpio_t *obj) {
MBED_ASSERT(obj->pin != (PinName)NC);
*obj->reg_mask &= ~obj->mask;
return ((*obj->reg_in & obj->mask) ? 1 : 0);
}
static inline int gpio_is_connected(const gpio_t *obj) {
return obj->pin != (PinName)NC;
}
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,399 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "i2c_api.h"
#include "cmsis.h"
#include "pinmap.h"
static const PinMap PinMap_I2C_SDA[] = {
{P0_0 , I2C_1, 3},
{P0_10, I2C_2, 2},
{P0_19, I2C_1, 3},
{P0_27, I2C_0, 1},
{P2_14, I2C_1, 3},
{P2_30, I2C_2, 3},
{P4_20, I2C_2, 2},
{NC , NC , 0}
};
static const PinMap PinMap_I2C_SCL[] = {
{P0_1 , I2C_1, 3},
{P0_11, I2C_2, 2},
{P0_20, I2C_1, 3},
{P0_28, I2C_0, 1},
{P2_15, I2C_1, 3},
{P2_31, I2C_2, 3},
{P4_21, I2C_2, 2},
{NC , NC, 0}
};
#define I2C_CONSET(x) (x->i2c->I2CONSET)
#define I2C_CONCLR(x) (x->i2c->I2CONCLR)
#define I2C_STAT(x) (x->i2c->I2STAT)
#define I2C_DAT(x) (x->i2c->I2DAT)
#define I2C_SCLL(x, val) (x->i2c->I2SCLL = val)
#define I2C_SCLH(x, val) (x->i2c->I2SCLH = val)
static const uint32_t I2C_addr_offset[2][4] = {
{0x0C, 0x20, 0x24, 0x28},
{0x30, 0x34, 0x38, 0x3C}
};
static inline void i2c_conclr(i2c_t *obj, int start, int stop, int interrupt, int acknowledge) {
I2C_CONCLR(obj) = (start << 5)
| (stop << 4)
| (interrupt << 3)
| (acknowledge << 2);
}
static inline void i2c_conset(i2c_t *obj, int start, int stop, int interrupt, int acknowledge) {
I2C_CONSET(obj) = (start << 5)
| (stop << 4)
| (interrupt << 3)
| (acknowledge << 2);
}
// Clear the Serial Interrupt (SI)
static inline void i2c_clear_SI(i2c_t *obj) {
i2c_conclr(obj, 0, 0, 1, 0);
}
static inline int i2c_status(i2c_t *obj) {
return I2C_STAT(obj);
}
// Wait until the Serial Interrupt (SI) is set
static int i2c_wait_SI(i2c_t *obj) {
int timeout = 0;
while (!(I2C_CONSET(obj) & (1 << 3))) {
timeout++;
if (timeout > 100000) return -1;
}
return 0;
}
static inline void i2c_interface_enable(i2c_t *obj) {
I2C_CONSET(obj) = 0x40;
}
static inline void i2c_power_enable(i2c_t *obj) {
switch ((int)obj->i2c) {
case I2C_0: LPC_SC->PCONP |= 1 << PCI2C0; break;
case I2C_1: LPC_SC->PCONP |= 1 << PCI2C1; break;
case I2C_2: LPC_SC->PCONP |= 1 << PCI2C2; break;
}
}
void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
// determine the SPI to use
I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
obj->i2c = (LPC_I2C_TypeDef *)pinmap_merge(i2c_sda, i2c_scl);
MBED_ASSERT((int)obj->i2c != NC);
// enable power
i2c_power_enable(obj);
// set default frequency at 100k
i2c_frequency(obj, 100000);
i2c_conclr(obj, 1, 1, 1, 1);
i2c_interface_enable(obj);
pinmap_pinout(sda, PinMap_I2C_SDA);
pinmap_pinout(scl, PinMap_I2C_SCL);
}
inline int i2c_start(i2c_t *obj) {
int status = 0;
// 8.1 Before master mode can be entered, I2CON must be initialised to:
// - I2EN STA STO SI AA - -
// - 1 0 0 0 x - -
// if AA = 0, it can't enter slave mode
i2c_conclr(obj, 1, 1, 1, 1);
// The master mode may now be entered by setting the STA bit
// this will generate a start condition when the bus becomes free
i2c_conset(obj, 1, 0, 0, 1);
i2c_wait_SI(obj);
status = i2c_status(obj);
// Clear start bit now transmitted, and interrupt bit
i2c_conclr(obj, 1, 0, 0, 0);
return status;
}
inline int i2c_stop(i2c_t *obj) {
int timeout = 0;
// write the stop bit
i2c_conset(obj, 0, 1, 0, 0);
i2c_clear_SI(obj);
// wait for STO bit to reset
while (I2C_CONSET(obj) & (1 << 4)) {
timeout ++;
if (timeout > 100000) return 1;
}
return 0;
}
static inline int i2c_do_write(i2c_t *obj, int value, uint8_t addr) {
// write the data
I2C_DAT(obj) = value;
// clear SI to init a send
i2c_clear_SI(obj);
// wait and return status
i2c_wait_SI(obj);
return i2c_status(obj);
}
static inline int i2c_do_read(i2c_t *obj, int last) {
// we are in state 0x40 (SLA+R tx'd) or 0x50 (data rx'd and ack)
if (last) {
i2c_conclr(obj, 0, 0, 0, 1); // send a NOT ACK
} else {
i2c_conset(obj, 0, 0, 0, 1); // send a ACK
}
// accept byte
i2c_clear_SI(obj);
// wait for it to arrive
i2c_wait_SI(obj);
// return the data
return (I2C_DAT(obj) & 0xFF);
}
void i2c_frequency(i2c_t *obj, int hz) {
// [TODO] set pclk to /4
uint32_t PCLK = SystemCoreClock / 4;
uint32_t pulse = PCLK / (hz * 2);
// I2C Rate
I2C_SCLL(obj, pulse);
I2C_SCLH(obj, pulse);
}
// The I2C does a read or a write as a whole operation
// There are two types of error conditions it can encounter
// 1) it can not obtain the bus
// 2) it gets error responses at part of the transmission
//
// We tackle them as follows:
// 1) we retry until we get the bus. we could have a "timeout" if we can not get it
// which basically turns it in to a 2)
// 2) on error, we use the standard error mechanisms to report/debug
//
// Therefore an I2C transaction should always complete. If it doesn't it is usually
// because something is setup wrong (e.g. wiring), and we don't need to programatically
// check for that
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
int count, status;
status = i2c_start(obj);
if ((status != 0x10) && (status != 0x08)) {
i2c_stop(obj);
return I2C_ERROR_BUS_BUSY;
}
status = i2c_do_write(obj, (address | 0x01), 1);
if (status != 0x40) {
i2c_stop(obj);
return I2C_ERROR_NO_SLAVE;
}
// Read in all except last byte
for (count = 0; count < (length - 1); count++) {
int value = i2c_do_read(obj, 0);
status = i2c_status(obj);
if (status != 0x50) {
i2c_stop(obj);
return count;
}
data[count] = (char) value;
}
// read in last byte
int value = i2c_do_read(obj, 1);
status = i2c_status(obj);
if (status != 0x58) {
i2c_stop(obj);
return length - 1;
}
data[count] = (char) value;
// If not repeated start, send stop.
if (stop) {
i2c_stop(obj);
}
return length;
}
int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
int i, status;
status = i2c_start(obj);
if ((status != 0x10) && (status != 0x08)) {
i2c_stop(obj);
return I2C_ERROR_BUS_BUSY;
}
status = i2c_do_write(obj, (address & 0xFE), 1);
if (status != 0x18) {
i2c_stop(obj);
return I2C_ERROR_NO_SLAVE;
}
for (i=0; i<length; i++) {
status = i2c_do_write(obj, data[i], 0);
if (status != 0x28) {
i2c_stop(obj);
return i;
}
}
// clearing the serial interrupt here might cause an unintended rewrite of the last byte
// see also issue report https://mbed.org/users/mbed_official/code/mbed/issues/1
// i2c_clear_SI(obj);
// If not repeated start, send stop.
if (stop) {
i2c_stop(obj);
}
return length;
}
void i2c_reset(i2c_t *obj) {
i2c_stop(obj);
}
int i2c_byte_read(i2c_t *obj, int last) {
return (i2c_do_read(obj, last) & 0xFF);
}
int i2c_byte_write(i2c_t *obj, int data) {
int ack;
int status = i2c_do_write(obj, (data & 0xFF), 0);
switch(status) {
case 0x18: case 0x28: // Master transmit ACKs
ack = 1;
break;
case 0x40: // Master receive address transmitted ACK
ack = 1;
break;
case 0xB8: // Slave transmit ACK
ack = 1;
break;
default:
ack = 0;
break;
}
return ack;
}
void i2c_slave_mode(i2c_t *obj, int enable_slave) {
if (enable_slave != 0) {
i2c_conclr(obj, 1, 1, 1, 0);
i2c_conset(obj, 0, 0, 0, 1);
} else {
i2c_conclr(obj, 1, 1, 1, 1);
}
}
int i2c_slave_receive(i2c_t *obj) {
int status;
int retval;
status = i2c_status(obj);
switch(status) {
case 0x60: retval = 3; break;
case 0x70: retval = 2; break;
case 0xA8: retval = 1; break;
default : retval = 0; break;
}
return(retval);
}
int i2c_slave_read(i2c_t *obj, char *data, int length) {
int count = 0;
int status;
do {
i2c_clear_SI(obj);
i2c_wait_SI(obj);
status = i2c_status(obj);
if((status == 0x80) || (status == 0x90)) {
data[count] = I2C_DAT(obj) & 0xFF;
}
count++;
} while (((status == 0x80) || (status == 0x90) ||
(status == 0x060) || (status == 0x70)) && (count < length));
if(status != 0xA0) {
i2c_stop(obj);
}
i2c_clear_SI(obj);
return count;
}
int i2c_slave_write(i2c_t *obj, const char *data, int length) {
int count = 0;
int status;
if(length <= 0) {
return(0);
}
do {
status = i2c_do_write(obj, data[count], 0);
count++;
} while ((count < length) && (status == 0xB8));
if((status != 0xC0) && (status != 0xC8)) {
i2c_stop(obj);
}
i2c_clear_SI(obj);
return(count);
}
void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) {
uint32_t addr;
if ((idx >= 0) && (idx <= 3)) {
addr = ((uint32_t)obj->i2c) + I2C_addr_offset[0][idx];
*((uint32_t *) addr) = address & 0xFF;
}
}

View File

@ -0,0 +1,78 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_OBJECTS_H
#define MBED_OBJECTS_H
#include "cmsis.h"
#include "PortNames.h"
#include "PeripheralNames.h"
#include "PinNames.h"
#ifdef __cplusplus
extern "C" {
#endif
struct gpio_irq_s {
uint32_t port;
uint32_t pin;
uint32_t ch;
};
struct port_s {
__IO uint32_t *reg_dir;
__IO uint32_t *reg_out;
__I uint32_t *reg_in;
PortName port;
uint32_t mask;
};
struct pwmout_s {
__IO uint32_t *MR;
PWMName pwm;
};
struct serial_s {
LPC_UART_TypeDef *uart;
int index;
};
struct analogin_s {
ADCName adc;
};
struct dac_s {
DACName dac;
};
struct can_s {
LPC_CAN_TypeDef *dev;
};
struct i2c_s {
LPC_I2C_TypeDef *i2c;
};
struct spi_s {
LPC_SSP_TypeDef *spi;
};
#include "gpio_object.h"
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,46 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed_assert.h"
#include "pinmap.h"
#include "mbed_error.h"
void pin_function(PinName pin, int function) {
MBED_ASSERT(pin != (PinName)NC);
uint32_t pin_number = (uint32_t)pin - (uint32_t)P0_0;
int index = pin_number >> 4;
int offset = (pin_number & 0xF) << 1;
PINCONARRAY->PINSEL[index] &= ~(0x3 << offset);
PINCONARRAY->PINSEL[index] |= function << offset;
}
void pin_mode(PinName pin, PinMode mode) {
MBED_ASSERT((pin != (PinName)NC) && (mode != OpenDrain));
uint32_t pin_number = (uint32_t)pin - (uint32_t)P0_0;
int index = pin_number >> 5;
int offset = pin_number & 0x1F;
uint32_t drain = ((uint32_t) mode & (uint32_t) OpenDrain) >> 2;
if (!drain) {
index = pin_number >> 4;
offset = (pin_number & 0xF) << 1;
PINCONARRAY->PINMODE[index] &= ~(0x3 << offset);
PINCONARRAY->PINMODE[index] |= (uint32_t)mode << offset;
}
}

View File

@ -0,0 +1,71 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "port_api.h"
#include "pinmap.h"
#include "gpio_api.h"
PinName port_pin(PortName port, int pin_n) {
return (PinName)(LPC_GPIO0_BASE + ((port << PORT_SHIFT) | pin_n));
}
void port_init(port_t *obj, PortName port, int mask, PinDirection dir) {
obj->port = port;
obj->mask = mask;
LPC_GPIO_TypeDef *port_reg = (LPC_GPIO_TypeDef *)(LPC_GPIO0_BASE + ((int)port * 0x20));
// Do not use masking, because it prevents the use of the unmasked pins
// port_reg->FIOMASK = ~mask;
obj->reg_out = &port_reg->FIOPIN;
obj->reg_in = &port_reg->FIOPIN;
obj->reg_dir = &port_reg->FIODIR;
uint32_t i;
// The function is set per pin: reuse gpio logic
for (i=0; i<32; i++) {
if (obj->mask & (1<<i)) {
gpio_set(port_pin(obj->port, i));
}
}
port_dir(obj, dir);
}
void port_mode(port_t *obj, PinMode mode) {
uint32_t i;
// The mode is set per pin: reuse pinmap logic
for (i=0; i<32; i++) {
if (obj->mask & (1<<i)) {
pin_mode(port_pin(obj->port, i), mode);
}
}
}
void port_dir(port_t *obj, PinDirection dir) {
switch (dir) {
case PIN_INPUT : *obj->reg_dir &= ~obj->mask; break;
case PIN_OUTPUT: *obj->reg_dir |= obj->mask; break;
}
}
void port_write(port_t *obj, int value) {
*obj->reg_out = (*obj->reg_in & ~obj->mask) | (value & obj->mask);
}
int port_read(port_t *obj) {
return (*obj->reg_in & obj->mask);
}

View File

@ -0,0 +1,175 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed_assert.h"
#include "pwmout_api.h"
#include "cmsis.h"
#include "pinmap.h"
#define TCR_CNT_EN 0x00000001
#define TCR_RESET 0x00000002
// PORT ID, PWM ID, Pin function
static const PinMap PinMap_PWM[] = {
{P1_18, PWM_1, 2},
{P1_20, PWM_2, 2},
{P1_21, PWM_3, 2},
{P1_23, PWM_4, 2},
{P1_24, PWM_5, 2},
{P1_26, PWM_6, 2},
{P2_0 , PWM_1, 1},
{P2_1 , PWM_2, 1},
{P2_2 , PWM_3, 1},
{P2_3 , PWM_4, 1},
{P2_4 , PWM_5, 1},
{P2_5 , PWM_6, 1},
{P3_24, PWM_1, 3},
{P3_25, PWM_2, 3},
{P3_26, PWM_3, 3},
{P3_27, PWM_4, 3},
{P3_28, PWM_5, 3},
{P3_29, PWM_6, 3},
{NC, NC, 0}
};
__IO uint32_t *PWM_MATCH[] = {
&(LPC_PWM1->MR0),
&(LPC_PWM1->MR1),
&(LPC_PWM1->MR2),
&(LPC_PWM1->MR3),
&(LPC_PWM1->MR4),
&(LPC_PWM1->MR5),
&(LPC_PWM1->MR6)
};
#define TCR_PWM_EN 0x00000008
static unsigned int pwm_clock_mhz;
void pwmout_init(pwmout_t* obj, PinName pin) {
// determine the channel
PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
MBED_ASSERT(pwm != (PWMName)NC);
obj->pwm = pwm;
obj->MR = PWM_MATCH[pwm];
// ensure the power is on
LPC_SC->PCONP |= 1 << 6;
// ensure clock to /4
LPC_SC->PCLKSEL0 &= ~(0x3 << 12); // pclk = /4
LPC_PWM1->PR = 0; // no pre-scale
// ensure single PWM mode
LPC_PWM1->MCR = 1 << 1; // reset TC on match 0
// enable the specific PWM output
LPC_PWM1->PCR |= 1 << (8 + pwm);
pwm_clock_mhz = SystemCoreClock / 4000000;
// default to 20ms: standard for servos, and fine for e.g. brightness control
pwmout_period_ms(obj, 20);
pwmout_write (obj, 0);
// Wire pinout
pinmap_pinout(pin, PinMap_PWM);
}
void pwmout_free(pwmout_t* obj) {
// [TODO]
}
void pwmout_write(pwmout_t* obj, float value) {
if (value < 0.0f) {
value = 0.0;
} else if (value > 1.0f) {
value = 1.0;
}
// set channel match to percentage
uint32_t v = (uint32_t)((float)(LPC_PWM1->MR0) * value);
// workaround for PWM1[1] - Never make it equal MR0, else we get 1 cycle dropout
if (v == LPC_PWM1->MR0) {
v++;
}
*obj->MR = v;
// accept on next period start
LPC_PWM1->LER |= 1 << obj->pwm;
}
float pwmout_read(pwmout_t* obj) {
float v = (float)(*obj->MR) / (float)(LPC_PWM1->MR0);
return (v > 1.0f) ? (1.0f) : (v);
}
void pwmout_period(pwmout_t* obj, float seconds) {
pwmout_period_us(obj, seconds * 1000000.0f);
}
void pwmout_period_ms(pwmout_t* obj, int ms) {
pwmout_period_us(obj, ms * 1000);
}
// Set the PWM period, keeping the duty cycle the same.
void pwmout_period_us(pwmout_t* obj, int us) {
// calculate number of ticks
uint32_t ticks = pwm_clock_mhz * us;
// set reset
LPC_PWM1->TCR = TCR_RESET;
// set the global match register
LPC_PWM1->MR0 = ticks;
// Scale the pulse width to preserve the duty ratio
if (LPC_PWM1->MR0 > 0) {
*obj->MR = (*obj->MR * ticks) / LPC_PWM1->MR0;
}
// set the channel latch to update value at next period start
LPC_PWM1->LER |= 1 << 0;
// enable counter and pwm, clear reset
LPC_PWM1->TCR = TCR_CNT_EN | TCR_PWM_EN;
}
void pwmout_pulsewidth(pwmout_t* obj, float seconds) {
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) {
pwmout_pulsewidth_us(obj, ms * 1000);
}
void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
// calculate number of ticks
uint32_t v = pwm_clock_mhz * us;
// workaround for PWM1[1] - Never make it equal MR0, else we get 1 cycle dropout
if (v == LPC_PWM1->MR0) {
v++;
}
// set the match register value
*obj->MR = v;
// set the channel latch to update value at next period start
LPC_PWM1->LER |= 1 << obj->pwm;
}

View File

@ -0,0 +1,117 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "rtc_api.h"
// ensure rtc is running (unchanged if already running)
/* Setup the RTC based on a time structure, ensuring RTC is enabled
*
* Can be clocked by a 32.768KHz oscillator or prescale divider based on the APB clock
* - We want to use the 32khz clock, allowing for sleep mode
*
* Most registers are not changed by a Reset
* - We must initialize these registers between power-on and setting the RTC into operation
* Clock Control Register
* RTC_CCR[0] : Enable - 0 = Disabled, 1 = Enabled
* RTC_CCR[1] : Reset - 0 = Normal, 1 = Reset
* RTC_CCR[4] : Clock Source - 0 = Prescaler, 1 = 32k Xtal
*
* The RTC may already be running, so we should set it up
* without impacting if it is the case
*/
void rtc_init(void) {
LPC_SC->PCONP |= (1 << PCRTC); // Ensure power is on
LPC_RTC->CCR = 0x00;
// clock source on 2368 is special test mode on 1768!
LPC_RTC->CCR |= 1 << 4; // Ensure clock source is 32KHz Xtal
LPC_RTC->CCR |= 1 << 0; // Ensure the RTC is enabled
}
void rtc_free(void) {
// [TODO]
}
/*
* Little check routine to see if the RTC has been enabled
*
* Clock Control Register
* RTC_CCR[0] : 0 = Disabled, 1 = Enabled
*
*/
int rtc_isenabled(void) {
return(((LPC_RTC->CCR) & 0x01) != 0);
}
/*
* RTC Registers
* RTC_SEC Seconds 0-59
* RTC_MIN Minutes 0-59
* RTC_HOUR Hour 0-23
* RTC_DOM Day of Month 1-28..31
* RTC_DOW Day of Week 0-6
* RTC_DOY Day of Year 1-365
* RTC_MONTH Month 1-12
* RTC_YEAR Year 0-4095
*
* struct tm
* tm_sec seconds after the minute 0-61
* tm_min minutes after the hour 0-59
* tm_hour hours since midnight 0-23
* tm_mday day of the month 1-31
* tm_mon months since January 0-11
* tm_year years since 1900
* tm_wday days since Sunday 0-6
* tm_yday days since January 1 0-365
* tm_isdst Daylight Saving Time flag
*/
time_t rtc_read(void) {
// Setup a tm structure based on the RTC
struct tm timeinfo;
timeinfo.tm_sec = LPC_RTC->SEC;
timeinfo.tm_min = LPC_RTC->MIN;
timeinfo.tm_hour = LPC_RTC->HOUR;
timeinfo.tm_mday = LPC_RTC->DOM;
timeinfo.tm_mon = LPC_RTC->MONTH - 1;
timeinfo.tm_year = LPC_RTC->YEAR - 1900;
// Convert to timestamp
time_t t = mktime(&timeinfo);
return t;
}
void rtc_write(time_t t) {
// Convert the time in to a tm
struct tm *timeinfo = localtime(&t);
// Pause clock, and clear counter register (clears us count)
LPC_RTC->CCR |= 2;
// Set the RTC
LPC_RTC->SEC = timeinfo->tm_sec;
LPC_RTC->MIN = timeinfo->tm_min;
LPC_RTC->HOUR = timeinfo->tm_hour;
LPC_RTC->DOM = timeinfo->tm_mday;
LPC_RTC->MONTH = timeinfo->tm_mon + 1;
LPC_RTC->YEAR = timeinfo->tm_year + 1900;
// Restart clock
LPC_RTC->CCR &= ~((uint32_t)2);
}

View File

@ -0,0 +1,338 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// math.h required for floating point operations for baud rate calculation
#include "mbed_assert.h"
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "serial_api.h"
#include "cmsis.h"
#include "pinmap.h"
/******************************************************************************
* INITIALIZATION
******************************************************************************/
#define UART_NUM 4
static const PinMap PinMap_UART_TX[] = {
{P0_0, UART_3, 2},
{P0_2, UART_0, 1},
{P0_10, UART_2, 1},
{P0_15, UART_1, 1},
{P0_25, UART_3, 3},
{P2_0 , UART_1, 2},
{P2_8 , UART_2, 2},
{P4_28, UART_3, 3},
{NC , NC , 0}
};
static const PinMap PinMap_UART_RX[] = {
{P0_1 , UART_3, 2},
{P0_3 , UART_0, 1},
{P0_11, UART_2, 1},
{P0_16, UART_1, 1},
{P0_26, UART_3, 3},
{P2_1 , UART_1, 2},
{P2_9 , UART_2, 2},
{P4_29, UART_3, 3},
{NC , NC , 0}
};
static uint32_t serial_irq_ids[UART_NUM] = {0};
static uart_irq_handler irq_handler;
int stdio_uart_inited = 0;
serial_t stdio_uart;
void serial_init(serial_t *obj, PinName tx, PinName rx) {
int is_stdio_uart = 0;
// determine the UART to use
UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX);
UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX);
UARTName uart = (UARTName)pinmap_merge(uart_tx, uart_rx);
MBED_ASSERT((int)uart != NC);
obj->uart = (LPC_UART_TypeDef *)uart;
// enable power
switch (uart) {
case UART_0: LPC_SC->PCONP |= 1 << 3; break;
case UART_1: LPC_SC->PCONP |= 1 << 4; break;
case UART_2: LPC_SC->PCONP |= 1 << 24; break;
case UART_3: LPC_SC->PCONP |= 1 << 25; break;
}
// enable fifos and default rx trigger level
obj->uart->FCR = 1 << 0 // FIFO Enable - 0 = Disables, 1 = Enabled
| 0 << 1 // Rx Fifo Reset
| 0 << 2 // Tx Fifo Reset
| 0 << 6; // Rx irq trigger level - 0 = 1 char, 1 = 4 chars, 2 = 8 chars, 3 = 14 chars
// disable irqs
obj->uart->IER = 0 << 0 // Rx Data available irq enable
| 0 << 1 // Tx Fifo empty irq enable
| 0 << 2; // Rx Line Status irq enable
// set default baud rate and format
serial_baud (obj, 9600);
serial_format(obj, 8, ParityNone, 1);
// pinout the chosen uart
pinmap_pinout(tx, PinMap_UART_TX);
pinmap_pinout(rx, PinMap_UART_RX);
// set rx/tx pins in PullUp mode
if (tx != NC) {
pin_mode(tx, PullUp);
}
if (rx != NC) {
pin_mode(rx, PullUp);
}
switch (uart) {
case UART_0: obj->index = 0; break;
case UART_1: obj->index = 1; break;
case UART_2: obj->index = 2; break;
case UART_3: obj->index = 3; break;
}
is_stdio_uart = (uart == STDIO_UART) ? (1) : (0);
if (is_stdio_uart) {
stdio_uart_inited = 1;
memcpy(&stdio_uart, obj, sizeof(serial_t));
}
}
void serial_free(serial_t *obj) {
serial_irq_ids[obj->index] = 0;
}
// serial_baud
// set the baud rate, taking in to account the current SystemFrequency
void serial_baud(serial_t *obj, int baudrate) {
MBED_ASSERT((int)obj->uart <= UART_3);
// The LPC2300 and LPC1700 have a divider and a fractional divider to control the
// baud rate. The formula is:
//
// Baudrate = (1 / PCLK) * 16 * DL * (1 + DivAddVal / MulVal)
// where:
// 1 < MulVal <= 15
// 0 <= DivAddVal < 14
// DivAddVal < MulVal
//
// set pclk to /1
switch ((int)obj->uart) {
case UART_0: LPC_SC->PCLKSEL0 &= ~(0x3 << 6); LPC_SC->PCLKSEL0 |= (0x1 << 6); break;
case UART_1: LPC_SC->PCLKSEL0 &= ~(0x3 << 8); LPC_SC->PCLKSEL0 |= (0x1 << 8); break;
case UART_2: LPC_SC->PCLKSEL1 &= ~(0x3 << 16); LPC_SC->PCLKSEL1 |= (0x1 << 16); break;
case UART_3: LPC_SC->PCLKSEL1 &= ~(0x3 << 18); LPC_SC->PCLKSEL1 |= (0x1 << 18); break;
default: break;
}
uint32_t PCLK = SystemCoreClock;
// First we check to see if the basic divide with no DivAddVal/MulVal
// ratio gives us an integer result. If it does, we set DivAddVal = 0,
// MulVal = 1. Otherwise, we search the valid ratio value range to find
// the closest match. This could be more elegant, using search methods
// and/or lookup tables, but the brute force method is not that much
// slower, and is more maintainable.
uint16_t DL = PCLK / (16 * baudrate);
uint8_t DivAddVal = 0;
uint8_t MulVal = 1;
int hit = 0;
uint16_t dlv;
uint8_t mv, dav;
if ((PCLK % (16 * baudrate)) != 0) { // Checking for zero remainder
int err_best = baudrate, b;
for (mv = 1; mv < 16 && !hit; mv++)
{
for (dav = 0; dav < mv; dav++)
{
// baudrate = PCLK / (16 * dlv * (1 + (DivAdd / Mul))
// solving for dlv, we get dlv = mul * PCLK / (16 * baudrate * (divadd + mul))
// mul has 4 bits, PCLK has 27 so we have 1 bit headroom which can be used for rounding
// for many values of mul and PCLK we have 2 or more bits of headroom which can be used to improve precision
// note: X / 32 doesn't round correctly. Instead, we use ((X / 16) + 1) / 2 for correct rounding
if ((mv * PCLK * 2) & 0x80000000) // 1 bit headroom
dlv = ((((2 * mv * PCLK) / (baudrate * (dav + mv))) / 16) + 1) / 2;
else // 2 bits headroom, use more precision
dlv = ((((4 * mv * PCLK) / (baudrate * (dav + mv))) / 32) + 1) / 2;
// datasheet says if DLL==DLM==0, then 1 is used instead since divide by zero is ungood
if (dlv == 0)
dlv = 1;
// datasheet says if dav > 0 then DL must be >= 2
if ((dav > 0) && (dlv < 2))
dlv = 2;
// integer rearrangement of the baudrate equation (with rounding)
b = ((PCLK * mv / (dlv * (dav + mv) * 8)) + 1) / 2;
// check to see how we went
b = abs(b - baudrate);
if (b < err_best)
{
err_best = b;
DL = dlv;
MulVal = mv;
DivAddVal = dav;
if (b == baudrate)
{
hit = 1;
break;
}
}
}
}
}
// set LCR[DLAB] to enable writing to divider registers
obj->uart->LCR |= (1 << 7);
// set divider values
obj->uart->DLM = (DL >> 8) & 0xFF;
obj->uart->DLL = (DL >> 0) & 0xFF;
obj->uart->FDR = (uint32_t) DivAddVal << 0
| (uint32_t) MulVal << 4;
// clear LCR[DLAB]
obj->uart->LCR &= ~(1 << 7);
}
void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) {
MBED_ASSERT((stop_bits == 1) || (stop_bits == 2)); // 0: 1 stop bits, 1: 2 stop bits
MBED_ASSERT((data_bits > 4) && (data_bits < 9)); // 0: 5 data bits ... 3: 8 data bits
MBED_ASSERT((parity == ParityNone) || (parity == ParityOdd) || (parity == ParityEven) ||
(parity == ParityForced1) || (parity == ParityForced0));
stop_bits -= 1;
data_bits -= 5;
int parity_enable = 0, parity_select = 0;
switch (parity) {
case ParityNone: parity_enable = 0; parity_select = 0; break;
case ParityOdd : parity_enable = 1; parity_select = 0; break;
case ParityEven: parity_enable = 1; parity_select = 1; break;
case ParityForced1: parity_enable = 1; parity_select = 2; break;
case ParityForced0: parity_enable = 1; parity_select = 3; break;
default:
break;
}
obj->uart->LCR = data_bits << 0
| stop_bits << 2
| parity_enable << 3
| parity_select << 4;
}
/******************************************************************************
* INTERRUPTS HANDLING
******************************************************************************/
static inline void uart_irq(uint32_t iir, uint32_t index) {
// [Chapter 14] LPC17xx UART0/2/3: UARTn Interrupt Handling
SerialIrq irq_type;
switch (iir) {
case 1: irq_type = TxIrq; break;
case 2: irq_type = RxIrq; break;
default: return;
}
if (serial_irq_ids[index] != 0){
irq_handler(serial_irq_ids[index], irq_type);
}
}
void uart0_irq() {uart_irq((LPC_UART0->IIR >> 1) & 0x7, 0);}
void uart1_irq() {uart_irq((LPC_UART1->IIR >> 1) & 0x7, 1);}
void uart2_irq() {uart_irq((LPC_UART2->IIR >> 1) & 0x7, 2);}
void uart3_irq() {uart_irq((LPC_UART3->IIR >> 1) & 0x7, 3);}
void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) {
irq_handler = handler;
serial_irq_ids[obj->index] = id;
}
void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
IRQn_Type irq_n = (IRQn_Type)0;
uint32_t vector = 0;
switch ((int)obj->uart) {
case UART_0: irq_n=UART0_IRQn; vector = (uint32_t)&uart0_irq; break;
case UART_1: irq_n=UART1_IRQn; vector = (uint32_t)&uart1_irq; break;
case UART_2: irq_n=UART2_IRQn; vector = (uint32_t)&uart2_irq; break;
case UART_3: irq_n=UART3_IRQn; vector = (uint32_t)&uart3_irq; break;
}
if (enable) {
obj->uart->IER |= 1 << irq;
NVIC_SetVector(irq_n, vector);
NVIC_EnableIRQ(irq_n);
} else { // disable
int all_disabled = 0;
SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
obj->uart->IER &= ~(1 << irq);
all_disabled = (obj->uart->IER & (1 << other_irq)) == 0;
if (all_disabled)
NVIC_DisableIRQ(irq_n);
}
}
/******************************************************************************
* READ/WRITE
******************************************************************************/
int serial_getc(serial_t *obj) {
while (!serial_readable(obj));
return obj->uart->RBR;
}
void serial_putc(serial_t *obj, int c) {
while (!serial_writable(obj));
obj->uart->THR = c;
}
int serial_readable(serial_t *obj) {
return obj->uart->LSR & 0x01;
}
int serial_writable(serial_t *obj) {
return obj->uart->LSR & 0x20;
}
void serial_clear(serial_t *obj) {
obj->uart->FCR = 1 << 1 // rx FIFO reset
| 1 << 2 // tx FIFO reset
| 0 << 6; // interrupt depth
}
void serial_pinout_tx(PinName tx) {
pinmap_pinout(tx, PinMap_UART_TX);
}
void serial_break_set(serial_t *obj) {
obj->uart->LCR |= (1 << 6);
}
void serial_break_clear(serial_t *obj) {
obj->uart->LCR &= ~(1 << 6);
}

View File

@ -0,0 +1,219 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed_assert.h"
#include <math.h>
#include "spi_api.h"
#include "cmsis.h"
#include "pinmap.h"
#include "mbed_error.h"
static const PinMap PinMap_SPI_SCLK[] = {
{P0_7 , SPI_1, 2},
{P0_15, SPI_0, 2},
{P1_20, SPI_0, 3},
{P1_31, SPI_1, 2},
{NC , NC , 0}
};
static const PinMap PinMap_SPI_MOSI[] = {
{P0_9 , SPI_1, 2},
{P0_13, SPI_1, 2},
{P0_18, SPI_0, 2},
{P1_24, SPI_0, 3},
{NC , NC , 0}
};
static const PinMap PinMap_SPI_MISO[] = {
{P0_8 , SPI_1, 2},
{P0_12, SPI_1, 2},
{P0_17, SPI_0, 2},
{P1_23, SPI_0, 3},
{NC , NC , 0}
};
static const PinMap PinMap_SPI_SSEL[] = {
{P0_6 , SPI_1, 2},
{P0_14, SPI_1, 3},
{P0_16, SPI_0, 2},
{P1_21, SPI_0, 3},
{NC , NC , 0}
};
static inline int ssp_disable(spi_t *obj);
static inline int ssp_enable(spi_t *obj);
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
// determine the SPI to use
SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
obj->spi = (LPC_SSP_TypeDef*)pinmap_merge(spi_data, spi_cntl);
MBED_ASSERT((int)obj->spi != NC);
// enable power and clocking
switch ((int)obj->spi) {
case SPI_0: LPC_SC->PCONP |= 1 << PCSSP0; break;
case SPI_1: LPC_SC->PCONP |= 1 << PCSSP1; break;
}
// set default format and frequency
if (ssel == NC) {
spi_format(obj, 8, 0, 0); // 8 bits, mode 0, master
} else {
spi_format(obj, 8, 0, 1); // 8 bits, mode 0, slave
}
spi_frequency(obj, 1000000);
// enable the ssp channel
ssp_enable(obj);
// pin out the spi pins
pinmap_pinout(mosi, PinMap_SPI_MOSI);
pinmap_pinout(miso, PinMap_SPI_MISO);
pinmap_pinout(sclk, PinMap_SPI_SCLK);
if (ssel != NC) {
pinmap_pinout(ssel, PinMap_SPI_SSEL);
}
}
void spi_free(spi_t *obj) {}
void spi_format(spi_t *obj, int bits, int mode, int slave) {
MBED_ASSERT(((bits >= 4) && (bits <= 16)) && ((mode >= 0) && (mode <= 3)));
ssp_disable(obj);
int polarity = (mode & 0x2) ? 1 : 0;
int phase = (mode & 0x1) ? 1 : 0;
// set it up
int DSS = bits - 1; // DSS (data select size)
int SPO = (polarity) ? 1 : 0; // SPO - clock out polarity
int SPH = (phase) ? 1 : 0; // SPH - clock out phase
int FRF = 0; // FRF (frame format) = SPI
uint32_t tmp = obj->spi->CR0;
tmp &= ~(0xFFFF);
tmp |= DSS << 0
| FRF << 4
| SPO << 6
| SPH << 7;
obj->spi->CR0 = tmp;
tmp = obj->spi->CR1;
tmp &= ~(0xD);
tmp |= 0 << 0 // LBM - loop back mode - off
| ((slave) ? 1 : 0) << 2 // MS - master slave mode, 1 = slave
| 0 << 3; // SOD - slave output disable - na
obj->spi->CR1 = tmp;
ssp_enable(obj);
}
void spi_frequency(spi_t *obj, int hz) {
ssp_disable(obj);
// setup the spi clock diveder to /1
switch ((int)obj->spi) {
case SPI_0:
LPC_SC->PCLKSEL1 &= ~(3 << 10);
LPC_SC->PCLKSEL1 |= (1 << 10);
break;
case SPI_1:
LPC_SC->PCLKSEL0 &= ~(3 << 20);
LPC_SC->PCLKSEL0 |= (1 << 20);
break;
}
uint32_t PCLK = SystemCoreClock;
int prescaler;
for (prescaler = 2; prescaler <= 254; prescaler += 2) {
int prescale_hz = PCLK / prescaler;
// calculate the divider
int divider = floor(((float)prescale_hz / (float)hz) + 0.5f);
// check we can support the divider
if (divider < 256) {
// prescaler
obj->spi->CPSR = prescaler;
// divider
obj->spi->CR0 &= ~(0xFFFF << 8);
obj->spi->CR0 |= (divider - 1) << 8;
ssp_enable(obj);
return;
}
}
error("Couldn't setup requested SPI frequency");
}
static inline int ssp_disable(spi_t *obj) {
return obj->spi->CR1 &= ~(1 << 1);
}
static inline int ssp_enable(spi_t *obj) {
return obj->spi->CR1 |= (1 << 1);
}
static inline int ssp_readable(spi_t *obj) {
return obj->spi->SR & (1 << 2);
}
static inline int ssp_writeable(spi_t *obj) {
return obj->spi->SR & (1 << 1);
}
static inline void ssp_write(spi_t *obj, int value) {
while (!ssp_writeable(obj));
obj->spi->DR = value;
}
static inline int ssp_read(spi_t *obj) {
while (!ssp_readable(obj));
return obj->spi->DR;
}
static inline int ssp_busy(spi_t *obj) {
return (obj->spi->SR & (1 << 4)) ? (1) : (0);
}
int spi_master_write(spi_t *obj, int value) {
ssp_write(obj, value);
return ssp_read(obj);
}
int spi_slave_receive(spi_t *obj) {
return (ssp_readable(obj) && !ssp_busy(obj)) ? (1) : (0);
}
int spi_slave_read(spi_t *obj) {
return obj->spi->DR;
}
void spi_slave_write(spi_t *obj, int value) {
while (ssp_writeable(obj) == 0) ;
obj->spi->DR = value;
}
int spi_busy(spi_t *obj) {
return ssp_busy(obj);
}

View File

@ -0,0 +1,64 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stddef.h>
#include "us_ticker_api.h"
#include "PeripheralNames.h"
#define US_TICKER_TIMER ((LPC_TIM_TypeDef *)LPC_TIM3_BASE)
#define US_TICKER_TIMER_IRQn TIMER3_IRQn
int us_ticker_inited = 0;
void us_ticker_init(void) {
if (us_ticker_inited) return;
us_ticker_inited = 1;
LPC_SC->PCONP |= 1 << PCTIM3; // Clock TIMER_3
US_TICKER_TIMER->CTCR = 0x0; // timer mode
uint32_t PCLK = SystemCoreClock / 4;
US_TICKER_TIMER->TCR = 0x2; // reset
uint32_t prescale = PCLK / 1000000; // default to 1MHz (1 us ticks)
US_TICKER_TIMER->PR = prescale - 1;
US_TICKER_TIMER->TCR = 1; // enable = 1, reset = 0
NVIC_SetVector(US_TICKER_TIMER_IRQn, (uint32_t)us_ticker_irq_handler);
NVIC_EnableIRQ(US_TICKER_TIMER_IRQn);
}
uint32_t us_ticker_read() {
if (!us_ticker_inited)
us_ticker_init();
return US_TICKER_TIMER->TC;
}
void us_ticker_set_interrupt(timestamp_t timestamp) {
// set match value
US_TICKER_TIMER->MR0 = (uint32_t)timestamp;
// enable match interrupt
US_TICKER_TIMER->MCR |= 1;
}
void us_ticker_disable_interrupt(void) {
US_TICKER_TIMER->MCR &= ~1;
}
void us_ticker_clear_interrupt(void) {
US_TICKER_TIMER->IR = 1;
}

View File

@ -0,0 +1,329 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: HAL_CM0.S
* Purpose: Hardware Abstraction Layer for ARM7TDMI
* Rev.: V1.0
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
.file "HAL_CM0.S"
.syntax unified
.equ TCB_TSTACK, 40
/*----------------------------------------------------------------------------
* Functions
*---------------------------------------------------------------------------*/
.arm
.section ".text"
.align 2
/*-------------------------- Save Context --------------------------------*/
/* MUST be called the first */
.macro SaveContext
/* Push R0 as we are going to use the register. */ \
STMDB SP!, {R0}
/* Set R0 to SP(user) */
STMDB SP,{SP}^
NOP
SUB SP, SP, #4
LDMIA SP!,{R0}
/* Push the LR return address onto the user stack. */
STMDB R0!, {LR}
/* Now we have saved LR we can use it instead of R0. */
MOV LR, R0
/* Pop R0 so we can save it onto the system mode stack. */
LDMIA SP!, {R0}
/* Push all the system mode registers onto the task stack. */
STMDB LR,{R0-R12,LR}^ /* LR can not be changed because user's LR is used*/
NOP /* pass 1 cycle before changing LR */
SUB LR, LR, #14*4 /* change LR now -15 dwords (R0-R14)*/
/* Push the SPSR onto the task stack. */
MRS R0, SPSR
STMDB LR!, {R0}
/* Store the new top of stack for the task. */
LDR R0,=os_tsk
LDR R0, [R0] /* R0 = (tcb) os_tsk.run */
STR LR, [R0, TCB_TSTACK] /* tcb.tsk_stack = SP(user) */
.endm
/*-------------------------- Restore Context --------------------------------*/
.type RestoreContext, %function
.global RestoreContext
RestoreContext:
.fnstart
.cantunwind
/* Set the LR to the task stack. */
LDR R0,=os_tsk
LDR R1, [R0, 4] /* R1 = (tcb) os_tsk.new */
STR R1, [R0] /* os_tsk.run = os_tsk_newk */
LDR LR, [R1, TCB_TSTACK] /* LR = tcb.tsk_stack */
/* Get the SPSR from the stack. */
LDMFD LR!, {R0} /* SPSR */
MSR SPSR, R0
/* Restore all system mode registers for the task. */
LDMFD LR, {R0-R12,LR}^
NOP
ADD LR, LR, 15*4 /* increase starck pointer */
/* Set SP(user) to LR */
STMDB SP!,{LR}
LDMIA SP,{SP}^
NOP
ADD SP, SP, #4
/* Restore the return address. */
LDR LR, [LR,#-4] /* last dword is task's PC register */
/* And return - correcting the offset in the LR to obtain the */
/* correct address. */
SUBS PC, LR, #4
/*-------------------------- End --------------------------------*/
.fnend
.size RestoreContext, .-RestoreContext
/*--------------------------- rt_set_PSP ------------------------------------*/
# void rt_set_PSP (U32 stack);
.type rt_set_PSP, %function
.global rt_set_PSP
rt_set_PSP:
.fnstart
.cantunwind
MOV SP,R0
BX LR
.fnend
.size rt_set_PSP, .-rt_set_PSP
/*--------------------------- rt_get_PSP ------------------------------------*/
# U32 rt_get_PSP (void);
.type rt_get_PSP, %function
.global rt_get_PSP
rt_get_PSP:
.fnstart
.cantunwind
MOV R0,SP
BX LR
.fnend
.size rt_get_PSP, .-rt_get_PSP
/*--------------------------- _alloc_box ------------------------------------*/
# void *_alloc_box (void *box_mem);
/* Function wrapper for Unprivileged/Privileged mode. */
.type _alloc_box, %function
.global _alloc_box
_alloc_box:
.fnstart
.cantunwind
LDR R3,=rt_alloc_box
MOV R12, R3
MRS R3, CPSR
AND R3, 0x1F
CMP R3, 0x12 /* IRQ mode*/
BNE PrivilegedA
CMP R3, 0x1F /* System mode*/
BNE PrivilegedA
SVC 0
BX LR
PrivilegedA:
BX R12
.fnend
.size _alloc_box, .-_alloc_box
/*--------------------------- _free_box -------------------------------------*/
# int _free_box (void *box_mem, void *box);
/* Function wrapper for Unprivileged/Privileged mode. */
.type _free_box, %function
.global _free_box
_free_box:
.fnstart
.cantunwind
LDR R3,=rt_free_box
MOV R12, R3
MRS R3, CPSR
AND R3, 0x1F
CMP R3, 0x12 /* IRQ mode*/
BNE PrivilegedA
CMP R3, 0x1F /* System mode*/
BNE PrivilegedA
SVC 0
BX LR
PrivilegedF:
BX R12
.fnend
.size _free_box, .-_free_box
/*-------------------------- SVC_Handler ------------------------------------*/
# void SVC_Handler (void);
.type SVC_Handler, %function
.global SVC_Handler
SVC_Handler:
.fnstart
.cantunwind
/* Within an IRQ ISR the link register has an offset from the true return
address, but an SWI ISR does not. Add the offset manually so the same
ISR return code can be used in both cases. */
STMFD SP!, {R0,LR} /* Store registers. */
ADD LR, LR, #4 /* Align LR with IRQ handler */
SaveContext
MOV R11, LR /* Save Task Stack Pointer */
LDMFD SP!, {R0,LR} /* Restore registers and return. */
STMFD SP!, {R11} /* Save Task Stack Pointer */
LDR R5, [LR,#-4] /* Calculate address of SWI instruction and load it into r5. */
BIC R5, R5,#0xff000000 /* Mask off top 8 bits of instruction to give SWI number. */
CMP R5, #0
BNE SVC_User /* User SVC Number > 0 */
MOV LR, PC /* set LR to return address */
BX R12 /* Call SVC Function */
LDMFD SP!, {R11} /* Load Task Stack Pointer */
STMIB R11!, {R0-R3} /* Store return values to Task stack */
SVC_Exit:
B RestoreContext /* return to the task */
/*------------------- User SVC ------------------------------*/
SVC_User:
LDR R6,=SVC_Count
LDR R6,[R6]
CMP R5,R6
LDMFDHI SP!, {R11}
BHI SVC_Done /* Overflow */
LDR R4,=SVC_Table - 4
LSLS R5,R5,#2
LDR R4,[R4,R5] /* Load SVC Function Address */
/* R0-R3,R12 are unchanged */
MOV LR, PC /* set LR to return address */
BX R4 /* Call SVC Function */
LDMFD SP!, {R11} /* Load Task Stack Pointer */
BEQ SVC_Exit /* no need in return values */
STMIB R11!, {R0-R3} /* Store return values to Task stack */
SVC_Done:
B RestoreContext /* return to the task */
.fnend
.size SVC_Handler, .-SVC_Handler
/*-------------------------- IRQ_Handler ---------------------------------*/
# void IRQ_Handler (void);
.type IRQ_Handler, %function
.global IRQ_Handler
IRQ_Handler:
.fnstart
.cantunwind
SaveContext
MOV R0, #0xFFFFFF00
LDR R0, [R0] /* Load address of raised IRQ handler*/
MOV LR, PC
BX R0
MOV R0, #0xFFFFFF00
STR R0, [R0] /* Clear interrupt */
B RestoreContext
.fnend
.size IRQ_Handler, .-IRQ_Handler
/*-------------------------- SysTick_Handler --------------------------------*/
# void SysTick_Handler (void);
.type SysTick_Handler, %function
.global SysTick_Handler
SysTick_Handler:
.fnstart
.cantunwind
PUSH {LR}
BL rt_systick
POP {LR}
BX LR /* return to IRQ handler */
/*-------------------------- End --------------------------------*/
.fnend
.size SysTick_Handler, .-SysTick_Handler
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/
.end

View File

@ -0,0 +1,56 @@
;/*----------------------------------------------------------------------------
; * RL-ARM - RTX
; *----------------------------------------------------------------------------
; * Name: SVC_TABLE.S
; * Purpose: Pre-defined SVC Table for Cortex-M
; * Rev.: V4.60
; *----------------------------------------------------------------------------
; *
; * Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
; * 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.
; *---------------------------------------------------------------------------*/
.file "SVC_Table.S"
.section ".svc_table"
.global SVC_Table
SVC_Table:
/* Insert user SVC functions here. SVC 0 used by RTL Kernel. */
# .long __SVC_1 /* user SVC function */
SVC_End:
.global SVC_Count
SVC_Count:
.long (SVC_End-SVC_Table)/4
.end
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,161 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: HAL_CM.C
* Purpose: Hardware Abstraction Layer for ARM7TDMI
* Rev.: V1.0
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Conf.h"
#include "rt_HAL_CM.h"
/*----------------------------------------------------------------------------
* Global Variables
*---------------------------------------------------------------------------*/
#ifdef DBG_MSG
BIT dbg_msg;
#endif
/*----------------------------------------------------------------------------
* Functions
*---------------------------------------------------------------------------*/
/*--------------------------- rt_init_stack ---------------------------------*/
void rt_init_stack (P_TCB p_TCB, FUNCP task_body) {
/* Prepare TCB and saved context for a first time start of a task. */
U32 *stk,i,size;
/* Prepare a complete interrupt frame for first task start */
size = p_TCB->priv_stack >> 2;
/* Write to the top of stack. */
stk = &p_TCB->stack[size];
/* Auto correct to 8-byte ARM stack alignment. */
if ((U32)stk & 0x04) {
stk--;
}
stk -= 16;
/* Default xPSR and initial PC */
stk[15] = (U32)task_body + 4; /* add 4 byte offset because SUB PC, LR - 4 */
stk[0] = INITIAL_xPSR;
/* Clear R0-R13/LR registers. */
for (i = 1; i < 14; i++) {
stk[i] = 0;
}
/* Assign a void pointer to R0. */
stk[TCB_STACK_R0_OFFSET_DWORDS] = (U32)p_TCB->msg;
/* Initial Task stack pointer. */
p_TCB->tsk_stack = (U32)stk;
/* Task entry point. */
p_TCB->ptask = task_body;
/* Set a magic word for checking of stack overflow.
For the main thread (ID: 0x01) the stack is in a memory area shared with the
heap, therefore the last word of the stack is a moving target.
We want to do stack/heap collision detection instead.
*/
if (p_TCB->task_id != 0x01)
p_TCB->stack[0] = MAGIC_WORD;
}
/*--------------------------- rt_ret_val ----------------------------------*/
static __inline U32 *rt_ret_regs (P_TCB p_TCB) {
/* Get pointer to task return value registers (R0..R3) in Stack */
/* Stack Frame: CPSR,R0-R13,PC */
return (U32 *)(p_TCB->tsk_stack + TCB_STACK_R0_OFFSET_BYTES);
}
void rt_ret_val (P_TCB p_TCB, U32 v0) {
U32 *ret;
ret = rt_ret_regs(p_TCB);
ret[0] = v0;
}
void rt_ret_val2(P_TCB p_TCB, U32 v0, U32 v1) {
U32 *ret;
ret = rt_ret_regs(p_TCB);
ret[0] = v0;
ret[1] = v1;
}
/*--------------------------- dbg_init --------------------------------------*/
#ifdef DBG_MSG
void dbg_init (void) {
if ((DEMCR & DEMCR_TRCENA) &&
(ITM_CONTROL & ITM_ITMENA) &&
(ITM_ENABLE & (1UL << 31))) {
dbg_msg = __TRUE;
}
}
#endif
/*--------------------------- dbg_task_notify -------------------------------*/
#ifdef DBG_MSG
void dbg_task_notify (P_TCB p_tcb, BOOL create) {
while (ITM_PORT31_U32 == 0);
ITM_PORT31_U32 = (U32)p_tcb->ptask;
while (ITM_PORT31_U32 == 0);
ITM_PORT31_U16 = (create << 8) | p_tcb->task_id;
}
#endif
/*--------------------------- dbg_task_switch -------------------------------*/
#ifdef DBG_MSG
void dbg_task_switch (U32 task_id) {
while (ITM_PORT31_U32 == 0);
ITM_PORT31_U8 = task_id;
}
#endif
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,384 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RTX_CM_LIB.H
* Purpose: RTX Kernel System Configuration
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
#include "mbed_error.h"
#if defined (__CC_ARM)
#pragma O3
#define __USED __attribute__((used))
#elif defined (__GNUC__)
#pragma GCC optimize ("O3")
#define __USED __attribute__((used))
#elif defined (__ICCARM__)
#define __USED __root
#endif
/*----------------------------------------------------------------------------
* Definitions
*---------------------------------------------------------------------------*/
#define _declare_box(pool,size,cnt) uint32_t pool[(((size)+3)/4)*(cnt) + 3]
#define _declare_box8(pool,size,cnt) uint64_t pool[(((size)+7)/8)*(cnt) + 2]
#define OS_TCB_SIZE 48
#define OS_TMR_SIZE 8
#if defined (__CC_ARM) && !defined (__MICROLIB)
typedef void *OS_ID;
typedef uint32_t OS_TID;
typedef uint32_t OS_MUT[3];
typedef uint32_t OS_RESULT;
#define runtask_id() rt_tsk_self()
#define mutex_init(m) rt_mut_init(m)
#define mutex_wait(m) os_mut_wait(m,0xFFFF)
#define mutex_rel(m) os_mut_release(m)
extern OS_TID rt_tsk_self (void);
extern void rt_mut_init (OS_ID mutex);
extern OS_RESULT rt_mut_release (OS_ID mutex);
extern OS_RESULT rt_mut_wait (OS_ID mutex, uint16_t timeout);
#define os_mut_wait(mutex,timeout) _os_mut_wait((uint32_t)rt_mut_wait,mutex,timeout)
#define os_mut_release(mutex) _os_mut_release((uint32_t)rt_mut_release,mutex)
OS_RESULT _os_mut_release (uint32_t p, OS_ID mutex) __svc_indirect(0);
OS_RESULT _os_mut_wait (uint32_t p, OS_ID mutex, uint16_t timeout) __svc_indirect(0);
#endif
/*----------------------------------------------------------------------------
* Global Variables
*---------------------------------------------------------------------------*/
#if (OS_TIMERS != 0)
#define OS_TASK_CNT (OS_TASKCNT + 1)
#else
#define OS_TASK_CNT OS_TASKCNT
#endif
uint16_t const os_maxtaskrun = OS_TASK_CNT;
uint32_t const os_rrobin = (OS_ROBIN << 16) | OS_ROBINTOUT;
uint32_t const os_trv = OS_TRV;
uint8_t const os_flags = OS_RUNPRIV;
/* Export following defines to uVision debugger. */
__USED uint32_t const os_clockrate = OS_TICK;
__USED uint32_t const os_timernum = 0;
/* Stack for the os_idle_demon */
unsigned int idle_task_stack[OS_IDLESTKSIZE];
unsigned short const idle_task_stack_size = OS_IDLESTKSIZE;
#ifndef OS_FIFOSZ
#define OS_FIFOSZ 16
#endif
/* Fifo Queue buffer for ISR requests.*/
uint32_t os_fifo[OS_FIFOSZ*2+1];
uint8_t const os_fifo_size = OS_FIFOSZ;
/* An array of Active task pointers. */
void *os_active_TCB[OS_TASK_CNT];
/* User Timers Resources */
#if (OS_TIMERS != 0)
extern void osTimerThread (void const *argument);
osThreadDef(osTimerThread, (osPriority)(OS_TIMERPRIO-3), 4*OS_TIMERSTKSZ);
osThreadId osThreadId_osTimerThread;
osMessageQDef(osTimerMessageQ, OS_TIMERCBQS, void *);
osMessageQId osMessageQId_osTimerMessageQ;
#else
osThreadDef_t os_thread_def_osTimerThread = { NULL };
osThreadId osThreadId_osTimerThread;
osMessageQDef(osTimerMessageQ, 0, void *);
osMessageQId osMessageQId_osTimerMessageQ;
#endif
/*----------------------------------------------------------------------------
* RTX Optimizations (empty functions)
*---------------------------------------------------------------------------*/
#if OS_ROBIN == 0
void rt_init_robin (void) {;}
void rt_chk_robin (void) {;}
#endif
#if OS_STKCHECK == 0
void rt_stk_check (void) {;}
#endif
/*----------------------------------------------------------------------------
* Standard Library multithreading interface
*---------------------------------------------------------------------------*/
#if defined (__CC_ARM) && !defined (__MICROLIB)
static OS_MUT std_libmutex[OS_MUTEXCNT];
static uint32_t nr_mutex;
/*--------------------------- _mutex_initialize -----------------------------*/
int _mutex_initialize (OS_ID *mutex) {
/* Allocate and initialize a system mutex. */
if (nr_mutex >= OS_MUTEXCNT) {
/* If you are here, you need to increase the number OS_MUTEXCNT. */
error("Not enough stdlib mutexes\n");
}
*mutex = &std_libmutex[nr_mutex++];
mutex_init (*mutex);
return (1);
}
/*--------------------------- _mutex_acquire --------------------------------*/
__attribute__((used)) void _mutex_acquire (OS_ID *mutex) {
/* Acquire a system mutex, lock stdlib resources. */
if (runtask_id ()) {
/* RTX running, acquire a mutex. */
mutex_wait (*mutex);
}
}
/*--------------------------- _mutex_release --------------------------------*/
__attribute__((used)) void _mutex_release (OS_ID *mutex) {
/* Release a system mutex, unlock stdlib resources. */
if (runtask_id ()) {
/* RTX running, release a mutex. */
mutex_rel (*mutex);
}
}
#endif
/*----------------------------------------------------------------------------
* RTX Startup
*---------------------------------------------------------------------------*/
/* Main Thread definition */
extern int main (void);
osThreadDef_t os_thread_def_main = {(os_pthread)main, osPriorityNormal, 0, NULL};
// This define should be probably moved to the CMSIS layer
#if defined(TARGET_LPC2460)
extern unsigned char __usr_stack_top__[];
#define INITIAL_SP (__usr_stack_top__)
#else
#error "no target defined"
#endif
#ifdef __CC_ARM
extern unsigned char Image$$RW_IRAM1$$ZI$$Limit[];
#define HEAP_START (Image$$RW_IRAM1$$ZI$$Limit)
#elif defined(__GNUC__)
extern unsigned char __end__[];
#define HEAP_START (__end__)
#elif defined(__ICCARM__)
#pragma section="HEAP"
#define HEAP_START (void *)__section_begin("HEAP")
#endif
void set_main_stack(void) {
// That is the bottom of the main stack block: no collision detection
os_thread_def_main.stack_pointer = HEAP_START;
// Leave OS_SCHEDULERSTKSIZE words for the scheduler and interrupts
os_thread_def_main.stacksize = (INITIAL_SP - (unsigned int)HEAP_START) - (OS_SCHEDULERSTKSIZE * 4);
}
#if defined (__CC_ARM)
#ifdef __MICROLIB
void _main_init (void) __attribute__((section(".ARM.Collect$$$$000000FF")));
void _main_init (void) {
osKernelInitialize();
set_main_stack();
osThreadCreate(&os_thread_def_main, NULL);
osKernelStart();
for (;;);
}
#else
/* The single memory model is checking for stack collision at run time, verifing
that the heap pointer is underneath the stack pointer.
With the RTOS there is not only one stack above the heap, there are multiple
stacks and some of them are underneath the heap pointer.
*/
#pragma import(__use_two_region_memory)
__asm void __rt_entry (void) {
IMPORT __user_setup_stackheap
IMPORT __rt_lib_init
IMPORT os_thread_def_main
IMPORT osKernelInitialize
IMPORT set_main_stack
IMPORT osKernelStart
IMPORT osThreadCreate
IMPORT exit
BL __user_setup_stackheap
MOV R1,R2
BL __rt_lib_init
BL osKernelInitialize
BL set_main_stack
LDR R0,=os_thread_def_main
MOVS R1,#0
BL osThreadCreate
BL osKernelStart
BL exit
ALIGN
}
#endif
#elif defined (__GNUC__)
#ifdef __CS3__
/* CS3 start_c routine.
*
* Copyright (c) 2006, 2007 CodeSourcery Inc
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice is included verbatim in any distributions. No written agreement,
* license, or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their authors
* and need not follow the licensing terms described here, provided that
* the new terms are clearly indicated on the first page of each file where
* they apply.
*/
#include "cs3.h"
extern void __libc_init_array (void);
__attribute ((noreturn)) void __cs3_start_c (void){
unsigned regions = __cs3_region_num;
const struct __cs3_region *rptr = __cs3_regions;
/* Initialize memory */
for (regions = __cs3_region_num, rptr = __cs3_regions; regions--; rptr++) {
long long *src = (long long *)rptr->init;
long long *dst = (long long *)rptr->data;
unsigned limit = rptr->init_size;
unsigned count;
if (src != dst)
for (count = 0; count != limit; count += sizeof (long long))
*dst++ = *src++;
else
dst = (long long *)((char *)dst + limit);
limit = rptr->zero_size;
for (count = 0; count != limit; count += sizeof (long long))
*dst++ = 0;
}
/* Run initializers. */
__libc_init_array ();
osKernelInitialize();
set_main_stack();
osThreadCreate(&os_thread_def_main, NULL);
osKernelStart();
for (;;);
}
#else
__attribute__((naked)) void software_init_hook (void) {
__asm (
".syntax unified\n"
".thumb\n"
"movs r0,#0\n"
"movs r1,#0\n"
"mov r8,r0\n"
"mov r9,r1\n"
"ldr r0,= __libc_fini_array\n"
"bl atexit\n"
"bl __libc_init_array\n"
"mov r0,r8\n"
"mov r1,r9\n"
"bl osKernelInitialize\n"
"bl set_main_stack\n"
"ldr r0,=os_thread_def_main\n"
"movs r1,#0\n"
"bl osThreadCreate\n"
"bl osKernelStart\n"
"bl exit\n"
);
}
#endif
#elif defined (__ICCARM__)
extern int __low_level_init(void);
extern void __iar_data_init3(void);
extern void exit(int arg);
__noreturn __stackless void __cmain(void) {
int a;
if (__low_level_init() != 0) {
__iar_data_init3();
}
osKernelInitialize();
set_main_stack();
osThreadCreate(&os_thread_def_main, NULL);
a = osKernelStart();
exit(a);
}
#endif
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,72 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RTX_CONFIG.H
* Purpose: Exported functions of RTX_Config.c
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
/* Error Codes */
#define OS_ERR_STK_OVF 1
#define OS_ERR_FIFO_OVF 2
#define OS_ERR_MBX_OVF 3
/* Definitions */
#define BOX_ALIGN_8 0x80000000
#define _declare_box(pool,size,cnt) U32 pool[(((size)+3)/4)*(cnt) + 3]
#define _declare_box8(pool,size,cnt) U64 pool[(((size)+7)/8)*(cnt) + 2]
#define _init_box8(pool,size,bsize) _init_box (pool,size,(bsize) | BOX_ALIGN_8)
/* Variables */
extern U32 idle_task_stack[];
extern U32 os_fifo[];
extern void *os_active_TCB[];
/* Constants */
extern U16 const os_maxtaskrun;
extern U32 const os_trv;
extern U8 const os_flags;
extern U32 const os_rrobin;
extern U32 const os_clockrate;
extern U32 const os_timernum;
extern U16 const idle_task_stack_size;
extern U8 const os_fifo_size;
/* Functions */
extern void os_idle_demon (void);
extern int os_tick_init (void);
extern void os_tick_irqack (void);
extern void os_tmr_call (U16 info);
extern void os_error (U32 err_code);
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,246 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RTX_Conf_CM.C
* Purpose: Configuration of CMSIS RTX Kernel for ARM7TDMI
* Rev.: V1.0
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
#include "cmsis_os.h"
/*----------------------------------------------------------------------------
* RTX User configuration part BEGIN
*---------------------------------------------------------------------------*/
//-------- <<< Use Configuration Wizard in Context Menu >>> -----------------
//
// <h>Thread Configuration
// =======================
//
// <o>Number of concurrent running threads <0-250>
// <i> Defines max. number of threads that will run at the same time.
// counting "main", but not counting "osTimerThread"
// <i> Default: 6
#ifndef OS_TASKCNT
# if defined(TARGET_LPC2368) || defined(TARGET_LPC2460)
# define OS_TASKCNT 14
# else
# error "no target defined"
# endif
#endif
// <o>Scheduler (+ interrupts) stack size [bytes] <64-4096:8><#/4>
#ifndef OS_SCHEDULERSTKSIZE
# if defined(TARGET_LPC2368) || defined(TARGET_LPC2460)
# define OS_SCHEDULERSTKSIZE (136*2)
# else
# error "no target defined"
# endif
#endif
// <o>Idle stack size [bytes] <64-4096:8><#/4>
// <i> Defines default stack size for the Idle thread.
#ifndef OS_IDLESTKSIZE
#define OS_IDLESTKSIZE 136
#endif
// <o>Timer Thread stack size [bytes] <64-4096:8><#/4>
// <i> Defines stack size for Timer thread.
// <i> Default: 200
#ifndef OS_TIMERSTKSZ
#define OS_TIMERSTKSZ WORDS_STACK_SIZE
#endif
// <q>Check for stack overflow
// <i> Includes the stack checking code for stack overflow.
// <i> Note that additional code reduces the Kernel performance.
#ifndef OS_STKCHECK
#define OS_STKCHECK 1
#endif
// <o>Processor mode for thread execution
// <0=> Unprivileged mode
// <1=> Privileged mode
// <i> Default: Privileged mode
#ifndef OS_RUNPRIV
#define OS_RUNPRIV 1
#endif
// </h>
// <h>SysTick Timer Configuration
// ==============================
//
// <o>Timer clock value [Hz] <1-1000000000>
// <i> Defines the timer clock value.
// <i> Default: 6000000 (6MHz)
#ifndef OS_CLOCK
# if defined(TARGET_LPC2368)
# define OS_CLOCK 96000000
# elif defined(TARGET_LPC2460)
# define OS_CLOCK 72000000
# else
# error "no target defined"
# endif
#endif
// <o>Timer tick value [us] <1-1000000>
// <i> Defines the timer tick value.
// <i> Default: 1000 (1ms)
#ifndef OS_TICK
#define OS_TICK 1000
#endif
// </h>
// <h>System Configuration
// =======================
//
// <e>Round-Robin Thread switching
// ===============================
//
// <i> Enables Round-Robin Thread switching.
#ifndef OS_ROBIN
#define OS_ROBIN 1
#endif
// <o>Round-Robin Timeout [ticks] <1-1000>
// <i> Defines how long a thread will execute before a thread switch.
// <i> Default: 5
#ifndef OS_ROBINTOUT
#define OS_ROBINTOUT 5
#endif
// </e>
// <e>User Timers
// ==============
// <i> Enables user Timers
#ifndef OS_TIMERS
#define OS_TIMERS 1
#endif
// <o>Timer Thread Priority
// <1=> Low
// <2=> Below Normal
// <3=> Normal
// <4=> Above Normal
// <5=> High
// <6=> Realtime (highest)
// <i> Defines priority for Timer Thread
// <i> Default: High
#ifndef OS_TIMERPRIO
#define OS_TIMERPRIO 5
#endif
// <o>Timer Callback Queue size <1-32>
// <i> Number of concurrent active timer callback functions.
// <i> Default: 4
#ifndef OS_TIMERCBQSZ
#define OS_TIMERCBQS 4
#endif
// </e>
// <o>ISR FIFO Queue size<4=> 4 entries <8=> 8 entries
// <12=> 12 entries <16=> 16 entries
// <24=> 24 entries <32=> 32 entries
// <48=> 48 entries <64=> 64 entries
// <96=> 96 entries
// <i> ISR functions store requests to this buffer,
// <i> when they are called from the interrupt handler.
// <i> Default: 16 entries
#ifndef OS_FIFOSZ
#define OS_FIFOSZ 16
#endif
// </h>
//------------- <<< end of configuration section >>> -----------------------
// Standard library system mutexes
// ===============================
// Define max. number system mutexes that are used to protect
// the arm standard runtime library. For microlib they are not used.
#ifndef OS_MUTEXCNT
#define OS_MUTEXCNT 12
#endif
/*----------------------------------------------------------------------------
* RTX User configuration part END
*---------------------------------------------------------------------------*/
#define OS_TRV ((uint32_t)(((double)OS_CLOCK*(double)OS_TICK)/1E6)-1)
/*----------------------------------------------------------------------------
* OS Idle daemon
*---------------------------------------------------------------------------*/
void os_idle_demon (void) {
/* The idle demon is a system thread, running when no other thread is */
/* ready to run. */
/* Sleep: ideally, we should put the chip to sleep.
Unfortunately, this usually requires disconnecting the interface chip (debugger).
This can be done, but it would break the local file system.
*/
for (;;) {
// sleep();
}
}
/*----------------------------------------------------------------------------
* RTX Errors
*---------------------------------------------------------------------------*/
extern void mbed_die(void);
void os_error (uint32_t err_code) {
/* This function is called when a runtime error is detected. Parameter */
/* 'err_code' holds the runtime error code (defined in RTX_Conf.h). */
mbed_die();
}
void sysThreadError(osStatus status) {
if (status != osOK) {
mbed_die();
}
}
/*----------------------------------------------------------------------------
* RTX Configuration Functions
*---------------------------------------------------------------------------*/
#include "RTX_CM_lib.h"
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,774 @@
/* ----------------------------------------------------------------------
* Copyright (C) 2015 ARM Limited. All rights reserved.
*
* $Date: 5. June 2012
* $Revision: V1.01
*
* Project: CMSIS-RTOS API
* Title: cmsis_os.h RTX header file
*
* Version 0.02
* Initial Proposal Phase
* Version 0.03
* osKernelStart added, optional feature: main started as thread
* osSemaphores have standard behavior
* osTimerCreate does not start the timer, added osTimerStart
* osThreadPass is renamed to osThreadYield
* Version 1.01
* Support for C++ interface
* - const attribute removed from the osXxxxDef_t typedef's
* - const attribute added to the osXxxxDef macros
* Added: osTimerDelete, osMutexDelete, osSemaphoreDelete
* Added: osKernelInitialize
* -------------------------------------------------------------------- */
/**
\page cmsis_os_h Header File Template: cmsis_os.h
The file \b cmsis_os.h is a template header file for a CMSIS-RTOS compliant Real-Time Operating System (RTOS).
Each RTOS that is compliant with CMSIS-RTOS shall provide a specific \b cmsis_os.h header file that represents
its implementation.
The file cmsis_os.h contains:
- CMSIS-RTOS API function definitions
- struct definitions for parameters and return types
- status and priority values used by CMSIS-RTOS API functions
- macros for defining threads and other kernel objects
<b>Name conventions and header file modifications</b>
All definitions are prefixed with \b os to give an unique name space for CMSIS-RTOS functions.
Definitions that are prefixed \b os_ are not used in the application code but local to this header file.
All definitions and functions that belong to a module are grouped and have a common prefix, i.e. \b osThread.
Definitions that are marked with <b>CAN BE CHANGED</b> can be adapted towards the needs of the actual CMSIS-RTOS implementation.
These definitions can be specific to the underlying RTOS kernel.
Definitions that are marked with <b>MUST REMAIN UNCHANGED</b> cannot be altered. Otherwise the CMSIS-RTOS implementation is no longer
compliant to the standard. Note that some functions are optional and need not to be provided by every CMSIS-RTOS implementation.
<b>Function calls from interrupt service routines</b>
The following CMSIS-RTOS functions can be called from threads and interrupt service routines (ISR):
- \ref osSignalSet
- \ref osSemaphoreRelease
- \ref osPoolAlloc, \ref osPoolCAlloc, \ref osPoolFree
- \ref osMessagePut, \ref osMessageGet
- \ref osMailAlloc, \ref osMailCAlloc, \ref osMailGet, \ref osMailPut, \ref osMailFree
Functions that cannot be called from an ISR are verifying the interrupt status and return in case that they are called
from an ISR context the status code \b osErrorISR. In some implementations this condition might be caught using the HARD FAULT vector.
Some CMSIS-RTOS implementations support CMSIS-RTOS function calls from multiple ISR at the same time.
If this is impossible, the CMSIS-RTOS rejects calls by nested ISR functions with the status code \b osErrorISRRecursive.
<b>Define and reference object definitions</b>
With <b>\#define osObjectsExternal</b> objects are defined as external symbols. This allows to create a consistent header file
that is used throughout a project as shown below:
<i>Header File</i>
\code
#include <cmsis_os.h> // CMSIS RTOS header file
// Thread definition
extern void thread_sample (void const *argument); // function prototype
osThreadDef (thread_sample, osPriorityBelowNormal, 1, 100);
// Pool definition
osPoolDef(MyPool, 10, long);
\endcode
This header file defines all objects when included in a C/C++ source file. When <b>\#define osObjectsExternal</b> is
present before the header file, the objects are defined as external symbols. A single consistent header file can therefore be
used throughout the whole project.
<i>Example</i>
\code
#include "osObjects.h" // Definition of the CMSIS-RTOS objects
\endcode
\code
#define osObjectExternal // Objects will be defined as external symbols
#include "osObjects.h" // Reference to the CMSIS-RTOS objects
\endcode
*/
#ifndef _CMSIS_OS_H
#define _CMSIS_OS_H
/// \note MUST REMAIN UNCHANGED: \b osCMSIS identifies the CMSIS-RTOS API version.
#define osCMSIS 0x10001 ///< API version (main [31:16] .sub [15:0])
/// \note CAN BE CHANGED: \b osCMSIS_KERNEL identifies the underlying RTOS kernel and version number.
#define osCMSIS_RTX ((4<<16)|61) ///< RTOS identification and version (main [31:16] .sub [15:0])
/// \note MUST REMAIN UNCHANGED: \b osKernelSystemId shall be consistent in every CMSIS-RTOS.
#define osKernelSystemId "RTX V4.61" ///< RTOS identification string
#define CMSIS_OS_RTX
// The stack space occupied is mainly dependent on the underling C standard library
#if defined(TOOLCHAIN_GCC) || defined(TOOLCHAIN_ARM_STD) || defined(TOOLCHAIN_IAR)
# define WORDS_STACK_SIZE 512
#elif defined(TOOLCHAIN_ARM_MICRO)
# define WORDS_STACK_SIZE 128
#endif
#define DEFAULT_STACK_SIZE (WORDS_STACK_SIZE*4)
/// \note MUST REMAIN UNCHANGED: \b osFeature_xxx shall be consistent in every CMSIS-RTOS.
#define osFeature_MainThread 1 ///< main thread 1=main can be thread, 0=not available
#define osFeature_Pool 1 ///< Memory Pools: 1=available, 0=not available
#define osFeature_MailQ 1 ///< Mail Queues: 1=available, 0=not available
#define osFeature_MessageQ 1 ///< Message Queues: 1=available, 0=not available
#define osFeature_Signals 16 ///< maximum number of Signal Flags available per thread
#define osFeature_Semaphore 65535 ///< maximum count for \ref osSemaphoreCreate function
#define osFeature_Wait 0 ///< osWait function: 1=available, 0=not available
#if defined (__CC_ARM)
#define os_InRegs __value_in_regs // Compiler specific: force struct in registers
#elif defined (__ICCARM__)
#define os_InRegs __value_in_regs // Compiler specific: force struct in registers
#else
#define os_InRegs
#endif
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C"
{
#endif
#include "os_tcb.h"
// ==== Enumeration, structures, defines ====
/// Priority used for thread control.
/// \note MUST REMAIN UNCHANGED: \b osPriority shall be consistent in every CMSIS-RTOS.
typedef enum {
osPriorityIdle = -3, ///< priority: idle (lowest)
osPriorityLow = -2, ///< priority: low
osPriorityBelowNormal = -1, ///< priority: below normal
osPriorityNormal = 0, ///< priority: normal (default)
osPriorityAboveNormal = +1, ///< priority: above normal
osPriorityHigh = +2, ///< priority: high
osPriorityRealtime = +3, ///< priority: realtime (highest)
osPriorityError = 0x84 ///< system cannot determine priority or thread has illegal priority
} osPriority;
/// Timeout value.
/// \note MUST REMAIN UNCHANGED: \b osWaitForever shall be consistent in every CMSIS-RTOS.
#define osWaitForever 0xFFFFFFFF ///< wait forever timeout value
/// Status code values returned by CMSIS-RTOS functions.
/// \note MUST REMAIN UNCHANGED: \b osStatus shall be consistent in every CMSIS-RTOS.
typedef enum {
osOK = 0, ///< function completed; no error or event occurred.
osEventSignal = 0x08, ///< function completed; signal event occurred.
osEventMessage = 0x10, ///< function completed; message event occurred.
osEventMail = 0x20, ///< function completed; mail event occurred.
osEventTimeout = 0x40, ///< function completed; timeout occurred.
osErrorParameter = 0x80, ///< parameter error: a mandatory parameter was missing or specified an incorrect object.
osErrorResource = 0x81, ///< resource not available: a specified resource was not available.
osErrorTimeoutResource = 0xC1, ///< resource not available within given time: a specified resource was not available within the timeout period.
osErrorISR = 0x82, ///< not allowed in ISR context: the function cannot be called from interrupt service routines.
osErrorISRRecursive = 0x83, ///< function called multiple times from ISR with same object.
osErrorPriority = 0x84, ///< system cannot determine priority or thread has illegal priority.
osErrorNoMemory = 0x85, ///< system is out of memory: it was impossible to allocate or reserve memory for the operation.
osErrorValue = 0x86, ///< value of a parameter is out of range.
osErrorOS = 0xFF, ///< unspecified RTOS error: run-time error but no other error message fits.
os_status_reserved = 0x7FFFFFFF ///< prevent from enum down-size compiler optimization.
} osStatus;
/// Timer type value for the timer definition.
/// \note MUST REMAIN UNCHANGED: \b os_timer_type shall be consistent in every CMSIS-RTOS.
typedef enum {
osTimerOnce = 0, ///< one-shot timer
osTimerPeriodic = 1 ///< repeating timer
} os_timer_type;
/// Entry point of a thread.
/// \note MUST REMAIN UNCHANGED: \b os_pthread shall be consistent in every CMSIS-RTOS.
typedef void (*os_pthread) (void const *argument);
/// Entry point of a timer call back function.
/// \note MUST REMAIN UNCHANGED: \b os_ptimer shall be consistent in every CMSIS-RTOS.
typedef void (*os_ptimer) (void const *argument);
// >>> the following data type definitions may shall adapted towards a specific RTOS
/// Thread ID identifies the thread (pointer to a thread control block).
/// \note CAN BE CHANGED: \b os_thread_cb is implementation specific in every CMSIS-RTOS.
typedef struct os_thread_cb *osThreadId;
/// Timer ID identifies the timer (pointer to a timer control block).
/// \note CAN BE CHANGED: \b os_timer_cb is implementation specific in every CMSIS-RTOS.
typedef struct os_timer_cb *osTimerId;
/// Mutex ID identifies the mutex (pointer to a mutex control block).
/// \note CAN BE CHANGED: \b os_mutex_cb is implementation specific in every CMSIS-RTOS.
typedef struct os_mutex_cb *osMutexId;
/// Semaphore ID identifies the semaphore (pointer to a semaphore control block).
/// \note CAN BE CHANGED: \b os_semaphore_cb is implementation specific in every CMSIS-RTOS.
typedef struct os_semaphore_cb *osSemaphoreId;
/// Pool ID identifies the memory pool (pointer to a memory pool control block).
/// \note CAN BE CHANGED: \b os_pool_cb is implementation specific in every CMSIS-RTOS.
typedef struct os_pool_cb *osPoolId;
/// Message ID identifies the message queue (pointer to a message queue control block).
/// \note CAN BE CHANGED: \b os_messageQ_cb is implementation specific in every CMSIS-RTOS.
typedef struct os_messageQ_cb *osMessageQId;
/// Mail ID identifies the mail queue (pointer to a mail queue control block).
/// \note CAN BE CHANGED: \b os_mailQ_cb is implementation specific in every CMSIS-RTOS.
typedef struct os_mailQ_cb *osMailQId;
/// Thread Definition structure contains startup information of a thread.
/// \note CAN BE CHANGED: \b os_thread_def is implementation specific in every CMSIS-RTOS.
typedef struct os_thread_def {
os_pthread pthread; ///< start address of thread function
osPriority tpriority; ///< initial thread priority
uint32_t stacksize; ///< stack size requirements in bytes
uint32_t *stack_pointer; ///< pointer to the stack memory block
struct OS_TCB tcb;
} osThreadDef_t;
/// Timer Definition structure contains timer parameters.
/// \note CAN BE CHANGED: \b os_timer_def is implementation specific in every CMSIS-RTOS.
typedef struct os_timer_def {
os_ptimer ptimer; ///< start address of a timer function
void *timer; ///< pointer to internal data
} osTimerDef_t;
/// Mutex Definition structure contains setup information for a mutex.
/// \note CAN BE CHANGED: \b os_mutex_def is implementation specific in every CMSIS-RTOS.
typedef struct os_mutex_def {
void *mutex; ///< pointer to internal data
} osMutexDef_t;
/// Semaphore Definition structure contains setup information for a semaphore.
/// \note CAN BE CHANGED: \b os_semaphore_def is implementation specific in every CMSIS-RTOS.
typedef struct os_semaphore_def {
void *semaphore; ///< pointer to internal data
} osSemaphoreDef_t;
/// Definition structure for memory block allocation.
/// \note CAN BE CHANGED: \b os_pool_def is implementation specific in every CMSIS-RTOS.
typedef struct os_pool_def {
uint32_t pool_sz; ///< number of items (elements) in the pool
uint32_t item_sz; ///< size of an item
void *pool; ///< pointer to memory for pool
} osPoolDef_t;
/// Definition structure for message queue.
/// \note CAN BE CHANGED: \b os_messageQ_def is implementation specific in every CMSIS-RTOS.
typedef struct os_messageQ_def {
uint32_t queue_sz; ///< number of elements in the queue
void *pool; ///< memory array for messages
} osMessageQDef_t;
/// Definition structure for mail queue.
/// \note CAN BE CHANGED: \b os_mailQ_def is implementation specific in every CMSIS-RTOS.
typedef struct os_mailQ_def {
uint32_t queue_sz; ///< number of elements in the queue
uint32_t item_sz; ///< size of an item
void *pool; ///< memory array for mail
} osMailQDef_t;
/// Event structure contains detailed information about an event.
/// \note MUST REMAIN UNCHANGED: \b os_event shall be consistent in every CMSIS-RTOS.
/// However the struct may be extended at the end.
typedef struct {
osStatus status; ///< status code: event or error information
union {
uint32_t v; ///< message as 32-bit value
void *p; ///< message or mail as void pointer
int32_t signals; ///< signal flags
} value; ///< event value
union {
osMailQId mail_id; ///< mail id obtained by \ref osMailCreate
osMessageQId message_id; ///< message id obtained by \ref osMessageCreate
} def; ///< event definition
} osEvent;
// ==== Kernel Control Functions ====
/// Initialize the RTOS Kernel for creating objects.
/// \return status code that indicates the execution status of the function.
/// \note MUST REMAIN UNCHANGED: \b osKernelInitialize shall be consistent in every CMSIS-RTOS.
osStatus osKernelInitialize (void);
/// Start the RTOS Kernel.
/// \return status code that indicates the execution status of the function.
/// \note MUST REMAIN UNCHANGED: \b osKernelStart shall be consistent in every CMSIS-RTOS.
osStatus osKernelStart (void);
/// Check if the RTOS kernel is already started.
/// \note MUST REMAIN UNCHANGED: \b osKernelRunning shall be consistent in every CMSIS-RTOS.
/// \return 0 RTOS is not started, 1 RTOS is started.
int32_t osKernelRunning(void);
// ==== Thread Management ====
/// Create a Thread Definition with function, priority, and stack requirements.
/// \param name name of the thread function.
/// \param priority initial priority of the thread function.
/// \param stacksz stack size (in bytes) requirements for the thread function.
/// \note CAN BE CHANGED: The parameters to \b osThreadDef shall be consistent but the
/// macro body is implementation specific in every CMSIS-RTOS.
#if defined (osObjectsExternal) // object is external
#define osThreadDef(name, priority, stacksz) \
extern osThreadDef_t os_thread_def_##name
#else // define the object
#define osThreadDef(name, priority, stacksz) \
uint32_t os_thread_def_stack_##name [stacksz / sizeof(uint32_t)]; \
osThreadDef_t os_thread_def_##name = \
{ (name), (priority), (stacksz), (os_thread_def_stack_##name)}
#endif
/// Access a Thread definition.
/// \param name name of the thread definition object.
/// \note CAN BE CHANGED: The parameter to \b osThread shall be consistent but the
/// macro body is implementation specific in every CMSIS-RTOS.
#define osThread(name) \
&os_thread_def_##name
/// Create a thread and add it to Active Threads and set it to state READY.
/// \param[in] thread_def thread definition referenced with \ref osThread.
/// \param[in] argument pointer that is passed to the thread function as start argument.
/// \return thread ID for reference by other functions or NULL in case of error.
/// \note MUST REMAIN UNCHANGED: \b osThreadCreate shall be consistent in every CMSIS-RTOS.
osThreadId osThreadCreate (osThreadDef_t *thread_def, void *argument);
/// Return the thread ID of the current running thread.
/// \return thread ID for reference by other functions or NULL in case of error.
/// \note MUST REMAIN UNCHANGED: \b osThreadGetId shall be consistent in every CMSIS-RTOS.
osThreadId osThreadGetId (void);
/// Terminate execution of a thread and remove it from Active Threads.
/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
/// \return status code that indicates the execution status of the function.
/// \note MUST REMAIN UNCHANGED: \b osThreadTerminate shall be consistent in every CMSIS-RTOS.
osStatus osThreadTerminate (osThreadId thread_id);
/// Pass control to next thread that is in state \b READY.
/// \return status code that indicates the execution status of the function.
/// \note MUST REMAIN UNCHANGED: \b osThreadYield shall be consistent in every CMSIS-RTOS.
osStatus osThreadYield (void);
/// Change priority of an active thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
/// \param[in] priority new priority value for the thread function.
/// \return status code that indicates the execution status of the function.
/// \note MUST REMAIN UNCHANGED: \b osThreadSetPriority shall be consistent in every CMSIS-RTOS.
osStatus osThreadSetPriority (osThreadId thread_id, osPriority priority);
/// Get current priority of an active thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
/// \return current priority value of the thread function.
/// \note MUST REMAIN UNCHANGED: \b osThreadGetPriority shall be consistent in every CMSIS-RTOS.
osPriority osThreadGetPriority (osThreadId thread_id);
// ==== Generic Wait Functions ====
/// Wait for Timeout (Time Delay).
/// \param[in] millisec time delay value
/// \return status code that indicates the execution status of the function.
osStatus osDelay (uint32_t millisec);
#if (defined (osFeature_Wait) && (osFeature_Wait != 0)) // Generic Wait available
/// Wait for Signal, Message, Mail, or Timeout.
/// \param[in] millisec timeout value or 0 in case of no time-out
/// \return event that contains signal, message, or mail information or error code.
/// \note MUST REMAIN UNCHANGED: \b osWait shall be consistent in every CMSIS-RTOS.
os_InRegs osEvent osWait (uint32_t millisec);
#endif // Generic Wait available
// ==== Timer Management Functions ====
/// Define a Timer object.
/// \param name name of the timer object.
/// \param function name of the timer call back function.
/// \note CAN BE CHANGED: The parameter to \b osTimerDef shall be consistent but the
/// macro body is implementation specific in every CMSIS-RTOS.
#if defined (osObjectsExternal) // object is external
#define osTimerDef(name, function) \
extern osTimerDef_t os_timer_def_##name
#else // define the object
#define osTimerDef(name, function) \
uint32_t os_timer_cb_##name[5]; \
osTimerDef_t os_timer_def_##name = \
{ (function), (os_timer_cb_##name) }
#endif
/// Access a Timer definition.
/// \param name name of the timer object.
/// \note CAN BE CHANGED: The parameter to \b osTimer shall be consistent but the
/// macro body is implementation specific in every CMSIS-RTOS.
#define osTimer(name) \
&os_timer_def_##name
/// Create a timer.
/// \param[in] timer_def timer object referenced with \ref osTimer.
/// \param[in] type osTimerOnce for one-shot or osTimerPeriodic for periodic behavior.
/// \param[in] argument argument to the timer call back function.
/// \return timer ID for reference by other functions or NULL in case of error.
/// \note MUST REMAIN UNCHANGED: \b osTimerCreate shall be consistent in every CMSIS-RTOS.
osTimerId osTimerCreate (osTimerDef_t *timer_def, os_timer_type type, void *argument);
/// Start or restart a timer.
/// \param[in] timer_id timer ID obtained by \ref osTimerCreate.
/// \param[in] millisec time delay value of the timer.
/// \return status code that indicates the execution status of the function.
/// \note MUST REMAIN UNCHANGED: \b osTimerStart shall be consistent in every CMSIS-RTOS.
osStatus osTimerStart (osTimerId timer_id, uint32_t millisec);
/// Stop the timer.
/// \param[in] timer_id timer ID obtained by \ref osTimerCreate.
/// \return status code that indicates the execution status of the function.
/// \note MUST REMAIN UNCHANGED: \b osTimerStop shall be consistent in every CMSIS-RTOS.
osStatus osTimerStop (osTimerId timer_id);
/// Delete a timer that was created by \ref osTimerCreate.
/// \param[in] timer_id timer ID obtained by \ref osTimerCreate.
/// \return status code that indicates the execution status of the function.
/// \note MUST REMAIN UNCHANGED: \b osTimerDelete shall be consistent in every CMSIS-RTOS.
osStatus osTimerDelete (osTimerId timer_id);
// ==== Signal Management ====
/// Set the specified Signal Flags of an active thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
/// \param[in] signals specifies the signal flags of the thread that should be set.
/// \return previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters.
/// \note MUST REMAIN UNCHANGED: \b osSignalSet shall be consistent in every CMSIS-RTOS.
int32_t osSignalSet (osThreadId thread_id, int32_t signals);
/// Clear the specified Signal Flags of an active thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
/// \param[in] signals specifies the signal flags of the thread that shall be cleared.
/// \return previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters.
/// \note MUST REMAIN UNCHANGED: \b osSignalClear shall be consistent in every CMSIS-RTOS.
int32_t osSignalClear (osThreadId thread_id, int32_t signals);
/// Get Signal Flags status of an active thread.
/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
/// \return previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters.
/// \note MUST REMAIN UNCHANGED: \b osSignalGet shall be consistent in every CMSIS-RTOS.
int32_t osSignalGet (osThreadId thread_id);
/// Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread.
/// \param[in] signals wait until all specified signal flags set or 0 for any single signal flag.
/// \param[in] millisec timeout value or 0 in case of no time-out.
/// \return event flag information or error code.
/// \note MUST REMAIN UNCHANGED: \b osSignalWait shall be consistent in every CMSIS-RTOS.
os_InRegs osEvent osSignalWait (int32_t signals, uint32_t millisec);
// ==== Mutex Management ====
/// Define a Mutex.
/// \param name name of the mutex object.
/// \note CAN BE CHANGED: The parameter to \b osMutexDef shall be consistent but the
/// macro body is implementation specific in every CMSIS-RTOS.
#if defined (osObjectsExternal) // object is external
#define osMutexDef(name) \
extern osMutexDef_t os_mutex_def_##name
#else // define the object
#define osMutexDef(name) \
uint32_t os_mutex_cb_##name[3]; \
osMutexDef_t os_mutex_def_##name = { (os_mutex_cb_##name) }
#endif
/// Access a Mutex definition.
/// \param name name of the mutex object.
/// \note CAN BE CHANGED: The parameter to \b osMutex shall be consistent but the
/// macro body is implementation specific in every CMSIS-RTOS.
#define osMutex(name) \
&os_mutex_def_##name
/// Create and Initialize a Mutex object.
/// \param[in] mutex_def mutex definition referenced with \ref osMutex.
/// \return mutex ID for reference by other functions or NULL in case of error.
/// \note MUST REMAIN UNCHANGED: \b osMutexCreate shall be consistent in every CMSIS-RTOS.
osMutexId osMutexCreate (osMutexDef_t *mutex_def);
/// Wait until a Mutex becomes available.
/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate.
/// \param[in] millisec timeout value or 0 in case of no time-out.
/// \return status code that indicates the execution status of the function.
/// \note MUST REMAIN UNCHANGED: \b osMutexWait shall be consistent in every CMSIS-RTOS.
osStatus osMutexWait (osMutexId mutex_id, uint32_t millisec);
/// Release a Mutex that was obtained by \ref osMutexWait.
/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate.
/// \return status code that indicates the execution status of the function.
/// \note MUST REMAIN UNCHANGED: \b osMutexRelease shall be consistent in every CMSIS-RTOS.
osStatus osMutexRelease (osMutexId mutex_id);
/// Delete a Mutex that was created by \ref osMutexCreate.
/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate.
/// \return status code that indicates the execution status of the function.
/// \note MUST REMAIN UNCHANGED: \b osMutexDelete shall be consistent in every CMSIS-RTOS.
osStatus osMutexDelete (osMutexId mutex_id);
// ==== Semaphore Management Functions ====
#if (defined (osFeature_Semaphore) && (osFeature_Semaphore != 0)) // Semaphore available
/// Define a Semaphore object.
/// \param name name of the semaphore object.
/// \note CAN BE CHANGED: The parameter to \b osSemaphoreDef shall be consistent but the
/// macro body is implementation specific in every CMSIS-RTOS.
#if defined (osObjectsExternal) // object is external
#define osSemaphoreDef(name) \
extern osSemaphoreDef_t os_semaphore_def_##name
#else // define the object
#define osSemaphoreDef(name) \
uint32_t os_semaphore_cb_##name[2]; \
osSemaphoreDef_t os_semaphore_def_##name = { (os_semaphore_cb_##name) }
#endif
/// Access a Semaphore definition.
/// \param name name of the semaphore object.
/// \note CAN BE CHANGED: The parameter to \b osSemaphore shall be consistent but the
/// macro body is implementation specific in every CMSIS-RTOS.
#define osSemaphore(name) \
&os_semaphore_def_##name
/// Create and Initialize a Semaphore object used for managing resources.
/// \param[in] semaphore_def semaphore definition referenced with \ref osSemaphore.
/// \param[in] count number of available resources.
/// \return semaphore ID for reference by other functions or NULL in case of error.
/// \note MUST REMAIN UNCHANGED: \b osSemaphoreCreate shall be consistent in every CMSIS-RTOS.
osSemaphoreId osSemaphoreCreate (osSemaphoreDef_t *semaphore_def, int32_t count);
/// Wait until a Semaphore token becomes available.
/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate.
/// \param[in] millisec timeout value or 0 in case of no time-out.
/// \return number of available tokens, or -1 in case of incorrect parameters.
/// \note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS.
int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec);
/// Release a Semaphore token.
/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate.
/// \return status code that indicates the execution status of the function.
/// \note MUST REMAIN UNCHANGED: \b osSemaphoreRelease shall be consistent in every CMSIS-RTOS.
osStatus osSemaphoreRelease (osSemaphoreId semaphore_id);
/// Delete a Semaphore that was created by \ref osSemaphoreCreate.
/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate.
/// \return status code that indicates the execution status of the function.
/// \note MUST REMAIN UNCHANGED: \b osSemaphoreDelete shall be consistent in every CMSIS-RTOS.
osStatus osSemaphoreDelete (osSemaphoreId semaphore_id);
#endif // Semaphore available
// ==== Memory Pool Management Functions ====
#if (defined (osFeature_Pool) && (osFeature_Pool != 0)) // Memory Pool Management available
/// \brief Define a Memory Pool.
/// \param name name of the memory pool.
/// \param no maximum number of blocks (objects) in the memory pool.
/// \param type data type of a single block (object).
/// \note CAN BE CHANGED: The parameter to \b osPoolDef shall be consistent but the
/// macro body is implementation specific in every CMSIS-RTOS.
#if defined (osObjectsExternal) // object is external
#define osPoolDef(name, no, type) \
extern osPoolDef_t os_pool_def_##name
#else // define the object
#define osPoolDef(name, no, type) \
uint32_t os_pool_m_##name[3+((sizeof(type)+3)/4)*(no)]; \
osPoolDef_t os_pool_def_##name = \
{ (no), sizeof(type), (os_pool_m_##name) }
#endif
/// \brief Access a Memory Pool definition.
/// \param name name of the memory pool
/// \note CAN BE CHANGED: The parameter to \b osPool shall be consistent but the
/// macro body is implementation specific in every CMSIS-RTOS.
#define osPool(name) \
&os_pool_def_##name
/// Create and Initialize a memory pool.
/// \param[in] pool_def memory pool definition referenced with \ref osPool.
/// \return memory pool ID for reference by other functions or NULL in case of error.
/// \note MUST REMAIN UNCHANGED: \b osPoolCreate shall be consistent in every CMSIS-RTOS.
osPoolId osPoolCreate (osPoolDef_t *pool_def);
/// Allocate a memory block from a memory pool.
/// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate.
/// \return address of the allocated memory block or NULL in case of no memory available.
/// \note MUST REMAIN UNCHANGED: \b osPoolAlloc shall be consistent in every CMSIS-RTOS.
void *osPoolAlloc (osPoolId pool_id);
/// Allocate a memory block from a memory pool and set memory block to zero.
/// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate.
/// \return address of the allocated memory block or NULL in case of no memory available.
/// \note MUST REMAIN UNCHANGED: \b osPoolCAlloc shall be consistent in every CMSIS-RTOS.
void *osPoolCAlloc (osPoolId pool_id);
/// Return an allocated memory block back to a specific memory pool.
/// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate.
/// \param[in] block address of the allocated memory block that is returned to the memory pool.
/// \return status code that indicates the execution status of the function.
/// \note MUST REMAIN UNCHANGED: \b osPoolFree shall be consistent in every CMSIS-RTOS.
osStatus osPoolFree (osPoolId pool_id, void *block);
#endif // Memory Pool Management available
// ==== Message Queue Management Functions ====
#if (defined (osFeature_MessageQ) && (osFeature_MessageQ != 0)) // Message Queues available
/// \brief Create a Message Queue Definition.
/// \param name name of the queue.
/// \param queue_sz maximum number of messages in the queue.
/// \param type data type of a single message element (for debugger).
/// \note CAN BE CHANGED: The parameter to \b osMessageQDef shall be consistent but the
/// macro body is implementation specific in every CMSIS-RTOS.
#if defined (osObjectsExternal) // object is external
#define osMessageQDef(name, queue_sz, type) \
extern osMessageQDef_t os_messageQ_def_##name
#else // define the object
#define osMessageQDef(name, queue_sz, type) \
uint32_t os_messageQ_q_##name[4+(queue_sz)]; \
osMessageQDef_t os_messageQ_def_##name = \
{ (queue_sz), (os_messageQ_q_##name) }
#endif
/// \brief Access a Message Queue Definition.
/// \param name name of the queue
/// \note CAN BE CHANGED: The parameter to \b osMessageQ shall be consistent but the
/// macro body is implementation specific in every CMSIS-RTOS.
#define osMessageQ(name) \
&os_messageQ_def_##name
/// Create and Initialize a Message Queue.
/// \param[in] queue_def queue definition referenced with \ref osMessageQ.
/// \param[in] thread_id thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL.
/// \return message queue ID for reference by other functions or NULL in case of error.
/// \note MUST REMAIN UNCHANGED: \b osMessageCreate shall be consistent in every CMSIS-RTOS.
osMessageQId osMessageCreate (osMessageQDef_t *queue_def, osThreadId thread_id);
/// Put a Message to a Queue.
/// \param[in] queue_id message queue ID obtained with \ref osMessageCreate.
/// \param[in] info message information.
/// \param[in] millisec timeout value or 0 in case of no time-out.
/// \return status code that indicates the execution status of the function.
/// \note MUST REMAIN UNCHANGED: \b osMessagePut shall be consistent in every CMSIS-RTOS.
osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec);
/// Get a Message or Wait for a Message from a Queue.
/// \param[in] queue_id message queue ID obtained with \ref osMessageCreate.
/// \param[in] millisec timeout value or 0 in case of no time-out.
/// \return event information that includes status code.
/// \note MUST REMAIN UNCHANGED: \b osMessageGet shall be consistent in every CMSIS-RTOS.
os_InRegs osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec);
#endif // Message Queues available
// ==== Mail Queue Management Functions ====
#if (defined (osFeature_MailQ) && (osFeature_MailQ != 0)) // Mail Queues available
/// \brief Create a Mail Queue Definition.
/// \param name name of the queue
/// \param queue_sz maximum number of messages in queue
/// \param type data type of a single message element
/// \note CAN BE CHANGED: The parameter to \b osMailQDef shall be consistent but the
/// macro body is implementation specific in every CMSIS-RTOS.
#if defined (osObjectsExternal) // object is external
#define osMailQDef(name, queue_sz, type) \
extern osMailQDef_t os_mailQ_def_##name
#else // define the object
#define osMailQDef(name, queue_sz, type) \
uint32_t os_mailQ_q_##name[4+(queue_sz)]; \
uint32_t os_mailQ_m_##name[3+((sizeof(type)+3)/4)*(queue_sz)]; \
void * os_mailQ_p_##name[2] = { (os_mailQ_q_##name), os_mailQ_m_##name }; \
osMailQDef_t os_mailQ_def_##name = \
{ (queue_sz), sizeof(type), (os_mailQ_p_##name) }
#endif
/// \brief Access a Mail Queue Definition.
/// \param name name of the queue
/// \note CAN BE CHANGED: The parameter to \b osMailQ shall be consistent but the
/// macro body is implementation specific in every CMSIS-RTOS.
#define osMailQ(name) \
&os_mailQ_def_##name
/// Create and Initialize mail queue.
/// \param[in] queue_def reference to the mail queue definition obtain with \ref osMailQ
/// \param[in] thread_id thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL.
/// \return mail queue ID for reference by other functions or NULL in case of error.
/// \note MUST REMAIN UNCHANGED: \b osMailCreate shall be consistent in every CMSIS-RTOS.
osMailQId osMailCreate (osMailQDef_t *queue_def, osThreadId thread_id);
/// Allocate a memory block from a mail.
/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate.
/// \param[in] millisec timeout value or 0 in case of no time-out
/// \return pointer to memory block that can be filled with mail or NULL in case of error.
/// \note MUST REMAIN UNCHANGED: \b osMailAlloc shall be consistent in every CMSIS-RTOS.
void *osMailAlloc (osMailQId queue_id, uint32_t millisec);
/// Allocate a memory block from a mail and set memory block to zero.
/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate.
/// \param[in] millisec timeout value or 0 in case of no time-out
/// \return pointer to memory block that can be filled with mail or NULL in case of error.
/// \note MUST REMAIN UNCHANGED: \b osMailCAlloc shall be consistent in every CMSIS-RTOS.
void *osMailCAlloc (osMailQId queue_id, uint32_t millisec);
/// Put a mail to a queue.
/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate.
/// \param[in] mail memory block previously allocated with \ref osMailAlloc or \ref osMailCAlloc.
/// \return status code that indicates the execution status of the function.
/// \note MUST REMAIN UNCHANGED: \b osMailPut shall be consistent in every CMSIS-RTOS.
osStatus osMailPut (osMailQId queue_id, void *mail);
/// Get a mail from a queue.
/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate.
/// \param[in] millisec timeout value or 0 in case of no time-out
/// \return event that contains mail information or error code.
/// \note MUST REMAIN UNCHANGED: \b osMailGet shall be consistent in every CMSIS-RTOS.
os_InRegs osEvent osMailGet (osMailQId queue_id, uint32_t millisec);
/// Free a memory block from a mail.
/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate.
/// \param[in] mail pointer to the memory block that was obtained with \ref osMailGet.
/// \return status code that indicates the execution status of the function.
/// \note MUST REMAIN UNCHANGED: \b osMailFree shall be consistent in every CMSIS-RTOS.
osStatus osMailFree (osMailQId queue_id, void *mail);
#endif // Mail Queues available
#ifdef __cplusplus
}
#endif
#endif // _CMSIS_OS_H

View File

@ -0,0 +1,55 @@
#ifndef OS_TCB_H
#define OS_TCB_H
/* Types */
typedef char S8;
typedef unsigned char U8;
typedef short S16;
typedef unsigned short U16;
typedef int S32;
typedef unsigned int U32;
typedef long long S64;
typedef unsigned long long U64;
typedef unsigned char BIT;
typedef unsigned int BOOL;
typedef void (*FUNCP)(void);
#define TCB_STACK_LR_OFFSET_BYTES (14*4) // prelast DWORD
#define TCB_STACK_LR_OFFSET_DWORDS (14) // prelast DWORD
#define TCB_STACK_R0_OFFSET_BYTES (1*4) // second DWORD
#define TCB_STACK_R0_OFFSET_DWORDS (1) // second DWORD
typedef struct OS_TCB {
/* General part: identical for all implementations. */
U8 cb_type; /* Control Block Type */
U8 state; /* Task state */
U8 prio; /* Execution priority */
U8 task_id; /* Task ID value for optimized TCB access */
struct OS_TCB *p_lnk; /* Link pointer for ready/sem. wait list */
struct OS_TCB *p_rlnk; /* Link pointer for sem./mbx lst backwards */
struct OS_TCB *p_dlnk; /* Link pointer for delay list */
struct OS_TCB *p_blnk; /* Link pointer for delay list backwards */
U16 delta_time; /* Time until time out */
U16 interval_time; /* Time interval for periodic waits */
U16 events; /* Event flags */
U16 waits; /* Wait flags */
void **msg; /* Direct message passing when task waits */
/* Hardware dependant part: specific for CM processor */
U8 stack_frame; /* Stack frame: 0=Basic, 1=Extended */
U8 reserved1;
U16 reserved2;
U32 priv_stack; /* Private stack size in bytes */
U32 tsk_stack; /* Current task Stack pointer (R13) */
U32 *stack; /* Pointer to Task Stack memory block */
/* Library dependant part */
#if defined (__CC_ARM) && !defined (__MICROLIB)
/* A memory space for arm standard library. */
U32 std_libspace[96/4];
#endif
/* Task entry point used for uVision debugger */
FUNCP ptask; /* Task entry address */
} *P_TCB;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,190 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_EVENT.C
* Purpose: Implements waits and wake-ups for event flags
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Conf.h"
#include "rt_System.h"
#include "rt_Event.h"
#include "rt_List.h"
#include "rt_Task.h"
#include "rt_HAL_CM.h"
/*----------------------------------------------------------------------------
* Functions
*---------------------------------------------------------------------------*/
/*--------------------------- rt_evt_wait -----------------------------------*/
OS_RESULT rt_evt_wait (U16 wait_flags, U16 timeout, BOOL and_wait) {
/* Wait for one or more event flags with optional time-out. */
/* "wait_flags" identifies the flags to wait for. */
/* "timeout" is the time-out limit in system ticks (0xffff if no time-out) */
/* "and_wait" specifies the AND-ing of "wait_flags" as condition to be met */
/* to complete the wait. (OR-ing if set to 0). */
U32 block_state;
if (and_wait) {
/* Check for AND-connected events */
if ((os_tsk.run->events & wait_flags) == wait_flags) {
os_tsk.run->events &= ~wait_flags;
return (OS_R_EVT);
}
block_state = WAIT_AND;
}
else {
/* Check for OR-connected events */
if (os_tsk.run->events & wait_flags) {
os_tsk.run->waits = os_tsk.run->events & wait_flags;
os_tsk.run->events &= ~wait_flags;
return (OS_R_EVT);
}
block_state = WAIT_OR;
}
/* Task has to wait */
os_tsk.run->waits = wait_flags;
rt_block (timeout, (U8)block_state);
return (OS_R_TMO);
}
/*--------------------------- rt_evt_set ------------------------------------*/
void rt_evt_set (U16 event_flags, OS_TID task_id) {
/* Set one or more event flags of a selectable task. */
P_TCB p_tcb;
p_tcb = os_active_TCB[task_id-1];
if (p_tcb == NULL) {
return;
}
p_tcb->events |= event_flags;
event_flags = p_tcb->waits;
/* If the task is not waiting for an event, it should not be put */
/* to ready state. */
if (p_tcb->state == WAIT_AND) {
/* Check for AND-connected events */
if ((p_tcb->events & event_flags) == event_flags) {
goto wkup;
}
}
if (p_tcb->state == WAIT_OR) {
/* Check for OR-connected events */
if (p_tcb->events & event_flags) {
p_tcb->waits &= p_tcb->events;
wkup: p_tcb->events &= ~event_flags;
rt_rmv_dly (p_tcb);
p_tcb->state = READY;
#ifdef __CMSIS_RTOS
rt_ret_val2(p_tcb, 0x08/*osEventSignal*/, p_tcb->waits);
#else
rt_ret_val (p_tcb, OS_R_EVT);
#endif
rt_dispatch (p_tcb);
}
}
}
/*--------------------------- rt_evt_clr ------------------------------------*/
void rt_evt_clr (U16 clear_flags, OS_TID task_id) {
/* Clear one or more event flags (identified by "clear_flags") of a */
/* selectable task (identified by "task"). */
P_TCB task = os_active_TCB[task_id-1];
if (task == NULL) {
return;
}
task->events &= ~clear_flags;
}
/*--------------------------- isr_evt_set -----------------------------------*/
void isr_evt_set (U16 event_flags, OS_TID task_id) {
/* Same function as "os_evt_set", but to be called by ISRs. */
P_TCB p_tcb = os_active_TCB[task_id-1];
if (p_tcb == NULL) {
return;
}
rt_psq_enq (p_tcb, event_flags);
rt_psh_req ();
}
/*--------------------------- rt_evt_get ------------------------------------*/
U16 rt_evt_get (void) {
/* Get events of a running task after waiting for OR connected events. */
return (os_tsk.run->waits);
}
/*--------------------------- rt_evt_psh ------------------------------------*/
void rt_evt_psh (P_TCB p_CB, U16 set_flags) {
/* Check if task has to be waken up */
U16 event_flags;
p_CB->events |= set_flags;
event_flags = p_CB->waits;
if (p_CB->state == WAIT_AND) {
/* Check for AND-connected events */
if ((p_CB->events & event_flags) == event_flags) {
goto rdy;
}
}
if (p_CB->state == WAIT_OR) {
/* Check for OR-connected events */
if (p_CB->events & event_flags) {
p_CB->waits &= p_CB->events;
rdy: p_CB->events &= ~event_flags;
rt_rmv_dly (p_CB);
p_CB->state = READY;
#ifdef __CMSIS_RTOS
rt_ret_val2(p_CB, 0x08/*osEventSignal*/, p_CB->waits);
#else
rt_ret_val (p_CB, OS_R_EVT);
#endif
rt_put_prio (&os_rdy, p_CB);
}
}
}
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,46 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_EVENT.H
* Purpose: Implements waits and wake-ups for event flags
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
/* Functions */
extern OS_RESULT rt_evt_wait (U16 wait_flags, U16 timeout, BOOL and_wait);
extern void rt_evt_set (U16 event_flags, OS_TID task_id);
extern void rt_evt_clr (U16 clear_flags, OS_TID task_id);
extern void isr_evt_set (U16 event_flags, OS_TID task_id);
extern U16 rt_evt_get (void);
extern void rt_evt_psh (P_TCB p_CB, U16 set_flags);
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,216 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_HAL_CM.H
* Purpose: Hardware Abstraction Layer for Cortex-M definitions
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
#include "cmsis.h"
/* Definitions */
#define INITIAL_xPSR 0x10000000
#define DEMCR_TRCENA 0x01000000
#define ITM_ITMENA 0x00000001
#define MAGIC_WORD 0xE25A2EA5
#define SYS_TICK_IRQn TIMER0_IRQn
extern void rt_set_PSP (U32 stack);
extern U32 rt_get_PSP (void);
extern void os_set_env (void);
extern void SysTick_Handler (void);
extern void *_alloc_box (void *box_mem);
extern int _free_box (void *box_mem, void *box);
extern void rt_init_stack (P_TCB p_TCB, FUNCP task_body);
extern void rt_ret_val (P_TCB p_TCB, U32 v0);
extern void rt_ret_val2 (P_TCB p_TCB, U32 v0, U32 v1);
extern void dbg_init (void);
extern void dbg_task_notify (P_TCB p_tcb, BOOL create);
extern void dbg_task_switch (U32 task_id);
#if defined (__CC_ARM) /* ARM Compiler */
#if ((__TARGET_ARCH_7_M || __TARGET_ARCH_7E_M) && !NO_EXCLUSIVE_ACCESS)
#define __USE_EXCLUSIVE_ACCESS
#else
#undef __USE_EXCLUSIVE_ACCESS
#endif
#elif defined (__GNUC__) /* GNU Compiler */
#undef __USE_EXCLUSIVE_ACCESS
#if defined (__CORTEX_M0) || defined (__CORTEX_M0PLUS)
#define __TARGET_ARCH_6S_M 1
#else
#define __TARGET_ARCH_6S_M 0
#endif
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
#define __TARGET_FPU_VFP 1
#else
#define __TARGET_FPU_VFP 0
#endif
#define __inline inline
#define __weak __attribute__((weak))
#elif defined (__ICCARM__) /* IAR Compiler */
#undef __USE_EXCLUSIVE_ACCESS
#if (__CORE__ == __ARM6M__)
#define __TARGET_ARCH_6S_M 1
#else
#define __TARGET_ARCH_6S_M 0
#endif
#if defined __ARMVFP__
#define __TARGET_FPU_VFP 1
#else
#define __TARGET_FPU_VFP 0
#endif
#define __inline inline
#endif
/* NVIC registers */
#define OS_PEND_IRQ() NVIC_PendIRQ(SYS_TICK_IRQn)
#define OS_PENDING NVIC_PendingIRQ(SYS_TICK_IRQn)
#define OS_UNPEND(fl) NVIC_UnpendIRQ(SYS_TICK_IRQn)
#define OS_PEND(fl,p) NVIC_PendIRQ(SYS_TICK_IRQn)
#define OS_LOCK() NVIC_DisableIRQ(SYS_TICK_IRQn)
#define OS_UNLOCK() NVIC_EnableIRQ(SYS_TICK_IRQn)
#define OS_X_PENDING NVIC_PendingIRQ(SYS_TICK_IRQn)
#define OS_X_UNPEND(fl) NVIC_UnpendIRQ(SYS_TICK_IRQn)
#define OS_X_PEND(fl,p) NVIC_PendIRQ(SYS_TICK_IRQn)
#define OS_X_INIT(n) NVIC_EnableIRQ(n)
#define OS_X_LOCK(n) NVIC_DisableIRQ(n)
#define OS_X_UNLOCK(n) NVIC_EnableIRQ(n)
/* Variables */
extern BIT dbg_msg;
/* Functions */
#ifdef __USE_EXCLUSIVE_ACCESS
#define rt_inc(p) while(__strex((__ldrex(p)+1),p))
#define rt_dec(p) while(__strex((__ldrex(p)-1),p))
#else
#define rt_inc(p) __disable_irq();(*p)++;__enable_irq();
#define rt_dec(p) __disable_irq();(*p)--;__enable_irq();
#endif
__inline static U32 rt_inc_qi (U32 size, U8 *count, U8 *first) {
U32 cnt,c2;
#ifdef __USE_EXCLUSIVE_ACCESS
do {
if ((cnt = __ldrex(count)) == size) {
__clrex();
return (cnt); }
} while (__strex(cnt+1, count));
do {
c2 = (cnt = __ldrex(first)) + 1;
if (c2 == size) c2 = 0;
} while (__strex(c2, first));
#else
__disable_irq();
if ((cnt = *count) < size) {
*count = cnt+1;
c2 = (cnt = *first) + 1;
if (c2 == size) c2 = 0;
*first = c2;
}
__enable_irq ();
#endif
return (cnt);
}
__inline static void rt_systick_init (void) {
#if SYS_TICK_IRQn == TIMER0_IRQn
#define SYS_TICK_TIMER LPC_TIM0
LPC_SC->PCONP |= (1 << PCTIM0);
LPC_SC->PCLKSEL0 = (LPC_SC->PCLKSEL0 & (~(1<<3))) | (1<<2); //PCLK == CPUCLK
#elif SYS_TICK_IRQn == TIMER1_IRQn
#define SYS_TICK_TIMER LPC_TIM1
LPC_SC->PCONP |= (1 << PCTIM1);
LPC_SC->PCLKSEL0 = (LPC_SC->PCLKSEL0 & (~(1<<5))) | (1<<4); //PCLK == CPUCLK
#elif SYS_TICK_IRQn == TIMER2_IRQn
#define SYS_TICK_TIMER LPC_TIM2
LPC_SC->PCONP |= (1 << PCTIM2);
LPC_SC->PCLKSEL1 = (LPC_SC->PCLKSEL1 & (~(1<<13))) | (1<<12); //PCLK == CPUCLK
#else
#define SYS_TICK_TIMER LPC_TIM3
LPC_SC->PCONP |= (1 << PCTIM3);
LPC_SC->PCLKSEL1 = (LPC_SC->PCLKSEL1 & (~(1<<15))) | (1<<14); //PCLK == CPUCLK
#endif
// setup Timer to count forever
//interrupt_reg
SYS_TICK_TIMER->TCR = 2; // reset & disable timer 0
SYS_TICK_TIMER->TC = os_trv;
SYS_TICK_TIMER->PR = 0; // set the prescale divider
//Reset of TC and Interrupt when MR3 MR2 matches TC
SYS_TICK_TIMER->MCR = (1 << 9) |(1 << 10); //TMCR_MR3_R_Msk | TMCR_MR3_I_Msk
SYS_TICK_TIMER->MR3 = os_trv; // match registers
SYS_TICK_TIMER->CCR = 0; // disable compare registers
SYS_TICK_TIMER->EMR = 0; // disable external match register
// initialize the interrupt vector
NVIC_SetVector(SYS_TICK_IRQn, (uint32_t)&SysTick_Handler);
SYS_TICK_TIMER->TCR = 1; // enable timer 0
}
__inline static void rt_svc_init (void) {
// TODO: add svcInit
}
#ifdef DBG_MSG
#define DBG_INIT() dbg_init()
#define DBG_TASK_NOTIFY(p_tcb,create) if (dbg_msg) dbg_task_notify(p_tcb,create)
#define DBG_TASK_SWITCH(task_id) if (dbg_msg && (os_tsk.new_tsk != os_tsk.run)) \
dbg_task_switch(task_id)
#else
#define DBG_INIT()
#define DBG_TASK_NOTIFY(p_tcb,create)
#define DBG_TASK_SWITCH(task_id)
#endif
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,320 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_LIST.C
* Purpose: Functions for the management of different lists
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Conf.h"
#include "rt_System.h"
#include "rt_List.h"
#include "rt_Task.h"
#include "rt_Time.h"
#include "rt_HAL_CM.h"
/*----------------------------------------------------------------------------
* Global Variables
*---------------------------------------------------------------------------*/
/* List head of chained ready tasks */
struct OS_XCB os_rdy;
/* List head of chained delay tasks */
struct OS_XCB os_dly;
/*----------------------------------------------------------------------------
* Functions
*---------------------------------------------------------------------------*/
/*--------------------------- rt_put_prio -----------------------------------*/
void rt_put_prio (P_XCB p_CB, P_TCB p_task) {
/* Put task identified with "p_task" into list ordered by priority. */
/* "p_CB" points to head of list; list has always an element at end with */
/* a priority less than "p_task->prio". */
P_TCB p_CB2;
U32 prio;
BOOL sem_mbx = __FALSE;
if (p_CB->cb_type == SCB || p_CB->cb_type == MCB || p_CB->cb_type == MUCB) {
sem_mbx = __TRUE;
}
prio = p_task->prio;
p_CB2 = p_CB->p_lnk;
/* Search for an entry in the list */
while (p_CB2 != NULL && prio <= p_CB2->prio) {
p_CB = (P_XCB)p_CB2;
p_CB2 = p_CB2->p_lnk;
}
/* Entry found, insert the task into the list */
p_task->p_lnk = p_CB2;
p_CB->p_lnk = p_task;
if (sem_mbx) {
if (p_CB2 != NULL) {
p_CB2->p_rlnk = p_task;
}
p_task->p_rlnk = (P_TCB)p_CB;
}
else {
p_task->p_rlnk = NULL;
}
}
/*--------------------------- rt_get_first ----------------------------------*/
P_TCB rt_get_first (P_XCB p_CB) {
/* Get task at head of list: it is the task with highest priority. */
/* "p_CB" points to head of list. */
P_TCB p_first;
p_first = p_CB->p_lnk;
p_CB->p_lnk = p_first->p_lnk;
if (p_CB->cb_type == SCB || p_CB->cb_type == MCB || p_CB->cb_type == MUCB) {
if (p_first->p_lnk != NULL) {
p_first->p_lnk->p_rlnk = (P_TCB)p_CB;
p_first->p_lnk = NULL;
}
p_first->p_rlnk = NULL;
}
else {
p_first->p_lnk = NULL;
}
return (p_first);
}
/*--------------------------- rt_put_rdy_first ------------------------------*/
void rt_put_rdy_first (P_TCB p_task) {
/* Put task identified with "p_task" at the head of the ready list. The */
/* task must have at least a priority equal to highest priority in list. */
p_task->p_lnk = os_rdy.p_lnk;
p_task->p_rlnk = NULL;
os_rdy.p_lnk = p_task;
}
/*--------------------------- rt_get_same_rdy_prio --------------------------*/
P_TCB rt_get_same_rdy_prio (void) {
/* Remove a task of same priority from ready list if any exists. Other- */
/* wise return NULL. */
P_TCB p_first;
p_first = os_rdy.p_lnk;
if (p_first->prio == os_tsk.run->prio) {
os_rdy.p_lnk = os_rdy.p_lnk->p_lnk;
return (p_first);
}
return (NULL);
}
/*--------------------------- rt_resort_prio --------------------------------*/
void rt_resort_prio (P_TCB p_task) {
/* Re-sort ordered lists after the priority of 'p_task' has changed. */
P_TCB p_CB;
if (p_task->p_rlnk == NULL) {
if (p_task->state == READY) {
/* Task is chained into READY list. */
p_CB = (P_TCB)&os_rdy;
goto res;
}
}
else {
p_CB = p_task->p_rlnk;
while (p_CB->cb_type == TCB) {
/* Find a header of this task chain list. */
p_CB = p_CB->p_rlnk;
}
res:rt_rmv_list (p_task);
rt_put_prio ((P_XCB)p_CB, p_task);
}
}
/*--------------------------- rt_put_dly ------------------------------------*/
void rt_put_dly (P_TCB p_task, U16 delay) {
/* Put a task identified with "p_task" into chained delay wait list using */
/* a delay value of "delay". */
P_TCB p;
U32 delta,idelay = delay;
p = (P_TCB)&os_dly;
if (p->p_dlnk == NULL) {
/* Delay list empty */
delta = 0;
goto last;
}
delta = os_dly.delta_time;
while (delta < idelay) {
if (p->p_dlnk == NULL) {
/* End of list found */
last: p_task->p_dlnk = NULL;
p->p_dlnk = p_task;
p_task->p_blnk = p;
p->delta_time = (U16)(idelay - delta);
p_task->delta_time = 0;
return;
}
p = p->p_dlnk;
delta += p->delta_time;
}
/* Right place found */
p_task->p_dlnk = p->p_dlnk;
p->p_dlnk = p_task;
p_task->p_blnk = p;
if (p_task->p_dlnk != NULL) {
p_task->p_dlnk->p_blnk = p_task;
}
p_task->delta_time = (U16)(delta - idelay);
p->delta_time -= p_task->delta_time;
}
/*--------------------------- rt_dec_dly ------------------------------------*/
void rt_dec_dly (void) {
/* Decrement delta time of list head: remove tasks having a value of zero.*/
P_TCB p_rdy;
if (os_dly.p_dlnk == NULL) {
return;
}
os_dly.delta_time--;
while ((os_dly.delta_time == 0) && (os_dly.p_dlnk != NULL)) {
p_rdy = os_dly.p_dlnk;
if (p_rdy->p_rlnk != NULL) {
/* Task is really enqueued, remove task from semaphore/mailbox */
/* timeout waiting list. */
p_rdy->p_rlnk->p_lnk = p_rdy->p_lnk;
if (p_rdy->p_lnk != NULL) {
p_rdy->p_lnk->p_rlnk = p_rdy->p_rlnk;
p_rdy->p_lnk = NULL;
}
p_rdy->p_rlnk = NULL;
}
rt_put_prio (&os_rdy, p_rdy);
os_dly.delta_time = p_rdy->delta_time;
if (p_rdy->state == WAIT_ITV) {
/* Calculate the next time for interval wait. */
p_rdy->delta_time = p_rdy->interval_time + (U16)os_time;
}
p_rdy->state = READY;
os_dly.p_dlnk = p_rdy->p_dlnk;
if (p_rdy->p_dlnk != NULL) {
p_rdy->p_dlnk->p_blnk = (P_TCB)&os_dly;
p_rdy->p_dlnk = NULL;
}
p_rdy->p_blnk = NULL;
}
}
/*--------------------------- rt_rmv_list -----------------------------------*/
void rt_rmv_list (P_TCB p_task) {
/* Remove task identified with "p_task" from ready, semaphore or mailbox */
/* waiting list if enqueued. */
P_TCB p_b;
if (p_task->p_rlnk != NULL) {
/* A task is enqueued in semaphore / mailbox waiting list. */
p_task->p_rlnk->p_lnk = p_task->p_lnk;
if (p_task->p_lnk != NULL) {
p_task->p_lnk->p_rlnk = p_task->p_rlnk;
}
return;
}
p_b = (P_TCB)&os_rdy;
while (p_b != NULL) {
/* Search the ready list for task "p_task" */
if (p_b->p_lnk == p_task) {
p_b->p_lnk = p_task->p_lnk;
return;
}
p_b = p_b->p_lnk;
}
}
/*--------------------------- rt_rmv_dly ------------------------------------*/
void rt_rmv_dly (P_TCB p_task) {
/* Remove task identified with "p_task" from delay list if enqueued. */
P_TCB p_b;
p_b = p_task->p_blnk;
if (p_b != NULL) {
/* Task is really enqueued */
p_b->p_dlnk = p_task->p_dlnk;
if (p_task->p_dlnk != NULL) {
/* 'p_task' is in the middle of list */
p_b->delta_time += p_task->delta_time;
p_task->p_dlnk->p_blnk = p_b;
p_task->p_dlnk = NULL;
}
else {
/* 'p_task' is at the end of list */
p_b->delta_time = 0;
}
p_task->p_blnk = NULL;
}
}
/*--------------------------- rt_psq_enq ------------------------------------*/
void rt_psq_enq (OS_ID entry, U32 arg) {
/* Insert post service request "entry" into ps-queue. */
U32 idx;
idx = rt_inc_qi (os_psq->size, &os_psq->count, &os_psq->first);
if (idx < os_psq->size) {
os_psq->q[idx].id = entry;
os_psq->q[idx].arg = arg;
}
else {
os_error (OS_ERR_FIFO_OVF);
}
}
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,67 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_LIST.H
* Purpose: Functions for the management of different lists
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
/* Definitions */
/* Values for 'cb_type' */
#define TCB 0
#define MCB 1
#define SCB 2
#define MUCB 3
#define HCB 4
/* Variables */
extern struct OS_XCB os_rdy;
extern struct OS_XCB os_dly;
/* Functions */
extern void rt_put_prio (P_XCB p_CB, P_TCB p_task);
extern P_TCB rt_get_first (P_XCB p_CB);
extern void rt_put_rdy_first (P_TCB p_task);
extern P_TCB rt_get_same_rdy_prio (void);
extern void rt_resort_prio (P_TCB p_task);
extern void rt_put_dly (P_TCB p_task, U16 delay);
extern void rt_dec_dly (void);
extern void rt_rmv_list (P_TCB p_task);
extern void rt_rmv_dly (P_TCB p_task);
extern void rt_psq_enq (OS_ID entry, U32 arg);
/* This is a fast macro generating in-line code */
#define rt_rdy_prio(void) (os_rdy.p_lnk->prio)
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,292 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_MAILBOX.C
* Purpose: Implements waits and wake-ups for mailbox messages
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Conf.h"
#include "rt_System.h"
#include "rt_List.h"
#include "rt_Mailbox.h"
#include "rt_MemBox.h"
#include "rt_Task.h"
#include "rt_HAL_CM.h"
/*----------------------------------------------------------------------------
* Functions
*---------------------------------------------------------------------------*/
/*--------------------------- rt_mbx_init -----------------------------------*/
void rt_mbx_init (OS_ID mailbox, U16 mbx_size) {
/* Initialize a mailbox */
P_MCB p_MCB = mailbox;
p_MCB->cb_type = MCB;
p_MCB->state = 0;
p_MCB->isr_st = 0;
p_MCB->p_lnk = NULL;
p_MCB->first = 0;
p_MCB->last = 0;
p_MCB->count = 0;
p_MCB->size = (mbx_size + sizeof(void *) - sizeof(struct OS_MCB)) /
(U32)sizeof (void *);
}
/*--------------------------- rt_mbx_send -----------------------------------*/
OS_RESULT rt_mbx_send (OS_ID mailbox, void *p_msg, U16 timeout) {
/* Send message to a mailbox */
P_MCB p_MCB = mailbox;
P_TCB p_TCB;
if ((p_MCB->p_lnk != NULL) && (p_MCB->state == 1)) {
/* A task is waiting for message */
p_TCB = rt_get_first ((P_XCB)p_MCB);
#ifdef __CMSIS_RTOS
rt_ret_val2(p_TCB, 0x10/*osEventMessage*/, (U32)p_msg);
#else
*p_TCB->msg = p_msg;
rt_ret_val (p_TCB, OS_R_MBX);
#endif
rt_rmv_dly (p_TCB);
rt_dispatch (p_TCB);
}
else {
/* Store message in mailbox queue */
if (p_MCB->count == p_MCB->size) {
/* No free message entry, wait for one. If message queue is full, */
/* then no task is waiting for message. The 'p_MCB->p_lnk' list */
/* pointer can now be reused for send message waits task list. */
if (timeout == 0) {
return (OS_R_TMO);
}
if (p_MCB->p_lnk != NULL) {
rt_put_prio ((P_XCB)p_MCB, os_tsk.run);
}
else {
p_MCB->p_lnk = os_tsk.run;
os_tsk.run->p_lnk = NULL;
os_tsk.run->p_rlnk = (P_TCB)p_MCB;
/* Task is waiting to send a message */
p_MCB->state = 2;
}
os_tsk.run->msg = p_msg;
rt_block (timeout, WAIT_MBX);
return (OS_R_TMO);
}
/* Yes, there is a free entry in a mailbox. */
p_MCB->msg[p_MCB->first] = p_msg;
rt_inc (&p_MCB->count);
if (++p_MCB->first == p_MCB->size) {
p_MCB->first = 0;
}
}
return (OS_R_OK);
}
/*--------------------------- rt_mbx_wait -----------------------------------*/
OS_RESULT rt_mbx_wait (OS_ID mailbox, void **message, U16 timeout) {
/* Receive a message; possibly wait for it */
P_MCB p_MCB = mailbox;
P_TCB p_TCB;
/* If a message is available in the fifo buffer */
/* remove it from the fifo buffer and return. */
if (p_MCB->count) {
*message = p_MCB->msg[p_MCB->last];
if (++p_MCB->last == p_MCB->size) {
p_MCB->last = 0;
}
if ((p_MCB->p_lnk != NULL) && (p_MCB->state == 2)) {
/* A task is waiting to send message */
p_TCB = rt_get_first ((P_XCB)p_MCB);
#ifdef __CMSIS_RTOS
rt_ret_val(p_TCB, 0/*osOK*/);
#else
rt_ret_val(p_TCB, OS_R_OK);
#endif
p_MCB->msg[p_MCB->first] = p_TCB->msg;
if (++p_MCB->first == p_MCB->size) {
p_MCB->first = 0;
}
rt_rmv_dly (p_TCB);
rt_dispatch (p_TCB);
}
else {
rt_dec (&p_MCB->count);
}
return (OS_R_OK);
}
/* No message available: wait for one */
if (timeout == 0) {
return (OS_R_TMO);
}
if (p_MCB->p_lnk != NULL) {
rt_put_prio ((P_XCB)p_MCB, os_tsk.run);
}
else {
p_MCB->p_lnk = os_tsk.run;
os_tsk.run->p_lnk = NULL;
os_tsk.run->p_rlnk = (P_TCB)p_MCB;
/* Task is waiting to receive a message */
p_MCB->state = 1;
}
rt_block(timeout, WAIT_MBX);
#ifndef __CMSIS_RTOS
os_tsk.run->msg = message;
#endif
return (OS_R_TMO);
}
/*--------------------------- rt_mbx_check ----------------------------------*/
OS_RESULT rt_mbx_check (OS_ID mailbox) {
/* Check for free space in a mailbox. Returns the number of messages */
/* that can be stored to a mailbox. It returns 0 when mailbox is full. */
P_MCB p_MCB = mailbox;
return (p_MCB->size - p_MCB->count);
}
/*--------------------------- isr_mbx_send ----------------------------------*/
void isr_mbx_send (OS_ID mailbox, void *p_msg) {
/* Same function as "os_mbx_send", but to be called by ISRs. */
P_MCB p_MCB = mailbox;
rt_psq_enq (p_MCB, (U32)p_msg);
rt_psh_req ();
}
/*--------------------------- isr_mbx_receive -------------------------------*/
OS_RESULT isr_mbx_receive (OS_ID mailbox, void **message) {
/* Receive a message in the interrupt function. The interrupt function */
/* should not wait for a message since this would block the rtx os. */
P_MCB p_MCB = mailbox;
if (p_MCB->count) {
/* A message is available in the fifo buffer. */
*message = p_MCB->msg[p_MCB->last];
if (p_MCB->state == 2) {
/* A task is locked waiting to send message */
rt_psq_enq (p_MCB, 0);
rt_psh_req ();
}
rt_dec (&p_MCB->count);
if (++p_MCB->last == p_MCB->size) {
p_MCB->last = 0;
}
return (OS_R_MBX);
}
return (OS_R_OK);
}
/*--------------------------- rt_mbx_psh ------------------------------------*/
void rt_mbx_psh (P_MCB p_CB, void *p_msg) {
/* Store the message to the mailbox queue or pass it to task directly. */
P_TCB p_TCB;
void *mem;
if (p_CB->p_lnk != NULL) switch (p_CB->state) {
#ifdef __CMSIS_RTOS
case 3:
/* Task is waiting to allocate memory, remove it from the waiting list */
mem = rt_alloc_box(p_msg);
if (mem == NULL) break;
p_TCB = rt_get_first ((P_XCB)p_CB);
rt_ret_val(p_TCB, (U32)mem);
p_TCB->state = READY;
rt_rmv_dly (p_TCB);
rt_put_prio (&os_rdy, p_TCB);
break;
#endif
case 2:
/* Task is waiting to send a message, remove it from the waiting list */
p_TCB = rt_get_first ((P_XCB)p_CB);
#ifdef __CMSIS_RTOS
rt_ret_val(p_TCB, 0/*osOK*/);
#else
rt_ret_val(p_TCB, OS_R_OK);
#endif
p_CB->msg[p_CB->first] = p_TCB->msg;
rt_inc (&p_CB->count);
if (++p_CB->first == p_CB->size) {
p_CB->first = 0;
}
p_TCB->state = READY;
rt_rmv_dly (p_TCB);
rt_put_prio (&os_rdy, p_TCB);
break;
case 1:
/* Task is waiting for a message, pass the message to the task directly */
p_TCB = rt_get_first ((P_XCB)p_CB);
#ifdef __CMSIS_RTOS
rt_ret_val2(p_TCB, 0x10/*osEventMessage*/, (U32)p_msg);
#else
*p_TCB->msg = p_msg;
rt_ret_val (p_TCB, OS_R_MBX);
#endif
p_TCB->state = READY;
rt_rmv_dly (p_TCB);
rt_put_prio (&os_rdy, p_TCB);
break;
} else {
/* No task is waiting for a message, store it to the mailbox queue */
if (p_CB->count < p_CB->size) {
p_CB->msg[p_CB->first] = p_msg;
rt_inc (&p_CB->count);
if (++p_CB->first == p_CB->size) {
p_CB->first = 0;
}
}
else {
os_error (OS_ERR_MBX_OVF);
}
}
}
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,48 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_MAILBOX.H
* Purpose: Implements waits and wake-ups for mailbox messages
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
/* Functions */
extern void rt_mbx_init (OS_ID mailbox, U16 mbx_size);
extern OS_RESULT rt_mbx_send (OS_ID mailbox, void *p_msg, U16 timeout);
extern OS_RESULT rt_mbx_wait (OS_ID mailbox, void **message, U16 timeout);
extern OS_RESULT rt_mbx_check (OS_ID mailbox);
extern void isr_mbx_send (OS_ID mailbox, void *p_msg);
extern OS_RESULT isr_mbx_receive (OS_ID mailbox, void **message);
extern void rt_mbx_psh (P_MCB p_CB, void *p_msg);
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,166 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_MEMBOX.C
* Purpose: Interface functions for fixed memory block management system
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Conf.h"
#include "rt_System.h"
#include "rt_MemBox.h"
#include "rt_HAL_CM.h"
/*----------------------------------------------------------------------------
* Global Functions
*---------------------------------------------------------------------------*/
/*--------------------------- _init_box -------------------------------------*/
int _init_box (void *box_mem, U32 box_size, U32 blk_size) {
/* Initialize memory block system, returns 0 if OK, 1 if fails. */
void *end;
void *blk;
void *next;
U32 sizeof_bm;
/* Create memory structure. */
if (blk_size & BOX_ALIGN_8) {
/* Memory blocks 8-byte aligned. */
blk_size = ((blk_size & ~BOX_ALIGN_8) + 7) & ~7;
sizeof_bm = (sizeof (struct OS_BM) + 7) & ~7;
}
else {
/* Memory blocks 4-byte aligned. */
blk_size = (blk_size + 3) & ~3;
sizeof_bm = sizeof (struct OS_BM);
}
if (blk_size == 0) {
return (1);
}
if ((blk_size + sizeof_bm) > box_size) {
return (1);
}
/* Create a Memory structure. */
blk = ((U8 *) box_mem) + sizeof_bm;
((P_BM) box_mem)->free = blk;
end = ((U8 *) box_mem) + box_size;
((P_BM) box_mem)->end = end;
((P_BM) box_mem)->blk_size = blk_size;
/* Link all free blocks using offsets. */
end = ((U8 *) end) - blk_size;
while (1) {
next = ((U8 *) blk) + blk_size;
if (next > end) break;
*((void **)blk) = next;
blk = next;
}
/* end marker */
*((void **)blk) = 0;
return (0);
}
/*--------------------------- rt_alloc_box ----------------------------------*/
void *rt_alloc_box (void *box_mem) {
/* Allocate a memory block and return start address. */
void **free;
#ifndef __USE_EXCLUSIVE_ACCESS
int irq_dis;
irq_dis = __disable_irq ();
free = ((P_BM) box_mem)->free;
if (free) {
((P_BM) box_mem)->free = *free;
}
if (!irq_dis) __enable_irq ();
#else
do {
if ((free = (void **)__ldrex(&((P_BM) box_mem)->free)) == 0) {
__clrex();
break;
}
} while (__strex((U32)*free, &((P_BM) box_mem)->free));
#endif
return (free);
}
/*--------------------------- _calloc_box -----------------------------------*/
void *_calloc_box (void *box_mem) {
/* Allocate a 0-initialized memory block and return start address. */
void *free;
U32 *p;
U32 i;
free = _alloc_box (box_mem);
if (free) {
p = free;
for (i = ((P_BM) box_mem)->blk_size; i; i -= 4) {
*p = 0;
p++;
}
}
return (free);
}
/*--------------------------- rt_free_box -----------------------------------*/
int rt_free_box (void *box_mem, void *box) {
/* Free a memory block, returns 0 if OK, 1 if box does not belong to box_mem */
#ifndef __USE_EXCLUSIVE_ACCESS
int irq_dis;
#endif
if (box < box_mem || box >= ((P_BM) box_mem)->end) {
return (1);
}
#ifndef __USE_EXCLUSIVE_ACCESS
irq_dis = __disable_irq ();
*((void **)box) = ((P_BM) box_mem)->free;
((P_BM) box_mem)->free = box;
if (!irq_dis) __enable_irq ();
#else
do {
*((void **)box) = (void *)__ldrex(&((P_BM) box_mem)->free);
} while (__strex ((U32)box, &((P_BM) box_mem)->free));
#endif
return (0);
}
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,46 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_MEMBOX.H
* Purpose: Interface functions for fixed memory block management system
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
/* Functions */
#define rt_init_box _init_box
#define rt_calloc_box _calloc_box
extern int _init_box (void *box_mem, U32 box_size, U32 blk_size);
extern void *rt_alloc_box (void *box_mem);
extern void * _calloc_box (void *box_mem);
extern int rt_free_box (void *box_mem, void *box);
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,197 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_MUTEX.C
* Purpose: Implements mutex synchronization objects
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Conf.h"
#include "rt_List.h"
#include "rt_Task.h"
#include "rt_Mutex.h"
#include "rt_HAL_CM.h"
/*----------------------------------------------------------------------------
* Functions
*---------------------------------------------------------------------------*/
/*--------------------------- rt_mut_init -----------------------------------*/
void rt_mut_init (OS_ID mutex) {
/* Initialize a mutex object */
P_MUCB p_MCB = mutex;
p_MCB->cb_type = MUCB;
p_MCB->prio = 0;
p_MCB->level = 0;
p_MCB->p_lnk = NULL;
p_MCB->owner = NULL;
}
/*--------------------------- rt_mut_delete ---------------------------------*/
#ifdef __CMSIS_RTOS
OS_RESULT rt_mut_delete (OS_ID mutex) {
/* Delete a mutex object */
P_MUCB p_MCB = mutex;
P_TCB p_TCB;
/* Restore owner task's priority. */
if (p_MCB->level != 0) {
p_MCB->owner->prio = p_MCB->prio;
if (p_MCB->owner != os_tsk.run) {
rt_resort_prio (p_MCB->owner);
}
}
while (p_MCB->p_lnk != NULL) {
/* A task is waiting for mutex. */
p_TCB = rt_get_first ((P_XCB)p_MCB);
rt_ret_val(p_TCB, 0/*osOK*/);
rt_rmv_dly(p_TCB);
p_TCB->state = READY;
rt_put_prio (&os_rdy, p_TCB);
}
if (os_rdy.p_lnk && (os_rdy.p_lnk->prio > os_tsk.run->prio)) {
/* preempt running task */
rt_put_prio (&os_rdy, os_tsk.run);
os_tsk.run->state = READY;
rt_dispatch (NULL);
}
p_MCB->cb_type = 0;
return (OS_R_OK);
}
#endif
/*--------------------------- rt_mut_release --------------------------------*/
OS_RESULT rt_mut_release (OS_ID mutex) {
/* Release a mutex object */
P_MUCB p_MCB = mutex;
P_TCB p_TCB;
if (p_MCB->level == 0 || p_MCB->owner != os_tsk.run) {
/* Unbalanced mutex release or task is not the owner */
return (OS_R_NOK);
}
if (--p_MCB->level != 0) {
return (OS_R_OK);
}
/* Restore owner task's priority. */
os_tsk.run->prio = p_MCB->prio;
if (p_MCB->p_lnk != NULL) {
/* A task is waiting for mutex. */
p_TCB = rt_get_first ((P_XCB)p_MCB);
#ifdef __CMSIS_RTOS
rt_ret_val(p_TCB, 0/*osOK*/);
#else
rt_ret_val(p_TCB, OS_R_MUT);
#endif
rt_rmv_dly (p_TCB);
/* A waiting task becomes the owner of this mutex. */
p_MCB->level = 1;
p_MCB->owner = p_TCB;
p_MCB->prio = p_TCB->prio;
/* Priority inversion, check which task continues. */
if (os_tsk.run->prio >= rt_rdy_prio()) {
rt_dispatch (p_TCB);
}
else {
/* Ready task has higher priority than running task. */
rt_put_prio (&os_rdy, os_tsk.run);
rt_put_prio (&os_rdy, p_TCB);
os_tsk.run->state = READY;
p_TCB->state = READY;
rt_dispatch (NULL);
}
}
else {
/* Check if own priority raised by priority inversion. */
if (rt_rdy_prio() > os_tsk.run->prio) {
rt_put_prio (&os_rdy, os_tsk.run);
os_tsk.run->state = READY;
rt_dispatch (NULL);
}
}
return (OS_R_OK);
}
/*--------------------------- rt_mut_wait -----------------------------------*/
OS_RESULT rt_mut_wait (OS_ID mutex, U16 timeout) {
/* Wait for a mutex, continue when mutex is free. */
P_MUCB p_MCB = mutex;
if (p_MCB->level == 0) {
p_MCB->owner = os_tsk.run;
p_MCB->prio = os_tsk.run->prio;
goto inc;
}
if (p_MCB->owner == os_tsk.run) {
/* OK, running task is the owner of this mutex. */
inc:p_MCB->level++;
return (OS_R_OK);
}
/* Mutex owned by another task, wait until released. */
if (timeout == 0) {
return (OS_R_TMO);
}
/* Raise the owner task priority if lower than current priority. */
/* This priority inversion is called priority inheritance. */
if (p_MCB->prio < os_tsk.run->prio) {
p_MCB->owner->prio = os_tsk.run->prio;
rt_resort_prio (p_MCB->owner);
}
if (p_MCB->p_lnk != NULL) {
rt_put_prio ((P_XCB)p_MCB, os_tsk.run);
}
else {
p_MCB->p_lnk = os_tsk.run;
os_tsk.run->p_lnk = NULL;
os_tsk.run->p_rlnk = (P_TCB)p_MCB;
}
rt_block(timeout, WAIT_MUT);
return (OS_R_TMO);
}
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,44 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_MUTEX.H
* Purpose: Implements mutex synchronization objects
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
/* Functions */
extern void rt_mut_init (OS_ID mutex);
extern OS_RESULT rt_mut_delete (OS_ID mutex);
extern OS_RESULT rt_mut_release (OS_ID mutex);
extern OS_RESULT rt_mut_wait (OS_ID mutex, U16 timeout);
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,84 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_ROBIN.C
* Purpose: Round Robin Task switching
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Conf.h"
#include "rt_List.h"
#include "rt_Task.h"
#include "rt_Time.h"
#include "rt_Robin.h"
#include "rt_HAL_CM.h"
/*----------------------------------------------------------------------------
* Global Variables
*---------------------------------------------------------------------------*/
struct OS_ROBIN os_robin;
/*----------------------------------------------------------------------------
* Global Functions
*---------------------------------------------------------------------------*/
/*--------------------------- rt_init_robin ---------------------------------*/
__weak void rt_init_robin (void) {
/* Initialize Round Robin variables. */
os_robin.task = NULL;
os_robin.tout = (U16)os_rrobin;
}
/*--------------------------- rt_chk_robin ----------------------------------*/
__weak void rt_chk_robin (void) {
/* Check if Round Robin timeout expired and switch to the next ready task.*/
P_TCB p_new;
if (os_robin.task != os_rdy.p_lnk) {
/* New task was suspended, reset Round Robin timeout. */
os_robin.task = os_rdy.p_lnk;
os_robin.time = (U16)os_time + os_robin.tout - 1;
}
if (os_robin.time == (U16)os_time) {
/* Round Robin timeout has expired, swap Robin tasks. */
os_robin.task = NULL;
p_new = rt_get_first (&os_rdy);
rt_put_prio ((P_XCB)&os_rdy, p_new);
}
}
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,45 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_ROBIN.H
* Purpose: Round Robin Task switching definitions
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
/* Variables */
extern struct OS_ROBIN os_robin;
/* Functions */
extern void rt_init_robin (void);
extern void rt_chk_robin (void);
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,183 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_SEMAPHORE.C
* Purpose: Implements binary and counting semaphores
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Conf.h"
#include "rt_System.h"
#include "rt_List.h"
#include "rt_Task.h"
#include "rt_Semaphore.h"
#include "rt_HAL_CM.h"
/*----------------------------------------------------------------------------
* Functions
*---------------------------------------------------------------------------*/
/*--------------------------- rt_sem_init -----------------------------------*/
void rt_sem_init (OS_ID semaphore, U16 token_count) {
/* Initialize a semaphore */
P_SCB p_SCB = semaphore;
p_SCB->cb_type = SCB;
p_SCB->p_lnk = NULL;
p_SCB->tokens = token_count;
}
/*--------------------------- rt_sem_delete ---------------------------------*/
#ifdef __CMSIS_RTOS
OS_RESULT rt_sem_delete (OS_ID semaphore) {
/* Delete semaphore */
P_SCB p_SCB = semaphore;
P_TCB p_TCB;
while (p_SCB->p_lnk != NULL) {
/* A task is waiting for token */
p_TCB = rt_get_first ((P_XCB)p_SCB);
rt_ret_val(p_TCB, 0);
rt_rmv_dly(p_TCB);
p_TCB->state = READY;
rt_put_prio (&os_rdy, p_TCB);
}
if (os_rdy.p_lnk && (os_rdy.p_lnk->prio > os_tsk.run->prio)) {
/* preempt running task */
rt_put_prio (&os_rdy, os_tsk.run);
os_tsk.run->state = READY;
rt_dispatch (NULL);
}
p_SCB->cb_type = 0;
return (OS_R_OK);
}
#endif
/*--------------------------- rt_sem_send -----------------------------------*/
OS_RESULT rt_sem_send (OS_ID semaphore) {
/* Return a token to semaphore */
P_SCB p_SCB = semaphore;
P_TCB p_TCB;
if (p_SCB->p_lnk != NULL) {
/* A task is waiting for token */
p_TCB = rt_get_first ((P_XCB)p_SCB);
#ifdef __CMSIS_RTOS
rt_ret_val(p_TCB, 1);
#else
rt_ret_val(p_TCB, OS_R_SEM);
#endif
rt_rmv_dly (p_TCB);
rt_dispatch (p_TCB);
}
else {
/* Store token. */
p_SCB->tokens++;
}
return (OS_R_OK);
}
/*--------------------------- rt_sem_wait -----------------------------------*/
OS_RESULT rt_sem_wait (OS_ID semaphore, U16 timeout) {
/* Obtain a token; possibly wait for it */
P_SCB p_SCB = semaphore;
if (p_SCB->tokens) {
p_SCB->tokens--;
return (OS_R_OK);
}
/* No token available: wait for one */
if (timeout == 0) {
return (OS_R_TMO);
}
if (p_SCB->p_lnk != NULL) {
rt_put_prio ((P_XCB)p_SCB, os_tsk.run);
}
else {
p_SCB->p_lnk = os_tsk.run;
os_tsk.run->p_lnk = NULL;
os_tsk.run->p_rlnk = (P_TCB)p_SCB;
}
rt_block(timeout, WAIT_SEM);
return (OS_R_TMO);
}
/*--------------------------- isr_sem_send ----------------------------------*/
void isr_sem_send (OS_ID semaphore) {
/* Same function as "os_sem"send", but to be called by ISRs */
P_SCB p_SCB = semaphore;
rt_psq_enq (p_SCB, 0);
rt_psh_req ();
}
/*--------------------------- rt_sem_psh ------------------------------------*/
void rt_sem_psh (P_SCB p_CB) {
/* Check if task has to be waken up */
P_TCB p_TCB;
if (p_CB->p_lnk != NULL) {
/* A task is waiting for token */
p_TCB = rt_get_first ((P_XCB)p_CB);
rt_rmv_dly (p_TCB);
p_TCB->state = READY;
#ifdef __CMSIS_RTOS
rt_ret_val(p_TCB, 1);
#else
rt_ret_val(p_TCB, OS_R_SEM);
#endif
rt_put_prio (&os_rdy, p_TCB);
}
else {
/* Store token */
p_CB->tokens++;
}
}
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,46 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_SEMAPHORE.H
* Purpose: Implements binary and counting semaphores
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
/* Functions */
extern void rt_sem_init (OS_ID semaphore, U16 token_count);
extern OS_RESULT rt_sem_delete(OS_ID semaphore);
extern OS_RESULT rt_sem_send (OS_ID semaphore);
extern OS_RESULT rt_sem_wait (OS_ID semaphore, U16 timeout);
extern void isr_sem_send (OS_ID semaphore);
extern void rt_sem_psh (P_SCB p_CB);
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,293 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_SYSTEM.C
* Purpose: System Task Manager
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Conf.h"
#include "rt_Task.h"
#include "rt_System.h"
#include "rt_Event.h"
#include "rt_List.h"
#include "rt_Mailbox.h"
#include "rt_Semaphore.h"
#include "rt_Time.h"
#include "rt_Robin.h"
#include "rt_HAL_CM.h"
/*----------------------------------------------------------------------------
* Global Variables
*---------------------------------------------------------------------------*/
int os_tick_irqn;
/*----------------------------------------------------------------------------
* Local Variables
*---------------------------------------------------------------------------*/
static volatile BIT os_lock;
static volatile BIT os_psh_flag;
static U8 pend_flags;
/*----------------------------------------------------------------------------
* Global Functions
*---------------------------------------------------------------------------*/
#if defined (__CC_ARM)
__asm void $$RTX$$version (void) {
/* Export a version number symbol for a version control. */
EXPORT __RL_RTX_VER
__RL_RTX_VER EQU 0x450
}
#endif
/*--------------------------- rt_suspend ------------------------------------*/
U32 rt_suspend (void) {
/* Suspend OS scheduler */
U32 delta = 0xFFFF;
rt_tsk_lock();
if (os_dly.p_dlnk) {
delta = os_dly.delta_time;
}
#ifndef __CMSIS_RTOS
if (os_tmr.next) {
if (os_tmr.tcnt < delta) delta = os_tmr.tcnt;
}
#endif
return (delta);
}
/*--------------------------- rt_resume -------------------------------------*/
void rt_resume (U32 sleep_time) {
/* Resume OS scheduler after suspend */
P_TCB next;
U32 delta;
os_tsk.run->state = READY;
rt_put_rdy_first (os_tsk.run);
os_robin.task = NULL;
/* Update delays. */
if (os_dly.p_dlnk) {
delta = sleep_time;
if (delta >= os_dly.delta_time) {
delta -= os_dly.delta_time;
os_time += os_dly.delta_time;
os_dly.delta_time = 1;
while (os_dly.p_dlnk) {
rt_dec_dly();
if (delta == 0) break;
delta--;
os_time++;
}
} else {
os_time += delta;
os_dly.delta_time -= delta;
}
} else {
os_time += sleep_time;
}
#ifndef __CMSIS_RTOS
/* Check the user timers. */
if (os_tmr.next) {
delta = sleep_time;
if (delta >= os_tmr.tcnt) {
delta -= os_tmr.tcnt;
os_tmr.tcnt = 1;
while (os_tmr.next) {
rt_tmr_tick();
if (delta == 0) break;
delta--;
}
} else {
os_tmr.tcnt -= delta;
}
}
#endif
/* Switch back to highest ready task */
next = rt_get_first (&os_rdy);
rt_switch_req (next);
rt_tsk_unlock();
}
/*--------------------------- rt_tsk_lock -----------------------------------*/
void rt_tsk_lock (void) {
/* Prevent task switching by locking out scheduler */
OS_X_LOCK(os_tick_irqn);
os_lock = __TRUE;
OS_X_UNPEND (&pend_flags);
}
/*--------------------------- rt_tsk_unlock ---------------------------------*/
void rt_tsk_unlock (void) {
/* Unlock scheduler and re-enable task switching */
OS_X_UNLOCK(os_tick_irqn);
os_lock = __FALSE;
OS_X_PEND (pend_flags, os_psh_flag);
os_psh_flag = __FALSE;
}
/*--------------------------- rt_psh_req ------------------------------------*/
void rt_psh_req (void) {
/* Initiate a post service handling request if required. */
if (os_lock == __FALSE) {
OS_PEND_IRQ ();
}
else {
os_psh_flag = __TRUE;
}
}
/*--------------------------- rt_pop_req ------------------------------------*/
void rt_pop_req (void) {
/* Process an ISR post service requests. */
struct OS_XCB *p_CB;
P_TCB next;
U32 idx;
os_tsk.run->state = READY;
rt_put_rdy_first (os_tsk.run);
idx = os_psq->last;
while (os_psq->count) {
p_CB = os_psq->q[idx].id;
if (p_CB->cb_type == TCB) {
/* Is of TCB type */
rt_evt_psh ((P_TCB)p_CB, (U16)os_psq->q[idx].arg);
}
else if (p_CB->cb_type == MCB) {
/* Is of MCB type */
rt_mbx_psh ((P_MCB)p_CB, (void *)os_psq->q[idx].arg);
}
else {
/* Must be of SCB type */
rt_sem_psh ((P_SCB)p_CB);
}
if (++idx == os_psq->size) idx = 0;
rt_dec (&os_psq->count);
}
os_psq->last = idx;
next = rt_get_first (&os_rdy);
rt_switch_req (next);
}
/*--------------------------- os_tick_init ----------------------------------*/
__weak int os_tick_init (void) {
/* Initialize SysTick timer as system tick timer. */
rt_systick_init ();
return (SYS_TICK_IRQn); /* Return IRQ number of SysTick timer */
}
/*--------------------------- os_tick_irqack --------------------------------*/
__weak void os_tick_irqack (void) {
/* Acknowledge timer interrupt. */
}
/*--------------------------- rt_systick ------------------------------------*/
extern void sysTimerTick(void);
void rt_systick (void) {
if(NVIC_Pending(SYS_TICK_IRQn)){
rt_pop_req();
NVIC_UnpendIRQ(SYS_TICK_IRQn);
SYS_TICK_TIMER->IR = 0xF; // clear timer interrupt
return;
}
/* Check for system clock update, suspend running task. */
P_TCB next;
os_tsk.run->state = READY;
rt_put_rdy_first (os_tsk.run);
/* Check Round Robin timeout. */
rt_chk_robin ();
/* Update delays. */
os_time++;
rt_dec_dly ();
/* Check the user timers. */
#ifdef __CMSIS_RTOS
sysTimerTick();
#else
rt_tmr_tick ();
#endif
/* Switch back to highest ready task */
next = rt_get_first (&os_rdy);
rt_switch_req (next);
SYS_TICK_TIMER->IR = 0xF; // clear timer interrupt
}
/*--------------------------- rt_stk_check ----------------------------------*/
__weak void rt_stk_check (void) {
/* Check for stack overflow. */
if (os_tsk.run->task_id == 0x01) {
// TODO: For the main thread the check should be done against the main heap pointer
} else {
if ((os_tsk.run->tsk_stack < (U32)os_tsk.run->stack) ||
(os_tsk.run->stack[0] != MAGIC_WORD)) {
os_error (OS_ERR_STK_OVF);
}
}
}
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,52 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_SYSTEM.H
* Purpose: System Task Manager definitions
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
/* Variables */
#define os_psq ((P_PSQ)&os_fifo)
extern int os_tick_irqn;
/* Functions */
extern U32 rt_suspend (void);
extern void rt_resume (U32 sleep_time);
extern void rt_tsk_lock (void);
extern void rt_tsk_unlock (void);
extern void rt_psh_req (void);
extern void rt_pop_req (void);
extern void rt_systick (void);
extern void rt_stk_check (void);
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,341 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_TASK.C
* Purpose: Task functions and system start up.
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Conf.h"
#include "rt_System.h"
#include "rt_Task.h"
#include "rt_List.h"
#include "rt_MemBox.h"
#include "rt_Robin.h"
#include "rt_HAL_CM.h"
/*----------------------------------------------------------------------------
* Global Variables
*---------------------------------------------------------------------------*/
/* Running and next task info. */
struct OS_TSK os_tsk;
/* Task Control Blocks of idle demon */
struct OS_TCB os_idle_TCB;
/*----------------------------------------------------------------------------
* Local Functions
*---------------------------------------------------------------------------*/
OS_TID rt_get_TID (void) {
U32 tid;
for (tid = 1; tid <= os_maxtaskrun; tid++) {
if (os_active_TCB[tid-1] == NULL) {
return ((OS_TID)tid);
}
}
return (0);
}
#if defined (__CC_ARM) && !defined (__MICROLIB)
/*--------------------------- __user_perthread_libspace ---------------------*/
extern void *__libspace_start;
void *__user_perthread_libspace (void) {
/* Provide a separate libspace for each task. */
if (os_tsk.run == NULL) {
/* RTX not running yet. */
return (&__libspace_start);
}
return (void *)(os_tsk.run->std_libspace);
}
#endif
/*--------------------------- rt_init_context -------------------------------*/
void rt_init_context (P_TCB p_TCB, U8 priority, FUNCP task_body) {
/* Initialize general part of the Task Control Block. */
p_TCB->cb_type = TCB;
p_TCB->state = READY;
p_TCB->prio = priority;
p_TCB->p_lnk = NULL;
p_TCB->p_rlnk = NULL;
p_TCB->p_dlnk = NULL;
p_TCB->p_blnk = NULL;
p_TCB->delta_time = 0;
p_TCB->interval_time = 0;
p_TCB->events = 0;
p_TCB->waits = 0;
p_TCB->stack_frame = 0;
rt_init_stack (p_TCB, task_body);
}
/*--------------------------- rt_switch_req ---------------------------------*/
void rt_switch_req (P_TCB p_new) {
/* Switch to next task (identified by "p_new"). */
os_tsk.new_tsk = p_new;
p_new->state = RUNNING;
DBG_TASK_SWITCH(p_new->task_id);
}
/*--------------------------- rt_dispatch -----------------------------------*/
void rt_dispatch (P_TCB next_TCB) {
/* Dispatch next task if any identified or dispatch highest ready task */
/* "next_TCB" identifies a task to run or has value NULL (=no next task) */
if (next_TCB == NULL) {
/* Running task was blocked: continue with highest ready task */
next_TCB = rt_get_first (&os_rdy);
rt_switch_req (next_TCB);
}
else {
/* Check which task continues */
if (next_TCB->prio > os_tsk.run->prio) {
/* preempt running task */
rt_put_rdy_first (os_tsk.run);
os_tsk.run->state = READY;
rt_switch_req (next_TCB);
}
else {
/* put next task into ready list, no task switch takes place */
next_TCB->state = READY;
rt_put_prio (&os_rdy, next_TCB);
}
}
}
/*--------------------------- rt_block --------------------------------------*/
void rt_block (U16 timeout, U8 block_state) {
/* Block running task and choose next ready task. */
/* "timeout" sets a time-out value or is 0xffff (=no time-out). */
/* "block_state" defines the appropriate task state */
P_TCB next_TCB;
if (timeout) {
if (timeout < 0xffff) {
rt_put_dly (os_tsk.run, timeout);
}
os_tsk.run->state = block_state;
next_TCB = rt_get_first (&os_rdy);
rt_switch_req (next_TCB);
}
}
/*--------------------------- rt_tsk_pass -----------------------------------*/
void rt_tsk_pass (void) {
/* Allow tasks of same priority level to run cooperatively.*/
P_TCB p_new;
p_new = rt_get_same_rdy_prio();
if (p_new != NULL) {
rt_put_prio ((P_XCB)&os_rdy, os_tsk.run);
os_tsk.run->state = READY;
rt_switch_req (p_new);
}
}
/*--------------------------- rt_tsk_self -----------------------------------*/
OS_TID rt_tsk_self (void) {
/* Return own task identifier value. */
if (os_tsk.run == NULL) {
return (0);
}
return (os_tsk.run->task_id);
}
/*--------------------------- rt_tsk_prio -----------------------------------*/
OS_RESULT rt_tsk_prio (OS_TID task_id, U8 new_prio) {
/* Change execution priority of a task to "new_prio". */
P_TCB p_task;
if (task_id == 0) {
/* Change execution priority of calling task. */
os_tsk.run->prio = new_prio;
run:if (rt_rdy_prio() > new_prio) {
rt_put_prio (&os_rdy, os_tsk.run);
os_tsk.run->state = READY;
rt_dispatch (NULL);
}
return (OS_R_OK);
}
/* Find the task in the "os_active_TCB" array. */
if (task_id > os_maxtaskrun || os_active_TCB[task_id-1] == NULL) {
/* Task with "task_id" not found or not started. */
return (OS_R_NOK);
}
p_task = os_active_TCB[task_id-1];
p_task->prio = new_prio;
if (p_task == os_tsk.run) {
goto run;
}
rt_resort_prio (p_task);
if (p_task->state == READY) {
/* Task enqueued in a ready list. */
p_task = rt_get_first (&os_rdy);
rt_dispatch (p_task);
}
return (OS_R_OK);
}
/*--------------------------- rt_tsk_delete ---------------------------------*/
OS_RESULT rt_tsk_delete (OS_TID task_id) {
/* Terminate the task identified with "task_id". */
P_TCB task_context;
if (task_id == 0 || task_id == os_tsk.run->task_id) {
/* Terminate itself. */
os_tsk.run->state = INACTIVE;
os_tsk.run->tsk_stack = 0;
rt_stk_check ();
os_active_TCB[os_tsk.run->task_id-1] = NULL;
os_tsk.run->stack = NULL;
DBG_TASK_NOTIFY(os_tsk.run, __FALSE);
os_tsk.run = NULL;
rt_dispatch (NULL);
/* The program should never come to this point. */
}
else {
/* Find the task in the "os_active_TCB" array. */
if (task_id > os_maxtaskrun || os_active_TCB[task_id-1] == NULL) {
/* Task with "task_id" not found or not started. */
return (OS_R_NOK);
}
task_context = os_active_TCB[task_id-1];
rt_rmv_list (task_context);
rt_rmv_dly (task_context);
os_active_TCB[task_id-1] = NULL;
task_context->stack = NULL;
DBG_TASK_NOTIFY(task_context, __FALSE);
}
return (OS_R_OK);
}
/*--------------------------- rt_sys_init -----------------------------------*/
#ifdef __CMSIS_RTOS
void rt_sys_init (void) {
#else
void rt_sys_init (FUNCP first_task, U32 prio_stksz, void *stk) {
#endif
/* Initialize system and start up task declared with "first_task". */
U32 i;
DBG_INIT();
/* Initialize dynamic memory and task TCB pointers to NULL. */
for (i = 0; i < os_maxtaskrun; i++) {
os_active_TCB[i] = NULL;
}
/* Set up TCB of idle demon */
os_idle_TCB.task_id = 255;
os_idle_TCB.priv_stack = idle_task_stack_size;
os_idle_TCB.stack = idle_task_stack;
rt_init_context (&os_idle_TCB, 0, os_idle_demon);
/* Set up ready list: initially empty */
os_rdy.cb_type = HCB;
os_rdy.p_lnk = NULL;
/* Set up delay list: initially empty */
os_dly.cb_type = HCB;
os_dly.p_dlnk = NULL;
os_dly.p_blnk = NULL;
os_dly.delta_time = 0;
/* Fix SP and systemvariables to assume idle task is running */
/* Transform main program into idle task by assuming idle TCB */
#ifndef __CMSIS_RTOS
rt_set_PSP (os_idle_TCB.tsk_stack);
#endif
os_tsk.run = &os_idle_TCB;
os_tsk.run->state = RUNNING;
/* Initialize ps queue */
os_psq->first = 0;
os_psq->last = 0;
os_psq->size = os_fifo_size;
rt_init_robin ();
/* Intitialize SVC and PendSV */
rt_svc_init ();
#ifndef __CMSIS_RTOS
/* Intitialize and start system clock timer */
os_tick_irqn = os_tick_init ();
if (os_tick_irqn >= 0) {
OS_X_INIT(os_tick_irqn);
}
/* Start up first user task before entering the endless loop */
rt_tsk_create (first_task, prio_stksz, stk, NULL);
#endif
}
/*--------------------------- rt_sys_start ----------------------------------*/
#ifdef __CMSIS_RTOS
void rt_sys_start (void) {
/* Start system */
/* Intitialize and start system clock timer */
os_tick_irqn = os_tick_init ();
if (os_tick_irqn >= 0) {
OS_X_INIT(os_tick_irqn);
}
extern void RestoreContext();
RestoreContext(); // Start the first task
}
#endif
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,73 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_TASK.H
* Purpose: Task functions and system start up.
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
/* Definitions */
#define __CMSIS_RTOS 1
/* Values for 'state' */
#define INACTIVE 0
#define READY 1
#define RUNNING 2
#define WAIT_DLY 3
#define WAIT_ITV 4
#define WAIT_OR 5
#define WAIT_AND 6
#define WAIT_SEM 7
#define WAIT_MBX 8
#define WAIT_MUT 9
/* Return codes */
#define OS_R_TMO 0x01
#define OS_R_EVT 0x02
#define OS_R_SEM 0x03
#define OS_R_MBX 0x04
#define OS_R_MUT 0x05
#define OS_R_OK 0x00
#define OS_R_NOK 0xff
/* Variables */
extern struct OS_TSK os_tsk;
extern struct OS_TCB os_idle_TCB;
/* Functions */
extern void rt_switch_req (P_TCB p_new);
extern void rt_dispatch (P_TCB next_TCB);
extern void rt_block (U16 timeout, U8 block_state);
extern void rt_tsk_pass (void);
extern OS_TID rt_tsk_self (void);
extern OS_RESULT rt_tsk_prio (OS_TID task_id, U8 new_prio);
extern OS_RESULT rt_tsk_delete (OS_TID task_id);
extern void rt_sys_init (void);
extern void rt_sys_start (void);

View File

@ -0,0 +1,94 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_TIME.C
* Purpose: Delay and interval wait functions
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
#include "rt_TypeDef.h"
#include "RTX_Conf.h"
#include "rt_Task.h"
#include "rt_Time.h"
/*----------------------------------------------------------------------------
* Global Variables
*---------------------------------------------------------------------------*/
/* Free running system tick counter */
U32 os_time;
/*----------------------------------------------------------------------------
* Functions
*---------------------------------------------------------------------------*/
/*--------------------------- rt_time_get -----------------------------------*/
U32 rt_time_get (void) {
/* Get system time tick */
return (os_time);
}
/*--------------------------- rt_dly_wait -----------------------------------*/
void rt_dly_wait (U16 delay_time) {
/* Delay task by "delay_time" */
rt_block (delay_time, WAIT_DLY);
}
/*--------------------------- rt_itv_set ------------------------------------*/
void rt_itv_set (U16 interval_time) {
/* Set interval length and define start of first interval */
os_tsk.run->interval_time = interval_time;
os_tsk.run->delta_time = interval_time + (U16)os_time;
}
/*--------------------------- rt_itv_wait -----------------------------------*/
void rt_itv_wait (void) {
/* Wait for interval end and define start of next one */
U16 delta;
delta = os_tsk.run->delta_time - (U16)os_time;
os_tsk.run->delta_time += os_tsk.run->interval_time;
if ((delta & 0x8000) == 0) {
rt_block (delta, WAIT_ITV);
}
}
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,47 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_TIME.H
* Purpose: Delay and interval wait functions definitions
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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.
*---------------------------------------------------------------------------*/
/* Variables */
extern U32 os_time;
/* Functions */
extern U32 rt_time_get (void);
extern void rt_dly_wait (U16 delay_time);
extern void rt_itv_set (U16 interval_time);
extern void rt_itv_wait (void);
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,128 @@
/*----------------------------------------------------------------------------
* RL-ARM - RTX
*----------------------------------------------------------------------------
* Name: RT_TYPEDEF.H
* Purpose: Type Definitions
* Rev.: V4.60
*----------------------------------------------------------------------------
*
* Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
* 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 RT_TYPE_DEF_H
#define RT_TYPE_DEF_H
#include "os_tcb.h"
typedef U32 OS_TID;
typedef void *OS_ID;
typedef U32 OS_RESULT;
#define TCB_STACKF 32 /* 'stack_frame' offset */
#define TCB_TSTACK 40 /* 'tsk_stack' offset */
typedef struct OS_PSFE { /* Post Service Fifo Entry */
void *id; /* Object Identification */
U32 arg; /* Object Argument */
} *P_PSFE;
typedef struct OS_PSQ { /* Post Service Queue */
U8 first; /* FIFO Head Index */
U8 last; /* FIFO Tail Index */
U8 count; /* Number of stored items in FIFO */
U8 size; /* FIFO Size */
struct OS_PSFE q[1]; /* FIFO Content */
} *P_PSQ;
typedef struct OS_TSK {
P_TCB run; /* Current running task */
P_TCB new_tsk; /* Scheduled task to run */
} *P_TSK;
typedef struct OS_ROBIN { /* Round Robin Control */
P_TCB task; /* Round Robin task */
U16 time; /* Round Robin switch time */
U16 tout; /* Round Robin timeout */
} *P_ROBIN;
typedef struct OS_XCB {
U8 cb_type; /* Control Block Type */
struct OS_TCB *p_lnk; /* Link pointer for ready/sem. wait list */
struct OS_TCB *p_rlnk; /* Link pointer for sem./mbx lst backwards */
struct OS_TCB *p_dlnk; /* Link pointer for delay list */
struct OS_TCB *p_blnk; /* Link pointer for delay list backwards */
U16 delta_time; /* Time until time out */
} *P_XCB;
typedef struct OS_MCB {
U8 cb_type; /* Control Block Type */
U8 state; /* State flag variable */
U8 isr_st; /* State flag variable for isr functions */
struct OS_TCB *p_lnk; /* Chain of tasks waiting for message */
U16 first; /* Index of the message list begin */
U16 last; /* Index of the message list end */
U16 count; /* Actual number of stored messages */
U16 size; /* Maximum number of stored messages */
void *msg[1]; /* FIFO for Message pointers 1st element */
} *P_MCB;
typedef struct OS_SCB {
U8 cb_type; /* Control Block Type */
U8 mask; /* Semaphore token mask */
U16 tokens; /* Semaphore tokens */
struct OS_TCB *p_lnk; /* Chain of tasks waiting for tokens */
} *P_SCB;
typedef struct OS_MUCB {
U8 cb_type; /* Control Block Type */
U8 prio; /* Owner task default priority */
U16 level; /* Call nesting level */
struct OS_TCB *p_lnk; /* Chain of tasks waiting for mutex */
struct OS_TCB *owner; /* Mutex owner task */
} *P_MUCB;
typedef struct OS_XTMR {
struct OS_TMR *next;
U16 tcnt;
} *P_XTMR;
typedef struct OS_TMR {
struct OS_TMR *next; /* Link pointer to Next timer */
U16 tcnt; /* Timer delay count */
U16 info; /* User defined call info */
} *P_TMR;
typedef struct OS_BM {
void *free; /* Pointer to first free memory block */
void *end; /* Pointer to memory block end */
U32 blk_size; /* Memory block size */
} *P_BM;
/* Definitions */
#define __TRUE 1
#define __FALSE 0
#define NULL ((void *) 0)
#endif

View File

@ -9,7 +9,7 @@
#define TIMER_IRQ TIMER_32_1_IRQn
#elif defined(TARGET_KL25Z)
#define TIMER_IRQ LPTimer_IRQn
#elif defined(TARGET_LPC2368)
#elif defined(TARGET_LPC2368) || defined(TARGET_LPC2460)
#define TIMER_IRQ TIMER3_IRQn
#else
#error This test can't run on this target.
@ -40,7 +40,7 @@ Ticker flipper_2;
Sender s1(pc, '1');
Sender s2(pc, '2');
#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC4088) || defined(TARGET_LPC2368) || defined(TARGET_LPC1114)
#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC4088) || defined(TARGET_LPC2368) || defined(TARGET_LPC1114) || defined(TARGET_LPC2460)
# define LED_NAME LED2
#elif defined(TARGET_KL05Z)
# define LED_NAME LED2

View File

@ -1,6 +1,6 @@
#include "mbed.h"
# if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC4088)
# if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC4088) || defined(TARGET_LPC2460)
# define LED_PORT Port1
# define LED1 (1 << 18) // P1.18
# define LED2 (1 << 20) // P1.20

View File

@ -28,7 +28,7 @@ int main() {
notify_completion(result == value ? true : false);
#elif defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24) || defined(TARGET_LPC4088)
#elif defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24) || defined(TARGET_LPC4088) || defined(TARGET_LPC2460)
PwmOut pwm_p25(p25);
PwmOut pwm_p26(p26);

View File

@ -1,3 +1,4 @@
#! /usr/bin/env python
"""
mbed SDK
Copyright (c) 2011-2013 ARM Limited
@ -33,6 +34,7 @@ OFFICIAL_MBED_LIBRARY_BUILD = (
('UBLOX_C027', ('ARM', 'GCC_ARM', 'GCC_CR', 'GCC_CS', 'IAR')),
('ARCH_PRO', ('ARM', 'GCC_ARM', 'GCC_CR', 'GCC_CS', 'IAR')),
('LPC2368', ('ARM', 'GCC_ARM')),
('LPC2460', ('GCC_ARM')),
('LPC812', ('uARM','IAR')),
('LPC824', ('uARM', 'GCC_ARM', 'IAR', 'GCC_CR')),
('SSCI824', ('uARM','GCC_ARM')),

View File

@ -29,6 +29,7 @@ import sys
build_list = (
{ "target": "LPC1768", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "eth", "usb_host", "usb", "ublox", "fat"] },
{ "target": "LPC2368", "toolchains": "GCC_ARM", "libs": ["fat"] },
{ "target": "LPC2460", "toolchains": "GCC_ARM", "libs": ["rtos", "usb_host", "usb", "fat"] },
{ "target": "LPC11U24", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
{ "target": "OC_MBUINO", "toolchains": "GCC_ARM", "libs": ["fat"] },

View File

@ -0,0 +1,72 @@
# This file was automagically generated by mbed.org. For more information,
# see http://mbed.org/handbook/Exporting-to-GCC-ARM-Embedded
GCC_BIN =
PROJECT = {{name}}
OBJECTS = {% for f in to_be_compiled %}{{f}} {% endfor %}
SYS_OBJECTS = {% for f in object_files %}{{f}} {% endfor %}
INCLUDE_PATHS = {% for p in include_paths %}-I{{p}} {% endfor %}
LIBRARY_PATHS = {% for p in library_paths %}-L{{p}} {% endfor %}
LIBRARIES = {% for lib in libraries %}-l{{lib}} {% endfor %}
LINKER_SCRIPT = {{linker_script}}
###############################################################################
AS = $(GCC_BIN)arm-none-eabi-as
CC = $(GCC_BIN)arm-none-eabi-gcc
CPP = $(GCC_BIN)arm-none-eabi-g++
LD = $(GCC_BIN)arm-none-eabi-gcc
OBJCOPY = $(GCC_BIN)arm-none-eabi-objcopy
OBJDUMP = $(GCC_BIN)arm-none-eabi-objdump
SIZE = $(GCC_BIN)arm-none-eabi-size
CPU = -mcpu=arm7tdmi-s
CC_FLAGS = $(CPU) -c -g -fno-common -fmessage-length=0 -Wall -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer
CC_FLAGS += -MMD -MP
CC_SYMBOLS = {% for s in symbols %}-D{{s}} {% endfor %}
LD_FLAGS = $(CPU) -Wl,--gc-sections --specs=nano.specs -u _printf_float -u _scanf_float -Wl,--wrap,main
LD_FLAGS += -Wl,-Map=$(PROJECT).map,--cref -Wl,--entry=_start
LD_SYS_LIBS = -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys
ifeq ($(DEBUG), 1)
CC_FLAGS += -DDEBUG -O0
else
CC_FLAGS += -DNDEBUG -Os
endif
all: $(PROJECT).bin $(PROJECT).hex
clean:
rm -f $(PROJECT).bin $(PROJECT).elf $(PROJECT).hex $(PROJECT).map $(PROJECT).lst $(OBJECTS) $(DEPS)
.s.o:
$(AS) $(CPU) -o $@ $<
.c.o:
$(CC) $(CC_FLAGS) $(CC_SYMBOLS) -std=gnu99 $(INCLUDE_PATHS) -o $@ $<
.cpp.o:
$(CPP) $(CC_FLAGS) $(CC_SYMBOLS) -std=gnu++98 -fno-rtti $(INCLUDE_PATHS) -o $@ $<
$(PROJECT).elf: $(OBJECTS) $(SYS_OBJECTS)
$(LD) $(LD_FLAGS) -T$(LINKER_SCRIPT) $(LIBRARY_PATHS) -o $@ $^ $(LIBRARIES) $(LD_SYS_LIBS) $(LIBRARIES) $(LD_SYS_LIBS)
$(SIZE) $@
$(PROJECT).bin: $(PROJECT).elf
@$(OBJCOPY) -O binary $< $@
$(PROJECT).hex: $(PROJECT).elf
@$(OBJCOPY) -O ihex $< $@
$(PROJECT).lst: $(PROJECT).elf
@$(OBJDUMP) -Sdh $< > $@
lst: $(PROJECT).lst
size:
$(SIZE) $(PROJECT).elf
DEPS = $(OBJECTS:.o=.d) $(SYS_OBJECTS:.o=.d)
-include $(DEPS)

View File

@ -53,6 +53,7 @@ class GccArm(Exporter):
'HRM1017',
'RBLAB_NRF51822',
'LPC2368',
'LPC2460',
'LPCCAPPUCCINO',
'ARCH_BLE',
'MTS_GAMBIT',

View File

@ -1,3 +1,4 @@
#!/usr/bin/env python
"""
mbed SDK
Copyright (c) 2011-2013 ARM Limited
@ -159,6 +160,7 @@ if __name__ == '__main__':
('gcc_arm', 'LPC11U35_501'),
('gcc_arm', 'LPCCAPPUCCINO'),
('gcc_arm', 'LPC2368'),
('gcc_arm', 'LPC2460'),
('gcc_arm', 'LPC824'),
('gcc_arm', 'SSCI824'),

View File

@ -254,6 +254,13 @@ class LPC2368(LPCTarget):
self.extra_labels = ['NXP', 'LPC23XX']
self.supported_toolchains = ["ARM", "GCC_ARM", "GCC_CR"]
class LPC2460(LPCTarget):
def __init__(self):
LPCTarget.__init__(self)
self.core = "ARM7TDMI-S"
self.extra_labels = ['NXP', 'LPC2460']
self.supported_toolchains = ["GCC_ARM"]
class LPC810(LPCTarget):
def __init__(self):
LPCTarget.__init__(self)
@ -1241,6 +1248,7 @@ TARGETS = [
UBLOX_C027(), # LPC1768
XBED_LPC1768(), # LPC1768
LPC2368(),
LPC2460(),
LPC810(),
LPC812(),
LPC824(),

View File

@ -143,7 +143,7 @@ TESTS = [
"dependencies": [MBED_LIBRARIES, TEST_MBED_LIB],
"automated": True,
"peripherals": ["analog_loop"],
"mcu": ["LPC1768", "LPC2368", "KL25Z", "K64F", "K22F", "LPC4088", "LPC1549",
"mcu": ["LPC1768", "LPC2368", "LPC2460", "KL25Z", "K64F", "K22F", "LPC4088", "LPC1549",
"NUCLEO_F072RB", "NUCLEO_F091RC", "NUCLEO_F302R8", "NUCLEO_F303RE",
"NUCLEO_F334R8", "NUCLEO_L053R8", "NUCLEO_L073RZ", "NUCLEO_L152RE",
"NUCLEO_F411RE", "DISCO_F407VG", "ARCH_MAX", "MAX32600MBED"]
@ -635,7 +635,7 @@ TESTS = [
"duration": 15,
"automated": True,
#"host_test": "wait_us_auto",
"mcu": ["LPC1768", "LPC1549", "LPC11U24", "LPC812",
"mcu": ["LPC1768", "LPC1549", "LPC11U24", "LPC812", "LPC2460",
"KL25Z", "KL05Z", "K64F", "KL46Z",
"RZ_A1H", "DISCO_F407VG", "DISCO_F429ZI", "NUCLEO_F411RE",
"NUCLEO_F401RE", "NUCLEO_F334R8", "DISCO_F334C8", "NUCLEO_F302R8",
@ -648,7 +648,7 @@ TESTS = [
"dependencies": [MBED_LIBRARIES, RTOS_LIBRARIES, TEST_MBED_LIB],
"duration": 20,
"automated": True,
"mcu": ["LPC1768", "LPC1549", "LPC11U24", "LPC812",
"mcu": ["LPC1768", "LPC1549", "LPC11U24", "LPC812", "LPC2460",
"KL25Z", "KL05Z", "K64F", "KL46Z",
"RZ_A1H", "DISCO_F407VG", "DISCO_F429ZI", "NUCLEO_F411RE",
"NUCLEO_F401RE", "NUCLEO_F334R8", "DISCO_F334C8", "NUCLEO_F302R8",
@ -661,7 +661,7 @@ TESTS = [
"dependencies": [MBED_LIBRARIES, RTOS_LIBRARIES, TEST_MBED_LIB],
"duration": 20,
"automated": True,
"mcu": ["LPC1768", "LPC1549", "LPC11U24", "LPC812",
"mcu": ["LPC1768", "LPC1549", "LPC11U24", "LPC812", "LPC2460",
"KL25Z", "KL05Z", "K64F", "KL46Z",
"RZ_A1H", "DISCO_F407VG", "DISCO_F429ZI", "NUCLEO_F411RE",
"NUCLEO_F401RE", "NUCLEO_F334R8", "DISCO_F334C8", "NUCLEO_F302R8",
@ -673,7 +673,7 @@ TESTS = [
"source_dir": join(TEST_DIR, "rtos", "mbed", "signals"),
"dependencies": [MBED_LIBRARIES, RTOS_LIBRARIES, TEST_MBED_LIB],
"automated": True,
"mcu": ["LPC1768", "LPC1549", "LPC11U24", "LPC812",
"mcu": ["LPC1768", "LPC1549", "LPC11U24", "LPC812", "LPC2460",
"KL25Z", "KL05Z", "K64F", "KL46Z",
"RZ_A1H", "DISCO_F407VG", "DISCO_F429ZI", "NUCLEO_F411RE",
"NUCLEO_F401RE", "NUCLEO_F334R8", "DISCO_F334C8", "NUCLEO_F302R8",
@ -685,7 +685,7 @@ TESTS = [
"source_dir": join(TEST_DIR, "rtos", "mbed", "queue"),
"dependencies": [MBED_LIBRARIES, RTOS_LIBRARIES, TEST_MBED_LIB],
"automated": True,
"mcu": ["LPC1768", "LPC1549", "LPC11U24", "LPC812",
"mcu": ["LPC1768", "LPC1549", "LPC11U24", "LPC812", "LPC2460",
"KL25Z", "KL05Z", "K64F", "KL46Z",
"RZ_A1H", "DISCO_F407VG", "DISCO_F429ZI", "NUCLEO_F411RE",
"NUCLEO_F401RE", "NUCLEO_F334R8", "DISCO_F334C8", "NUCLEO_F302R8",
@ -697,7 +697,7 @@ TESTS = [
"source_dir": join(TEST_DIR, "rtos", "mbed", "mail"),
"dependencies": [MBED_LIBRARIES, RTOS_LIBRARIES, TEST_MBED_LIB],
"automated": True,
"mcu": ["LPC1768", "LPC1549", "LPC11U24", "LPC812",
"mcu": ["LPC1768", "LPC1549", "LPC11U24", "LPC812", "LPC2460",
"KL25Z", "KL05Z", "K64F", "KL46Z",
"RZ_A1H", "DISCO_F407VG", "DISCO_F429ZI", "NUCLEO_F411RE",
"NUCLEO_F401RE", "NUCLEO_F334R8", "DISCO_F334C8", "NUCLEO_F302R8",
@ -711,7 +711,7 @@ TESTS = [
"duration": 15,
"automated": True,
#"host_test": "wait_us_auto",
"mcu": ["LPC1768", "LPC1549", "LPC11U24", "LPC812",
"mcu": ["LPC1768", "LPC1549", "LPC11U24", "LPC812", "LPC2460",
"KL25Z", "KL05Z", "K64F", "KL46Z",
"RZ_A1H", "DISCO_F407VG", "DISCO_F429ZI", "NUCLEO_F411RE",
"NUCLEO_F401RE", "NUCLEO_F334R8", "DISCO_F334C8", "NUCLEO_F302R8",
@ -723,7 +723,7 @@ TESTS = [
"source_dir": join(TEST_DIR, "rtos", "mbed", "isr"),
"dependencies": [MBED_LIBRARIES, RTOS_LIBRARIES, TEST_MBED_LIB],
"automated": True,
"mcu": ["LPC1768", "LPC1549", "LPC11U24", "LPC812",
"mcu": ["LPC1768", "LPC1549", "LPC11U24", "LPC812", "LPC2460",
"KL25Z", "KL05Z", "K64F", "KL46Z",
"RZ_A1H", "DISCO_F407VG", "DISCO_F429ZI", "NUCLEO_F411RE",
"NUCLEO_F401RE", "NUCLEO_F334R8", "DISCO_F334C8", "NUCLEO_F302R8",