stm32: Add initial support for STM32WBxx MCUs.

This new series of MCUs is similar to the L4 series with an additional
Cortex-M0 coprocessor.  The firmware for the wireless stack must be managed
separately and MicroPython does not currently interface to it.  Supported
features so far include: RTC, UART, USB, internal flash filesystem.
This commit is contained in:
Damien George 2019-07-17 16:33:31 +10:00
parent d42392b9a7
commit 59b7166d87
19 changed files with 165 additions and 38 deletions

View File

@ -79,6 +79,7 @@ CFLAGS_MCU_f7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7
CFLAGS_MCU_l0 = $(CFLAGS_CORTEX_M) -mtune=cortex-m0plus -mcpu=cortex-m0plus
CFLAGS_MCU_l4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4
CFLAGS_MCU_h7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7
CFLAGS_MCU_wb = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4
CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib $(CFLAGS_MOD) $(CFLAGS_EXTRA)
CFLAGS += -D$(CMSIS_MCU)
@ -335,7 +336,7 @@ SRC_HAL = $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\
hal_uart.c \
)
ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 h7 l0 l4))
ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 h7 l0 l4 wb))
SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\
ll_usb.c \
)
@ -361,7 +362,7 @@ endif
ifeq ($(CMSIS_MCU),$(filter $(CMSIS_MCU),STM32H743xx))
SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_, hal_fdcan.c)
else
ifneq ($(MCU_SERIES),$(filter $(MCU_SERIES),l0))
ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 f4 f7 h7 l4))
SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_, hal_can.c)
endif
endif

View File

@ -34,6 +34,18 @@
#include "dma.h"
#include "irq.h"
#if defined(STM32WB)
// DMA is currently not implemented for this MCU
void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint32_t dir, void *data) {
}
void dma_deinit(const dma_descr_t *dma_descr) {
}
#else
#define DMA_IDLE_ENABLED() (dma_idle.enabled != 0)
#define DMA_SYSTICK_LOG2 (3)
#define DMA_SYSTICK_MASK ((1 << DMA_SYSTICK_LOG2) - 1)
@ -919,3 +931,5 @@ void dma_nohal_start(const dma_descr_t *descr, uint32_t src_addr, uint32_t dst_a
}
#endif
#endif // defined(STM32WB)

View File

@ -73,7 +73,7 @@ extern const dma_descr_t dma_I2C_2_RX;
extern const dma_descr_t dma_I2C_1_TX;
extern const dma_descr_t dma_I2C_1_RX;
#elif defined(STM32L4)
#elif defined(STM32L4) || defined(STM32WB)
extern const dma_descr_t dma_ADC_1_RX;
extern const dma_descr_t dma_ADC_2_RX;

View File

@ -91,7 +91,7 @@
#define EXTI_SWIER_BB(line) (*(__IO uint32_t *)(PERIPH_BB_BASE + ((EXTI_OFFSET + offsetof(EXTI_TypeDef, SWIER)) * 32) + ((line) * 4)))
#endif
#if defined(STM32L4)
#if defined(STM32L4) || defined(STM32WB)
// The L4 MCU supports 40 Events/IRQs lines of the type configurable and direct.
// Here we only support configurable line types. Details, see page 330 of RM0351, Rev 1.
// The USB_FS_WAKUP event is a direct type and there is no support for it.
@ -140,6 +140,7 @@ STATIC mp_obj_t pyb_extint_callback_arg[EXTI_NUM_VECTORS];
STATIC const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = {
#if defined(STM32F0) || defined(STM32L0)
EXTI0_1_IRQn, EXTI0_1_IRQn, EXTI2_3_IRQn, EXTI2_3_IRQn,
EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn,
EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn,
@ -155,11 +156,19 @@ STATIC const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = {
RTC_IRQn,
ADC1_COMP_IRQn,
ADC1_COMP_IRQn,
#else
EXTI0_IRQn, EXTI1_IRQn, EXTI2_IRQn, EXTI3_IRQn, EXTI4_IRQn,
EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn,
EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn,
EXTI15_10_IRQn,
#if defined(STM32WB)
PVD_PVM_IRQn,
RTC_Alarm_IRQn,
TAMP_STAMP_LSECSS_IRQn,
RTC_WKUP_IRQn,
#else
#if defined(STM32L4)
PVD_PVM_IRQn,
#else
@ -177,6 +186,8 @@ STATIC const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = {
TAMP_STAMP_IRQn,
RTC_WKUP_IRQn,
#endif
#endif
};
// Set override_callback_obj to true if you want to unconditionally set the
@ -285,7 +296,9 @@ void extint_register_pin(const pin_obj_t *pin, uint32_t mode, bool hard_irq, mp_
pyb_extint_callback_arg[line] = MP_OBJ_FROM_PTR(pin);
// Route the GPIO to EXTI
#if !defined(STM32WB)
__HAL_RCC_SYSCFG_CLK_ENABLE();
#endif
SYSCFG->EXTICR[line >> 2] =
(SYSCFG->EXTICR[line >> 2] & ~(0x0f << (4 * (line & 0x03))))
| ((uint32_t)(GPIO_GET_INDEX(pin->gpio)) << (4 * (line & 0x03)));
@ -320,7 +333,9 @@ void extint_set(const pin_obj_t *pin, uint32_t mode) {
pyb_extint_callback_arg[line] = MP_OBJ_FROM_PTR(pin);
// Route the GPIO to EXTI
#if !defined(STM32WB)
__HAL_RCC_SYSCFG_CLK_ENABLE();
#endif
SYSCFG->EXTICR[line >> 2] =
(SYSCFG->EXTICR[line >> 2] & ~(0x0f << (4 * (line & 0x03))))
| ((uint32_t)(GPIO_GET_INDEX(pin->gpio)) << (4 * (line & 0x03)));
@ -358,12 +373,16 @@ void extint_enable(uint line) {
if (pyb_extint_mode[line] == EXTI_Mode_Interrupt) {
#if defined(STM32H7)
EXTI_D1->IMR1 |= (1 << line);
#elif defined(STM32WB)
EXTI->IMR1 |= (1 << line);
#else
EXTI->IMR |= (1 << line);
#endif
} else {
#if defined(STM32H7)
EXTI_D1->EMR1 |= (1 << line);
#elif defined(STM32WB)
EXTI->EMR1 |= (1 << line);
#else
EXTI->EMR |= (1 << line);
#endif
@ -388,6 +407,9 @@ void extint_disable(uint line) {
#if defined(STM32H7)
EXTI_D1->IMR1 &= ~(1 << line);
EXTI_D1->EMR1 &= ~(1 << line);
#elif defined(STM32WB)
EXTI->IMR1 &= ~(1 << line);
EXTI->EMR1 &= ~(1 << line);
#else
EXTI->IMR &= ~(1 << line);
EXTI->EMR &= ~(1 << line);
@ -407,7 +429,7 @@ void extint_swint(uint line) {
return;
}
// we need 0 to 1 transition to trigger the interrupt
#if defined(STM32L4) || defined(STM32H7)
#if defined(STM32L4) || defined(STM32H7) || defined(STM32WB)
EXTI->SWIER1 &= ~(1 << line);
EXTI->SWIER1 |= (1 << line);
#else
@ -485,7 +507,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_swint_obj, extint_obj_swint);
/// \classmethod regs()
/// Dump the values of the EXTI registers.
STATIC mp_obj_t extint_regs(void) {
#if defined(STM32L4)
#if defined(STM32L4) || defined(STM32WB)
printf("EXTI_IMR1 %08x\n", (unsigned int)EXTI->IMR1);
printf("EXTI_IMR2 %08x\n", (unsigned int)EXTI->IMR2);
printf("EXTI_EMR1 %08x\n", (unsigned int)EXTI->EMR1);

View File

@ -46,7 +46,7 @@
#if defined(STM32F0) || defined(STM32L4)
#define EXTI_RTC_TIMESTAMP (19)
#define EXTI_RTC_WAKEUP (20)
#elif defined(STM32H7)
#elif defined(STM32H7) || defined(STM32WB)
#define EXTI_RTC_TIMESTAMP (18)
#define EXTI_RTC_WAKEUP (19)
#else

View File

@ -68,7 +68,7 @@ static const flash_layout_t flash_layout[] = {
{ 0x08040000, 0x40000, 3 },
};
#elif defined(STM32L0) || defined(STM32L4)
#elif defined(STM32L0) || defined(STM32L4) || defined(STM32WB)
static const flash_layout_t flash_layout[] = {
{ (uint32_t)FLASH_BASE, (uint32_t)FLASH_PAGE_SIZE, 512 },
@ -122,7 +122,7 @@ static uint32_t get_page(uint32_t addr) {
}
#endif
#elif defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE)
#elif (defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE)) || defined(STM32WB)
static uint32_t get_page(uint32_t addr) {
return (addr - FLASH_BASE) / FLASH_PAGE_SIZE;
@ -175,7 +175,7 @@ void flash_erase(uint32_t flash_dest, uint32_t num_word32) {
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.PageAddress = flash_dest;
EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE;
#elif defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE)
#elif (defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE)) || defined(STM32WB)
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.Page = get_page(flash_dest);
@ -247,7 +247,7 @@ void flash_erase_it(uint32_t flash_dest, uint32_t num_word32) {
*/
void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) {
#if defined(STM32L4)
#if defined(STM32L4) || defined(STM32WB)
// program the flash uint64 by uint64
for (int i = 0; i < num_word32 / 2; i++) {

View File

@ -105,7 +105,8 @@ STATIC byte flash_cache_mem[0x4000] __attribute__((aligned(4))); // 16k
#elif defined(STM32L432xx) || \
defined(STM32L451xx) || defined(STM32L452xx) || defined(STM32L462xx) || \
defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L496xx)
defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L496xx) || \
defined(STM32WB)
// The STM32L4xx doesn't have CCRAM, so we use SRAM2 for this, although
// actual location and size is defined by the linker script.

View File

@ -489,7 +489,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_readchar_obj, pyb_uart_readchar);
// uart.sendbreak()
STATIC mp_obj_t pyb_uart_sendbreak(mp_obj_t self_in) {
pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
#if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7)
#if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB)
self->uartx->RQR = USART_RQR_SBKRQ; // write-only register
#else
self->uartx->CR1 |= USART_CR1_SBK;

View File

@ -61,7 +61,7 @@
#define RCC_CSR_BORRSTF RCC_CSR_PORRSTF
#endif
#if defined(STM32L4)
#if defined(STM32L4) || defined(STM32WB)
// L4 does not have a POR, so use BOR instead
#define RCC_CSR_PORRSTF RCC_CSR_BORRSTF
#endif
@ -305,7 +305,7 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) {
return mp_obj_new_tuple(MP_ARRAY_SIZE(tuple), tuple);
} else {
// set
#if defined(STM32F0) || defined(STM32L0) || defined(STM32L4)
#if defined(STM32F0) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB)
mp_raise_NotImplementedError("machine.freq set not supported yet");
#else
mp_int_t sysclk = mp_obj_get_int(args[0]);

View File

@ -202,6 +202,15 @@
#define MICROPY_HW_MAX_TIMER (17)
#define MICROPY_HW_MAX_UART (6)
// Configuration for STM32WB series
#elif defined(STM32WB)
#define MP_HAL_UNIQUE_ID_ADDRESS (UID_BASE)
#define PYB_EXTI_NUM_VECTORS (20)
#define MICROPY_HW_MAX_I2C (3)
#define MICROPY_HW_MAX_TIMER (17)
#define MICROPY_HW_MAX_UART (1)
#else
#error Unsupported MCU series
#endif

View File

@ -122,7 +122,7 @@ void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio) {
#elif defined(STM32L0)
#define AHBxENR IOPENR
#define AHBxENR_GPIOAEN_Pos RCC_IOPENR_IOPAEN_Pos
#elif defined(STM32L4)
#elif defined(STM32L4) || defined(STM32WB)
#define AHBxENR AHB2ENR
#define AHBxENR_GPIOAEN_Pos RCC_AHB2ENR_GPIOAEN_Pos
#endif

View File

@ -76,7 +76,7 @@ void powerctrl_check_enter_bootloader(void) {
if ((bl_addr & 0xfff) == 0 && (RCC->RCC_SR & RCC_SR_SFTRSTF)) {
// Reset by NVIC_SystemReset with bootloader data set -> branch to bootloader
RCC->RCC_SR = RCC_SR_RMVF;
#if defined(STM32F0) || defined(STM32F4) || defined(STM32L4)
#if defined(STM32F0) || defined(STM32F4) || defined(STM32L4) || defined(STM32WB)
__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
#endif
uint32_t r0 = BL_STATE[0];
@ -84,7 +84,7 @@ void powerctrl_check_enter_bootloader(void) {
}
}
#if !defined(STM32F0) && !defined(STM32L0)
#if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32WB)
// Assumes that PLL is used as the SYSCLK source
int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk_mhz, bool need_pllsai) {
@ -158,7 +158,7 @@ int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk
#endif
#if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4)
#if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4) && !defined(STM32WB)
STATIC uint32_t calc_ahb_div(uint32_t wanted_div) {
if (wanted_div <= 1) { return RCC_SYSCLK_DIV1; }
@ -333,7 +333,7 @@ void powerctrl_enter_stop_mode(void) {
__HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_MSI);
#endif
#if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4)
#if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4) && !defined(STM32WB)
// takes longer to wake but reduces stop current
HAL_PWREx_EnableFlashPowerDown();
#endif
@ -380,6 +380,9 @@ void powerctrl_enter_stop_mode(void) {
#if defined(STM32H7)
while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL1) {
}
#elif defined(STM32WB)
while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_PLLCLK) {
}
#else
while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) {
}
@ -450,7 +453,7 @@ void powerctrl_enter_standby_mode(void) {
PWR->CR2 |= PWR_CR2_CWUPF6 | PWR_CR2_CWUPF5 | PWR_CR2_CWUPF4 | PWR_CR2_CWUPF3 | PWR_CR2_CWUPF2 | PWR_CR2_CWUPF1;
#elif defined(STM32H7)
// TODO
#elif defined(STM32L4)
#elif defined(STM32L4) || defined(STM32WB)
// clear all wake-up flags
PWR->SCR |= PWR_SCR_CWUF5 | PWR_SCR_CWUF4 | PWR_SCR_CWUF3 | PWR_SCR_CWUF2 | PWR_SCR_CWUF1;
// TODO

View File

@ -131,4 +131,50 @@ void SystemClock_Config(void) {
#endif
}
#elif defined(STM32WB)
void SystemClock_Config(void) {
// Enable the 32MHz external oscillator
RCC->CR |= RCC_CR_HSEON;
while (!(RCC->CR & RCC_CR_HSERDY)) {
}
// Use HSE and the PLL to get a 64MHz SYSCLK
#define PLLM (HSE_VALUE / 8000000) // VCO input is 8MHz
#define PLLN (24) // 24*8MHz = 192MHz
#define PLLQ (4) // f_Q = 48MHz
#define PLLR (3) // f_R = 64MHz
RCC->PLLCFGR =
(PLLR - 1) << RCC_PLLCFGR_PLLR_Pos | RCC_PLLCFGR_PLLREN
| (PLLQ - 1) << RCC_PLLCFGR_PLLQ_Pos | RCC_PLLCFGR_PLLQEN
| PLLN << RCC_PLLCFGR_PLLN_Pos
| (PLLM - 1) << RCC_PLLCFGR_PLLM_Pos
| 3 << RCC_PLLCFGR_PLLSRC_Pos;
RCC->CR |= RCC_CR_PLLON;
while (!(RCC->CR & RCC_CR_PLLRDY)) {
// Wait for PLL to lock
}
const uint32_t sysclk_src = 3;
// Set divider for HCLK2 to 2 so f_HCLK2 = 32MHz
RCC->EXTCFGR = 8 << RCC_EXTCFGR_C2HPRE_Pos;
// Set flash latency to 3 because SYSCLK > 54MHz
FLASH->ACR |= 3 << FLASH_ACR_LATENCY_Pos;
// Select SYSCLK source
RCC->CFGR |= sysclk_src << RCC_CFGR_SW_Pos;
while (((RCC->CFGR >> RCC_CFGR_SWS_Pos) & 0x3) != sysclk_src) {
// Wait for SYSCLK source to change
}
// Select PLLQ as 48MHz source for USB and RNG
RCC->CCIPR = 2 << RCC_CCIPR_CLK48SEL_Pos;
SystemCoreClockUpdate();
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
}
#endif

View File

@ -31,6 +31,14 @@
#include "rtc.h"
#include "irq.h"
#if defined(STM32WB)
#define RCC_CSR_LSION RCC_CSR_LSI1ON
#define RCC_FLAG_LSIRDY RCC_FLAG_LSI1RDY
#define RCC_OSCILLATORTYPE_LSI RCC_OSCILLATORTYPE_LSI1
#define __HAL_RCC_LSI_ENABLE __HAL_RCC_LSI1_ENABLE
#define __HAL_RCC_LSI_DISABLE __HAL_RCC_LSI1_DISABLE
#endif
/// \moduleref pyb
/// \class RTC - real time clock
///
@ -177,7 +185,7 @@ void rtc_init_finalise() {
// fresh reset; configure RTC Calendar
RTC_CalendarConfig();
#if defined(STM32L4)
#if defined(STM32L4) || defined(STM32WB)
if(__HAL_RCC_GET_FLAG(RCC_FLAG_BORRST) != RESET) {
#else
if(__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST) != RESET) {
@ -209,7 +217,7 @@ STATIC HAL_StatusTypeDef PYB_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruc
/*------------------------------ LSE Configuration -------------------------*/
if ((RCC_OscInitStruct->OscillatorType & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE) {
#if !defined(STM32H7)
#if !defined(STM32H7) && !defined(STM32WB)
// Enable Power Clock
__HAL_RCC_PWR_CLK_ENABLE();
#endif
@ -218,7 +226,7 @@ STATIC HAL_StatusTypeDef PYB_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruc
HAL_PWR_EnableBkUpAccess();
uint32_t tickstart = HAL_GetTick();
#if defined(STM32F7) || defined(STM32L4) || defined(STM32H7)
#if defined(STM32F7) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB)
//__HAL_RCC_PWR_CLK_ENABLE();
// Enable write access to Backup domain
//PWR->CR1 |= PWR_CR1_DBP;
@ -298,7 +306,7 @@ STATIC HAL_StatusTypeDef PYB_RTC_Init(RTC_HandleTypeDef *hrtc) {
// Exit Initialization mode
hrtc->Instance->ISR &= (uint32_t)~RTC_ISR_INIT;
#if defined(STM32L0) || defined(STM32L4) || defined(STM32H7)
#if defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB)
hrtc->Instance->OR &= (uint32_t)~RTC_OR_ALARMOUTTYPE;
hrtc->Instance->OR |= (uint32_t)(hrtc->Init.OutPutType);
#elif defined(STM32F7)
@ -649,7 +657,7 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) {
RTC->WPR = 0xff;
// enable external interrupts on line EXTI_RTC_WAKEUP
#if defined(STM32L4)
#if defined(STM32L4) || defined(STM32WB)
EXTI->IMR1 |= 1 << EXTI_RTC_WAKEUP;
EXTI->RTSR1 |= 1 << EXTI_RTC_WAKEUP;
#elif defined(STM32H7)
@ -662,7 +670,7 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) {
// clear interrupt flags
RTC->ISR &= ~RTC_ISR_WUTF;
#if defined(STM32L4)
#if defined(STM32L4) || defined(STM32WB)
EXTI->PR1 = 1 << EXTI_RTC_WAKEUP;
#elif defined(STM32H7)
EXTI_D1->PR1 = 1 << EXTI_RTC_WAKEUP;
@ -682,7 +690,7 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) {
RTC->WPR = 0xff;
// disable external interrupts on line EXTI_RTC_WAKEUP
#if defined(STM32L4)
#if defined(STM32L4) || defined(STM32WB)
EXTI->IMR1 &= ~(1 << EXTI_RTC_WAKEUP);
#elif defined(STM32H7)
EXTI_D1->IMR1 |= 1 << EXTI_RTC_WAKEUP;

View File

@ -306,6 +306,14 @@ void USB_IRQHandler(void) {
}
#endif
#elif defined(STM32WB)
#if MICROPY_HW_USB_FS
void USB_LP_IRQHandler(void) {
HAL_PCD_IRQHandler(&pcd_fs_handle);
}
#endif
#else
/**

View File

@ -78,6 +78,8 @@
#include "py/mphal.h"
#include "powerctrl.h"
#if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) || defined(STM32L4)
void __fatal_error(const char *msg);
/**
@ -392,3 +394,5 @@ void SystemClock_Config(void)
NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, TICK_INT_PRIORITY, 0));
#endif
}
#endif

View File

@ -81,7 +81,7 @@
#define USART_CR2_IE_ALL (USART_CR2_IE_BASE)
#define USART_CR3_IE_ALL (USART_CR3_IE_BASE | USART_CR3_WUFIE)
#elif defined(STM32L4)
#elif defined(STM32L4) || defined(STM32WB)
#define USART_CR1_IE_ALL (USART_CR1_IE_BASE | USART_CR1_EOBIE | USART_CR1_RTOIE | USART_CR1_CMIE)
#define USART_CR2_IE_ALL (USART_CR2_IE_BASE)
#if defined(USART_CR3_TCBGTIE)
@ -439,11 +439,13 @@ void uart_deinit(pyb_uart_obj_t *self) {
__HAL_RCC_USART1_FORCE_RESET();
__HAL_RCC_USART1_RELEASE_RESET();
__HAL_RCC_USART1_CLK_DISABLE();
#if defined(USART2)
} else if (self->uart_id == 2) {
HAL_NVIC_DisableIRQ(USART2_IRQn);
__HAL_RCC_USART2_FORCE_RESET();
__HAL_RCC_USART2_RELEASE_RESET();
__HAL_RCC_USART2_CLK_DISABLE();
#endif
#if defined(USART3)
} else if (self->uart_id == 3) {
#if !defined(STM32F0)
@ -653,7 +655,7 @@ int uart_rx_char(pyb_uart_obj_t *self) {
return data;
} else {
// no buffering
#if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7)
#if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB)
int data = self->uartx->RDR & self->char_mask;
self->uartx->ICR = USART_ICR_ORECF; // clear ORE if it was set
return data;
@ -779,7 +781,7 @@ void uart_irq_handler(mp_uint_t uart_id) {
uint16_t next_head = (self->read_buf_head + 1) % self->read_buf_len;
if (next_head != self->read_buf_tail) {
// only read data if room in buf
#if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7)
#if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB)
int data = self->uartx->RDR; // clears UART_FLAG_RXNE
self->uartx->ICR = USART_ICR_ORECF; // clear ORE if it was set
#else

View File

@ -142,7 +142,7 @@ int8_t usbd_cdc_control(usbd_cdc_state_t *cdc_in, uint8_t cmd, uint8_t* pbuf, ui
// configure its serial port (in most cases to disable local echo)
cdc->connect_state = USBD_CDC_CONNECT_STATE_CONNECTING;
usbd_cdc_connect_tx_timer = 8; // wait for 8 SOF IRQs
#if defined(STM32L0)
#if defined(STM32L0) || defined(STM32WB)
USB->CNTR |= USB_CNTR_SOFM;
#else
PCD_HandleTypeDef *hpcd = cdc->base.usbd->pdev->pData;
@ -219,7 +219,7 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) {
--usbd_cdc_connect_tx_timer;
} else {
usbd_cdc_msc_hid_state_t *usbd = ((USBD_HandleTypeDef*)hpcd->pData)->pClassData;
#if defined(STM32L0)
#if defined(STM32L0) || defined(STM32WB)
USB->CNTR &= ~USB_CNTR_SOFM;
#else
hpcd->Instance->GINTMSK &= ~USB_OTG_GINTMSK_SOFM;

View File

@ -44,7 +44,7 @@ PCD_HandleTypeDef pcd_fs_handle;
PCD_HandleTypeDef pcd_hs_handle;
#endif
#if defined(STM32L0)
#if defined(STM32L0) || defined(STM32WB)
// The STM32L0xx has a single USB device-only instance
#define USB_OTG_FS USB
#endif
@ -64,6 +64,8 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) {
const uint32_t otg_alt = GPIO_AF10_OTG1_FS;
#elif defined(STM32L0)
const uint32_t otg_alt = GPIO_AF0_USB;
#elif defined(STM32WB)
const uint32_t otg_alt = GPIO_AF10_USB;
#else
const uint32_t otg_alt = GPIO_AF10_OTG_FS;
#endif
@ -90,7 +92,7 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) {
#endif
// Enable USB FS Clocks
#if defined(STM32L0)
#if defined(STM32L0) || defined(STM32WB)
__HAL_RCC_USB_CLK_ENABLE();
#else
__USB_OTG_FS_CLK_ENABLE();
@ -111,6 +113,9 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) {
#if defined(STM32L0)
NVIC_SetPriority(USB_IRQn, IRQ_PRI_OTG_FS);
HAL_NVIC_EnableIRQ(USB_IRQn);
#elif defined(STM32WB)
NVIC_SetPriority(USB_LP_IRQn, IRQ_PRI_OTG_FS);
HAL_NVIC_EnableIRQ(USB_LP_IRQn);
#else
NVIC_SetPriority(OTG_FS_IRQn, IRQ_PRI_OTG_FS);
HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
@ -190,7 +195,7 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) {
* @retval None
*/
void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd) {
#if defined(STM32L0)
#if defined(STM32L0) || defined(STM32WB)
__HAL_RCC_USB_CLK_DISABLE();
#else
@ -354,6 +359,10 @@ void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) {
USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) {
#if MICROPY_HW_USB_FS
if (pdev->id == USB_PHY_FS_ID) {
#if defined(STM32WB)
PWR->CR2 |= PWR_CR2_USV; // USB supply is valid
#endif
// Set LL Driver parameters
pcd_fs_handle.Instance = USB_OTG_FS;
#if MICROPY_HW_USB_CDC_NUM == 2
@ -370,7 +379,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) {
pcd_fs_handle.Init.lpm_enable = DISABLE;
pcd_fs_handle.Init.battery_charging_enable = DISABLE;
#endif
#if !defined(STM32L0)
#if !defined(STM32L0) && !defined(STM32WB)
pcd_fs_handle.Init.use_dedicated_ep1 = 0;
pcd_fs_handle.Init.dma_enable = 0;
#if !defined(MICROPY_HW_USB_VBUS_DETECT_PIN)
@ -387,7 +396,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) {
// Initialize LL Driver
HAL_PCD_Init(&pcd_fs_handle);
#if defined(STM32L0)
#if defined(STM32L0) || defined(STM32WB)
// We have 512 16-bit words it total to use here (when using PCD_SNG_BUF)
HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x00, PCD_SNG_BUF, 64); // EP0
HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x80, PCD_SNG_BUF, 128); // EP0