1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #318 from OlegHahm/lpc1768

initial support for the mbed NXP LPC168
This commit is contained in:
Oleg Hahm 2013-12-19 09:03:22 -08:00
commit 1cc2767bb4
24 changed files with 5733 additions and 0 deletions

View File

@ -31,3 +31,6 @@ endif
ifeq ($(BOARD),native)
INCLUDES += -I$(RIOTBOARD)/native/include/
endif
ifeq ($(BOARD),mbed_lpc1768)
INCLUDES += -I$(RIOTBOARD)/mbed_lpc1768/include/
endif

View File

@ -0,0 +1,28 @@
SRC = $(wildcard *.c)
BINDIR = $(RIOTBOARD)/$(BOARD)/bin/
OBJ = $(SRC:%.c=$(BINDIR)%.o)## defines
DEP = $(SRC:%.c=$(BINDIR)%.d)
export ARCH = mbed_lpc1768_base.a
INCLUDES += -Iinclude/
INCLUDES += -I$(RIOTCPU)/$(CPU)/include
INCLUDES += -I$(RIOTBASE)/core/include
all: $(BINDIR)$(ARCH)
$(BINDIR)$(ARCH): $(OBJ)
$(AR) rcs $(BINDIR)$(ARCH) $(OBJ)
# pull in dependency info for *existing* .o files
-include $(OBJ:.o=.d)
# compile and generate dependency info
$(BINDIR)%.o: %.c
mkdir -p $(BINDIR)
$(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -c $*.c -o $(BINDIR)$*.o
$(CC) $(CFLAGS) $(INCLUDES) $(BOARDINCLUDE) $(PROJECTINCLUDE) $(CPUINCLUDE) -MM $*.c > $(BINDIR)$*.d
@printf "$(BINDIR)"|cat - $(BINDIR)$*.d > /tmp/riot_out && mv /tmp/riot_out $(BINDIR)$*.d
# remove compilation products
clean:
rm -f $(OBJ) $(DEP)

View File

@ -0,0 +1,28 @@
## the cpu to build for
export CPU = lpc1768
# toolchain config
export PREFIX = arm-none-eabi-
export CC = @$(PREFIX)gcc
export AR = @$(PREFIX)ar
export CFLAGS = -DUSE_STDPERIPH_DRIVER -ggdb -g3 -std=gnu99 -O0 -Wall -Wstrict-prototypes -mcpu=cortex-m3 $(FPU_USAGE) -mlittle-endian -mthumb -mthumb-interwork -nostartfiles
export ASFLAGS = -ggdb -g3 -mcpu=cortex-m3 $(FPU_USAGE) -mlittle-endian
export AS = $(PREFIX)as
export LINK = $(PREFIX)gcc
export SIZE = $(PREFIX)size
export OBJCOPY = $(PREFIX)objcopy
#LINKFLAGS = -g3 -ggdb -mcpu=cortex-m3 $(FPU_USAGE) -mlittle-endian -static -lgcc -mthumb -mthumb-interwork -nostartfiles -T$(RIOTCPU)/$(CPU)/LPC1768.ld
LINKFLAGS = -mcpu=cortex-m3 -mthumb -Wl,--gc-sections,--cref -lc -lgcc -lnosys -T$(RIOTCPU)/$(CPU)/LPC1768.ld -nostartfiles
ifeq ($(strip $(PORT)),)
export PORT = /dev/ttyUSB0
endif
export HEXFILE = bin/$(PROJECT).hex
export FFLAGS = $(HEXFILE)
export ELFFILE = bin/$(PROJECT).elf
export DEBUGGER_FLAGS = $(ELFFILE)
INCLUDES += -Iinclude/
INCLUDES += -I$(RIOTCPU)/$(CPU)/include
export OFLAGS = -O binary

View File

@ -0,0 +1,569 @@
/**************************************************************************//**
* @file boards_init.c
* @brief CMSIS Cortex-M3 Device Peripheral Access Layer Source File
* for the NXP LPC17xx Device Series
* @version V1.09
* @date 09. November 2013
*
* @note Integrated, adopted, and renamed for RIOT by Oliver Hahm.
*
* Copyright (C) 2009 ARM Limited. All rights reserved.
* Copyright (C) 2013 Oliver Hahm <oliver.hahm@inria.fr>
*
* @par
* ARM Limited (ARM) is supplying this software for use with Cortex-M
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* @par
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/
#include <stdint.h>
#include "board.h"
#include "LPC17xx.h"
/*--------------------- Clock Configuration ----------------------------------
//
// <e> Clock Configuration
// <h> System Controls and Status Register (SCS)
// <o1.4> OSCRANGE: Main Oscillator Range Select
// <0=> 1 MHz to 20 MHz
// <1=> 15 MHz to 24 MHz
// <e1.5> OSCEN: Main Oscillator Enable
// </e>
// </h>
//
// <h> Clock Source Select Register (CLKSRCSEL)
// <o2.0..1> CLKSRC: PLL Clock Source Selection
// <0=> Internal RC oscillator
// <1=> Main oscillator
// <2=> RTC oscillator
// </h>
//
// <e3> PLL0 Configuration (Main PLL)
// <h> PLL0 Configuration Register (PLL0CFG)
// <i> F_cco0 = (2 * M * F_in) / N
// <i> F_in must be in the range of 32 kHz to 50 MHz
// <i> F_cco0 must be in the range of 275 MHz to 550 MHz
// <o4.0..14> MSEL: PLL Multiplier Selection
// <6-32768><#-1>
// <i> M Value
// <o4.16..23> NSEL: PLL Divider Selection
// <1-256><#-1>
// <i> N Value
// </h>
// </e>
//
// <e5> PLL1 Configuration (USB PLL)
// <h> PLL1 Configuration Register (PLL1CFG)
// <i> F_usb = M * F_osc or F_usb = F_cco1 / (2 * P)
// <i> F_cco1 = F_osc * M * 2 * P
// <i> F_cco1 must be in the range of 156 MHz to 320 MHz
// <o6.0..4> MSEL: PLL Multiplier Selection
// <1-32><#-1>
// <i> M Value (for USB maximum value is 4)
// <o6.5..6> PSEL: PLL Divider Selection
// <0=> 1
// <1=> 2
// <2=> 4
// <3=> 8
// <i> P Value
// </h>
// </e>
//
// <h> CPU Clock Configuration Register (CCLKCFG)
// <o7.0..7> CCLKSEL: Divide Value for CPU Clock from PLL0
// <1-256><#-1>
// </h>
//
// <h> USB Clock Configuration Register (USBCLKCFG)
// <o8.0..3> USBSEL: Divide Value for USB Clock from PLL0
// <0-15>
// <i> Divide is USBSEL + 1
// </h>
//
// <h> Peripheral Clock Selection Register 0 (PCLKSEL0)
// <o9.0..1> PCLK_WDT: Peripheral Clock Selection for WDT
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.2..3> PCLK_TIMER0: Peripheral Clock Selection for TIMER0
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.4..5> PCLK_TIMER1: Peripheral Clock Selection for TIMER1
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.6..7> PCLK_UART0: Peripheral Clock Selection for UART0
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.8..9> PCLK_UART1: Peripheral Clock Selection for UART1
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.12..13> PCLK_PWM1: Peripheral Clock Selection for PWM1
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.14..15> PCLK_I2C0: Peripheral Clock Selection for I2C0
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.16..17> PCLK_SPI: Peripheral Clock Selection for SPI
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.20..21> PCLK_SSP1: Peripheral Clock Selection for SSP1
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.22..23> PCLK_DAC: Peripheral Clock Selection for DAC
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.24..25> PCLK_ADC: Peripheral Clock Selection for ADC
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o9.26..27> PCLK_CAN1: Peripheral Clock Selection for CAN1
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 6
// <o9.28..29> PCLK_CAN2: Peripheral Clock Selection for CAN2
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 6
// <o9.30..31> PCLK_ACF: Peripheral Clock Selection for ACF
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 6
// </h>
//
// <h> Peripheral Clock Selection Register 1 (PCLKSEL1)
// <o10.0..1> PCLK_QEI: Peripheral Clock Selection for the Quadrature Encoder Interface
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.2..3> PCLK_GPIO: Peripheral Clock Selection for GPIOs
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.4..5> PCLK_PCB: Peripheral Clock Selection for the Pin Connect Block
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.6..7> PCLK_I2C1: Peripheral Clock Selection for I2C1
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.10..11> PCLK_SSP0: Peripheral Clock Selection for SSP0
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.12..13> PCLK_TIMER2: Peripheral Clock Selection for TIMER2
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.14..15> PCLK_TIMER3: Peripheral Clock Selection for TIMER3
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.16..17> PCLK_UART2: Peripheral Clock Selection for UART2
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.18..19> PCLK_UART3: Peripheral Clock Selection for UART3
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.20..21> PCLK_I2C2: Peripheral Clock Selection for I2C2
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.22..23> PCLK_I2S: Peripheral Clock Selection for I2S
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.26..27> PCLK_RIT: Peripheral Clock Selection for the Repetitive Interrupt Timer
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.28..29> PCLK_SYSCON: Peripheral Clock Selection for the System Control Block
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// <o10.30..31> PCLK_MC: Peripheral Clock Selection for the Motor Control PWM
// <0=> Pclk = Cclk / 4
// <1=> Pclk = Cclk
// <2=> Pclk = Cclk / 2
// <3=> Pclk = Hclk / 8
// </h>
//
// <h> Power Control for Peripherals Register (PCONP)
// <o11.1> PCTIM0: Timer/Counter 0 power/clock enable
// <o11.2> PCTIM1: Timer/Counter 1 power/clock enable
// <o11.3> PCUART0: UART 0 power/clock enable
// <o11.4> PCUART1: UART 1 power/clock enable
// <o11.6> PCPWM1: PWM 1 power/clock enable
// <o11.7> PCI2C0: I2C interface 0 power/clock enable
// <o11.8> PCSPI: SPI interface power/clock enable
// <o11.9> PCRTC: RTC power/clock enable
// <o11.10> PCSSP1: SSP interface 1 power/clock enable
// <o11.12> PCAD: A/D converter power/clock enable
// <o11.13> PCCAN1: CAN controller 1 power/clock enable
// <o11.14> PCCAN2: CAN controller 2 power/clock enable
// <o11.15> PCGPIO: GPIOs power/clock enable
// <o11.16> PCRIT: Repetitive interrupt timer power/clock enable
// <o11.17> PCMC: Motor control PWM power/clock enable
// <o11.18> PCQEI: Quadrature encoder interface power/clock enable
// <o11.19> PCI2C1: I2C interface 1 power/clock enable
// <o11.21> PCSSP0: SSP interface 0 power/clock enable
// <o11.22> PCTIM2: Timer 2 power/clock enable
// <o11.23> PCTIM3: Timer 3 power/clock enable
// <o11.24> PCUART2: UART 2 power/clock enable
// <o11.25> PCUART3: UART 3 power/clock enable
// <o11.26> PCI2C2: I2C interface 2 power/clock enable
// <o11.27> PCI2S: I2S interface power/clock enable
// <o11.29> PCGPDMA: GP DMA function power/clock enable
// <o11.30> PCENET: Ethernet block power/clock enable
// <o11.31> PCUSB: USB interface power/clock enable
// </h>
//
// <h> Clock Output Configuration Register (CLKOUTCFG)
// <o12.0..3> CLKOUTSEL: Selects clock source for CLKOUT
// <0=> CPU clock
// <1=> Main oscillator
// <2=> Internal RC oscillator
// <3=> USB clock
// <4=> RTC oscillator
// <o12.4..7> CLKOUTDIV: Selects clock divider for CLKOUT
// <1-16><#-1>
// <o12.8> CLKOUT_EN: CLKOUT enable control
// </h>
//
// </e>
*/
#define CLOCK_SETUP 1
#define SCS_Val 0x00000020
#define CLKSRCSEL_Val 0x00000001
#define PLL0_SETUP 1
#define PLL0CFG_Val 0x00050063
#define PLL1_SETUP 1
#define PLL1CFG_Val 0x00000023
#define CCLKCFG_Val 0x00000003
#define USBCLKCFG_Val 0x00000000
#define PCLKSEL0_Val 0x00000000
#define PCLKSEL1_Val 0x00000000
#define PCONP_Val 0x042887DE
#define CLKOUTCFG_Val 0x00000000
/*--------------------- Flash Accelerator Configuration ----------------------
//
// <e> Flash Accelerator Configuration
// <o1.12..15> FLASHTIM: Flash Access Time
// <0=> 1 CPU clock (for CPU clock up to 20 MHz)
// <1=> 2 CPU clocks (for CPU clock up to 40 MHz)
// <2=> 3 CPU clocks (for CPU clock up to 60 MHz)
// <3=> 4 CPU clocks (for CPU clock up to 80 MHz)
// <4=> 5 CPU clocks (for CPU clock up to 100 MHz)
// <5=> 6 CPU clocks (for any CPU clock)
// </e>
*/
#define FLASH_SETUP 1
#define FLASHCFG_Val 0x00004000
/*
//-------- <<< end of configuration section >>> ------------------------------
*/
/*----------------------------------------------------------------------------
Check the register settings
*----------------------------------------------------------------------------*/
#define CHECK_RANGE(val, min, max) ((val < min) || (val > max))
#define CHECK_RSVD(val, mask) (val & mask)
/* Clock Configuration -------------------------------------------------------*/
#if (CHECK_RSVD((SCS_Val), ~0x00000030))
#error "SCS: Invalid values of reserved bits!"
#endif
#if (CHECK_RANGE((CLKSRCSEL_Val), 0, 2))
#error "CLKSRCSEL: Value out of range!"
#endif
#if (CHECK_RSVD((PLL0CFG_Val), ~0x00FF7FFF))
#error "PLL0CFG: Invalid values of reserved bits!"
#endif
#if (CHECK_RSVD((PLL1CFG_Val), ~0x0000007F))
#error "PLL1CFG: Invalid values of reserved bits!"
#endif
#if (PLL0_SETUP) /* if PLL0 is used */
#if (CCLKCFG_Val < 2) /* CCLKSEL must be greater then 1 */
#error "CCLKCFG: CCLKSEL must be greater then 1 if PLL0 is used!"
#endif
#endif
#if (CHECK_RANGE((CCLKCFG_Val), 2, 255))
#error "CCLKCFG: Value out of range!"
#endif
#if (CHECK_RSVD((USBCLKCFG_Val), ~0x0000000F))
#error "USBCLKCFG: Invalid values of reserved bits!"
#endif
#if (CHECK_RSVD((PCLKSEL0_Val), 0x000C0C00))
#error "PCLKSEL0: Invalid values of reserved bits!"
#endif
#if (CHECK_RSVD((PCLKSEL1_Val), 0x03000300))
#error "PCLKSEL1: Invalid values of reserved bits!"
#endif
#if (CHECK_RSVD((PCONP_Val), 0x10100821))
#error "PCONP: Invalid values of reserved bits!"
#endif
#if (CHECK_RSVD((CLKOUTCFG_Val), ~0x000001FF))
#error "CLKOUTCFG: Invalid values of reserved bits!"
#endif
/* Flash Accelerator Configuration -------------------------------------------*/
#if (CHECK_RSVD((FLASHCFG_Val), ~0x0000F000))
#error "FLASHCFG: Invalid values of reserved bits!"
#endif
/*----------------------------------------------------------------------------
DEFINES
*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
Define clocks
*----------------------------------------------------------------------------*/
#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) ((2ULL * __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
#else
#if ((CLKSRCSEL_Val & 0x03) == 1)
#define __CORE_CLK (OSC_CLK / __CCLK_DIV)
#elif ((CLKSRCSEL_Val & 0x03) == 2)
#define __CORE_CLK (RTC_CLK / __CCLK_DIV)
#else
#define __CORE_CLK (IRC_OSC / __CCLK_DIV)
#endif
#endif
#define BLINK_DELAY (1000000)
void loop_delay(uint32_t t)
{
for (uint32_t delay = 0; delay < t; delay++) {
__asm("NOP");
}
}
void bl_blink(void)
{
LED_ON(1);
LED_ON(2);
LED_ON(3);
LED_ON(4);
loop_delay(BLINK_DELAY);
LED_OFF(1);
LED_OFF(2);
LED_OFF(3);
LED_OFF(4);
}
/*----------------------------------------------------------------------------
Clock Variable definitions
*----------------------------------------------------------------------------*/
uint32_t system_clock = __CORE_CLK;/*!< System Clock Frequency (Core Clock)*/
/*----------------------------------------------------------------------------
Clock functions
*----------------------------------------------------------------------------*/
void clock_update(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 */
system_clock = (IRC_OSC *
((2ULL * ((LPC_SC->PLL0STAT & 0x7FFF) + 1))) /
(((LPC_SC->PLL0STAT >> 16) & 0xFF) + 1) /
((LPC_SC->CCLKCFG & 0xFF) + 1));
break;
case 1: /* Main oscillator => PLL0 */
system_clock = (OSC_CLK *
((2ULL * ((LPC_SC->PLL0STAT & 0x7FFF) + 1))) /
(((LPC_SC->PLL0STAT >> 16) & 0xFF) + 1) /
((LPC_SC->CCLKCFG & 0xFF) + 1));
break;
case 2: /* RTC oscillator => PLL0 */
system_clock = (RTC_CLK *
((2ULL * ((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 */
system_clock = IRC_OSC / ((LPC_SC->CCLKCFG & 0xFF) + 1);
break;
case 1: /* Main oscillator => PLL0 */
system_clock = OSC_CLK / ((LPC_SC->CCLKCFG & 0xFF) + 1);
break;
case 2: /* RTC oscillator => PLL0 */
system_clock = RTC_CLK / ((LPC_SC->CCLKCFG & 0xFF) + 1);
break;
}
}
}
/**
* Initialize the system
*
* @brief Setup the microcontroller system.
* Initialize the System.
*/
void board_init(void)
{
#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 */
LPC_SC->PCLKSEL0 = PCLKSEL0_Val; /* Peripheral Clock Selection */
LPC_SC->PCLKSEL1 = PCLKSEL1_Val;
LPC_SC->CLKSRCSEL = CLKSRCSEL_Val; /* Select Clock Source for PLL0 */
#if (PLL0_SETUP)
LPC_SC->PLL0CFG = PLL0CFG_Val; /* configure PLL0 */
LPC_SC->PLL0FEED = 0xAA;
LPC_SC->PLL0FEED = 0x55;
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;
while (!(LPC_SC->PLL0STAT & ((1 << 25) | (1 << 24)))); /* Wait for PLLC0_STAT & PLLE0_STAT */
#endif
#if (PLL1_SETUP)
LPC_SC->PLL1CFG = PLL1CFG_Val;
LPC_SC->PLL1FEED = 0xAA;
LPC_SC->PLL1FEED = 0x55;
LPC_SC->PLL1CON = 0x01; /* PLL1 Enable */
LPC_SC->PLL1FEED = 0xAA;
LPC_SC->PLL1FEED = 0x55;
while (!(LPC_SC->PLL1STAT & (1 << 10))); /* Wait for PLOCK1 */
LPC_SC->PLL1CON = 0x03; /* PLL1 Enable & Connect */
LPC_SC->PLL1FEED = 0xAA;
LPC_SC->PLL1FEED = 0x55;
while (!(LPC_SC->PLL1STAT & ((1 << 9) | (1 << 8)))); /* Wait for PLLC1_STAT & PLLE1_STAT */
#else
LPC_SC->USBCLKCFG = USBCLKCFG_Val; /* Setup USB Clock Divider */
#endif
LPC_SC->PCONP = PCONP_Val; /* Power Control for Peripherals */
LPC_SC->CLKOUTCFG = CLKOUTCFG_Val; /* Clock Output Configuration */
#endif
#if (FLASH_SETUP == 1) /* Flash Accelerator Setup */
LPC_SC->FLASHCFG = (LPC_SC->FLASHCFG & ~0x0000F000) | FLASHCFG_Val;
#endif
/* Initialize LED pins */
LPC_GPIO1->FIODIR |= PIN_LED1;
LPC_GPIO1->FIODIR |= PIN_LED2;
LPC_GPIO1->FIODIR |= PIN_LED3;
LPC_GPIO1->FIODIR |= PIN_LED4;
bl_blink();
}

View File

@ -0,0 +1,35 @@
#ifndef __BOARD_H
#define __BOARD_H
/**
* @file boards.h
* @author Oliver Hahm <oliver.hahm@inria.fr>
*
* @defgroup mbed_lpc1768 mbed NXP LPC1768 development kit
* @ingroup boards
* @{
*/
#include <stdint.h>
#include "bitarithm.h"
#define PIN_LED1 (BIT18)
#define PIN_LED2 (BIT20)
#define PIN_LED3 (BIT21)
#define PIN_LED4 (BIT23)
#define LED_ON(led_nr) (LPC_GPIO1->FIOSET = PIN_LED##led_nr)
#define LED_OFF(led_nr) (LPC_GPIO1->FIOCLR = PIN_LED##led_nr)
#define LED_TOGGLE(led_nr) (LPC_GPIO1->FIOPIN ^= PIN_LED##led_nr)
typedef uint8_t radio_packet_length_t;
/**
* @brief Busy waiting function (while hwtimer is not available at boot time)
*
* @param[in] t The waiting cycles
*/
void loop_delay(uint32_t t);
/** @} */
#endif /* __BOARD_H */

View File

@ -0,0 +1,56 @@
/******************************************************************************
* @file: system_LPC17xx.h
* @purpose: CMSIS Cortex-M3 Device Peripheral Access Layer Header File
* for the NXP LPC17xx Device Series
* @version: V1.03
* @date: 09. November 2013
*
* @note: Integrated and adopted for RIOT by Oliver Hahm.
*----------------------------------------------------------------------------
*
* Copyright (C) 2009 ARM Limited. All rights reserved.
* Copyright (C) 2013 Oliver Hahm <oliver.hahm@fu-berlin.de>
*
* ARM Limited (ARM) is supplying this software for use with Cortex-M3
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/
#ifndef __SYSTEM_LPC17xx_H
#define __SYSTEM_LPC17xx_H
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t system_clock; /*!< System Clock Frequency (Core Clock) */
/**
* Initialize the system
*
* @brief Setup the microcontroller system.
* Initialize the System and update the SystemCoreClock variable.
*/
extern void board_init(void);
/**
* Update system_clock variable
*
* @brief Updates the system_clock with current core Clock
* retrieved from cpu registers.
*/
extern void clock_update(void);
#ifdef __cplusplus
}
#endif
#endif /* __SYSTEM_LPC17xx_H */

View File

@ -1,3 +1,7 @@
ifeq ($(CPU),lpc1768)
DIRS = lpc1768
endif
ifeq ($(CPU),lpc2387)
DIRS = arm_common lpc_common lpc2387
endif
@ -27,6 +31,7 @@ $(DIRS):
@"$(MAKE)" -C $@
clean:
@"$(MAKE)" -C lpc1768 clean
@"$(MAKE)" -C lpc2387 clean
@"$(MAKE)" -C mc1322x clean
@"$(MAKE)" -C lpc_common clean

View File

@ -1,3 +1,6 @@
ifeq ($(CPU),lpc1768)
INCLUDES += -I$(MAKEBASE)/cpu/lpc1768/include
endif
ifeq ($(CPU),lpc2387)
INCLUDES += -I$(MAKEBASE)/cpu/arm_common/include/
INCLUDES += -I$(MAKEBASE)/cpu/lpc_common/include/

View File

@ -1,4 +1,7 @@
### Minimal setup
ifeq ($(CPU),lpc1768)
export UNDEF += $(BINDIR)syscalls.o
endif
ifeq ($(CPU),lpc2387)
export USEMODULE += arm_common lpc_common
export UNDEF += $(BINDIR)syscalls.o $(BINDIR)lpc_syscalls.o

154
cpu/lpc1768/LPC1768.ld Normal file
View File

@ -0,0 +1,154 @@
/* Linker script for mbed LPC1768 */
/* Linker script to configure memory regions. */
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 512K
RAM (rwx) : ORIGIN = 0x100000C8, LENGTH = 0x7F38
USB_RAM(rwx) : ORIGIN = 0x2007C000, LENGTH = 16K
ETH_RAM(rwx) : ORIGIN = 0x20080000, LENGTH = 16K
}
/* Linker script to place sections and symbol values. Should be used together
* with other linker script that defines memory regions FLASH and RAM.
* It references following symbols, which must be defined in code:
* Reset_Handler : Entry of reset handler
*
* It defines following symbols, which code can use without definition:
* __exidx_start
* __exidx_end
* __etext
* __data_start__
* __preinit_array_start
* __preinit_array_end
* __init_array_start
* __init_array_end
* __fini_array_start
* __fini_array_end
* __data_end__
* __bss_start__
* __bss_end__
* __end__
* end
* __HeapLimit
* __StackLimit
* __StackTop
* __stack
*/
ENTRY(Reset_Handler)
SECTIONS
{
.text :
{
KEEP(*(.isr_vector))
*(.text*)
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.rodata*)
KEEP(*(.eh_frame*))
} > FLASH
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH
__exidx_end = .;
__etext = .;
__sidata = __etext;
.data : AT (__etext)
{
__data_start__ = .;
*(vtable)
*(.data*)
. = ALIGN(4);
/* preinit data */
PROVIDE (__preinit_array_start = .);
KEEP(*(.preinit_array))
PROVIDE (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE (__fini_array_end = .);
. = ALIGN(4);
/* All data end */
__data_end__ = .;
} > RAM
.bss :
{
__bss_start__ = .;
*(.bss*)
*(COMMON)
__bss_end__ = .;
} > RAM
__heap_size = ORIGIN(RAM) + LENGTH(RAM) - . ;/*- __stack_size;*/
.heap :
{
PROVIDE(__heap_start = .);
__end__ = .;
end = __end__;
*(.heap*)
. = . + __heap_size;
PROVIDE(__heap_max = .);
__HeapLimit = .;
} > RAM
/* .stack_dummy section doesn't contains any symbols. It is only
* used for linker to calculate size of stack sections, and assign
* values to stack symbols later */
.stack_dummy :
{
*(.stack)
} > RAM
/* Set stack top to end of RAM, and stack limit move down by
* size of stack_dummy section */
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
}

30
cpu/lpc1768/Makefile Normal file
View File

@ -0,0 +1,30 @@
MODULE =cpu
OBJECTS = system_LPC17xx.o startup_LPC17xx.o main.o
CC_SYMBOLS = -DTARGET_LPC1769 -DTOOLCHAIN_GCC_ARM -DNDEBUG -D__CORTEX_M3
LD_FLAGS = -mcpu=cortex-m3 -mthumb -Wl,--gc-sections,-Map=$(PROJECT).map,--cref --specs=nano.specs
LD_SYS_LIBS = -lc -lgcc -lnosys
INCLUDES = -Iinclude
INCLUDES += -I$(RIOTBASE)/core/include -I$(RIOTBASE)/sys/include -I$(RIOTBASE)/sys/lib
all: $(BINDIR)$(MODULE).a
include $(RIOTBASE)/Makefile.base
clean::
@for i in $(DIRS) ; do "$(MAKE)" -C $$i clean ; done ;
# This is needed for NXP Cortex M devices
nxpsum:
$(CCLOCAL) nxpsum.c -std=c99 -o nxpsum
#$(PROJECT).elf: $(OBJECTS) $(SYS_OBJECTS)
# $(LD) $(LD_FLAGS) -T$(LINKER_SCRIPT) $(LIBRARY_PATHS) -o $@ $(addprefix $(BUILD_DIR), $^) $(LIBRARIES) $(LD_SYS_LIBS) $(LIBRARIES) $(LD_SYS_LIBS)
$(PROJECT).bin: $(PROJECT).elf nxpsum
$(OBJCOPY) -O binary $< $@
# Compute nxp checksum on .bin file here
./nxpsum $@

167
cpu/lpc1768/atom.c Normal file
View File

@ -0,0 +1,167 @@
/**
* CPU speficic RIOT kernel function for NXP LPC1768
*
* Copyright (C) 2013 Oliver Hahm <oliver.hahm@inria.fr>
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup lpc1768
* @{
* @file atom.c
* @author Stefan Pfeiffer <stefan.pfeiffer@fu-berlin.de>
* @author Oliver Hahm <oliver.hahm@inria.fr>
* @}
*/
#include "sched.h"
#include "cpu.h"
#include "irq.h"
extern void sched_task_exit(void);
void sched_task_return(void);
unsigned int atomic_set_return(unsigned int* p, unsigned int uiVal) {
//unsigned int cspr = disableIRQ(); //crashes
dINT();
unsigned int uiOldVal = *p;
*p = uiVal;
//restoreIRQ(cspr); //crashes
eINT();
return uiOldVal;
}
void cpu_switch_context_exit(void){
sched_run();
sched_task_return();
}
void thread_yield(void) {
asm("svc 0x01\n");
}
__attribute__((naked))
void SVC_Handler(void)
{
save_context();
asm("bl sched_run");
/* call scheduler update active_thread variable with pdc of next thread
* the thread that has higest priority and is in PENDING state */
restore_context();
}
/* kernel functions */
void ctx_switch(void)
{
/* Save return address on stack */
/* stmfd sp!, {lr} */
/* disable interrupts */
/* mov lr, #NOINT|SVCMODE */
/* msr CPSR_c, lr */
/* cpsid i */
/* save other register */
asm("nop");
asm("mov r12, sp");
asm("stmfd r12!, {r4-r11}");
/* save user mode stack pointer in *active_thread */
asm("ldr r1, =active_thread"); /* r1 = &active_thread */
asm("ldr r1, [r1]"); /* r1 = *r1 = active_thread */
asm("str r12, [r1]"); /* store stack pointer in tasks pdc*/
sched_task_return();
}
/* call scheduler so active_thread points to the next task */
void sched_task_return(void)
{
/* load pdc->stackpointer in r0 */
asm("ldr r0, =active_thread"); /* r0 = &active_thread */
asm("ldr r0, [r0]"); /* r0 = *r0 = active_thread */
asm("ldr sp, [r0]"); /* sp = r0 restore stack pointer*/
asm("pop {r4}"); /* skip exception return */
asm(" pop {r4-r11}");
asm(" pop {r0-r3,r12,lr}"); /* simulate register restor from stack */
// asm("pop {r4}"); /*foo*/
asm("pop {pc}");
}
/*
* cortex m4 knows stacks and handles register backups
*
* so use different stack frame layout
*
*
* with float storage
* ------------------------------------------------------------------------------------------------------------------------------------
* | R0 | R1 | R2 | R3 | LR | PC | xPSR | S0 | S1 | S2 | S3 | S4 | S5 | S6 | S7 | S8 | S9 | S10 | S11 | S12 | S13 | S14 | S15 | FPSCR |
* ------------------------------------------------------------------------------------------------------------------------------------
*
* without
*
* --------------------------------------
* | R0 | R1 | R2 | R3 | LR | PC | xPSR |
* --------------------------------------
*
*
*/
char * thread_stack_init(void * task_func, void * stack_start, int stack_size ) {
unsigned int * stk;
stk = (unsigned int *) (stack_start + stack_size);
/* marker */
stk--;
*stk = 0x77777777;
//FIXME FPSCR
stk--;
*stk = (unsigned int) 0;
//S0 - S15
for (int i = 15; i >= 0; i--) {
stk--;
*stk = i;
}
//FIXME xPSR
stk--;
*stk = (unsigned int) 0x01000200;
//program counter
stk--;
*stk = (unsigned int) task_func;
/* link register */
stk--;
*stk = (unsigned int) 0x0;
/* r12 */
stk--;
*stk = (unsigned int) 0;
/* r0 - r3 */
for (int i = 3; i >= 0; i--) {
stk--;
*stk = i;
}
/* r11 - r4 */
for (int i = 11; i >= 4; i--) {
stk--;
*stk = i;
}
/* foo */
/*stk--;
*stk = (unsigned int) 0xDEADBEEF;*/
/* lr means exception return code */
stk--;
*stk = (unsigned int) 0xfffffff9; // return to taskmode main stack pointer
return (char*) stk;
}

108
cpu/lpc1768/cpu.c Normal file
View File

@ -0,0 +1,108 @@
/**
* CPU specific functions for the RIOT scheduler on NXP LPC1768
*
* Copyright (C) 2013 Oliver Hahm <oliver.hahm@inria.fr>
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @file cpu.c
* @author Kaspar Schleiser <kaspar.schleiser@fu-berlin.de>
* @author Oliver Hahm <oliver.hahm@inria.fr>
*/
#include <stdint.h>
#include "cpu.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
int inISR(void)
{
return (__get_IPSR() & 0xFF);
}
unsigned int disableIRQ(void)
{
// FIXME PRIMASK is the old CPSR (FAULTMASK ??? BASEPRI ???)
//PRIMASK lesen
unsigned int uiPriMask = __get_PRIMASK();
__disable_irq();
return uiPriMask;
}
void restoreIRQ(unsigned oldPRIMASK)
{
//PRIMASK lesen setzen
__set_PRIMASK(oldPRIMASK);
}
__attribute__((naked))
void HardFault_Handler(void) {
DEBUG("HARD FAULT\n");
while(1);
}
__attribute__((naked))
void BusFault_Handler(void) {
DEBUG("BusFault_Handler\n");
while(1);
}
__attribute__((naked))
void Usage_Handler(void) {
DEBUG("Usage FAULT\n");
while(1);
}
__attribute__((naked))
void WWDG_Handler(void) {
DEBUG("WWDG FAULT\n");
while(1);
}
void dINT(void)
{
__disable_irq();
}
void eINT(void)
{
__enable_irq();
}
void save_context(void)
{
/* {r0-r3,r12,LR,PC,xPSR} are saved automatically on exception entry */
asm("push {r4-r11}");
/* save unsaved registers */
asm("push {LR}");
/* save exception return value */
asm("ldr r1, =active_thread");
/* load address of currend pdc */
asm("ldr r1, [r1]");
/* deref pdc */
asm("str sp, [r1]");
/* write sp to pdc->sp means current threads stack pointer */
}
void restore_context(void)
{
asm("ldr r0, =active_thread");
/* load address of currend pdc */
asm("ldr r0, [r0]");
/* deref pdc */
asm("ldr sp, [r0]");
/* load pdc->sp to sp register */
asm("pop {r0}");
/* restore exception retrun value from stack */
asm("pop {r4-r11}");
/* load unloaded register */
// asm("pop {r4}"); /*foo*/
asm("bx r0"); /* load exception return value to pc causes end of exception*/
/* {r0-r3,r12,LR,PC,xPSR} are restored automatically on exception return */
}

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,617 @@
/**************************************************************************//**
* @file core_cmFunc.h
* @brief CMSIS Cortex-M Core Function Access Header File
* @version V3.02
* @date 24. May 2012
*
* @note
* Copyright (C) 2009-2012 ARM Limited. All rights reserved.
*
* @par
* ARM Limited (ARM) is supplying this software for use with Cortex-M
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* @par
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/
#ifndef __CORE_CMFUNC_H
#define __CORE_CMFUNC_H
#include <stdint.h>
/* ########################### Core Function Access ########################### */
/** \ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
@{
*/
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
/* ARM armcc specific functions */
#if (__ARMCC_VERSION < 400677)
#error "Please use ARM Compiler Toolchain V4.0.677 or later!"
#endif
/* intrinsic void __enable_irq(); */
/* intrinsic void __disable_irq(); */
/** \brief Get Control Register
This function returns the content of the Control Register.
\return Control Register value
*/
__STATIC_INLINE uint32_t __get_CONTROL(void)
{
register uint32_t __regControl __ASM("control");
return(__regControl);
}
/** \brief Set Control Register
This function writes the given value to the Control Register.
\param [in] control Control Register value to set
*/
__STATIC_INLINE void __set_CONTROL(uint32_t control)
{
register uint32_t __regControl __ASM("control");
__regControl = control;
}
/** \brief Get IPSR Register
This function returns the content of the IPSR Register.
\return IPSR Register value
*/
__STATIC_INLINE uint32_t __get_IPSR(void)
{
register uint32_t __regIPSR __ASM("ipsr");
return(__regIPSR);
}
/** \brief Get APSR Register
This function returns the content of the APSR Register.
\return APSR Register value
*/
__STATIC_INLINE uint32_t __get_APSR(void)
{
register uint32_t __regAPSR __ASM("apsr");
return(__regAPSR);
}
/** \brief Get xPSR Register
This function returns the content of the xPSR Register.
\return xPSR Register value
*/
__STATIC_INLINE uint32_t __get_xPSR(void)
{
register uint32_t __regXPSR __ASM("xpsr");
return(__regXPSR);
}
/** \brief Get Process Stack Pointer
This function returns the current value of the Process Stack Pointer (PSP).
\return PSP Register value
*/
__STATIC_INLINE uint32_t __get_PSP(void)
{
register uint32_t __regProcessStackPointer __ASM("psp");
return(__regProcessStackPointer);
}
/** \brief Set Process Stack Pointer
This function assigns the given value to the Process Stack Pointer (PSP).
\param [in] topOfProcStack Process Stack Pointer value to set
*/
__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
{
register uint32_t __regProcessStackPointer __ASM("psp");
__regProcessStackPointer = topOfProcStack;
}
/** \brief Get Main Stack Pointer
This function returns the current value of the Main Stack Pointer (MSP).
\return MSP Register value
*/
__STATIC_INLINE uint32_t __get_MSP(void)
{
register uint32_t __regMainStackPointer __ASM("msp");
return(__regMainStackPointer);
}
/** \brief Set Main Stack Pointer
This function assigns the given value to the Main Stack Pointer (MSP).
\param [in] topOfMainStack Main Stack Pointer value to set
*/
__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
{
register uint32_t __regMainStackPointer __ASM("msp");
__regMainStackPointer = topOfMainStack;
}
/** \brief Get Priority Mask
This function returns the current state of the priority mask bit from the Priority Mask Register.
\return Priority Mask value
*/
__STATIC_INLINE uint32_t __get_PRIMASK(void)
{
register uint32_t __regPriMask __ASM("primask");
return(__regPriMask);
}
/** \brief Set Priority Mask
This function assigns the given value to the Priority Mask Register.
\param [in] priMask Priority Mask
*/
__STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
{
register uint32_t __regPriMask __ASM("primask");
__regPriMask = (priMask);
}
#if (__CORTEX_M >= 0x03)
/** \brief Enable FIQ
This function enables FIQ interrupts by clearing the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
#define __enable_fault_irq __enable_fiq
/** \brief Disable FIQ
This function disables FIQ interrupts by setting the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
#define __disable_fault_irq __disable_fiq
/** \brief Get Base Priority
This function returns the current value of the Base Priority register.
\return Base Priority register value
*/
__STATIC_INLINE uint32_t __get_BASEPRI(void)
{
register uint32_t __regBasePri __ASM("basepri");
return(__regBasePri);
}
/** \brief Set Base Priority
This function assigns the given value to the Base Priority register.
\param [in] basePri Base Priority value to set
*/
__STATIC_INLINE void __set_BASEPRI(uint32_t basePri)
{
register uint32_t __regBasePri __ASM("basepri");
__regBasePri = (basePri & 0xff);
}
/** \brief Get Fault Mask
This function returns the current value of the Fault Mask register.
\return Fault Mask register value
*/
__STATIC_INLINE uint32_t __get_FAULTMASK(void)
{
register uint32_t __regFaultMask __ASM("faultmask");
return(__regFaultMask);
}
/** \brief Set Fault Mask
This function assigns the given value to the Fault Mask register.
\param [in] faultMask Fault Mask value to set
*/
__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
{
register uint32_t __regFaultMask __ASM("faultmask");
__regFaultMask = (faultMask & (uint32_t)1);
}
#endif /* (__CORTEX_M >= 0x03) */
#if (__CORTEX_M == 0x04)
/** \brief Get FPSCR
This function returns the current value of the Floating Point Status/Control register.
\return Floating Point Status/Control register value
*/
__STATIC_INLINE uint32_t __get_FPSCR(void)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
register uint32_t __regfpscr __ASM("fpscr");
return(__regfpscr);
#else
return(0);
#endif
}
/** \brief Set FPSCR
This function assigns the given value to the Floating Point Status/Control register.
\param [in] fpscr Floating Point Status/Control value to set
*/
__STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
register uint32_t __regfpscr __ASM("fpscr");
__regfpscr = (fpscr);
#endif
}
#endif /* (__CORTEX_M == 0x04) */
#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
/* IAR iccarm specific functions */
#include <cmsis_iar.h>
#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
/* TI CCS specific functions */
#include <cmsis_ccs.h>
#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */
/** \brief Enable IRQ Interrupts
This function enables IRQ interrupts by clearing the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void)
{
__ASM volatile ("cpsie i" : : : "memory");
}
/** \brief Disable IRQ Interrupts
This function disables IRQ interrupts by setting the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void)
{
__ASM volatile ("cpsid i" : : : "memory");
}
/** \brief Get Control Register
This function returns the content of the Control Register.
\return Control Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void)
{
uint32_t result;
__ASM volatile ("MRS %0, control" : "=r" (result) );
return(result);
}
/** \brief Set Control Register
This function writes the given value to the Control Register.
\param [in] control Control Register value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control)
{
__ASM volatile ("MSR control, %0" : : "r" (control) );
}
/** \brief Get IPSR Register
This function returns the content of the IPSR Register.
\return IPSR Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, ipsr" : "=r" (result) );
return(result);
}
/** \brief Get APSR Register
This function returns the content of the APSR Register.
\return APSR Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, apsr" : "=r" (result) );
return(result);
}
/** \brief Get xPSR Register
This function returns the content of the xPSR Register.
\return xPSR Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, xpsr" : "=r" (result) );
return(result);
}
/** \brief Get Process Stack Pointer
This function returns the current value of the Process Stack Pointer (PSP).
\return PSP Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void)
{
register uint32_t result;
__ASM volatile ("MRS %0, psp\n" : "=r" (result) );
return(result);
}
/** \brief Set Process Stack Pointer
This function assigns the given value to the Process Stack Pointer (PSP).
\param [in] topOfProcStack Process Stack Pointer value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
{
__ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) );
}
/** \brief Get Main Stack Pointer
This function returns the current value of the Main Stack Pointer (MSP).
\return MSP Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void)
{
register uint32_t result;
__ASM volatile ("MRS %0, msp\n" : "=r" (result) );
return(result);
}
/** \brief Set Main Stack Pointer
This function assigns the given value to the Main Stack Pointer (MSP).
\param [in] topOfMainStack Main Stack Pointer value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
{
__ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) );
}
/** \brief Get Priority Mask
This function returns the current state of the priority mask bit from the Priority Mask Register.
\return Priority Mask value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void)
{
uint32_t result;
__ASM volatile ("MRS %0, primask" : "=r" (result) );
return(result);
}
/** \brief Set Priority Mask
This function assigns the given value to the Priority Mask Register.
\param [in] priMask Priority Mask
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
{
__ASM volatile ("MSR primask, %0" : : "r" (priMask) );
}
#if (__CORTEX_M >= 0x03)
/** \brief Enable FIQ
This function enables FIQ interrupts by clearing the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void)
{
__ASM volatile ("cpsie f" : : : "memory");
}
/** \brief Disable FIQ
This function disables FIQ interrupts by setting the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void)
{
__ASM volatile ("cpsid f" : : : "memory");
}
/** \brief Get Base Priority
This function returns the current value of the Base Priority register.
\return Base Priority register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void)
{
uint32_t result;
__ASM volatile ("MRS %0, basepri_max" : "=r" (result) );
return(result);
}
/** \brief Set Base Priority
This function assigns the given value to the Base Priority register.
\param [in] basePri Base Priority value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value)
{
__ASM volatile ("MSR basepri, %0" : : "r" (value) );
}
/** \brief Get Fault Mask
This function returns the current value of the Fault Mask register.
\return Fault Mask register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void)
{
uint32_t result;
__ASM volatile ("MRS %0, faultmask" : "=r" (result) );
return(result);
}
/** \brief Set Fault Mask
This function assigns the given value to the Fault Mask register.
\param [in] faultMask Fault Mask value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
{
__ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) );
}
#endif /* (__CORTEX_M >= 0x03) */
#if (__CORTEX_M == 0x04)
/** \brief Get FPSCR
This function returns the current value of the Floating Point Status/Control register.
\return Floating Point Status/Control register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
uint32_t result;
__ASM volatile ("VMRS %0, fpscr" : "=r" (result) );
return(result);
#else
return(0);
#endif
}
/** \brief Set FPSCR
This function assigns the given value to the Floating Point Status/Control register.
\param [in] fpscr Floating Point Status/Control value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
__ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) );
#endif
}
#endif /* (__CORTEX_M == 0x04) */
#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
/* TASKING carm specific functions */
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all instrinsics,
* Including the CMSIS ones.
*/
#endif
/*@} end of CMSIS_Core_RegAccFunctions */
#endif /* __CORE_CMFUNC_H */

View File

@ -0,0 +1,643 @@
/**************************************************************************//**
* @file core_cmInstr.h
* @brief CMSIS Cortex-M Core Instruction Access Header File
* @version V3.03
* @date 29. August 2012
*
* @note
* Copyright (C) 2009-2012 ARM Limited. All rights reserved.
*
* @par
* ARM Limited (ARM) is supplying this software for use with Cortex-M
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* @par
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/
#ifndef __CORE_CMINSTR_H
#define __CORE_CMINSTR_H
/* ########################## Core Instruction Access ######################### */
/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
Access to dedicated instructions
@{
*/
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
/* ARM armcc specific functions */
#if (__ARMCC_VERSION < 400677)
#error "Please use ARM Compiler Toolchain V4.0.677 or later!"
#endif
/** \brief No Operation
No Operation does nothing. This instruction can be used for code alignment purposes.
*/
#define __NOP __nop
/** \brief Wait For Interrupt
Wait For Interrupt is a hint instruction that suspends execution
until one of a number of events occurs.
*/
#define __WFI __wfi
/** \brief Wait For Event
Wait For Event is a hint instruction that permits the processor to enter
a low-power state until one of a number of events occurs.
*/
#define __WFE __wfe
/** \brief Send Event
Send Event is a hint instruction. It causes an event to be signaled to the CPU.
*/
#define __SEV __sev
/** \brief Instruction Synchronization Barrier
Instruction Synchronization Barrier flushes the pipeline in the processor,
so that all instructions following the ISB are fetched from cache or
memory, after the instruction has been completed.
*/
#define __ISB() __isb(0xF)
/** \brief Data Synchronization Barrier
This function acts as a special kind of Data Memory Barrier.
It completes when all explicit memory accesses before this instruction complete.
*/
#define __DSB() __dsb(0xF)
/** \brief Data Memory Barrier
This function ensures the apparent order of the explicit memory operations before
and after the instruction, without ensuring their completion.
*/
#define __DMB() __dmb(0xF)
/** \brief Reverse byte order (32 bit)
This function reverses the byte order in integer value.
\param [in] value Value to reverse
\return Reversed value
*/
#define __REV __rev
/** \brief Reverse byte order (16 bit)
This function reverses the byte order in two unsigned short values.
\param [in] value Value to reverse
\return Reversed value
*/
#ifndef __NO_EMBEDDED_ASM
__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
{
rev16 r0, r0
bx lr
}
#endif
/** \brief Reverse byte order in signed short value
This function reverses the byte order in a signed short value with sign extension to integer.
\param [in] value Value to reverse
\return Reversed value
*/
#ifndef __NO_EMBEDDED_ASM
__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value)
{
revsh r0, r0
bx lr
}
#endif
/** \brief Rotate Right in unsigned value (32 bit)
This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
\param [in] value Value to rotate
\param [in] value Number of Bits to rotate
\return Rotated value
*/
#define __ROR __ror
/** \brief Breakpoint
This function causes the processor to enter Debug state.
Debug tools can use this to investigate system state when the instruction at a particular address is reached.
\param [in] value is ignored by the processor.
If required, a debugger can use it to store additional information about the breakpoint.
*/
#define __BKPT(value) __breakpoint(value)
#if (__CORTEX_M >= 0x03)
/** \brief Reverse bit order of value
This function reverses the bit order of the given value.
\param [in] value Value to reverse
\return Reversed value
*/
#define __RBIT __rbit
/** \brief LDR Exclusive (8 bit)
This function performs a exclusive LDR command for 8 bit value.
\param [in] ptr Pointer to data
\return value of type uint8_t at (*ptr)
*/
#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr))
/** \brief LDR Exclusive (16 bit)
This function performs a exclusive LDR command for 16 bit values.
\param [in] ptr Pointer to data
\return value of type uint16_t at (*ptr)
*/
#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr))
/** \brief LDR Exclusive (32 bit)
This function performs a exclusive LDR command for 32 bit values.
\param [in] ptr Pointer to data
\return value of type uint32_t at (*ptr)
*/
#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr))
/** \brief STR Exclusive (8 bit)
This function performs a exclusive STR command for 8 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#define __STREXB(value, ptr) __strex(value, ptr)
/** \brief STR Exclusive (16 bit)
This function performs a exclusive STR command for 16 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#define __STREXH(value, ptr) __strex(value, ptr)
/** \brief STR Exclusive (32 bit)
This function performs a exclusive STR command for 32 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#define __STREXW(value, ptr) __strex(value, ptr)
/** \brief Remove the exclusive lock
This function removes the exclusive lock which is created by LDREX.
*/
#define __CLREX __clrex
/** \brief Signed Saturate
This function saturates a signed value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (1..32)
\return Saturated value
*/
#define __SSAT __ssat
/** \brief Unsigned Saturate
This function saturates an unsigned value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (0..31)
\return Saturated value
*/
#define __USAT __usat
/** \brief Count leading zeros
This function counts the number of leading zeros of a data value.
\param [in] value Value to count the leading zeros
\return number of leading zeros in value
*/
#define __CLZ __clz
#endif /* (__CORTEX_M >= 0x03) */
#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
/* IAR iccarm specific functions */
#include <cmsis_iar.h>
#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
/* TI CCS specific functions */
#include <cmsis_ccs.h>
#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */
/** \brief No Operation
No Operation does nothing. This instruction can be used for code alignment purposes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void)
{
__ASM volatile ("nop");
}
/** \brief Wait For Interrupt
Wait For Interrupt is a hint instruction that suspends execution
until one of a number of events occurs.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void)
{
__ASM volatile ("wfi");
}
/** \brief Wait For Event
Wait For Event is a hint instruction that permits the processor to enter
a low-power state until one of a number of events occurs.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void)
{
__ASM volatile ("wfe");
}
/** \brief Send Event
Send Event is a hint instruction. It causes an event to be signaled to the CPU.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void)
{
__ASM volatile ("sev");
}
/** \brief Instruction Synchronization Barrier
Instruction Synchronization Barrier flushes the pipeline in the processor,
so that all instructions following the ISB are fetched from cache or
memory, after the instruction has been completed.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void)
{
__ASM volatile ("isb");
}
/** \brief Data Synchronization Barrier
This function acts as a special kind of Data Memory Barrier.
It completes when all explicit memory accesses before this instruction complete.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void)
{
__ASM volatile ("dsb");
}
/** \brief Data Memory Barrier
This function ensures the apparent order of the explicit memory operations before
and after the instruction, without ensuring their completion.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void)
{
__ASM volatile ("dmb");
}
/** \brief Reverse byte order (32 bit)
This function reverses the byte order in integer value.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value)
{
uint32_t result;
__ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/** \brief Reverse byte order (16 bit)
This function reverses the byte order in two unsigned short values.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value)
{
uint32_t result;
__ASM volatile ("rev16 %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/** \brief Reverse byte order in signed short value
This function reverses the byte order in a signed short value with sign extension to integer.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value)
{
uint32_t result;
__ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/** \brief Rotate Right in unsigned value (32 bit)
This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
\param [in] value Value to rotate
\param [in] value Number of Bits to rotate
\return Rotated value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
{
__ASM volatile ("ror %0, %0, %1" : "+r" (op1) : "r" (op2) );
return(op1);
}
/** \brief Breakpoint
This function causes the processor to enter Debug state.
Debug tools can use this to investigate system state when the instruction at a particular address is reached.
\param [in] value is ignored by the processor.
If required, a debugger can use it to store additional information about the breakpoint.
*/
#define __BKPT(value) __ASM volatile ("bkpt "#value)
#if (__CORTEX_M >= 0x03)
/** \brief Reverse bit order of value
This function reverses the bit order of the given value.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
{
uint32_t result;
__ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/** \brief LDR Exclusive (8 bit)
This function performs a exclusive LDR command for 8 bit value.
\param [in] ptr Pointer to data
\return value of type uint8_t at (*ptr)
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr)
{
uint8_t result;
__ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/** \brief LDR Exclusive (16 bit)
This function performs a exclusive LDR command for 16 bit values.
\param [in] ptr Pointer to data
\return value of type uint16_t at (*ptr)
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr)
{
uint16_t result;
__ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/** \brief LDR Exclusive (32 bit)
This function performs a exclusive LDR command for 32 bit values.
\param [in] ptr Pointer to data
\return value of type uint32_t at (*ptr)
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr)
{
uint32_t result;
__ASM volatile ("ldrex %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/** \brief STR Exclusive (8 bit)
This function performs a exclusive STR command for 8 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr)
{
uint32_t result;
__ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
return(result);
}
/** \brief STR Exclusive (16 bit)
This function performs a exclusive STR command for 16 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr)
{
uint32_t result;
__ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
return(result);
}
/** \brief STR Exclusive (32 bit)
This function performs a exclusive STR command for 32 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr)
{
uint32_t result;
__ASM volatile ("strex %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
return(result);
}
/** \brief Remove the exclusive lock
This function removes the exclusive lock which is created by LDREX.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void)
{
__ASM volatile ("clrex");
}
/** \brief Signed Saturate
This function saturates a signed value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (1..32)
\return Saturated value
*/
#define __SSAT(ARG1,ARG2) \
({ \
uint32_t __RES, __ARG1 = (ARG1); \
__ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
__RES; \
})
/** \brief Unsigned Saturate
This function saturates an unsigned value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (0..31)
\return Saturated value
*/
#define __USAT(ARG1,ARG2) \
({ \
uint32_t __RES, __ARG1 = (ARG1); \
__ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
__RES; \
})
/** \brief Count leading zeros
This function counts the number of leading zeros of a data value.
\param [in] value Value to count the leading zeros
\return number of leading zeros in value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value)
{
uint8_t result;
__ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
#endif /* (__CORTEX_M >= 0x03) */
#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
/* TASKING carm specific functions */
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all intrinsics,
* Including the CMSIS ones.
*/
#endif
/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
#endif /* __CORE_CMINSTR_H */

View File

@ -0,0 +1,18 @@
#ifndef CPU_CONF_H
#define CPU_CONF_H
/**
* @name Kernel configuration
* @{
*/
#define F_CPU 96000000
#define KERNEL_CONF_STACKSIZE_PRINTF (4096)
#ifndef KERNEL_CONF_STACKSIZE_DEFAULT
#define KERNEL_CONF_STACKSIZE_DEFAULT 1500
#endif
#define KERNEL_CONF_STACKSIZE_IDLE 1000
/** @} */
#endif /* CPU_CONF_H */

34
cpu/lpc1768/include/cpu.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef CPU_H
#define CPU_H
/**
* @defgroup lpc1768 NXP LPC1768
* @ingroup cpu
* @{
*/
#include "LPC17xx.h"
#include "core_cm3.h"
#include "core_cmFunc.h"
extern void dINT(void);
extern void eINT(void);
/**
* @brief Save the thread's context
*/
void save_context(void);
/**
* @brief Restores the before saved context of a thread
*/
void restore_context(void);
/**
* @brief Let the thread yield
*/
void thread_yield(void);
/** @} */
#endif /* CPU_H */

View File

@ -0,0 +1,8 @@
#ifndef HWTIMER_CPU_H_
#define HWTIMER_CPU_H_
#define ARCH_MAXTIMERS 3
#define HWTIMER_SPEED 1000000
#define HWTIMER_MAXTICKS (0xFFFFFFFF)
#endif /* HWTIMER_CPU_H_ */

36
cpu/lpc1768/lpc1768-lpm.c Normal file
View File

@ -0,0 +1,36 @@
/**
* LPM dummys for NXP LPC1768
*
* Copyright (C) 2013 Oliver Hahm <oliver.hahm@inria.fr>
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup lpc1768
* @{
* @file lpc1768-lpm.c
* @author Oliver Hahm <oliver.hahm@inria.fr>
* @}
*/
#include <stdio.h>
#include <stdint.h>
#include "lpm.h"
/* lpm is accessed before memory init and initialized separately through code */
__attribute__((section(".noinit")))
static enum lpm_mode lpm;
// TODO
enum lpm_mode lpm_set(enum lpm_mode target) {
enum lpm_mode last_lpm = lpm;
lpm = target;
return last_lpm;
}
void lpm_awake(void) {
lpm = LPM_ON;
}

297
cpu/lpc1768/startup.c Normal file
View File

@ -0,0 +1,297 @@
/******************************************************************************
* @file: startup.c
* @purpose: CMSIS Cortex-M3 Core Device Startup File
* @version: V1.02
* @date: 9. November 2013
*
* @note: Integrated and adopted for RIOT by Oliver Hahm.
*----------------------------------------------------------------------------
*
* Copyright (C) 2009 ARM Limited. All rights reserved.
* Copyright (C) 2013 Oliver Hahm <oliver.hahm@inria.fr>
*
* ARM Limited (ARM) is supplying this software for use with Cortex-Mx
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/
#include "LPC17xx.h"
#include "kernel_internal.h"
#define WEAK __attribute__ ((weak))
/*****************************************************************************
*
* Forward declaration of the default fault handlers.
*
*****************************************************************************/
/* System exception vector handler */
void WEAK Reset_Handler(void); /* Reset Handler */
void WEAK NMI_Handler(void); /* NMI Handler */
void WEAK HardFault_Handler(void); /* Hard Fault Handler */
void WEAK MemManage_Handler(void); /* MPU Fault Handler */
void WEAK BusFault_Handler(void); /* Bus Fault Handler */
void WEAK UsageFault_Handler(void); /* Usage Fault Handler */
void WEAK SVC_Handler(void); /* SVCall Handler */
void WEAK DebugMon_Handler(void); /* Debug Monitor Handler */
void WEAK PendSV_Handler(void); /* PendSV Handler */
void WEAK SysTick_Handler(void); /* SysTick Handler */
/* External interrupt vector handler */
void WEAK WDT_IRQHandler(void); /* Watchdog Timer */
void WEAK TIMER0_IRQHandler(void); /* Timer0 */
void WEAK TIMER1_IRQHandler(void); /* Timer1 */
void WEAK TIMER2_IRQHandler(void); /* Timer2 */
void WEAK TIMER3_IRQHandler(void); /* Timer3 */
void WEAK UART0_IRQHandler(void); /* UART0 */
void WEAK UART1_IRQHandler(void); /* UART1 */
void WEAK UART2_IRQHandler(void); /* UART2 */
void WEAK UART3_IRQHandler(void); /* UART3 */
void WEAK PWM1_IRQHandler(void); /* PWM1 */
void WEAK I2C0_IRQHandler(void); /* I2C0 */
void WEAK I2C1_IRQHandler(void); /* I2C1 */
void WEAK I2C2_IRQHandler(void); /* I2C2 */
void WEAK SPI_IRQHandler(void); /* SPI */
void WEAK SSP0_IRQHandler(void); /* SSP0 */
void WEAK SSP1_IRQHandler(void); /* SSP1 */
void WEAK PLL0_IRQHandler(void); /* PLL0 (Main PLL) */
void WEAK RTC_IRQHandler(void); /* Real Time Clock */
void WEAK EINT0_IRQHandler(void); /* External Interrupt 0 */
void WEAK EINT1_IRQHandler(void); /* External Interrupt 1 */
void WEAK EINT2_IRQHandler(void); /* External Interrupt 2 */
void WEAK EINT3_IRQHandler(void); /* External Interrupt 3 */
void WEAK ADC_IRQHandler(void); /* A/D Converter */
void WEAK BOD_IRQHandler(void); /* Brown Out Detect */
void WEAK USB_IRQHandler(void); /* USB */
void WEAK CAN_IRQHandler(void); /* CAN */
void WEAK DMA_IRQHandler(void); /* GP DMA */
void WEAK I2S_IRQHandler(void); /* I2S */
void WEAK ENET_IRQHandler(void); /* Ethernet */
void WEAK RIT_IRQHandler(void); /* Repetitive Interrupt Timer */
void WEAK MCPWM_IRQHandler(void); /* Motor Control PWM */
void WEAK QEI_IRQHandler(void); /* Quadrature Encoder Interface */
void WEAK PLL1_IRQHandler(void); /* PLL1 (USB PLL) */
/* Exported constants --------------------------------------------------------*/
extern unsigned long __etext;
extern unsigned long __sidata; /* start address for the initialization values of the .data section. defined in linker script */
extern unsigned long __data_start__; /* start address for the .data section. defined in linker script */
extern unsigned long __data_end__; /* end address for the .data section. defined in linker script */
extern unsigned long __bss_start__; /* start address for the .bss section. defined in linker script */
extern unsigned long __bss_end__; /* end address for the .bss section. defined in linker script */
extern void _estack; /* init value for the stack pointer. defined in linker script */
/* function prototypes ------------------------------------------------------*/
void Reset_Handler(void) __attribute__((__interrupt__));
extern void _CPUregTestPOST (void);
/******************************************************************************
*
* The minimal vector table for a Cortex M3. Note that the proper constructs
* must be placed on this to ensure that it ends up at physical address
* 0x0000.0000.
*
******************************************************************************/
#define STACK_SIZE 0x00000200
__attribute__ ((section(".stackarea")))
/* static */ unsigned long pulStack[STACK_SIZE];
__attribute__ ((section(".isr_vector")))
void (* const g_pfnVectors[])(void) =
{
/* &_estack, // The initial stack pointer */
(void (*)(void))((unsigned long)pulStack + sizeof(pulStack)), // The initial stack pointer
Reset_Handler, /* Reset Handler */
NMI_Handler, /* NMI Handler */
HardFault_Handler, /* Hard Fault Handler */
MemManage_Handler, /* MPU Fault Handler */
BusFault_Handler, /* Bus Fault Handler */
UsageFault_Handler, /* Usage Fault Handler */
0, /* Reserved */
0, /* Reserved */
0, /* Reserved */
0, /* Reserved */
SVC_Handler, /* SVCall Handler */
DebugMon_Handler, /* Debug Monitor Handler */
0, /* Reserved */
PendSV_Handler, /* PendSV Handler */
SysTick_Handler, /* SysTick Handler */
// External Interrupts
WDT_IRQHandler, /* Watchdog Timer */
TIMER0_IRQHandler, /* Timer0 */
TIMER1_IRQHandler, /* Timer1 */
TIMER2_IRQHandler, /* Timer2 */
TIMER3_IRQHandler, /* Timer3 */
UART0_IRQHandler, /* UART0 */
UART1_IRQHandler, /* UART1 */
UART2_IRQHandler, /* UART2 */
UART3_IRQHandler, /* UART3 */
PWM1_IRQHandler, /* PWM1 */
I2C0_IRQHandler, /* I2C0 */
I2C1_IRQHandler, /* I2C1 */
I2C2_IRQHandler, /* I2C2 */
SPI_IRQHandler, /* SPI */
SSP0_IRQHandler, /* SSP0 */
SSP1_IRQHandler, /* SSP1 */
PLL0_IRQHandler, /* PLL0 (Main PLL) */
RTC_IRQHandler, /* Real Time Clock */
EINT0_IRQHandler, /* External Interrupt 0 */
EINT1_IRQHandler, /* External Interrupt 1 */
EINT2_IRQHandler, /* External Interrupt 2 */
EINT3_IRQHandler, /* External Interrupt 3 */
ADC_IRQHandler, /* A/D Converter */
BOD_IRQHandler, /* Brown Out Detect */
USB_IRQHandler, /* USB */
CAN_IRQHandler, /* CAN */
DMA_IRQHandler, /* GP DMA */
I2S_IRQHandler, /* I2S */
ENET_IRQHandler, /* Ethernet */
RIT_IRQHandler, /* Repetitive Interrupt Timer */
MCPWM_IRQHandler, /* Motor Control PWM */
QEI_IRQHandler, /* Quadrature Encoder Interface */
PLL1_IRQHandler, /* PLL1 (USB PLL) */
};
/*******************************************************************************
* Function Name : Reset_Handler
* Description : This is the code that gets called when the processor first starts execution
* following a reset event. Only the absolutely necessary set is performed,
* after which the application supplied main() routine is called.
* Input :
* Output :
* Return :
*******************************************************************************/
void Reset_Handler(void)
{
unsigned long *pulSrc, *pulDest;
/*
* This used for cleaning AHBRAM0 section
*/
#if 0
for (pulDest = ((unsigned long *)AHBRAM0_BASE); \
pulDest < ((unsigned long *)(AHBRAM0_BASE + AHBRAM0_SIZE)); \
pulDest++){
*(pulDest++) = 0;
}
#endif
/*
* This used for cleaning AHBRAM1 section
*/
#if 0
for (pulDest = ((unsigned long *)AHBRAM1_BASE); \
pulDest < ((unsigned long *)(AHBRAM1_BASE + AHBRAM1_SIZE)); \
pulDest++){
*(pulDest++) = 0;
}
#endif
/*
* Copy the data segment initializers from flash to SRAM in ROM mode
*/
#if (__RAM_MODE__==0)
pulSrc = &__sidata;
for(pulDest = &__data_start__; pulDest < &__data_end__; )
{
*(pulDest++) = *(pulSrc++);
}
#endif
/*
* Zero fill the bss segment.
*/
for(pulDest = &__bss_start__; pulDest < &__bss_end__; )
{
*(pulDest++) = 0;
}
/*
* Call IEC60335 CPU register tests POST
*/
// __ASM volatile ("bl _CPUregTestPOST \t\n");
/*
* Call the application's entry point.
*/
board_init();
kernel_init();
}
/*****************************************************************************
*
* Provide weak aliases for each Exception handler to the default_handler.
* As they are weak aliases, any function with the same name will override
* this definition.
*
****************************************************************************/
#pragma weak MemManage_Handler = default_handler /* MPU Fault Handler */
#pragma weak BusFault_Handler = default_handler /* Bus Fault Handler */
#pragma weak UsageFault_Handler = default_handler /* Usage Fault Handler */
#pragma weak SVC_Handler = default_handler /* SVCall Handler */
#pragma weak DebugMon_Handler = default_handler /* Debug Monitor Handler */
#pragma weak PendSV_Handler = default_handler /* PendSV Handler */
#pragma weak SysTick_Handler = default_handler /* SysTick Handler */
/* External interrupt vector handler */
#pragma weak WDT_IRQHandler = default_handler /* Watchdog Timer */
#pragma weak TIMER0_IRQHandler = default_handler /* Timer0 */
#pragma weak TIMER1_IRQHandler = default_handler /* Timer1 */
#pragma weak TIMER2_IRQHandler = default_handler /* Timer2 */
#pragma weak TIMER3_IRQHandler = default_handler /* Timer3 */
#pragma weak UART0_IRQHandler = default_handler /* UART0 */
#pragma weak UART1_IRQHandler = default_handler /* UART1 */
#pragma weak UART2_IRQHandler = default_handler /* UART2 */
#pragma weak UART3_IRQHandler = default_handler /* UART3 */
#pragma weak PWM1_IRQHandler = default_handler /* PWM1 */
#pragma weak I2C0_IRQHandler = default_handler /* I2C0 */
#pragma weak I2C1_IRQHandler = default_handler /* I2C1 */
#pragma weak I2C2_IRQHandler = default_handler /* I2C2 */
#pragma weak SPI_IRQHandler = default_handler /* SPI */
#pragma weak SSP0_IRQHandler = default_handler /* SSP0 */
#pragma weak SSP1_IRQHandler = default_handler /* SSP1 */
#pragma weak PLL0_IRQHandler = default_handler /* PLL0 (Main PLL) */
#pragma weak RTC_IRQHandler = default_handler /* Real Time Clock */
#pragma weak EINT0_IRQHandler = default_handler /* External Interrupt 0 */
#pragma weak EINT1_IRQHandler = default_handler /* External Interrupt 1 */
#pragma weak EINT2_IRQHandler = default_handler /* External Interrupt 2 */
#pragma weak EINT3_IRQHandler = default_handler /* External Interrupt 3 */
#pragma weak ADC_IRQHandler = default_handler /* A/D Converter */
#pragma weak BOD_IRQHandler = default_handler /* Brown Out Detect */
#pragma weak USB_IRQHandler = default_handler /* USB */
#pragma weak CAN_IRQHandler = default_handler /* CAN */
#pragma weak DMA_IRQHandler = default_handler /* GP DMA */
#pragma weak I2S_IRQHandler = default_handler /* I2S */
#pragma weak ENET_IRQHandler = default_handler /* Ethernet */
#pragma weak RIT_IRQHandler = default_handler /* Repetitive Interrupt Timer */
#pragma weak MCPWM_IRQHandler = default_handler /* Motor Control PWM */
#pragma weak QEI_IRQHandler = default_handler /* Quadrature Encoder Interface */
#pragma weak PLL1_IRQHandler = default_handler /* PLL1 (USB PLL) */
/*****************************************************************************
*
* This is the code that gets called when the processor receives an unexpected
* interrupt. This simply enters an infinite loop, preserving the system state
* for examination by a debugger.
*
****************************************************************************/
void default_handler(void) {
/* Go into an infinite loop. */
while (1) {
}
}

231
cpu/lpc1768/syscalls.c Normal file
View File

@ -0,0 +1,231 @@
/**
* Syscall implementation for NXP LPC1768
*
* Copyright (C) 2013 Oliver Hahm <oliver.hahm@inria.fr>
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup lpc1768
* @{
* @file syscalls.c
* @author Oliver Hahm <oliver.hahm@inria.fr>
* @author Alaeddine Weslati <alaeddine.weslati@inria.fr>
* @}
*/
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/unistd.h>
#include <stdint.h>
#include "kernel.h"
#include "irq.h"
/**
* @name Heaps (defined in linker script)
* @{
*/
#define NUM_HEAPS 1
#define DEBUG_SYSCALLS 0
#if DEBUG_SYSCALLS
#define PRINTF(...) printf(__VA_ARGS__)
#else
#define PRINTF(...)
#endif
extern uintptr_t __heap_start; ///< start of heap memory space
extern uintptr_t __heap_max; ///< maximum for end of heap memory space
/// current position in heap
static caddr_t heap[NUM_HEAPS] = {(caddr_t)&__heap_start};
/// maximum position in heap
static const caddr_t heap_max[NUM_HEAPS] = {(caddr_t)&__heap_max};
// start position in heap
static const caddr_t heap_start[NUM_HEAPS] = {(caddr_t)&__heap_start};
// current heap in use
volatile static uint8_t iUsedHeap = 0;
/** @} */
/*-----------------------------------------------------------------------------------*/
void heap_stats(void) {
for(int i = 0; i < NUM_HEAPS; i++)
printf("# heap %i: %p -- %p -> %p (%li of %li free)\n", i, heap_start[i], heap[i], heap_max[i],
(uint32_t)heap_max[i] - (uint32_t)heap[i], (uint32_t)heap_max[i] - (uint32_t)heap_start[i]);
}
/*-----------------------------------------------------------------------------------*/
void __assert_func(const char *file, int line, const char *func, const char *failedexpr)
{
printf("#! assertion %s failed\n\t%s() in %s:%u\n", failedexpr, func, file, line );
_exit(3);
}
/*-----------------------------------------------------------------------------------*/
void __assert(const char *file, int line, const char *failedexpr)
{
__assert_func(file, line, "?", failedexpr);
}
/*-----------------------------------------------------------------------------------*/
caddr_t _sbrk_r(struct _reent *r, size_t incr)
{
if(incr < 0)
{
puts("[syscalls] Negative Values for _sbrk_r are not supported");
r->_errno = ENOMEM;
return NULL;
}
uint32_t cpsr = disableIRQ();
/* check all heaps for a chunk of the requested size */
for( ; iUsedHeap < NUM_HEAPS; iUsedHeap++ ) {
caddr_t new_heap = heap[iUsedHeap] + incr;
if( new_heap <= heap_max[iUsedHeap] ) {
caddr_t prev_heap = heap[iUsedHeap];
heap[iUsedHeap] = new_heap;
r->_errno = 0;
restoreIRQ(cpsr);
return prev_heap;
}
}
restoreIRQ(cpsr);
r->_errno = ENOMEM;
return NULL;
}
/*---------------------------------------------------------------------------*/
int _isatty_r(struct _reent *r, int fd)
{
r->_errno = 0;
if( fd == STDOUT_FILENO || fd == STDERR_FILENO )
return 1;
else
return 0;
}
/*---------------------------------------------------------------------------*/
_off_t _lseek_r(struct _reent *r, int fd, _off_t pos, int whence)
{
_off_t result = -1;
PRINTF("lseek [%i] pos %li whence %i\n", fd, pos, whence);
r->_errno = ENODEV;
PRINTF("lseek returned %li (0 is success)\n", result);
return result;
}
/*---------------------------------------------------------------------------*/
int _open_r(struct _reent *r, const char *name, int mode)
{
int ret = -1;
PRINTF("open '%s' mode %#x\n", name, mode);
r->_errno = ENODEV; // no such device
PRINTF("open [%i] errno %i\n", ret, r->_errno);
return ret;
}
/*---------------------------------------------------------------------------*/
int _stat_r(struct _reent *r, char *name, struct stat *st)
{
int ret = -1;
PRINTF("_stat_r '%s' \n", name);
r->_errno = ENODEV; // no such device
PRINTF("_stat_r [%i] errno %i\n", ret, r->_errno);
return ret;
}
/*---------------------------------------------------------------------------*/
int _fstat_r(struct _reent *r, int fd, struct stat * st)
{
int ret = -1;
r->_errno = 0;
memset(st, 0, sizeof(*st));
if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
st->st_mode = S_IFCHR;
ret = 0;
}
else {
r->_errno = ENODEV;
}
return ret;
}
/*---------------------------------------------------------------------------*/
int _write_r(struct _reent *r, int fd, const void *data, unsigned int count)
{
int result = EOF;
r->_errno = EBADF;
switch(fd) {
case STDOUT_FILENO:
case STDERR_FILENO:
{
//FIXME impl fw_puts
//char* chars = (char*) data;
for(int i = 0;i < count;i++) {
//USART_SendData(USART2, chars[i]);
/* Loop until the end of transmission */
//while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET){}
}
return count;
//result = fw_puts((char*)data, count);
}
break;
default:
break;
}
return result;
}
/*---------------------------------------------------------------------------*/
int _read_r(struct _reent *r, int fd, void *buffer, unsigned int count)
{
int result = -1;
r->_errno = EBADF;
return result;
}
/*---------------------------------------------------------------------------*/
int _close_r(struct _reent *r, int fd)
{
int ret = -1;
r->_errno = EBADF;
return ret;
}
/*---------------------------------------------------------------------------*/
int _unlink_r(struct _reent *r, char* path)
{
int ret = -1;
r->_errno = ENODEV;
return ret;
}
/*---------------------------------------------------------------------------*/
void _exit(int n)
{
printf("#! exit %i: resetting\n", n);
//FIXME write out all peripherie buffers stdout flush
NVIC_SystemReset();
while(1);
}
/*---------------------------------------------------------------------------*/
int _getpid(void)
{
return active_thread->pid;
}
/*---------------------------------------------------------------------------*/
int _kill_r(struct _reent *r, int pid, int sig)
{
/* not implemented */
r->_errno = ESRCH; // no such process
return -1;
}
/*---------------------------------------------------------------------------*/
void _init(void){}
void _fini(void){}