1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-25 14:33:52 +01:00

cpu: initial support for stm32wb

This commit is contained in:
Francisco Molina 2019-07-15 15:31:27 +02:00
parent 0ee04bd6d6
commit 66a8922f8c
No known key found for this signature in database
GPG Key ID: 3E94EAC3DBDEEDA8
22 changed files with 564 additions and 37 deletions

View File

@ -51,7 +51,7 @@ uint32_t periph_apb_clk(uint8_t bus)
if (bus == APB1) {
return CLOCK_APB1;
}
#if defined (CPU_FAM_STM32L4)
#if defined (CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB)
else if (bus == APB12) {
return CLOCK_APB1;
}
@ -70,7 +70,7 @@ void periph_clk_en(bus_t bus, uint32_t mask)
{
switch (bus) {
case APB1:
#if defined(CPU_FAM_STM32L4)
#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB)
RCC->APB1ENR1 |= mask;
#else
RCC->APB1ENR |= mask;
@ -79,7 +79,7 @@ void periph_clk_en(bus_t bus, uint32_t mask)
case APB2:
RCC->APB2ENR |= mask;
break;
#if defined(CPU_FAM_STM32L4)
#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB)
case APB12:
RCC->APB1ENR2 |= mask;
break;
@ -97,7 +97,8 @@ void periph_clk_en(bus_t bus, uint32_t mask)
RCC->AHBENR |= mask;
break;
#elif defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4) || \
defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32F7)
defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32F7) || \
defined(CPU_FAM_STM32WB)
case AHB1:
RCC->AHB1ENR |= mask;
break;
@ -123,7 +124,7 @@ void periph_clk_dis(bus_t bus, uint32_t mask)
{
switch (bus) {
case APB1:
#if defined(CPU_FAM_STM32L4)
#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB)
RCC->APB1ENR1 &= ~(mask);
#else
RCC->APB1ENR &= ~(mask);
@ -132,7 +133,7 @@ void periph_clk_dis(bus_t bus, uint32_t mask)
case APB2:
RCC->APB2ENR &= ~(mask);
break;
#if defined(CPU_FAM_STM32L4)
#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB)
case APB12:
RCC->APB1ENR2 &= ~(mask);
break;
@ -150,7 +151,8 @@ void periph_clk_dis(bus_t bus, uint32_t mask)
RCC->AHBENR &= ~(mask);
break;
#elif defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4) || \
defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32F7)
defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32F7) || \
defined(CPU_FAM_STM32WB)
case AHB1:
RCC->AHB1ENR &= ~(mask);
break;
@ -163,6 +165,11 @@ void periph_clk_dis(bus_t bus, uint32_t mask)
RCC->AHB3ENR &= ~(mask);
break;
#endif
#if defined(CPU_FAM_STM32WB)
case AHB4:
RCC->AHB3ENR &= ~(mask);
break;
#endif
#endif
default:
DEBUG("unsupported bus %d\n", (int)bus);

View File

@ -149,7 +149,9 @@ void cpu_init(void)
/* initialize the Cortex-M core */
cortexm_init();
/* enable PWR module */
#ifndef CPU_FAM_STM32WB
periph_clk_en(APB1, BIT_APB_PWREN);
#endif
/* initialize the system clock as configured in the periph_conf.h */
stmclk_init_sysclk();
#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F1) || \

View File

@ -29,7 +29,8 @@ extern "C" {
#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3) || \
defined(CPU_FAM_STM32F7) || defined(CPU_FAM_STM32L0) || \
defined(CPU_FAM_STM32L4)
defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32L4) || \
defined(CPU_FAM_STM32WB)
/**
* @brief Timing register settings
@ -37,8 +38,8 @@ extern "C" {
* @ref i2c_timing_param_t
*/
static const i2c_timing_param_t timing_params[] = {
#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32L4) || \
defined(CPU_FAM_STM32F7)
#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F7) || \
defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB)
[ I2C_SPEED_NORMAL ] = {
.presc = 0xB,
.scll = 0x13, /* t_SCLL = 5.0us */
@ -108,7 +109,7 @@ static const i2c_timing_param_t timing_params[] = {
};
#endif /* CPU_FAM_STM32F0 || CPU_FAM_STM32F3 || CPU_FAM_STM32F7 ||
CPU_FAM_STM32L0 || CPU_FAM_STM32L4 */
CPU_FAM_STM32L0 || CPU_FAM_STM32L4 || CPU_FAM_STM32WB */
#ifdef __cplusplus
}

View File

@ -36,7 +36,8 @@ extern "C" {
#elif defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1)
#define CLOCK_LSI (37000U)
#elif defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4) || \
defined(CPU_FAM_STM32F7) || defined(CPU_FAM_STM32L4)
defined(CPU_FAM_STM32F7) || defined(CPU_FAM_STM32L4) || \
defined(CPU_FAM_STM32WB)
#define CLOCK_LSI (32000U)
#else
#error "error: LSI clock speed not defined for your target CPU"
@ -121,23 +122,27 @@ extern "C" {
typedef enum {
APB1, /**< APB1 bus */
APB2, /**< APB2 bus */
#if defined(CPU_FAM_STM32L4)
#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB)
APB12, /**< AHB1 bus, second register */
#endif
#if defined(CPU_FAM_STM32L0)
AHB, /**< AHB bus */
IOP, /**< IOP bus */
#elif defined(CPU_FAM_STM32L1) || defined(CPU_FAM_STM32F1) \
|| defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3)
#elif defined(CPU_FAM_STM32L1) || defined(CPU_FAM_STM32F1) || \
defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3)
AHB, /**< AHB bus */
#elif defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4) \
|| defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32F7)
#elif defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4) || \
defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32F7) || \
defined(CPU_FAM_STM32WB)
AHB1, /**< AHB1 bus */
AHB2, /**< AHB2 bus */
AHB3 /**< AHB3 bus */
AHB3, /**< AHB3 bus */
#else
#warning "unsupported stm32XX family"
#endif
#if defined(CPU_FAM_STM32WB)
AHB4, /**< AHB4 bus */
#endif
} bus_t;
#ifndef DOXYGEN
@ -469,7 +474,8 @@ typedef struct {
gpio_af_t rts_af; /**< alternate function for RTS pin */
#endif
#endif
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L4)
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L4) || \
defined(CPU_FAM_STM32WB)
uart_type_t type; /**< hardware module type (USART or LPUART) */
uint32_t clk_src; /**< clock source used for UART */
#endif
@ -519,7 +525,7 @@ typedef enum {
I2C_SPEED_FAST, /**< fast mode: ~400kbit/s */
#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3) || \
defined(CPU_FAM_STM32F7) || defined(CPU_FAM_STM32L0) || \
defined(CPU_FAM_STM32L4)
defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB)
I2C_SPEED_FAST_PLUS, /**< fast plus mode: ~1Mbit/s */
#endif
} i2c_speed_t;
@ -552,7 +558,7 @@ typedef struct {
#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3) || \
defined(CPU_FAM_STM32F7) || defined(CPU_FAM_STM32L0) || \
defined(CPU_FAM_STM32L4)
defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB)
/**
* @brief Structure for I2C timing register settings
*

View File

@ -2,7 +2,7 @@ MODULE = stm32_common_periph
# Select the specific implementation for `periph_i2c`
ifneq (,$(filter periph_i2c,$(USEMODULE)))
ifneq (,$(filter $(CPU),stm32f0 stm32f3 stm32f7 stm32l0 stm32l4))
ifneq (,$(filter $(CPU),stm32f0 stm32f3 stm32f7 stm32l0 stm32l4 stm32wb))
SRC += i2c_1.c
else # stm32f1/f2/f4/l1
SRC += i2c_2.c

View File

@ -83,7 +83,7 @@ int gpio_init(gpio_t pin, gpio_mode_t mode)
periph_clk_en(AHB, (RCC_AHBENR_GPIOAEN << _port_num(pin)));
#elif defined (CPU_FAM_STM32L0)
periph_clk_en(IOP, (RCC_IOPENR_GPIOAEN << _port_num(pin)));
#elif defined (CPU_FAM_STM32L4)
#elif defined (CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB)
periph_clk_en(AHB2, (RCC_AHB2ENR_GPIOAEN << _port_num(pin)));
#ifdef PWR_CR2_IOSV
if (port == GPIOG) {
@ -132,7 +132,7 @@ void gpio_init_analog(gpio_t pin)
periph_clk_en(AHB, (RCC_AHBENR_GPIOAEN << _port_num(pin)));
#elif defined (CPU_FAM_STM32L0)
periph_clk_en(IOP, (RCC_IOPENR_GPIOAEN << _port_num(pin)));
#elif defined (CPU_FAM_STM32L4)
#elif defined (CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB)
periph_clk_en(AHB2, (RCC_AHB2ENR_GPIOAEN << _port_num(pin)));
#else
periph_clk_en(AHB1, (RCC_AHB1ENR_GPIOAEN << _port_num(pin)));
@ -196,7 +196,13 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
isr_ctx[pin_num].arg = arg;
/* enable clock of the SYSCFG module for EXTI configuration */
#ifndef CPU_FAM_STM32WB
#ifdef CPU_FAM_STM32F0
periph_clk_en(APB2, RCC_APB2ENR_SYSCFGCOMPEN);
#else
periph_clk_en(APB2, RCC_APB2ENR_SYSCFGEN);
#endif
#endif
/* initialize pin as input */
gpio_init(pin, mode);

View File

@ -43,6 +43,8 @@ void hwrng_read(void *buf, unsigned int num)
periph_clk_en(AHB1, RCC_AHB1ENR_RNGEN);
#elif defined(CPU_FAM_STM32L0)
periph_clk_en(AHB, RCC_AHBENR_RNGEN);
#elif defined(CPU_FAM_STM32WB)
periph_clk_en(AHB3, RCC_AHB3ENR_RNGEN);
#else
periph_clk_en(AHB2, RCC_AHB2ENR_RNGEN);
#endif
@ -67,6 +69,8 @@ void hwrng_read(void *buf, unsigned int num)
periph_clk_dis(AHB1, RCC_AHB1ENR_RNGEN);
#elif defined(CPU_FAM_STM32L0)
periph_clk_dis(AHB, RCC_AHBENR_RNGEN);
#elif defined(CPU_FAM_STM32WB)
periph_clk_dis(AHB3, RCC_AHB3ENR_RNGEN);
#else
periph_clk_dis(AHB2, RCC_AHB2ENR_RNGEN);
#endif

View File

@ -17,7 +17,7 @@
* @file
* @brief Low-level I2C driver implementation
*
* This driver supports the STM32 F0, F3, F7, L0 and L4 families.
* This driver supports the STM32 F0, F3, F7, L0, L4 & WB families.
* @note This implementation only implements the 7-bit addressing polling mode
* (for now interrupt mode is not available)
*

View File

@ -47,8 +47,11 @@
#define PM_STOP_CONFIG (PWR_CR_LPSDSR | PWR_CR_ULP | PWR_CR_CWUF)
#elif defined(CPU_FAM_STM32L4)
#define PM_STOP_CONFIG (PWR_CR1_LPMS_STOP1)
#elif defined(CPU_FAM_STM32WB)
#define PM_STOP_CONFIG (PWR_CR1_LPMS_0)
#elif defined(CPU_FAM_STM32F7)
#define PM_STOP_CONFIG (PWR_CR1_LPDS | PWR_CR1_FPDS | PWR_CR1_LPUDS)
#elif defined(CPU_FAM_STM32WB)
#else
#define PM_STOP_CONFIG (PWR_CR_LPDS | PWR_CR_FPDS)
#endif
@ -64,6 +67,8 @@
#define PM_STANDBY_CONFIG (PWR_CR_PDDS | PWR_CR_CWUF | PWR_CR_CSBF | PWR_CR_ULP)
#elif defined(CPU_FAM_STM32L4)
#define PM_STANDBY_CONFIG (PWR_CR1_LPMS_STANDBY)
#elif defined(CPU_FAM_STM32WB)
#define PM_STANDBY_CONFIG (PWR_CR1_LPMS_0 | PWR_CR1_LPMS_1)
#elif defined(CPU_FAM_STM32F7)
#define PM_STANDBY_CONFIG (PWR_CR1_PDDS | PWR_CR1_CSBF)
#else
@ -71,7 +76,7 @@
#endif
#endif
#if defined(CPU_FAM_STM32L4)
#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB)
#define PWR_CR_REG PWR->CR1
#define PWR_WUP_REG PWR->CR3
/* Allow overridable SRAM2 retention mode using CFLAGS */
@ -96,12 +101,14 @@ void pm_set(unsigned mode)
case STM32_PM_STANDBY:
PWR_CR_REG &= ~(PM_STOP_CONFIG | PM_STANDBY_CONFIG);
PWR_CR_REG |= PM_STANDBY_CONFIG;
#if defined(CPU_FAM_STM32L4)
#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB)
#if STM32L4_SRAM2_RETENTION
PWR->CR3 |= PWR_CR3_RRS;
#else
PWR->CR3 &= ~PWR_CR3_RRS;
#endif
#endif
#if defined(CPU_FAM_STM32L4)
/* Clear flags */
PWR->SCR |= PWR_SCR_CSBF;
#endif

View File

@ -60,6 +60,11 @@
#define EXTI_FTSR_BIT (EXTI_FTSR1_FT18)
#define EXTI_RTSR_BIT (EXTI_RTSR1_RT18)
#define EXTI_PR_BIT (EXTI_PR1_PIF18)
#elif defined(CPU_FAM_STM32WB)
#define EXTI_IMR_BIT (EXTI_IMR1_IM17)
#define EXTI_FTSR_BIT (EXTI_FTSR1_FT17)
#define EXTI_RTSR_BIT (EXTI_RTSR1_RT17)
#define EXTI_PR_BIT (EXTI_PR1_PIF17)
#else
#if defined(CPU_FAM_STM32L0)
#define EXTI_IMR_BIT (EXTI_IMR_IM17)

View File

@ -36,7 +36,7 @@
#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32L0) || \
defined(CPU_FAM_STM32F3) || defined(CPU_FAM_STM32L4) || \
defined(CPU_FAM_STM32F7)
defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32F7)
#define ISR_REG ISR
#define ISR_TXE USART_ISR_TXE
#define ISR_TC USART_ISR_TC
@ -46,7 +46,6 @@
#define ISR_TXE USART_SR_TXE
#define ISR_TC USART_SR_TC
#define TDR_REG DR
#endif
#define RXENABLE (USART_CR1_RE | USART_CR1_RXNEIE)
@ -69,7 +68,8 @@ static inline USART_TypeDef *dev(uart_t uart)
}
static inline void uart_init_usart(uart_t uart, uint32_t baudrate);
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L4)
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L4) || \
defined(CPU_FAM_STM32WB)
#ifdef MODULE_PERIPH_LPUART
static inline void uart_init_lpuart(uart_t uart, uint32_t baudrate);
#endif
@ -161,7 +161,8 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
dev(uart)->CR2 = 0;
dev(uart)->CR3 = 0;
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L4)
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L4) || \
defined(CPU_FAM_STM32WB)
switch (uart_config[uart].type) {
case STM32_USART:
uart_init_usart(uart, baudrate);
@ -262,7 +263,8 @@ static inline void uart_init_usart(uart_t uart, uint32_t baudrate)
dev(uart)->BRR = ((mantissa & 0x0fff) << 4) | (fraction & 0x0f);
}
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L4)
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L4) || \
defined(CPU_FAM_STM32WB)
#ifdef MODULE_PERIPH_LPUART
static inline void uart_init_lpuart(uart_t uart, uint32_t baudrate)
{
@ -295,7 +297,7 @@ static inline void uart_init_lpuart(uart_t uart, uint32_t baudrate)
dev(uart)->BRR = brr;
}
#endif /* MODULE_PERIPH_LPUART */
#endif /* STM32L0 || STM32L4 */
#endif /* STM32L0 || STM32L4 || STM32WB */
static inline void send_byte(uart_t uart, uint8_t byte)
{
@ -401,7 +403,7 @@ static inline void irq_handler(uart_t uart)
{
#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32L0) || \
defined(CPU_FAM_STM32F3) || defined(CPU_FAM_STM32L4) || \
defined(CPU_FAM_STM32F7)
defined(CPU_FAM_STM32F7) || defined(CPU_FAM_STM32WB)
uint32_t status = dev(uart)->ISR;

View File

@ -5,7 +5,7 @@ RAM_START_ADDR ?= 0x20000000
# The next block takes care of setting the rigth lengths of RAM and ROM
# for the stm32 family. Most of the CPUs should have been taken into
# account here, so no need to assign the lengths per model.
STM32_INFO := $(shell printf '%s' '$(CPU_MODEL)' | tr 'a-z' 'A-Z' | sed -E -e 's/^STM32(F|L)(0|1|2|3|4|7)([A-Z0-9])([0-9])(.)(.)(_A)?/\1 \2 \2\3\4 \3 \4 \5 \6 \7/')
STM32_INFO := $(shell printf '%s' '$(CPU_MODEL)' | tr 'a-z' 'A-Z' | sed -E -e 's/^STM32(F|L|W)(0|1|2|3|4|7|B)([A-Z0-9])([0-9])(.)(.)(_A)?/\1 \2 \2\3\4 \3 \4 \5 \6 \7/')
STM32_TYPE := $(word 1, $(STM32_INFO))
STM32_FAMILY := $(word 2, $(STM32_INFO))
STM32_MODEL := $(word 3, $(STM32_INFO))
@ -260,6 +260,16 @@ else ifeq ($(STM32_TYPE), L)
RAM_LEN = 640K
endif
endif
else ifeq ($(STM32_TYPE), W)
ifeq ($(STM32_FAMILY), B)
ifeq ($(STM32_MODEL), B55)
ifeq ($(STM32_ROMSIZE), C)
RAM_LEN = 128K
else ifneq (, $(filter $(STM32_ROMSIZE), E G))
RAM_LEN = 256K
endif
endif
endif
endif
ifeq ($(RAM_LEN), )
@ -317,7 +327,11 @@ else ifeq ($(STM32_PINCOUNT), N)
else ifeq ($(STM32_PINCOUNT), Q)
STM32_PINCOUNT = 132
else ifeq ($(STM32_PINCOUNT), R)
STM32_PINCOUNT = 64
ifeq ($(STM32_TYPE), W)
STM32_PINCOUNT = 68
else
STM32_PINCOUNT = 64
endif
else ifeq ($(STM32_PINCOUNT), T)
STM32_PINCOUNT = 36
else ifeq ($(STM32_PINCOUNT), U)

View File

@ -23,7 +23,8 @@
#include "stmclk.h"
#include "periph_conf.h"
#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32F7)
#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32F7) || \
defined(CPU_FAM_STM32WB)
#define REG_PWR_CR CR1
#define BIT_CR_DBP PWR_CR1_DBP
#else
@ -41,6 +42,12 @@
#define BIT_LSERDY RCC_BDCR_LSERDY
#endif
#if defined (CPU_FAM_STM32WB)
#define RCC_CFGR_SWS_HSI RCC_CFGR_SWS_0
#define RCC_CSR_LSION RCC_CSR_LSI1ON
#define RCC_CSR_LSIRDY RCC_CSR_LSI1RDY
#endif
#ifndef CLOCK_HSE
#define CLOCK_HSE (0U)
#endif

10
cpu/stm32wb/Makefile Normal file
View File

@ -0,0 +1,10 @@
# 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
# (file triggers compiler bug. see #5775)
SRC_NOLTO += vectors.c
include $(RIOTBASE)/Makefile.base

1
cpu/stm32wb/Makefile.dep Normal file
View File

@ -0,0 +1 @@
include $(RIOTCPU)/stm32_common/Makefile.dep

View File

@ -0,0 +1,3 @@
FEATURES_PROVIDED += periph_hwrng
-include $(RIOTCPU)/stm32_common/Makefile.features

View File

@ -0,0 +1,16 @@
CPU_ARCH = cortex-m4
CPU_FAM = stm32wb
# "The Vector table must be naturally aligned to a power of two whose alignment
# value is greater than or equal to number of Exceptions supported x 4"
# CPU_IRQ_NUMOFF for stm32l4 boards is < 91+16 so (107*4 bytes = 428 bytes ~= 0x200)
# RIOTBOOT_HDR_LEN can be set to 0x200
RIOTBOOT_HDR_LEN ?= 0x200
# Slot size is determined by "((total_flash_size - RIOTBOOT_LEN) / 2)".
# If RIOTBOOT_LEN uses an odd number of flashpages, the remainder of the
# flash cannot be divided by two slots while staying FLASHPAGE_SIZE aligned.
RIOTBOOT_LEN ?= 0x2000
include $(RIOTCPU)/stm32_common/Makefile.include
include $(RIOTMAKE)/arch/cortexm.inc.mk

View File

@ -0,0 +1,67 @@
/*
* Copyright (C) 2019 Inria
*
* 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_stm32wb STM32WB
* @brief STM32WB specific code
* @ingroup cpu
* @{
*
* @file
* @brief Implementation specific CPU configuration options
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
*
*/
#ifndef CPU_CONF_H
#define CPU_CONF_H
#include "cpu_conf_common.h"
#if defined(CPU_MODEL_STM32WB55RG)
#include "vendor/stm32wb55xx.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief ARM Cortex-M specific CPU configuration
* @{
*/
#define CPU_DEFAULT_IRQ_PRIO (1U)
#if defined(CPU_MODEL_STM32WB55RG)
#define CPU_IRQ_NUMOF (63U)
#endif
#define CPU_FLASH_BASE FLASH_BASE
/** @} */
/**
* @name Flash page configuration
* @{
*/
#define FLASHPAGE_SIZE (4096U)
#define FLASHPAGE_NUMOF (STM32_FLASHSIZE / FLASHPAGE_SIZE)
/* The minimum block size which can be written is 8B. However, the erase
* block is always FLASHPAGE_SIZE.
*/
#define FLASHPAGE_RAW_BLOCKSIZE (8U)
/* Writing should be always 8 bytes aligned */
#define FLASHPAGE_RAW_ALIGNMENT (8U)
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* CPU_CONF_H */
/** @} */

View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2019 Inria
*
* 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_stm32wb
* @{
*
* @file
* @brief CPU specific definitions for internal peripheral handling
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
*
*/
#ifndef PERIPH_CPU_H
#define PERIPH_CPU_H
#include "periph_cpu_common.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Starting address of the CPU ID
*/
#define CPUID_ADDR (0x1fff7580)
/**
* @brief Available ports
*/
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_H = 7, /**< port H */
};
#ifdef __cplusplus
}
#endif
#endif /* PERIPH_CPU_H */
/** @} */

View File

@ -0,0 +1 @@
include $(RIOTMAKE)/periph.mk

163
cpu/stm32wb/stmclk.c Normal file
View File

@ -0,0 +1,163 @@
/*
* Copyright (C) 2017 Freie Universität Berlin
* 2017 OTA keys S.A.
* 2017 HAW-Hamburg
*
* 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_stm32wb
* @{
*
* @file
* @brief Implementation of STM32 clock configuration
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Nick van IJzendoorn <nijzendoorn@engineering-spirit.nl>
* @author Vincent Dupont <vincent@otakeys.com>
* @author Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#include "cpu.h"
#include "stmclk.h"
#include "periph_conf.h"
/* make sure we have all needed information about the clock configuration */
#ifndef CLOCK_HSE
#error "Please provide CLOCK_HSE in your board's perhip_conf.h"
#endif
#ifndef CLOCK_LSE
#error "Please provide CLOCK_LSE in your board's periph_conf.h"
#endif
#if !defined(CLOCK_PLL_M) || !defined(CLOCK_PLL_N) || !defined(CLOCK_PLL_R)
#error "Please provide the PLL configuration in your board's periph_conf.h"
#endif
/* map CMSIS defines not present in stm32wb55xx.h */
#if defined(CPU_FAM_STM32WB)
#define RCC_PLLCFGR_PLLSRC_HSE (RCC_PLLCFGR_PLLSRC_0 | RCC_PLLCFGR_PLLSRC_1)
#define RCC_PLLCFGR_PLLSRC_MSI (RCC_PLLCFGR_PLLSRC_0)
#define RCC_CFGR_SW_MSI (0x00000000U)
#define RCC_CFGR_SW_HSI (RCC_CFGR_SW_0)
#define RCC_CFGR_SW_HSE (RCC_CFGR_SW_1)
#define RCC_CFGR_SW_PLL (RCC_CFGR_SW_1 + RCC_CFGR_SW_0)
#define RCC_CFGR_SWS_MSI (0x00000000U)
#define RCC_CFGR_SWS_HSI (RCC_CFGR_SWS_0)
#define RCC_CFGR_SWS_HSE (RCC_CFGR_SWS_1)
#define RCC_CFGR_SWS_PLL (RCC_CFGR_SWS_1 + RCC_CFGR_SWS_0)
#endif
/**
* @name PLL configuration
* @{
*/
/* figure out which input to use */
#if (CLOCK_HSE)
#define PLL_IN CLOCK_HSE
#define PLL_SRC RCC_PLLCFGR_PLLSRC_HSE
#else
#define PLL_IN (48000000) /* MSI @ 48MHz */
#define PLL_SRC RCC_PLLCFGR_PLLSRC_MSI
#endif
/**check configuration and get the corresponding bitfields */
#if (CLOCK_PLL_M < 1 || CLOCK_PLL_M > 8)
#error "PLL configuration: PLL M value is out of range"
#endif
#define PLL_M ((CLOCK_PLL_M - 1) << RCC_PLLCFGR_PLLM_Pos)
#if (CLOCK_PLL_N < 8 || CLOCK_PLL_N > 86)
#error "PLL configuration: PLL N value is out of range"
#endif
#define PLL_N (CLOCK_PLL_N << RCC_PLLCFGR_PLLN_Pos)
#if (CLOCK_PLL_R < 1 || CLOCK_PLL_R > 8)
#error "PLL configuration: PLL R value is invalid"
#else
#define PLL_R ((CLOCK_PLL_R - 1)<< RCC_PLLCFGR_PLLR_Pos)
#endif
/** @} */
/**
* @name Deduct the needed flash wait states from the core clock frequency
* @{
*/
#define FLASH_WAITSTATES ((CLOCK_CORECLOCK - 1) / 18000000U)
/** @} */
void stmclk_init_sysclk(void)
{
/* disable any interrupts. Global interrupts could be enabled if this is
* called from some kind of bootloader... */
unsigned is = irq_disable();
RCC->CIER = 0;
/* enable HSI clock for the duration of initialization */
stmclk_enable_hsi();
/* use HSI as system clock while we do any further configuration and
* configure the AHB and APB clock dividers as configure by the board */
RCC->CFGR = (RCC_CFGR_SW_HSI | CLOCK_AHB_DIV |
CLOCK_APB1_DIV | CLOCK_APB2_DIV);
/* Use HSE/2 for radios systems */
RCC->EXTCFGR = (RCC_EXTCFGR_RFCSS | CLOCK_EXTAHB_DIV);
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) {}
/* we enable I+D cashes, pre-fetch, and we set the actual number of
* needed flash wait states */
FLASH->ACR = (FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_PRFTEN |
FLASH_WAITSTATES);
/* disable all active clocks except HSI -> resets the clk configuration
* Note: on STM32L4x5 & STM32L4x6 this disables the following:
PLLSAI1, PLLSAI2, Main PLL (via PLLON),
Clock security system (via CSSON), MSI clock PLL (via MSIPLLEN),
HSE crystal oscillator bypass (via HSEBYP), HSE,
HSI16 automatic start from Stop (via HSIASFS),
HSI16 always enable for peripheral kernels (via HSIKERON).
Additionally it configures the MSI clock range (MSIRANGE) to
~100 kHz and the MSI clock to be based on MSISRANGE in RCC_CSR
(instead of MSIRANGE in the RCC_CR) */
RCC->CR = (RCC_CR_HSION);
#if (CLOCK_HSE)
/* if configured, we need to enable the HSE clock now */
RCC->CR |= (RCC_CR_HSEON);
while (!(RCC->CR & RCC_CR_HSERDY)) {}
#endif
#if ((CLOCK_HSE == 0) || CLOCK_MSI_ENABLE)
/* reset clock to MSI with 48MHz, disables all other clocks */
RCC->CR |= (RCC_CR_MSIRANGE_11 | RCC_CR_MSION);
while (!(RCC->CR & RCC_CR_MSIRDY)) {}
/* select the MSI clock for the 48MHz clock tree (USB, RNG) */
RCC->CCIPR = (RCC_CCIPR_CLK48SEL_0 | RCC_CCIPR_CLK48SEL_1);
#if (CLOCK_MSI_LSE_PLL && CLOCK_LSE)
/* configure the low speed clock domain */
stmclk_enable_lfclk();
/* now we can enable the MSI PLL mode to enhance accuracy of the MSI*/
RCC->CR |= RCC_CR_MSIPLLEN;
while (!(RCC->CR & RCC_CR_MSIRDY)) {}
#endif /* (CLOCK_MSI_LSE_PLL && CLOCK_LSE) */
#endif /* ((CLOCK_HSE == 0) || CLOCK_MSI_ENABLE) */
/* now we can safely configure and start the PLL */
RCC->PLLCFGR = (PLL_SRC | PLL_M | PLL_N | PLL_R | RCC_PLLCFGR_PLLREN);
RCC->CR |= (RCC_CR_PLLON);
while (!(RCC->CR & RCC_CR_PLLRDY)) {}
/* now that the PLL is running, we use it as system clock */
RCC->CFGR |= RCC_CFGR_SW_PLL;
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) {}
stmclk_disable_hsi();
irq_restore(is);
}

154
cpu/stm32wb/vectors.c Normal file
View File

@ -0,0 +1,154 @@
/*
* Copyright (C) 2017 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_stm32l4
* @{
*
* @file
* @brief Interrupt vector definitions
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*
* @}
*/
#include "vectors_cortexm.h"
/* define a local dummy handler as it needs to be in the same compilation unit
* as the alias definition */
void dummy_handler(void) {
dummy_handler_default();
}
/* STM32L4 specific interrupt vectors */
WEAK_DEFAULT void isr_adc1(void);
WEAK_DEFAULT void isr_aes1(void);
WEAK_DEFAULT void isr_aes2(void);
WEAK_DEFAULT void isr_c2sev_pwr_c2h(void);
WEAK_DEFAULT void isr_comp(void);
WEAK_DEFAULT void isr_crs(void);
WEAK_DEFAULT void isr_dma1_channel1(void);
WEAK_DEFAULT void isr_dma1_channel2(void);
WEAK_DEFAULT void isr_dma1_channel3(void);
WEAK_DEFAULT void isr_dma1_channel4(void);
WEAK_DEFAULT void isr_dma1_channel5(void);
WEAK_DEFAULT void isr_dma1_channel6(void);
WEAK_DEFAULT void isr_dma1_channel7(void);
WEAK_DEFAULT void isr_dma2_channel1(void);
WEAK_DEFAULT void isr_dma2_channel2(void);
WEAK_DEFAULT void isr_dma2_channel3(void);
WEAK_DEFAULT void isr_dma2_channel4(void);
WEAK_DEFAULT void isr_dma2_channel5(void);
WEAK_DEFAULT void isr_dma2_channel6(void);
WEAK_DEFAULT void isr_dma2_channel7(void);
WEAK_DEFAULT void isr_dmamux1_ovr(void);
WEAK_DEFAULT void isr_exti(void);
WEAK_DEFAULT void isr_flash(void);
WEAK_DEFAULT void isr_fpu(void);
WEAK_DEFAULT void isr_hsem(void);
WEAK_DEFAULT void isr_ipcc_c1_rx(void);
WEAK_DEFAULT void isr_ipcc_c1_tx(void);
WEAK_DEFAULT void isr_i2c1_er(void);
WEAK_DEFAULT void isr_i2c1_ev(void);
WEAK_DEFAULT void isr_i2c3_er(void);
WEAK_DEFAULT void isr_i2c3_ev(void);
WEAK_DEFAULT void isr_lcd(void);
WEAK_DEFAULT void isr_lptim1(void);
WEAK_DEFAULT void isr_lptim2(void);
WEAK_DEFAULT void isr_lpuart1(void);
WEAK_DEFAULT void isr_pka(void);
WEAK_DEFAULT void isr_pvd_pvm(void);
WEAK_DEFAULT void isr_quadspi(void);
WEAK_DEFAULT void isr_rcc(void);
WEAK_DEFAULT void isr_rng(void);
WEAK_DEFAULT void isr_rtc_alarm(void);
WEAK_DEFAULT void isr_rtc_wkup(void);
WEAK_DEFAULT void isr_sai1(void);
WEAK_DEFAULT void isr_sotf_pwr_ble_802_rfphase(void);
WEAK_DEFAULT void isr_spi1(void);
WEAK_DEFAULT void isr_spi2(void);
WEAK_DEFAULT void isr_tamp_stamp(void);
WEAK_DEFAULT void isr_tim1_brk(void);
WEAK_DEFAULT void isr_tim1_cc(void);
WEAK_DEFAULT void isr_tim1_up_tim16(void);
WEAK_DEFAULT void isr_tim2(void);
WEAK_DEFAULT void isr_tsc(void);
WEAK_DEFAULT void isr_usart1(void);
WEAK_DEFAULT void isr_usb_hp(void);
WEAK_DEFAULT void isr_usb_lp(void);
WEAK_DEFAULT void isr_wwdg(void);
/* CPU specific interrupt vector table */
ISR_VECTOR(1) const isr_t vector_cpu[CPU_IRQ_NUMOF] = {
[WWDG_IRQn ] = isr_wwdg, /* [ 0] Window WatchDog Interrupt */
[PVD_PVM_IRQn ] = isr_pvd_pvm, /* [ 1] PVD and PVM detector */
[TAMP_STAMP_LSECSS_IRQn ] = isr_tamp_stamp, /* [ 2] RTC Tamper and TimeStamp Interrupts and LSECSS Interrupts */
[RTC_WKUP_IRQn ] = isr_rtc_wkup, /* [ 3] RTC Wakeup Interrupt */
[FLASH_IRQn ] = isr_flash, /* [ 4] FLASH global Interrupt */
[RCC_IRQn ] = isr_rcc, /* [ 5] RCC global Interrupt */
[EXTI0_IRQn ] = isr_exti, /* [ 6] EXTI Line0 Interrupt */
[EXTI1_IRQn ] = isr_exti, /* [ 7] EXTI Line1 Interrupt */
[EXTI2_IRQn ] = isr_exti, /* [ 8] EXTI Line2 Interrupt */
[EXTI3_IRQn ] = isr_exti, /* [ 9] EXTI Line3 Interrupt */
[EXTI4_IRQn ] = isr_exti, /* [10] EXTI Line4 Interrupt */
[DMA1_Channel1_IRQn ] = isr_dma1_channel1, /* [11] DMA1 Channel 1 global Interrupt */
[DMA1_Channel2_IRQn ] = isr_dma1_channel2, /* [12] DMA1 Channel 2 global Interrupt */
[DMA1_Channel3_IRQn ] = isr_dma1_channel3, /* [13] DMA1 Channel 3 global Interrupt */
[DMA1_Channel4_IRQn ] = isr_dma1_channel4, /* [14] DMA1 Channel 4 global Interrupt */
[DMA1_Channel5_IRQn ] = isr_dma1_channel5, /* [15] DMA1 Channel 5 global Interrupt */
[DMA1_Channel6_IRQn ] = isr_dma1_channel6, /* [16] DMA1 Channel 6 global Interrupt */
[DMA1_Channel7_IRQn ] = isr_dma1_channel7, /* [17] DMA1 Channel 7 global Interrupt */
[ADC1_IRQn ] = isr_adc1, /* [18] ADC1 Interrup */
[USB_HP_IRQn ] = isr_usb_hp, /* [19] USB High Priority Interrupt */
[USB_LP_IRQn ] = isr_usb_lp, /* [20] USB Low Priority Interrupt (including USB wakeup) */
[C2SEV_PWR_C2H_IRQn ] = isr_c2sev_pwr_c2h, /* [21] CPU2 SEV Interrupt */
[COMP_IRQn ] = isr_comp, /* [62] COMP1 and COMP2 Interrupts */
[EXTI9_5_IRQn ] = isr_exti, /* [23] External Line[9:5] Interrupts */
[TIM1_BRK_IRQn ] = isr_tim1_brk, /* [24] TIM1 Break interrupt */
[TIM1_UP_TIM16_IRQn ] = isr_tim1_up_tim16, /* [25] TIM1 Update Interrupt and TIM16 global interrupt */
[TIM1_CC_IRQn ] = isr_tim1_cc, /* [27] TIM1 Capture Compare Interrupt */
[TIM2_IRQn ] = isr_tim2, /* [28] TIM2 global Interrupt */
[PKA_IRQn ] = isr_pka, /* [29] PKA Interrup */
[I2C1_EV_IRQn ] = isr_i2c1_ev, /* [30] I2C1 Event Interrupt */
[I2C1_ER_IRQn ] = isr_i2c1_er, /* [31] I2C1 Error Interrupt */
[I2C3_EV_IRQn ] = isr_i2c3_ev, /* [32] I2C3 Event Interrupt */
[I2C3_ER_IRQn ] = isr_i2c3_er, /* [33] I2C3 Error Interrupt */
[SPI1_IRQn ] = isr_spi1, /* [34] SPI1 global Interrupt */
[SPI2_IRQn ] = isr_spi2, /* [35] SPI2 global Interrupt */
[USART1_IRQn ] = isr_usart1, /* [36] USART1 global Interrupt */
[LPUART1_IRQn ] = isr_lpuart1, /* [37] LP UART1 interrupt */
[SAI1_IRQn ] = isr_sai1, /* [38] Serial Audio Interface 1 global interrupt */
[TSC_IRQn ] = isr_tsc, /* [39] Touch Sense Controller global interrupt */
[EXTI15_10_IRQn ] = isr_exti, /* [40] External Line[15:10] Interrupts */
[RTC_Alarm_IRQn ] = isr_rtc_alarm, /* [41] RTC Alarm (A and B) through EXTI Line Interrupt */
[CRS_IRQn ] = isr_crs, /* [42] CRS global interrupt */
[PWR_SOTF_BLEACT_802ACT_RFPHASE_IRQn] = isr_sotf_pwr_ble_802_rfphase, /* [43] PWR switching on the fly interrupt
PWR end of BLE activity interrupt
PWR end of 802.15.4 (Zigbee) activity interrupt
PWR end of critical radio phase interrupt */
[IPCC_C1_RX_IRQn ] = isr_ipcc_c1_rx, /* [44] IPCC RX Occupied Interrupt */
[IPCC_C1_TX_IRQn ] = isr_ipcc_c1_tx, /* [45] HIPCC TX Free Interrupt */
[HSEM_IRQn ] = isr_hsem, /* [46] HSEM Interrupt */
[LPTIM1_IRQn ] = isr_lptim1, /* [47] LP TIM1 interrupt */
[LPTIM2_IRQn ] = isr_lptim2, /* [48] LP TIM2 interrupt */
[LCD_IRQn ] = isr_lcd, /* [49] LCD global interrupt */
[QUADSPI_IRQn ] = isr_quadspi, /* [50] Quad SPI global interrupt */
[AES1_IRQn ] = isr_aes1, /* [51] AES1 Interrup */
[AES2_IRQn ] = isr_aes2, /* [52] AES2 Interrupt */
[RNG_IRQn ] = isr_rng, /* [53] RNG global interrupt */
[FPU_IRQn ] = isr_fpu, /* [54] FPU global interrupt */
[DMA2_Channel1_IRQn ] = isr_dma2_channel1, /* [55] DMA2 Channel 1 global Interrupt */
[DMA2_Channel2_IRQn ] = isr_dma2_channel2, /* [56] DMA2 Channel 2 global Interrupt */
[DMA2_Channel3_IRQn ] = isr_dma2_channel3, /* [57] DMA2 Channel 3 global Interrupt */
[DMA2_Channel4_IRQn ] = isr_dma2_channel4, /* [58] DMA2 Channel 4 global Interrupt */
[DMA2_Channel5_IRQn ] = isr_dma2_channel5, /* [69] DMA2 Channel 5 global Interrupt */
[DMA2_Channel6_IRQn ] = isr_dma2_channel6, /* [60] DMA2 Channel 6 global interrupt */
[DMA2_Channel7_IRQn ] = isr_dma2_channel7, /* [61] DMA2 Channel 7 global interrupt */
[DMAMUX1_OVR_IRQn ] = isr_dmamux1_ovr, /* [62] DMAMUX1 overrun global interrupt */
};