mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-25 06:23:53 +01:00
Merge pull request #1191 from haukepetersen/board_stm32f4discovery
board: Initial import of stm32f4discovery board
This commit is contained in:
commit
86eb5c420e
4
boards/stm32f4discovery/Makefile
Normal file
4
boards/stm32f4discovery/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
# tell the Makefile.base which module to build
|
||||
MODULE = $(BOARD)_base
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
47
boards/stm32f4discovery/Makefile.include
Normal file
47
boards/stm32f4discovery/Makefile.include
Normal file
@ -0,0 +1,47 @@
|
||||
# define the cpu used by the stm32f4-discovery board
|
||||
export CPU = stm32f4
|
||||
export CPU_MODEL = stm32f407vg
|
||||
|
||||
#define the default port depending on the host OS
|
||||
OS := $(shell uname)
|
||||
ifeq ($(OS),Linux)
|
||||
PORT ?= /dev/ttyUSB0
|
||||
else ifeq ($(OS),Darwin)
|
||||
PORT ?= $(shell ls -1 /dev/tty.SLAB_USBtoUART* | head -n 1)
|
||||
else
|
||||
$(info CAUTION: No flash tool for your host system found!)
|
||||
# TODO: add support for windows as host platform
|
||||
endif
|
||||
export PORT
|
||||
|
||||
# define tools used for building the project
|
||||
export PREFIX = arm-none-eabi-
|
||||
export CC = $(PREFIX)gcc
|
||||
export AR = $(PREFIX)ar
|
||||
export AS = $(PREFIX)as
|
||||
export LINK = $(PREFIX)gcc
|
||||
export SIZE = $(PREFIX)size
|
||||
export OBJCOPY = $(PREFIX)objcopy
|
||||
export TERMPROG = $(RIOTBASE)/dist/tools/pyterm/pyterm.py
|
||||
export FLASHER = st-flash
|
||||
export DEBUGGER = $(RIOTBOARD)/$(BOARD)/dist/debug.sh
|
||||
|
||||
# define build specific options
|
||||
CPU_USAGE = -mcpu=cortex-m4
|
||||
FPU_USAGE = -mfloat-abi=hard -mfpu=fpv4-sp-d16
|
||||
export CFLAGS += -ggdb -g3 -std=gnu99 -Os -Wall -Wstrict-prototypes $(CPU_USAGE) $(FPU_USAGE) -mlittle-endian -mthumb -mthumb-interwork -nostartfiles
|
||||
export CFLAGS += -ffunction-sections -fdata-sections -fno-builtin
|
||||
export ASFLAGS += -ggdb -g3 $(CPU_USAGE) $(FPU_USAGE) -mlittle-endian
|
||||
export LINKFLAGS += -g3 -ggdb -std=gnu99 $(CPU_USAGE) $(FPU_USAGE) -mlittle-endian -static -lgcc -mthumb -mthumb-interwork -nostartfiles
|
||||
export LINKFLAGS += -T$(LINKERSCRIPT)
|
||||
export OFLAGS = -O binary
|
||||
export FFLAGS = write bin/$(BOARD)/$(APPLICATION).hex 0x8000000
|
||||
export DEBUGGER_FLAGS = $(RIOTBOARD)/$(BOARD)/dist/gdb.conf $(BINDIR)/$(APPLICATION).elf
|
||||
|
||||
# use newLib nano-specs if available
|
||||
ifeq ($(shell $(LINK) -specs=nano.specs -E - 2>/dev/null >/dev/null </dev/null ; echo $$?),0)
|
||||
export LINKFLAGS += -specs=nano.specs -lc -lnosys
|
||||
endif
|
||||
|
||||
# export board specific includes to the global includes-listing
|
||||
export INCLUDES += -I$(RIOTBOARD)/$(BOARD)/include
|
||||
63
boards/stm32f4discovery/board.c
Normal file
63
boards/stm32f4discovery/board.c
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup board_stm32f4discovery
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Board specific implementations for the STM32F4Discovery evaluation board
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "board.h"
|
||||
|
||||
static void leds_init(void);
|
||||
|
||||
void board_init(void)
|
||||
{
|
||||
/* initialize the boards LEDs, this is done first for debugging purposes */
|
||||
leds_init();
|
||||
|
||||
/* initialize the CPU */
|
||||
cpu_init();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the boards on-board LEDs (LD3 and LD4)
|
||||
*
|
||||
* The LED initialization is hard-coded in this function. As the LEDs are soldered
|
||||
* onto the board they are fixed to their CPU pins.
|
||||
*
|
||||
* The LEDs are connected to the following pins:
|
||||
* - LD3: PD13
|
||||
* - LD4: PD12
|
||||
* - LD5: PD14
|
||||
* - LD6: PD15
|
||||
*/
|
||||
static void leds_init(void)
|
||||
{
|
||||
/* enable clock for port GPIOD */
|
||||
RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
|
||||
|
||||
/* configure pins as general outputs */
|
||||
LED_PORT->MODER &= ~(0xff000000);
|
||||
LED_PORT->MODER |= 0x55000000;
|
||||
/* set output speed high-speed */
|
||||
LED_PORT->OSPEEDR |= 0xff000000;
|
||||
/* set output type to push-pull */
|
||||
LED_PORT->OTYPER &= ~(0xf000);
|
||||
/* disable pull resistors */
|
||||
LED_PORT->PUPDR &= ~(0xff000000);
|
||||
|
||||
/* turn all LEDs off */
|
||||
LED_PORT->BSRRH = 0xf000;
|
||||
}
|
||||
4
boards/stm32f4discovery/dist/debug.sh
vendored
Executable file
4
boards/stm32f4discovery/dist/debug.sh
vendored
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Debugging $1"
|
||||
arm-none-eabi-gdb -tui -command=$1 $2
|
||||
1
boards/stm32f4discovery/dist/gdb.conf
vendored
Normal file
1
boards/stm32f4discovery/dist/gdb.conf
vendored
Normal file
@ -0,0 +1 @@
|
||||
tar extended-remote :4242
|
||||
88
boards/stm32f4discovery/include/board.h
Normal file
88
boards/stm32f4discovery/include/board.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup board_stm32f4discovery STM32F4Discovery
|
||||
* @ingroup boards
|
||||
* @brief Board specific files for the STM32F4Discovery board
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Board specific definitions for the STM32F4Discovery evaluation board
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef __BOARD_H
|
||||
#define __BOARD_H
|
||||
|
||||
#include "cpu.h"
|
||||
#include "periph_conf.h"
|
||||
|
||||
/**
|
||||
* Define the nominal CPU core clock in this board
|
||||
*/
|
||||
#define F_CPU CLOCK_CORECLOCK
|
||||
|
||||
/**
|
||||
* @name Assign the hardware timer
|
||||
*/
|
||||
#define HW_TIMER TIMER_0
|
||||
|
||||
/**
|
||||
* @name Define UART device and baudrate for stdio
|
||||
* @{
|
||||
*/
|
||||
#define STDIO UART_0
|
||||
#define STDIO_BAUDRATE (115200U)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name LED pin definitions
|
||||
* @{
|
||||
*/
|
||||
#define LED_PORT GPIOD
|
||||
#define LD3_PIN (1 << 13)
|
||||
#define LD4_PIN (1 << 12)
|
||||
#define LD5_PIN (1 << 14)
|
||||
#define LD6_PIN (1 << 15)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Macros for controlling the on-board LEDs.
|
||||
* @{
|
||||
*/
|
||||
#define LD3_ON (LED_PORT->BSRRL = LD3_PIN)
|
||||
#define LD3_OFF (LED_PORT->BSRRH = LD3_PIN)
|
||||
#define LD3_TOGGLE (LED_PORT->ODR ^= LD3_PIN)
|
||||
#define LD4_ON (LED_PORT->BSRRL = LD4_PIN)
|
||||
#define LD4_OFF (LED_PORT->BSRRH = LD4_PIN)
|
||||
#define LD4_TOGGLE (LED_PORT->ODR ^= LD4_PIN)
|
||||
#define LD5_ON (LED_PORT->BSRRL = LD5_PIN)
|
||||
#define LD5_OFF (LED_PORT->BSRRH = LD5_PIN)
|
||||
#define LD5_TOGGLE (LED_PORT->ODR ^= LD5_PIN)
|
||||
#define LD6_ON (LED_PORT->BSRRL = LD6_PIN)
|
||||
#define LD6_OFF (LED_PORT->BSRRH = LD6_PIN)
|
||||
#define LD6_TOGGLE (LED_PORT->ODR ^= LD6_PIN)
|
||||
|
||||
/* for compatability to other boards */
|
||||
#define LED_GREEN_ON LD4_ON
|
||||
#define LED_GREEN_OFF LD4_OFF
|
||||
#define LED_GREEN_TOGGLE LD4_TOGGLE
|
||||
#define LED_RED_ON LD5_ON
|
||||
#define LED_RED_OFF LD5_OFF
|
||||
#define LED_RED_TOGGLE LD5_TOGGLE
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Initialize board specific hardware, including clock, LEDs and std-IO
|
||||
*/
|
||||
void board_init(void);
|
||||
|
||||
#endif /** __BOARD_H */
|
||||
/** @} */
|
||||
386
boards/stm32f4discovery/include/periph_conf.h
Normal file
386
boards/stm32f4discovery/include/periph_conf.h
Normal file
@ -0,0 +1,386 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup board_stm32f4discovery
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @name Peripheral MCU configuration for the STM32F4discovery board
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef __PERIPH_CONF_H
|
||||
#define __PERIPH_CONF_H
|
||||
|
||||
/**
|
||||
* @name Clock system configuration
|
||||
* @{
|
||||
*/
|
||||
#define CLOCK_HSE (8000000U) /* external oscillator */
|
||||
#define CLOCK_CORECLOCK (168000000U) /* desired core clock frequency */
|
||||
|
||||
/* the actual PLL values are automatically generated */
|
||||
#define CLOCK_PLL_M (CLOCK_HSE / 1000000)
|
||||
#define CLOCK_PLL_N ((CLOCK_CORECLOCK / 1000000) * 2)
|
||||
#define CLOCK_PLL_P (2U)
|
||||
#define CLOCK_PLL_Q (CLOCK_PLL_N / 48)
|
||||
#define CLOCK_AHB_DIV RCC_CFGR_HPRE_DIV1
|
||||
#define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV2
|
||||
#define CLOCK_APB1_DIV RCC_CFGR_PPRE1_DIV4
|
||||
#define CLOCK_FLASH_LATENCY FLASH_ACR_LATENCY_5WS
|
||||
/** @} */
|
||||
|
||||
|
||||
/**
|
||||
* @name Timer configuration
|
||||
* @{
|
||||
*/
|
||||
#define TIMER_NUMOF (2U)
|
||||
#define TIMER_0_EN 1
|
||||
#define TIMER_1_EN 1
|
||||
#define TIMER_IRQ_PRIO 1
|
||||
|
||||
/* Timer 0 configuration */
|
||||
#define TIMER_0_DEV TIM2
|
||||
#define TIMER_0_CHANNELS 4
|
||||
#define TIMER_0_PRESCALER (83U)
|
||||
#define TIMER_0_MAX_VALUE (0xffffffff)
|
||||
#define TIMER_0_CLKEN() (RCC->APB1ENR |= RCC_APB1ENR_TIM2EN)
|
||||
#define TIMER_0_ISR isr_tim2
|
||||
#define TIMER_0_IRQ_CHAN TIM2_IRQn
|
||||
|
||||
/* Timer 1 configuration */
|
||||
#define TIMER_1_DEV TIM5
|
||||
#define TIMER_1_CHANNELS 4
|
||||
#define TIMER_1_PRESCALER (83U)
|
||||
#define TIMER_1_MAX_VALUE (0xffffffff)
|
||||
#define TIMER_1_CLKEN() (RCC->APB1ENR |= RCC_APB1ENR_TIM5EN)
|
||||
#define TIMER_1_ISR isr_tim5
|
||||
#define TIMER_1_IRQ_CHAN TIM5_IRQn
|
||||
/** @} */
|
||||
|
||||
|
||||
/**
|
||||
* @name UART configuration
|
||||
* @{
|
||||
*/
|
||||
#define UART_NUMOF (2U)
|
||||
#define UART_0_EN 1
|
||||
#define UART_1_EN 1
|
||||
#define UART_IRQ_PRIO 1
|
||||
#define UART_CLK (14000000U) /* UART clock runs with 14MHz */
|
||||
|
||||
/* UART 0 device configuration */
|
||||
#define UART_0_DEV USART2
|
||||
#define UART_0_CLKEN() (RCC->APB1ENR |= RCC_APB1ENR_USART2EN)
|
||||
#define UART_0_CLK (42000000) /* UART clock runs with 42MHz (F_CPU / 4) */
|
||||
#define UART_0_IRQ_CHAN USART2_IRQn
|
||||
#define UART_0_ISR isr_usart2
|
||||
/* UART 0 pin configuration */
|
||||
#define UART_0_PORT_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN)
|
||||
#define UART_0_PORT GPIOA
|
||||
#define UART_0_TX_PIN 2
|
||||
#define UART_0_RX_PIN 3
|
||||
#define UART_0_AF 7
|
||||
|
||||
/* UART 1 device configuration */
|
||||
#define UART_1_DEV USART3
|
||||
#define UART_1_CLKEN() (RCC->APB1ENR |= RCC_APB1ENR_USART3EN)
|
||||
#define UART_1_CLK (42000000) /* UART clock runs with 42MHz (F_CPU / 4) */
|
||||
#define UART_1_IRQ_CHAN USART3_IRQn
|
||||
#define UART_1_ISR isr_usart3
|
||||
/* UART 1 pin configuration */
|
||||
#define UART_1_PORT_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN)
|
||||
#define UART_1_PORT GPIOD
|
||||
#define UART_1_TX_PIN 8
|
||||
#define UART_1_RX_PIN 9
|
||||
#define UART_1_AF 7
|
||||
/** @} */
|
||||
|
||||
|
||||
/**
|
||||
* @name ADC configuration
|
||||
* @{
|
||||
*/
|
||||
#define ADC_NUMOF (0U)
|
||||
#define ADC_0_EN 0
|
||||
#define ADC_1_EN 0
|
||||
|
||||
/* ADC 0 configuration */
|
||||
#define ADC_0_DEV ADC1 /* TODO !!!!!!! */
|
||||
#define ADC_0_SAMPLE_TIMER
|
||||
/* ADC 0 channel 0 pin config */
|
||||
#define ADC_0_C0_PORT
|
||||
#define ADC_0_C0_PIN
|
||||
#define ADC_0_C0_CLKEN()
|
||||
#define ADC_0_C0_AFCFG()
|
||||
/* ADC 0 channel 1 pin config */
|
||||
#define ADC_0_C1_PORT
|
||||
#define ADC_0_C1_PIN
|
||||
#define ADC_0_C1_CLKEN()
|
||||
#define ADC_0_C1_AFCFG()
|
||||
/* ADC 0 channel 2 pin config */
|
||||
#define ADC_0_C2_PORT
|
||||
#define ADC_0_C2_PIN
|
||||
#define ADC_0_C2_CLKEN()
|
||||
#define ADC_0_C2_AFCFG()
|
||||
/* ADC 0 channel 3 pin config */
|
||||
#define ADC_0_C3_PORT
|
||||
#define ADC_0_C3_PIN
|
||||
#define ADC_0_C3_CLKEN()
|
||||
#define ADC_0_C3_AFCFG()
|
||||
|
||||
/* ADC 0 configuration */
|
||||
#define ADC_1_DEV ADC2 /* TODO !!!!!!! */
|
||||
#define ADC_1_SAMPLE_TIMER
|
||||
/* ADC 0 channel 0 pin config */
|
||||
#define ADC_1_C0_PORT
|
||||
#define ADC_1_C0_PIN
|
||||
#define ADC_1_C0_CLKEN()
|
||||
#define ADC_1_C0_AFCFG()
|
||||
/* ADC 0 channel 1 pin config */
|
||||
#define ADC_1_C1_PORT
|
||||
#define ADC_1_C1_PIN
|
||||
#define ADC_1_C1_CLKEN()
|
||||
#define ADC_1_C1_AFCFG()
|
||||
/* ADC 0 channel 2 pin config */
|
||||
#define ADC_1_C2_PORT
|
||||
#define ADC_1_C2_PIN
|
||||
#define ADC_1_C2_CLKEN()
|
||||
#define ADC_1_C2_AFCFG()
|
||||
/* ADC 0 channel 3 pin config */
|
||||
#define ADC_1_C3_PORT
|
||||
#define ADC_1_C3_PIN
|
||||
#define ADC_1_C3_CLKEN()
|
||||
#define ADC_1_C3_AFCFG()
|
||||
/** @} */
|
||||
|
||||
|
||||
/**
|
||||
* @name PWM configuration
|
||||
* @{
|
||||
*/
|
||||
#define PWM_NUMOF (0U) /* TODO !!!!!!! */
|
||||
#define PWM_0_EN 0
|
||||
#define PWM_1_EN 0
|
||||
|
||||
/* PWM 0 device configuration */
|
||||
#define PWM_0_DEV TIM1
|
||||
#define PWM_0_CHANNELS 4
|
||||
/* PWM 0 pin configuration */
|
||||
#define PWM_0_PORT
|
||||
#define PWM_0_PINS
|
||||
#define PWM_0_PORT_CLKEN()
|
||||
#define PWM_0_CH1_AFCFG()
|
||||
#define PWM_0_CH2_AFCFG()
|
||||
#define PWM_0_CH3_AFCFG()
|
||||
#define PWM_0_CH4_AFCFG()
|
||||
|
||||
/* PWM 1 device configuration */
|
||||
#define PWM_1_DEV TIM3
|
||||
#define PWM_1_CHANNELS 4
|
||||
/* PWM 1 pin configuration */
|
||||
#define PWM_1_PORT
|
||||
#define PWM_1_PINS
|
||||
#define PWM_1_PORT_CLKEN()
|
||||
#define PWM_1_CH1_AFCFG()
|
||||
#define PWM_1_CH2_AFCFG()
|
||||
#define PWM_1_CH3_AFCFG()
|
||||
#define PWM_1_CH4_AFCFG()
|
||||
/** @} */
|
||||
|
||||
|
||||
/**
|
||||
* @name SPI configuration
|
||||
* @{
|
||||
*/
|
||||
#define SPI_NUMOF (0U) /* TODO !!!!!!! */
|
||||
#define SPI_0_EN 0
|
||||
#define SPI_1_EN 0
|
||||
|
||||
/* SPI 0 device config */
|
||||
#define SPI_0_DEV
|
||||
#define SPI_0_CLKEN()
|
||||
#define SPI_0_IRQ
|
||||
#define SPI_0_IRQ_HANDLER
|
||||
#define SPI_0_IRQ_PRIO
|
||||
/* SPI 1 pin configuration */
|
||||
#define SPI_0_PORT
|
||||
#define SPI_0_PINS
|
||||
#define SPI_1_PORT_CLKEN()
|
||||
#define SPI_1_SCK_AFCFG()
|
||||
#define SPI_1_MISO_AFCFG()
|
||||
#define SPI_1_MOSI_AFCFG()
|
||||
|
||||
/* SPI 1 device config */
|
||||
#define SPI_1_DEV
|
||||
#define SPI_1_CLKEN()
|
||||
#define SPI_1_IRQ
|
||||
#define SPI_1_IRQ_HANDLER
|
||||
#define SPI_1_IRQ_PRIO
|
||||
/* SPI 1 pin configuration */
|
||||
#define SPI_1_PORT
|
||||
#define SPI_1_PINS
|
||||
#define SPI_1_PORT_CLKEN()
|
||||
#define SPI_1_SCK_AFCFG()
|
||||
#define SPI_1_MISO_AFCFG()
|
||||
#define SPI_1_MOSI_AFCFG()
|
||||
/** @} */
|
||||
|
||||
|
||||
/**
|
||||
* @name I2C configuration
|
||||
* @{
|
||||
*/
|
||||
#define I2C_NUMOF (0U) /* TODO !!!!!!! */
|
||||
#define I2C_0_EN 0
|
||||
#define I2C_0_EN 0
|
||||
|
||||
/* SPI 0 device configuration */
|
||||
#define I2C_0_DEV
|
||||
#define I2C_0_CLKEN()
|
||||
#define I2C_0_ISR
|
||||
#define I2C_0_IRQ
|
||||
#define I2C_0_IRQ_PRIO
|
||||
/* SPI 0 pin configuration */
|
||||
#define I2C_0_PORT
|
||||
#define I2C_0_PINS
|
||||
#define I2C_0_PORT_CLKEN()
|
||||
#define I2C_0_SCL_AFCFG()
|
||||
#define I2C_0_SDA_AFCFG()
|
||||
|
||||
/* SPI 1 device configuration */
|
||||
#define I2C_1_DEV
|
||||
#define I2C_1_CLKEN()
|
||||
#define I2C_1_ISR
|
||||
#define I2C_1_IRQ
|
||||
#define I2C_1_IRQ_PRIO
|
||||
/* SPI 1 pin configuration */
|
||||
#define I2C_1_PORT
|
||||
#define I2C_1_PINS
|
||||
#define I2C_1_PORT_CLKEN()
|
||||
#define I2C_1_SCL_AFCFG()
|
||||
#define I2C_1_SDA_AFCFG()
|
||||
/** @} */
|
||||
|
||||
|
||||
/**
|
||||
* @name GPIO configuration
|
||||
* @{
|
||||
*/
|
||||
#define GPIO_NUMOF 12
|
||||
#define GPIO_0_EN 1
|
||||
#define GPIO_1_EN 1
|
||||
#define GPIO_2_EN 1
|
||||
#define GPIO_3_EN 1
|
||||
#define GPIO_4_EN 1
|
||||
#define GPIO_5_EN 1
|
||||
#define GPIO_6_EN 1
|
||||
#define GPIO_7_EN 1
|
||||
#define GPIO_8_EN 1
|
||||
#define GPIO_9_EN 1
|
||||
#define GPIO_10_EN 1
|
||||
#define GPIO_11_EN 1
|
||||
#define GPIO_IRQ_PRIO 1
|
||||
|
||||
/* IRQ config */
|
||||
#define GPIO_IRQ_0 GPIO_0 /* alternatively GPIO_1 could be used here */
|
||||
#define GPIO_IRQ_1 GPIO_2
|
||||
#define GPIO_IRQ_2 GPIO_3
|
||||
#define GPIO_IRQ_3 GPIO_4
|
||||
#define GPIO_IRQ_4 GPIO_5
|
||||
#define GPIO_IRQ_5 GPIO_6
|
||||
#define GPIO_IRQ_6 GPIO_7
|
||||
#define GPIO_IRQ_7 GPIO_8
|
||||
#define GPIO_IRQ_8 GPIO_9
|
||||
#define GPIO_IRQ_9 GPIO_10
|
||||
#define GPIO_IRQ_10 GPIO_11
|
||||
#define GPIO_IRQ_11 -1/* not configured */
|
||||
#define GPIO_IRQ_12 -1/* not configured */
|
||||
#define GPIO_IRQ_13 -1/* not configured */
|
||||
#define GPIO_IRQ_14 -1/* not configured */
|
||||
#define GPIO_IRQ_15 -1/* not configured */
|
||||
|
||||
/* GPIO channel 0 config */
|
||||
#define GPIO_0_PORT GPIOA /* Used for user button 1 */
|
||||
#define GPIO_0_PIN 0
|
||||
#define GPIO_0_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN)
|
||||
#define GPIO_0_EXTI_CFG() (SYSCFG->EXTICR[0] |= SYSCFG_EXTICR1_EXTI0_PA)
|
||||
#define GPIO_0_IRQ EXTI0_IRQn
|
||||
/* GPIO channel 1 config */
|
||||
#define GPIO_1_PORT GPIOE /* LIS302DL INT1 */
|
||||
#define GPIO_1_PIN 0
|
||||
#define GPIO_1_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN)
|
||||
#define GPIO_1_EXTI_CFG() (SYSCFG->EXTICR[0] |= SYSCFG_EXTICR1_EXTI0_PE)
|
||||
#define GPIO_1_IRQ EXTI0_IRQn
|
||||
/* GPIO channel 2 config */
|
||||
#define GPIO_2_PORT GPIOE /* LIS302DL INT2 */
|
||||
#define GPIO_2_PIN 1
|
||||
#define GPIO_2_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN)
|
||||
#define GPIO_2_EXTI_CFG() (SYSCFG->EXTICR[0] |= SYSCFG_EXTICR1_EXTI1_PE)
|
||||
#define GPIO_2_IRQ EXTI1_IRQn
|
||||
/* GPIO channel 3 config */
|
||||
#define GPIO_3_PORT GPIOE
|
||||
#define GPIO_3_PIN 2
|
||||
#define GPIO_3_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN)
|
||||
#define GPIO_3_EXTI_CFG() (SYSCFG->EXTICR[0] |= SYSCFG_EXTICR1_EXTI2_PE)
|
||||
#define GPIO_3_IRQ EXTI2_IRQn
|
||||
/* GPIO channel 4 config */
|
||||
#define GPIO_4_PORT GPIOE /* LIS302DL CS */
|
||||
#define GPIO_4_PIN 3
|
||||
#define GPIO_4_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN)
|
||||
#define GPIO_4_EXTI_CFG() (SYSCFG->EXTICR[0] |= SYSCFG_EXTICR1_EXTI3_PE)
|
||||
#define GPIO_4_IRQ EXTI3_IRQn
|
||||
/* GPIO channel 5 config */
|
||||
#define GPIO_5_PORT GPIOD /* CS43L22 RESET */
|
||||
#define GPIO_5_PIN 4
|
||||
#define GPIO_5_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN)
|
||||
#define GPIO_5_EXTI_CFG() (SYSCFG->EXTICR[1] |= SYSCFG_EXTICR2_EXTI4_PD)
|
||||
#define GPIO_5_IRQ EXTI4_IRQn
|
||||
/* GPIO channel 6 config */
|
||||
#define GPIO_6_PORT GPIOD /* LD8 */
|
||||
#define GPIO_6_PIN 5
|
||||
#define GPIO_6_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN)
|
||||
#define GPIO_6_EXTI_CFG() (SYSCFG->EXTICR[1] |= SYSCFG_EXTICR2_EXTI5_PD)
|
||||
#define GPIO_6_IRQ EXTI9_5_IRQn
|
||||
/* GPIO channel 7 config */
|
||||
#define GPIO_7_PORT GPIOD
|
||||
#define GPIO_7_PIN 6
|
||||
#define GPIO_7_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN)
|
||||
#define GPIO_7_EXTI_CFG() (SYSCFG->EXTICR[1] |= SYSCFG_EXTICR2_EXTI6_PD)
|
||||
#define GPIO_7_IRQ EXTI9_5_IRQn
|
||||
/* GPIO channel 8 config */
|
||||
#define GPIO_8_PORT GPIOD
|
||||
#define GPIO_8_PIN 7
|
||||
#define GPIO_8_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN)
|
||||
#define GPIO_8_EXTI_CFG() (SYSCFG->EXTICR[1] |= SYSCFG_EXTICR2_EXTI7_PD)
|
||||
#define GPIO_8_IRQ EXTI9_5_IRQn
|
||||
/* GPIO channel 9 config */
|
||||
#define GPIO_9_PORT GPIOA
|
||||
#define GPIO_9_PIN 8
|
||||
#define GPIO_9_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN)
|
||||
#define GPIO_9_EXTI_CFG() (SYSCFG->EXTICR[2] |= SYSCFG_EXTICR3_EXTI8_PA)
|
||||
#define GPIO_9_IRQ EXTI9_5_IRQn
|
||||
/* GPIO channel 10 config */
|
||||
#define GPIO_10_PORT GPIOA /* LD7 */
|
||||
#define GPIO_10_PIN 9
|
||||
#define GPIO_10_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN)
|
||||
#define GPIO_10_EXTI_CFG() (SYSCFG->EXTICR[2] |= SYSCFG_EXTICR3_EXTI9_PA)
|
||||
#define GPIO_10_IRQ EXTI9_5_IRQn
|
||||
/* GPIO channel 11 config */
|
||||
#define GPIO_11_PORT GPIOD
|
||||
#define GPIO_11_PIN 10
|
||||
#define GPIO_11_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN)
|
||||
#define GPIO_11_EXTI_CFG() (SYSCFG->EXTICR[2] |= SYSCFG_EXTICR3_EXTI10_PD)
|
||||
#define GPIO_11_IRQ EXTI15_10_IRQn
|
||||
/** @} */
|
||||
|
||||
#endif /* __PERIPH_CONF_H */
|
||||
/** @} */
|
||||
4
cpu/cortex-m4_common/Makefile
Normal file
4
cpu/cortex-m4_common/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
# define the module that is build
|
||||
MODULE = cortex-m4_common
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
2
cpu/cortex-m4_common/Makefile.include
Normal file
2
cpu/cortex-m4_common/Makefile.include
Normal file
@ -0,0 +1,2 @@
|
||||
# include module specific includes
|
||||
export INCLUDES += -I$(RIOTCPU)/cortex-m4_common/include
|
||||
32
cpu/cortex-m4_common/atomic_arch.c
Normal file
32
cpu/cortex-m4_common/atomic_arch.c
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_cortexm4_common
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Implementation of the kernels atomic interface
|
||||
*
|
||||
* @author Stefan Pfeiffer <stefan.pfeiffer@fu-berlin.de>
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "arch/atomic_arch.h"
|
||||
#include "irq.h"
|
||||
|
||||
unsigned int atomic_arch_set_return(unsigned int *to_set, unsigned int value)
|
||||
{
|
||||
disableIRQ();
|
||||
unsigned int old = *to_set;
|
||||
*to_set = value;
|
||||
enableIRQ();
|
||||
return old;
|
||||
}
|
||||
1772
cpu/cortex-m4_common/include/core_cm4.h
Normal file
1772
cpu/cortex-m4_common/include/core_cm4.h
Normal file
File diff suppressed because it is too large
Load Diff
673
cpu/cortex-m4_common/include/core_cm4_simd.h
Normal file
673
cpu/cortex-m4_common/include/core_cm4_simd.h
Normal file
@ -0,0 +1,673 @@
|
||||
/**************************************************************************//**
|
||||
* @file core_cm4_simd.h
|
||||
* @brief CMSIS Cortex-M4 SIMD Header File
|
||||
* @version V3.20
|
||||
* @date 25. February 2013
|
||||
*
|
||||
* @note
|
||||
*
|
||||
******************************************************************************/
|
||||
/* Copyright (c) 2009 - 2013 ARM LIMITED
|
||||
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of ARM nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
*
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef __CORE_CM4_SIMD_H
|
||||
#define __CORE_CM4_SIMD_H
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Hardware Abstraction Layer
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
/* ################### Compiler specific Intrinsics ########################### */
|
||||
/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
|
||||
Access to dedicated SIMD instructions
|
||||
@{
|
||||
*/
|
||||
|
||||
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
|
||||
/* ARM armcc specific functions */
|
||||
|
||||
/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/
|
||||
#define __SADD8 __sadd8
|
||||
#define __QADD8 __qadd8
|
||||
#define __SHADD8 __shadd8
|
||||
#define __UADD8 __uadd8
|
||||
#define __UQADD8 __uqadd8
|
||||
#define __UHADD8 __uhadd8
|
||||
#define __SSUB8 __ssub8
|
||||
#define __QSUB8 __qsub8
|
||||
#define __SHSUB8 __shsub8
|
||||
#define __USUB8 __usub8
|
||||
#define __UQSUB8 __uqsub8
|
||||
#define __UHSUB8 __uhsub8
|
||||
#define __SADD16 __sadd16
|
||||
#define __QADD16 __qadd16
|
||||
#define __SHADD16 __shadd16
|
||||
#define __UADD16 __uadd16
|
||||
#define __UQADD16 __uqadd16
|
||||
#define __UHADD16 __uhadd16
|
||||
#define __SSUB16 __ssub16
|
||||
#define __QSUB16 __qsub16
|
||||
#define __SHSUB16 __shsub16
|
||||
#define __USUB16 __usub16
|
||||
#define __UQSUB16 __uqsub16
|
||||
#define __UHSUB16 __uhsub16
|
||||
#define __SASX __sasx
|
||||
#define __QASX __qasx
|
||||
#define __SHASX __shasx
|
||||
#define __UASX __uasx
|
||||
#define __UQASX __uqasx
|
||||
#define __UHASX __uhasx
|
||||
#define __SSAX __ssax
|
||||
#define __QSAX __qsax
|
||||
#define __SHSAX __shsax
|
||||
#define __USAX __usax
|
||||
#define __UQSAX __uqsax
|
||||
#define __UHSAX __uhsax
|
||||
#define __USAD8 __usad8
|
||||
#define __USADA8 __usada8
|
||||
#define __SSAT16 __ssat16
|
||||
#define __USAT16 __usat16
|
||||
#define __UXTB16 __uxtb16
|
||||
#define __UXTAB16 __uxtab16
|
||||
#define __SXTB16 __sxtb16
|
||||
#define __SXTAB16 __sxtab16
|
||||
#define __SMUAD __smuad
|
||||
#define __SMUADX __smuadx
|
||||
#define __SMLAD __smlad
|
||||
#define __SMLADX __smladx
|
||||
#define __SMLALD __smlald
|
||||
#define __SMLALDX __smlaldx
|
||||
#define __SMUSD __smusd
|
||||
#define __SMUSDX __smusdx
|
||||
#define __SMLSD __smlsd
|
||||
#define __SMLSDX __smlsdx
|
||||
#define __SMLSLD __smlsld
|
||||
#define __SMLSLDX __smlsldx
|
||||
#define __SEL __sel
|
||||
#define __QADD __qadd
|
||||
#define __QSUB __qsub
|
||||
|
||||
#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \
|
||||
((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) )
|
||||
|
||||
#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \
|
||||
((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) )
|
||||
|
||||
#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \
|
||||
((int64_t)(ARG3) << 32) ) >> 32))
|
||||
|
||||
/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
|
||||
/* IAR iccarm specific functions */
|
||||
|
||||
/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/
|
||||
#include <cmsis_iar.h>
|
||||
|
||||
/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
|
||||
/* TI CCS specific functions */
|
||||
|
||||
/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/
|
||||
#include <cmsis_ccs.h>
|
||||
|
||||
/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
|
||||
/* GNU gcc specific functions */
|
||||
|
||||
/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
#define __SSAT16(ARG1,ARG2) \
|
||||
({ \
|
||||
uint32_t __RES, __ARG1 = (ARG1); \
|
||||
__ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
|
||||
__RES; \
|
||||
})
|
||||
|
||||
#define __USAT16(ARG1,ARG2) \
|
||||
({ \
|
||||
uint32_t __RES, __ARG1 = (ARG1); \
|
||||
__ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
|
||||
__RES; \
|
||||
})
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1));
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1));
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
#define __SMLALD(ARG1,ARG2,ARG3) \
|
||||
({ \
|
||||
uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((uint64_t)(ARG3) >> 32), __ARG3_L = (uint32_t)((uint64_t)(ARG3) & 0xFFFFFFFFUL); \
|
||||
__ASM volatile ("smlald %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \
|
||||
(uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \
|
||||
})
|
||||
|
||||
#define __SMLALDX(ARG1,ARG2,ARG3) \
|
||||
({ \
|
||||
uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((uint64_t)(ARG3) >> 32), __ARG3_L = (uint32_t)((uint64_t)(ARG3) & 0xFFFFFFFFUL); \
|
||||
__ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \
|
||||
(uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \
|
||||
})
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
#define __SMLSLD(ARG1,ARG2,ARG3) \
|
||||
({ \
|
||||
uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((ARG3) >> 32), __ARG3_L = (uint32_t)((ARG3) & 0xFFFFFFFFUL); \
|
||||
__ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \
|
||||
(uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \
|
||||
})
|
||||
|
||||
#define __SMLSLDX(ARG1,ARG2,ARG3) \
|
||||
({ \
|
||||
uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((ARG3) >> 32), __ARG3_L = (uint32_t)((ARG3) & 0xFFFFFFFFUL); \
|
||||
__ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \
|
||||
(uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \
|
||||
})
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
#define __PKHBT(ARG1,ARG2,ARG3) \
|
||||
({ \
|
||||
uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
|
||||
__ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \
|
||||
__RES; \
|
||||
})
|
||||
|
||||
#define __PKHTB(ARG1,ARG2,ARG3) \
|
||||
({ \
|
||||
uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
|
||||
if (ARG3 == 0) \
|
||||
__ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \
|
||||
else \
|
||||
__ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \
|
||||
__RES; \
|
||||
})
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3)
|
||||
{
|
||||
int32_t result;
|
||||
|
||||
__ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
|
||||
/* TASKING carm specific functions */
|
||||
|
||||
|
||||
/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/
|
||||
/* not yet supported */
|
||||
/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/*@} end of group CMSIS_SIMD_intrinsics */
|
||||
|
||||
|
||||
#endif /* __CORE_CM4_SIMD_H */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
609
cpu/cortex-m4_common/include/core_cmFunc.h
Normal file
609
cpu/cortex-m4_common/include/core_cmFunc.h
Normal file
@ -0,0 +1,609 @@
|
||||
/**************************************************************************//**
|
||||
* @file core_cmFunc.h
|
||||
* @brief CMSIS Cortex-M Core Function Access Header File
|
||||
* @version V2.10
|
||||
* @date 26. July 2011
|
||||
*
|
||||
* @note
|
||||
* Copyright (C) 2009-2011 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
|
||||
|
||||
|
||||
/* ########################### 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 ISPR Register
|
||||
|
||||
This function returns the content of the ISPR Register.
|
||||
|
||||
\return ISPR 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 ( __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");
|
||||
}
|
||||
|
||||
|
||||
/** \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");
|
||||
}
|
||||
|
||||
|
||||
/** \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 ISPR Register
|
||||
|
||||
This function returns the content of the ISPR Register.
|
||||
|
||||
\return ISPR 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");
|
||||
}
|
||||
|
||||
|
||||
/** \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");
|
||||
}
|
||||
|
||||
|
||||
/** \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 */
|
||||
585
cpu/cortex-m4_common/include/core_cmInstr.h
Normal file
585
cpu/cortex-m4_common/include/core_cmInstr.h
Normal file
@ -0,0 +1,585 @@
|
||||
/**************************************************************************//**
|
||||
* @file core_cmInstr.h
|
||||
* @brief CMSIS Cortex-M Core Instruction Access Header File
|
||||
* @version V2.10
|
||||
* @date 19. July 2011
|
||||
*
|
||||
* @note
|
||||
* Copyright (C) 2009-2011 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
|
||||
*/
|
||||
static __INLINE __ASM uint32_t __REV16(uint32_t value)
|
||||
{
|
||||
rev16 r0, r0
|
||||
bx lr
|
||||
}
|
||||
|
||||
|
||||
/** \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
|
||||
*/
|
||||
static __INLINE __ASM int32_t __REVSH(int32_t value)
|
||||
{
|
||||
revsh r0, r0
|
||||
bx lr
|
||||
}
|
||||
|
||||
|
||||
#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 ( __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);
|
||||
}
|
||||
|
||||
|
||||
#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 */
|
||||
54
cpu/cortex-m4_common/include/cpu.h
Normal file
54
cpu/cortex-m4_common/include/cpu.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup cpu_cortexm4_common ARM Cortex-M4 common
|
||||
* @ingroup cpu
|
||||
* @brief Common implementations and headers for Cortex-M4 family based micro-controllers
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Basic definitions for the Cortex-M4 common module
|
||||
*
|
||||
* When ever you want to do something hardware related, that is accessing MCUs registers directly,
|
||||
* just include this file. It will then make sure that the MCU specific headers are included.
|
||||
*
|
||||
* @author Stefan Pfeiffer <stefan.pfeiffer@fu-berlin.de>
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef __CORTEXM_COMMON_H
|
||||
#define __CORTEXM_COMMON_H
|
||||
|
||||
#include "cpu-conf.h"
|
||||
|
||||
/**
|
||||
* For downwards compatibility with old RIOT code.
|
||||
* TODO: remove once core was adjusted
|
||||
*/
|
||||
#include "irq.h"
|
||||
#define eINT enableIRQ
|
||||
#define dINT disableIRQ
|
||||
|
||||
/**
|
||||
* @brief Macro has to be called in the beginning of each ISR
|
||||
*/
|
||||
#define ISR_ENTER() asm("push {LR}")
|
||||
|
||||
/**
|
||||
* @brief Macro has to be called on each exit of an ISR
|
||||
*/
|
||||
#define ISR_EXIT() asm("pop {r0}"); asm("bx r0")
|
||||
|
||||
/**
|
||||
* @brief Initialization of the CPU
|
||||
*/
|
||||
void cpu_init(void);
|
||||
|
||||
#endif /* __CORTEXM_COMMON_H */
|
||||
/** @} */
|
||||
58
cpu/cortex-m4_common/irq_arch.c
Normal file
58
cpu/cortex-m4_common/irq_arch.c
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_cortexm4_common
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Implementation of the kernels irq interface
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "arch/irq_arch.h"
|
||||
#include "cpu.h"
|
||||
|
||||
/**
|
||||
* @brief Disable all maskable interrupts
|
||||
*/
|
||||
unsigned int irq_arch_disable(void)
|
||||
{
|
||||
uint32_t mask = __get_PRIMASK();
|
||||
__disable_irq();
|
||||
return mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable all maskable interrupts
|
||||
*/
|
||||
unsigned int irq_arch_enable(void)
|
||||
{
|
||||
__enable_irq();
|
||||
return __get_PRIMASK();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Restore the state of the IRQ flags
|
||||
*/
|
||||
void irq_arch_restore(unsigned int state)
|
||||
{
|
||||
__set_PRIMASK(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief See if the current context is inside an ISR
|
||||
*/
|
||||
int irq_arch_in(void)
|
||||
{
|
||||
return (__get_IPSR() & 0xFF);
|
||||
}
|
||||
212
cpu/cortex-m4_common/thread_arch.c
Normal file
212
cpu/cortex-m4_common/thread_arch.c
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_cortexm4_common
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Implementation of the kernel's architecture dependent thread interface
|
||||
*
|
||||
* @author Stefan Pfeiffer <stefan.pfeiffer@fu-berlin.de>
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "arch/thread_arch.h"
|
||||
#include "sched.h"
|
||||
#include "thread.h"
|
||||
#include "irq.h"
|
||||
#include "cpu.h"
|
||||
#include "kernel_internal.h"
|
||||
|
||||
/**
|
||||
* @name noticeable marker marking the beginning of a stack segment
|
||||
*
|
||||
* This marker is used e.g. by *thread_arch_start_threading* to identify the stacks start.
|
||||
*/
|
||||
#define STACK_MARKER (0x77777777)
|
||||
|
||||
/**
|
||||
* @name ARM Cortex-M specific exception return value, that triggers the return to the task mode
|
||||
* stack pointer
|
||||
*/
|
||||
#define EXCEPT_RET_TASK_MODE (0xfffffffd)
|
||||
|
||||
/**
|
||||
* Cortex-M knows stacks and handles register backups, so use different stack frame layout
|
||||
*
|
||||
* TODO: How to handle different Cortex-Ms? Code is so far valid for M3 and M4 without FPU
|
||||
*
|
||||
* Layout with storage of floating point registers (applicable for Cortex-M4):
|
||||
* ------------------------------------------------------------------------------------------------------------------------------------
|
||||
* | R0 | R1 | R2 | R3 | LR | PC | xPSR | S0 | S1 | S2 | S3 | S4 | S5 | S6 | S7 | S8 | S9 | S10 | S11 | S12 | S13 | S14 | S15 | FPSCR |
|
||||
* ------------------------------------------------------------------------------------------------------------------------------------
|
||||
*
|
||||
* Layout without floating point registers:
|
||||
* --------------------------------------
|
||||
* | R0 | R1 | R2 | R3 | LR | PC | xPSR |
|
||||
* --------------------------------------
|
||||
*
|
||||
*/
|
||||
char *thread_arch_stack_init(void *(*task_func)(void *),
|
||||
void *arg,
|
||||
void *stack_start,
|
||||
int stack_size)
|
||||
{
|
||||
uint32_t *stk;
|
||||
stk = (uint32_t *)(stack_start + stack_size);
|
||||
|
||||
/* marker */
|
||||
stk--;
|
||||
*stk = STACK_MARKER;
|
||||
|
||||
/* TODO: fix FPU handling for Cortex-M4 */
|
||||
/*
|
||||
stk--;
|
||||
*stk = (unsigned int) 0;
|
||||
*/
|
||||
|
||||
/* S0 - S15 */
|
||||
/*
|
||||
for (int i = 15; i >= 0; i--) {
|
||||
stk--;
|
||||
*stk = i;
|
||||
}
|
||||
*/
|
||||
|
||||
/* FIXME xPSR */
|
||||
stk--;
|
||||
*stk = (uint32_t) 0x01000200;
|
||||
|
||||
/* program counter */
|
||||
stk--;
|
||||
*stk = (uint32_t) task_func;
|
||||
|
||||
/* link register, jumped to when thread exits */
|
||||
stk--;
|
||||
*stk = (uint32_t) sched_task_exit;
|
||||
|
||||
/* r12 */
|
||||
stk--;
|
||||
*stk = (uint32_t) 0;
|
||||
|
||||
/* r1 - r3 */
|
||||
for (int i = 3; i >= 1; i--) {
|
||||
stk--;
|
||||
*stk = i;
|
||||
}
|
||||
|
||||
/* r0 -> thread function parameter */
|
||||
stk--;
|
||||
*stk = (uint32_t) arg;
|
||||
|
||||
/* r11 - r4 */
|
||||
for (int i = 11; i >= 4; i--) {
|
||||
stk--;
|
||||
*stk = i;
|
||||
}
|
||||
|
||||
/* lr means exception return code */
|
||||
stk--;
|
||||
*stk = EXCEPT_RET_TASK_MODE; /* return to task-mode main stack pointer */
|
||||
|
||||
return (char*) stk;
|
||||
}
|
||||
|
||||
void thread_arch_stack_print(void)
|
||||
{
|
||||
int count = 0;
|
||||
uint32_t *sp = (uint32_t *)sched_active_thread->sp;
|
||||
|
||||
printf("printing the current stack of thread %i\n", thread_getpid());
|
||||
printf(" address: data:\n");
|
||||
|
||||
do {
|
||||
printf(" 0x%08x: 0x%08x\n", (unsigned int)sp, (unsigned int)*sp);
|
||||
sp++;
|
||||
count++;
|
||||
} while (*sp != STACK_MARKER);
|
||||
|
||||
printf("current stack size: %i byte\n", count);
|
||||
}
|
||||
|
||||
__attribute__((naked)) void NORETURN thread_arch_start_threading(void)
|
||||
{
|
||||
/* switch to user mode use PSP instead of MSP in ISR Mode*/
|
||||
CONTROL_Type mode;
|
||||
mode.w = __get_CONTROL();
|
||||
mode.b.SPSEL = 1; /* select PSP */
|
||||
mode.b.nPRIV = 0; /* privilege */
|
||||
__set_CONTROL(mode.w);
|
||||
|
||||
/* enable IRQs to make sure the SVC interrupt is reachable */
|
||||
enableIRQ();
|
||||
|
||||
/* trigger the SVC interrupt which will get and execute the next thread */
|
||||
asm("svc 0x01");
|
||||
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void thread_arch_yield(void)
|
||||
{
|
||||
/* trigger the PENDSV interrupt to run scheduler and schedule new thread if applicable */
|
||||
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static __INLINE void context_save(void)
|
||||
{
|
||||
/* {r0-r3,r12,LR,PC,xPSR} are saved automatically on exception entry */
|
||||
|
||||
/* save unsaved registers */
|
||||
asm("mrs r0, psp" ); /* get stack pointer from user mode */
|
||||
asm("stmdb r0!,{r4-r11}" ); /* save regs */
|
||||
asm("stmdb r0!,{lr}" ); /* exception return value */
|
||||
/* asm("vstmdb sp!, {s16-s31}" ); */ /* TODO save FPU registers if needed */
|
||||
asm("ldr r1, =sched_active_thread" ); /* load address of current tcb */
|
||||
asm("ldr r1, [r1]" ); /* dereference pdc */
|
||||
asm("str r0, [r1]" ); /* write r0 to pdc->sp means current threads stack pointer */
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static __INLINE void context_restore(void)
|
||||
{
|
||||
asm("ldr r0, =sched_active_thread" ); /* load address of current TCB */
|
||||
asm("ldr r0, [r0]" ); /* dereference TCB */
|
||||
asm("ldr r1, [r0]" ); /* load tcb->sp to register 1 */
|
||||
asm("ldmia r1!, {r0}" ); /* restore exception return value from stack */
|
||||
/* asm("pop {s16-s31}" ); */ /* TODO load FPU register if needed depends on r0 exret */
|
||||
asm("ldmia r1!, {r4-r11}" ); /* restore other registers */
|
||||
asm("msr psp, r1" ); /* restore PSP register (user mode SP)*/
|
||||
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 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The svc is used for running the scheduler and scheduling a new task during start-up or
|
||||
* after a thread has exited
|
||||
*/
|
||||
__attribute__((naked)) void isr_svc(void)
|
||||
{
|
||||
sched_run();
|
||||
context_restore();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief All task switching activity is carried out int the pendSV interrupt
|
||||
*/
|
||||
__attribute__((naked)) void isr_pendsv(void)
|
||||
{
|
||||
context_save();
|
||||
sched_run();
|
||||
context_restore();
|
||||
}
|
||||
7
cpu/stm32f4/Makefile
Normal file
7
cpu/stm32f4/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
# define the module that is build
|
||||
MODULE = cpu
|
||||
|
||||
# add a list of subdirectories, that should also be build
|
||||
DIRS = periph $(CORTEX_M4_COMMON)
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
28
cpu/stm32f4/Makefile.include
Normal file
28
cpu/stm32f4/Makefile.include
Normal file
@ -0,0 +1,28 @@
|
||||
# this CPU implementation is using the explicit core/CPU interface
|
||||
export CFLAGS += -DCOREIF_NG=1
|
||||
|
||||
# export the peripheral drivers to be linked into the final binary
|
||||
export USEMODULE += periph
|
||||
|
||||
# tell the build system that the CPU depends on the Cortex-M common files
|
||||
export USEMODULE += cortex-m4_common
|
||||
|
||||
# define path to cortex-m common module, which is needed for this CPU
|
||||
export CORTEX_M4_COMMON = $(RIOTCPU)/cortex-m4_common/
|
||||
|
||||
# CPU depends on the cortex-m common module, so include it
|
||||
include $(CORTEX_M4_COMMON)Makefile.include
|
||||
|
||||
# define the linker script to use for this CPU
|
||||
export LINKERSCRIPT = $(RIOTCPU)/$(CPU)/$(CPU_MODEL)_linkerscript.ld
|
||||
|
||||
#export the CPU model
|
||||
MODEL = $(shell echo $(CPU_MODEL)|tr 'a-z' 'A-Z')
|
||||
export CFLAGS += -DCPU_MODEL_$(MODEL)
|
||||
|
||||
# include CPU specific includes
|
||||
export INCLUDES += -I$(RIOTCPU)/$(CPU)/include
|
||||
|
||||
# add the CPU specific system calls implementations for the linker
|
||||
export UNDEF += $(BINDIR)cpu/syscalls.o
|
||||
export UNDEF += $(BINDIR)cpu/startup.o
|
||||
150
cpu/stm32f4/cpu.c
Normal file
150
cpu/stm32f4/cpu.c
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_stm32f4
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Implementation of the CPU initialization
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "cpu.h"
|
||||
#include "periph_conf.h"
|
||||
|
||||
/**
|
||||
* @name Pattern to write into the Coprocessor Access Control Register to allow full FPU access
|
||||
*/
|
||||
#define FULL_FPU_ACCESS (0x00f00000)
|
||||
|
||||
|
||||
static void cpu_clock_init(void);
|
||||
|
||||
/**
|
||||
* @brief Initialize the CPU, set IRQ priorities
|
||||
*/
|
||||
void cpu_init(void)
|
||||
{
|
||||
/* give full access to the FPU */
|
||||
SCB->CPACR |= (uint32_t)FULL_FPU_ACCESS;
|
||||
|
||||
/* configure the vector table location to internal flash */
|
||||
SCB->VTOR = FLASH_BASE;
|
||||
|
||||
/* initialize the clock system */
|
||||
cpu_clock_init();
|
||||
|
||||
/* set pendSV interrupt to lowest possible priority */
|
||||
NVIC_SetPriority(PendSV_IRQn, 0xff);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the controllers clock system
|
||||
*
|
||||
* The clock initialization make the following assumptions:
|
||||
* - the external HSE clock from an external oscillator is used as base clock
|
||||
* - the internal PLL circuit is used for clock refinement
|
||||
*
|
||||
* Use the following formulas to calculate the needed values:
|
||||
*
|
||||
* SYSCLK = ((HSE_VALUE / CLOCK_PLL_M) * CLOCK_PLL_N) / CLOCK_PLL_P
|
||||
* USB, SDIO and RNG Clock = ((HSE_VALUE / CLOCK_PLL_M) * CLOCK_PLL_N) / CLOCK_PLL_Q
|
||||
*
|
||||
* The actual used values are specified in the board's `periph_conf.h` file.
|
||||
*
|
||||
* NOTE: currently there is not timeout for initialization of PLL and other locks
|
||||
* -> when wrong values are chosen, the initialization could stall
|
||||
*/
|
||||
static void cpu_clock_init(void)
|
||||
{
|
||||
/* configure the HSE clock */
|
||||
|
||||
/* enable the HSI clock */
|
||||
RCC->CR |= RCC_CR_HSION;
|
||||
|
||||
/* reset clock configuration register */
|
||||
RCC->CFGR = 0;
|
||||
|
||||
/* disable HSE, CSS and PLL */
|
||||
RCC->CR &= ~(RCC_CR_HSEON | RCC_CR_HSEBYP | RCC_CR_CSSON | RCC_CR_PLLON);
|
||||
|
||||
/* disable all clock interrupts */
|
||||
RCC->CIR = 0;
|
||||
|
||||
/* enable the HSE clock */
|
||||
RCC->CR |= RCC_CR_HSEON;
|
||||
|
||||
/* wait for HSE to be ready */
|
||||
while (!(RCC->CR & RCC_CR_HSERDY));
|
||||
|
||||
/* setup power module */
|
||||
|
||||
/* enable the power module */
|
||||
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
|
||||
/* set the voltage scaling to 1 to enable the maximum frequency */
|
||||
PWR->CR |= PWR_CR_VOS_1;
|
||||
|
||||
/* setup the peripheral bus prescalers */
|
||||
|
||||
/* set the AHB clock divider */
|
||||
RCC->CFGR &= ~RCC_CFGR_HPRE;
|
||||
RCC->CFGR |= CLOCK_AHB_DIV;
|
||||
/* set the APB2 (high speed) bus clock divider */
|
||||
RCC->CFGR &= ~RCC_CFGR_PPRE2;
|
||||
RCC->CFGR |= CLOCK_APB2_DIV;
|
||||
/* set the APB1 (low speed) bus clock divider */
|
||||
RCC->CFGR &= ~RCC_CFGR_PPRE1;
|
||||
RCC->CFGR |= CLOCK_APB1_DIV;
|
||||
|
||||
/* configure the PLL */
|
||||
|
||||
/* reset PLL config register */
|
||||
RCC->PLLCFGR = 0;
|
||||
/* set HSE as source for the PLL */
|
||||
RCC->PLLCFGR |= RCC_PLLCFGR_PLLSRC_HSE;
|
||||
/* set division factor for main PLL input clock */
|
||||
RCC->PLLCFGR |= (CLOCK_PLL_M & 0x3F);
|
||||
/* set main PLL multiplication factor for VCO */
|
||||
RCC->PLLCFGR |= (CLOCK_PLL_N & 0x1FF) << 6;
|
||||
/* set main PLL division factor for main system clock */
|
||||
RCC->PLLCFGR |= (((CLOCK_PLL_P & 0x03) >> 1) - 1) << 16;
|
||||
/* set main PLL division factor for USB OTG FS, SDIO and RNG clocks */
|
||||
RCC->PLLCFGR |= (CLOCK_PLL_Q & 0x0F) << 24;
|
||||
|
||||
/* enable PLL again */
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
/* wait until PLL is stable */
|
||||
while(!(RCC->CR & RCC_CR_PLLRDY));
|
||||
|
||||
/* configure flash latency */
|
||||
|
||||
/* reset flash access control register */
|
||||
FLASH->ACR = 0;
|
||||
/* enable instruction cache */
|
||||
FLASH->ACR |= FLASH_ACR_ICEN;
|
||||
/* enable data cache */
|
||||
FLASH->ACR |= FLASH_ACR_DCEN;
|
||||
/* enable pre-fetch buffer */
|
||||
// FLASH->ACR |= FLASH_ACR_PRFTEN;
|
||||
/* set flash latency */
|
||||
FLASH->ACR &= ~FLASH_ACR_LATENCY;
|
||||
FLASH->ACR |= CLOCK_FLASH_LATENCY;
|
||||
|
||||
/* configure the sysclock and the peripheral clocks */
|
||||
|
||||
/* set sysclock to be driven by the PLL clock */
|
||||
RCC->CFGR &= ~RCC_CFGR_SW;
|
||||
RCC->CFGR |= RCC_CFGR_SW_PLL;
|
||||
|
||||
/* wait for sysclock to be stable */
|
||||
while (!(RCC->CFGR & RCC_CFGR_SWS_PLL));
|
||||
}
|
||||
77
cpu/stm32f4/hwtimer_arch.c
Normal file
77
cpu/stm32f4/hwtimer_arch.c
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_stm32f4
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Implementation of the kernels hwtimer interface
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "arch/hwtimer_arch.h"
|
||||
#include "board.h"
|
||||
#include "periph/timer.h"
|
||||
#include "thread.h"
|
||||
|
||||
/**
|
||||
* @brief Callback function that is given to the low-level timer
|
||||
*
|
||||
* @param[in] channel the channel of the low-level timer that was triggered
|
||||
*/
|
||||
void irq_handler(int channel);
|
||||
|
||||
/**
|
||||
* @brief Hold a reference to the hwtimer callback
|
||||
*/
|
||||
void (*timeout_handler)(int);
|
||||
|
||||
void hwtimer_arch_init(void (*handler)(int), uint32_t fcpu)
|
||||
{
|
||||
timeout_handler = handler;
|
||||
timer_init(HW_TIMER, 1, &irq_handler);
|
||||
}
|
||||
|
||||
void hwtimer_arch_enable_interrupt(void)
|
||||
{
|
||||
timer_irq_enable(HW_TIMER);
|
||||
}
|
||||
|
||||
void hwtimer_arch_disable_interrupt(void)
|
||||
{
|
||||
timer_irq_disable(HW_TIMER);
|
||||
}
|
||||
|
||||
void hwtimer_arch_set(unsigned long offset, short timer)
|
||||
{
|
||||
timer_set(HW_TIMER, timer, offset);
|
||||
}
|
||||
|
||||
void hwtimer_arch_set_absolute(unsigned long value, short timer)
|
||||
{
|
||||
timer_set_absolute(HW_TIMER, timer, value);
|
||||
}
|
||||
|
||||
void hwtimer_arch_unset(short timer)
|
||||
{
|
||||
timer_clear(HW_TIMER, timer);
|
||||
}
|
||||
|
||||
unsigned long hwtimer_arch_now(void)
|
||||
{
|
||||
return timer_read(HW_TIMER);
|
||||
}
|
||||
|
||||
void irq_handler(int channel)
|
||||
{
|
||||
timeout_handler((short)(channel));
|
||||
}
|
||||
55
cpu/stm32f4/include/cpu-conf.h
Normal file
55
cpu/stm32f4/include/cpu-conf.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup cpu_stm32f4 STM32F4
|
||||
* @ingroup cpu
|
||||
* @brief CPU specific implementations for the STM32F4
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Implementation specific CPU configuration options
|
||||
*
|
||||
* @author Hauke Petersen <hauke.peterse@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef __CPU_CONF_H
|
||||
#define __CPU_CONF_H
|
||||
|
||||
#ifdef CPU_MODEL_STM32F407VG
|
||||
#include "stm32f407xx.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name Kernel configuration
|
||||
*
|
||||
* TODO: measure and adjust for the Cortex-M4f
|
||||
* @{
|
||||
*/
|
||||
#define KERNEL_CONF_STACKSIZE_PRINTF (2500)
|
||||
|
||||
#ifndef KERNEL_CONF_STACKSIZE_DEFAULT
|
||||
#define KERNEL_CONF_STACKSIZE_DEFAULT (2500)
|
||||
#endif
|
||||
|
||||
#define KERNEL_CONF_STACKSIZE_IDLE (512)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name UART0 buffer size definition for compatibility reasons
|
||||
*
|
||||
* TODO: remove once the remodeling of the uart0 driver is done
|
||||
* @{
|
||||
*/
|
||||
#ifndef UART0_BUFSIZE
|
||||
#define UART0_BUFSIZE (128)
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
#endif /* __CPU_CONF_H */
|
||||
/** @} */
|
||||
32
cpu/stm32f4/include/hwtimer_cpu.h
Normal file
32
cpu/stm32f4/include/hwtimer_cpu.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_stm32f4
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief CPU specific hwtimer configuration options
|
||||
*
|
||||
* @author Hauke Petersen <hauke.peterse@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef __HWTIMER_CPU_H
|
||||
#define __HWTIMER_CPU_H
|
||||
|
||||
/**
|
||||
* @name Hardware timer configuration
|
||||
* @{
|
||||
*/
|
||||
#define HWTIMER_MAXTIMERS 4 /**< the CPU implementation supports 4 HW timers */
|
||||
#define HWTIMER_SPEED 1000000 /**< the HW timer runs with 1MHz */
|
||||
#define HWTIMER_MAXTICKS (0xFFFFFFFF) /**< 32-bit timer */
|
||||
/** @} */
|
||||
|
||||
#endif /* __HWTIMER_CPU_H */
|
||||
/** @} */
|
||||
7952
cpu/stm32f4/include/stm32f407xx.h
Normal file
7952
cpu/stm32f4/include/stm32f407xx.h
Normal file
File diff suppressed because it is too large
Load Diff
31
cpu/stm32f4/io_arch.c
Normal file
31
cpu/stm32f4/io_arch.c
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_stm32f4
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Implementation of the kernel's architecture dependent IO interface
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "board.h"
|
||||
#include "arch/io_arch.h"
|
||||
#include "periph/uart.h"
|
||||
|
||||
int io_arch_puts(char *data, int size)
|
||||
{
|
||||
for (int i = 0; i < size; i++) {
|
||||
uart_write_blocking(STDIO, data[i]);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
53
cpu/stm32f4/lpm_arch.c
Normal file
53
cpu/stm32f4/lpm_arch.c
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_stm32f4
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Implementation of the kernels power management interface
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "arch/lpm_arch.h"
|
||||
|
||||
void lpm_arch_init(void)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
enum lpm_mode lpm_arch_set(enum lpm_mode target)
|
||||
{
|
||||
/* TODO */
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum lpm_mode lpm_arch_get(void)
|
||||
{
|
||||
/* TODO */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lpm_arch_awake(void)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
void lpm_arch_begin_awake(void)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
void lpm_arch_end_awake(void)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
3
cpu/stm32f4/periph/Makefile
Normal file
3
cpu/stm32f4/periph/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = periph
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
758
cpu/stm32f4/periph/gpio.c
Normal file
758
cpu/stm32f4/periph/gpio.c
Normal file
@ -0,0 +1,758 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_stm32f4
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Low-level GPIO driver implementation
|
||||
*
|
||||
* @author Hauke Petersen <mail@haukepetersen.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "cpu.h"
|
||||
#include "sched.h"
|
||||
#include "thread.h"
|
||||
#include "periph/gpio.h"
|
||||
#include "periph_conf.h"
|
||||
|
||||
typedef struct {
|
||||
void (*cb)(void);
|
||||
} gpio_state_t;
|
||||
|
||||
/**
|
||||
* @brief Unified IRQ handler shared by all interrupt routines
|
||||
*
|
||||
* @param[in] dev the device that triggered the interrupt
|
||||
*/
|
||||
static inline void irq_handler(gpio_t dev);
|
||||
|
||||
/**
|
||||
* @brief Hold one callback function pointer for each gpio device
|
||||
*/
|
||||
static gpio_state_t config[GPIO_NUMOF];
|
||||
|
||||
int gpio_init_out(gpio_t dev, gpio_pp_t pushpull)
|
||||
{
|
||||
GPIO_TypeDef *port;
|
||||
uint32_t pin;
|
||||
|
||||
switch (dev) {
|
||||
#if GPIO_0_EN
|
||||
case GPIO_0:
|
||||
GPIO_0_CLKEN();
|
||||
port = GPIO_0_PORT;
|
||||
pin = GPIO_0_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_1_EN
|
||||
case GPIO_1:
|
||||
GPIO_1_CLKEN();
|
||||
port = GPIO_1_PORT;
|
||||
pin = GPIO_1_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_2_EN
|
||||
case GPIO_2:
|
||||
GPIO_2_CLKEN();
|
||||
port = GPIO_2_PORT;
|
||||
pin = GPIO_2_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_3_EN
|
||||
case GPIO_3:
|
||||
GPIO_3_CLKEN();
|
||||
port = GPIO_3_PORT;
|
||||
pin = GPIO_3_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_4_EN
|
||||
case GPIO_4:
|
||||
GPIO_4_CLKEN();
|
||||
port = GPIO_4_PORT;
|
||||
pin = GPIO_4_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_5_EN
|
||||
case GPIO_5:
|
||||
GPIO_5_CLKEN();
|
||||
port = GPIO_5_PORT;
|
||||
pin = GPIO_5_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_6_EN
|
||||
case GPIO_6:
|
||||
GPIO_6_CLKEN();
|
||||
port = GPIO_6_PORT;
|
||||
pin = GPIO_6_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_7_EN
|
||||
case GPIO_7:
|
||||
GPIO_7_CLKEN();
|
||||
port = GPIO_7_PORT;
|
||||
pin = GPIO_7_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_8_EN
|
||||
case GPIO_8:
|
||||
GPIO_8_CLKEN();
|
||||
port = GPIO_8_PORT;
|
||||
pin = GPIO_8_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_9_EN
|
||||
case GPIO_9:
|
||||
GPIO_9_CLKEN();
|
||||
port = GPIO_9_PORT;
|
||||
pin = GPIO_9_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_10_EN
|
||||
case GPIO_10:
|
||||
GPIO_10_CLKEN();
|
||||
port = GPIO_10_PORT;
|
||||
pin = GPIO_10_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_11_EN
|
||||
case GPIO_11:
|
||||
GPIO_11_CLKEN();
|
||||
port = GPIO_11_PORT;
|
||||
pin = GPIO_11_PIN;
|
||||
break;
|
||||
#endif
|
||||
case GPIO_UNDEFINED:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
port->MODER &= ~(2 << (2 * pin)); /* set pin to output mode */
|
||||
port->MODER |= (1 << (2 * pin));
|
||||
port->OTYPER &= ~(1 << pin); /* set to push-pull configuration */
|
||||
port->OSPEEDR |= (3 << (2 * pin)); /* set to high speed */
|
||||
port->PUPDR &= ~(3 << (2 * pin)); /* configure push-pull resistors */
|
||||
port->PUPDR |= (pushpull << (2 * pin));
|
||||
port->ODR &= ~(1 << pin); /* set pin to low signal */
|
||||
|
||||
return 0; /* all OK */
|
||||
}
|
||||
|
||||
int gpio_init_in(gpio_t dev, gpio_pp_t pushpull)
|
||||
{
|
||||
GPIO_TypeDef *port;
|
||||
uint32_t pin;
|
||||
|
||||
switch (dev) {
|
||||
#if GPIO_0_EN
|
||||
case GPIO_0:
|
||||
GPIO_0_CLKEN();
|
||||
port = GPIO_0_PORT;
|
||||
pin = GPIO_0_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_1_EN
|
||||
case GPIO_1:
|
||||
GPIO_1_CLKEN();
|
||||
port = GPIO_1_PORT;
|
||||
pin = GPIO_1_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_2_EN
|
||||
case GPIO_2:
|
||||
GPIO_2_CLKEN();
|
||||
port = GPIO_2_PORT;
|
||||
pin = GPIO_2_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_3_EN
|
||||
case GPIO_3:
|
||||
GPIO_3_CLKEN();
|
||||
port = GPIO_3_PORT;
|
||||
pin = GPIO_3_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_4_EN
|
||||
case GPIO_4:
|
||||
GPIO_4_CLKEN();
|
||||
port = GPIO_4_PORT;
|
||||
pin = GPIO_4_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_5_EN
|
||||
case GPIO_5:
|
||||
GPIO_5_CLKEN();
|
||||
port = GPIO_5_PORT;
|
||||
pin = GPIO_5_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_6_EN
|
||||
case GPIO_6:
|
||||
GPIO_6_CLKEN();
|
||||
port = GPIO_6_PORT;
|
||||
pin = GPIO_6_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_7_EN
|
||||
case GPIO_7:
|
||||
GPIO_7_CLKEN();
|
||||
port = GPIO_7_PORT;
|
||||
pin = GPIO_7_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_8_EN
|
||||
case GPIO_8:
|
||||
GPIO_8_CLKEN();
|
||||
port = GPIO_8_PORT;
|
||||
pin = GPIO_8_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_9_EN
|
||||
case GPIO_9:
|
||||
GPIO_9_CLKEN();
|
||||
port = GPIO_9_PORT;
|
||||
pin = GPIO_9_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_10_EN
|
||||
case GPIO_10:
|
||||
GPIO_10_CLKEN();
|
||||
port = GPIO_10_PORT;
|
||||
pin = GPIO_10_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_11_EN
|
||||
case GPIO_11:
|
||||
GPIO_11_CLKEN();
|
||||
port = GPIO_11_PORT;
|
||||
pin = GPIO_11_PIN;
|
||||
break;
|
||||
#endif
|
||||
case GPIO_UNDEFINED:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
port->MODER &= ~(3 << (2 * pin)); /* configure pin as input */
|
||||
port->PUPDR &= ~(3 << (2 * pin)); /* configure push-pull resistors */
|
||||
port->PUPDR |= (pushpull << (2 * pin));
|
||||
|
||||
return 0; /* everything alright here */
|
||||
}
|
||||
|
||||
int gpio_init_int(gpio_t dev, gpio_pp_t pushpull, gpio_flank_t flank, void (*cb)(void))
|
||||
{
|
||||
int res;
|
||||
uint32_t pin;
|
||||
|
||||
res = gpio_init_in(dev, pushpull);
|
||||
if (res < 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
/* enable the SYSCFG clock */
|
||||
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
|
||||
|
||||
switch (dev) {
|
||||
#if GPIO_0_EN
|
||||
case GPIO_0:
|
||||
pin = GPIO_0_PIN;
|
||||
GPIO_0_EXTI_CFG();
|
||||
NVIC_SetPriority(GPIO_0_IRQ, GPIO_IRQ_PRIO);
|
||||
NVIC_EnableIRQ(GPIO_0_IRQ);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_1_EN
|
||||
case GPIO_1:
|
||||
pin = GPIO_1_PIN;
|
||||
GPIO_1_EXTI_CFG();
|
||||
NVIC_SetPriority(GPIO_1_IRQ, GPIO_IRQ_PRIO);
|
||||
NVIC_EnableIRQ(GPIO_1_IRQ);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_2_EN
|
||||
case GPIO_2:
|
||||
pin = GPIO_2_PIN;
|
||||
GPIO_2_EXTI_CFG();
|
||||
NVIC_SetPriority(GPIO_2_IRQ, GPIO_IRQ_PRIO);
|
||||
NVIC_EnableIRQ(GPIO_2_IRQ);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_3_EN
|
||||
case GPIO_3:
|
||||
pin = GPIO_3_PIN;
|
||||
GPIO_3_EXTI_CFG();
|
||||
NVIC_SetPriority(GPIO_3_IRQ, GPIO_IRQ_PRIO);
|
||||
NVIC_EnableIRQ(GPIO_3_IRQ);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_4_EN
|
||||
case GPIO_4:
|
||||
pin = GPIO_4_PIN;
|
||||
GPIO_4_EXTI_CFG();
|
||||
NVIC_SetPriority(GPIO_4_IRQ, GPIO_IRQ_PRIO);
|
||||
NVIC_EnableIRQ(GPIO_4_IRQ);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_5_EN
|
||||
case GPIO_5:
|
||||
pin = GPIO_5_PIN;
|
||||
GPIO_5_EXTI_CFG();
|
||||
NVIC_SetPriority(GPIO_5_IRQ, GPIO_IRQ_PRIO);
|
||||
NVIC_EnableIRQ(GPIO_5_IRQ);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_6_EN
|
||||
case GPIO_6:
|
||||
pin = GPIO_6_PIN;
|
||||
GPIO_6_EXTI_CFG();
|
||||
NVIC_SetPriority(GPIO_6_IRQ, GPIO_IRQ_PRIO);
|
||||
NVIC_EnableIRQ(GPIO_6_IRQ);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_7_EN
|
||||
case GPIO_7:
|
||||
pin = GPIO_7_PIN;
|
||||
GPIO_7_EXTI_CFG();
|
||||
NVIC_SetPriority(GPIO_7_IRQ, GPIO_IRQ_PRIO);
|
||||
NVIC_EnableIRQ(GPIO_7_IRQ);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_8_EN
|
||||
case GPIO_8:
|
||||
pin = GPIO_8_PIN;
|
||||
GPIO_8_EXTI_CFG();
|
||||
NVIC_SetPriority(GPIO_8_IRQ, GPIO_IRQ_PRIO);
|
||||
NVIC_EnableIRQ(GPIO_8_IRQ);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_9_EN
|
||||
case GPIO_9:
|
||||
pin = GPIO_9_PIN;
|
||||
GPIO_9_EXTI_CFG();
|
||||
NVIC_SetPriority(GPIO_9_IRQ, GPIO_IRQ_PRIO);
|
||||
NVIC_EnableIRQ(GPIO_9_IRQ);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_10_EN
|
||||
case GPIO_10:
|
||||
pin = GPIO_10_PIN;
|
||||
GPIO_10_EXTI_CFG();
|
||||
NVIC_SetPriority(GPIO_10_IRQ, GPIO_IRQ_PRIO);
|
||||
NVIC_EnableIRQ(GPIO_10_IRQ);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_11_EN
|
||||
case GPIO_11:
|
||||
pin = GPIO_11_PIN;
|
||||
GPIO_11_EXTI_CFG();
|
||||
NVIC_SetPriority(GPIO_11_IRQ, GPIO_IRQ_PRIO);
|
||||
NVIC_EnableIRQ(GPIO_11_IRQ);
|
||||
break;
|
||||
#endif
|
||||
case GPIO_UNDEFINED:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* set callback */
|
||||
config[dev].cb = cb;
|
||||
|
||||
/* configure the active edges */
|
||||
switch (flank) {
|
||||
case GPIO_RISING:
|
||||
EXTI->RTSR |= (1 << pin);
|
||||
EXTI->FTSR &= ~(1 << pin);
|
||||
break;
|
||||
case GPIO_FALLING:
|
||||
EXTI->RTSR &= ~(1 << pin);
|
||||
EXTI->FTSR |= (1 << pin);
|
||||
break;
|
||||
case GPIO_BOTH:
|
||||
EXTI->RTSR |= (1 << pin);
|
||||
EXTI->FTSR |= (1 << pin);
|
||||
break;
|
||||
}
|
||||
|
||||
/* enable interrupt for EXTI line */
|
||||
EXTI->IMR |= (1 << pin);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpio_read(gpio_t dev)
|
||||
{
|
||||
GPIO_TypeDef *port;
|
||||
uint32_t pin;
|
||||
|
||||
switch (dev) {
|
||||
#if GPIO_0_EN
|
||||
case GPIO_0:
|
||||
port = GPIO_0_PORT;
|
||||
pin = GPIO_0_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_1_EN
|
||||
case GPIO_1:
|
||||
port = GPIO_1_PORT;
|
||||
pin = GPIO_1_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_2_EN
|
||||
case GPIO_2:
|
||||
port = GPIO_2_PORT;
|
||||
pin = GPIO_2_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_3_EN
|
||||
case GPIO_3:
|
||||
port = GPIO_3_PORT;
|
||||
pin = GPIO_3_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_4_EN
|
||||
case GPIO_4:
|
||||
port = GPIO_4_PORT;
|
||||
pin = GPIO_4_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_5_EN
|
||||
case GPIO_5:
|
||||
port = GPIO_5_PORT;
|
||||
pin = GPIO_5_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_6_EN
|
||||
case GPIO_6:
|
||||
port = GPIO_6_PORT;
|
||||
pin = GPIO_6_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_7_EN
|
||||
case GPIO_7:
|
||||
port = GPIO_7_PORT;
|
||||
pin = GPIO_7_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_8_EN
|
||||
case GPIO_8:
|
||||
port = GPIO_8_PORT;
|
||||
pin = GPIO_8_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_9_EN
|
||||
case GPIO_9:
|
||||
port = GPIO_9_PORT;
|
||||
pin = GPIO_9_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_10_EN
|
||||
case GPIO_10:
|
||||
port = GPIO_10_PORT;
|
||||
pin = GPIO_10_PIN;
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_11_EN
|
||||
case GPIO_11:
|
||||
port = GPIO_11_PORT;
|
||||
pin = GPIO_11_PIN;
|
||||
break;
|
||||
#endif
|
||||
case GPIO_UNDEFINED:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (port->MODER & (3 << (pin * 2))) { /* if configured as output */
|
||||
return port->ODR & (1 << pin); /* read output data register */
|
||||
} else {
|
||||
return port->IDR & (1 << pin); /* else read input data register */
|
||||
}
|
||||
}
|
||||
|
||||
int gpio_set(gpio_t dev)
|
||||
{
|
||||
switch (dev) {
|
||||
#if GPIO_0_EN
|
||||
case GPIO_0:
|
||||
GPIO_0_PORT->ODR |= (1 << GPIO_0_PIN);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_1_EN
|
||||
case GPIO_1:
|
||||
GPIO_1_PORT->ODR |= (1 << GPIO_1_PIN);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_2_EN
|
||||
case GPIO_2:
|
||||
GPIO_2_PORT->ODR |= (1 << GPIO_2_PIN);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_3_EN
|
||||
case GPIO_3:
|
||||
GPIO_3_PORT->ODR |= (1 << GPIO_3_PIN);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_4_EN
|
||||
case GPIO_4:
|
||||
GPIO_4_PORT->ODR |= (1 << GPIO_4_PIN);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_5_EN
|
||||
case GPIO_5:
|
||||
GPIO_5_PORT->ODR |= (1 << GPIO_5_PIN);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_6_EN
|
||||
case GPIO_6:
|
||||
GPIO_6_PORT->ODR |= (1 << GPIO_6_PIN);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_7_EN
|
||||
case GPIO_7:
|
||||
GPIO_7_PORT->ODR |= (1 << GPIO_7_PIN);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_8_EN
|
||||
case GPIO_8:
|
||||
GPIO_8_PORT->ODR |= (1 << GPIO_8_PIN);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_9_EN
|
||||
case GPIO_9:
|
||||
GPIO_9_PORT->ODR |= (1 << GPIO_9_PIN);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_10_EN
|
||||
case GPIO_10:
|
||||
GPIO_10_PORT->ODR |= (1 << GPIO_10_PIN);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_11_EN
|
||||
case GPIO_11:
|
||||
GPIO_11_PORT->ODR |= (1 << GPIO_11_PIN);
|
||||
#endif
|
||||
break;
|
||||
case GPIO_UNDEFINED:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpio_clear(gpio_t dev)
|
||||
{
|
||||
switch (dev) {
|
||||
#if GPIO_0_EN
|
||||
case GPIO_0:
|
||||
GPIO_0_PORT->ODR &= ~(1 << GPIO_0_PIN);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_1_EN
|
||||
case GPIO_1:
|
||||
GPIO_1_PORT->ODR &= ~(1 << GPIO_1_PIN);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_2_EN
|
||||
case GPIO_2:
|
||||
GPIO_2_PORT->ODR &= ~(1 << GPIO_2_PIN);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_3_EN
|
||||
case GPIO_3:
|
||||
GPIO_3_PORT->ODR &= ~(1 << GPIO_3_PIN);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_4_EN
|
||||
case GPIO_4:
|
||||
GPIO_4_PORT->ODR &= ~(1 << GPIO_4_PIN);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_5_EN
|
||||
case GPIO_5:
|
||||
GPIO_5_PORT->ODR &= ~(1 << GPIO_5_PIN);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_6_EN
|
||||
case GPIO_6:
|
||||
GPIO_6_PORT->ODR &= ~(1 << GPIO_6_PIN);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_7_EN
|
||||
case GPIO_7:
|
||||
GPIO_7_PORT->ODR &= ~(1 << GPIO_7_PIN);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_8_EN
|
||||
case GPIO_8:
|
||||
GPIO_8_PORT->ODR &= ~(1 << GPIO_8_PIN);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_9_EN
|
||||
case GPIO_9:
|
||||
GPIO_9_PORT->ODR &= ~(1 << GPIO_9_PIN);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_10_EN
|
||||
case GPIO_10:
|
||||
GPIO_10_PORT->ODR &= ~(1 << GPIO_10_PIN);
|
||||
break;
|
||||
#endif
|
||||
#if GPIO_11_EN
|
||||
case GPIO_11:
|
||||
GPIO_11_PORT->ODR &= ~(1 << GPIO_11_PIN);
|
||||
break;
|
||||
#endif
|
||||
case GPIO_UNDEFINED:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpio_toggle(gpio_t dev)
|
||||
{
|
||||
if (gpio_read(dev)) {
|
||||
return gpio_clear(dev);
|
||||
} else {
|
||||
return gpio_set(dev);
|
||||
}
|
||||
}
|
||||
|
||||
int gpio_write(gpio_t dev, int value)
|
||||
{
|
||||
if (value) {
|
||||
return gpio_set(dev);
|
||||
} else {
|
||||
return gpio_clear(dev);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void irq_handler(gpio_t dev)
|
||||
{
|
||||
config[dev].cb();
|
||||
if (sched_context_switch_request) {
|
||||
thread_yield();
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((naked))
|
||||
void isr_exti0(void)
|
||||
{
|
||||
ISR_ENTER();
|
||||
if (EXTI->PR & EXTI_PR_PR0) {
|
||||
EXTI->PR |= EXTI_PR_PR0; /* clear status bit by writing a 1 to it */
|
||||
irq_handler(GPIO_IRQ_0);
|
||||
}
|
||||
ISR_EXIT();
|
||||
}
|
||||
|
||||
__attribute__((naked))
|
||||
void isr_exti1(void)
|
||||
{
|
||||
ISR_ENTER();
|
||||
if (EXTI->PR & EXTI_PR_PR1) {
|
||||
EXTI->PR |= EXTI_PR_PR1; /* clear status bit by writing a 1 to it */
|
||||
irq_handler(GPIO_IRQ_1);
|
||||
}
|
||||
ISR_EXIT();
|
||||
}
|
||||
|
||||
__attribute__((naked))
|
||||
void isr_exti2(void)
|
||||
{
|
||||
ISR_ENTER();
|
||||
if (EXTI->PR & EXTI_PR_PR2) {
|
||||
EXTI->PR |= EXTI_PR_PR2; /* clear status bit by writing a 1 to it */
|
||||
irq_handler(GPIO_IRQ_2);
|
||||
}
|
||||
ISR_EXIT();
|
||||
}
|
||||
|
||||
__attribute__((naked))
|
||||
void isr_exti3(void)
|
||||
{
|
||||
ISR_ENTER();
|
||||
if (EXTI->PR & EXTI_PR_PR3) {
|
||||
EXTI->PR |= EXTI_PR_PR3; /* clear status bit by writing a 1 to it */
|
||||
irq_handler(GPIO_IRQ_3);
|
||||
}
|
||||
ISR_EXIT();
|
||||
}
|
||||
|
||||
__attribute__((naked))
|
||||
void isr_exti4(void)
|
||||
{
|
||||
ISR_ENTER();
|
||||
if (EXTI->PR & EXTI_PR_PR4) {
|
||||
EXTI->PR |= EXTI_PR_PR4; /* clear status bit by writing a 1 to it */
|
||||
irq_handler(GPIO_IRQ_4);
|
||||
}
|
||||
ISR_EXIT();
|
||||
}
|
||||
|
||||
__attribute__((naked))
|
||||
void isr_exti9_5(void)
|
||||
{
|
||||
ISR_ENTER();
|
||||
if (EXTI->PR & EXTI_PR_PR5) {
|
||||
EXTI->PR |= EXTI_PR_PR5; /* clear status bit by writing a 1 to it */
|
||||
irq_handler(GPIO_IRQ_5);
|
||||
}
|
||||
if (EXTI->PR & EXTI_PR_PR6) {
|
||||
EXTI->PR |= EXTI_PR_PR6; /* clear status bit by writing a 1 to it */
|
||||
irq_handler(GPIO_IRQ_6);
|
||||
}
|
||||
if (EXTI->PR & EXTI_PR_PR7) {
|
||||
EXTI->PR |= EXTI_PR_PR7; /* clear status bit by writing a 1 to it */
|
||||
irq_handler(GPIO_IRQ_7);
|
||||
}
|
||||
if (EXTI->PR & EXTI_PR_PR8) {
|
||||
EXTI->PR |= EXTI_PR_PR8; /* clear status bit by writing a 1 to it */
|
||||
irq_handler(GPIO_IRQ_8);
|
||||
}
|
||||
if (EXTI->PR & EXTI_PR_PR9) {
|
||||
EXTI->PR |= EXTI_PR_PR9; /* clear status bit by writing a 1 to it */
|
||||
irq_handler(GPIO_IRQ_9);
|
||||
}
|
||||
ISR_EXIT();
|
||||
}
|
||||
|
||||
__attribute__((naked))
|
||||
void isr_exti15_10(void)
|
||||
{
|
||||
ISR_ENTER();
|
||||
if (EXTI->PR & EXTI_PR_PR10) {
|
||||
EXTI->PR |= EXTI_PR_PR10; /* clear status bit by writing a 1 to it */
|
||||
irq_handler(GPIO_IRQ_10);
|
||||
}
|
||||
if (EXTI->PR & EXTI_PR_PR11) {
|
||||
EXTI->PR |= EXTI_PR_PR11; /* clear status bit by writing a 1 to it */
|
||||
irq_handler(GPIO_IRQ_11);
|
||||
}
|
||||
if (EXTI->PR & EXTI_PR_PR12) {
|
||||
EXTI->PR |= EXTI_PR_PR12; /* clear status bit by writing a 1 to it */
|
||||
irq_handler(GPIO_IRQ_12);
|
||||
}
|
||||
if (EXTI->PR & EXTI_PR_PR13) {
|
||||
EXTI->PR |= EXTI_PR_PR13; /* clear status bit by writing a 1 to it */
|
||||
irq_handler(GPIO_IRQ_13);
|
||||
}
|
||||
if (EXTI->PR & EXTI_PR_PR14) {
|
||||
EXTI->PR |= EXTI_PR_PR14; /* clear status bit by writing a 1 to it */
|
||||
irq_handler(GPIO_IRQ_14);
|
||||
}
|
||||
if (EXTI->PR & EXTI_PR_PR15) {
|
||||
EXTI->PR |= EXTI_PR_PR15; /* clear status bit by writing a 1 to it */
|
||||
irq_handler(GPIO_IRQ_15);
|
||||
}
|
||||
ISR_EXIT();
|
||||
}
|
||||
335
cpu/stm32f4/periph/timer.c
Normal file
335
cpu/stm32f4/periph/timer.c
Normal file
@ -0,0 +1,335 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_stm32f4
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Low-level timer driver implementation
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "board.h"
|
||||
#include "sched.h"
|
||||
#include "thread.h"
|
||||
#include "periph_conf.h"
|
||||
#include "periph/timer.h"
|
||||
|
||||
/** Unified IRQ handler for all timers */
|
||||
static inline void irq_handler(tim_t timer, TIM_TypeDef *dev);
|
||||
|
||||
/** Type for timer state */
|
||||
typedef struct {
|
||||
void (*cb)(int);
|
||||
} timer_conf_t;
|
||||
|
||||
/** Timer state memory */
|
||||
timer_conf_t config[TIMER_NUMOF];
|
||||
|
||||
|
||||
int timer_init(tim_t dev, unsigned int ticks_per_us, void (*callback)(int))
|
||||
{
|
||||
TIM_TypeDef *timer;
|
||||
|
||||
switch (dev) {
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
/* enable timer peripheral clock */
|
||||
TIMER_0_CLKEN();
|
||||
/* set timer's IRQ priority */
|
||||
NVIC_SetPriority(TIMER_0_IRQ_CHAN, TIMER_IRQ_PRIO);
|
||||
/* select timer */
|
||||
timer = TIMER_0_DEV;
|
||||
timer->PSC = TIMER_0_PRESCALER * ticks_per_us;
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
/* enable timer peripheral clock */
|
||||
TIMER_1_CLKEN();
|
||||
/* set timer's IRQ priority */
|
||||
NVIC_SetPriority(TIMER_1_IRQ_CHAN, TIMER_IRQ_PRIO);
|
||||
/* select timer */
|
||||
timer = TIMER_1_DEV;
|
||||
timer->PSC = TIMER_0_PRESCALER * ticks_per_us;
|
||||
break;
|
||||
#endif
|
||||
case TIMER_UNDEFINED:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* set callback function */
|
||||
config[dev].cb = callback;
|
||||
|
||||
/* set timer to run in counter mode */
|
||||
timer->CR1 = 0;
|
||||
timer->CR2 = 0;
|
||||
|
||||
/* set auto-reload and prescaler values and load new values */
|
||||
timer->EGR |= TIM_EGR_UG;
|
||||
|
||||
/* enable the timer's interrupt */
|
||||
timer_irq_enable(dev);
|
||||
|
||||
/* start the timer */
|
||||
timer_start(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_set(tim_t dev, int channel, unsigned int timeout)
|
||||
{
|
||||
int now = timer_read(dev);
|
||||
return timer_set_absolute(dev, channel, now + timeout - 1);
|
||||
}
|
||||
|
||||
int timer_set_absolute(tim_t dev, int channel, unsigned int value)
|
||||
{
|
||||
TIM_TypeDef *timer;
|
||||
|
||||
switch (dev) {
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
timer = TIMER_0_DEV;
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
timer = TIMER_1_DEV;
|
||||
break;
|
||||
#endif
|
||||
case TIMER_UNDEFINED:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (channel) {
|
||||
case 0:
|
||||
timer->CCR1 = value;
|
||||
timer->SR &= ~TIM_SR_CC1IF;
|
||||
timer->DIER |= TIM_DIER_CC1IE;
|
||||
break;
|
||||
case 1:
|
||||
timer->CCR2 = value;
|
||||
timer->SR &= ~TIM_SR_CC2IF;
|
||||
timer->DIER |= TIM_DIER_CC2IE;
|
||||
break;
|
||||
case 2:
|
||||
timer->CCR3 = value;
|
||||
timer->SR &= ~TIM_SR_CC3IF;
|
||||
timer->DIER |= TIM_DIER_CC3IE;
|
||||
break;
|
||||
case 3:
|
||||
timer->CCR4 = value;
|
||||
timer->SR &= ~TIM_SR_CC4IF;
|
||||
timer->DIER |= TIM_DIER_CC4IE;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_clear(tim_t dev, int channel)
|
||||
{
|
||||
TIM_TypeDef *timer;
|
||||
|
||||
switch (dev) {
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
timer = TIMER_0_DEV;
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
timer = TIMER_1_DEV;
|
||||
break;
|
||||
#endif
|
||||
case TIMER_UNDEFINED:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (channel) {
|
||||
case 0:
|
||||
timer->DIER &= ~TIM_DIER_CC1IE;
|
||||
break;
|
||||
case 1:
|
||||
timer->DIER &= ~TIM_DIER_CC2IE;
|
||||
break;
|
||||
case 2:
|
||||
timer->DIER &= ~TIM_DIER_CC3IE;
|
||||
break;
|
||||
case 3:
|
||||
timer->DIER &= ~TIM_DIER_CC4IE;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int timer_read(tim_t dev)
|
||||
{
|
||||
switch (dev) {
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
return TIMER_0_DEV->CNT;
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
return TIMER_1_DEV->CNT;
|
||||
break;
|
||||
#endif
|
||||
case TIMER_UNDEFINED:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_start(tim_t dev)
|
||||
{
|
||||
switch (dev) {
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
TIMER_0_DEV->CR1 |= TIM_CR1_CEN;
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
TIMER_1_DEV->CR1 |= TIM_CR1_CEN;
|
||||
break;
|
||||
#endif
|
||||
case TIMER_UNDEFINED:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_stop(tim_t dev)
|
||||
{
|
||||
switch (dev) {
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
TIMER_0_DEV->CR1 &= ~TIM_CR1_CEN;
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
TIMER_1_DEV->CR1 &= ~TIM_CR1_CEN;
|
||||
break;
|
||||
#endif
|
||||
case TIMER_UNDEFINED:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_irq_enable(tim_t dev)
|
||||
{
|
||||
switch (dev) {
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
NVIC_EnableIRQ(TIMER_0_IRQ_CHAN);
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
NVIC_EnableIRQ(TIMER_1_IRQ_CHAN);
|
||||
break;
|
||||
#endif
|
||||
case TIMER_UNDEFINED:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_irq_disable(tim_t dev)
|
||||
{
|
||||
switch (dev) {
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
NVIC_DisableIRQ(TIMER_0_IRQ_CHAN);
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
NVIC_DisableIRQ(TIMER_1_IRQ_CHAN);
|
||||
break;
|
||||
#endif
|
||||
case TIMER_UNDEFINED:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_reset(tim_t dev)
|
||||
{
|
||||
switch (dev) {
|
||||
#if TIMER_0_EN
|
||||
case TIMER_0:
|
||||
TIMER_0_DEV->CNT = 0;
|
||||
break;
|
||||
#endif
|
||||
#if TIMER_1_EN
|
||||
case TIMER_1:
|
||||
TIMER_1_DEV->CNT = 0;
|
||||
break;
|
||||
#endif
|
||||
case TIMER_UNDEFINED:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__ ((naked)) void TIMER_0_ISR(void)
|
||||
{
|
||||
ISR_ENTER();
|
||||
irq_handler(TIMER_0, TIMER_0_DEV);
|
||||
ISR_EXIT();
|
||||
}
|
||||
|
||||
__attribute__ ((naked)) void TIMER_1_ISR(void)
|
||||
{
|
||||
ISR_ENTER();
|
||||
irq_handler(TIMER_1, TIMER_1_DEV);
|
||||
ISR_EXIT();
|
||||
}
|
||||
|
||||
static inline void irq_handler(tim_t timer, TIM_TypeDef *dev)
|
||||
{
|
||||
if (dev->SR & TIM_SR_CC1IF) {
|
||||
dev->DIER &= ~TIM_DIER_CC1IE;
|
||||
dev->SR &= ~TIM_SR_CC1IF;
|
||||
config[timer].cb(0);
|
||||
}
|
||||
else if (dev->SR & TIM_SR_CC2IF) {
|
||||
dev->DIER &= ~TIM_DIER_CC2IE;
|
||||
dev->SR &= ~TIM_SR_CC2IF;
|
||||
config[timer].cb(1);
|
||||
}
|
||||
else if (dev->SR & TIM_SR_CC3IF) {
|
||||
dev->DIER &= ~TIM_DIER_CC3IE;
|
||||
dev->SR &= ~TIM_SR_CC3IF;
|
||||
config[timer].cb(2);
|
||||
}
|
||||
else if (dev->SR & TIM_SR_CC4IF) {
|
||||
dev->DIER &= ~TIM_DIER_CC4IE;
|
||||
dev->SR &= ~TIM_SR_CC4IF;
|
||||
config[timer].cb(3);
|
||||
}
|
||||
if (sched_context_switch_request) {
|
||||
thread_yield();
|
||||
}
|
||||
}
|
||||
313
cpu/stm32f4/periph/uart.c
Normal file
313
cpu/stm32f4/periph/uart.c
Normal file
@ -0,0 +1,313 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_stm32f4
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Low-level UART driver implementation
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "thread.h"
|
||||
#include "sched.h"
|
||||
#include "periph_conf.h"
|
||||
#include "periph/uart.h"
|
||||
|
||||
|
||||
/**
|
||||
* @brief Each UART device has to store two callbacks.
|
||||
*/
|
||||
typedef struct {
|
||||
void (*rx_cb)(char);
|
||||
void (*tx_cb)(void);
|
||||
} uart_conf_t;
|
||||
|
||||
/**
|
||||
* @brief Unified interrupt handler for all UART devices
|
||||
*
|
||||
* @param uartnum the number of the UART that triggered the ISR
|
||||
* @param uart the UART device that triggered the ISR
|
||||
*/
|
||||
static inline void irq_handler(uart_t uartnum, USART_TypeDef *uart);
|
||||
|
||||
/**
|
||||
* @brief Allocate memory to store the callback functions.
|
||||
*/
|
||||
static uart_conf_t config[UART_NUMOF];
|
||||
|
||||
int uart_init(uart_t uart, uint32_t baudrate, void (*rx_cb)(char), void (*tx_cb)(void))
|
||||
{
|
||||
/* do basic initialization */
|
||||
int res = uart_init_blocking(uart, baudrate);
|
||||
if (res < 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
/* remember callback addresses */
|
||||
config[uart].rx_cb = rx_cb;
|
||||
config[uart].tx_cb = tx_cb;
|
||||
|
||||
/* enable receive interrupt */
|
||||
switch (uart) {
|
||||
#if UART_0_EN
|
||||
case UART_0:
|
||||
NVIC_SetPriority(UART_0_IRQ_CHAN, UART_IRQ_PRIO);
|
||||
NVIC_EnableIRQ(UART_0_IRQ_CHAN);
|
||||
UART_0_DEV->CR1 |= USART_CR1_RXNEIE;
|
||||
break;
|
||||
#endif
|
||||
#if UART_1_EN
|
||||
case UART_1:
|
||||
NVIC_SetPriority(UART_1_IRQ_CHAN, UART_IRQ_PRIO);
|
||||
NVIC_EnableIRQ(UART_1_IRQ_CHAN);
|
||||
UART_1_DEV->CR1 |= USART_CR1_RXNEIE;
|
||||
break;
|
||||
#endif
|
||||
case UART_UNDEFINED:
|
||||
default:
|
||||
return -2;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uart_init_blocking(uart_t uart, uint32_t baudrate)
|
||||
{
|
||||
USART_TypeDef *dev;
|
||||
GPIO_TypeDef *port;
|
||||
uint32_t tx_pin;
|
||||
uint32_t rx_pin;
|
||||
uint8_t af;
|
||||
float clk;
|
||||
float divider;
|
||||
uint16_t mantissa;
|
||||
uint8_t fraction;
|
||||
|
||||
switch (uart) {
|
||||
#if UART_0_EN
|
||||
case UART_0:
|
||||
dev = UART_0_DEV;
|
||||
port = UART_0_PORT;
|
||||
clk = UART_0_CLK;
|
||||
tx_pin = UART_0_TX_PIN;
|
||||
rx_pin = UART_0_RX_PIN;
|
||||
af = UART_0_AF;
|
||||
UART_0_CLKEN();
|
||||
UART_0_PORT_CLKEN();
|
||||
break;
|
||||
#endif
|
||||
#if UART_1_EN
|
||||
case UART_1:
|
||||
dev = UART_1_DEV;
|
||||
port = UART_1_PORT;
|
||||
clk = UART_1_CLK;
|
||||
tx_pin = UART_1_TX_PIN;
|
||||
rx_pin = UART_1_RX_PIN;
|
||||
af = UART_1_AF;
|
||||
UART_1_CLKEN();
|
||||
UART_1_PORT_CLKEN();
|
||||
break;
|
||||
#endif
|
||||
case UART_UNDEFINED:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* configure RX and TX pins, set pin to use alternative function mode */
|
||||
port->MODER &= ~(3 << (rx_pin * 2) | 3 << (tx_pin * 2));
|
||||
port->MODER |= 2 << (rx_pin * 2) | 2 << (tx_pin * 2);
|
||||
/* and assign alternative function */
|
||||
if (rx_pin < 8) {
|
||||
port->AFR[0] &= ~(0xf << (rx_pin * 4));
|
||||
port->AFR[0] |= af << (rx_pin * 4);
|
||||
}
|
||||
else {
|
||||
port->AFR[1] &= ~(0xf << ((rx_pin - 8) * 4));
|
||||
port->AFR[1] |= af << ((rx_pin - 8) * 4);
|
||||
}
|
||||
if (tx_pin < 8) {
|
||||
port->AFR[0] &= ~(0xf << (tx_pin * 4));
|
||||
port->AFR[0] |= af << (tx_pin * 4);
|
||||
}
|
||||
else {
|
||||
port->AFR[1] &= ~(0xf << ((tx_pin - 8) * 4));
|
||||
port->AFR[1] |= af << ((tx_pin - 8) * 4);
|
||||
}
|
||||
|
||||
/* configure UART to mode 8N1 with given baudrate */
|
||||
divider = clk / (16 * baudrate);
|
||||
mantissa = (uint16_t)divider;
|
||||
fraction = (uint8_t)((divider - mantissa) * 16);
|
||||
dev->BRR = ((mantissa & 0x0fff) << 4) | (0x0f & fraction);
|
||||
|
||||
/* enable receive and transmit mode */
|
||||
dev->CR3 = 0;
|
||||
dev->CR2 = 0;
|
||||
dev->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uart_tx_begin(uart_t uart)
|
||||
{
|
||||
switch (uart) {
|
||||
#if UART_0_EN
|
||||
case UART_0:
|
||||
UART_0_DEV->CR1 |= USART_CR1_TXEIE;
|
||||
break;
|
||||
#endif
|
||||
#if UART_1_EN
|
||||
case UART_1:
|
||||
UART_1_DEV->CR1 |= USART_CR1_TXEIE;
|
||||
break;
|
||||
#endif
|
||||
case UART_UNDEFINED:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void uart_tx_end(uart_t uart)
|
||||
{
|
||||
switch (uart) {
|
||||
#if UART_0_EN
|
||||
case UART_0:
|
||||
UART_0_DEV->CR1 &= ~USART_CR1_TXEIE;
|
||||
break;
|
||||
#endif
|
||||
#if UART_1_EN
|
||||
case UART_1:
|
||||
UART_1_DEV->CR1 &= ~USART_CR1_TXEIE;
|
||||
break;
|
||||
#endif
|
||||
case UART_UNDEFINED:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int uart_write(uart_t uart, char data)
|
||||
{
|
||||
USART_TypeDef *dev;
|
||||
|
||||
switch (uart) {
|
||||
#if UART_0_EN
|
||||
case UART_0:
|
||||
dev = UART_0_DEV;
|
||||
break;
|
||||
#endif
|
||||
#if UART_1_EN
|
||||
case UART_1:
|
||||
dev = UART_1_DEV;
|
||||
break;
|
||||
#endif
|
||||
case UART_UNDEFINED:
|
||||
default:
|
||||
return -2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dev->SR & USART_SR_TXE) {
|
||||
dev->DR = (uint8_t)data;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uart_read_blocking(uart_t uart, char *data)
|
||||
{
|
||||
USART_TypeDef *dev;
|
||||
|
||||
switch (uart) {
|
||||
#if UART_0_EN
|
||||
case UART_0:
|
||||
dev = UART_0_DEV;
|
||||
break;
|
||||
#endif
|
||||
#if UART_1_EN
|
||||
case UART_1:
|
||||
dev = UART_1_DEV;
|
||||
break;
|
||||
#endif
|
||||
case UART_UNDEFINED:
|
||||
default:
|
||||
return -2;
|
||||
break;
|
||||
}
|
||||
|
||||
while (!(dev->SR & USART_SR_RXNE));
|
||||
*data = (char)dev->DR;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uart_write_blocking(uart_t uart, char data)
|
||||
{
|
||||
USART_TypeDef *dev;
|
||||
|
||||
switch (uart) {
|
||||
#if UART_0_EN
|
||||
case UART_0:
|
||||
dev = UART_0_DEV;
|
||||
break;
|
||||
#endif
|
||||
#if UART_1_EN
|
||||
case UART_1:
|
||||
dev = UART_1_DEV;
|
||||
break;
|
||||
#endif
|
||||
case UART_UNDEFINED:
|
||||
default:
|
||||
return -2;
|
||||
break;
|
||||
}
|
||||
|
||||
while (!(dev->SR & USART_SR_TXE));
|
||||
dev->DR = (uint8_t)data;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
__attribute__((naked))
|
||||
void UART_0_ISR(void)
|
||||
{
|
||||
ISR_ENTER();
|
||||
irq_handler(UART_0, UART_0_DEV);
|
||||
ISR_EXIT();
|
||||
}
|
||||
|
||||
__attribute__((naked))
|
||||
void UART_1_ISR(void)
|
||||
{
|
||||
ISR_ENTER();
|
||||
irq_handler(UART_1, UART_1_DEV);
|
||||
ISR_EXIT();
|
||||
}
|
||||
|
||||
static inline void irq_handler(uint8_t uartnum, USART_TypeDef *dev)
|
||||
{
|
||||
if (dev->SR & USART_SR_RXNE) {
|
||||
char data = (char)dev->DR;
|
||||
config[uartnum].rx_cb(data);
|
||||
}
|
||||
else if (dev->SR & USART_SR_TXE) {
|
||||
config[uartnum].tx_cb();
|
||||
}
|
||||
if (sched_context_switch_request) {
|
||||
thread_yield();
|
||||
}
|
||||
}
|
||||
34
cpu/stm32f4/reboot_arch.c
Normal file
34
cpu/stm32f4/reboot_arch.c
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_stm32f4
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Implementation of the kernels reboot interface
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "arch/reboot_arch.h"
|
||||
#include "cpu.h"
|
||||
|
||||
|
||||
int reboot_arch(int mode)
|
||||
{
|
||||
printf("Going into reboot, mode %i\n", mode);
|
||||
|
||||
NVIC_SystemReset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
307
cpu/stm32f4/startup.c
Normal file
307
cpu/stm32f4/startup.c
Normal file
@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_stm32f4
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Startup code and interrupt vector definition
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* memory markers as defined in the linker script
|
||||
*/
|
||||
extern uint32_t _sfixed;
|
||||
extern uint32_t _efixed;
|
||||
extern uint32_t _etext;
|
||||
extern uint32_t _srelocate;
|
||||
extern uint32_t _erelocate;
|
||||
extern uint32_t _szero;
|
||||
extern uint32_t _ezero;
|
||||
extern uint32_t _sstack;
|
||||
extern uint32_t _estack;
|
||||
|
||||
/**
|
||||
* @brief functions for initializing the board, std-lib and kernel
|
||||
*/
|
||||
extern void board_init(void);
|
||||
extern void kernel_init(void);
|
||||
extern void __libc_init_array(void);
|
||||
|
||||
/**
|
||||
* @brief This function is the entry point after a system reset
|
||||
*
|
||||
* After a system reset, the following steps are necessary and carried out:
|
||||
* 1. load data section from flash to ram
|
||||
* 2. overwrite uninitialized data section (BSS) with zeros
|
||||
* 3. initialize the newlib
|
||||
* 4. initialize the board (sync clock, setup std-IO)
|
||||
* 5. initialize and start RIOTs kernel
|
||||
*/
|
||||
void reset_handler(void)
|
||||
{
|
||||
uint32_t *dst;
|
||||
uint32_t *src = &_etext;
|
||||
|
||||
/* load data section from flash to ram */
|
||||
for (dst = &_srelocate; dst < &_erelocate; ) {
|
||||
*(dst++) = *(src++);
|
||||
}
|
||||
|
||||
/* default bss section to zero */
|
||||
for (dst = &_szero; dst < &_ezero; ) {
|
||||
*(dst++) = 0;
|
||||
}
|
||||
|
||||
/* initialize the board and startup the kernel */
|
||||
board_init();
|
||||
/* initialize std-c library (this should be done after board_init) */
|
||||
__libc_init_array();
|
||||
/* startup the kernel */
|
||||
kernel_init();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Default handler is called in case no interrupt handler was defined
|
||||
*/
|
||||
void dummy_handler(void)
|
||||
{
|
||||
while (1) {asm ("nop");}
|
||||
}
|
||||
|
||||
void isr_nmi(void)
|
||||
{
|
||||
while (1) {asm ("nop");}
|
||||
}
|
||||
|
||||
void isr_mem_manage(void)
|
||||
{
|
||||
while (1) {asm ("nop");}
|
||||
}
|
||||
|
||||
void isr_debug_mon(void)
|
||||
{
|
||||
while (1) {asm ("nop");}
|
||||
}
|
||||
|
||||
void isr_hard_fault(void)
|
||||
{
|
||||
while (1) {asm ("nop");}
|
||||
}
|
||||
|
||||
void isr_bus_fault(void)
|
||||
{
|
||||
while (1) {asm ("nop");}
|
||||
}
|
||||
|
||||
void isr_usage_fault(void)
|
||||
{
|
||||
while (1) {asm ("nop");}
|
||||
}
|
||||
|
||||
/* Cortex-M specific interrupt vectors */
|
||||
void isr_svc(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_pendsv(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_systick(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
|
||||
/* STM32F4 specific interrupt vector */
|
||||
void isr_wwdg(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_pvd(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_tamp_stamp(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_rtc_wkup(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_flash(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_rcc(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_exti0(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_exti1(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_exti2(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_exti3(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_exti4(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_dma1_stream0(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_dma1_stream1(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_dma1_stream2(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_dma1_stream3(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_dma1_stream4(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_dma1_stream5(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_dma1_stream6(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_adc(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_can1_tx(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_can1_rx0(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_can1_rx1(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_can1_sce(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_exti9_5(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_tim1_brk_tim9(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_tim1_up_tim10(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_tim1_trg_com_tim11(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_tim1_cc(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_tim2(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_tim3(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_tim4(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_i2c1_ev(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_i2c1_er(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_i2c2_ev(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_i2c2_er(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_spi1(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_spi2(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_usart1(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_usart2(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_usart3(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_exti15_10(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_rtc_alarm(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_otg_fs_wkup(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_tim8_brk_tim12(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_tim8_up_tim13(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_tim8_trg_com_tim14(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_tim8_cc(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_dma1_stream7(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_fsmc(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_sdio(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_tim5(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_spi3(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_uart4(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_uart5(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_tim6_dac(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_tim7(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_dma2_stream0(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_dma2_stream1(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_dma2_stream2(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_dma2_stream3(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_dma2_stream4(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_eth(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_eth_wkup(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_can2_tx(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_can2_rx0(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_can2_rx1(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_can2_sce(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_otg_fs(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_dma2_stream5(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_dma2_stream6(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_dma2_stream7(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_usart6(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_i2c3_ev(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_i2c3_er(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_otg_hs_ep1_out(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_otg_hs_ep1_in(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_otg_hs_wkup(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_otg_hs(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_dcmi(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_cryp(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_hash_rng(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
void isr_fpu(void) __attribute__ ((weak, alias("dummy_handler")));
|
||||
|
||||
/* interrupt vector table */
|
||||
__attribute__ ((section(".vectors")))
|
||||
const void *interrupt_vector[] = {
|
||||
/* Stack pointer */
|
||||
(void*) (&_estack), /* pointer to the top of the empty stack */
|
||||
/* Cortex-M4 handlers */
|
||||
(void*) reset_handler, /* entry point of the program */
|
||||
(void*) isr_nmi, /* non maskable interrupt handler */
|
||||
(void*) isr_hard_fault, /* if you end up here its not good */
|
||||
(void*) isr_mem_manage, /* memory controller interrupt */
|
||||
(void*) isr_bus_fault, /* also not good to end up here */
|
||||
(void*) isr_usage_fault, /* autsch */
|
||||
(void*) (0UL), /* Reserved */
|
||||
(void*) (0UL), /* Reserved */
|
||||
(void*) (0UL), /* Reserved */
|
||||
(void*) (0UL), /* Reserved */
|
||||
(void*) isr_svc, /* system call interrupt */
|
||||
(void*) isr_debug_mon, /* debug interrupt */
|
||||
(void*) (0UL), /* Reserved */
|
||||
(void*) isr_pendsv, /* pendSV interrupt, used for task switching in RIOT */
|
||||
(void*) isr_systick, /* SysTick interrupt, not used in RIOT */
|
||||
/* STM specific peripheral handlers */
|
||||
(void*) isr_wwdg, /* Window WatchDog */
|
||||
(void*) isr_pvd, /* PVD through EXTI Line detection */
|
||||
(void*) isr_tamp_stamp, /* Tamper and TimeStamps through the EXTI line */
|
||||
(void*) isr_rtc_wkup, /* RTC Wakeup through the EXTI line */
|
||||
(void*) isr_flash, /* FLASH */
|
||||
(void*) isr_rcc, /* RCC */
|
||||
(void*) isr_exti0, /* EXTI Line0 */
|
||||
(void*) isr_exti1, /* EXTI Line1 */
|
||||
(void*) isr_exti2, /* EXTI Line2 */
|
||||
(void*) isr_exti3, /* EXTI Line3 */
|
||||
(void*) isr_exti4, /* EXTI Line4 */
|
||||
(void*) isr_dma1_stream0, /* DMA1 Stream 0 */
|
||||
(void*) isr_dma1_stream1, /* DMA1 Stream 1 */
|
||||
(void*) isr_dma1_stream2, /* DMA1 Stream 2 */
|
||||
(void*) isr_dma1_stream3, /* DMA1 Stream 3 */
|
||||
(void*) isr_dma1_stream4, /* DMA1 Stream 4 */
|
||||
(void*) isr_dma1_stream5, /* DMA1 Stream 5 */
|
||||
(void*) isr_dma1_stream6, /* DMA1 Stream 6 */
|
||||
(void*) isr_adc, /* ADC1, ADC2 and ADC3s */
|
||||
(void*) isr_can1_tx, /* CAN1 TX */
|
||||
(void*) isr_can1_rx0, /* CAN1 RX0 */
|
||||
(void*) isr_can1_rx1, /* CAN1 RX1 */
|
||||
(void*) isr_can1_sce, /* CAN1 SCE */
|
||||
(void*) isr_exti9_5, /* External Line[9:5]s */
|
||||
(void*) isr_tim1_brk_tim9, /* TIM1 Break and TIM9 */
|
||||
(void*) isr_tim1_up_tim10, /* TIM1 Update and TIM10 */
|
||||
(void*) isr_tim1_trg_com_tim11, /* TIM1 Trigger and Commutation and TIM11 */
|
||||
(void*) isr_tim1_cc, /* TIM1 Capture Compare */
|
||||
(void*) isr_tim2, /* TIM2 */
|
||||
(void*) isr_tim3, /* TIM3 */
|
||||
(void*) isr_tim4, /* TIM4 */
|
||||
(void*) isr_i2c1_ev, /* I2C1 Event */
|
||||
(void*) isr_i2c1_er, /* I2C1 Error */
|
||||
(void*) isr_i2c2_ev, /* I2C2 Event */
|
||||
(void*) isr_i2c2_er, /* I2C2 Error */
|
||||
(void*) isr_spi1, /* SPI1 */
|
||||
(void*) isr_spi2, /* SPI2 */
|
||||
(void*) isr_usart1, /* USART1 */
|
||||
(void*) isr_usart2, /* USART2 */
|
||||
(void*) isr_usart3, /* USART3 */
|
||||
(void*) isr_exti15_10, /* External Line[15:10]s */
|
||||
(void*) isr_rtc_alarm, /* RTC Alarm (A and B) through EXTI Line */
|
||||
(void*) isr_otg_fs_wkup, /* USB OTG FS Wakeup through EXTI line */
|
||||
(void*) isr_tim8_brk_tim12, /* TIM8 Break and TIM12 */
|
||||
(void*) isr_tim8_up_tim13, /* TIM8 Update and TIM13 */
|
||||
(void*) isr_tim8_trg_com_tim14, /* TIM8 Trigger and Commutation and TIM14 */
|
||||
(void*) isr_tim8_cc, /* TIM8 Capture Compare */
|
||||
(void*) isr_dma1_stream7, /* DMA1 Stream7 */
|
||||
(void*) isr_fsmc, /* FSMC */
|
||||
(void*) isr_sdio, /* SDIO */
|
||||
(void*) isr_tim5, /* TIM5 */
|
||||
(void*) isr_spi3, /* SPI3 */
|
||||
(void*) isr_uart4, /* UART4 */
|
||||
(void*) isr_uart5, /* UART5 */
|
||||
(void*) isr_tim6_dac, /* TIM6 and DAC1&2 underrun errors */
|
||||
(void*) isr_tim7, /* TIM7 */
|
||||
(void*) isr_dma2_stream0, /* DMA2 Stream 0 */
|
||||
(void*) isr_dma2_stream1, /* DMA2 Stream 1 */
|
||||
(void*) isr_dma2_stream2, /* DMA2 Stream 2 */
|
||||
(void*) isr_dma2_stream3, /* DMA2 Stream 3 */
|
||||
(void*) isr_dma2_stream4, /* DMA2 Stream 4 */
|
||||
(void*) isr_eth, /* Ethernet */
|
||||
(void*) isr_eth_wkup, /* Ethernet Wakeup through EXTI line */
|
||||
(void*) isr_can2_tx, /* CAN2 TX */
|
||||
(void*) isr_can2_rx0, /* CAN2 RX0 */
|
||||
(void*) isr_can2_rx1, /* CAN2 RX1 */
|
||||
(void*) isr_can2_sce, /* CAN2 SCE */
|
||||
(void*) isr_otg_fs, /* USB OTG FS */
|
||||
(void*) isr_dma2_stream5, /* DMA2 Stream 5 */
|
||||
(void*) isr_dma2_stream6, /* DMA2 Stream 6 */
|
||||
(void*) isr_dma2_stream7, /* DMA2 Stream 7 */
|
||||
(void*) isr_usart6, /* USART6 */
|
||||
(void*) isr_i2c3_ev, /* I2C3 event */
|
||||
(void*) isr_i2c3_er, /* I2C3 error */
|
||||
(void*) isr_otg_hs_ep1_out, /* USB OTG HS End Point 1 Out */
|
||||
(void*) isr_otg_hs_ep1_in, /* USB OTG HS End Point 1 In */
|
||||
(void*) isr_otg_hs_wkup, /* USB OTG HS Wakeup through EXTI */
|
||||
(void*) isr_otg_hs, /* USB OTG HS */
|
||||
(void*) isr_dcmi, /* DCMI */
|
||||
(void*) isr_cryp, /* CRYP crypto */
|
||||
(void*) isr_hash_rng, /* Hash and Rng */
|
||||
(void*) isr_fpu, /* FPU */
|
||||
};
|
||||
144
cpu/stm32f4/stm32f407vg_linkerscript.ld
Normal file
144
cpu/stm32f4/stm32f407vg_linkerscript.ld
Normal file
@ -0,0 +1,144 @@
|
||||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following condition is met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL 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.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
SEARCH_DIR(.)
|
||||
|
||||
/* Memory Spaces Definitions */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
|
||||
ccmram (rwx): ORIGIN = 0x10000000, LENGTH = 64K
|
||||
}
|
||||
|
||||
/* The stack size used by the application. NOTE: you need to adjust */
|
||||
STACK_SIZE = DEFINED(STACK_SIZE) ? STACK_SIZE : 0x2000 ;
|
||||
|
||||
|
||||
/* Section Definitions */
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_sfixed = .;
|
||||
KEEP(*(.vectors .vectors.*))
|
||||
*(.text .text.* .gnu.linkonce.t.*)
|
||||
*(.glue_7t) *(.glue_7)
|
||||
*(.rodata .rodata* .gnu.linkonce.r.*)
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
|
||||
/* Support C constructors, and C destructors in both user code
|
||||
and the C library. This also provides support for C++ code. */
|
||||
. = 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(0x4);
|
||||
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))
|
||||
|
||||
. = ALIGN(4);
|
||||
_efixed = .; /* End of text section */
|
||||
} > rom
|
||||
|
||||
/* .ARM.exidx is sorted, so has to go in its own output section. */
|
||||
PROVIDE_HIDDEN (__exidx_start = .);
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > rom
|
||||
PROVIDE_HIDDEN (__exidx_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
_etext = .;
|
||||
|
||||
.relocate : AT (_etext)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_srelocate = .;
|
||||
*(.ramfunc .ramfunc.*);
|
||||
*(.data .data.*);
|
||||
. = ALIGN(4);
|
||||
_erelocate = .;
|
||||
} > ram
|
||||
|
||||
/* .bss section which is used for uninitialized data */
|
||||
.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_sbss = . ;
|
||||
_szero = .;
|
||||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
_ebss = . ;
|
||||
_ezero = .;
|
||||
} > ram
|
||||
|
||||
/* stack section */
|
||||
.stack (NOLOAD):
|
||||
{
|
||||
. = ALIGN(8);
|
||||
_sstack = .;
|
||||
. = . + STACK_SIZE;
|
||||
. = ALIGN(8);
|
||||
_estack = .;
|
||||
} > ram
|
||||
|
||||
. = ALIGN(4);
|
||||
_end = . ;
|
||||
}
|
||||
271
cpu/stm32f4/syscalls.c
Normal file
271
cpu/stm32f4/syscalls.c
Normal file
@ -0,0 +1,271 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_stm32f4
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief NewLib system call implementations for STM32F4
|
||||
*
|
||||
* @author Michael Baar <michael.baar@fu-berlin.de>
|
||||
* @author Stefan Pfeiffer <pfeiffer@inf.fu-berlin.de>
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "board.h"
|
||||
#include "thread.h"
|
||||
#include "kernel.h"
|
||||
#include "irq.h"
|
||||
#include "periph/uart.h"
|
||||
|
||||
/**
|
||||
* manage the heap
|
||||
*/
|
||||
extern uint32_t _end; /* address of last used memory cell */
|
||||
caddr_t heap_top = (caddr_t)&_end + 4;
|
||||
|
||||
/**
|
||||
* @brief Initialize NewLib, called by __libc_init_array() from the startup script
|
||||
*/
|
||||
void _init(void)
|
||||
{
|
||||
uart_init_blocking(STDIO, STDIO_BAUDRATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free resources on NewLib de-initialization, not used for RIOT
|
||||
*/
|
||||
void _fini(void)
|
||||
{
|
||||
/* nothing to do here */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exit a program without cleaning up files
|
||||
*
|
||||
* If your system doesn't provide this, it is best to avoid linking with subroutines that
|
||||
* require it (exit, system).
|
||||
*
|
||||
* @param n the exit code, 0 for all OK, >0 for not OK
|
||||
*/
|
||||
void _exit(int n)
|
||||
{
|
||||
printf("#! exit %i: resetting\n", n);
|
||||
NVIC_SystemReset();
|
||||
while(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocate memory from the heap.
|
||||
*
|
||||
* The current heap implementation is very rudimentary, it is only able to allocate
|
||||
* memory. But it does not
|
||||
* - check if the returned address is valid (no check if the memory very exists)
|
||||
* - have any means to free memory again
|
||||
*
|
||||
* TODO: check if the requested memory is really available
|
||||
*
|
||||
* @return [description]
|
||||
*/
|
||||
caddr_t _sbrk_r(struct _reent *r, size_t incr)
|
||||
{
|
||||
unsigned int state = disableIRQ();
|
||||
caddr_t res = heap_top;
|
||||
heap_top += incr;
|
||||
restoreIRQ(state);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the process-ID of the current thread
|
||||
*
|
||||
* @return the process ID of the current thread
|
||||
*/
|
||||
int _getpid(void)
|
||||
{
|
||||
return sched_active_thread->pid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send a signal to a given thread
|
||||
*
|
||||
* @param r TODO
|
||||
* @param pid TODO
|
||||
* @param sig TODO
|
||||
*
|
||||
* @return TODO
|
||||
*/
|
||||
int _kill_r(struct _reent *r, int pid, int sig)
|
||||
{
|
||||
r->_errno = ESRCH; /* not implemented yet */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Open a file
|
||||
*
|
||||
* @param r TODO
|
||||
* @param name TODO
|
||||
* @param mode TODO
|
||||
*
|
||||
* @return TODO
|
||||
*/
|
||||
int _open_r(struct _reent *r, const char *name, int mode)
|
||||
{
|
||||
r->_errno = ENODEV; /* not implemented yet */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read from a file
|
||||
*
|
||||
* All input is read from UART_0. The function will block until a byte is actually read.
|
||||
*
|
||||
* Note: the read function does not buffer - data will be lost if the function is not
|
||||
* called fast enough.
|
||||
*
|
||||
* TODO: implement more sophisticated read call.
|
||||
*
|
||||
* @param r TODO
|
||||
* @param fd TODO
|
||||
* @param buffer TODO
|
||||
* @param int TODO
|
||||
*
|
||||
* @return TODO
|
||||
*/
|
||||
int _read_r(struct _reent *r, int fd, void *buffer, unsigned int count)
|
||||
{
|
||||
char c;
|
||||
char *buff = (char*)buffer;
|
||||
uart_read_blocking(STDIO, &c);
|
||||
buff[0] = c;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write characters to a file
|
||||
*
|
||||
* All output is currently directed to UART_0, independent of the given file descriptor.
|
||||
* The write call will further block until the byte is actually written to the UART.
|
||||
*
|
||||
* TODO: implement more sophisticated write call.
|
||||
*
|
||||
* @param r TODO
|
||||
* @param fd TODO
|
||||
* @param data TODO
|
||||
* @param int TODO
|
||||
*
|
||||
* @return TODO
|
||||
*/
|
||||
int _write_r(struct _reent *r, int fd, const void *data, unsigned int count)
|
||||
{
|
||||
char *c = (char*)data;
|
||||
for (int i = 0; i < count; i++) {
|
||||
uart_write_blocking(STDIO, c[i]);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Close a file
|
||||
*
|
||||
* @param r TODO
|
||||
* @param fd TODO
|
||||
*
|
||||
* @return TODO
|
||||
*/
|
||||
int _close_r(struct _reent *r, int fd)
|
||||
{
|
||||
r->_errno = ENODEV; /* not implemented yet */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set position in a file
|
||||
*
|
||||
* @param r TODO
|
||||
* @param fd TODO
|
||||
* @param pos TODO
|
||||
* @param dir TODO
|
||||
*
|
||||
* @return TODO
|
||||
*/
|
||||
_off_t _lseek_r(struct _reent *r, int fd, _off_t pos, int dir)
|
||||
{
|
||||
r->_errno = ENODEV; /* not implemented yet */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Status of an open file
|
||||
*
|
||||
* @param r TODO
|
||||
* @param fd TODO
|
||||
* @param stat TODO
|
||||
*
|
||||
* @return TODO
|
||||
*/
|
||||
int _fstat_r(struct _reent *r, int fd, struct stat * st)
|
||||
{
|
||||
r->_errno = ENODEV; /* not implemented yet */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Status of a file (by name)
|
||||
*
|
||||
* @param r TODO
|
||||
* @param name TODO
|
||||
* @param stat TODO
|
||||
*
|
||||
* @return TODO
|
||||
*/
|
||||
int _stat_r(struct _reent *r, char *name, struct stat *st)
|
||||
{
|
||||
r->_errno = ENODEV; /* not implemented yet */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Query whether output stream is a terminal
|
||||
*
|
||||
* @param r TODO
|
||||
* @param fd TODO
|
||||
*
|
||||
* @return TODO
|
||||
*/
|
||||
int _isatty_r(struct _reent *r, int fd)
|
||||
{
|
||||
r->_errno = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Remove a file's directory entry
|
||||
*
|
||||
* @param r TODO
|
||||
* @param path TODO
|
||||
*
|
||||
* @return TODO
|
||||
*/
|
||||
int _unlink_r(struct _reent *r, char* path)
|
||||
{
|
||||
r->_errno = ENODEV; /* not implemented yet */
|
||||
return -1;
|
||||
}
|
||||
@ -29,7 +29,7 @@ QUIET ?= 1
|
||||
|
||||
BOARD_INSUFFICIENT_RAM := chronos msb-430h telosb wsn430-v1_3b wsn430-v1_4
|
||||
BOARD_BLACKLIST := arduino-due mbed_lpc1768 msb-430 pttu redbee-econotag udoo z1 qemu-i386 \
|
||||
stm32f0discovery
|
||||
stm32f0discovery stm32f4discovery
|
||||
# mbed_lpc1768: see https://github.com/RIOT-OS/RIOT/issues/675
|
||||
# msb-430: see https://github.com/RIOT-OS/RIOT/issues/658
|
||||
# pttu: see https://github.com/RIOT-OS/RIOT/issues/659
|
||||
@ -37,6 +37,7 @@ BOARD_BLACKLIST := arduino-due mbed_lpc1768 msb-430 pttu redbee-econotag udoo z1
|
||||
# z1: lacks RTC features
|
||||
# qemu-i386: no transceiver, yet
|
||||
# stm32f0discovery: no transceiver, yet
|
||||
# stm32f4discovery: no transceiver, yet
|
||||
|
||||
# Modules to include:
|
||||
|
||||
|
||||
@ -29,7 +29,7 @@ QUIET ?= 1
|
||||
|
||||
BOARD_INSUFFICIENT_RAM := chronos msb-430h telosb wsn430-v1_3b wsn430-v1_4
|
||||
BOARD_BLACKLIST := arduino-due mbed_lpc1768 msb-430 pttu redbee-econotag udoo z1 qemu-i386 \
|
||||
stm32f0discovery
|
||||
stm32f0discovery stm32f4discovery
|
||||
# mbed_lpc1768: see https://github.com/RIOT-OS/RIOT/issues/675
|
||||
# msb-430: see https://github.com/RIOT-OS/RIOT/issues/658
|
||||
# pttu: see https://github.com/RIOT-OS/RIOT/issues/659
|
||||
@ -37,6 +37,7 @@ BOARD_BLACKLIST := arduino-due mbed_lpc1768 msb-430 pttu redbee-econotag udoo z1
|
||||
# z1: lacks RTC features
|
||||
# qemu-i386: no transceiver, yet
|
||||
# stm32f0discovery: no transceiver, yet
|
||||
# stm32f4discovery: no transceiver, yet
|
||||
|
||||
# Modules to include:
|
||||
|
||||
|
||||
@ -28,13 +28,15 @@ RIOTBASE ?= $(CURDIR)/../..
|
||||
QUIET ?= 1
|
||||
|
||||
# Blacklist boards
|
||||
BOARD_BLACKLIST := arduino-due avsextrem chronos mbed_lpc1768 msb-430h msba2 redbee-econotag telosb wsn430-v1_3b wsn430-v1_4 msb-430 pttu udoo qemu-i386 z1 \
|
||||
stm32f0discovery
|
||||
BOARD_BLACKLIST := arduino-due avsextrem chronos mbed_lpc1768 msb-430h msba2 redbee-econotag \
|
||||
telosb wsn430-v1_3b wsn430-v1_4 msb-430 pttu udoo qemu-i386 z1 stm32f0discovery \
|
||||
stm32f4discovery
|
||||
# This example only works with native for now.
|
||||
# msb430-based boards: msp430-g++ is not provided in mspgcc.
|
||||
# (People who want use c++ can build c++ compiler from source, or get binaries from Energia http://energia.nu/)
|
||||
# msba2: some changes should be applied to successfully compile c++. (_kill_r, _kill, __dso_handle)
|
||||
# stm32f0discovery: g++ does not support some used flags (e.g. -mthumb...)
|
||||
# stm32f4discovery: g++ does not support some used flags (e.g. -mthumb...)
|
||||
# others: untested.
|
||||
|
||||
# If you want to add some extra flags when compile c++ files, add these flags
|
||||
|
||||
@ -35,12 +35,14 @@ ifeq ($(shell $(CC) -Wno-cpp -E - 2>/dev/null >/dev/null dev/null ; echo $$?),0)
|
||||
endif
|
||||
|
||||
BOARD_INSUFFICIENT_RAM := chronos msb-430h redbee-econotag telosb wsn430-v1_3b wsn430-v1_4 z1
|
||||
BOARD_BLACKLIST := arduino-due mbed_lpc1768 msb-430 pttu udoo qemu-i386 stm32f0discovery
|
||||
BOARD_BLACKLIST := arduino-due mbed_lpc1768 msb-430 pttu udoo qemu-i386 stm32f0discovery \
|
||||
stm32f4discovery
|
||||
# mbed_lpc1768: see https://github.com/RIOT-OS/RIOT/issues/675
|
||||
# msb-430: see https://github.com/RIOT-OS/RIOT/issues/658
|
||||
# pttu: see https://github.com/RIOT-OS/RIOT/issues/659
|
||||
# qemu-i386: no transceiver, yet
|
||||
# stm32f0discovery: no transceiver, yet
|
||||
# stm32f4discovery: no transceiver, yet
|
||||
|
||||
# Modules to include:
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ APPLICATION = test_coap
|
||||
include ../Makefile.tests_common
|
||||
|
||||
BOARD_BLACKLIST := arduino-due chronos mbed_lpc1768 msb-430 msb-430h qemu-i386 stm32f0discovery \
|
||||
telosb wsn430-v1_3b wsn430-v1_4 udoo z1
|
||||
stm32f4discovery telosb wsn430-v1_3b wsn430-v1_4 udoo z1
|
||||
BOARD_INSUFFICIENT_RAM := redbee-econotag
|
||||
#MSP boards: no assert.h
|
||||
#rest: no radio
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
APPLICATION = test_net_if
|
||||
|
||||
BOARD_BLACKLIST = mbed_lpc1768 arduino-due udoo qemu-i386 stm32f0discovery
|
||||
BOARD_BLACKLIST = mbed_lpc1768 arduino-due udoo qemu-i386 stm32f0discovery stm32f4discovery
|
||||
# qemu-i386: no transceiver, yet
|
||||
# stm32f0discovery: no transceiver, yet
|
||||
# stm32f4discovery: no transceiver, yet
|
||||
|
||||
include ../Makefile.tests_common
|
||||
|
||||
|
||||
@ -2,11 +2,13 @@ APPLICATION = test_pnet
|
||||
include ../Makefile.tests_common
|
||||
|
||||
BOARD_INSUFFICIENT_RAM := chronos msb-430h redbee-econotag telosb wsn430-v1_3b wsn430-v1_4 z1
|
||||
BOARD_BLACKLIST := arduino-due mbed_lpc1768 msb-430 udoo qemu-i386 stm32f0discovery
|
||||
BOARD_BLACKLIST := arduino-due mbed_lpc1768 msb-430 udoo qemu-i386 stm32f0discovery \
|
||||
stm32f4discovery
|
||||
# mbed_lpc1768: see https://github.com/RIOT-OS/RIOT/issues/675
|
||||
# msb-430: see https://github.com/RIOT-OS/RIOT/issues/658
|
||||
# qemu-i386: no transceiver, yet
|
||||
# stm32f0discovery: no transceiver, yet
|
||||
# stm32f4discovery: no transceiver, yet
|
||||
|
||||
USEMODULE += posix
|
||||
USEMODULE += pnet
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user