Merge pull request #5397 from OTAkeys/pr/stm32f2xx

cpu: add stm32f2xx family support (based on #4497)
pr/spi.typo
Kaspar Schleiser 7 years ago committed by GitHub
commit 26e4004de4

@ -0,0 +1,3 @@
MODULE = board
include $(RIOTBASE)/Makefile.base

@ -0,0 +1,15 @@
# Put defined MCU peripherals here (in alphabetical order)
FEATURES_PROVIDED += periph_cpuid
FEATURES_PROVIDED += periph_gpio
FEATURES_PROVIDED += periph_i2c
FEATURES_PROVIDED += periph_pwm
FEATURES_PROVIDED += periph_rtc
FEATURES_PROVIDED += periph_spi
FEATURES_PROVIDED += periph_timer
FEATURES_PROVIDED += periph_uart
# Various other features (if any)
FEATURES_PROVIDED += cpp
# The board MPU family (used for grouping by the CI system)
FEATURES_MCU_GROUP = cortex-m3

@ -0,0 +1,6 @@
# define the cpu used by the nucleo-f207 board
export CPU = stm32f2
export CPU_MODEL = stm32f207zg
# load the common Makefile.include for Nucleo boards
include $(RIOTBOARD)/nucleo-common/Makefile.include

@ -0,0 +1,33 @@
/*
* Copyright (C) 2016 OTA keys S.A.
*
* 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 boards_nucleo-f207
* @{
*
* @file
* @brief Board specific implementations for the nucleo-f207 board
*
* @author Vincent Dupont <vincent@otakeys.com>
*
* @}
*/
#include "board.h"
#include "periph/gpio.h"
void board_init(void)
{
/* initialize the CPU */
cpu_init();
/* initialize the boards LEDs */
gpio_init(LED0_PIN, GPIO_OUT);
gpio_init(LED1_PIN, GPIO_OUT);
gpio_init(LED2_PIN, GPIO_OUT);
}

@ -0,0 +1,7 @@
source [find interface/stlink-v2-1.cfg]
transport select hla_swd
source [find target/stm32f2x.cfg]
reset_config srst_only

@ -0,0 +1,79 @@
/*
* Copyright (C) 2016 OTA keys S.A.
*
* 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 boards_nucleo-f207 Nucleo-F207
* @ingroup boards
* @brief Board specific files for the nucleo-f207 board
* @{
*
* @file
* @brief Board specific definitions for the nucleo-f207 board
*
* @author Vincent Dupont <vincent@otakeys.com
* @author Toon Stegen <toon.stegen@altran.com>
*/
#ifndef BOARD_H_
#define BOARD_H_
#include "board_common.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief LED pin definitions and handlers
* @{
*/
#undef LED0_PIN
#undef LED0_MASK
#undef LED0_ON
#undef LED0_OFF
#undef LED0_TOGGLE
#define LED0_PIN GPIO_PIN(PORT_B, 0)
#define LED0_MASK (1 << 0)
#define LED0_ON (GPIOB->BSRR = LED0_MASK)
#define LED0_OFF (GPIOB->BSRR = (LED0_MASK << 16))
#define LED0_TOGGLE (GPIOB->ODR ^= LED0_MASK)
#define LED1_PIN GPIO_PIN(PORT_B, 7)
#define LED1_MASK (1 << 7)
#define LED1_ON (GPIOB->BSRR = LED1_MASK)
#define LED1_OFF (GPIOB->BSRR = (LED1_MASK << 16))
#define LED1_TOGGLE (GPIOB->ODR ^= LED1_MASK)
#define LED2_PIN GPIO_PIN(PORT_B, 14)
#define LED2_MASK (1 << 14)
#define LED2_ON (GPIOB->BSRR = LED2_MASK)
#define LED2_OFF (GPIOB->BSRR = (LED2_MASK << 16))
#define LED2_TOGGLE (GPIOB->ODR ^= LED2_MASK)
/** @} */
/**
* @brief Use the 1st UART for STDIO on this board
*/
#define UART_STDIO_DEV UART_DEV(0)
/**
* @brief User button
*/
#define BTN_B1_PIN GPIO_PIN(PORT_C, 13)
/**
* @brief Initialize board specific hardware, including clock, LEDs and std-IO
*/
void board_init(void);
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H_ */
/** @} */

@ -0,0 +1,320 @@
/*
* Copyright (C) 2016 OTA keys S.A.
*
* 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 boards_nucleo-f207
* @{
*
* @file
* @name Peripheral MCU configuration for the nucleo-f207 board
*
* @author Vincent Dupont <vincent@otakeys.com>
* @author Aurelien Gonce <aurelien.gonce@altran.fr>
* @author Toon Stegen <toon.stegen@altran.com>
*/
#ifndef PERIPH_CONF_H_
#define PERIPH_CONF_H_
#include "periph_cpu.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Clock system configuration
* @{
*/
#define CLOCK_HSE (8000000U) /* external oscillator */
#define CLOCK_CORECLOCK (120000000U) /* 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_APB1_DIV RCC_CFGR_PPRE1_DIV4
#define CLOCK_APB2_DIV RCC_CFGR_PPRE2_DIV2
#define CLOCK_FLASH_LATENCY FLASH_ACR_LATENCY_5WS
/* bus clocks for simplified peripheral initialization, UPDATE MANUALLY! */
#define CLOCK_AHB (CLOCK_CORECLOCK / 1)
#define CLOCK_APB1 (CLOCK_CORECLOCK / 4)
#define CLOCK_APB2 (CLOCK_CORECLOCK / 2)
/** @} */
/**
* @name PWM configuration
* @{
*/
#define PWM_NUMOF (1U)
#define PWM_0_EN 1
static const pwm_conf_t pwm_config[PWM_NUMOF] = {
{
.tim = 2,
.port = GPIOC,
.bus = AHB1,
.rcc_mask = RCC_AHB1ENR_GPIOCEN,
.CH0 = 6,
.CH1 = 7,
.CH2 = 8,
.CH3 = 9,
.AF = 2
}
};
/** @} */
/**
* @name Timer configuration
* @{
*/
#define TIMER_NUMOF (4U)
#define TIMER_0_EN 1
#define TIMER_1_EN 1
#define TIMER_2_EN 1
#define TIMER_3_EN 1
#define TIMER_IRQ_PRIO 1
static const timer_conf_t timer_config[TIMER_NUMOF] = {
{
.dev = TIM2,
.channels = 4,
.freq = (CLOCK_APB1 * 2),
.rcc_mask = RCC_APB1ENR_TIM2EN,
.bus = APB1,
.irqn = TIM2_IRQn,
.priority = TIMER_IRQ_PRIO
},
{
.dev = TIM5,
.channels = 4,
.freq = (CLOCK_APB1 * 2),
.rcc_mask = RCC_APB1ENR_TIM5EN,
.bus = APB1,
.irqn = TIM5_IRQn,
.priority = TIMER_IRQ_PRIO
},
{
.dev = TIM3,
.channels = 4,
.freq = (CLOCK_APB1 * 2),
.rcc_mask = RCC_APB1ENR_TIM3EN,
.bus = APB1,
.irqn = TIM3_IRQn,
.priority = TIMER_IRQ_PRIO
},
{
.dev = TIM4,
.channels = 4,
.freq = (CLOCK_APB1 * 2),
.rcc_mask = RCC_APB1ENR_TIM4EN,
.bus = APB1,
.irqn = TIM4_IRQn,
.priority = TIMER_IRQ_PRIO
}
};
#define TIMER_0_ISR isr_tim2
#define TIMER_1_ISR isr_tim5
#define TIMER_2_ISR isr_tim3
#define TIMER_3_ISR isr_tim4
/** @} */
/**
* @brief UART configuration
* @{
*/
static const uart_conf_t uart_config[] = {
{
.dev = USART3,
.rcc_mask = RCC_APB1ENR_USART3EN,
.rx_pin = GPIO_PIN(PORT_D, 9),
.tx_pin = GPIO_PIN(PORT_D, 8),
.rts_pin = GPIO_PIN(PORT_D, 12),
.cts_pin = GPIO_PIN(PORT_D, 11),
.rx_mode = GPIO_IN,
.tx_mode = GPIO_OUT,
.af = GPIO_AF7,
.irqn = USART3_IRQn,
.dma_stream = 3,
.dma_chan = 4,
.hw_flow_ctrl = 0
},
{
.dev = USART2,
.rcc_mask = RCC_APB1ENR_USART2EN,
.rx_pin = GPIO_PIN(PORT_D, 6),
.tx_pin = GPIO_PIN(PORT_D, 5),
.rts_pin = GPIO_PIN(PORT_D, 4),
.cts_pin = GPIO_PIN(PORT_D, 3),
.rx_mode = GPIO_IN,
.tx_mode = GPIO_OUT,
.rts_mode = GPIO_OUT,
.cts_mode = GPIO_IN,
.af = GPIO_AF7,
.irqn = USART2_IRQn,
.dma_stream = 6,
.dma_chan = 4,
.hw_flow_ctrl = 1
},
{
.dev = USART1,
.rcc_mask = RCC_APB2ENR_USART1EN,
.rx_pin = GPIO_PIN(PORT_A, 10),
.tx_pin = GPIO_PIN(PORT_A, 9),
.rts_pin = GPIO_PIN(PORT_A, 12),
.cts_pin = GPIO_PIN(PORT_A, 11),
.rx_mode = GPIO_IN,
.tx_mode = GPIO_OUT,
.rts_mode = GPIO_OUT,
.cts_mode = GPIO_IN,
.af = GPIO_AF7,
.irqn = USART1_IRQn,
.dma_stream = 7,
.dma_chan = 4,
.hw_flow_ctrl = 1
}
};
/* assign ISR vector names */
#define UART_0_ISR isr_usart3
#define UART_0_DMA_ISR isr_dma1_stream3
#define UART_1_ISR isr_usart2
#define UART_1_DMA_ISR isr_dma1_stream6
#define UART_2_ISR isr_usart1
#define UART_2_DMA_ISR isr_dma1_stream7
/* deduct number of defined UART interfaces */
#define UART_NUMOF (sizeof(uart_config) / sizeof(uart_config[0]))
/** @} */
/**
* @name SPI configuration
* @{
*/
#define SPI_NUMOF (2U)
#define SPI_0_EN 1
#define SPI_1_EN 1
#define SPI_IRQ_PRIO 1
/* SPI 0 device config */
#define SPI_0_DEV SPI1
#define SPI_0_CLKEN() (RCC->APB2ENR |= RCC_APB2ENR_SPI1EN)
#define SPI_0_CLKDIS() (RCC->APB2ENR &= ~RCC_APB2ENR_SPI1EN)
#define SPI_0_BUS_DIV 1 /* 1 -> SPI bus runs with half CPU clock, 0 -> quarter CPU clock */
#define SPI_0_IRQ SPI1_IRQn
#define SPI_0_IRQ_HANDLER isr_spi1
/* SPI 0 pin configuration */
#define SPI_0_SCK_PORT GPIOA /* A5 pin is shared with the green LED. */
#define SPI_0_SCK_PIN 5
#define SPI_0_SCK_AF 5
#define SPI_0_SCK_PORT_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN)
#define SPI_0_MISO_PORT GPIOA
#define SPI_0_MISO_PIN 6
#define SPI_0_MISO_AF 5
#define SPI_0_MISO_PORT_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN)
#define SPI_0_MOSI_PORT GPIOA
#define SPI_0_MOSI_PIN 7
#define SPI_0_MOSI_AF 5
#define SPI_0_MOSI_PORT_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN)
/* SPI 1 device config */
#define SPI_1_DEV SPI2
#define SPI_1_CLKEN() (RCC->APB1ENR |= RCC_APB1ENR_SPI2EN)
#define SPI_1_CLKDIS() (RCC->APB1ENR &= ~RCC_APB1ENR_SPI2EN)
#define SPI_1_BUS_DIV 0 /* 1 -> SPI bus runs with half CPU clock, 0 -> quarter CPU clock */
#define SPI_1_IRQ SPI2_IRQn
#define SPI_1_IRQ_HANDLER isr_spi2
/* SPI 1 pin configuration */
#define SPI_1_SCK_PORT GPIOB
#define SPI_1_SCK_PIN 3
#define SPI_1_SCK_AF 5
#define SPI_1_SCK_PORT_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN)
#define SPI_1_MISO_PORT GPIOB
#define SPI_1_MISO_PIN 4
#define SPI_1_MISO_AF 5
#define SPI_1_MISO_PORT_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN)
#define SPI_1_MOSI_PORT GPIOB
#define SPI_1_MOSI_PIN 5
#define SPI_1_MOSI_AF 5
#define SPI_1_MOSI_PORT_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN)
/** @} */
/**
* @name I2C configuration
* @{
*/
#define I2C_NUMOF (1U)
#define I2C_0_EN 1
#define I2C_IRQ_PRIO 1
#define I2C_APBCLK (CLOCK_APB1)
/* I2C 0 device configuration */
#define I2C_0_DEV I2C1
#define I2C_0_CLKEN() (RCC->APB1ENR |= RCC_APB1ENR_I2C1EN)
#define I2C_0_CLKDIS() (RCC->APB1ENR &= ~(RCC_APB1ENR_I2C1EN))
#define I2C_0_EVT_IRQ I2C1_EV_IRQn
#define I2C_0_EVT_ISR isr_i2c1_ev
#define I2C_0_ERR_IRQ I2C1_ER_IRQn
#define I2C_0_ERR_ISR isr_i2c1_er
/* I2C 0 pin configuration */
#define I2C_0_SCL_PORT GPIOB
#define I2C_0_SCL_PIN 8
#define I2C_0_SCL_AF 4
#define I2C_0_SCL_PULLUP 0
#define I2C_0_SCL_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN)
#define I2C_0_SDA_PORT GPIOB
#define I2C_0_SDA_PIN 9
#define I2C_0_SDA_AF 4
#define I2C_0_SDA_PULLUP 0
#define I2C_0_SDA_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN)
/** @} */
/**
* @brief ADC configuration
*
* We need to define the following fields:
* PIN, device (ADCx), channel
* @{
*/
#define ADC_CONFIG { \
{GPIO_PIN(PORT_A, 4), 0, 0}, \
{GPIO_PIN(PORT_A, 5), 1, 0} \
}
#define ADC_NUMOF (2)
/** @} */
/**
* @brief DAC configuration
* @{
*/
#define DAC_NUMOF (0)
/** @} */
/**
* @brief RTC configuration
* @{
*/
#define RTC_NUMOF (1)
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* PERIPH_CONF_H_ */
/** @} */

@ -0,0 +1,7 @@
# define the module that is build
MODULE = cpu
# add a list of subdirectories, that should also be build
DIRS = periph $(RIOTCPU)/cortexm_common $(RIOTCPU)/stm32_common
include $(RIOTBASE)/Makefile.base

@ -0,0 +1,5 @@
export CPU_ARCH = cortex-m3
export CPU_FAM = stm32f2
include $(RIOTCPU)/stm32_common/Makefile.include
include $(RIOTCPU)/Makefile.include.cortexm_common

@ -0,0 +1,103 @@
/*
* Copyright (C) 2015 Engineering-Spirit
*
* 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_stm32f2
* @{
*
* @file
* @brief Implementation of the kernel cpu functions
*
* @author Nick v. IJzendoorn <nijzendoorn@engineering-spirit.nl>
* @}
*/
#include "cpu.h"
#include "periph_conf.h"
#ifdef HSI_VALUE
# define RCC_CR_SOURCE RCC_CR_HSION
# define RCC_CR_SOURCE_RDY RCC_CR_HSIRDY
# define RCC_PLL_SOURCE RCC_PLLCFGR_PLLSRC_HSI
#else
# define RCC_CR_SOURCE RCC_CR_HSEON
# define RCC_CR_SOURCE_RDY RCC_CR_HSERDY
# define RCC_PLL_SOURCE RCC_PLLCFGR_PLLSRC_HSE
#endif
static void clk_init(void);
void cpu_init(void)
{
/* initialize the Cortex-M core */
cortexm_init();
/* initialize system clocks */
clk_init();
}
/**
* @brief Configure the clock system of the stm32f2
*
*/
static void clk_init(void)
{
/* Reset the RCC clock configuration to the default reset state(for debug purpose) */
/* Set HSION bit */
RCC->CR |= 0x00000001U;
/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
RCC->CFGR = 0x00000000U;
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= 0xFEF6FFFFU;
/* Reset PLLCFGR register */
RCC->PLLCFGR = 0x24003010U;
/* Reset HSEBYP bit */
RCC->CR &= 0xFFFBFFFFU;
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x00000000U;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration */
/* Enable the high speed clock source */
RCC->CR |= RCC_CR_SOURCE;
/* Wait till hish speed clock source is ready,
* NOTE: the MCU will stay here forever if no HSE clock is connected */
while ((RCC->CR & RCC_CR_SOURCE_RDY) == 0);
/* Configure Flash prefetch, Instruction cache, Data cache and wait state */
FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN;
/* Flash 2 wait state */
FLASH->ACR &= ~((uint32_t)FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)CLOCK_FLASH_LATENCY;
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)CLOCK_AHB_DIV;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)CLOCK_APB2_DIV;
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)CLOCK_APB1_DIV;
/* reset PLL config register */
RCC->PLLCFGR &= ~((uint32_t)(RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLN | RCC_PLLCFGR_PLLM | RCC_PLLCFGR_PLLP | RCC_PLLCFGR_PLLQ));
/* set HSE as source for the PLL */
RCC->PLLCFGR |= RCC_PLL_SOURCE;
/* 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 */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while ((RCC->CR & RCC_CR_PLLRDY) == 0);
/* Select PLL as system clock source */
RCC->CFGR &= ~((uint32_t)(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
}

@ -0,0 +1,54 @@
/*
* Copyright (C) 2015 Engineering-Spirit
*
* 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_stm32f2 STM32F2
* @ingroup cpu
* @brief CPU specific implementations for the STM32F2
* @{
*
* @file
* @brief Implementation specific CPU configuration options
*
* @author Nick v. IJzendoorn <nijzendoorn@engineering-spirit.nl
*/
#ifndef __CPU_CONF_H
#define __CPU_CONF_H
#include "cpu_conf_common.h"
#if defined(CPU_MODEL_STM32F205RG)
#include "stm32f205xx.h"
#elif defined(CPU_MODEL_STM32F207ZG)
#include "stm32f207xx.h"
#elif defined(CPU_MODEL_STM32F215RG) || defined(CPU_MODEL_STM32F215VG) || defined(CPU_MODEL_STM32F215VE)
#include "stm32f215xx.h"
#elif defined(CPU_MODEL_STM32F217ZG)
#include "stm32f217xx.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief ARM Cortex-M specific CPU configuration
* @{
*/
#define CPU_DEFAULT_IRQ_PRIO (1U)
#define CPU_IRQ_NUMOF (81U)
#define CPU_FLASH_BASE FLASH_BASE
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* __CPU_CONF_H */
/** @} */

@ -0,0 +1,304 @@
/*
* Copyright (C) 2015 Engineering-Spirit
* Copyright (C) 2016 OTA keys S.A.
*
* 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_stm32f2
* @{
*
* @file
* @brief CPU specific definitions for internal peripheral handling
*
* @author Nick v. IJzendoorn <nijzendoorn@engineering-spirit.nl>
* @author Aurelien Gonce <aurelien.gonce@altran.fr>
*/
#ifndef PERIPH_CPU_H
#define PERIPH_CPU_H
#include "periph_cpu_common.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Generate GPIO mode bitfields
*
* We use 5 bit to encode the mode:
* - bit 0+1: pin mode (input / output)
* - bit 2+3: pull resistor configuration
* - bit 4: output type (0: push-pull, 1: open-drain)
*/
#define GPIO_MODE(io, pr, ot) ((io << 0) | (pr << 2) | (ot << 4))
/**
* @brief Override GPIO mode options
* @{
*/
#define HAVE_GPIO_MODE_T
typedef enum {
GPIO_IN = GPIO_MODE(0, 0, 0), /**< input w/o pull R */
GPIO_IN_PD = GPIO_MODE(0, 2, 0), /**< input with pull-down */
GPIO_IN_PU = GPIO_MODE(0, 1, 0), /**< input with pull-up */
GPIO_OUT = GPIO_MODE(1, 0, 0), /**< push-pull output */
GPIO_OD = GPIO_MODE(1, 0, 1), /**< open-drain w/o pull R */
GPIO_OD_PU = GPIO_MODE(1, 1, 1) /**< open-drain with pull-up */
} gpio_mode_t;
/** @} */
/**
* @brief Available peripheral buses
*/
enum {
AHB1, /**< AHB1 bus */
AHB2, /**< AHB2 bus */
AHB3 /**< AHB3 bus */
};
/**
* @brief Available ports on the STM32F2 family
*/
enum {
PORT_A = 0, /**< port A */
PORT_B = 1, /**< port B */
PORT_C = 2, /**< port C */
PORT_D = 3, /**< port D */
PORT_E = 4, /**< port E */
PORT_F = 5, /**< port F */
PORT_G = 6, /**< port G */
PORT_H = 7, /**< port H */
PORT_I = 8 /**< port I */
};
/**
* @brief Available MUX values for configuring a pin's alternate function
*/
typedef enum {
GPIO_AF0 = 0, /**< use alternate function 0 */
GPIO_AF1, /**< use alternate function 1 */
GPIO_AF2, /**< use alternate function 2 */
GPIO_AF3, /**< use alternate function 3 */
GPIO_AF4, /**< use alternate function 4 */
GPIO_AF5, /**< use alternate function 5 */
GPIO_AF6, /**< use alternate function 6 */
GPIO_AF7, /**< use alternate function 7 */
GPIO_AF8, /**< use alternate function 8 */
GPIO_AF9, /**< use alternate function 9 */
GPIO_AF10, /**< use alternate function 10 */
GPIO_AF11, /**< use alternate function 11 */
GPIO_AF12, /**< use alternate function 12 */
GPIO_AF13, /**< use alternate function 13 */
GPIO_AF14 /**< use alternate function 14 */
} gpio_af_t;
/**
* @name PWM configuration
* @{
*/
typedef struct {
uint8_t tim; /**< timer used */
GPIO_TypeDef *port; /**< pwm device */
uint8_t bus; /**< AHBx bus */
uint32_t rcc_mask; /**< corresponding bit in the RCC register */
uint8_t CH0; /**< channel 0 */
uint8_t CH1; /**< channel 1 */
uint8_t CH2; /**< channel 2 */
uint8_t CH3; /**< channel 3 */
uint8_t AF; /**< alternate function */
} pwm_conf_t;
/**
* @brief Timer configuration
* @{
*/
typedef struct {
TIM_TypeDef *dev; /**< timer device */
uint8_t channels; /**< number of channel */
uint32_t freq; /**< frequency */
uint32_t rcc_mask; /**< corresponding bit in the RCC register */
uint8_t bus; /**< APBx bus the timer is clock from */
uint8_t irqn; /**< global IRQ channel */
uint8_t priority; /**< priority */
} timer_conf_t;
/** @} */
/**
* @brief Structure for UART configuration data
* @{
*/
typedef struct {
USART_TypeDef *dev; /**< UART device base register address */
uint32_t rcc_mask; /**< bit in clock enable register */
gpio_t rx_pin; /**< RX pin */
gpio_t tx_pin; /**< TX pin */
gpio_mode_t rx_mode; /**< RX pin mode */
gpio_mode_t tx_mode; /**< TX pin mode */
gpio_t rts_pin; /**< RTS pin */
gpio_t cts_pin; /**< CTS pin */
gpio_mode_t rts_mode; /**< RTS pin mode */
gpio_mode_t cts_mode; /**< CTS pin mode */
gpio_af_t af; /**< alternate pin function to use */
uint8_t irqn; /**< IRQ channel */
uint8_t dma_stream; /**< DMA stream used for TX */
uint8_t dma_chan; /**< DMA channel used for TX */
uint8_t hw_flow_ctrl; /**< Support for hardware flow control */
} uart_conf_t;
/** @} */
/**
* @brief Available number of ADC devices
*/
#define ADC_DEVS (2U)
/**
* @brief ADC channel configuration data
*/
typedef struct {
gpio_t pin; /**< pin connected to the channel */
uint8_t dev; /**< ADCx - 1 device used for the channel */
uint8_t chan; /**< CPU ADC channel connected to the pin */
} adc_conf_t;
/**
* @brief Override the ADC resolution configuration
* @{
*/
#define HAVE_ADC_RES_T
typedef enum {
ADC_RES_6BIT = 0x03000000, /**< ADC resolution: 6 bit */
ADC_RES_8BIT = 0x02000000, /**< ADC resolution: 8 bit */
ADC_RES_10BIT = 0x01000000, /**< ADC resolution: 10 bit */
ADC_RES_12BIT = 0x00000000, /**< ADC resolution: 12 bit */
ADC_RES_14BIT = 1, /**< ADC resolution: 14 bit (not supported) */
ADC_RES_16BIT = 2 /**< ADC resolution: 16 bit (not supported)*/
} adc_res_t;
/** @} */
/**
* @brief DAC line configuration data
*/
typedef struct {
gpio_t pin; /**< pin connected to the line */
uint8_t chan; /**< DAC device used for this line */
} dac_conf_t;
/**
* @brief Configure the alternate function for the given pin
*
* @note This is meant for internal use in STM32F2 peripheral drivers only
*
* @param[in] pin pin to configure
* @param[in] af alternate function to use
*/
void gpio_init_af(gpio_t pin, gpio_af_t af);
/**
* @brief Configure the given pin to be used as ADC input
*
* @param[in] pin pin to configure
*/
void gpio_init_analog(gpio_t pin);
/**
* @brief Power on the DMA device the given stream belongs to
*
* @param[in] stream logical DMA stream
*/
static inline void dma_poweron(int stream)
{
if (stream < 8) {
RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN;
} else {
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
}
}
/**
* @brief Get DMA base register
*
* For simplifying DMA stream handling, we map the DMA channels transparently to
* one integer number, such that DMA1 stream0 equals 0, DMA2 stream0 equals 8,
* DMA2 stream 7 equals 15 and so on.
*
* @param[in] stream logical DMA stream
*/
static inline DMA_TypeDef *dma_base(int stream)
{
return (stream < 8) ? DMA1 : DMA2;
}
/**
* @brief Get the DMA stream base address
*
* @param[in] stream logical DMA stream
*
* @return base address for the selected DMA stream
*/
static inline DMA_Stream_TypeDef *dma_stream(int stream)
{
uint32_t base = (uint32_t)dma_base(stream);
return (DMA_Stream_TypeDef *)(base + (0x10 + (0x18 * (stream & 0x7))));
}
/**
* @brief Select high or low DMA interrupt register based on stream number
*
* @param[in] stream logical DMA stream
*
* @return 0 for streams 0-3, 1 for streams 3-7
*/
static inline int dma_hl(int stream)
{
return ((stream & 0x4) >> 2);
}
/**
* @brief Get the interrupt flag clear bit position in the DMA LIFCR register
*
* @param[in] stream logical DMA stream
*/
static inline uint32_t dma_ifc(int stream)
{
switch (stream & 0x3) {
case 0: /* 0 and 4 */
return (1 << 5);
case 1: /* 1 and 5 */
return (1 << 11);
case 2: /* 2 and 6 */
return (1 << 21);
case 3: /* 3 and 7 */
return (1 << 27);
default:
return 0;
}
}
static inline void dma_isr_enable(int stream)
{
if (stream < 7) {
NVIC_EnableIRQ((IRQn_Type)((int)DMA1_Stream0_IRQn + stream));
}
else if (stream == 7) {
NVIC_EnableIRQ(DMA1_Stream7_IRQn);
}
else if (stream < 13) {
NVIC_EnableIRQ((IRQn_Type)((int)DMA2_Stream0_IRQn + (stream - 8)));
}
else if (stream < 16) {
NVIC_EnableIRQ((IRQn_Type)((int)DMA2_Stream5_IRQn + (stream - 13)));
}
}
#ifdef __cplusplus
}
#endif
#endif /* PERIPH_CPU_H */
/** @} */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,32 @@
/*
* Copyright (C) 2015 Engineering-Spirit
* Copyright (C) 2016 OTA keys S.A.
*
* 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.
*/
/**
* @addtogroup cpu_stm32f2
* @{
*
* @file
* @brief Memory definitions for the STM32F205RG
*
* @author Nick v. IJzendoorn <nijzendoorn@engineering-spirit.nl>
* @author Vincent Dupont <vincent@otakeys.com>
*
* @}
*/
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
cpuid (r) : ORIGIN = 0x1fff7a10, LENGTH = 12
}
_cpuid_address = ORIGIN(cpuid);
INCLUDE cortexm_base.ld

@ -0,0 +1,30 @@
/*
* Copyright (C) 2015 Engineering-Spirit
*
* 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.
*/
/**
* @addtogroup cpu_stm32f2
* @{
*
* @file
* @brief Memory definitions for the STM32F207ZG
*
* @author Nick v. IJzendoorn <nijzendoorn@engineering-spirit.nl>
*
* @}
*/
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
cpuid (r) : ORIGIN = 0x1fff7a10, LENGTH = 12
}
_cpuid_address = ORIGIN(cpuid);
INCLUDE cortexm_base.ld

@ -0,0 +1,32 @@
/*
* Copyright (C) 2015 Engineering-Spirit
* Copyright (C) 2016 OTA keys S.A.
*
* 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.
*/
/**
* @addtogroup cpu_stm32f2
* @{
*
* @file
* @brief Memory definitions for the STM32F215RG
*
* @author Nick v. IJzendoorn <nijzendoorn@engineering-spirit.nl>
* @author Vincent Dupont <vincent@otakeys.com>
*
* @}
*/
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
cpuid (r) : ORIGIN = 0x1fff7a10, LENGTH = 12
}
_cpuid_address = ORIGIN(cpuid);
INCLUDE cortexm_base.ld

@ -0,0 +1,32 @@
/*
* Copyright (C) 2015 Engineering-Spirit
* Copyright (C) 2016 OTA keys S.A.
*
* 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.
*/
/**
* @addtogroup cpu_stm32f2
* @{
*
* @file
* @brief Memory definitions for the STM32F215VG
*
* @author Nick v. IJzendoorn <nijzendoorn@engineering-spirit.nl>
* @author Vincent Dupont <vincent@otakeys.com>
*
* @}
*/
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 512K
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
cpuid (r) : ORIGIN = 0x1fff7a10, LENGTH = 12
}
_cpuid_address = ORIGIN(cpuid);
INCLUDE cortexm_base.ld

@ -0,0 +1,32 @@
/*
* Copyright (C) 2015 Engineering-Spirit
* Copyright (C) 2016 OTA keys S.A.
*
* 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.
*/
/**
* @addtogroup cpu_stm32f2
* @{
*
* @file
* @brief Memory definitions for the STM32F215VG
*
* @author Nick v. IJzendoorn <nijzendoorn@engineering-spirit.nl>
* @author Vincent Dupont <vincent@otakeys.com>
*
* @}
*/
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
cpuid (r) : ORIGIN = 0x1fff7a10, LENGTH = 12
}
_cpuid_address = ORIGIN(cpuid);
INCLUDE cortexm_base.ld

@ -0,0 +1,32 @@
/*
* Copyright (C) 2015 Engineering-Spirit
* Copyright (C) 2016 OTA keys S.A.
*
* 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.
*/
/**
* @addtogroup cpu_stm32f2
* @{
*
* @file
* @brief Memory definitions for the STM32F217ZG
*
* @author Nick v. IJzendoorn <nijzendoorn@engineering-spirit.nl>
* @author Vincent Dupont <vincent@otakeys.com>
*
* @}
*/
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
cpuid (r) : ORIGIN = 0x1fff7a10, LENGTH = 12
}
_cpuid_address = ORIGIN(cpuid);
INCLUDE cortexm_base.ld

@ -0,0 +1,98 @@
/*
* Copyright (C) 2015 Engineering-Spirit
*
* 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_stm32f2
* @{
*
* @file
* @brief Implementation of the kernels power management interface
*
* @author Nick v. IJzendoorn <nijzndoorn@engineering-spirit.nl>
*
* @}
*/
#include "cpu.h"
#include "arch/lpm_arch.h"
static enum lpm_mode current_mode = LPM_UNKNOWN;
void lpm_arch_init(void)
{
current_mode = LPM_ON;
}
enum lpm_mode lpm_arch_set(enum lpm_mode target)
{
enum lpm_mode last_mode = current_mode;
switch (target) {
case LPM_ON: /* STM Run mode */
current_mode = LPM_ON;
break;
case LPM_IDLE: /* STM Sleep mode */
current_mode = LPM_IDLE;
/* Reset SLEEPDEEP bit of system control block */
SCB->SCR &= ~(SCB_SCR_SLEEPDEEP_Msk);
/* Enter sleep mode */
__WFI();
break;
case LPM_SLEEP: /* STM Stop mode */
current_mode = LPM_SLEEP;
/* Clear PDDS and LPDS bits to enter stop mode on */
/* deepsleep with voltage regulator on */
PWR->CR &= ~(PWR_CR_PDDS | PWR_CR_LPDS);
/* Set SLEEPDEEP bit of system control block */
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
/* Enter stop mode */
__WFI();
break;
case LPM_POWERDOWN: /* STM Standby mode */
/* Fall-through */
case LPM_OFF: /* STM Standby mode */
current_mode = LPM_POWERDOWN;
/* Set PDDS to enter standby mode on deepsleep and clear flags */
PWR->CR |= (PWR_CR_PDDS | PWR_CR_CWUF | PWR_CR_CSBF);
/* Enable WKUP pin to use for wakeup from standby mode */
PWR->CSR |= PWR_CSR_EWUP;
/* Set SLEEPDEEP bit of system control block */
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
#if defined ( __CC_ARM )
/* Ensure that store operations are completed */
__force_stores();
#endif
/* Enter standby mode */
__WFI();
break;
default:
break;
}
return last_mode;
}
enum lpm_mode lpm_arch_get(void)
{
return current_mode;
}
void lpm_arch_awake(void)
{
if (current_mode == LPM_SLEEP) {
/* After stop mode, the clock system needs to be reconfigured */
cpu_init();
}
current_mode = LPM_ON;
}
/** Not provided */
inline void lpm_arch_begin_awake(void) { }
/** Not provided */
inline void lpm_arch_end_awake(void) { }

@ -0,0 +1,5 @@
# define the module name
MODULE = periph
# include RIOTs generic Makefile
include $(RIOTBASE)/Makefile.base

@ -0,0 +1,138 @@
/*
* Copyright (C) 2016 Engineering-Spirit
*
* 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_stm32f2
* @{
*
* @file
* @brief Low-level ADC driver implementation
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Nick v. IJzendoorn <nijzendoorn@engineering-spirit.nl>
*
* @}
*/
#include "cpu.h"
#include "mutex.h"
#include "periph/adc.h"
#include "periph_conf.h"
/**
* @brief Maximum allowed ADC clock speed
*/
#define MAX_ADC_SPEED (12000000U)
/**
* @brief Load the ADC configuration
* @{
*/
#ifdef ADC_CONFIG
static const adc_conf_t adc_config[] = ADC_CONFIG;
#else
static const adc_conf_t adc_config[] = {};
#endif
/**
* @brief Allocate locks for all three available ADC devices
*/
static mutex_t locks[] = {
#if ADC_DEVS > 1
MUTEX_INIT,
#endif
#if ADC_DEVS > 2
MUTEX_INIT,
#endif
MUTEX_INIT
};
static inline ADC_TypeDef *dev(adc_t line)
{
return (ADC_TypeDef *)(ADC1_BASE + (adc_config[line].dev << 8));
}
static inline void prep(adc_t line)
{
mutex_lock(&locks[adc_config[line].dev]);
RCC->APB2ENR |= (RCC_APB2ENR_ADC1EN << adc_config[line].dev);
}
static inline void done(adc_t line)
{
RCC->APB2ENR &= ~(RCC_APB2ENR_ADC1EN << adc_config[line].dev);
mutex_unlock(&locks[adc_config[line].dev]);
}
int adc_init(adc_t line)
{
uint32_t clk_div = 2;
/* check if the line is valid */
if (line >= ADC_NUMOF) {
return -1;
}
/* lock and power-on the device */
prep(line);
/* configure the pin */
gpio_init_analog(adc_config[line].pin);
/* set clock prescaler to get the maximal possible ADC clock value */
for (clk_div = 2; clk_div < 8; clk_div += 2) {
if ((CLOCK_CORECLOCK / clk_div) <= MAX_ADC_SPEED) {
break;
}
}
ADC->CCR = ((clk_div / 2) - 1) << 16;
/* enable the ADC module */
dev(line)->CR2 = ADC_CR2_ADON;
/* check if this channel is an internal ADC channel, if so
* enable the internal temperature and Vref */
if (adc_config[line].chan == 16 || adc_config[line].chan == 17) {
/* check if the internal channels are configured to use ADC1 */
if (dev(line) != ADC1) {
return -3;
}
ADC->CCR |= ADC_CCR_TSVREFE;
}
/* free the device again */
done(line);
return 0;
}
int adc_sample(adc_t line, adc_res_t res)
{
int sample;
/* check if resolution is applicable */
if (res < 0xff) {
return -1;
}
/* lock and power on the ADC device */
prep(line);
/* set resolution and conversion channel */
dev(line)->CR1 = res;
dev(line)->SQR3 = adc_config[line].chan;
/* start conversion and wait for results */
dev(line)->CR2 |= ADC_CR2_SWSTART;
while (!(dev(line)->SR & ADC_SR_EOC)) {}
/* finally read sample and reset the STRT bit in the status register */
sample = (int)dev(line)->DR;
/* power off and unlock device again */
done(line);
return sample;
}

@ -0,0 +1,76 @@
/*
* Copyright (C) 2015 Engineering-Spirit
*
* 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_stm32f2
* @{
*
* @file
* @brief Low-level DAC driver implementation
*
* @author Nick v. IJzendoorn <nijzendoorn@engineering-spirit.nl>
*
* @}
*/
#include "cpu.h"
#include "periph/dac.h"
#include "periph_conf.h"
/* guard in case that no DAC device is defined */
#if DAC_NUMOF
/**
* @brief Get the DAC configuration from the board (if configured)
* @{
*/
#ifdef DAC_CONFIG
static const dac_conf_t dac_config[] = DAC_CONFIG;
#else
static const dac_conf_t dac_config[] = {};
#endif
/** @} */
int8_t dac_init(dac_t line)
{
if (line >= DAC_NUMOF) {
return -1;
}
/* configure pin */
gpio_init_analog(dac_config[line].pin);
/* enable the DAC's clock */
RCC->APB1ENR |= RCC_APB1ENR_DACEN;
/* reset output and enable the line's channel */
dac_set(line, 0);
dac_poweron(line);
return 0;
}
void dac_set(dac_t line, uint16_t value)
{
value = (value >> 4); /* scale to 12-bit */
if (dac_config[line].chan) {
DAC->DHR12R2 = value;
}
else {
DAC->DHR12R1 = value;
}
}
void dac_poweron(dac_t line)
{
DAC->CR |= (1 << (16 * dac_config[line].chan));
}
void dac_poweroff(dac_t line)
{
DAC->CR &= ~(1 << (16 * dac_config[line].chan));
}
#endif /* DAC_NUMOF */

@ -0,0 +1,221 @@
/*
* Copyright (C) 2015 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_stm32f2
* @{
*
* @file
* @brief Low-level GPIO driver implementation
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Fabian Nack <nack@inf.fu-berlin.de>
*
* @}
*/
#include "cpu.h"
#include "sched.h"
#include "thread.h"
#include "periph/gpio.h"
#include "periph_conf.h"
/**
* @brief Number of available external interrupt lines
*/
#define GPIO_ISR_CHAN_NUMOF (16U)
/**
* @brief Hold one callback function pointer for each interrupt line
*/
static gpio_isr_ctx_t exti_chan[GPIO_ISR_CHAN_NUMOF];
/**
* @brief Extract the port base address from the given pin identifier
*/
static inline GPIO_TypeDef *_port(gpio_t pin)
{
return (GPIO_TypeDef *)(pin & ~(0x0f));
}
/**
* @brief Extract the port number form the given identifier
*
* The port number is extracted by looking at bits 10, 11, 12, 13 of the base
* register addresses.
*/
static inline int _port_num(gpio_t pin)
{
return ((pin >> 10) & 0x0f);
}
/**
* @brief Extract the pin number from the last 4 bit of the pin identifier
*/
static inline int _pin_num(gpio_t pin)
{
return (pin & 0x0f);
}
int gpio_init(gpio_t pin, gpio_mode_t mode)
{
GPIO_TypeDef *port = _port(pin);
int pin_num = _pin_num(pin);
/* enable clock */
RCC->AHB1ENR |= (RCC_AHB1ENR_GPIOAEN << _port_num(