1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-24 22:13:52 +01:00

Merge pull request #11895 from fjmolinas/pr_pnucleowb55

boards/p-nucleo-wb55: add initial support
This commit is contained in:
Alexandre Abadie 2020-03-25 10:00:13 +01:00 committed by GitHub
commit a62abe00ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 14838 additions and 62 deletions

3
boards/common/stm32/dist/stm32wb.cfg vendored Normal file
View File

@ -0,0 +1,3 @@
source [find target/stm32wbx.cfg]
reset_config srst_only
$_TARGETNAME configure -rtos auto

View File

@ -47,7 +47,7 @@ static const i2c_conf_t i2c_config[] = {
.rcc_mask = RCC_APB1ENR_I2C1EN,
.clk = CLOCK_APB1,
.irqn = I2C1_EV_IRQn,
#elif CPU_FAM_STM32L4
#elif CPU_FAM_STM32L4 || CPU_FAM_STM32WB
.rcc_mask = RCC_APB1ENR1_I2C1EN,
.irqn = I2C1_ER_IRQn,
#elif CPU_FAM_STM32F7
@ -65,7 +65,7 @@ static const i2c_conf_t i2c_config[] = {
#if CPU_FAM_STM32F4 || CPU_FAM_STM32F2
#define I2C_0_ISR isr_i2c1_ev
#elif CPU_FAM_STM32L4 || CPU_FAM_STM32F7
#elif CPU_FAM_STM32L4 || CPU_FAM_STM32F7 || CPU_FAM_STM32WB
#define I2C_0_ISR isr_i2c1_er
#elif CPU_FAM_STM32F0 || CPU_FAM_STM32L0
#define I2C_0_ISR isr_i2c1

View File

@ -37,7 +37,7 @@ static const timer_conf_t timer_config[] = {
#else
.max = 0xffffffff,
#endif
#if CPU_FAM_STM32L4
#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB)
.rcc_mask = RCC_APB1ENR1_TIM2EN,
#else
.rcc_mask = RCC_APB1ENR_TIM2EN,

View File

@ -0,0 +1,4 @@
MODULE = board
DIRS = $(RIOTBOARD)/common/nucleo
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,3 @@
FEATURES_REQUIRED += periph_lpuart
include $(RIOTBOARD)/common/nucleo/Makefile.dep

View File

@ -0,0 +1,16 @@
## the cpu to build for
CPU = stm32wb
CPU_MODEL = stm32wb55rg
# Put defined MCU peripherals here (in alphabetical order)
FEATURES_PROVIDED += periph_i2c
FEATURES_PROVIDED += periph_lpuart
FEATURES_PROVIDED += periph_rtc
FEATURES_PROVIDED += periph_rtt
FEATURES_PROVIDED += periph_spi
FEATURES_PROVIDED += periph_timer
FEATURES_PROVIDED += periph_uart
# Put other features for this board (in alphabetical order)
FEATURES_PROVIDED += arduino
FEATURES_PROVIDED += riotboot

View File

@ -0,0 +1,14 @@
# CPU2 defines a restricted memory region. This is not available for
# CPU1 linking or general access, for now we define it by its default
# value.
CPU2_ROM_LEN = 216K
# CPU2 can define restricted SRAM within SRAM2a and SRAM2b. These subregions
# will generate busfaults if accessed by CPU1. For now we will assume that both
# SRAM2a regions are completely dedicated to CPU2.
CPU2_RAM_LEN = 64K
OPENOCD_RESET_USE_CONNECT_ASSERT_SRST ?= 1
# include shared global Nucleo Makefile
include $(RIOTBOARD)/common/nucleo/Makefile.include

View File

@ -0,0 +1,110 @@
/**
@defgroup boards_p-nucleo-wb55 STM32 p-nucleo-wb55
@ingroup boards_common_nucleo
@brief Support for the STM32 p-nucleo-wb55
Hardware
========
![st-nucleo-wb55](https://miro.medium.com/max/700/1*9OG-4Ix4EzHX9uBpMve2IA.jpeg)
MCU
---
| MCU | STM32WB55RG |
|:---------- |:------------------------------- |
| Family | ARM Cortex-M4 |
| Vendor | ST Microelectronics |
| RAM | 256KB |
| Flash | 512KB |
| Frequency | 64MHz |
| FPU | yes |
| Timers | 8 (3x 16-bit, 1x 32-bit [TIM5]) |
| LPTimers | 2x 16-bit |
| ADCs | 1x 19-channel 12-bit |
| UARTs | 1 |
| LUARTs | 1 |
| SPIs | 1 |
| I2Cs | 2 |
| RTC | 1 |
| Vcc | 1.65V - 3.6V |
| Datasheet | [Datasheet](https://www.st.com/resource/en/datasheet/stm32wb55cc.pdf)|
| Reference Manual | [Reference Manual](https://www.st.com/resource/en/datasheet/stm32wb55cc.pdf) |
| User Manual | [User Manual](https://www.st.com/content/ccc/resource/technical/document/user_manual/group1/13/58/22/1a/f2/ff/43/5c/DM00517423/files/DM00517423.pdf/jcr:content/translations/en.DM00517423.pdf) |
Overview
========
The p-nucleo-wb55 is a multi-protocol wireless and ultra-low-power
device embedding a powerful and ultra-low-power radio compliant with the
Bluetooth® Low Energy (BLE) SIG specification v5.0 and with IEEE
802.15.4-2011 board. It integrates an ARM Cortex-M4 STM32WB55RG microcontroller
with 256KB of RAM and 1MB of ROM Flash.
Flashing the device
-------------------
The ST p-nucleo-wb55 board includes an on-board ST-LINK programmer and can be
flashed using OpenOCD.
@note The latest release of OpenOCD doesn't contain support for this board,
so a recent development version must be built from source to be able to flash
this board.
To flash this board, just use the following command:
```
make BOARD=p-nucleo-wb55 flash -C examples/hello-world
```
STDIO
-----
STDIO is available via the ST-Link programmer.
Use the `term` target to open a terminal:
make BOARD=p-nucleo-wb55 -C examples/hello-world term
User Interface
--------------
4 Button:
| NAME | RESET/SW4 | SW1 | SW2 | SW3 |
|:------ |:--------- |:----- |:----- |:----- |
| Pin | NRST | PC4 | PD0 | PD1 |
3 LED:
| NAME | LED1 | LED2 | LED3 |
| ----- | ------ | ------ | ------ |
| Color | blue | green | red |
| Pin | PB5 | PB0 | PB1 |
Implementation Status
---------------------
| Device | ID | Supported | Comments |
|:---------------- |:----------------- |:------- |:------- |
| MCU | stm32wb | yes | |
| | M0+ co-processor | no | |
| | BLE | no | |
| | 802.15.4 | no | |
| Low-level driver | GPIO | yes | |
| | UART | yes | UART1 |
| | LPUART | yes | LPUART1 |
| | I2C | yes | I2C1 |
| | SPI | yes | |
| | ADC | yes | |
| | RTT | yes | |
| | RTC | yes | |
| | RNG | yes | |
| | Timer | yes | TIM2 |
| | WDT | no | |
| | USB | no | |
| | PWM | no | |
| | AES | no | |
*/

View File

@ -0,0 +1,73 @@
/*
* Copyright (C) 2016 Freie Universität Berlin
* 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 boards_p-nucleo-wb55
* @{
*
* @file
* @brief Board specific configuration for the Arduino API
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
*/
#ifndef ARDUINO_BOARD_H
#define ARDUINO_BOARD_H
#include "arduino_pinmap.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Look-up table for the Arduino's digital pins
*/
static const gpio_t arduino_pinmap[] = {
ARDUINO_PIN_0,
ARDUINO_PIN_1,
ARDUINO_PIN_2,
ARDUINO_PIN_3,
ARDUINO_PIN_4,
ARDUINO_PIN_5,
ARDUINO_PIN_6,
ARDUINO_PIN_7,
ARDUINO_PIN_8,
ARDUINO_PIN_9,
ARDUINO_PIN_10,
ARDUINO_PIN_11,
ARDUINO_PIN_12,
ARDUINO_PIN_13,
ARDUINO_PIN_A0,
ARDUINO_PIN_A1,
ARDUINO_PIN_A2,
ARDUINO_PIN_A3,
ARDUINO_PIN_A4,
ARDUINO_PIN_A5,
};
/**
* @brief Look-up table for the Arduino's analog pins
*/
static const adc_t arduino_analog_map[] = {
ARDUINO_A0,
ARDUINO_A1,
ARDUINO_A2,
ARDUINO_A3,
ARDUINO_A4,
ARDUINO_A5,
};
#ifdef __cplusplus
}
#endif
#endif /* ARDUINO_BOARD_H */
/** @} */

View File

@ -0,0 +1,80 @@
/*
* 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 boards_p-nucleo-wb55
* @{
*
* @file
* @brief Mapping from MCU pins to Arduino pins
*
* You can use the defines in this file for simplified interaction with the
* Arduino specific pin numbers.
*
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
* @author Francisco Molina <francois-xavier.molina@inria.fr>
*
*/
#ifndef ARDUINO_PINMAP_H
#define ARDUINO_PINMAP_H
#include "periph/gpio.h"
#include "periph/adc.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Mapping of MCU pins to Arduino pins
* @{
*/
#define ARDUINO_PIN_0 GPIO_PIN(PORT_A, 3)
#define ARDUINO_PIN_1 GPIO_PIN(PORT_A, 2)
#define ARDUINO_PIN_2 GPIO_PIN(PORT_C, 6)
#define ARDUINO_PIN_3 GPIO_PIN(PORT_A, 10)
#define ARDUINO_PIN_4 GPIO_PIN(PORT_C, 10)
#define ARDUINO_PIN_5 GPIO_PIN(PORT_A, 15)
#define ARDUINO_PIN_6 GPIO_PIN(PORT_A, 8)
#define ARDUINO_PIN_7 GPIO_PIN(PORT_C, 13)
#define ARDUINO_PIN_8 GPIO_PIN(PORT_C, 12)
#define ARDUINO_PIN_9 GPIO_PIN(PORT_A, 9)
#define ARDUINO_PIN_10 GPIO_PIN(PORT_A, 4)
#define ARDUINO_PIN_11 GPIO_PIN(PORT_A, 7)
#define ARDUINO_PIN_12 GPIO_PIN(PORT_A, 6)
#define ARDUINO_PIN_13 GPIO_PIN(PORT_A, 5)
#define ARDUINO_PIN_14 GPIO_PIN(PORT_B, 9)
#define ARDUINO_PIN_15 GPIO_PIN(PORT_B, 8)
#define ARDUINO_PIN_A0 GPIO_PIN(PORT_C, 0)
#define ARDUINO_PIN_A1 GPIO_PIN(PORT_C, 1)
#define ARDUINO_PIN_A2 GPIO_PIN(PORT_A, 1)
#define ARDUINO_PIN_A3 GPIO_PIN(PORT_A, 0)
#define ARDUINO_PIN_A4 GPIO_PIN(PORT_C, 3)
#define ARDUINO_PIN_A5 GPIO_PIN(PORT_C, 2)
/** @ */
/**
* @name Mapping of Arduino analog pins to RIOT ADC lines
* @{
*/
#define ARDUINO_A0 ADC_LINE(0)
#define ARDUINO_A1 ADC_LINE(1)
#define ARDUINO_A2 ADC_LINE(2)
#define ARDUINO_A3 ADC_LINE(3)
#define ARDUINO_A4 ADC_LINE(4)
#define ARDUINO_A5 ADC_LINE(5)
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* ARDUINO_PINMAP_H */
/** @} */

View File

@ -0,0 +1,77 @@
/*
* 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 boards_p-nucleo-wb55
* @{
*
* @file
* @brief Pin definitions and board configuration options
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
*/
#ifndef BOARD_H
#define BOARD_H
#include "board_nucleo.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name LED pin definitions and handlers
* @{
*/
#define LED0_PORT GPIOB
#define LED0_PIN GPIO_PIN(PORT_B, 5)
#define LED0_MASK (1 << 5)
#define LED0_ON (LED0_PORT->BSRR = LED0_MASK)
#define LED0_OFF (LED0_PORT->BSRR = (LED0_MASK << 16))
#define LED0_TOGGLE (LED0_PORT->ODR ^= LED0_MASK)
#define LED1_PORT GPIOB
#define LED1_PIN GPIO_PIN(PORT_B, 0)
#define LED1_MASK (1 << 0)
#define LED1_ON (LED0_PORT->BSRR = LED1_MASK)
#define LED1_OFF (LED0_PORT->BSRR = (LED1_MASK << 16))
#define LED1_TOGGLE (LED0_PORT->ODR ^= LED1_MASK)
#define LED2_PORT GPIOB
#define LED2_PIN GPIO_PIN(PORT_B, 1)
#define LED2_MASK (1 << 1)
#define LED2_ON (LED0_PORT->BSRR = LED2_MASK)
#define LED2_OFF (LED0_PORT->BSRR = (LED2_MASK << 16))
#define LED2_TOGGLE (LED0_PORT->ODR ^= LED2_MASK)
/** @} */
/* p-nucleo-wb55 always use LED0, as there is no dual use of its pin */
#ifndef AUTO_INIT_LED0
#define AUTO_INIT_LED0
#endif
/** @} */
/**
* @name User button
* @{
*/
#define BTN0_PIN GPIO_PIN(PORT_C, 4)
#define BTN0_MODE GPIO_IN_PU
#define BTN1_PIN GPIO_PIN(PORT_D, 0)
#define BTN1_MODE GPIO_IN_PU
#define BTN2_PIN GPIO_PIN(PORT_D, 1)
#define BTN2_MODE GPIO_IN_PU
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H */
/** @} */

View File

@ -0,0 +1,78 @@
/*
* 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 boards_p-nucleo-wb55
* @{
*
* @file
* @brief Board specific configuration of direct mapped GPIOs
*
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
* @author Francisco Molina <francois-xavier.molina@inria.fr>
*
*/
#ifndef GPIO_PARAMS_H
#define GPIO_PARAMS_H
#include "board.h"
#include "saul/periph.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief GPIO pin configuration
*/
static const saul_gpio_params_t saul_gpio_params[] =
{
#ifdef AUTO_INIT_LED0
{
.name = "LED(blue)",
.pin = LED0_PIN,
.mode = GPIO_OUT
},
#endif
{
.name = "LED(green)",
.pin = LED1_PIN,
.mode = GPIO_OUT
},
{
.name = "LED(red)",
.pin = LED2_PIN,
.mode = GPIO_OUT
},
{
.name = "Button(B1 User)",
.pin = BTN0_PIN,
.mode = BTN0_MODE,
.flags = SAUL_GPIO_INVERTED,
},
{
.name = "Button(B2 User)",
.pin = BTN1_PIN,
.mode = BTN1_MODE,
.flags = SAUL_GPIO_INVERTED,
},
{
.name = "Button(B3 User)",
.pin = BTN2_PIN,
.mode = BTN2_MODE,
.flags = SAUL_GPIO_INVERTED,
},
};
#ifdef __cplusplus
}
#endif
#endif /* GPIO_PARAMS_H */
/** @} */

View File

@ -0,0 +1,175 @@
/*
* 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 boards_p-nucleo-wb55
* @{
*
* @file
* @brief Peripheral MCU configuration for the p-nucleo-wb55 board
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
*/
#ifndef PERIPH_CONF_H
#define PERIPH_CONF_H
#include "periph_cpu.h"
#include "cfg_i2c1_pb8_pb9.h"
#include "cfg_rtt_default.h"
#include "cfg_timer_tim2.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Clock system configuration
* @{
*/
/* 0: no external high speed crystal available
* else: actual crystal frequency [in Hz] */
#define CLOCK_HSE (32000000U)
#ifndef CLOCK_LSE
/* 0: no external low speed crystal available,
* 1: external crystal available (always 32.768kHz)
*/
#define CLOCK_LSE (1)
#endif
/* 0: enable MSI only if HSE isn't available
* 1: always enable MSI (e.g. if USB or RNG is used)*/
#define CLOCK_MSI_ENABLE (1)
#ifndef CLOCK_MSI_LSE_PLL
/* 0: disable Hardware auto calibration with LSE
* 1: enable Hardware auto calibration with LSE (PLL-mode)
*/
#define CLOCK_MSI_LSE_PLL (1)
#endif
/* give the target core clock (HCLK) frequency [in Hz], maximum: 64MHz */
#define CLOCK_CORECLOCK (64000000U)
/* PLL configuration: make sure your values are legit!
*
* compute by: CORECLOCK = (((PLL_IN / M) * N) / R)
* with:
* PLL_IN: input clock, HSE or MSI @ 48MHz
* M: pre-divider, allowed range: [1:8]
* N: multiplier, allowed range: [8:86]
* R: post-divider, allowed range: [2:8]
*
* Also the following constraints need to be met:
* (PLL_IN / M) -> [4MHz:16MHz]
* (PLL_IN / M) * N -> [64MHz:344MHz]
* CORECLOCK -> 64MHz MAX!
*/
#define CLOCK_PLL_M (4)
#define CLOCK_PLL_N (32)
#define CLOCK_PLL_R (4)
/* EXTAHB (HCLK2) max freq 32 Mhz*/
#define CLOCK_EXTAHB_DIV RCC_EXTCFGR_C2HPRE_3
#define CLOCK_EXTAHB (CLOCK_CORECLOCK / 2)
/* peripheral clock setup */
#define CLOCK_AHB_DIV 0x00000000U
#define CLOCK_AHB (CLOCK_CORECLOCK / 1)
#define CLOCK_APB1_DIV 0x00000000U
#define CLOCK_APB1 (CLOCK_CORECLOCK / 1)
#define CLOCK_APB2_DIV 0x00000000U
#define CLOCK_APB2 (CLOCK_CORECLOCK / 1)
/** @} */
/**
* @name UART configuration
* @{
*/
static const uart_conf_t uart_config[] = {
{
.dev = USART1,
.rcc_mask = RCC_APB2ENR_USART1EN,
.rx_pin = GPIO_PIN(PORT_B, 7),
.tx_pin = GPIO_PIN(PORT_B, 6),
.rx_af = GPIO_AF7,
.tx_af = GPIO_AF7,
.bus = APB2,
.irqn = USART1_IRQn,
.type = STM32_USART,
.clk_src = 0, /* Use APB clock */
},
{
.dev = LPUART1,
.rcc_mask = RCC_APB1ENR2_LPUART1EN,
.rx_pin = GPIO_PIN(PORT_A, 3),
.tx_pin = GPIO_PIN(PORT_A, 2),
.rx_af = GPIO_AF8,
.tx_af = GPIO_AF8,
.bus = APB12,
.irqn = LPUART1_IRQn,
.type = STM32_LPUART,
.clk_src = 0, /* Use APB clock */
},
};
#define UART_0_ISR (isr_usart1)
#define UART_1_ISR (isr_lpuart1)
#define UART_NUMOF ARRAY_SIZE(uart_config)
/** @} */
/**
* @name SPI configuration
*
* @note The spi_divtable is auto-generated from
* `cpu/stm32_common/dist/spi_divtable/spi_divtable.c`
* @{
*/
static const uint8_t spi_divtable[2][5] = {
{ /* for APB1 @ 20000000Hz */
7, /* -> 78125Hz */
5, /* -> 312500Hz */
3, /* -> 1250000Hz */
1, /* -> 5000000Hz */
0 /* -> 10000000Hz */
},
{ /* for APB2 @ 40000000Hz */
7, /* -> 156250Hz */
6, /* -> 312500Hz */
4, /* -> 1250000Hz */
2, /* -> 5000000Hz */
1 /* -> 10000000Hz */
}
};
static const spi_conf_t spi_config[] = {
{
.dev = SPI1,
.mosi_pin = GPIO_PIN(PORT_A, 7),
.miso_pin = GPIO_PIN(PORT_A, 6),
.sclk_pin = GPIO_PIN(PORT_A, 5),
.cs_pin = GPIO_UNDEF,
.mosi_af = GPIO_AF5,
.miso_af = GPIO_AF5,
.sclk_af = GPIO_AF5,
.cs_af = GPIO_AF5,
.rccmask = RCC_APB2ENR_SPI1EN,
.apbbus = APB2,
}
};
#define SPI_NUMOF ARRAY_SIZE(spi_config)
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* PERIPH_CONF_H */
/** @} */

View File

@ -9,8 +9,20 @@ INCLUDES += -I$(RIOTCPU)/stm32_common/include
# Compute ROM_LEN and RAM_LEN
include $(RIOTCPU)/stm32_common/stm32_mem_lengths.mk
KB := 1024
LEN := $(shell echo $(ROM_LEN) | sed 's/K//')
FLASHSIZE := $(shell echo $$(( $(LEN) * $(KB) )) )
ROM_LEN_K := $(shell echo $(ROM_LEN) | sed 's/K//')
ifeq (stm32wb55rg,$(CPU_MODEL))
# adjust RAM_LEN and ROM_LEN according to CPU2 RAM_LEN and ROM_LEN
RAM_LEN_K := $(shell echo $(RAM_LEN) | sed 's/K//')
CPU2_RAM_LEN_K := $(shell echo $(CPU2_RAM_LEN) | sed 's/K//')
RAM_LEN := $(shell echo $$(( ($(RAM_LEN_K) - $(CPU2_RAM_LEN_K) ) ))K)
CPU2_ROM_LEN_K := $(shell echo $(CPU2_ROM_LEN) | sed 's/K//')
FLASHSIZE := $(shell echo $$(( ($(ROM_LEN_K) - $(CPU2_ROM_LEN_K) )* $(KB) )) )
ROM_LEN := $(shell echo $$(( ($(ROM_LEN_K) - $(CPU2_ROM_LEN_K) ) ))K)
else
FLASHSIZE := $(shell echo $$(( $(ROM_LEN_K) * $(KB) )) )
endif
# Get CPU_LINE_ variable
-include $(RIOTCPU)/$(CPU)/stm32_line.mk

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

@ -32,7 +32,7 @@
#define CNTRL_REG_LOCK (FLASH_PECR_PELOCK)
#define KEY_REG (FLASH->PEKEYR)
#else
#if defined(CPU_FAM_STM32L4)
#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB)
#define FLASH_KEY1 ((uint32_t)0x45670123)
#define FLASH_KEY2 ((uint32_t)0xCDEF89AB)
#endif

View File

@ -40,7 +40,7 @@
#define FLASH_CR_PER (FLASH_PECR_ERASE | FLASH_PECR_PROG)
#define FLASHPAGE_DIV (4U) /* write 4 bytes in one go */
#else
#if defined(CPU_FAM_STM32L4)
#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB)
#define FLASHPAGE_DIV (8U)
#else
#define FLASHPAGE_DIV (2U)
@ -72,7 +72,7 @@ static void _unlock_flash(void)
static void _erase_page(void *page_addr)
{
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1) || \
defined(CPU_FAM_STM32L4)
defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB)
uint32_t *dst = page_addr;
#else
uint16_t *dst = page_addr;
@ -97,10 +97,10 @@ static void _erase_page(void *page_addr)
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1)
DEBUG("[flashpage] erase: trigger the page erase\n");
*dst = (uint32_t)0;
#elif defined(CPU_FAM_STM32L4)
#elif defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB)
DEBUG("[flashpage] erase: setting the page address\n");
uint8_t pn;
#if FLASHPAGE_NUMOF <= 256
#if (FLASHPAGE_NUMOF <= 256) || defined(CPU_FAM_STM32WB)
pn = (uint8_t)flashpage_page(dst);
#else
uint16_t page = flashpage_page(dst);
@ -158,7 +158,7 @@ void flashpage_write_raw(void *target_addr, const void *data, size_t len)
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1)
uint32_t *dst = target_addr;
const uint32_t *data_addr = data;
#elif defined(CPU_FAM_STM32L4)
#elif defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB)
uint64_t *dst = target_addr;
const uint64_t *data_addr = data;
#else
@ -181,7 +181,8 @@ void flashpage_write_raw(void *target_addr, const void *data, size_t len)
DEBUG("[flashpage_raw] write: now writing the data\n");
#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F1) || \
defined(CPU_FAM_STM32F3) || defined(CPU_FAM_STM32L4)
defined(CPU_FAM_STM32F3) || defined(CPU_FAM_STM32L4) || \
defined(CPU_FAM_STM32WB)
/* set PG bit and program page to flash */
CNTRL_REG |= FLASH_CR_PG;
#endif
@ -194,7 +195,8 @@ void flashpage_write_raw(void *target_addr, const void *data, size_t len)
/* clear program bit again */
#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F1) || \
defined(CPU_FAM_STM32F3) || defined(CPU_FAM_STM32L4)
defined(CPU_FAM_STM32F3) || defined(CPU_FAM_STM32L4) || \
defined(CPU_FAM_STM32WB)
CNTRL_REG &= ~(FLASH_CR_PG);
#endif
DEBUG("[flashpage_raw] write: done writing data\n");
@ -215,6 +217,11 @@ void flashpage_write(int page, const void *data)
{
assert(page < (int)FLASHPAGE_NUMOF);
/* ensure there is no attempt to write to CPU2 protected area */
#if defined(CPU_FAM_STM32WB)
assert(page < (int)(FLASH->SFR & FLASH_SFR_SFSA));
#endif
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1)
/* STM32L0/L1 only supports word sizes */
uint32_t *page_addr = flashpage_addr(page);

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

View File

@ -9,7 +9,7 @@
*/
/**
* @ingroup cpu_stm32l4
* @ingroup cpu_stm32_common
* @{
*
* @file
@ -19,6 +19,7 @@
* @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>
* @}
*/
@ -26,6 +27,8 @@
#include "stmclk.h"
#include "periph_conf.h"
#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB)
/* 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"
@ -37,6 +40,20 @@
#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
* @{
@ -61,6 +78,13 @@
#endif
#define PLL_N (CLOCK_PLL_N << RCC_PLLCFGR_PLLN_Pos)
#if defined(CPU_FAM_STM32WB)
#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
#else
#if (CLOCK_PLL_R == 2)
#define PLL_R (0)
#elif (CLOCK_PLL_R == 4)
@ -72,25 +96,25 @@
#else
#error "PLL configuration: PLL R value is invalid"
#endif
#endif
/** @} */
/**
* @name Deduct the needed flash wait states from the core clock frequency
* @{
*/
#if (CLOCK_CORECLOCK <= 16000000)
#define FLASH_WAITSTATES FLASH_ACR_LATENCY_0WS
#elif (CLOCK_CORECLOCK <= 32000000)
#define FLASH_WAITSTATES FLASH_ACR_LATENCY_1WS
#elif (CLOCK_CORECLOCK <= 48000000)
#define FLASH_WAITSTATES FLASH_ACR_LATENCY_2WS
#elif (CLOCK_CORECLOCK <= 64000000)
#define FLASH_WAITSTATES FLASH_ACR_LATENCY_3WS
#if defined(CPU_FAM_STM32WB)
#if (CLOCK_AHB <= 64000000)
#define FLASH_WAITSTATES ((CLOCK_AHB - 1) / 18000000U)
#else
#define FLASH_WAITSTATES FLASH_ACR_LATENCY_4WS
#define FLASH_WAITSTATES FLASH_ACR_LATENCY_3WS
#endif
#else
#define FLASH_WAITSTATES ((CLOCK_AHB - 1) / 16000000U)
#endif
/** @} */
void stmclk_init_sysclk(void)
{
/* disable any interrupts. Global interrupts could be enabled if this is
@ -105,6 +129,10 @@ void stmclk_init_sysclk(void)
* 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);
#if defined(CPU_FAM_STM32WB)
/* Use HSE/2 for radios systems */
RCC->EXTCFGR = (RCC_EXTCFGR_RFCSS | CLOCK_EXTAHB_DIV);
#endif
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) {}
/* we enable I+D cashes, pre-fetch, and we set the actual number of
@ -114,7 +142,7 @@ void stmclk_init_sysclk(void)
/* disable all active clocks except HSI -> resets the clk configuration
* Note: on STM32L4x5 & STM32L4x6 this disables the following:
PLLSAI2, PLLSAI1, Main PLL (via PLLON),
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),
@ -133,7 +161,11 @@ void stmclk_init_sysclk(void)
#if ((CLOCK_HSE == 0) || CLOCK_MSI_ENABLE)
/* reset clock to MSI with 48MHz, disables all other clocks */
#if defined(CPU_FAM_STM32WB)
RCC->CR |= (RCC_CR_MSIRANGE_11 | RCC_CR_MSION);
#else
RCC->CR |= (RCC_CR_MSIRANGE_11 | RCC_CR_MSION | RCC_CR_MSIRGSEL);
#endif
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);
@ -152,9 +184,10 @@ void stmclk_init_sysclk(void)
while (!(RCC->CR & RCC_CR_PLLRDY)) {}
/* now that the PLL is running, we use it as system clock */
RCC->CFGR |= (RCC_CFGR_SW_PLL);
RCC->CFGR |= RCC_CFGR_SW_PLL;
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) {}
stmclk_disable_hsi();
irq_restore(is);
}
#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,5 @@
FEATURES_PROVIDED += periph_flashpage
FEATURES_PROVIDED += periph_flashpage_raw
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 */
/** @} */

13717
cpu/stm32wb/include/vendor/stm32wb55xx.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

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

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 */
};

View File

@ -32,6 +32,10 @@ void flashpage_read(int page, void *data)
{
assert(page < (int)FLASHPAGE_NUMOF);
#if defined(CPU_FAM_STM32WB)
assert(page < (int)(FLASH->SFR & FLASH_SFR_SFSA));
#endif
memcpy(data, flashpage_addr(page), FLASHPAGE_SIZE);
}
@ -39,6 +43,10 @@ int flashpage_verify(int page, const void *data)
{
assert(page < (int)FLASHPAGE_NUMOF);
#if defined(CPU_FAM_STM32WB)
assert(page < (int)(FLASH->SFR & FLASH_SFR_SFSA));
#endif
if (memcmp(flashpage_addr(page), data, FLASHPAGE_SIZE) == 0) {
return FLASHPAGE_OK;
}