From 9f37253c1b510f27722d8ef3358e16310470efd2 Mon Sep 17 00:00:00 2001 From: Andy Piper Date: Wed, 5 Aug 2026 20:28:57 +0100 Subject: [PATCH 01/21] RP: restore upstream RP2350 support on ArduPilot stable Upstream's RP2350 support is written against RT 8.0.0. Taking that tree wholesale would bump the kernel under every ArduPilot board, so the RP HAL and the ARMv8-M-ML-ALT core port are brought in on top of the existing RT 7.0.6 kernel instead. Nothing in either needs RT 8; what they do need is added to files the port owns - PORT_WORKING_AREA in the ALT port's chcore.h, and PORT_CORE0_BSS_SECTION / PORT_CORE1_BSS_SECTION in the ALT SMP header aliased to the existing PORT_MEM_LOCAL_COHERENT_BSSn names. ArduPilot's local patches to the replaced files are retained: chMtxForceReleaseS, PORT_IRQ_ATTRIBUTES, the CH_CFG_STACK_OVERFLOW_HOOK call sites and the 1MHz CH_CFG_ST_FREQUENCY conversions. --- os/common/ext/RP/RP2040/rp2040.h | 6110 +++++++++-------- os/common/ext/RP/RP2040/system_rp2040.h | 78 +- os/common/ext/RP/RP2350/rp2350.h | 3044 ++++++++ os/common/ext/RP/RP2350/system_rp2350.h | 39 + os/common/ports/ARMv8-M-ML-ALT/chcore.c | 240 + os/common/ports/ARMv8-M-ML-ALT/chcore.h | 1356 ++++ .../ARMv8-M-ML-ALT/compilers/GCC/chcoreasm.S | 406 ++ .../ARMv8-M-ML-ALT/compilers/GCC/mk/port.mk | 13 + .../compilers/GCC/mk/port_rp2.mk | 15 + .../ports/ARMv8-M-ML-ALT/smp/rp2/chcoresmp.c | 143 + .../ports/ARMv8-M-ML-ALT/smp/rp2/chcoresmp.h | 220 + .../ARMv8-M-ML-ALT/smp/rp2/chcoresmp_timer.h | 137 + .../ARMCMx/compilers/GCC/ld/RP2040_FLASH.ld | 123 + .../ARMCMx/compilers/GCC/ld/RP2350_FLASH.ld | 118 + .../ARMCMx/compilers/GCC/ld/RP2350_RAM.ld | 98 + .../ARMCMx/compilers/GCC/mk/startup_rp2040.mk | 12 +- .../ARMCMx/compilers/GCC/mk/startup_rp2350.mk | 23 + .../RP2040/bs2_default_padded_checksummed.S | 27 + .../startup/ARMCMx/devices/RP2350/cmparams.h | 93 + .../ARMCMx/devices/RP2350/rp2350_imagedef.S | 105 + os/hal/boards/RP_PICO2_RP2350/board.c | 110 + os/hal/boards/RP_PICO2_RP2350/board.h | 84 + os/hal/boards/RP_PICO2_RP2350/board.mk | 9 + os/hal/boards/RP_PICO_RP2040/board.c | 18 +- os/hal/include/hal_usb.h | 9 + os/hal/ports/RP/LLD/ADCv1/driver.mk | 9 + os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.c | 430 ++ os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.h | 305 + os/hal/ports/RP/LLD/DMAv1/rp_dma.c | 25 +- os/hal/ports/RP/LLD/DMAv1/rp_dma.h | 28 +- os/hal/ports/RP/LLD/EFLv1/driver.mk | 9 + os/hal/ports/RP/LLD/EFLv1/rp_efl_lld.c | 481 ++ os/hal/ports/RP/LLD/EFLv1/rp_efl_lld.h | 52 + os/hal/ports/RP/LLD/EFLv1/rp_efl_lld_api.inc | 35 + os/hal/ports/RP/LLD/GPIOv1/hal_pal_lld.c | 212 +- os/hal/ports/RP/LLD/GPIOv1/hal_pal_lld.h | 249 +- os/hal/ports/RP/LLD/I2Cv1/driver.mk | 9 + os/hal/ports/RP/LLD/I2Cv1/hal_i2c_lld.c | 573 +- os/hal/ports/RP/LLD/I2Cv1/hal_i2c_lld.h | 127 +- os/hal/ports/RP/LLD/PIOv1/driver.mk | 2 + os/hal/ports/RP/LLD/PIOv1/rp_pio.c | 577 ++ os/hal/ports/RP/LLD/PIOv1/rp_pio.h | 649 ++ os/hal/ports/RP/LLD/PWMv1/driver.mk | 9 + os/hal/ports/RP/LLD/PWMv1/hal_pwm_lld.c | 555 ++ os/hal/ports/RP/LLD/PWMv1/hal_pwm_lld.h | 478 ++ os/hal/ports/RP/LLD/RTCv1/hal_rtc_lld.c | 35 +- os/hal/ports/RP/LLD/SPIv1/driver.mk | 7 + os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.c | 16 +- os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.h | 4 +- os/hal/ports/RP/LLD/TIMERv1/hal_st_lld.c | 52 +- os/hal/ports/RP/LLD/TIMERv1/hal_st_lld.h | 67 +- os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.c | 24 +- os/hal/ports/RP/LLD/USBv1/driver.mk | 9 + os/hal/ports/RP/LLD/USBv1/hal_usb_lld.c | 911 +++ os/hal/ports/RP/LLD/USBv1/hal_usb_lld.h | 495 ++ os/hal/ports/RP/LLD/USBv1/rp_usb.h | 366 + os/hal/ports/RP/LLD/WDGv1/hal_wdg_lld.c | 29 +- os/hal/ports/RP/LLD/WDGv1/hal_wdg_lld.h | 2 +- os/hal/ports/RP/RP2040/hal_efl_lld.c | 601 ++ os/hal/ports/RP/RP2040/hal_efl_lld.h | 186 + os/hal/ports/RP/RP2040/hal_lld.c | 55 +- os/hal/ports/RP/RP2040/hal_lld.h | 133 +- os/hal/ports/RP/RP2040/platform.mk | 17 +- os/hal/ports/RP/RP2040/rp_clocks.c | 214 + os/hal/ports/RP/RP2040/rp_clocks.h | 192 + os/hal/ports/RP/RP2040/rp_isr.c | 8 +- os/hal/ports/RP/RP2040/rp_isr.h | 49 +- os/hal/ports/RP/RP2040/rp_pal_lld.h | 54 + os/hal/ports/RP/RP2040/rp_pll.c | 132 + os/hal/ports/RP/RP2040/rp_pll.h | 74 + os/hal/ports/RP/RP2040/rp_registry.h | 57 +- os/hal/ports/RP/RP2040/rp_xosc.c | 89 + os/hal/ports/RP/RP2040/rp_xosc.h | 80 + os/hal/ports/RP/RP2350/hal_efl_lld.c | 600 ++ os/hal/ports/RP/RP2350/hal_efl_lld.h | 215 + os/hal/ports/RP/RP2350/hal_lld.c | 141 + os/hal/ports/RP/RP2350/hal_lld.h | 322 + os/hal/ports/RP/RP2350/platform.mk | 52 + os/hal/ports/RP/RP2350/rp_clocks.c | 182 + os/hal/ports/RP/RP2350/rp_clocks.h | 155 + os/hal/ports/RP/RP2350/rp_fifo.h | 114 + os/hal/ports/RP/RP2350/rp_isr.c | 74 + os/hal/ports/RP/RP2350/rp_isr.h | 213 + os/hal/ports/RP/RP2350/rp_pal_lld.h | 57 + os/hal/ports/RP/RP2350/rp_pll.c | 132 + os/hal/ports/RP/RP2350/rp_pll.h | 74 + os/hal/ports/RP/RP2350/rp_registry.h | 131 + os/hal/ports/RP/RP2350/rp_xosc.c | 89 + os/hal/ports/RP/RP2350/rp_xosc.h | 79 + os/hal/ports/RP/rp_bootrom.c | 267 + os/hal/ports/RP/rp_bootrom.h | 309 + os/hal/ports/common/ARMCMx/mpu_v8m.h | 247 + 92 files changed, 21655 insertions(+), 3200 deletions(-) create mode 100644 os/common/ext/RP/RP2350/rp2350.h create mode 100644 os/common/ext/RP/RP2350/system_rp2350.h create mode 100644 os/common/ports/ARMv8-M-ML-ALT/chcore.c create mode 100644 os/common/ports/ARMv8-M-ML-ALT/chcore.h create mode 100644 os/common/ports/ARMv8-M-ML-ALT/compilers/GCC/chcoreasm.S create mode 100644 os/common/ports/ARMv8-M-ML-ALT/compilers/GCC/mk/port.mk create mode 100644 os/common/ports/ARMv8-M-ML-ALT/compilers/GCC/mk/port_rp2.mk create mode 100644 os/common/ports/ARMv8-M-ML-ALT/smp/rp2/chcoresmp.c create mode 100644 os/common/ports/ARMv8-M-ML-ALT/smp/rp2/chcoresmp.h create mode 100644 os/common/ports/ARMv8-M-ML-ALT/smp/rp2/chcoresmp_timer.h create mode 100644 os/common/startup/ARMCMx/compilers/GCC/ld/RP2040_FLASH.ld create mode 100644 os/common/startup/ARMCMx/compilers/GCC/ld/RP2350_FLASH.ld create mode 100644 os/common/startup/ARMCMx/compilers/GCC/ld/RP2350_RAM.ld create mode 100644 os/common/startup/ARMCMx/compilers/GCC/mk/startup_rp2350.mk create mode 100644 os/common/startup/ARMCMx/devices/RP2040/bs2_default_padded_checksummed.S create mode 100644 os/common/startup/ARMCMx/devices/RP2350/cmparams.h create mode 100644 os/common/startup/ARMCMx/devices/RP2350/rp2350_imagedef.S create mode 100644 os/hal/boards/RP_PICO2_RP2350/board.c create mode 100644 os/hal/boards/RP_PICO2_RP2350/board.h create mode 100644 os/hal/boards/RP_PICO2_RP2350/board.mk create mode 100644 os/hal/ports/RP/LLD/ADCv1/driver.mk create mode 100644 os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.c create mode 100644 os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.h create mode 100644 os/hal/ports/RP/LLD/EFLv1/driver.mk create mode 100644 os/hal/ports/RP/LLD/EFLv1/rp_efl_lld.c create mode 100644 os/hal/ports/RP/LLD/EFLv1/rp_efl_lld.h create mode 100644 os/hal/ports/RP/LLD/EFLv1/rp_efl_lld_api.inc create mode 100644 os/hal/ports/RP/LLD/I2Cv1/driver.mk create mode 100644 os/hal/ports/RP/LLD/PIOv1/driver.mk create mode 100644 os/hal/ports/RP/LLD/PIOv1/rp_pio.c create mode 100644 os/hal/ports/RP/LLD/PIOv1/rp_pio.h create mode 100644 os/hal/ports/RP/LLD/PWMv1/driver.mk create mode 100644 os/hal/ports/RP/LLD/PWMv1/hal_pwm_lld.c create mode 100644 os/hal/ports/RP/LLD/PWMv1/hal_pwm_lld.h create mode 100644 os/hal/ports/RP/LLD/USBv1/driver.mk create mode 100644 os/hal/ports/RP/LLD/USBv1/hal_usb_lld.c create mode 100644 os/hal/ports/RP/LLD/USBv1/hal_usb_lld.h create mode 100644 os/hal/ports/RP/LLD/USBv1/rp_usb.h create mode 100644 os/hal/ports/RP/RP2040/hal_efl_lld.c create mode 100644 os/hal/ports/RP/RP2040/hal_efl_lld.h create mode 100644 os/hal/ports/RP/RP2040/rp_clocks.c create mode 100644 os/hal/ports/RP/RP2040/rp_clocks.h create mode 100644 os/hal/ports/RP/RP2040/rp_pal_lld.h create mode 100644 os/hal/ports/RP/RP2040/rp_pll.c create mode 100644 os/hal/ports/RP/RP2040/rp_pll.h create mode 100644 os/hal/ports/RP/RP2040/rp_xosc.c create mode 100644 os/hal/ports/RP/RP2040/rp_xosc.h create mode 100644 os/hal/ports/RP/RP2350/hal_efl_lld.c create mode 100644 os/hal/ports/RP/RP2350/hal_efl_lld.h create mode 100644 os/hal/ports/RP/RP2350/hal_lld.c create mode 100644 os/hal/ports/RP/RP2350/hal_lld.h create mode 100644 os/hal/ports/RP/RP2350/platform.mk create mode 100644 os/hal/ports/RP/RP2350/rp_clocks.c create mode 100644 os/hal/ports/RP/RP2350/rp_clocks.h create mode 100644 os/hal/ports/RP/RP2350/rp_fifo.h create mode 100644 os/hal/ports/RP/RP2350/rp_isr.c create mode 100644 os/hal/ports/RP/RP2350/rp_isr.h create mode 100644 os/hal/ports/RP/RP2350/rp_pal_lld.h create mode 100644 os/hal/ports/RP/RP2350/rp_pll.c create mode 100644 os/hal/ports/RP/RP2350/rp_pll.h create mode 100644 os/hal/ports/RP/RP2350/rp_registry.h create mode 100644 os/hal/ports/RP/RP2350/rp_xosc.c create mode 100644 os/hal/ports/RP/RP2350/rp_xosc.h create mode 100644 os/hal/ports/RP/rp_bootrom.c create mode 100644 os/hal/ports/RP/rp_bootrom.h create mode 100644 os/hal/ports/common/ARMCMx/mpu_v8m.h diff --git a/os/common/ext/RP/RP2040/rp2040.h b/os/common/ext/RP/RP2040/rp2040.h index ce08e83c82..d1e967c3a0 100644 --- a/os/common/ext/RP/RP2040/rp2040.h +++ b/os/common/ext/RP/RP2040/rp2040.h @@ -1,2735 +1,3375 @@ -/* - ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file RP/rp2040.h - * @brief CMSIS device file for the RP2040. - * - * @defgroup CMSIS_RP2040 RP2040 Device File - * @ingroup CMSIS_DEVICE - * @{ - */ - -#ifndef RP2040_H -#define RP2040_H - -#include - -#define __CM0PLUS_REV 0U -#define __MPU_PRESENT 1U -#define __VTOR_PRESENT 1U -#define __NVIC_PRIO_BITS 2U -#define __Vendor_SysTickConfig 0U - -/** - * @brief Interrupt vector numbers. - */ -typedef enum { - NonMaskableInt_IRQn = -14, - HardFault_IRQn = -13, - SVC_IRQn = -5, - PendSV_IRQn = -2, - SysTick_IRQn = -1, - Vector_0n = 0, - Vector_1n = 1, - Vector_2n = 2, - Vector_3n = 3, - Vector_4n = 4, - Vector_5n = 5, - Vector_6n = 6, - Vector_7n = 7, - Vector_8n = 8, - Vector_9n = 9, - Vector_10n = 10, - Vector_11n = 11, - Vector_12n = 12, - Vector_13n = 13, - Vector_14n = 14, - Vector_15n = 15, - Vector_16n = 16, - Vector_17n = 17, - Vector_18n = 18, - Vector_19n = 19, - Vector_20n = 20, - Vector_21n = 21, - Vector_22n = 22, - Vector_23n = 23, - Vector_24n = 24, - Vector_25n = 25, - Vector_26n = 26, - Vector_27n = 27, - Vector_28n = 28, - Vector_29n = 29, - Vector_30n = 30, - Vector_31n = 31 -} IRQn_Type; - -#include "core_cm0plus.h" -#include "system_rp2040.h" - -/** - * @name Peripheral structures - * @{ - */ -typedef struct { - __IO uint32_t READ_ADDR; - __IO uint32_t WRITE_ADDR; - __IO uint32_t TRANS_COUNT; - __IO uint32_t CTRL_TRIG; - __IO uint32_t AL1_CTRL; - __IO uint32_t AL1_READ_ADDR; - __IO uint32_t AL1_WRITE_ADDR; - __IO uint32_t AL1_TRANSFER_COUNT_TRIG; - __IO uint32_t AL2_CTRL; - __IO uint32_t AL2_TRANSFER_COUNT; - __IO uint32_t AL2_READ_ADDR; - __IO uint32_t AL2_WRITE_ADDR_TRIG; - __IO uint32_t AL3_CTRL; - __IO uint32_t AL3_WRITE_ADDR; - __IO uint32_t AL3_TRANSFER_COUNT; - __IO uint32_t AL3_READ_ADDR_TRIG; -} DMA_Channel_Typedef; - -typedef struct { - __I uint32_t CTDREQ; - __I uint32_t TCR; - __I uint32_t resvd8[14]; -} DMA_Debug_Typedef; - -typedef struct { - DMA_Channel_Typedef CH[12]; - __I uint32_t resvd300[64]; - __IO uint32_t INTR; - __IO uint32_t INTE0; - __IO uint32_t INTF0; - __IO uint32_t INTS0; - __I uint32_t resvd410; - __IO uint32_t INTE1; - __IO uint32_t INTF1; - __IO uint32_t INTS1; - __IO uint32_t TIMER[4]; - __IO uint32_t MULTI_CHAN_TRIGGER; - __IO uint32_t SNIFF_CTRL; - __IO uint32_t SNIFF_DATA; - __I uint32_t resvd43C; - __I uint32_t FIFO_LEVELS; - __IO uint32_t CHAN_ABORT; - __I uint32_t N_CHANNELS; - __I uint32_t resvd44C[237]; - DMA_Debug_Typedef CH_DBG[12]; - __I uint32_t resvdB00[320]; - struct { - DMA_Channel_Typedef CH[12]; - __I uint32_t resvd300[64]; - __IO uint32_t INTR; - __IO uint32_t INTE0; - __IO uint32_t INTF0; - __IO uint32_t INTS0; - __I uint32_t resvd410; - __IO uint32_t INTE1; - __IO uint32_t INTF1; - __IO uint32_t INTS1; - __IO uint32_t TIMER[4]; - __IO uint32_t MULTI_CHAN_TRIGGER; - __IO uint32_t SNIFF_CTRL; - __IO uint32_t SNIFF_DATA; - __I uint32_t resvd43C; - __I uint32_t FIFO_LEVELS; - __IO uint32_t CHAN_ABORT; - __I uint32_t N_CHANNELS; - __I uint32_t resvd44C[237]; - DMA_Debug_Typedef CH_DBG[12]; - __I uint32_t resvdB00[320]; - } XOR; - struct { - DMA_Channel_Typedef CH[12]; - __I uint32_t resvd300[64]; - __IO uint32_t INTR; - __IO uint32_t INTE0; - __IO uint32_t INTF0; - __IO uint32_t INTS0; - __I uint32_t resvd410; - __IO uint32_t INTE1; - __IO uint32_t INTF1; - __IO uint32_t INTS1; - __IO uint32_t TIMER[4]; - __IO uint32_t MULTI_CHAN_TRIGGER; - __IO uint32_t SNIFF_CTRL; - __IO uint32_t SNIFF_DATA; - __I uint32_t resvd43C; - __I uint32_t FIFO_LEVELS; - __IO uint32_t CHAN_ABORT; - __I uint32_t N_CHANNELS; - __I uint32_t resvd44C[237]; - DMA_Debug_Typedef CH_DBG[12]; - __I uint32_t resvdB00[320]; - } SET; - struct { - DMA_Channel_Typedef CH[12]; - __I uint32_t resvd300[64]; - __IO uint32_t INTR; - __IO uint32_t INTE0; - __IO uint32_t INTF0; - __IO uint32_t INTS0; - __I uint32_t resvd410; - __IO uint32_t INTE1; - __IO uint32_t INTF1; - __IO uint32_t INTS1; - __IO uint32_t TIMER[4]; - __IO uint32_t MULTI_CHAN_TRIGGER; - __IO uint32_t SNIFF_CTRL; - __IO uint32_t SNIFF_DATA; - __I uint32_t resvd43C; - __I uint32_t FIFO_LEVELS; - __IO uint32_t CHAN_ABORT; - __I uint32_t N_CHANNELS; - __I uint32_t resvd44C[237]; - DMA_Debug_Typedef CH_DBG[12]; - __I uint32_t resvdB00[320]; - } CLR; -} DMA_TypeDef; - -typedef struct { - struct { - __I uint32_t STATUS; - __IO uint32_t CTRL; - } GPIO[30]; - __IO uint32_t INTR[4]; - struct { - __IO uint32_t INTE[4]; - __IO uint32_t INTF[4]; - __I uint32_t INTS[4]; - } PROC[2]; - __IO uint32_t DW_INTE[4]; - __IO uint32_t DW_INTF[4]; - __I uint32_t DW_INTS[4]; -} IOUSER_TypeDef; - -typedef struct { - struct { - __I uint32_t STATUS; - __IO uint32_t CTRL; - } GPIO[6]; - __IO uint32_t INTR[1]; - struct { - __IO uint32_t INTE[1]; - __IO uint32_t INTF[1]; - __I uint32_t INTS[1]; - } PROC[2]; - __IO uint32_t DW_INTE[1]; - __IO uint32_t DW_INTF[1]; - __I uint32_t DW_INTS[1]; -} IOQSPI_TypeDef; - -typedef struct { - __IO uint32_t VOLTAGE_SELECT; - __IO uint32_t GPIO[30]; - __IO uint32_t SWCLK; - __IO uint32_t SWD; -} PADS_TypeDef; - -typedef struct { - __IO uint32_t FRCE_ON; - __IO uint32_t FRCE_OFF; - __IO uint32_t WDSEL; - __IO uint32_t DONE; - __I uint32_t resvd10[1020]; - struct { - __IO uint32_t FRCE_ON; - __IO uint32_t FRCE_OFF; - __IO uint32_t WDSEL; - __IO uint32_t DONE; - __I uint32_t resvd10[1020]; - } XOR; - struct { - __IO uint32_t FRCE_ON; - __IO uint32_t FRCE_OFF; - __IO uint32_t WDSEL; - __IO uint32_t DONE; - __I uint32_t resvd10[1020]; - } SET; - struct { - __IO uint32_t FRCE_ON; - __IO uint32_t FRCE_OFF; - __IO uint32_t WDSEL; - __IO uint32_t DONE; - __I uint32_t resvd10[1020]; - } CLR; -} PSM_TypeDef; - -typedef struct { - __IO uint32_t RESET; - __IO uint32_t WDSEL; - __I uint32_t RESET_DONE; -} RESETS_TypeDef; - -typedef struct { - __I uint32_t CPUID; - __I uint32_t GPIO_IN; - __I uint32_t GPIO_HI_IN; - __I uint32_t resvdC; - __IO uint32_t GPIO_OUT; - __IO uint32_t GPIO_OUT_SET; - __IO uint32_t GPIO_OUT_CLR; - __IO uint32_t GPIO_OUT_XOR; - __IO uint32_t GPIO_OE; - __IO uint32_t GPIO_OE_SET; - __IO uint32_t GPIO_OE_CLR; - __IO uint32_t GPIO_OE_XOR; - __IO uint32_t GPIO_HI_OUT; - __IO uint32_t GPIO_HI_OUT_SET; - __IO uint32_t GPIO_HI_OUT_CLR; - __IO uint32_t GPIO_HI_OUT_XOR; - __IO uint32_t GPIO_HI_OE; - __IO uint32_t GPIO_HI_OE_SET; - __IO uint32_t GPIO_HI_OE_CLR; - __IO uint32_t GPIO_HI_OE_XOR; - __IO uint32_t FIFO_ST; - __IO uint32_t FIFO_WR; - __I uint32_t FIFO_RD; - __IO uint32_t SPINLOCK_ST; - __IO uint32_t DIV_UDIVIDEND; - __IO uint32_t DIV_UDIVISOR; - __IO uint32_t DIV_SDIVIDEND; - __IO uint32_t DIV_SDIVISOR; - __IO uint32_t DIV_QUOTIENT; - __IO uint32_t DIV_REMAINDER; - __I uint32_t DIV_CSR; - __I uint32_t resvd7C; - struct { - __IO uint32_t ACCUM0; - __IO uint32_t ACCUM1; - __IO uint32_t BASE0; - __IO uint32_t BASE1; - __IO uint32_t BASE2; - __I uint32_t POP_LANE0; - __I uint32_t POP_LANE1; - __I uint32_t POP_FULL; - __I uint32_t PEEK_LANE0; - __I uint32_t PEEK_LANE1; - __I uint32_t PEEK_FULL; - __IO uint32_t CTRL_LANE0; - __IO uint32_t CTRL_LANE1; - __IO uint32_t ACCUM0_ADD; - __IO uint32_t ACCUM1_ADD; - __IO uint32_t BASE_1AND0; - } INTERP[2]; - __IO uint32_t SPINLOCK[32]; /* NUM_SPIN_LOCKS */ -} SIO_TypeDef; - -typedef struct { - __IO uint32_t SSPCR0; - __IO uint32_t SSPCR1; - __IO uint32_t SSPDR; - __I uint32_t SSPSR; - __IO uint32_t SSPCPSR; - __IO uint32_t SSPIMSC; - __I uint32_t SSPRIS; - __I uint32_t SSPMIS; - __IO uint32_t SSPICR; - __IO uint32_t SSPDMACR; - __I uint32_t resvd28[1006]; - __I uint32_t SSPPERIPHID0; - __I uint32_t SSPPERIPHID1; - __I uint32_t SSPPERIPHID2; - __I uint32_t SSPPERIPHID3; - __I uint32_t SSPPCELLID0; - __I uint32_t SSPPCELLID1; - __I uint32_t SSPPCELLID2; - __I uint32_t SSPPCELLID3; - struct { - __IO uint32_t SSPCR0; - __IO uint32_t SSPCR1; - __IO uint32_t SSPDR; - __I uint32_t SSPSR; - __IO uint32_t SSPCPSR; - __IO uint32_t SSPIMSC; - __I uint32_t SSPRIS; - __I uint32_t SSPMIS; - __IO uint32_t SSPICR; - __IO uint32_t SSPDMACR; - __I uint32_t resvd28[1006]; - __I uint32_t SSPPERIPHID0; - __I uint32_t SSPPERIPHID1; - __I uint32_t SSPPERIPHID2; - __I uint32_t SSPPERIPHID3; - __I uint32_t SSPPCELLID0; - __I uint32_t SSPPCELLID1; - __I uint32_t SSPPCELLID2; - __I uint32_t SSPPCELLID3; - } XOR; - struct { - __IO uint32_t SSPCR0; - __IO uint32_t SSPCR1; - __IO uint32_t SSPDR; - __I uint32_t SSPSR; - __IO uint32_t SSPCPSR; - __IO uint32_t SSPIMSC; - __I uint32_t SSPRIS; - __I uint32_t SSPMIS; - __IO uint32_t SSPICR; - __IO uint32_t SSPDMACR; - __I uint32_t resvd28[1006]; - __I uint32_t SSPPERIPHID0; - __I uint32_t SSPPERIPHID1; - __I uint32_t SSPPERIPHID2; - __I uint32_t SSPPERIPHID3; - __I uint32_t SSPPCELLID0; - __I uint32_t SSPPCELLID1; - __I uint32_t SSPPCELLID2; - __I uint32_t SSPPCELLID3; - } SET; - struct { - __IO uint32_t SSPCR0; - __IO uint32_t SSPCR1; - __IO uint32_t SSPDR; - __I uint32_t SSPSR; - __IO uint32_t SSPCPSR; - __IO uint32_t SSPIMSC; - __I uint32_t SSPRIS; - __I uint32_t SSPMIS; - __IO uint32_t SSPICR; - __IO uint32_t SSPDMACR; - __I uint32_t resvd28[1006]; - __I uint32_t SSPPERIPHID0; - __I uint32_t SSPPERIPHID1; - __I uint32_t SSPPERIPHID2; - __I uint32_t SSPPERIPHID3; - __I uint32_t SSPPCELLID0; - __I uint32_t SSPPCELLID1; - __I uint32_t SSPPCELLID2; - __I uint32_t SSPPCELLID3; - } CLR; -} SPI_TypeDef; - -typedef struct { - __IO uint32_t TIMEHW; - __IO uint32_t TIMELW; - __I uint32_t TIMEHR; - __I uint32_t TIMELR; - __IO uint32_t ALARM[4]; /* NUM_TIMERS */ - __IO uint32_t ARMED; - __I uint32_t TIMERAWH; - __I uint32_t TIMERAWL; - __IO uint32_t DBGPAUSE; - __IO uint32_t PAUSE; - __IO uint32_t INTR; - __IO uint32_t INTE; - __IO uint32_t INTF; - __I uint32_t INTS; - __I uint32_t resvd44[1007]; - struct { - __IO uint32_t TIMEHW; - __IO uint32_t TIMELW; - __I uint32_t TIMEHR; - __I uint32_t TIMELR; - __IO uint32_t ALARM[4]; /* NUM_TIMERS */ - __IO uint32_t ARMED; - __I uint32_t TIMERAWH; - __I uint32_t TIMERAWL; - __IO uint32_t DBGPAUSE; - __IO uint32_t PAUSE; - __IO uint32_t INTR; - __IO uint32_t INTE; - __IO uint32_t INTF; - __I uint32_t INTS; - __I uint32_t resvd44[1007]; - } XOR; - struct { - __IO uint32_t TIMEHW; - __IO uint32_t TIMELW; - __I uint32_t TIMEHR; - __I uint32_t TIMELR; - __IO uint32_t ALARM[4]; /* NUM_TIMERS */ - __IO uint32_t ARMED; - __I uint32_t TIMERAWH; - __I uint32_t TIMERAWL; - __IO uint32_t DBGPAUSE; - __IO uint32_t PAUSE; - __IO uint32_t INTR; - __IO uint32_t INTE; - __IO uint32_t INTF; - __I uint32_t INTS; - __I uint32_t resvd44[1007]; - } SET; - struct { - __IO uint32_t TIMEHW; - __IO uint32_t TIMELW; - __I uint32_t TIMEHR; - __I uint32_t TIMELR; - __IO uint32_t ALARM[4]; /* NUM_TIMERS */ - __IO uint32_t ARMED; - __I uint32_t TIMERAWH; - __I uint32_t TIMERAWL; - __IO uint32_t DBGPAUSE; - __IO uint32_t PAUSE; - __IO uint32_t INTR; - __IO uint32_t INTE; - __IO uint32_t INTF; - __I uint32_t INTS; - __I uint32_t resvd44[1007]; - } CLR; -} TIMER_TypeDef; - -typedef struct { - __IO uint32_t UARTDR; - __IO uint32_t UARTRSR; - __I uint32_t resvd8; - __I uint32_t resvdC; - __I uint32_t resvd10; - __I uint32_t resvd14; - __I uint32_t UARTFR; - __I uint32_t resvd1C; - __IO uint32_t UARTILPR; - __IO uint32_t UARTIBRD; - __IO uint32_t UARTFBRD; - __IO uint32_t UARTLCR_H; - __IO uint32_t UARTCR; - __IO uint32_t UARTIFLS; - __IO uint32_t UARTIMSC; - __I uint32_t UARTRIS; - __I uint32_t UARTMIS; - __IO uint32_t UARTICR; - __IO uint32_t UARTDMACR; - __I uint32_t resvd4C[997]; - __I uint32_t UARTPERIPHID0; - __I uint32_t UARTPERIPHID1; - __I uint32_t UARTPERIPHID2; - __I uint32_t UARTPERIPHID3; - __I uint32_t UARTPCELLID0; - __I uint32_t UARTPCELLID1; - __I uint32_t UARTPCELLID2; - __I uint32_t UARTPCELLID3; - struct { - __IO uint32_t UARTDR; - __IO uint32_t UARTRSR; - __I uint32_t resvd8; - __I uint32_t resvdC; - __I uint32_t resvd10; - __I uint32_t resvd14; - __I uint32_t UARTFR; - __I uint32_t resvd1C; - __IO uint32_t UARTILPR; - __IO uint32_t UARTIBRD; - __IO uint32_t UARTFBRD; - __IO uint32_t UARTLCR_H; - __IO uint32_t UARTCR; - __IO uint32_t UARTIFLS; - __IO uint32_t UARTIMSC; - __I uint32_t UARTRIS; - __I uint32_t UARTMIS; - __IO uint32_t UARTICR; - __IO uint32_t UARTDMACR; - __I uint32_t resvd4C[997]; - __I uint32_t UARTPERIPHID0; - __I uint32_t UARTPERIPHID1; - __I uint32_t UARTPERIPHID2; - __I uint32_t UARTPERIPHID3; - __I uint32_t UARTPCELLID0; - __I uint32_t UARTPCELLID1; - __I uint32_t UARTPCELLID2; - __I uint32_t UARTPCELLID3; - } XOR; - struct { - __IO uint32_t UARTDR; - __IO uint32_t UARTRSR; - __I uint32_t resvd8; - __I uint32_t resvdC; - __I uint32_t resvd10; - __I uint32_t resvd14; - __I uint32_t UARTFR; - __I uint32_t resvd1C; - __IO uint32_t UARTILPR; - __IO uint32_t UARTIBRD; - __IO uint32_t UARTFBRD; - __IO uint32_t UARTLCR_H; - __IO uint32_t UARTCR; - __IO uint32_t UARTIFLS; - __IO uint32_t UARTIMSC; - __I uint32_t UARTRIS; - __I uint32_t UARTMIS; - __IO uint32_t UARTICR; - __IO uint32_t UARTDMACR; - __I uint32_t resvd4C[997]; - __I uint32_t UARTPERIPHID0; - __I uint32_t UARTPERIPHID1; - __I uint32_t UARTPERIPHID2; - __I uint32_t UARTPERIPHID3; - __I uint32_t UARTPCELLID0; - __I uint32_t UARTPCELLID1; - __I uint32_t UARTPCELLID2; - __I uint32_t UARTPCELLID3; - } SET; - struct { - __IO uint32_t UARTDR; - __IO uint32_t UARTRSR; - __I uint32_t resvd8; - __I uint32_t resvdC; - __I uint32_t resvd10; - __I uint32_t resvd14; - __I uint32_t UARTFR; - __I uint32_t resvd1C; - __IO uint32_t UARTILPR; - __IO uint32_t UARTIBRD; - __IO uint32_t UARTFBRD; - __IO uint32_t UARTLCR_H; - __IO uint32_t UARTCR; - __IO uint32_t UARTIFLS; - __IO uint32_t UARTIMSC; - __I uint32_t UARTRIS; - __I uint32_t UARTMIS; - __IO uint32_t UARTICR; - __IO uint32_t UARTDMACR; - __I uint32_t resvd4C[997]; - __I uint32_t UARTPERIPHID0; - __I uint32_t UARTPERIPHID1; - __I uint32_t UARTPERIPHID2; - __I uint32_t UARTPERIPHID3; - __I uint32_t UARTPCELLID0; - __I uint32_t UARTPCELLID1; - __I uint32_t UARTPCELLID2; - __I uint32_t UARTPCELLID3; - } CLR; -} UART_TypeDef; - -typedef struct { - __IO uint32_t CLKDIVM1; - __IO uint32_t SETUP0; - __IO uint32_t SETUP1; - __IO uint32_t CTRL; - __IO uint32_t IRQSETUP0; - __IO uint32_t IRQSETUP1; - __IO uint32_t RTC1; - __IO uint32_t RTC0; - __IO uint32_t INTR; - __IO uint32_t INTE; - __IO uint32_t INTF; - __IO uint32_t INTS; - __I uint32_t resvd30[1012]; - struct { - __IO uint32_t CLKDIVM1; - __IO uint32_t SETUP0; - __IO uint32_t SETUP1; - __IO uint32_t CTRL; - __IO uint32_t IRQSETUP0; - __IO uint32_t IRQSETUP1; - __IO uint32_t RTC1; - __IO uint32_t RTC0; - __IO uint32_t INTR; - __IO uint32_t INTE; - __IO uint32_t INTF; - __IO uint32_t INTS; - __I uint32_t resvd30[1012]; - } XOR; - struct { - __IO uint32_t CLKDIVM1; - __IO uint32_t SETUP0; - __IO uint32_t SETUP1; - __IO uint32_t CTRL; - __IO uint32_t IRQSETUP0; - __IO uint32_t IRQSETUP1; - __IO uint32_t RTC1; - __IO uint32_t RTC0; - __IO uint32_t INTR; - __IO uint32_t INTE; - __IO uint32_t INTF; - __IO uint32_t INTS; - __I uint32_t resvd30[1012]; - } SET; - struct { - __IO uint32_t CLKDIVM1; - __IO uint32_t SETUP0; - __IO uint32_t SETUP1; - __IO uint32_t CTRL; - __IO uint32_t IRQSETUP0; - __IO uint32_t IRQSETUP1; - __IO uint32_t RTC1; - __IO uint32_t RTC0; - __IO uint32_t INTR; - __IO uint32_t INTE; - __IO uint32_t INTF; - __IO uint32_t INTS; - __I uint32_t resvd30[1012]; - } CLR; -} RTC_TypeDef; - -typedef struct { - __IO uint32_t CON; - __IO uint32_t TAR; - __IO uint32_t SAR; - __I uint32_t resvdC; - __IO uint32_t DATACMD; - __IO uint32_t SSSCLHCNT; - __IO uint32_t SSSCLLCNT; - __IO uint32_t FSSCLHCNT; - __IO uint32_t FSSCLLCNT; - __I uint32_t resvd24[2]; - __IO uint32_t INTRSTAT; - __IO uint32_t INTRMASK; - __IO uint32_t RAWINTRSTAT; - __IO uint32_t RXTL; - __IO uint32_t TXTL; - __IO uint32_t CLRINTR; - __IO uint32_t CLRRXUNDER; - __IO uint32_t CLRRXOVER; - __IO uint32_t CLRTXOVER; - __IO uint32_t CLRRDREQ; - __IO uint32_t CLRTXABRT; - __IO uint32_t CLRRXDONE; - __IO uint32_t CLRACTIVITY; - __IO uint32_t CLRSTOPDET; - __IO uint32_t CLRSTARTDET; - __IO uint32_t CLRGENCALL; - __IO uint32_t ENABLE; - __IO uint32_t STATUS; - __IO uint32_t TXFLR; - __IO uint32_t RXFLR; - __IO uint32_t SDAHOLD; - __IO uint32_t TXABRTSOURCE; - __IO uint32_t SLVDATANACKONLY; - __IO uint32_t DMACR; - __IO uint32_t DMATDLR; - __IO uint32_t DMARDLR; - __IO uint32_t SDASETUP; - __IO uint32_t ACKGENERALCALL; - __IO uint32_t ENABLESTATUS; - __IO uint32_t FSSPKLEN; - __I uint32_t resvdA4; - __IO uint32_t CLRRESTARTDET; - __I uint32_t resvdac[981]; - struct { - __IO uint32_t CON; - __IO uint32_t TAR; - __IO uint32_t SAR; - __I uint32_t resvdC; - __IO uint32_t DATACMD; - __IO uint32_t SSSCLHCNT; - __IO uint32_t SSSCLLCNT; - __IO uint32_t FSSCLHCNT; - __IO uint32_t FSSCLLCNT; - __I uint32_t resvd24[2]; - __IO uint32_t INTRSTAT; - __IO uint32_t INTRMASK; - __IO uint32_t RAWINTRSTAT; - __IO uint32_t RXTL; - __IO uint32_t TXTL; - __IO uint32_t CLRINTR; - __IO uint32_t CLRRXUNDER; - __IO uint32_t CLRRXOVER; - __IO uint32_t CLRTXOVER; - __IO uint32_t CLRRDREQ; - __IO uint32_t CLRTXABRT; - __IO uint32_t CLRRXDONE; - __IO uint32_t CLRACTIVITY; - __IO uint32_t CLRSTOPDET; - __IO uint32_t CLRSTARTDET; - __IO uint32_t CLRGENCALL; - __IO uint32_t ENABLE; - __IO uint32_t STATUS; - __IO uint32_t TXFLR; - __IO uint32_t RXFLR; - __IO uint32_t SDAHOLD; - __IO uint32_t TXABRTSOURCE; - __IO uint32_t SLVDATANACKONLY; - __IO uint32_t DMACR; - __IO uint32_t DMATDLR; - __IO uint32_t DMARDLR; - __IO uint32_t SDASETUP; - __IO uint32_t ACKGENERALCALL; - __IO uint32_t ENABLESTATUS; - __IO uint32_t FSSPKLEN; - __I uint32_t resvdA4; - __IO uint32_t CLRRESTARTDET; - __I uint32_t resvdac[981]; - } XOR; - struct { - __IO uint32_t CON; - __IO uint32_t TAR; - __IO uint32_t SAR; - __I uint32_t resvdC; - __IO uint32_t DATACMD; - __IO uint32_t SSSCLHCNT; - __IO uint32_t SSSCLLCNT; - __IO uint32_t FSSCLHCNT; - __IO uint32_t FSSCLLCNT; - __I uint32_t resvd24[2]; - __IO uint32_t INTRSTAT; - __IO uint32_t INTRMASK; - __IO uint32_t RAWINTRSTAT; - __IO uint32_t RXTL; - __IO uint32_t TXTL; - __IO uint32_t CLRINTR; - __IO uint32_t CLRRXUNDER; - __IO uint32_t CLRRXOVER; - __IO uint32_t CLRTXOVER; - __IO uint32_t CLRRDREQ; - __IO uint32_t CLRTXABRT; - __IO uint32_t CLRRXDONE; - __IO uint32_t CLRACTIVITY; - __IO uint32_t CLRSTOPDET; - __IO uint32_t CLRSTARTDET; - __IO uint32_t CLRGENCALL; - __IO uint32_t ENABLE; - __IO uint32_t STATUS; - __IO uint32_t TXFLR; - __IO uint32_t RXFLR; - __IO uint32_t SDAHOLD; - __IO uint32_t TXABRTSOURCE; - __IO uint32_t SLVDATANACKONLY; - __IO uint32_t DMACR; - __IO uint32_t DMATDLR; - __IO uint32_t DMARDLR; - __IO uint32_t SDASETUP; - __IO uint32_t ACKGENERALCALL; - __IO uint32_t ENABLESTATUS; - __IO uint32_t FSSPKLEN; - __I uint32_t resvdA4; - __IO uint32_t CLRRESTARTDET; - __I uint32_t resvdac[981]; - } SET; - struct { - __IO uint32_t CON; - __IO uint32_t TAR; - __IO uint32_t SAR; - __I uint32_t resvdC; - __IO uint32_t DATACMD; - __IO uint32_t SSSCLHCNT; - __IO uint32_t SSSCLLCNT; - __IO uint32_t FSSCLHCNT; - __IO uint32_t FSSCLLCNT; - __I uint32_t resvd24[2]; - __IO uint32_t INTRSTAT; - __IO uint32_t INTRMASK; - __IO uint32_t RAWINTRSTAT; - __IO uint32_t RXTL; - __IO uint32_t TXTL; - __IO uint32_t CLRINTR; - __IO uint32_t CLRRXUNDER; - __IO uint32_t CLRRXOVER; - __IO uint32_t CLRTXOVER; - __IO uint32_t CLRRDREQ; - __IO uint32_t CLRTXABRT; - __IO uint32_t CLRRXDONE; - __IO uint32_t CLRACTIVITY; - __IO uint32_t CLRSTOPDET; - __IO uint32_t CLRSTARTDET; - __IO uint32_t CLRGENCALL; - __IO uint32_t ENABLE; - __IO uint32_t STATUS; - __IO uint32_t TXFLR; - __IO uint32_t RXFLR; - __IO uint32_t SDAHOLD; - __IO uint32_t TXABRTSOURCE; - __IO uint32_t SLVDATANACKONLY; - __IO uint32_t DMACR; - __IO uint32_t DMATDLR; - __IO uint32_t DMARDLR; - __IO uint32_t SDASETUP; - __IO uint32_t ACKGENERALCALL; - __IO uint32_t ENABLESTATUS; - __IO uint32_t FSSPKLEN; - __I uint32_t resvdA4; - __IO uint32_t CLRRESTARTDET; - __I uint32_t resvdac[981]; - } CLR; -} I2C_TypeDef; - -typedef struct { - __IO uint32_t CS; - __IO uint32_t RESULT; - __IO uint32_t FCS; - __IO uint32_t FIFO; - __IO uint32_t DIV; - __IO uint32_t INTR; - __IO uint32_t INTE; - __IO uint32_t INTF; - __IO uint32_t INTS; - __I uint32_t resvd24[1015]; -struct { - __IO uint32_t CS; - __IO uint32_t RESULT; - __IO uint32_t FCS; - __IO uint32_t FIFO; - __IO uint32_t DIV; - __IO uint32_t INTR; - __IO uint32_t INTE; - __IO uint32_t INTF; - __IO uint32_t INTS; - __I uint32_t resvd24[1015]; - } XOR; -struct { - __IO uint32_t CS; - __IO uint32_t RESULT; - __IO uint32_t FCS; - __IO uint32_t FIFO; - __IO uint32_t DIV; - __IO uint32_t INTR; - __IO uint32_t INTE; - __IO uint32_t INTF; - __IO uint32_t INTS; - __I uint32_t resvd24[1015]; - } SET; -struct { - __IO uint32_t CS; - __IO uint32_t RESULT; - __IO uint32_t FCS; - __IO uint32_t FIFO; - __IO uint32_t DIV; - __IO uint32_t INTR; - __IO uint32_t INTE; - __IO uint32_t INTF; - __IO uint32_t INTS; - __I uint32_t resvd24[1015]; - } CLR; -} ADC_TypeDef; - -typedef struct { - struct { - __IO uint32_t CSR; - __IO uint32_t DIV; - __IO uint32_t CTR; - __IO uint32_t CC; - __IO uint32_t TOP; - } CH[8]; - __IO uint32_t EN; - __IO uint32_t INTR; - __IO uint32_t INTE; - __IO uint32_t INTF; - __I uint32_t INTS; - __I uint32_t resvdpwm[979]; - struct { - struct { - __IO uint32_t CSR; - __IO uint32_t DIV; - __IO uint32_t CTR; - __IO uint32_t CC; - __IO uint32_t TOP; - } CH[8]; - __IO uint32_t EN; - __IO uint32_t INTR; - __IO uint32_t INTE; - __IO uint32_t INTF; - __I uint32_t INTS; - __I uint32_t resvdpwm[979]; - } XOR; - struct { - struct { - __IO uint32_t CSR; - __IO uint32_t DIV; - __IO uint32_t CTR; - __IO uint32_t CC; - __IO uint32_t TOP; - } CH[8]; - __IO uint32_t EN; - __IO uint32_t INTR; - __IO uint32_t INTE; - __IO uint32_t INTF; - __I uint32_t INTS; - __I uint32_t resvdpwm[979]; - } SET; - struct { - struct { - __IO uint32_t CSR; - __IO uint32_t DIV; - __IO uint32_t CTR; - __IO uint32_t CC; - __IO uint32_t TOP; - } CH[8]; - __IO uint32_t EN; - __IO uint32_t INTR; - __IO uint32_t INTE; - __IO uint32_t INTF; - __I uint32_t INTS; - __I uint32_t resvdpwm[979]; - } CLR; -} PWM_TypeDef; - -typedef struct { - __IO uint32_t DEVADDRCTRL; - __IO uint32_t INTEPADDRCTRL[15]; /* USB_HOST_INTERRUPT_ENDPOINTS */ - __IO uint32_t MAINCTRL; - __IO uint32_t SOFRW; - __I uint32_t SOFRD; - __IO uint32_t SIECTRL; - __IO uint32_t SIESTATUS; - __IO uint32_t INTEPCTRL; - __IO uint32_t BUFSTATUS; - __IO uint32_t BUFCPUSHOULDHANDLE; - __IO uint32_t ABORT; - __IO uint32_t ABORTDONE; - __IO uint32_t EPSTALLARM; - __IO uint32_t NAKPOLL; - __IO uint32_t EPNAKSTALLSTATUS; - __IO uint32_t MUXING; - __IO uint32_t PWR; - __IO uint32_t PHYDIRECT; - __IO uint32_t PHYDIRECTOVERRIDE; - __IO uint32_t PHYTRIM; - __IO uint32_t LINESTATETUNING; - __IO uint32_t INTR; - __IO uint32_t INTE; - __IO uint32_t INTF; - __IO uint32_t INTS; - __I uint32_t resvd9c[985]; - struct { - __IO uint32_t DEVADDRCTRL; - __IO uint32_t INTEPADDRCTRL[15]; /* USB_HOST_INTERRUPT_ENDPOINTS */ - __IO uint32_t MAINCTRL; - __IO uint32_t SOFRW; - __I uint32_t SOFRD; - __IO uint32_t SIECTRL; - __IO uint32_t SIESTATUS; - __IO uint32_t INTEPCTRL; - __IO uint32_t BUFSTATUS; - __IO uint32_t BUFCPUSHOULDHANDLE; - __IO uint32_t ABORT; - __IO uint32_t ABORTDONE; - __IO uint32_t EPSTALLARM; - __IO uint32_t NAKPOLL; - __IO uint32_t EPNAKSTALLSTATUS; - __IO uint32_t MUXING; - __IO uint32_t PWR; - __IO uint32_t PHYDIRECT; - __IO uint32_t PHYDIRECTOVERRIDE; - __IO uint32_t PHYTRIM; - __IO uint32_t LINESTATETUNING; - __IO uint32_t INTR; - __IO uint32_t INTE; - __IO uint32_t INTF; - __IO uint32_t INTS; - __I uint32_t resvd9c[985]; - } XOR; - struct { - __IO uint32_t DEVADDRCTRL; - __IO uint32_t INTEPADDRCTRL[15]; /* USB_HOST_INTERRUPT_ENDPOINTS */ - __IO uint32_t MAINCTRL; - __IO uint32_t SOFRW; - __I uint32_t SOFRD; - __IO uint32_t SIECTRL; - __IO uint32_t SIESTATUS; - __IO uint32_t INTEPCTRL; - __IO uint32_t BUFSTATUS; - __IO uint32_t BUFCPUSHOULDHANDLE; - __IO uint32_t ABORT; - __IO uint32_t ABORTDONE; - __IO uint32_t EPSTALLARM; - __IO uint32_t NAKPOLL; - __IO uint32_t EPNAKSTALLSTATUS; - __IO uint32_t MUXING; - __IO uint32_t PWR; - __IO uint32_t PHYDIRECT; - __IO uint32_t PHYDIRECTOVERRIDE; - __IO uint32_t PHYTRIM; - __IO uint32_t LINESTATETUNING; - __IO uint32_t INTR; - __IO uint32_t INTE; - __IO uint32_t INTF; - __IO uint32_t INTS; - __I uint32_t resvd9c[985]; - } SET; - struct { - __IO uint32_t DEVADDRCTRL; - __IO uint32_t INTEPADDRCTRL[15]; /* USB_HOST_INTERRUPT_ENDPOINTS */ - __IO uint32_t MAINCTRL; - __IO uint32_t SOFRW; - __I uint32_t SOFRD; - __IO uint32_t SIECTRL; - __IO uint32_t SIESTATUS; - __IO uint32_t INTEPCTRL; - __IO uint32_t BUFSTATUS; - __IO uint32_t BUFCPUSHOULDHANDLE; - __IO uint32_t ABORT; - __IO uint32_t ABORTDONE; - __IO uint32_t EPSTALLARM; - __IO uint32_t NAKPOLL; - __IO uint32_t EPNAKSTALLSTATUS; - __IO uint32_t MUXING; - __IO uint32_t PWR; - __IO uint32_t PHYDIRECT; - __IO uint32_t PHYDIRECTOVERRIDE; - __IO uint32_t PHYTRIM; - __IO uint32_t LINESTATETUNING; - __IO uint32_t INTR; - __IO uint32_t INTE; - __IO uint32_t INTF; - __IO uint32_t INTS; - __I uint32_t resvd9c[985]; - } CLR; -} USB_TypeDef; - -typedef struct { - __IO uint32_t CTRL; - __O uint32_t LOAD; - __I uint32_t REASON; - __IO uint32_t SCRATCH[8]; - __IO uint32_t TICK; - __I uint32_t resvd30[1012]; - struct { - __IO uint32_t CTRL; - __O uint32_t LOAD; - __I uint32_t REASON; - __IO uint32_t SCRATCH[8]; - __IO uint32_t TICK; - __I uint32_t resvd30[1012]; - } XOR; - struct { - __IO uint32_t CTRL; - __O uint32_t LOAD; - __I uint32_t REASON; - __IO uint32_t SCRATCH[8]; - __IO uint32_t TICK; - __I uint32_t resvd30[1012]; - } SET; - struct { - __IO uint32_t CTRL; - __O uint32_t LOAD; - __I uint32_t REASON; - __IO uint32_t SCRATCH[8]; - __IO uint32_t TICK; - __I uint32_t resvd30[1012]; - } CLR; -} WATCHDOG_TypeDef; - -typedef struct { - __IO uint32_t CTRL; - __I uint32_t FSTAT; - __IO uint32_t FDEBUG; - __I uint32_t FLEVEL; - __O uint32_t TXF[4]; /* NUM_PIO_STATE_MACHINES */ - __I uint32_t RXF[4]; /* NUM_PIO_STATE_MACHINES */ - __IO uint32_t IRQ; - __O uint32_t IRQFORCE; - __IO uint32_t INPUTSYNCBYPASS; - __IO uint32_t DBGPADOUT; - __IO uint32_t DBGPADOE; - __IO uint32_t DBGCFGINFO; - __O uint32_t INSTRMEM[32]; - struct { - __IO uint32_t CLKDIV; - __IO uint32_t EXECCTRL; - __IO uint32_t SHIFTCTRL; - __I uint32_t ADDR; - __IO uint32_t INSTR; - __IO uint32_t PINCTRL; - } SM[4]; /* NUM_PIO_STATE_MACHINES */ - __IO uint32_t INTR; - __IO uint32_t INTE0; - __IO uint32_t INTF0; - __I uint32_t INTS0; - __IO uint32_t INTE1; - __IO uint32_t INTF1; - __I uint32_t INTS1; - __I uint32_t resvd144[943]; - struct { - __IO uint32_t CTRL; - __I uint32_t FSTAT; - __IO uint32_t FDEBUG; - __I uint32_t FLEVEL; - __O uint32_t TXF[4]; /* NUM_PIO_STATE_MACHINES */ - __I uint32_t RXF[4]; /* NUM_PIO_STATE_MACHINES */ - __IO uint32_t IRQ; - __O uint32_t IRQFORCE; - __IO uint32_t INPUTSYNCBYPASS; - __IO uint32_t DBGPADOUT; - __IO uint32_t DBGPADOE; - __IO uint32_t DBGCFGINFO; - __O uint32_t INSTRMEM[32]; - struct { - __IO uint32_t CLKDIV; - __IO uint32_t EXECCTRL; - __IO uint32_t SHIFTCTRL; - __I uint32_t ADDR; - __IO uint32_t INSTR; - __IO uint32_t PINCTRL; - } SM[4]; /* NUM_PIO_STATE_MACHINES */ - __IO uint32_t INTR; - __IO uint32_t INTE0; - __IO uint32_t INTF0; - __I uint32_t INTS0; - __IO uint32_t INTE1; - __IO uint32_t INTF1; - __I uint32_t INTS1; - __I uint32_t resvd144[943]; - } XOR; - struct { - __IO uint32_t CTRL; - __I uint32_t FSTAT; - __IO uint32_t FDEBUG; - __I uint32_t FLEVEL; - __O uint32_t TXF[4]; /* NUM_PIO_STATE_MACHINES */ - __I uint32_t RXF[4]; /* NUM_PIO_STATE_MACHINES */ - __IO uint32_t IRQ; - __O uint32_t IRQFORCE; - __IO uint32_t INPUTSYNCBYPASS; - __IO uint32_t DBGPADOUT; - __IO uint32_t DBGPADOE; - __IO uint32_t DBGCFGINFO; - __O uint32_t INSTRMEM[32]; - struct { - __IO uint32_t CLKDIV; - __IO uint32_t EXECCTRL; - __IO uint32_t SHIFTCTRL; - __I uint32_t ADDR; - __IO uint32_t INSTR; - __IO uint32_t PINCTRL; - } SM[4]; /* NUM_PIO_STATE_MACHINES */ - __IO uint32_t INTR; - __IO uint32_t INTE0; - __IO uint32_t INTF0; - __I uint32_t INTS0; - __IO uint32_t INTE1; - __IO uint32_t INTF1; - __I uint32_t INTS1; - __I uint32_t resvd144[943]; - } SET; - struct { - __IO uint32_t CTRL; - __I uint32_t FSTAT; - __IO uint32_t FDEBUG; - __I uint32_t FLEVEL; - __O uint32_t TXF[4]; /* NUM_PIO_STATE_MACHINES */ - __I uint32_t RXF[4]; /* NUM_PIO_STATE_MACHINES */ - __IO uint32_t IRQ; - __O uint32_t IRQFORCE; - __IO uint32_t INPUTSYNCBYPASS; - __IO uint32_t DBGPADOUT; - __IO uint32_t DBGPADOE; - __IO uint32_t DBGCFGINFO; - __O uint32_t INSTRMEM[32]; - struct { - __IO uint32_t CLKDIV; - __IO uint32_t EXECCTRL; - __IO uint32_t SHIFTCTRL; - __I uint32_t ADDR; - __IO uint32_t INSTR; - __IO uint32_t PINCTRL; - } SM[4]; /* NUM_PIO_STATE_MACHINES */ - __IO uint32_t INTR; - __IO uint32_t INTE0; - __IO uint32_t INTF0; - __I uint32_t INTS0; - __IO uint32_t INTE1; - __IO uint32_t INTF1; - __I uint32_t INTS1; - __I uint32_t resvd144[943]; - } CLR; -} PIO_TypeDef; -/** @} */ - -/** - * @name Base addresses - * @{ - */ -#define __APBPERIPH_BASE 0x40000000U -#define __AHBPERIPH_BASE 0x50000000U -#define __IOPORT_BASE 0xD0000000U - -#define __RESETS_BASE (__APBPERIPH_BASE + 0x0000C000U) -#define __IOUSER0_BASE (__APBPERIPH_BASE + 0x00014000U) -#define __IOQSPI_BASE (__APBPERIPH_BASE + 0x00018000U) -#define __PADSUSER0_BASE (__APBPERIPH_BASE + 0x0001C000U) -#define __PADSQSPI_BASE (__APBPERIPH_BASE + 0x00020000U) -#define __PSM_BASE (__APBPERIPH_BASE + 0x00010000U) -#define __TIMER_BASE (__APBPERIPH_BASE + 0x00054000U) -#define __UART0_BASE (__APBPERIPH_BASE + 0x00034000U) -#define __UART1_BASE (__APBPERIPH_BASE + 0x00038000U) -#define __SPI0_BASE (__APBPERIPH_BASE + 0x0003C000U) -#define __SPI1_BASE (__APBPERIPH_BASE + 0x00040000U) -#define __I2C0_BASE (__APBPERIPH_BASE + 0x00044000U) -#define __I2C1_BASE (__APBPERIPH_BASE + 0x00048000U) -#define __ADC_BASE (__APBPERIPH_BASE + 0x0004C000U) -#define __PWM_BASE (__APBPERIPH_BASE + 0x00050000U) -#define __WATCHDOG_BASE (__APBPERIPH_BASE + 0x00058000U) -#define __RTC_BASE (__APBPERIPH_BASE + 0x0005C000U) - -#define __DMA_BASE (__AHBPERIPH_BASE + 0x00000000U) -#define __USB_BASE (__AHBPERIPH_BASE + 0x00110000U) -#define __PIO0_BASE (__AHBPERIPH_BASE + 0x00200000U) -#define __PIO1_BASE (__AHBPERIPH_BASE + 0x00300000U) - -#define __SIO_BASE (__IOPORT_BASE + 0x00000000U) -/** @} */ - -/** - * @name Peripherals - * @{ - */ -#define DMA ((DMA_TypeDef *) __DMA_BASE) -#define IO_BANK0 ((IOUSER_TypeDef *) __IOUSER0_BASE) -#define IO_QSPI ((IOUSER_TypeDef *) __IOQSPI_BASE) -#define PADS_BANK0 ((PADS_TypeDef *) __PADSUSER0_BASE) -#define PADS_QSPI ((PADS_TypeDef *) __PADSQSPI_BASE) -#define PSM ((PSM_TypeDef *) __PSM_BASE) -#define RESETS ((RESETS_TypeDef *) __RESETS_BASE) -#define SIO ((SIO_TypeDef *) __SIO_BASE) -#define TIMER ((TIMER_TypeDef *) __TIMER_BASE) -#define UART0 ((UART_TypeDef *) __UART0_BASE) -#define UART1 ((UART_TypeDef *) __UART1_BASE) -#define RTC ((RTC_TypeDef *) __RTC_BASE) -#define SPI0 ((SPI_TypeDef *) __SPI0_BASE) -#define SPI1 ((SPI_TypeDef *) __SPI1_BASE) -#define I2C0 ((I2C_TypeDef *) __I2C0_BASE) -#define I2C1 ((I2C_TypeDef *) __I2C1_BASE) -#define ADC ((ADC_TypeDef *) __ADC_BASE) -#define PWM ((PWM_TypeDef *) __PWM_BASE) -#define PIO0 ((PIO_TypeDef *) __PIO0_BASE) -#define PIO1 ((PIO_TypeDef *) __PIO1_BASE) -#define USB ((USB_TypeDef *) __USB_BASE) -#define WATCHDOG ((WATCHDOG_TypeDef *) __WATCHDOG_BASE) -/** @} */ - -/** - * @name DMA bits definitions - * @{ - */ -#define DMA_CTRL_TRIG_AHB_ERROR (1U << 31) -#define DMA_CTRL_TRIG_READ_ERROR (1U << 30) -#define DMA_CTRL_TRIG_WRITE_ERROR (1U << 29) -#define DMA_CTRL_TRIG_BUSY (1U << 24) -#define DMA_CTRL_TRIG_SNIFF_EN (1U << 23) -#define DMA_CTRL_TRIG_BSWAP (1U << 22) -#define DMA_CTRL_TRIG_IRQ_QUIET (1U << 21) -#define DMA_CTRL_TRIG_TREQ_SEL_Pos 15U -#define DMA_CTRL_TRIG_TREQ_SEL_Msk (0x3FU << DMA_CTRL_TRIG_TREQ_SEL_Pos) -#define DMA_CTRL_TRIG_TREQ_SEL(n) ((n) << DMA_CTRL_TRIG_TREQ_SEL_Pos) -#define DMA_CTRL_TRIG_TREQ_PIO0_TX0 DMA_CTRL_TRIG_TREQ_SEL(0x00U) -#define DMA_CTRL_TRIG_TREQ_PIO0_TX1 DMA_CTRL_TRIG_TREQ_SEL(0x01U) -#define DMA_CTRL_TRIG_TREQ_PIO0_TX2 DMA_CTRL_TRIG_TREQ_SEL(0x02U) -#define DMA_CTRL_TRIG_TREQ_PIO0_TX3 DMA_CTRL_TRIG_TREQ_SEL(0x03U) -#define DMA_CTRL_TRIG_TREQ_PIO0_RX0 DMA_CTRL_TRIG_TREQ_SEL(0x04U) -#define DMA_CTRL_TRIG_TREQ_PIO0_RX1 DMA_CTRL_TRIG_TREQ_SEL(0x05U) -#define DMA_CTRL_TRIG_TREQ_PIO0_RX2 DMA_CTRL_TRIG_TREQ_SEL(0x06U) -#define DMA_CTRL_TRIG_TREQ_PIO0_RX3 DMA_CTRL_TRIG_TREQ_SEL(0x07U) -#define DMA_CTRL_TRIG_TREQ_PIO1_TX0 DMA_CTRL_TRIG_TREQ_SEL(0x08U) -#define DMA_CTRL_TRIG_TREQ_PIO1_TX1 DMA_CTRL_TRIG_TREQ_SEL(0x09U) -#define DMA_CTRL_TRIG_TREQ_PIO1_TX2 DMA_CTRL_TRIG_TREQ_SEL(0x0AU) -#define DMA_CTRL_TRIG_TREQ_PIO1_TX3 DMA_CTRL_TRIG_TREQ_SEL(0x0BU) -#define DMA_CTRL_TRIG_TREQ_PIO1_RX0 DMA_CTRL_TRIG_TREQ_SEL(0x0CU) -#define DMA_CTRL_TRIG_TREQ_PIO1_RX1 DMA_CTRL_TRIG_TREQ_SEL(0x0DU) -#define DMA_CTRL_TRIG_TREQ_PIO1_RX2 DMA_CTRL_TRIG_TREQ_SEL(0x0EU) -#define DMA_CTRL_TRIG_TREQ_PIO1_RX3 DMA_CTRL_TRIG_TREQ_SEL(0x0FU) -#define DMA_CTRL_TRIG_TREQ_SPI0_TX DMA_CTRL_TRIG_TREQ_SEL(0x10U) -#define DMA_CTRL_TRIG_TREQ_SPI0_RX DMA_CTRL_TRIG_TREQ_SEL(0x11U) -#define DMA_CTRL_TRIG_TREQ_SPI1_TX DMA_CTRL_TRIG_TREQ_SEL(0x12U) -#define DMA_CTRL_TRIG_TREQ_SPI1_RX DMA_CTRL_TRIG_TREQ_SEL(0x13U) -#define DMA_CTRL_TRIG_TREQ_UART0_TX DMA_CTRL_TRIG_TREQ_SEL(0x14U) -#define DMA_CTRL_TRIG_TREQ_UART0_RX DMA_CTRL_TRIG_TREQ_SEL(0x15U) -#define DMA_CTRL_TRIG_TREQ_UART1_TX DMA_CTRL_TRIG_TREQ_SEL(0x16U) -#define DMA_CTRL_TRIG_TREQ_UART1_RX DMA_CTRL_TRIG_TREQ_SEL(0x17U) -#define DMA_CTRL_TRIG_TREQ_PWM_WRAP0 DMA_CTRL_TRIG_TREQ_SEL(0x18U) -#define DMA_CTRL_TRIG_TREQ_PWM_WRAP1 DMA_CTRL_TRIG_TREQ_SEL(0x19U) -#define DMA_CTRL_TRIG_TREQ_PWM_WRAP2 DMA_CTRL_TRIG_TREQ_SEL(0x1AU) -#define DMA_CTRL_TRIG_TREQ_PWM_WRAP3 DMA_CTRL_TRIG_TREQ_SEL(0x1BU) -#define DMA_CTRL_TRIG_TREQ_PWM_WRAP4 DMA_CTRL_TRIG_TREQ_SEL(0x1CU) -#define DMA_CTRL_TRIG_TREQ_PWM_WRAP5 DMA_CTRL_TRIG_TREQ_SEL(0x1DU) -#define DMA_CTRL_TRIG_TREQ_PWM_WRAP6 DMA_CTRL_TRIG_TREQ_SEL(0x1EU) -#define DMA_CTRL_TRIG_TREQ_PWM_WRAP7 DMA_CTRL_TRIG_TREQ_SEL(0x1FU) -#define DMA_CTRL_TRIG_TREQ_I2C0_TX DMA_CTRL_TRIG_TREQ_SEL(0x20U) -#define DMA_CTRL_TRIG_TREQ_I2C0_RX DMA_CTRL_TRIG_TREQ_SEL(0x21U) -#define DMA_CTRL_TRIG_TREQ_I2C1_TX DMA_CTRL_TRIG_TREQ_SEL(0x22U) -#define DMA_CTRL_TRIG_TREQ_I2C1_RX DMA_CTRL_TRIG_TREQ_SEL(0x23U) -#define DMA_CTRL_TRIG_TREQ_ADC DMA_CTRL_TRIG_TREQ_SEL(0x24U) -#define DMA_CTRL_TRIG_TREQ_XIP_STREAM DMA_CTRL_TRIG_TREQ_SEL(0x25U) -#define DMA_CTRL_TRIG_TREQ_XIP_SSITX DMA_CTRL_TRIG_TREQ_SEL(0x26U) -#define DMA_CTRL_TRIG_TREQ_XIP_SSIRX DMA_CTRL_TRIG_TREQ_SEL(0x27U) -#define DMA_CTRL_TRIG_TREQ_TIMER0 DMA_CTRL_TRIG_TREQ_SEL(0x3BU) -#define DMA_CTRL_TRIG_TREQ_TIMER1 DMA_CTRL_TRIG_TREQ_SEL(0x3CU) -#define DMA_CTRL_TRIG_TREQ_TIMER2 DMA_CTRL_TRIG_TREQ_SEL(0x3DU) -#define DMA_CTRL_TRIG_TREQ_TIMER3 DMA_CTRL_TRIG_TREQ_SEL(0x3EU) -#define DMA_CTRL_TRIG_TREQ_PERMANENT DMA_CTRL_TRIG_TREQ_SEL(0x3FU) -#define DMA_CTRL_TRIG_CHAIN_TO_Pos 11U -#define DMA_CTRL_TRIG_CHAIN_TO_Msk (15U << DMA_CTRL_TRIG_CHAIN_TO_Pos) -#define DMA_CTRL_TRIG_CHAIN_TO(n) ((n) << DMA_CTRL_TRIG_CHAIN_TO_Pos) -#define DMA_CTRL_TRIG_RING_SEL (1U << 10) -#define DMA_CTRL_TRIG_RING_SIZE_Pos 6U -#define DMA_CTRL_TRIG_RING_SIZE_Msk (15U << DMA_CTRL_TRIG_RING_SIZE_Pos) -#define DMA_CTRL_TRIG_RING_SIZE(n) ((n) << DMA_CTRL_TRIG_RING_SIZE_Pos) -#define DMA_CTRL_TRIG_INCR_WRITE (1U << 5) -#define DMA_CTRL_TRIG_INCR_READ (1U << 4) -#define DMA_CTRL_TRIG_DATA_SIZE_Pos 2U -#define DMA_CTRL_TRIG_DATA_SIZE_Msk (3U << DMA_CTRL_TRIG_DATA_SIZE_Pos) -#define DMA_CTRL_TRIG_DATA_SIZE(n) ((n) << DMA_CTRL_TRIG_DATA_SIZE_Pos) -#define DMA_CTRL_TRIG_DATA_SIZE_BYTE DMA_CTRL_TRIG_DATA_SIZE(0U) -#define DMA_CTRL_TRIG_DATA_SIZE_HWORD DMA_CTRL_TRIG_DATA_SIZE(1U) -#define DMA_CTRL_TRIG_DATA_SIZE_WORD DMA_CTRL_TRIG_DATA_SIZE(2U) -#define DMA_CTRL_TRIG_HIGH_PRIORITY (1U << 1) -#define DMA_CTRL_TRIG_PRIORITY(n) ((n) << 1) -#define DMA_CTRL_TRIG_EN (1U << 0) -/** @} */ - -/** - * @name PSM bits definitions (dangerous) - * @{ - */ -#define PSM_ANY_PROC1 (1U << 16) -#define PSM_ANY_PROC0 (1U << 15) -#define PSM_ANY_SIO (1U << 14) -#define PSM_ANY_VREG_AND_CHIP_RESET (1U << 13) -#define PSM_ANY_XIP (1U << 12) -#define PSM_ANY_SRAM5 (1U << 11) -#define PSM_ANY_SRAM4 (1U << 10) -#define PSM_ANY_SRAM3 (1U << 9) -#define PSM_ANY_SRAM2 (1U << 8) -#define PSM_ANY_SRAM1 (1U << 7) -#define PSM_ANY_SRAM0 (1U << 6) -#define PSM_ANY_ROM (1U << 5) -#define PSM_ANY_BUSFABRIC (1U << 4) -#define PSM_ANY_RESETS (1U << 3) -#define PSM_ANY_CLOCKS (1U << 2) -#define PSM_ANY_XOSC (1U << 1) -#define PSM_ANY_ROSC (1U << 0) -/** @} */ - -/** - * @name RESETS bits definitions - * @{ - */ -#define RESETS_ALLREG_USBCTRL (1U << 24) -#define RESETS_ALLREG_UART1 (1U << 23) -#define RESETS_ALLREG_UART0 (1U << 22) -#define RESETS_ALLREG_TIMER (1U << 21) -#define RESETS_ALLREG_TBMAN (1U << 20) -#define RESETS_ALLREG_SYSINFO (1U << 19) -#define RESETS_ALLREG_SYSCFG (1U << 18) -#define RESETS_ALLREG_SPI1 (1U << 17) -#define RESETS_ALLREG_SPI0 (1U << 16) -#define RESETS_ALLREG_RTC (1U << 15) -#define RESETS_ALLREG_PWM (1U << 14) -#define RESETS_ALLREG_PLL_USB (1U << 13) -#define RESETS_ALLREG_PLL_SYS (1U << 12) -#define RESETS_ALLREG_PIO1 (1U << 11) -#define RESETS_ALLREG_PIO0 (1U << 10) -#define RESETS_ALLREG_PADS_QSPI (1U << 9) -#define RESETS_ALLREG_PADS_BANK0 (1U << 8) -#define RESETS_ALLREG_JTAG (1U << 7) -#define RESETS_ALLREG_IO_QSPI (1U << 6) -#define RESETS_ALLREG_IO_BANK0 (1U << 5) -#define RESETS_ALLREG_I2C1 (1U << 4) -#define RESETS_ALLREG_I2C0 (1U << 3) -#define RESETS_ALLREG_DMA (1U << 2) -#define RESETS_ALLREG_BUSCTRL (1U << 1) -#define RESETS_ALLREG_ADC (1U << 0) -/** @} */ - -/** - * @name SIO bits definitions - * @{ - */ -#define SIO_FIFO_ST_VLD_Pos 0U -#define SIO_FIFO_ST_VLD_Msk (1U << SIO_FIFO_ST_VLD_Pos) -#define SIO_FIFO_ST_VLD SIO_FIFO_ST_VLD_Msk -#define SIO_FIFO_ST_RDY_Pos 1U -#define SIO_FIFO_ST_RDY_Msk (1U << SIO_FIFO_ST_RDY_Pos) -#define SIO_FIFO_ST_RDY SIO_FIFO_ST_RDY_Msk -#define SIO_FIFO_ST_WOF_Pos 2U -#define SIO_FIFO_ST_WOF_Msk (1U << SIO_FIFO_ST_WOF_Pos) -#define SIO_FIFO_ST_WOF SIO_FIFO_ST_WOF_Msk -#define SIO_FIFO_ST_ROE_Pos 3U -#define SIO_FIFO_ST_ROE_Msk (1U << SIO_FIFO_ST_ROE_Pos) -#define SIO_FIFO_ST_ROE SIO_FIFO_ST_ROE_Msk -/** @} */ - -/** - * @name SPI bits definitions - * @{ - */ -#define SPI_SSPCR0_SCR_Pos 8U -#define SPI_SSPCR0_SCR_Msk (255U << SPI_SSPCR0_SCR_Pos) -#define SPI_SSPCR0_SCR(n) ((n) << SPI_SSPCR0_SCR_Pos) -#define SPI_SSPCR0_SPH_Pos 7U -#define SPI_SSPCR0_SPH_Msk (1U << SPI_SSPCR0_SPH_Pos) -#define SPI_SSPCR0_SPH SPI_SSPCR0_SPH_Msk -#define SPI_SSPCR0_SPO_Pos 6U -#define SPI_SSPCR0_SPO_Msk (1U << SPI_SSPCR0_SPO_Pos) -#define SPI_SSPCR0_SPO SPI_SSPCR0_SPO_Msk -#define SPI_SSPCR0_FRF_Pos 4U -#define SPI_SSPCR0_FRF_Msk (3U << SPI_SSPCR0_FRF_Pos) -#define SPI_SSPCR0_FRF(n) ((n) << SPI_SSPCR0_FRF_Pos) -#define SPI_SSPCR0_FRF_MOTOROLA SPI_SSPCR0_FRF(0U) -#define SPI_SSPCR0_FRF_TI SPI_SSPCR0_FRF(1U) -#define SPI_SSPCR0_FRF_NATIONAL SPI_SSPCR0_FRF(2U) -#define SPI_SSPCR0_DSS_Pos 0U -#define SPI_SSPCR0_DSS_Msk (15U << SPI_SSPCR0_DSS_Pos) -#define SPI_SSPCR0_DSS(n) ((n) << SPI_SSPCR0_DSS_Pos) -#define SPI_SSPCR0_DSS_4BIT SPI_SSPCR0_DSS(3U) -#define SPI_SSPCR0_DSS_5BIT SPI_SSPCR0_DSS(4U) -#define SPI_SSPCR0_DSS_6BIT SPI_SSPCR0_DSS(5U) -#define SPI_SSPCR0_DSS_7BIT SPI_SSPCR0_DSS(6U) -#define SPI_SSPCR0_DSS_8BIT SPI_SSPCR0_DSS(7U) -#define SPI_SSPCR0_DSS_9BIT SPI_SSPCR0_DSS(8U) -#define SPI_SSPCR0_DSS_10BIT SPI_SSPCR0_DSS(9U) -#define SPI_SSPCR0_DSS_11BIT SPI_SSPCR0_DSS(10U) -#define SPI_SSPCR0_DSS_12BIT SPI_SSPCR0_DSS(11U) -#define SPI_SSPCR0_DSS_13BIT SPI_SSPCR0_DSS(12U) -#define SPI_SSPCR0_DSS_14BIT SPI_SSPCR0_DSS(13U) -#define SPI_SSPCR0_DSS_15BIT SPI_SSPCR0_DSS(14U) -#define SPI_SSPCR0_DSS_16BIT SPI_SSPCR0_DSS(15U) - -#define SPI_SSPCR1_SOD_Pos 3U -#define SPI_SSPCR1_SOD_Msk (1U << SPI_SSPCR1_SOD_Pos) -#define SPI_SSPCR1_SOD SPI_SSPCR1_SOD_Msk -#define SPI_SSPCR1_MS_Pos 2U -#define SPI_SSPCR1_MS_Msk (1U << SPI_SSPCR1_MS_Pos) -#define SPI_SSPCR1_MS SPI_SSPCR1_MS_Msk -#define SPI_SSPCR1_SSE_Pos 1U -#define SPI_SSPCR1_SSE_Msk (1U << SPI_SSPCR1_SSE_Pos) -#define SPI_SSPCR1_SSE SPI_SSPCR1_SSE_Msk -#define SPI_SSPCR1_LBM_Pos 0U -#define SPI_SSPCR1_LBM_Msk (1U << SPI_SSPCR1_LBM_Pos) -#define SPI_SSPCR1_LBM SPI_SSPCR1_LBM_Msk - -#define SPI_SSPSR_BSY_Pos 4U -#define SPI_SSPSR_BSY_Msk (1U << SPI_SSPSR_BSY_Pos) -#define SPI_SSPSR_BSY SPI_SSPSR_BSY_Msk -#define SPI_SSPSR_RFF_Pos 3U -#define SPI_SSPSR_RFF_Msk (1U << SPI_SSPSR_RFF_Pos) -#define SPI_SSPSR_RFF SPI_SSPSR_RFF_Msk -#define SPI_SSPSR_RNE_Pos 2U -#define SPI_SSPSR_RNE_Msk (1U << SPI_SSPSR_RNE_Pos) -#define SPI_SSPSR_RNE SPI_SSPSR_RNE_Msk -#define SPI_SSPSR_TNF_Pos 1U -#define SPI_SSPSR_TNF_Msk (1U << SPI_SSPSR_TNF_Pos) -#define SPI_SSPSR_TNF SPI_SSPSR_TNF_Msk -#define SPI_SSPSR_TFE_Pos 0U -#define SPI_SSPSR_TFE_Msk (1U << SPI_SSPSR_TFE_Pos) -#define SPI_SSPSR_TFE SPI_SSPSR_TFE_Msk - -#define SPI_SSPCPSR_CPSDVSR_Pos 0U -#define SPI_SSPCPSR_CPSDVSR_Msk (255U << SPI_SSPCPSR_CPSDVSR_Pos) -#define SPI_SSPCPSR_CPSDVSR(n) ((n) << SPI_SSPCPSR_CPSDVSR_Msk) - -#define SPI_SSPIMSC_TXIM_Pos 3U -#define SPI_SSPIMSC_TXIM_Msk (1U << SPI_SSPIMSC_TXIM_Pos) -#define SPI_SSPIMSC_TXIM SPI_SSPIMSC_TXIM_Msk -#define SPI_SSPIMSC_RXIM_Pos 2U -#define SPI_SSPIMSC_RXIM_Msk (1U << SPI_SSPIMSC_RXIM_Pos) -#define SPI_SSPIMSC_RXIM SPI_SSPIMSC_RXIM_Msk -#define SPI_SSPIMSC_RTIM_Pos 1U -#define SPI_SSPIMSC_RTIM_Msk (1U << SPI_SSPIMSC_RTIM_Pos) -#define SPI_SSPIMSC_RTIM SPI_SSPIMSC_RTIM_Msk -#define SPI_SSPIMSC_RORIM_Pos 0U -#define SPI_SSPIMSC_RORIM_Msk (1U << SPI_SSPIMSC_RORIM_Pos) -#define SPI_SSPIMSC_RORIM SPI_SSPIMSC_RORIM_Msk - -#define SPI_SSPRIS_TXRIS_Pos 3U -#define SPI_SSPRIS_TXRIS_Msk (1U << SPI_SSPRIS_TXRIS_Pos) -#define SPI_SSPRIS_TXRIS SPI_SSPRIS_TXRIS_Msk -#define SPI_SSPRIS_RXRIS_Pos 2U -#define SPI_SSPRIS_RXRIS_Msk (1U << SPI_SSPRIS_RXRIS_Pos) -#define SPI_SSPRIS_RXRIS SPI_SSPRIS_RXRIS_Msk -#define SPI_SSPRIS_RTRIS_Pos 1U -#define SPI_SSPRIS_RTRIS_Msk (1U << SPI_SSPRIS_RTRIS_Pos) -#define SPI_SSPRIS_RTRIS SPI_SSPRIS_RTRIS_Msk -#define SPI_SSPRIS_RORRIS_Pos 0U -#define SPI_SSPRIS_RORRIS_Msk (1U << SPI_SSPRIS_RORRIS_Pos) -#define SPI_SSPRIS_RORRIS SPI_SSPRIS_RORRIS_Msk - -#define SPI_SSPMIS_TXMIS_Pos 3U -#define SPI_SSPMIS_TXMIS_Msk (1U << SPI_SSPMIS_TXMIS_Pos) -#define SPI_SSPMIS_TXMIS SPI_SSPMIS_TXMIS_Msk -#define SPI_SSPMIS_RXMIS_Pos 2U -#define SPI_SSPMIS_RXMIS_Msk (1U << SPI_SSPMIS_RXMIS_Pos) -#define SPI_SSPMIS_RXMIS SPI_SSPMIS_RXMIS_Msk -#define SPI_SSPMIS_RTMIS_Pos 1U -#define SPI_SSPMIS_RTMIS_Msk (1U << SPI_SSPMIS_RTMIS_Pos) -#define SPI_SSPMIS_RTMIS SPI_SSPMIS_RTMIS_Msk -#define SPI_SSPMIS_RORMIS_Pos 0U -#define SPI_SSPMIS_RORMIS_Msk (1U << SPI_SSPMIS_RORMIS_Pos) -#define SPI_SSPMIS_RORMIS SPI_SSPMIS_RORMIS_Msk - -#define SPI_SSPICR_RTIC_Pos 1U -#define SPI_SSPICR_RTIC_Msk (1U << SPI_SSPICR_RTIC_Pos) -#define SPI_SSPICR_RTIC SPI_SSPICR_RTIC_Msk -#define SPI_SSPICR_RORIC_Pos 0U -#define SPI_SSPICR_RORIC_Msk (1U << SPI_SSPICR_RORIC_Pos) -#define SPI_SSPICR_RORIC SPI_SSPICR_RORIC_Msk - -#define SPI_SSPDMACR_TXDMAE_Pos 1U -#define SPI_SSPDMACR_TXDMAE_Msk (1U << SPI_SSPDMACR_TXDMAE_Pos) -#define SPI_SSPDMACR_TXDMAE SPI_SSPDMACR_TXDMAE_Msk -#define SPI_SSPDMACR_RXDMAE_Pos 0U -#define SPI_SSPDMACR_RXDMAE_Msk (1U << SPI_SSPDMACR_RXDMAE_Pos) -#define SPI_SSPDMACR_RXDMAE SPI_SSPDMACR_RXDMAE_Msk -/** @} */ - -/** - * @name TIMER bits definitions - * @{ - */ -#define TIMER_ARMED_ALARM0_Pos 0U -#define TIMER_ARMED_ALARM0_Msk (1U << TIMER_ARMED_ALARM0_Pos) -#define TIMER_ARMED_ALARM0 TIMER_ARMED_ALARM0_Msk -#define TIMER_ARMED_ALARM1_Pos 1U -#define TIMER_ARMED_ALARM1_Msk (1U << TIMER_ARMED_ALARM1_Pos) -#define TIMER_ARMED_ALARM1 TIMER_ARMED_ALARM1_Msk -#define TIMER_ARMED_ALARM2_Pos 2U -#define TIMER_ARMED_ALARM2_Msk (1U << TIMER_ARMED_ALARM2_Pos) -#define TIMER_ARMED_ALARM2 TIMER_ARMED_ALARM2_Msk -#define TIMER_ARMED_ALARM3_Pos 3U -#define TIMER_ARMED_ALARM3_Msk (1U << TIMER_ARMED_ALARM3_Pos) -#define TIMER_ARMED_ALARM3 TIMER_ARMED_ALARM3_Msk - -#define TIMER_DBGPAUSE_DBG0_Pos 1U -#define TIMER_DBGPAUSE_DBG0_Msk (1U << TIMER_DBGPAUSE_DBG0_Pos) -#define TIMER_DBGPAUSE_DBG0 TIMER_DBGPAUSE_DBG0_Msk -#define TIMER_DBGPAUSE_DBG1_Pos 2U -#define TIMER_DBGPAUSE_DBG1_Msk (1U << TIMER_DBGPAUSE_DBG1_Pos) -#define TIMER_DBGPAUSE_DBG1 TIMER_DBGPAUSE_DBG1_Msk - -#define TIMER_PAUSE_PAUSE_Pos 0U -#define TIMER_PAUSE_PAUSE_Msk (1U << TIMER_PAUSE_PAUSE_Pos) -#define TIMER_PAUSE_PAUSE TIMER_PAUSE_PAUSE_Msk - -#define TIMER_INTR_ALARM0_Pos 0U -#define TIMER_INTR_ALARM0_Msk (1U << TIMER_INTR_ALARM0_Pos) -#define TIMER_INTR_ALARM0 TIMER_INTR_ALARM0_Msk -#define TIMER_INTR_ALARM1_Pos 1U -#define TIMER_INTR_ALARM1_Msk (1U << TIMER_INTR_ALARM1_Pos) -#define TIMER_INTR_ALARM1 TIMER_INTR_ALARM1_Msk -#define TIMER_INTR_ALARM2_Pos 2U -#define TIMER_INTR_ALARM2_Msk (1U << TIMER_INTR_ALARM2_Pos) -#define TIMER_INTR_ALARM2 TIMER_INTR_ALARM2_Msk -#define TIMER_INTR_ALARM3_Pos 3U -#define TIMER_INTR_ALARM3_Msk (1U << TIMER_INTR_ALARM3_Pos) -#define TIMER_INTR_ALARM3 TIMER_INTR_ALARM3_Msk - -#define TIMER_INTE_ALARM0_Pos 0U -#define TIMER_INTE_ALARM0_Msk (1U << TIMER_INTE_ALARM0_Pos) -#define TIMER_INTE_ALARM0 TIMER_INTE_ALARM0_Msk -#define TIMER_INTE_ALARM1_Pos 1U -#define TIMER_INTE_ALARM1_Msk (1U << TIMER_INTE_ALARM1_Pos) -#define TIMER_INTE_ALARM1 TIMER_INTE_ALARM1_Msk -#define TIMER_INTE_ALARM2_Pos 2U -#define TIMER_INTE_ALARM2_Msk (1U << TIMER_INTE_ALARM2_Pos) -#define TIMER_INTE_ALARM2 TIMER_INTE_ALARM2_Msk -#define TIMER_INTE_ALARM3_Pos 3U -#define TIMER_INTE_ALARM3_Msk (1U << TIMER_INTE_ALARM3_Pos) -#define TIMER_INTE_ALARM3 TIMER_INTE_ALARM3_Msk - -#define TIMER_INTF_ALARM0_Pos 0U -#define TIMER_INTF_ALARM0_Msk (1U << TIMER_INTF_ALARM0_Pos) -#define TIMER_INTF_ALARM0 TIMER_INTF_ALARM0_Msk -#define TIMER_INTF_ALARM1_Pos 1U -#define TIMER_INTF_ALARM1_Msk (1U << TIMER_INTF_ALARM1_Pos) -#define TIMER_INTF_ALARM1 TIMER_INTF_ALARM1_Msk -#define TIMER_INTF_ALARM2_Pos 2U -#define TIMER_INTF_ALARM2_Msk (1U << TIMER_INTF_ALARM2_Pos) -#define TIMER_INTF_ALARM2 TIMER_INTF_ALARM2_Msk -#define TIMER_INTF_ALARM3_Pos 3U -#define TIMER_INTF_ALARM3_Msk (1U << TIMER_INTF_ALARM3_Pos) -#define TIMER_INTF_ALARM3 TIMER_INTF_ALARM3_Msk - -#define TIMER_INTS_ALARM0_Pos 0U -#define TIMER_INTS_ALARM0_Msk (1U << TIMER_INTS_ALARM0_Pos) -#define TIMER_INTS_ALARM0 TIMER_INTS_ALARM0_Msk -#define TIMER_INTS_ALARM1_Pos 1U -#define TIMER_INTS_ALARM1_Msk (1U << TIMER_INTS_ALARM1_Pos) -#define TIMER_INTS_ALARM1 TIMER_INTS_ALARM1_Msk -#define TIMER_INTS_ALARM2_Pos 2U -#define TIMER_INTS_ALARM2_Msk (1U << TIMER_INTS_ALARM2_Pos) -#define TIMER_INTS_ALARM2 TIMER_INTS_ALARM2_Msk -#define TIMER_INTS_ALARM3_Pos 3U -#define TIMER_INTS_ALARM3_Msk (1U << TIMER_INTS_ALARM3_Pos) -#define TIMER_INTS_ALARM3 TIMER_INTS_ALARM3_Msk -/** @} */ - -/** - * @name UART bits definitions - * @{ - */ -#define UART_UARTDR_OE_Pos 11U -#define UART_UARTDR_OE_Msk (1U << UART_UARTDR_OE_Pos) -#define UART_UARTDR_OE UART_UARTDR_OE_Msk -#define UART_UARTDR_BE_Pos 10U -#define UART_UARTDR_BE_Msk (1U << UART_UARTDR_BE_Pos) -#define UART_UARTDR_BE UART_UARTDR_BE_Msk -#define UART_UARTDR_PE_Pos 9U -#define UART_UARTDR_PE_Msk (1U << UART_UARTDR_PE_Pos) -#define UART_UARTDR_PE UART_UARTDR_PE_Msk -#define UART_UARTDR_FE_Pos 8U -#define UART_UARTDR_FE_Msk (1U << UART_UARTDR_FE_Pos) -#define UART_UARTDR_FE UART_UARTDR_FE_Msk - -#define UART_UARTRSR_OE_Pos 3U -#define UART_UARTRSR_OE_Msk (1U << UART_UARTRSR_OE_Pos) -#define UART_UARTRSR_OE UART_UARTRSR_OE_Msk -#define UART_UARTRSR_BE_Pos 2U -#define UART_UARTRSR_BE_Msk (1U << UART_UARTRSR_BE_Pos) -#define UART_UARTRSR_BE UART_UARTRSR_BE_Msk -#define UART_UARTRSR_PE_Pos 1U -#define UART_UARTRSR_PE_Msk (1U << UART_UARTRSR_PE_Pos) -#define UART_UARTRSR_PE UART_UARTRSR_PE_Msk -#define UART_UARTRSR_FE_Pos 0U -#define UART_UARTRSR_FE_Msk (1U << UART_UARTRSR_FE_Pos) -#define UART_UARTRSR_FE UART_UARTRSR_FE_Msk - -#define UART_UARTFR_RI_Pos 8U -#define UART_UARTFR_RI_Msk (1U << UART_UARTFR_RI_Pos) -#define UART_UARTFR_RI UART_UARTFR_RI_Msk -#define UART_UARTFR_TXFE_Pos 7U -#define UART_UARTFR_TXFE_Msk (1U << UART_UARTFR_TXFE_Pos) -#define UART_UARTFR_TXFE UART_UARTFR_TXFE_Msk -#define UART_UARTFR_RXFF_Pos 6U -#define UART_UARTFR_RXFF_Msk (1U << UART_UARTFR_RXFF_Pos) -#define UART_UARTFR_RXFF UART_UARTFR_RXFF_Msk -#define UART_UARTFR_TXFF_Pos 5U -#define UART_UARTFR_TXFF_Msk (1U << UART_UARTFR_TXFF_Pos) -#define UART_UARTFR_TXFF UART_UARTFR_TXFF_Msk -#define UART_UARTFR_RXFE_Pos 4U -#define UART_UARTFR_RXFE_Msk (1U << UART_UARTFR_RXFE_Pos) -#define UART_UARTFR_RXFE UART_UARTFR_RXFE_Msk -#define UART_UARTFR_BUSY_Pos 3U -#define UART_UARTFR_BUSY_Msk (1U << UART_UARTFR_BUSY_Pos) -#define UART_UARTFR_BUSY UART_UARTFR_BUSY_Msk -#define UART_UARTFR_DCD_Pos 2U -#define UART_UARTFR_DCD_Msk (1U << UART_UARTFR_DCD_Pos) -#define UART_UARTFR_DCD UART_UARTFR_DCD_Msk -#define UART_UARTFR_DSR_Pos 1U -#define UART_UARTFR_DSR_Msk (1U << UART_UARTFR_DSR_Pos) -#define UART_UARTFR_DSR UART_UARTFR_DSR_Msk -#define UART_UARTFR_CTS_Pos 0U -#define UART_UARTFR_CTS_Msk (1U << UART_UARTFR_CTS_Pos) -#define UART_UARTFR_CTS UART_UARTFR_CTS_Msk - -#define UART_UARTILPR_ILPDVSR_Pos 0U -#define UART_UARTILPR_ILPDVSR_Msk (255U << UART_UARTILPR_ILPDVSR_Pos) -#define UART_UARTILPR_ILPDVSR(n) ((n) << UART_UARTILPR_ILPDVSR_Pos) - -#define UART_UARTIBRD_BAUD_DIVINT_Pos 0U -#define UART_UARTIBRD_BAUD_DIVINT_Msk (0xFFFFU << UART_UARTIBRD_BAUD_DIVINT_Pos) -#define UART_UARTIBRD_BAUD_DIVINT(n) ((n) << UART_UARTIBRD_BAUD_DIVINT_Pos) - -#define UART_UARTFBRD_BAUD_DIVFRAC_Pos 0U -#define UART_UARTFBRD_BAUD_DIVFRAC_Msk (63U << UART_UARTFBRD_BAUD_DIVFRAC_Pos) -#define UART_UARTFBRD_BAUD_DIVFRAC(n) ((n) << UART_UARTFBRD_BAUD_DIVFRAC_Pos) - -#define UART_UARTLCR_H_SPS_Pos 7U -#define UART_UARTLCR_H_SPS_Msk (1U << UART_UARTLCR_H_SPS_Pos) -#define UART_UARTLCR_H_SPS UART_UARTLCR_H_SPS_Msk -#define UART_UARTLCR_H_WLEN_Pos 5U -#define UART_UARTLCR_H_WLEN_Msk (1U << UART_UARTLCR_H_WLEN_Pos) -#define UART_UARTLCR_H_WLEN(n) ((n) << UART_UARTLCR_H_WLEN_Pos) -#define UART_UARTLCR_H_WLEN_5BITS UART_UARTLCR_H_WLEN(0U) -#define UART_UARTLCR_H_WLEN_6BITS UART_UARTLCR_H_WLEN(1U) -#define UART_UARTLCR_H_WLEN_7BITS UART_UARTLCR_H_WLEN(2U) -#define UART_UARTLCR_H_WLEN_8BITS UART_UARTLCR_H_WLEN(3U) -#define UART_UARTLCR_H_FEN_Pos 4U -#define UART_UARTLCR_H_FEN_Msk (1U << UART_UARTLCR_H_FEN_Pos) -#define UART_UARTLCR_H_FEN UART_UARTLCR_H_FEN_Msk -#define UART_UARTLCR_H_STP2_Pos 3U -#define UART_UARTLCR_H_STP2_Msk (1U << UART_UARTLCR_H_STP2_Pos) -#define UART_UARTLCR_H_STP2 UART_UARTLCR_H_STP2_Msk -#define UART_UARTLCR_H_EPS_Pos 2U -#define UART_UARTLCR_H_EPS_Msk (1U << UART_UARTLCR_H_EPS_Pos) -#define UART_UARTLCR_H_EPS UART_UARTLCR_H_EPS_Msk -#define UART_UARTLCR_H_PEN_Pos 1U -#define UART_UARTLCR_H_PEN_Msk (1U << UART_UARTLCR_H_PEN_Pos) -#define UART_UARTLCR_H_PEN UART_UARTLCR_H_PEN_Msk -#define UART_UARTLCR_H_BRK_Pos 0U -#define UART_UARTLCR_H_BRK_Msk (1U << UART_UARTLCR_H_BRK_Pos) -#define UART_UARTLCR_H_BRK UART_UARTLCR_H_BRK_Msk - -#define UART_UARTCR_CTSEN_Pos 15U -#define UART_UARTCR_CTSEN_Msk (1U << UART_UARTCR_CTSEN_Pos) -#define UART_UARTCR_CTSEN UART_UARTCR_CTSEN_Msk -#define UART_UARTCR_RTSEN_Pos 14U -#define UART_UARTCR_RTSEN_Msk (1U << UART_UARTCR_RTSEN_Pos) -#define UART_UARTCR_RTSEN UART_UARTCR_RTSEN_Msk -#define UART_UARTCR_OUT2_Pos 13U -#define UART_UARTCR_OUT2_Msk (1U << UART_UARTCR_OUT2_Pos) -#define UART_UARTCR_OUT2 UART_UARTCR_OUT2_Msk -#define UART_UARTCR_OUT1_Pos 12U -#define UART_UARTCR_OUT1_Msk (1U << UART_UARTCR_OUT1_Pos) -#define UART_UARTCR_OUT1 UART_UARTCR_OUT1_Msk -#define UART_UARTCR_RTS_Pos 11U -#define UART_UARTCR_RTS_Msk (1U << UART_UARTCR_RTS_Pos) -#define UART_UARTCR_RTS UART_UARTCR_RTS_Msk -#define UART_UARTCR_DTR_Pos 10U -#define UART_UARTCR_DTR_Msk (1U << UART_UARTCR_DTR_Pos) -#define UART_UARTCR_DTR UART_UARTCR_DTR_Msk -#define UART_UARTCR_RXE_Pos 9U -#define UART_UARTCR_RXE_Msk (1U << UART_UARTCR_RXE_Pos) -#define UART_UARTCR_RXE UART_UARTCR_RXE_Msk -#define UART_UARTCR_TXE_Pos 8U -#define UART_UARTCR_TXE_Msk (1U << UART_UARTCR_TXE_Pos) -#define UART_UARTCR_TXE UART_UARTCR_TXE_Msk -#define UART_UARTCR_LBE_Pos 7U -#define UART_UARTCR_LBE_Msk (1U << UART_UARTCR_LBE_Pos) -#define UART_UARTCR_LBE UART_UARTCR_LBE_Msk -#define UART_UARTCR_SIRLP_Pos 2U -#define UART_UARTCR_SIRLP_Msk (1U << UART_UARTCR_SIRLP_Pos) -#define UART_UARTCR_SIRLP UART_UARTCR_SIRLP_Msk -#define UART_UARTCR_SIREN_Pos 1U -#define UART_UARTCR_SIREN_Msk (1U << UART_UARTCR_SIREN_Pos) -#define UART_UARTCR_SIREN UART_UARTCR_SIREN_Msk -#define UART_UARTCR_UARTEN_Pos 0U -#define UART_UARTCR_UARTEN_Msk (1U << UART_UARTCR_UARTEN_Pos) -#define UART_UARTCR_UARTEN UART_UARTCR_UARTEN_Msk - -#define UART_UARTIFLS_RXIFLSEL_Pos 3U -#define UART_UARTIFLS_RXIFLSEL_Msk (1U << UART_UARTIFLS_RXIFLSEL_Pos) -#define UART_UARTIFLS_RXIFLSEL(n) ((n) << UART_UARTIFLS_RXIFLSEL_Pos) -#define UART_UARTIFLS_RXIFLSEL_1_8F UART_UARTIFLS_RXIFLSEL(0U) -#define UART_UARTIFLS_RXIFLSEL_1_4F UART_UARTIFLS_RXIFLSEL(1U) -#define UART_UARTIFLS_RXIFLSEL_1_2F UART_UARTIFLS_RXIFLSEL(2U) -#define UART_UARTIFLS_RXIFLSEL_3_4F UART_UARTIFLS_RXIFLSEL(3U) -#define UART_UARTIFLS_RXIFLSEL_7_8F UART_UARTIFLS_RXIFLSEL(4U) - -#define UART_UARTIFLS_TXIFLSEL_Pos 3U -#define UART_UARTIFLS_TXIFLSEL_Msk (1U << UART_UARTIFLS_TXIFLSEL_Pos) -#define UART_UARTIFLS_TXIFLSEL(n) ((n) << UART_UARTIFLS_TXIFLSEL_Pos) -#define UART_UARTIFLS_TXIFLSEL_1_8E UART_UARTIFLS_TXIFLSEL(0U) -#define UART_UARTIFLS_TXIFLSEL_1_4E UART_UARTIFLS_TXIFLSEL(1U) -#define UART_UARTIFLS_TXIFLSEL_1_2E UART_UARTIFLS_TXIFLSEL(2U) -#define UART_UARTIFLS_TXIFLSEL_3_4E UART_UARTIFLS_TXIFLSEL(3U) -#define UART_UARTIFLS_TXIFLSEL_7_8E UART_UARTIFLS_TXIFLSEL(4U) - -#define UART_UARTIMSC_OEIM_Pos 10U -#define UART_UARTIMSC_OEIM_Msk (1U << UART_UARTIMSC_OEIM_Pos) -#define UART_UARTIMSC_OEIM UART_UARTIMSC_OEIM_Msk -#define UART_UARTIMSC_BEIM_Pos 9U -#define UART_UARTIMSC_BEIM_Msk (1U << UART_UARTIMSC_BEIM_Pos) -#define UART_UARTIMSC_BEIM UART_UARTIMSC_BEIM_Msk -#define UART_UARTIMSC_PEIM_Pos 8U -#define UART_UARTIMSC_PEIM_Msk (1U << UART_UARTIMSC_PEIM_Pos) -#define UART_UARTIMSC_PEIM UART_UARTIMSC_PEIM_Msk -#define UART_UARTIMSC_FEIM_Pos 7U -#define UART_UARTIMSC_FEIM_Msk (1U << UART_UARTIMSC_FEIM_Pos) -#define UART_UARTIMSC_FEIM UART_UARTIMSC_FEIM_Msk -#define UART_UARTIMSC_RTIM_Pos 6U -#define UART_UARTIMSC_RTIM_Msk (1U << UART_UARTIMSC_RTIM_Pos) -#define UART_UARTIMSC_RTIM UART_UARTIMSC_RTIM_Msk -#define UART_UARTIMSC_TXIM_Pos 5U -#define UART_UARTIMSC_TXIM_Msk (1U << UART_UARTIMSC_TXIM_Pos) -#define UART_UARTIMSC_TXIM UART_UARTIMSC_TXIM_Msk -#define UART_UARTIMSC_RXIM_Pos 4U -#define UART_UARTIMSC_RXIM_Msk (1U << UART_UARTIMSC_RXIM_Pos) -#define UART_UARTIMSC_RXIM UART_UARTIMSC_RXIM_Msk -#define UART_UARTIMSC_DSRMIM_Pos 3U -#define UART_UARTIMSC_DSRMIM_Msk (1U << UART_UARTIMSC_DSRMIM_Pos) -#define UART_UARTIMSC_DSRMIM UART_UARTIMSC_DSRMIM_Msk -#define UART_UARTIMSC_DCDMIM_Pos 2U -#define UART_UARTIMSC_DCDMIM_Msk (1U << UART_UARTIMSC_DCDMIM_Pos) -#define UART_UARTIMSC_DCDMIM UART_UARTIMSC_DCDMIM_Msk -#define UART_UARTIMSC_CTSMIM_Pos 1U -#define UART_UARTIMSC_CTSMIM_Msk (1U << UART_UARTIMSC_CTSMIM_Pos) -#define UART_UARTIMSC_CTSMIM UART_UARTIMSC_CTSMIM_Msk -#define UART_UARTIMSC_RIMIM_Pos 0U -#define UART_UARTIMSC_RIMIM_Msk (1U << UART_UARTIMSC_RIMIM_Pos) -#define UART_UARTIMSC_RIMIM UART_UARTIMSC_RIMIM_Msk - -#define UART_UARTRIS_OERIS_Pos 10U -#define UART_UARTRIS_OERIS_Msk (1U << UART_UARTRIS_OERIS_Pos) -#define UART_UARTRIS_OERIS UART_UARTRIS_OERIS_Msk -#define UART_UARTRIS_BERIS_Pos 9U -#define UART_UARTRIS_BERIS_Msk (1U << UART_UARTRIS_BERIS_Pos) -#define UART_UARTRIS_BERIS UART_UARTRIS_BERIS_Msk -#define UART_UARTRIS_PERIS_Pos 8U -#define UART_UARTRIS_PERIS_Msk (1U << UART_UARTRIS_PERIS_Pos) -#define UART_UARTRIS_PERIS UART_UARTRIS_PERIS_Msk -#define UART_UARTRIS_FERIS_Pos 7U -#define UART_UARTRIS_FERIS_Msk (1U << UART_UARTRIS_FERIS_Pos) -#define UART_UARTRIS_FERIS UART_UARTRIS_FERIS_Msk -#define UART_UARTRIS_RTRIS_Pos 6U -#define UART_UARTRIS_RTRIS_Msk (1U << UART_UARTRIS_RTRIS_Pos) -#define UART_UARTRIS_RTRIS UART_UARTRIS_RTRIS_Msk -#define UART_UARTRIS_TXRIS_Pos 5U -#define UART_UARTRIS_TXRIS_Msk (1U << UART_UARTRIS_TXRIS_Pos) -#define UART_UARTRIS_TXRIS UART_UARTRIS_TXRIS_Msk -#define UART_UARTRIS_RXRIS_Pos 4U -#define UART_UARTRIS_RXRIS_Msk (1U << UART_UARTRIS_RXRIS_Pos) -#define UART_UARTRIS_RXRIS UART_UARTRIS_RXRIS_Msk -#define UART_UARTRIS_DSRRMIS_Pos 3U -#define UART_UARTRIS_DSRRMIS_Msk (1U << UART_UARTRIS_DSRRMIS_Pos) -#define UART_UARTRIS_DSRRMIS UART_UARTRIS_DSRRMIS_Msk -#define UART_UARTRIS_DCDRMIS_Pos 2U -#define UART_UARTRIS_DCDRMIS_Msk (1U << UART_UARTRIS_DCDRMIS_Pos) -#define UART_UARTRIS_DCDRMIS UART_UARTRIS_DCDRMIS_Msk -#define UART_UARTRIS_CTSRMIS_Pos 1U -#define UART_UARTRIS_CTSRMIS_Msk (1U << UART_UARTRIS_CTSRMIS_Pos) -#define UART_UARTRIS_CTSRMIS UART_UARTRIS_CTSRMIS_Msk -#define UART_UARTRIS_RIRMIS_Pos 0U -#define UART_UARTRIS_RIRMIS_Msk (1U << UART_UARTRIS_RIRMIS_Pos) -#define UART_UARTRIS_RIRMIS UART_UARTIMSC_RIRMIS_Msk - -#define UART_UARTMIS_OEMIS_Pos 10U -#define UART_UARTMIS_OEMIS_Msk (1U << UART_UARTMIS_OEMIS_Pos) -#define UART_UARTMIS_OEMIS UART_UARTMIS_OEMIS_Msk -#define UART_UARTMIS_BEMIS_Pos 9U -#define UART_UARTMIS_BEMIS_Msk (1U << UART_UARTMIS_BEMIS_Pos) -#define UART_UARTMIS_BEMIS UART_UARTMIS_BEMIS_Msk -#define UART_UARTMIS_PEMIS_Pos 8U -#define UART_UARTMIS_PEMIS_Msk (1U << UART_UARTMIS_PEMIS_Pos) -#define UART_UARTMIS_PEMIS UART_UARTMIS_PEMIS_Msk -#define UART_UARTMIS_FEMIS_Pos 7U -#define UART_UARTMIS_FEMIS_Msk (1U << UART_UARTMIS_FEMIS_Pos) -#define UART_UARTMIS_FEMIS UART_UARTMIS_FEMIS_Msk -#define UART_UARTMIS_RTMIS_Pos 6U -#define UART_UARTMIS_RTMIS_Msk (1U << UART_UARTMIS_RTMIS_Pos) -#define UART_UARTMIS_RTMIS UART_UARTMIS_RTMIS_Msk -#define UART_UARTMIS_TXMIS_Pos 5U -#define UART_UARTMIS_TXMIS_Msk (1U << UART_UARTMIS_TXMIS_Pos) -#define UART_UARTMIS_TXMIS UART_UARTMIS_TXMIS_Msk -#define UART_UARTMIS_RXMIS_Pos 4U -#define UART_UARTMIS_RXMIS_Msk (1U << UART_UARTMIS_RXMIS_Pos) -#define UART_UARTMIS_RXMIS UART_UARTMIS_RXMIS_Msk -#define UART_UARTMIS_DSRMMIS_Pos 3U -#define UART_UARTMIS_DSRMMIS_Msk (1U << UART_UARTMIS_DSRMMIS_Pos) -#define UART_UARTMIS_DSRRMIS UART_UARTMIS_DSRMMIS_Msk -#define UART_UARTMIS_DCDMMIS_Pos 2U -#define UART_UARTMIS_DCDMMIS_Msk (1U << UART_UARTMIS_DCDMMIS_Pos) -#define UART_UARTMIS_DCDMMIS UART_UARTMIS_DCDMMIS_Msk -#define UART_UARTMIS_CTSMMIS_Pos 1U -#define UART_UARTMIS_CTSMMIS_Msk (1U << UART_UARTMIS_CTSMMIS_Pos) -#define UART_UARTMIS_CTSMMIS UART_UARTMIS_CTSMMIS_Msk -#define UART_UARTMIS_RIMMIS_Pos 0U -#define UART_UARTMIS_RIMMIS_Msk (1U << UART_UARTMIS_RIMMIS_Pos) -#define UART_UARTMIS_RIMMIS UART_UARTIMSC_RIMMIS_Msk - -#define UART_UARTICR_OEIC_Pos 10U -#define UART_UARTICR_OEIC_Msk (1U << UART_UARTICR_OEIC_Pos) -#define UART_UARTICR_OEIC UART_UARTICR_OEIC_Msk -#define UART_UARTICR_BEIC_Pos 9U -#define UART_UARTICR_BEIC_Msk (1U << UART_UARTICR_BEIC_Pos) -#define UART_UARTICR_BEIC UART_UARTICR_BEIC_Msk -#define UART_UARTICR_PEIC_Pos 8U -#define UART_UARTICR_PEIC_Msk (1U << UART_UARTICR_PEIC_Pos) -#define UART_UARTICR_PEIC UART_UARTICR_PEIC_Msk -#define UART_UARTICR_FEIC_Pos 7U -#define UART_UARTICR_FEIC_Msk (1U << UART_UARTICR_FEIC_Pos) -#define UART_UARTICR_FEIC UART_UARTICR_FEIC_Msk -#define UART_UARTICR_RTIC_Pos 6U -#define UART_UARTICR_RTIC_Msk (1U << UART_UARTICR_RTIC_Pos) -#define UART_UARTICR_RTIC UART_UARTICR_RTIC_Msk -#define UART_UARTICR_TXIC_Pos 5U -#define UART_UARTICR_TXIC_Msk (1U << UART_UARTICR_TXIC_Pos) -#define UART_UARTICR_TXIC UART_UARTICR_TXIC_Msk -#define UART_UARTICR_RXIC_Pos 4U -#define UART_UARTICR_RXIC_Msk (1U << UART_UARTICR_RXIC_Pos) -#define UART_UARTICR_RXIC UART_UARTICR_RXIC_Msk -#define UART_UARTICR_DSRMIC_Pos 3U -#define UART_UARTICR_DSRMIC_Msk (1U << UART_UARTICR_DSRMIC_Pos) -#define UART_UARTICR_DSRMIC UART_UARTICR_DSRMIC_Msk -#define UART_UARTICR_DCDMIC_Pos 2U -#define UART_UARTICR_DCDMIC_Msk (1U << UART_UARTICR_DCDMIC_Pos) -#define UART_UARTICR_DCDMIC UART_UARTICR_DCDMIC_Msk -#define UART_UARTICR_CTSMIC_Pos 1U -#define UART_UARTICR_CTSMIC_Msk (1U << UART_UARTICR_CTSMIC_Pos) -#define UART_UARTICR_CTSMIC UART_UARTICR_CTSMIC_Msk -#define UART_UARTICR_RIMIC_Pos 0U -#define UART_UARTICR_RIMIC_Msk (1U << UART_UARTICR_RIMIC_Pos) -#define UART_UARTICR_RIMIC UART_UARTICR_RIMIC_Msk - -#define UART_UARTDMACR_DMAONERR_Pos 2U -#define UART_UARTDMACR_DMAONERR_Msk (1U << UART_UARTDMACR_DMAONERR_Pos) -#define UART_UARTDMACR_DMAONERR UART_UARTDMACR_DMAONERR_Msk -#define UART_UARTDMACR_TXDMAE_Pos 1U -#define UART_UARTDMACR_TXDMAE_Msk (1U << UART_UARTDMACR_TXDMAE_Pos) -#define UART_UARTDMACR_TXDMAE UART_UARTDMACR_TXDMAE_Msk -#define UART_UARTDMACR_RXDMAE_Pos 0U -#define UART_UARTDMACR_RXDMAE_Msk (1U << UART_UARTDMACR_RXDMAE_Pos) -#define UART_UARTDMACR_RXDMAE UART_UARTDMACR_RXDMAE_Msk -/** @} */ - -/** - * @name RTC bits definitions - * @{ - */ -#define RTC_CLKDIV_M1_Pos 0U -#define RTC_CLKDIV_M1_Msk (0xFFFFU << RTC_CLKDIV_M1_Pos) -#define RTC_CLKDIV_M1 RTC_CLKDIV_M1_Msk - -#define RTC_SETUP_0_YEAR_Pos 12U -#define RTC_SETUP_0_YEAR_Msk (0xFFFU << RTC_SETUP_0_YEAR_Pos) -#define RTC_SETUP_0_YEAR(n) ((n) << RTC_SETUP_0_YEAR_Pos) -#define RTC_SETUP_0_MONTH_Pos 8U -#define RTC_SETUP_0_MONTH_Msk (0xFU << RTC_SETUP_0_MONTH_Pos) -#define RTC_SETUP_0_MONTH(n) ((n) << RTC_SETUP_0_MONTH_Pos) -#define RTC_SETUP_0_DAY_Pos 0U -#define RTC_SETUP_0_DAY_Msk (0x1FU << RTC_SETUP_0_DAY_Pos) -#define RTC_SETUP_0_DAY(n) ((n) << RTC_SETUP_0_DAY_Pos) - -#define RTC_SETUP_1_DOTW_Pos 24U -#define RTC_SETUP_1_DOTW_Msk (0x7U << RTC_SETUP_1_DOTW_Pos) -#define RTC_SETUP_1_DOTW(n) ((n) << RTC_SETUP_1_DOTW_Pos) -#define RTC_SETUP_1_HOUR_Pos 16U -#define RTC_SETUP_1_HOUR_Msk (0x1FU << RTC_SETUP_1_HOUR_Pos) -#define RTC_SETUP_1_HOUR(n) ((n) << RTC_SETUP_1_HOUR_Pos) -#define RTC_SETUP_1_MIN_Pos 8U -#define RTC_SETUP_1_MIN_Msk (0x3FU << RTC_SETUP_1_MIN_Pos) -#define RTC_SETUP_1_MIN(n) ((n) << RTC_SETUP_1_MIN_Pos) -#define RTC_SETUP_1_SEC_Pos 0U -#define RTC_SETUP_1_SEC_Msk (0x3FU << RTC_SETUP_1_SEC_Pos) -#define RTC_SETUP_1_SEC(n) ((n) << RTC_SETUP_1_SEC_Pos) - -#define RTC_CTRL_FORCE_NOTLEAPYEAR_Pos 8U -#define RTC_CTRL_FORCE_NOTLEAPYEAR_Msk (1U << RTC_CTRL_FORCE_NOTLEAPYEAR_Pos) -#define RTC_CTRL_FORCE_NOTLEAPYEAR RTC_CTRL_FORCE_NOTLEAPYEAR_Msk - -#define RTC_CTRL_LOAD_Pos 4U -#define RTC_CTRL_LOAD_Msk (1U << RTC_CTRL_LOAD_Pos) -#define RTC_CTRL_LOAD RTC_CTRL_LOAD_Msk - -#define RTC_CTRL_RTC_ACTIVE_Pos 1U -#define RTC_CTRL_RTC_ACTIVE_Msk (1U << RTC_CTRL_RTC_ACTIVE_Pos) -#define RTC_CTRL_RTC_ACTIVE RTC_CTRL_RTC_ACTIVE_Msk - -#define RTC_CTRL_RTC_ENABLE_Pos 0U -#define RTC_CTRL_RTC_ENABLE_Msk (1U << RTC_CTRL_RTC_ENABLE_Pos) -#define RTC_CTRL_RTC_ENABLE RTC_CTRL_RTC_ENABLE_Msk - -#define RTC_IRQ_SETUP_0_MATCH_ACTIVE_Pos 29U -#define RTC_IRQ_SETUP_0_MATCH_ACTIVE_Msk (1U << RTC_IRQ_SETUP_0_MATCH_ACTIVE_Pos) -#define RTC_IRQ_SETUP_0_MATCH_ACTIVE RTC_IRQ_SETUP_0_MATCH_ACTIVE_Msk -#define RTC_IRQ_SETUP_0_MATCH_ENA_Pos 28U -#define RTC_IRQ_SETUP_0_MATCH_ENA_Msk (1U << RTC_IRQ_SETUP_0_MATCH_ENA_Pos) -#define RTC_IRQ_SETUP_0_MATCH_ENA RTC_IRQ_SETUP_0_MATCH_ENA_Msk -#define RTC_IRQ_SETUP_0_YEAR_ENA_Pos 26U -#define RTC_IRQ_SETUP_0_YEAR_ENA_Msk (1U << RTC_IRQ_SETUP_0_YEAR_ENA_Pos) -#define RTC_IRQ_SETUP_0_YEAR_ENA RTC_IRQ_SETUP_0_YEAR_ENA_Msk -#define RTC_IRQ_SETUP_0_MONTH_ENA_Pos 25U -#define RTC_IRQ_SETUP_0_MONTH_ENA_Msk (1U << RTC_IRQ_SETUP_0_MONTH_ENA_Pos) -#define RTC_IRQ_SETUP_0_MONTH_ENA RTC_IRQ_SETUP_0_MONTH_ENA_Msk -#define RTC_IRQ_SETUP_0_DAY_ENA_Pos 24U -#define RTC_IRQ_SETUP_0_DAY_ENA_Msk (1U << RTC_IRQ_SETUP_0_DAY_ENA_Pos) -#define RTC_IRQ_SETUP_0_DAY_ENA RTC_IRQ_SETUP_0_DAY_ENA_Msk - -#define RTC_IRQ_SETUP_0_YEAR_Pos 12U -#define RTC_IRQ_SETUP_0_YEAR_Msk (0xFFFU << RTC_IRQ_SETUP_0_YEAR_Pos) -#define RTC_IRQ_SETUP_0_YEAR(n) ((n) << RTC_IRQ_SETUP_0_YEAR_Pos) -#define RTC_IRQ_SETUP_0_MONTH_Pos 8U -#define RTC_IRQ_SETUP_0_MONTH_Msk (0xFU << RTC_IRQ_SETUP_0_MONTH_Pos) -#define RTC_IRQ_SETUP_0_MONTH(n) ((n) << RTC_IRQ_SETUP_0_MONTH_Pos) -#define RTC_IRQ_SETUP_0_DAY_Pos 0U -#define RTC_IRQ_SETUP_0_DAY_Msk (0x1FU << RTC_IRQ_SETUP_0_DAY_Pos) -#define RTC_IRQ_SETUP_0_DAY(n) ((n) << RTC_IRQ_SETUP_0_DAY_Pos) - -#define RTC_IRQ_SETUP_1_DOTW_ENA_Pos 31U -#define RTC_IRQ_SETUP_1_DOTW_ENA_Msk (1U << RTC_IRQ_SETUP_1_DOTW_ENA_Pos) -#define RTC_IRQ_SETUP_1_DOTW_ENA RTC_IRQ_SETUP_1_DOTW_ENA_Msk -#define RTC_IRQ_SETUP_1_HOUR_ENA_Pos 30U -#define RTC_IRQ_SETUP_1_HOUR_ENA_Msk (1U << RTC_IRQ_SETUP_1_HOUR_ENA_Pos) -#define RTC_IRQ_SETUP_1_HOUR_ENA RTC_IRQ_SETUP_1_HOUR_ENA_Msk -#define RTC_IRQ_SETUP_1_MIN_ENA_Pos 29U -#define RTC_IRQ_SETUP_1_MIN_ENA_Msk (1U << RTC_IRQ_SETUP_1_MIN_ENA_Pos) -#define RTC_IRQ_SETUP_1_MIN_ENA RTC_IRQ_SETUP_1_MIN_ENA_Msk -#define RTC_IRQ_SETUP_1_SEC_ENA_Pos 28U -#define RTC_IRQ_SETUP_1_SEC_ENA_Msk (1U << RTC_IRQ_SETUP_1_SEC_ENA_Pos) -#define RTC_IRQ_SETUP_1_SEC_ENA RTC_IRQ_SETUP_1_SEC_ENA_Msk - -#define RTC_IRQ_SETUP_1_DOTW_Pos 24U -#define RTC_IRQ_SETUP_1_DOTW_Msk (0x7U << RTC_IRQ_SETUP_1_DOTW_Pos) -#define RTC_IRQ_SETUP_1_DOTW(n) ((n) << RTC_IRQ_SETUP_1_DOTW_Pos) -#define RTC_IRQ_SETUP_1_HOUR_Pos 16U -#define RTC_IRQ_SETUP_1_HOUR_Msk (0x1FU << RTC_IRQ_SETUP_1_HOUR_Pos) -#define RTC_IRQ_SETUP_1_HOUR(n) ((n) << RTC_IRQ_SETUP_1_HOUR_Pos) -#define RTC_IRQ_SETUP_1_MIN_Pos 8U -#define RTC_IRQ_SETUP_1_MIN_Msk (0x3FU << RTC_IRQ_SETUP_1_MIN_Pos) -#define RTC_IRQ_SETUP_1_MIN(n) ((n) << RTC_IRQ_SETUP_1_MIN_Pos) -#define RTC_IRQ_SETUP_1_SEC_Pos 0U -#define RTC_IRQ_SETUP_1_SEC_Msk (0x3FU << RTC_IRQ_SETUP_1_SEC_Pos) -#define RTC_IRQ_SETUP_1_SEC(n) ((n) << RTC_IRQ_SETUP_1_SEC_Pos) - -#define RTC_INTR_RTC_Pos 0U -#define RTC_INTR_RTC_Msk (1U << RTC_INTR_RTC_Pos) -#define RTC_INTR_RTC RTC_INTR_RTC_Msk - -#define RTC_INTE_RTC_Pos 0U -#define RTC_INTE_RTC_Msk (1U << RTC_INTE_RTC_Pos) -#define RTC_INTE_RTC RTC_INTE_RTC_Msk - -#define RTC_INTF_RTC_Pos 0U -#define RTC_INTF_RTC_Msk (1U << RTC_INTF_RTC_Pos) -#define RTC_INTF_RTC RTC_INTF_RTC_Msk - -#define RTC_INTS_RTC_Pos 0U -#define RTC_INTS_RTC_Msk (1U << RTC_INTS_RTC_Pos) -#define RTC_INTS_RTC RTC_INTS_RTC_Msk - -/* Normalisation of RTC0 & RTC1 fields read from RTC. */ -#define RTC_RTC_1_YEAR_Pos 12U -#define RTC_RTC_1_YEAR_Msk (0xFFFU << RTC_RTC_1_YEAR_Pos) -#define RTC_RTC_1_YEAR(n) ((n & RTC_RTC_1_YEAR_Msk) >> \ - RTC_RTC_1_YEAR_Pos) -#define RTC_RTC_1_MONTH_Pos 8U -#define RTC_RTC_1_MONTH_Msk (0xFU << RTC_RTC_1_MONTH_Pos) -#define RTC_RTC_1_MONTH(n) ((n & RTC_RTC_1_MONTH_Msk) >> \ - RTC_RTC_1_MONTH_Pos) -#define RTC_RTC_1_DAY_Pos 0U -#define RTC_RTC_1_DAY_Msk (0x1FU << RTC_RTC_1_DAY_Pos) -#define RTC_RTC_1_DAY(n) ((n & RTC_RTC_1_DAY_Msk) >> \ - RTC_RTC_1_DAY_Pos) -#define RTC_RTC_0_DOTW_Pos 24U -#define RTC_RTC_0_DOTW_Msk (0x7U << RTC_RTC_0_DOTW_Pos) -#define RTC_RTC_0_DOTW(n) ((n & RTC_RTC_0_DOTW_Msk) >> \ - RTC_RTC_0_DOTW_Pos) -#define RTC_RTC_0_HOUR_Pos 16U -#define RTC_RTC_0_HOUR_Msk (0x1FU << RTC_RTC_0_HOUR_Pos) -#define RTC_RTC_0_HOUR(n) ((n & RTC_RTC_0_HOUR_Msk) >> \ - RTC_RTC_0_HOUR_Pos) -#define RTC_RTC_0_MIN_Pos 8U -#define RTC_RTC_0_MIN_Msk (0x3FU << RTC_RTC_0_MIN_Pos) -#define RTC_RTC_0_MIN(n) ((n & RTC_RTC_0_MIN_Msk) >> \ - RTC_RTC_0_MIN_Pos) -#define RTC_RTC_0_SEC_Pos 0U -#define RTC_RTC_0_SEC_Msk (0x3FU << RTC_RTC_0_SEC_Pos) -#define RTC_RTC_0_SEC(n) ((n & RTC_RTC_0_SEC_Msk) >> \ - RTC_RTC_0_SEC_Pos) -/** @} */ - -/** - * @name WATCHDOG bits definitions - * @{ - */ -#define WATCHDOG_CTRL_TRIGGER_Pos 31U -#define WATCHDOG_CTRL_TRIGGER_Msk (1U << WATCHDOG_CTRL_TRIGGER_Pos) -#define WATCHDOG_CTRL_TRIGGER WATCHDOG_CTRL_TRIGGER_Msk -#define WATCHDOG_CTRL_ENABLE_Pos 30U -#define WATCHDOG_CTRL_ENABLE_Msk (1U << WATCHDOG_CTRL_ENABLE_Pos) -#define WATCHDOG_CTRL_ENABLE WATCHDOG_CTRL_ENABLE_Msk -#define WATCHDOG_CTRL_PAUSE_DBG1_Pos 26U -#define WATCHDOG_CTRL_PAUSE_DBG1_Msk (1U << WATCHDOG_CTRL_PAUSE_DBG1_Pos) -#define WATCHDOG_CTRL_PAUSE_DBG1 WATCHDOG_CTRL_PAUSE_DBG1_Msk -#define WATCHDOG_CTRL_PAUSE_DBG0_Pos 25U -#define WATCHDOG_CTRL_PAUSE_DBG0_Msk (1U << WATCHDOG_CTRL_PAUSE_DBG0_Pos) -#define WATCHDOG_CTRL_PAUSE_DBG0 WATCHDOG_CTRL_PAUSE_DBG0_Msk -#define WATCHDOG_CTRL_PAUSE_JTAG_Pos 24U -#define WATCHDOG_CTRL_PAUSE_JTAG_Msk (1U << WATCHDOG_CTRL_PAUSE_JTAG_Pos) -#define WATCHDOG_CTRL_PAUSE_JTAG WATCHDOG_CTRL_PAUSE_JTAG_Msk -#define WATCHDOG_CTRL_TIME_Pos 0U -#define WATCHDOG_CTRL_TIME_Msk (0xFFFFFFU << WATCHDOG_CTRL_TIME_Pos) -#define WATCHDOG_CTRL_TIME WATCHDOG_CTRL_TIME_Msk - -#define WATCHDOG_LOAD_Pos 0U -#define WATCHDOG_LOAD_Msk (0xFFFFFFU << WATCHDOG_LOAD_Pos) -#define WATCHDOG_LOAD WATCHDOG_LOAD_Msk - -#define WATCHDOG_REASON_FORCE_Pos 1U -#define WATCHDOG_REASON_FORCE_Msk (1U << WATCHDOG_REASON_FORCE_Pos) -#define WATCHDOG_REASON_FORCE WATCHDOG_REASON_FORCE_Msk -#define WATCHDOG_REASON_TIMER_Pos 0U -#define WATCHDOG_REASON_TIMER_Msk (1U << WATCHDOG_REASON_TIMER_Pos) -#define WATCHDOG_REASON_TIMER WATCHDOG_REASON_TIMER_Msk - -#define WATCHDOG_TICK_COUNT_Pos 11U -#define WATCHDOG_TICK_COUNT_Msk (0xFF800U << WATCHDOG_TICK_COUNT_Pos) -#define WATCHDOG_TICK_COUNT WATCHDOG_TICK_COUNT_Msk -#define WATCHDOG_TICK_RUNNING_Pos 10U -#define WATCHDOG_TICK_RUNNING_Msk (1U << WATCHDOG_TICK_RUNNING_Pos) -#define WATCHDOG_TICK_RUNNING WATCHDOG_TICK_RUNNING_Msk -#define WATCHDOG_TICK_ENABLE_Pos 9U -#define WATCHDOG_TICK_ENABLE_Msk (1U << WATCHDOG_TICK_ENABLE_Pos) -#define WATCHDOG_TICK_ENABLE WATCHDOG_TICK_ENABLE_Msk -#define WATCHDOG_TICK_CYCLES_Pos 0U -#define WATCHDOG_TICK_CYCLES_Msk (0x1FFU << WATCHDOG_TICK_CYCLES_Pos) -#define WATCHDOG_TICK_CYCLES WATCHDOG_TICK_CYCLES_Msk -/** @} */ - -/** - * @name I2C bits definitions - * @{ - */ -#define I2C_IC_CON_STOP_DET_IF_MASTER_ACTIVE_Pos 10U -#define I2C_IC_CON_STOP_DET_IF_MASTER_ACTIVE_Msk (1U << I2C_IC_CON_STOP_DET_IF_MASTER_ACTIVE_Pos) -#define I2C_IC_CON_STOP_DET_IF_MASTER_ACTIVE I2C_IC_CON_STOP_DET_IF_MASTER_ACTIVE_Msk -#define I2C_IC_CON_RX_FIFO_FULL_HLD_CTRL_Pos 9U -#define I2C_IC_CON_RX_FIFO_FULL_HLD_CTRL_Msk (1U << I2C_IC_CON_RX_FIFO_FULL_HLD_CTRL_Pos) -#define I2C_IC_CON_RX_FIFO_FULL_HLD_CTRL I2C_IC_CON_RX_FIFO_FULL_HLD_CTRL_Msk -#define I2C_IC_CON_TX_EMPTY_CTRL_Pos 8U -#define I2C_IC_CON_TX_EMPTY_CTRL_Msk (1U << I2C_IC_CON_TX_EMPTY_CTRL_Pos) -#define I2C_IC_CON_TX_EMPTY_CTRL I2C_IC_CON_TX_EMPTY_CTRL_Msk -#define I2C_IC_CON_STOP_DET_IFADDRESSED_Pos 7U -#define I2C_IC_CON_STOP_DET_IFADDRESSED_Msk (1U << I2C_IC_CON_STOP_DET_IFADDRESSED_Pos) -#define I2C_IC_CON_STOP_DET_IFADDRESSED I2C_IC_CON_STOP_DET_IFADDRESSED_Msk -#define I2C_IC_CON_IC_SLAVE_DISABLE_Pos 6U -#define I2C_IC_CON_IC_SLAVE_DISABLE_Msk (1U << I2C_IC_CON_IC_SLAVE_DISABLE_Pos) -#define I2C_IC_CON_IC_SLAVE_DISABLE I2C_IC_CON_IC_SLAVE_DISABLE_Msk -#define I2C_IC_CON_IC_RESTART_EN_Pos 5U -#define I2C_IC_CON_IC_RESTART_EN_Msk (1U << I2C_IC_CON_IC_RESTART_EN_Pos) -#define I2C_IC_CON_IC_RESTART_EN I2C_IC_CON_IC_RESTART_EN_Msk -#define I2C_IC_CON_IC_10BITADDR_MASTER_Pos 4U -#define I2C_IC_CON_IC_10BITADDR_MASTER_Msk (1U << I2C_IC_CON_IC_10BITADDR_MASTER_Pos) -#define I2C_IC_CON_IC_10BITADDR_MASTER I2C_IC_CON_IC_10BITADDR_MASTER_Msk -#define I2C_IC_CON_IC_10BITADDR_SLAVE_Pos 3U -#define I2C_IC_CON_IC_10BITADDR_SLAVE_Msk (1U << I2C_IC_CON_IC_10BITADDR_SLAVE_Pos) -#define I2C_IC_CON_IC_10BITADDR_SLAVE I2C_IC_CON_IC_10BITADDR_SLAVE_Msk -#define I2C_IC_CON_SPEED_Pos 1U -#define I2C_IC_CON_SPEED_Msk (3U << I2C_IC_CON_SPEED_Pos) -#define I2C_IC_CON_SPEED I2C_IC_CON_SPEED_Msk -#define I2C_IC_CON_MASTER_MODE_Pos 0U -#define I2C_IC_CON_MASTER_MODE_Msk (1U << I2C_IC_CON_MASTER_MODE_Pos) -#define I2C_IC_CON_MASTER_MODE I2C_IC_CON_MASTER_MODE_Msk - -#define I2C_IC_TAR_SPECIAL_Pos 11U -#define I2C_IC_TAR_SPECIAL_Msk (1U << I2C_IC_TAR_SPECIAL_Pos) -#define I2C_IC_TAR_SPECIAL I2C_IC_TAR_SPECIAL_Msk -#define I2C_IC_TAR_GC_OR_START_Pos 10U -#define I2C_IC_TAR_GC_OR_START_Msk (1U << I2C_IC_TAR_GC_OR_START_Pos) -#define I2C_IC_TAR_GC_OR_START I2C_IC_TAR_GC_OR_START_Msk -#define I2C_IC_TAR_IC_TAR_Pos 0U -#define I2C_IC_TAR_IC_TAR_Msk (0x3FFU << I2C_IC_TAR_IC_TAR_Pos) -#define I2C_IC_TAR_IC_TAR I2C_IC_TAR_IC_TAR_Msk - -#define I2C_IC_SAR_IC_SAR_Pos 0U -#define I2C_IC_SAR_IC_SAR_Msk (0x3FFU << I2C_IC_SAR_IC_SAR_Pos) -#define I2C_IC_SAR_IC_SAR I2C_IC_SAR_IC_SAR_Msk - -#define I2C_IC_DATA_CMD_FIRST_DATA_BYTE_Pos 11U -#define I2C_IC_DATA_CMD_FIRST_DATA_BYTE_Msk (1U << I2C_IC_DATA_CMD_FIRST_DATA_BYTE_Pos) -#define I2C_IC_DATA_CMD_FIRST_DATA_BYTE I2C_IC_DATA_CMD_FIRST_DATA_BYTE_Msk -#define I2C_IC_DATA_CMD_RESTART_Pos 10U -#define I2C_IC_DATA_CMD_RESTART_Msk (1U << I2C_IC_DATA_CMD_RESTART_Pos) -#define I2C_IC_DATA_CMD_RESTART I2C_IC_DATA_CMD_RESTART_Msk -#define I2C_IC_DATA_CMD_STOP_Pos 9U -#define I2C_IC_DATA_CMD_STOP_Msk (1U << I2C_IC_DATA_CMD_STOP_Pos) -#define I2C_IC_DATA_CMD_STOP I2C_IC_DATA_CMD_STOP_Msk -#define I2C_IC_DATA_CMD_CMD_Pos 8U -#define I2C_IC_DATA_CMD_CMD_Msk (1U << I2C_IC_DATA_CMD_CMD_Pos) -#define I2C_IC_DATA_CMD_CMD I2C_IC_DATA_CMD_CMD_Msk -#define I2C_IC_DATA_CMD_DAT_Pos 0U -#define I2C_IC_DATA_CMD_DAT_Msk (0xFFU << I2C_IC_DATA_CMD_DAT_Pos) -#define I2C_IC_DATA_CMD_DAT I2C_IC_DATA_CMD_DAT_Msk - -#define I2C_IC_SS_SCL_HCNT_Pos 0U -#define I2C_IC_SS_SCL_HCNT_Msk (0xFFFFU << I2C_IC_SS_SCL_HCNT_Pos) -#define I2C_IC_SS_SCL_HCNT I2C_IC_SS_SCL_HCNT_Msk - -#define I2C_IC_SS_SCL_LCNT_Pos 0U -#define I2C_IC_SS_SCL_LCNT_Msk (0xFFFFU << I2C_IC_SS_SCL_LCNT_Pos) -#define I2C_IC_SS_SCL_LCNT I2C_IC_SS_SCL_LCNT_Msk - -#define I2C_IC_SS_SCL_HCNT_IC_SS_SCL_HCNT_Pos 0U -#define I2C_IC_SS_SCL_HCNT_IC_SS_SCL_HCNT_Msk (0xFFFFU << I2C_IC_SS_SCL_HCNT_IC_SS_SCL_HCNT_Pos) -#define I2C_IC_SS_SCL_HCNT_IC_SS_SCL_HCNT I2C_IC_SS_SCL_HCNT_IC_SS_SCL_HCNT_Msk - -#define I2C_IC_SS_SCL_LCNT_IC_SS_SCL_LCNT_Pos 0U -#define I2C_IC_SS_SCL_LCNT_IC_SS_SCL_LCNT_Msk (0xFFFFU << I2C_IC_SS_SCL_LCNT_IC_SS_SCL_LCNT_Pos) -#define I2C_IC_SS_SCL_LCNT_IC_SS_SCL_LCNT I2C_IC_SS_SCL_LCNT_IC_SS_SCL_LCNT_Msk - -#define I2C_IC_FS_SCL_HCNT_Pos 0U -#define I2C_IC_FS_SCL_HCNT_Msk (0xFFFFU << I2C_IC_FS_SCL_HCNT_Pos) -#define I2C_IC_FS_SCL_HCNT I2C_IC_FS_SCL_HCNT_Msk - -#define I2C_IC_FS_SCL_LCNT_Pos 0U -#define I2C_IC_FS_SCL_LCNT_Msk (0xFFFFU << I2C_IC_FS_SCL_LCNT_Pos) -#define I2C_IC_FS_SCL_LCNT I2C_IC_FS_SCL_LCNT_Msk - -#define I2C_IC_FS_SCL_HCNT_IC_FS_SCL_HCNT_Pos 0U -#define I2C_IC_FS_SCL_HCNT_IC_FS_SCL_HCNT_Msk (0xFFFFU << I2C_IC_FS_SCL_HCNT_IC_FS_SCL_HCNT_Pos) -#define I2C_IC_FS_SCL_HCNT_IC_FS_SCL_HCNT I2C_IC_FS_SCL_HCNT_IC_FS_SCL_HCNT_Msk - -#define I2C_IC_FS_SCL_LCNT_IC_FS_SCL_LCNT_Pos 0U -#define I2C_IC_FS_SCL_LCNT_IC_FS_SCL_LCNT_Msk (0xFFFFU << I2C_IC_FS_SCL_LCNT_IC_FS_SCL_LCNT_Pos) -#define I2C_IC_FS_SCL_LCNT_IC_FS_SCL_LCNT I2C_IC_FS_SCL_LCNT_IC_FS_SCL_LCNT_Msk - -#define I2C_IC_INTR_STAT_R_MASTER_ON_HOLD_Pos 13U -#define I2C_IC_INTR_STAT_R_MASTER_ON_HOLD_Msk (1U << I2C_IC_INTR_STAT_R_MASTER_ON_HOLD_Pos) -#define I2C_IC_INTR_STAT_R_MASTER_ON_HOLD I2C_IC_INTR_STAT_R_MASTER_ON_HOLD_Msk -#define I2C_IC_INTR_STAT_R_RESTART_DET_Pos 12U -#define I2C_IC_INTR_STAT_R_RESTART_DET_Msk (1U << I2C_IC_INTR_STAT_R_RESTART_DET_Pos) -#define I2C_IC_INTR_STAT_R_RESTART_DET I2C_IC_INTR_STAT_R_RESTART_DET_Msk -#define I2C_IC_INTR_STAT_R_GEN_CALL_Pos 11U -#define I2C_IC_INTR_STAT_R_GEN_CALL_Msk (1U << I2C_IC_INTR_STAT_R_GEN_CALL_Pos) -#define I2C_IC_INTR_STAT_R_GEN_CALL I2C_IC_INTR_STAT_R_GEN_CALL_Msk -#define I2C_IC_INTR_STAT_R_START_DET_Pos 10U -#define I2C_IC_INTR_STAT_R_START_DET_Msk (1U << I2C_IC_INTR_STAT_R_START_DET_Pos) -#define I2C_IC_INTR_STAT_R_START_DET I2C_IC_INTR_STAT_R_START_DET_Msk -#define I2C_IC_INTR_STAT_R_STOP_DET_Pos 9U -#define I2C_IC_INTR_STAT_R_STOP_DET_Msk (1U << I2C_IC_INTR_STAT_R_STOP_DET_Pos) -#define I2C_IC_INTR_STAT_R_STOP_DET I2C_IC_INTR_STAT_R_STOP_DET_Msk -#define I2C_IC_INTR_STAT_R_ACTIVITY_Pos 8U -#define I2C_IC_INTR_STAT_R_ACTIVITY_Msk (1U << I2C_IC_INTR_STAT_R_ACTIVITY_Pos) -#define I2C_IC_INTR_STAT_R_ACTIVITY I2C_IC_INTR_STAT_R_ACTIVITY_Msk -#define I2C_IC_INTR_STAT_R_RX_DONE_Pos 7U -#define I2C_IC_INTR_STAT_R_RX_DONE_Msk (1U << I2C_IC_INTR_STAT_R_RX_DONE_Pos) -#define I2C_IC_INTR_STAT_R_RX_DONE I2C_IC_INTR_STAT_R_RX_DONE_Msk -#define I2C_IC_INTR_STAT_R_TX_ABRT_Pos 6U -#define I2C_IC_INTR_STAT_R_TX_ABRT_Msk (1U << I2C_IC_INTR_STAT_R_TX_ABRT_Pos) -#define I2C_IC_INTR_STAT_R_TX_ABRT I2C_IC_INTR_STAT_R_TX_ABRT_Msk -#define I2C_IC_INTR_STAT_R_RD_REQ_Pos 5U -#define I2C_IC_INTR_STAT_R_RD_REQ_Msk (1U << I2C_IC_INTR_STAT_R_RD_REQ_Pos) -#define I2C_IC_INTR_STAT_R_RD_REQ I2C_IC_INTR_STAT_R_RD_REQ_Msk -#define I2C_IC_INTR_STAT_R_TX_EMPTY_Pos 4U -#define I2C_IC_INTR_STAT_R_TX_EMPTY_Msk (1U << I2C_IC_INTR_STAT_R_TX_EMPTY_Pos) -#define I2C_IC_INTR_STAT_R_TX_EMPTY I2C_IC_INTR_STAT_R_TX_EMPTY_Msk -#define I2C_IC_INTR_STAT_R_TX_OVER_Pos 3U -#define I2C_IC_INTR_STAT_R_TX_OVER_Msk (1U << I2C_IC_INTR_STAT_R_TX_OVER_Pos) -#define I2C_IC_INTR_STAT_R_TX_OVER I2C_IC_INTR_STAT_R_TX_OVER_Msk -#define I2C_IC_INTR_STAT_R_RX_FULL_Pos 2U -#define I2C_IC_INTR_STAT_R_RX_FULL_Msk (1U << I2C_IC_INTR_STAT_R_RX_FULL_Pos) -#define I2C_IC_INTR_STAT_R_RX_FULL I2C_IC_INTR_STAT_R_RX_FULL_Msk -#define I2C_IC_INTR_STAT_R_RX_OVER_Pos 1U -#define I2C_IC_INTR_STAT_R_RX_OVER_Msk (1U << I2C_IC_INTR_STAT_R_RX_OVER_Pos) -#define I2C_IC_INTR_STAT_R_RX_OVER I2C_IC_INTR_STAT_R_RX_OVER_Msk -#define I2C_IC_INTR_STAT_R_RX_UNDER_Pos 0U -#define I2C_IC_INTR_STAT_R_RX_UNDER_Msk (1U << I2C_IC_INTR_STAT_R_RX_UNDER_Pos) -#define I2C_IC_INTR_STAT_R_RX_UNDER I2C_IC_INTR_STAT_R_RX_UNDER_Msk - -#define I2C_IC_INTR_MASK_M_MASTER_ON_HOLD_Pos 13U -#define I2C_IC_INTR_MASK_M_MASTER_ON_HOLD_Msk (1U << I2C_IC_INTR_MASK_M_MASTER_ON_HOLD_Pos) -#define I2C_IC_INTR_MASK_M_MASTER_ON_HOLD I2C_IC_INTR_MASK_M_MASTER_ON_HOLD_Msk -#define I2C_IC_INTR_MASK_M_MASTER_ON_HOLD_READ_ONLY I2C_IC_INTR_MASK_M_MASTER_ON_HOLD -#define I2C_IC_INTR_MASK_M_RESTART_DET_Pos 12U -#define I2C_IC_INTR_MASK_M_RESTART_DET_Msk (1U << I2C_IC_INTR_MASK_M_RESTART_DET_Pos) -#define I2C_IC_INTR_MASK_M_RESTART_DET I2C_IC_INTR_MASK_M_RESTART_DET_Msk -#define I2C_IC_INTR_MASK_M_GEN_CALL_Pos 11U -#define I2C_IC_INTR_MASK_M_GEN_CALL_Msk (1U << I2C_IC_INTR_MASK_M_GEN_CALL_Pos) -#define I2C_IC_INTR_MASK_M_GEN_CALL I2C_IC_INTR_MASK_M_GEN_CALL_Msk -#define I2C_IC_INTR_MASK_M_START_DET_Pos 10U -#define I2C_IC_INTR_MASK_M_START_DET_Msk (1U << I2C_IC_INTR_MASK_M_START_DET_Pos) -#define I2C_IC_INTR_MASK_M_START_DET I2C_IC_INTR_MASK_M_START_DET_Msk -#define I2C_IC_INTR_MASK_M_STOP_DET_Pos 9U -#define I2C_IC_INTR_MASK_M_STOP_DET_Msk (1U << I2C_IC_INTR_MASK_M_STOP_DET_Pos) -#define I2C_IC_INTR_MASK_M_STOP_DET I2C_IC_INTR_MASK_M_STOP_DET_Msk -#define I2C_IC_INTR_MASK_M_ACTIVITY_Pos 8U -#define I2C_IC_INTR_MASK_M_ACTIVITY_Msk (1U << I2C_IC_INTR_MASK_M_ACTIVITY_Pos) -#define I2C_IC_INTR_MASK_M_ACTIVITY I2C_IC_INTR_MASK_M_ACTIVITY_Msk -#define I2C_IC_INTR_MASK_M_RX_DONE_Pos 7U -#define I2C_IC_INTR_MASK_M_RX_DONE_Msk (1U << I2C_IC_INTR_MASK_M_RX_DONE_Pos) -#define I2C_IC_INTR_MASK_M_RX_DONE I2C_IC_INTR_MASK_M_RX_DONE_Msk -#define I2C_IC_INTR_MASK_M_TX_ABRT_Pos 6U -#define I2C_IC_INTR_MASK_M_TX_ABRT_Msk (1U << I2C_IC_INTR_MASK_M_TX_ABRT_Pos) -#define I2C_IC_INTR_MASK_M_TX_ABRT I2C_IC_INTR_MASK_M_TX_ABRT_Msk -#define I2C_IC_INTR_MASK_M_RD_REQ_Pos 5U -#define I2C_IC_INTR_MASK_M_RD_REQ_Msk (1U << I2C_IC_INTR_MASK_M_RD_REQ_Pos) -#define I2C_IC_INTR_MASK_M_RD_REQ I2C_IC_INTR_MASK_M_RD_REQ_Msk -#define I2C_IC_INTR_MASK_M_TX_EMPTY_Pos 4U -#define I2C_IC_INTR_MASK_M_TX_EMPTY_Msk (1U << I2C_IC_INTR_MASK_M_TX_EMPTY_Pos) -#define I2C_IC_INTR_MASK_M_TX_EMPTY I2C_IC_INTR_MASK_M_TX_EMPTY_Msk -#define I2C_IC_INTR_MASK_M_TX_OVER_Pos 3U -#define I2C_IC_INTR_MASK_M_TX_OVER_Msk (1U << I2C_IC_INTR_MASK_M_TX_OVER_Pos) -#define I2C_IC_INTR_MASK_M_TX_OVER I2C_IC_INTR_MASK_M_TX_OVER_Msk -#define I2C_IC_INTR_MASK_M_RX_FULL_Pos 2U -#define I2C_IC_INTR_MASK_M_RX_FULL_Msk (1U << I2C_IC_INTR_MASK_M_RX_FULL_Pos) -#define I2C_IC_INTR_MASK_M_RX_FULL I2C_IC_INTR_MASK_M_RX_FULL_Msk -#define I2C_IC_INTR_MASK_M_RX_OVER_Pos 1U -#define I2C_IC_INTR_MASK_M_RX_OVER_Msk (1U << I2C_IC_INTR_MASK_M_RX_OVER_Pos) -#define I2C_IC_INTR_MASK_M_RX_OVER I2C_IC_INTR_MASK_M_RX_OVER_Msk -#define I2C_IC_INTR_MASK_M_RX_UNDER_Pos 0U -#define I2C_IC_INTR_MASK_M_RX_UNDER_Msk (1U << I2C_IC_INTR_MASK_M_RX_UNDER_Pos) -#define I2C_IC_INTR_MASK_M_RX_UNDER I2C_IC_INTR_MASK_M_RX_UNDER_Msk -#define I2C_IC_RAW_INTR_STAT_MASTER_ON_HOLD_Pos 13U -#define I2C_IC_RAW_INTR_STAT_MASTER_ON_HOLD_Msk (1U << I2C_IC_RAW_INTR_STAT_MASTER_ON_HOLD_Pos) -#define I2C_IC_RAW_INTR_STAT_MASTER_ON_HOLD I2C_IC_RAW_INTR_STAT_MASTER_ON_HOLD_Msk -#define I2C_IC_INTR_STAT_M_RESTART_DET_Pos 12U -#define I2C_IC_INTR_STAT_M_RESTART_DET_Msk (1U << I2C_IC_INTR_STAT_M_RESTART_DET_Pos) -#define I2C_IC_INTR_STAT_M_RESTART_DET I2C_IC_INTR_STAT_M_RESTART_DET_Msk -#define I2C_IC_INTR_STAT_M_GEN_CALL_Pos 11U -#define I2C_IC_INTR_STAT_M_GEN_CALL_Msk (1U << I2C_IC_INTR_STAT_M_GEN_CALL_Pos) -#define I2C_IC_INTR_STAT_M_GEN_CALL I2C_IC_INTR_STAT_M_GEN_CALL_Msk -#define I2C_IC_INTR_STAT_M_START_DET_Pos 10U -#define I2C_IC_INTR_STAT_M_START_DET_Msk (1U << I2C_IC_INTR_STAT_M_START_DET_Pos) -#define I2C_IC_INTR_STAT_M_START_DET I2C_IC_INTR_STAT_M_START_DET_Msk -#define I2C_IC_INTR_STAT_M_STOP_DET_Pos 9U -#define I2C_IC_INTR_STAT_M_STOP_DET_Msk (1U << I2C_IC_INTR_STAT_M_STOP_DET_Pos) -#define I2C_IC_INTR_STAT_M_STOP_DET I2C_IC_INTR_STAT_M_STOP_DET_Msk -#define I2C_IC_INTR_STAT_M_ACTIVITY_Pos 8U -#define I2C_IC_INTR_STAT_M_ACTIVITY_Msk (1U << I2C_IC_INTR_STAT_M_ACTIVITY_Pos) -#define I2C_IC_INTR_STAT_M_ACTIVITY I2C_IC_INTR_STAT_M_ACTIVITY_Msk -#define I2C_IC_INTR_STAT_M_RX_DONE_Pos 7U -#define I2C_IC_INTR_STAT_M_RX_DONE_Msk (1U << I2C_IC_INTR_STAT_M_RX_DONE_Pos) -#define I2C_IC_INTR_STAT_M_RX_DONE I2C_IC_INTR_STAT_M_RX_DONE_Msk -#define I2C_IC_INTR_STAT_M_TX_ABRT_Pos 6U -#define I2C_IC_INTR_STAT_M_TX_ABRT_Msk (1U << I2C_IC_INTR_STAT_M_TX_ABRT_Pos) -#define I2C_IC_INTR_STAT_M_TX_ABRT I2C_IC_INTR_STAT_M_TX_ABRT_Msk -#define I2C_IC_INTR_STAT_M_RD_REQ_Pos 5U -#define I2C_IC_INTR_STAT_M_RD_REQ_Msk (1U << I2C_IC_INTR_STAT_M_RD_REQ_Pos) -#define I2C_IC_INTR_STAT_M_RD_REQ I2C_IC_INTR_STAT_M_RD_REQ_Msk -#define I2C_IC_INTR_STAT_M_TX_EMPTY_Pos 4U -#define I2C_IC_INTR_STAT_M_TX_EMPTY_Msk (1U << I2C_IC_INTR_STAT_M_TX_EMPTY_Pos) -#define I2C_IC_INTR_STAT_M_TX_EMPTY I2C_IC_INTR_STAT_M_TX_EMPTY_Msk -#define I2C_IC_INTR_STAT_M_TX_OVER_Pos 3U -#define I2C_IC_INTR_STAT_M_TX_OVER_Msk (1U << I2C_IC_INTR_STAT_M_TX_OVER_Pos) -#define I2C_IC_INTR_STAT_M_TX_OVER I2C_IC_INTR_STAT_M_TX_OVER_Msk -#define I2C_IC_INTR_STAT_M_RX_FULL_Pos 2U -#define I2C_IC_INTR_STAT_M_RX_FULL_Msk (1U << I2C_IC_INTR_STAT_M_RX_FULL_Pos) -#define I2C_IC_INTR_STAT_M_RX_FULL I2C_IC_INTR_STAT_M_RX_FULL_Msk -#define I2C_IC_INTR_STAT_M_RX_OVER_Pos 1U -#define I2C_IC_INTR_STAT_M_RX_OVER_Msk (1U << I2C_IC_INTR_STAT_M_RX_OVER_Pos) -#define I2C_IC_INTR_STAT_M_RX_OVER I2C_IC_INTR_STAT_M_RX_OVER_Msk -#define I2C_IC_INTR_STAT_M_RX_UNDER_Pos 0U -#define I2C_IC_INTR_STAT_M_RX_UNDER_Msk (1U << I2C_IC_INTR_STAT_M_RX_UNDER_Pos) -#define I2C_IC_INTR_STAT_M_RX_UNDER I2C_IC_INTR_STAT_M_RX_UNDER_Msk - -#define I2C_IC_RX_TL_RX_TL_Pos 0U -#define I2C_IC_RX_TL_RX_TL_Msk (0xFFU << I2C_IC_RX_TL_RX_TL_Pos) -#define I2C_IC_RX_TL_RX_TL I2C_IC_RX_TL_RX_TL_Msk - -#define I2C_IC_TX_TL_TX_TL_Pos 0U -#define I2C_IC_TX_TL_TX_TL_Msk (0xFFU << I2C_IC_TX_TL_TX_TL_Pos) -#define I2C_IC_TX_TL_TX_TL I2C_IC_TX_TL_TX_TL_Msk - -#define I2C_IC_ENABLE_TX_CMD_BLOCK_Pos 2U -#define I2C_IC_ENABLE_TX_CMD_BLOCK_Msk (1U << I2C_IC_ENABLE_TX_CMD_BLOCK_Pos) -#define I2C_IC_ENABLE_TX_CMD_BLOCK I2C_IC_ENABLE_TX_CMD_BLOCK_Msk -#define I2C_IC_ENABLE_ABORT_Pos 1U -#define I2C_IC_ENABLE_ABORT_Msk (1U << I2C_IC_ENABLE_ABORT_Pos) -#define I2C_IC_ENABLE_ABORT I2C_IC_ENABLE_ABORT_Msk -#define I2C_IC_ENABLE_ENABLE_Pos 0U -#define I2C_IC_ENABLE_ENABLE_Msk (1U << I2C_IC_ENABLE_ENABLE_Pos) -#define I2C_IC_ENABLE_ENABLE I2C_IC_ENABLE_ENABLE_Msk - -#define I2C_IC_STATUS_SLV_ACTIVITY_Pos 6U -#define I2C_IC_STATUS_SLV_ACTIVITY_Msk (1U << I2C_IC_STATUS_SLV_ACTIVITY_Pos) -#define I2C_IC_STATUS_SLV_ACTIVITY I2C_IC_STATUS_SLV_ACTIVITY_Msk -#define I2C_IC_STATUS_MST_ACTIVITY_Pos 5U -#define I2C_IC_STATUS_MST_ACTIVITY_Msk (1U << I2C_IC_STATUS_MST_ACTIVITY_Pos) -#define I2C_IC_STATUS_MST_ACTIVITY I2C_IC_STATUS_MST_ACTIVITY_Msk -#define I2C_IC_STATUS_RFF_Pos 4U -#define I2C_IC_STATUS_RFF_Msk (1U << I2C_IC_STATUS_RFF_Pos) -#define I2C_IC_STATUS_RFF I2C_IC_STATUS_RFF_Msk -#define I2C_IC_STATUS_RFNE_Pos 3U -#define I2C_IC_STATUS_RFNE_Msk (1U << I2C_IC_STATUS_RFNE_Pos) -#define I2C_IC_STATUS_RFNE I2C_IC_STATUS_RFNE_Msk -#define I2C_IC_STATUS_TFE_Pos 2U -#define I2C_IC_STATUS_TFE_Msk (1U << I2C_IC_STATUS_TFE_Pos) -#define I2C_IC_STATUS_TFE I2C_IC_STATUS_TFE_Msk -#define I2C_IC_STATUS_TFNF_Pos 1U -#define I2C_IC_STATUS_TFNF_Msk (1U << I2C_IC_STATUS_TFNF_Pos) -#define I2C_IC_STATUS_TFNF I2C_IC_STATUS_TFNF_Msk -#define I2C_IC_STATUS_ACTIVITY_Pos 0U -#define I2C_IC_STATUS_ACTIVITY_Msk (1U << I2C_IC_STATUS_ACTIVITY_Pos) -#define I2C_IC_STATUS_ACTIVITY I2C_IC_STATUS_ACTIVITY_Msk - -#define I2C_IC_TXFLR_TXFLR_Pos 0U -#define I2C_IC_TXFLR_TXFLR_Msk (0x1FU << I2C_IC_TXFLR_TXFLR_Pos) -#define I2C_IC_TXFLR_TXFLR I2C_IC_TXFLR_TXFLR_Msk - -#define I2C_IC_RXFLR_RXFLR_Pos 0U -#define I2C_IC_RXFLR_RXFLR_Msk (0x1FU << I2C_IC_RXFLR_RXFLR_Pos) -#define I2C_IC_RXFLR_RXFLR I2C_IC_RXFLR_RXFLR_Msk - -#define I2C_IC_SDA_HOLD_IC_SDA_RX_HOLD_Pos 16U -#define I2C_IC_SDA_HOLD_IC_SDA_RX_HOLD_Msk (0xFFU << I2C_IC_SDA_HOLD_IC_SDA_RX_HOLD_Pos) -#define I2C_IC_SDA_HOLD_IC_SDA_RX_HOLD I2C_IC_SDA_HOLD_IC_SDA_RX_HOLD_Msk -#define I2C_IC_SDA_HOLD_IC_SDA_TX_HOLD_Pos 0U -#define I2C_IC_SDA_HOLD_IC_SDA_TX_HOLD_Msk (0xFFU << I2C_IC_SDA_HOLD_IC_SDA_TX_HOLD_Pos) -#define I2C_IC_SDA_HOLD_IC_SDA_TX_HOLD I2C_IC_SDA_HOLD_IC_SDA_TX_HOLD_Msk - -#define I2C_IC_TX_ABRT_SOURCE_TX_FLUSH_CNT_Pos 23U -#define I2C_IC_TX_ABRT_SOURCE_TX_FLUSH_CNT_Msk (0xFF8U << I2C_IC_TX_ABRT_SOURCE_TX_FLUSH_CNT_Pos) -#define I2C_IC_TX_ABRT_SOURCE_TX_FLUSH_CNT I2C_IC_TX_ABRT_SOURCE_TX_FLUSH_CNT_Msk -#define I2C_IC_TX_ABRT_SOURCE_ABRT_USER_ABRT_Pos 16U -#define I2C_IC_TX_ABRT_SOURCE_ABRT_USER_ABRT_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_USER_ABRT_Pos) -#define I2C_IC_TX_ABRT_SOURCE_ABRT_USER_ABRT I2C_IC_TX_ABRT_SOURCE_ABRT_USER_ABRT_Msk -#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX_Pos 15U -#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX_Pos) -#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX I2C_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX_Msk -#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST_Pos 14U -#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST_Pos) -#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST I2C_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST_Msk -#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO_Pos 13U -#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO_Pos) -#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO I2C_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO_Msk -#define I2C_IC_TX_ABRT_SOURCE_ARB_LOST_Pos 12U -#define I2C_IC_TX_ABRT_SOURCE_ARB_LOST_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ARB_LOST_Pos) -#define I2C_IC_TX_ABRT_SOURCE_ARB_LOST I2C_IC_TX_ABRT_SOURCE_ARB_LOST_Msk -#define I2C_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS_Pos 11U -#define I2C_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS_Pos) -#define I2C_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS I2C_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS_Msk -#define I2C_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT_Pos 10U -#define I2C_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT_Pos) -#define I2C_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT I2C_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT_Msk -#define I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT_Pos 9U -#define I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT_Pos) -#define I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT_Msk -#define I2C_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT_Pos 8U -#define I2C_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT_Pos) -#define I2C_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT I2C_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT_Msk -#define I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET_Pos 7U -#define I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET_Pos) -#define I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET_Msk -#define I2C_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET_Pos 6U -#define I2C_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET_Pos) -#define I2C_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET I2C_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET_Msk -#define I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ_Pos 5U -#define I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ_Pos) -#define I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ_Msk -#define I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK_Pos 4U -#define I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK_Pos) -#define I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK_Msk -#define I2C_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK_Pos 3U -#define I2C_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK_Pos) -#define I2C_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK I2C_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK_Msk -#define I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK_Pos 2U -#define I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK_Pos) -#define I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK_Msk -#define I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK_Pos 1U -#define I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK_Pos) -#define I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK_Msk -#define I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK_Pos 0U -#define I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK_Pos) -#define I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK_Msk - -#define I2C_IC_DMA_CR_TDMAE_Pos 1U -#define I2C_IC_DMA_CR_TDMAE_Msk (1U << I2C_IC_DMA_CR_TDMAE_Pos) -#define I2C_IC_DMA_CR_TDMAE I2C_IC_DMA_CR_TDMAE_Msk -#define I2C_IC_DMA_CR_RDMAE_Pos 0U -#define I2C_IC_DMA_CR_RDMAE_Msk (1U << I2C_IC_DMA_CR_RDMAE_Pos) -#define I2C_IC_DMA_CR_RDMAE I2C_IC_DMA_CR_RDMAE_Msk - -#define I2C_IC_DMA_TDLR_DMATDL_Pos 0U -#define I2C_IC_DMA_TDLR_DMATDL_Msk (0xFU << I2C_IC_DMA_TDLR_DMATDL_Pos) -#define I2C_IC_DMA_TDLR_DMATDL I2C_IC_DMA_TDLR_DMATDL_Msk - -#define I2C_IC_DMA_RDLR_DMARDL_Pos 0U -#define I2C_IC_DMA_RDLR_DMARDL_Msk (0xFU << I2C_IC_DMA_RDLR_DMARDL_Pos) -#define I2C_IC_DMA_RDLR_DMARDL I2C_IC_DMA_RDLR_DMARDL_Msk - -#define I2C_IC_SDA_SETUP_SDA_SETUP_Pos 0U -#define I2C_IC_SDA_SETUP_SDA_SETUP_Msk (0xFFU << I2C_IC_SDA_SETUP_SDA_SETUP_Pos) -#define I2C_IC_SDA_SETUP_SDA_SETUP I2C_IC_SDA_SETUP_SDA_SETUP_Msk - -#define I2C_IC_ACK_GENERAL_CALL_ACK_GEN_CALL_Pos 0U -#define I2C_IC_ACK_GENERAL_CALL_ACK_GEN_CALL_Msk (1U << I2C_IC_ACK_GENERAL_CALL_ACK_GEN_CALL_Pos) -#define I2C_IC_ACK_GENERAL_CALL_ACK_GEN_CALL I2C_IC_ACK_GENERAL_CALL_ACK_GEN_CALL_Msk - -#define I2C_IC_ENABLE_STATUS_SLV_RX_DATA_LOST_Pos 2U -#define I2C_IC_ENABLE_STATUS_SLV_RX_DATA_LOST_Msk (1U << I2C_IC_ENABLE_STATUS_SLV_RX_DATA_LOST_Pos) -#define I2C_IC_ENABLE_STATUS_SLV_RX_DATA_LOST I2C_IC_ENABLE_STATUS_SLV_RX_DATA_LOST_Msk -#define I2C_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY_Pos 1U -#define I2C_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY_Msk (1U << I2C_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY_Pos) -#define I2C_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY I2C_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY_Msk -#define I2C_IC_ENABLE_STATUS_IC_EN_Pos 0U -#define I2C_IC_ENABLE_STATUS_IC_EN_Msk (1U << I2C_IC_ENABLE_STATUS_IC_EN_Pos) -#define I2C_IC_ENABLE_STATUS_IC_EN I2C_IC_ENABLE_STATUS_IC_EN_Msk - -#define I2C_IC_FS_SPKLEN_IC_FS_SPKLEN_Pos 0U -#define I2C_IC_FS_SPKLEN_IC_FS_SPKLEN_Msk (0xFFU << I2C_IC_FS_SPKLEN_IC_FS_SPKLEN_Pos) -#define I2C_IC_FS_SPKLEN_IC_FS_SPKLEN I2C_IC_FS_SPKLEN_IC_FS_SPKLEN_Msk - -#define I2C_IC_COMP_PARAM_1_TX_BUFFER_DEPTH_Pos 16U -#define I2C_IC_COMP_PARAM_1_TX_BUFFER_DEPTH_Msk (0xFFU << I2C_IC_COMP_PARAM_1_TX_BUFFER_DEPTH_Pos) -#define I2C_IC_COMP_PARAM_1_TX_BUFFER_DEPTH I2C_IC_COMP_PARAM_1_TX_BUFFER_DEPTH_Msk -#define I2C_IC_COMP_PARAM_1_RX_BUFFER_DEPTH_Pos 0U -#define I2C_IC_COMP_PARAM_1_RX_BUFFER_DEPTH_Msk (0xFFU << I2C_IC_COMP_PARAM_1_RX_BUFFER_DEPTH_Pos) -#define I2C_IC_COMP_PARAM_1_RX_BUFFER_DEPTH I2C_IC_COMP_PARAM_1_RX_BUFFER_DEPTH_Msk - -#define I2C_IC_COMP_PARAM_1_ADD_ENCODED_PARAMS_Pos 7U -#define I2C_IC_COMP_PARAM_1_ADD_ENCODED_PARAMS_Msk (1U << I2C_IC_COMP_PARAM_1_ADD_ENCODED_PARAMS_Pos) -#define I2C_IC_COMP_PARAM_1_ADD_ENCODED_PARAMS I2C_IC_COMP_PARAM_1_ADD_ENCODED_PARAMS_Msk -#define I2C_IC_COMP_PARAM_1_HAS_DMA_Pos 6U -#define I2C_IC_COMP_PARAM_1_HAS_DMA_Msk (1U << I2C_IC_COMP_PARAM_1_HAS_DMA_Pos) -#define I2C_IC_COMP_PARAM_1_HAS_DMA I2C_IC_COMP_PARAM_1_HAS_DMA_Msk -#define I2C_IC_COMP_PARAM_1_INTR_IO_Pos 5U -#define I2C_IC_COMP_PARAM_1_INTR_IO_Msk (1U << I2C_IC_COMP_PARAM_1_INTR_IO_Pos) -#define I2C_IC_COMP_PARAM_1_INTR_IO I2C_IC_COMP_PARAM_1_INTR_IO_Msk -#define I2C_IC_COMP_PARAM_1_HC_COUNT_VALUES_Pos 4U -#define I2C_IC_COMP_PARAM_1_HC_COUNT_VALUES_Msk (1U << I2C_IC_COMP_PARAM_1_HC_COUNT_VALUES_Pos) -#define I2C_IC_COMP_PARAM_1_HC_COUNT_VALUES I2C_IC_COMP_PARAM_1_HC_COUNT_VALUES_Msk -#define I2C_IC_COMP_PARAM_1_MAX_SPEED_MODE_Pos 2U -#define I2C_IC_COMP_PARAM_1_MAX_SPEED_MODE_Msk (3U << I2C_IC_COMP_PARAM_1_MAX_SPEED_MODE_Pos) -#define I2C_IC_COMP_PARAM_1_MAX_SPEED_MODE I2C_IC_COMP_PARAM_1_MAX_SPEED_MODE_Msk -#define I2C_IC_COMP_PARAM_1_APB_DATA_WIDTH_Pos 0U -#define I2C_IC_COMP_PARAM_1_APB_DATA_WIDTH_Msk (3U << I2C_IC_COMP_PARAM_1_APB_DATA_WIDTH_Pos) -#define I2C_IC_COMP_PARAM_1_APB_DATA_WIDTH I2C_IC_COMP_PARAM_1_APB_DATA_WIDTH_Msk -/** @} */ - -/** - * @name PWM bits definitions - * @{ - */ -#define PWM_CSR_PH_ADV_Pos 7U -#define PWM_CSR_PH_ADV_Msk (1U << PWM_CSR_PH_ADV_Pos) -#define PWM_CSR_PH_ADV PWM_CSR_PH_ADV_Msk -#define PWM_CSR_PH_RET_Pos 6U -#define PWM_CSR_PH_RET_Msk (1U << PWM_CSR_PH_RET_Pos) -#define PWM_CSR_PH_RET PWM_CSR_PH_RET_Msk -#define PWM_CSR_DIVMODE_Pos 4U -#define PWM_CSR_DIVMODE_Msk (0x3U << PWM_CSR_DIVMODE_Pos) -#define PWM_CSR_DIVMODE(n) ((n) << PWM_CSR_DIVMODE_Pos) -#define PWM_CSR_B_INV_Pos 3U -#define PWM_CSR_B_INV_Msk (1U << PWM_CSR_B_INV_Pos) -#define PWM_CSR_B_INV PWM_CSR_B_INV_Msk -#define PWM_CSR_A_INV_Pos 2U -#define PWM_CSR_A_INV_Msk (1U << PWM_CSR_A_INV_Pos) -#define PWM_CSR_A_INV PWM_CSR_A_INV_Msk -#define PWM_CSR_PH_CORRECT_Pos 1U -#define PWM_CSR_PH_CORRECT_Msk (1U << PWM_CSR_PH_CORRECT_Pos) -#define PWM_CSR_PH_CORRECT PWM_CSR_PH_CORRECT_Msk -#define PWM_CSR_EN_Pos 0U -#define PWM_CSR_EN_Msk (1U << PWM_CSR_EN_Pos) -#define PWM_CSR_EN PWM_CSR_EN_Msk -#define PWM_CSR_PH_CORRECT_PHASE_CORRECT_MODULATION (1U << PWM_CSR_PH_CORRECT_Pos) -#define PWM_CSR_PH_CORRECT_TRAILING_EDGE (0U << PWM_CSR_PH_CORRECT_Pos) -#define PWM_CSR_DIVMODE_FREE PWM_CSR_DIVMODE(0U) -#define PWM_CSR_DIVMODE_GATED PWM_CSR_DIVMODE(1U) -#define PWM_CSR_DIVMODE_RISING_EDGE PWM_CSR_DIVMODE(2U) -#define PWM_CSR_DIVMODE_FALING_EDGE PWM_CSR_DIVMODE(3U) - -#define PWM_DIV_INT_Pos 4U -#define PWM_DIV_INT_Msk (0xFFU << PWM_DIV_INT_Pos) -#define PWM_DIV_INT PWM_DIV_INT_Msk -#define PWM_DIV_FRAC_Pos 0U -#define PWM_DIV_FRAC_Msk (0xFU << PWM_DIV_FRAC_Pos) -#define PWM_DIV_FRAC PWM_DIV_FRAC_Msk - -#define PWM_CTR_COUNTER_Pos 0U -#define PWM_CTR_COUNTER_Msk (0xFFFFU << PWM_CTR_COUNTER_Pos) -#define PWM_CTR_COUNTER PWM_CTR_COUNTER_Msk - -#define PWM_CC_B_Pos 16U -#define PWM_CC_B_Msk (0xFFFFU << PWM_CC_B_Pos) -#define PWM_CC_B PWM_CC_B_Msk -#define PWM_CC_A_Pos 0U -#define PWM_CC_A_Msk (0xFFFFU << PWM_CC_A_Pos) -#define PWM_CC_A PWM_CC_A_Msk - -#define PWM_TOP_VALUE_Pos 0U -#define PWM_TOP_VALUE_Msk (0xFFFFU << PWM_TOP_VALUE_Pos) -#define PWM_TOP_VALUE PWM_TOP_VALUE_Msk - -#define PWM_EN_CH7_Pos 7U -#define PWM_EN_CH7_Msk (1U << PWM_EN_CH7_Pos) -#define PWM_EN_CH7 PWM_EN_CH7_Msk -#define PWM_EN_CH6_Pos 6U -#define PWM_EN_CH6_Msk (1U << PWM_EN_CH6_Pos) -#define PWM_EN_CH6 PWM_EN_CH6_Msk -#define PWM_EN_CH5_Pos 5U -#define PWM_EN_CH5_Msk (1U << PWM_EN_CH5_Pos) -#define PWM_EN_CH5 PWM_EN_CH5_Msk -#define PWM_EN_CH4_Pos 4U -#define PWM_EN_CH4_Msk (1U << PWM_EN_CH4_Pos) -#define PWM_EN_CH4 PWM_EN_CH4_Msk -#define PWM_EN_CH3_Pos 3U -#define PWM_EN_CH3_Msk (1U << PWM_EN_CH3_Pos) -#define PWM_EN_CH3 PWM_EN_CH3_Msk -#define PWM_EN_CH2_Pos 2U -#define PWM_EN_CH2_Msk (1U << PWM_EN_CH2_Pos) -#define PWM_EN_CH2 PWM_EN_CH2_Msk -#define PWM_EN_CH1_Pos 1U -#define PWM_EN_CH1_Msk (1U << PWM_EN_CH1_Pos) -#define PWM_EN_CH1 PWM_EN_CH1_Msk -#define PWM_EN_CH0_Pos 0U -#define PWM_EN_CH0_Msk (1U << PWM_EN_CH0_Pos) -#define PWM_EN_CH0 PWM_EN_CH0_Msk - -#define PWM_INTR_CH7_Pos 7U -#define PWM_INTR_CH7_Msk (1U << PWM_INTR_CH7_Pos) -#define PWM_INTR_CH7 PWM_INTR_CH7_Msk -#define PWM_INTR_CH6_Pos 6U -#define PWM_INTR_CH6_Msk (1U << PWM_INTR_CH6_Pos) -#define PWM_INTR_CH6 PWM_INTR_CH6_Msk -#define PWM_INTR_CH5_Pos 5U -#define PWM_INTR_CH5_Msk (1U << PWM_INTR_CH5_Pos) -#define PWM_INTR_CH5 PWM_INTR_CH5_Msk -#define PWM_INTR_CH4_Pos 4U -#define PWM_INTR_CH4_Msk (1U << PWM_INTR_CH4_Pos) -#define PWM_INTR_CH4 PWM_INTR_CH4_Msk -#define PWM_INTR_CH3_Pos 3U -#define PWM_INTR_CH3_Msk (1U << PWM_INTR_CH3_Pos) -#define PWM_INTR_CH3 PWM_INTR_CH3_Msk -#define PWM_INTR_CH2_Pos 2U -#define PWM_INTR_CH2_Msk (1U << PWM_INTR_CH2_Pos) -#define PWM_INTR_CH2 PWM_INTR_CH2_Msk -#define PWM_INTR_CH1_Pos 1U -#define PWM_INTR_CH1_Msk (1U << PWM_INTR_CH1_Pos) -#define PWM_INTR_CH1 PWM_INTR_CH1_Msk -#define PWM_INTR_CH0_Pos 0U -#define PWM_INTR_CH0_Msk (1U << PWM_INTR_CH0_Pos) -#define PWM_INTR_CH0 PWM_INTR_CH0_Msk -#define PWM_INTR_CH(n) (1U << n) - -#define PWM_INTE_CH7_Pos 7U -#define PWM_INTE_CH7_Msk (1U << PWM_INTE_CH7_Pos) -#define PWM_INTE_CH7 PWM_INTE_CH7_Msk -#define PWM_INTE_CH6_Pos 6U -#define PWM_INTE_CH6_Msk (1U << PWM_INTE_CH6_Pos) -#define PWM_INTE_CH6 PWM_INTE_CH6_Msk -#define PWM_INTE_CH5_Pos 5U -#define PWM_INTE_CH5_Msk (1U << PWM_INTE_CH5_Pos) -#define PWM_INTE_CH5 PWM_INTE_CH5_Msk -#define PWM_INTE_CH4_Pos 4U -#define PWM_INTE_CH4_Msk (1U << PWM_INTE_CH4_Pos) -#define PWM_INTE_CH4 PWM_INTE_CH4_Msk -#define PWM_INTE_CH3_Pos 3U -#define PWM_INTE_CH3_Msk (1U << PWM_INTE_CH3_Pos) -#define PWM_INTE_CH3 PWM_INTE_CH3_Msk -#define PWM_INTE_CH2_Pos 2U -#define PWM_INTE_CH2_Msk (1U << PWM_INTE_CH2_Pos) -#define PWM_INTE_CH2 PWM_INTE_CH2_Msk -#define PWM_INTE_CH1_Pos 1U -#define PWM_INTE_CH1_Msk (1U << PWM_INTE_CH1_Pos) -#define PWM_INTE_CH1 PWM_INTE_CH1_Msk -#define PWM_INTE_CH0_Pos 0U -#define PWM_INTE_CH0_Msk (1U << PWM_INTE_CH0_Pos) -#define PWM_INTE_CH0 PWM_INTE_CH0_Msk -#define PWM_INTE_CH(n) (1U << n) - -#define PWM_INTF_CH7_Pos 7U -#define PWM_INTF_CH7_Msk (1U << PWM_INTF_CH7_Pos) -#define PWM_INTF_CH7 PWM_INTF_CH7_Msk -#define PWM_INTF_CH6_Pos 6U -#define PWM_INTF_CH6_Msk (1U << PWM_INTF_CH6_Pos) -#define PWM_INTF_CH6 PWM_INTF_CH6_Msk -#define PWM_INTF_CH5_Pos 5U -#define PWM_INTF_CH5_Msk (1U << PWM_INTF_CH5_Pos) -#define PWM_INTF_CH5 PWM_INTF_CH5_Msk -#define PWM_INTF_CH4_Pos 4U -#define PWM_INTF_CH4_Msk (1U << PWM_INTF_CH4_Pos) -#define PWM_INTF_CH4 PWM_INTF_CH4_Msk -#define PWM_INTF_CH3_Pos 3U -#define PWM_INTF_CH3_Msk (1U << PWM_INTF_CH3_Pos) -#define PWM_INTF_CH3 PWM_INTF_CH3_Msk -#define PWM_INTF_CH2_Pos 2U -#define PWM_INTF_CH2_Msk (1U << PWM_INTF_CH2_Pos) -#define PWM_INTF_CH2 PWM_INTF_CH2_Msk -#define PWM_INTF_CH1_Pos 1U -#define PWM_INTF_CH1_Msk (1U << PWM_INTF_CH1_Pos) -#define PWM_INTF_CH1 PWM_INTF_CH1_Msk -#define PWM_INTF_CH0_Pos 0U -#define PWM_INTF_CH0_Msk (1U << PWM_INTF_CH0_Pos) -#define PWM_INTF_CH0 PWM_INTF_CH0_Msk -#define PWM_INTF_CH(n) (1U << n) - -#define PWM_INTS_CH7_Pos 7U -#define PWM_INTS_CH7_Msk (1U << PWM_INTS_CH7_Pos) -#define PWM_INTS_CH7 PWM_INTS_CH7_Msk -#define PWM_INTS_CH6_Pos 6U -#define PWM_INTS_CH6_Msk (1U << PWM_INTS_CH6_Pos) -#define PWM_INTS_CH6 PWM_INTS_CH6_Msk -#define PWM_INTS_CH5_Pos 5U -#define PWM_INTS_CH5_Msk (1U << PWM_INTS_CH5_Pos) -#define PWM_INTS_CH5 PWM_INTS_CH5_Msk -#define PWM_INTS_CH4_Pos 4U -#define PWM_INTS_CH4_Msk (1U << PWM_INTS_CH4_Pos) -#define PWM_INTS_CH4 PWM_INTS_CH4_Msk -#define PWM_INTS_CH3_Pos 3U -#define PWM_INTS_CH3_Msk (1U << PWM_INTS_CH3_Pos) -#define PWM_INTS_CH3 PWM_INTS_CH3_Msk -#define PWM_INTS_CH2_Pos 2U -#define PWM_INTS_CH2_Msk (1U << PWM_INTS_CH2_Pos) -#define PWM_INTS_CH2 PWM_INTS_CH2_Msk -#define PWM_INTS_CH1_Pos 1U -#define PWM_INTS_CH1_Msk (1U << PWM_INTS_CH1_Pos) -#define PWM_INTS_CH1 PWM_INTS_CH1_Msk -#define PWM_INTS_CH0_Pos 0U -#define PWM_INTS_CH0_Msk (1U << PWM_INTS_CH0_Pos) -#define PWM_INTS_CH0 PWM_INTS_CH0_Msk -#define PWM_INTS_CH(n) (1U << n) -/** @} */ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* RP2040_H */ - -/** @} */ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP/rp2040.h + * @brief CMSIS device file for the RP2040. + * + * @defgroup CMSIS_RP2040 RP2040 Device File + * @ingroup CMSIS_DEVICE + * @{ + */ + +#ifndef RP2040_H +#define RP2040_H + +#include + +#define __CM0PLUS_REV 0U +#define __MPU_PRESENT 1U +#define __VTOR_PRESENT 1U +#define __NVIC_PRIO_BITS 2U +#define __Vendor_SysTickConfig 0U + +/** + * @brief Interrupt vector numbers. + */ +typedef enum { + NonMaskableInt_IRQn = -14, + HardFault_IRQn = -13, + SVCall_IRQn = -5, + PendSV_IRQn = -2, + SysTick_IRQn = -1, + Vector_0n = 0, + Vector_1n = 1, + Vector_2n = 2, + Vector_3n = 3, + Vector_4n = 4, + Vector_5n = 5, + Vector_6n = 6, + Vector_7n = 7, + Vector_8n = 8, + Vector_9n = 9, + Vector_10n = 10, + Vector_11n = 11, + Vector_12n = 12, + Vector_13n = 13, + Vector_14n = 14, + Vector_15n = 15, + Vector_16n = 16, + Vector_17n = 17, + Vector_18n = 18, + Vector_19n = 19, + Vector_20n = 20, + Vector_21n = 21, + Vector_22n = 22, + Vector_23n = 23, + Vector_24n = 24, + Vector_25n = 25, + Vector_26n = 26, + Vector_27n = 27, + Vector_28n = 28, + Vector_29n = 29, + Vector_30n = 30, + Vector_31n = 31 +} IRQn_Type; + +#define SVC_IRQn SVCall_IRQn + +#include "core_cm0plus.h" +#include "system_rp2040.h" + +/** + * @name Peripheral structures + * @{ + */ +typedef struct { + __IO uint32_t READ_ADDR; + __IO uint32_t WRITE_ADDR; + __IO uint32_t TRANS_COUNT; + __IO uint32_t CTRL_TRIG; + __IO uint32_t AL1_CTRL; + __IO uint32_t AL1_READ_ADDR; + __IO uint32_t AL1_WRITE_ADDR; + __IO uint32_t AL1_TRANSFER_COUNT_TRIG; + __IO uint32_t AL2_CTRL; + __IO uint32_t AL2_TRANSFER_COUNT; + __IO uint32_t AL2_READ_ADDR; + __IO uint32_t AL2_WRITE_ADDR_TRIG; + __IO uint32_t AL3_CTRL; + __IO uint32_t AL3_WRITE_ADDR; + __IO uint32_t AL3_TRANSFER_COUNT; + __IO uint32_t AL3_READ_ADDR_TRIG; +} DMA_Channel_TypeDef; + +typedef struct { + __I uint32_t CTDREQ; + __I uint32_t TCR; + __I uint32_t resvd8[14]; +} DMA_Debug_TypeDef; + +typedef struct { + DMA_Channel_TypeDef CH[12]; + __I uint32_t resvd300[64]; + __IO uint32_t INTR; + __IO uint32_t INTE0; + __IO uint32_t INTF0; + __IO uint32_t INTS0; + __IO uint32_t INTR1; + __IO uint32_t INTE1; + __IO uint32_t INTF1; + __IO uint32_t INTS1; + __IO uint32_t TIMER[4]; + __IO uint32_t MULTI_CHAN_TRIGGER; + __IO uint32_t SNIFF_CTRL; + __IO uint32_t SNIFF_DATA; + __I uint32_t resvd43C; + __I uint32_t FIFO_LEVELS; + __IO uint32_t CHAN_ABORT; + __I uint32_t N_CHANNELS; + __I uint32_t resvd44C[237]; + DMA_Debug_TypeDef CH_DBG[12]; + __I uint32_t resvdB00[320]; + struct { + DMA_Channel_TypeDef CH[12]; + __I uint32_t resvd300[64]; + __IO uint32_t INTR; + __IO uint32_t INTE0; + __IO uint32_t INTF0; + __IO uint32_t INTS0; + __IO uint32_t INTR1; + __IO uint32_t INTE1; + __IO uint32_t INTF1; + __IO uint32_t INTS1; + __IO uint32_t TIMER[4]; + __IO uint32_t MULTI_CHAN_TRIGGER; + __IO uint32_t SNIFF_CTRL; + __IO uint32_t SNIFF_DATA; + __I uint32_t resvd43C; + __I uint32_t FIFO_LEVELS; + __IO uint32_t CHAN_ABORT; + __I uint32_t N_CHANNELS; + __I uint32_t resvd44C[237]; + DMA_Debug_TypeDef CH_DBG[12]; + __I uint32_t resvdB00[320]; + } XOR; + struct { + DMA_Channel_TypeDef CH[12]; + __I uint32_t resvd300[64]; + __IO uint32_t INTR; + __IO uint32_t INTE0; + __IO uint32_t INTF0; + __IO uint32_t INTS0; + __IO uint32_t INTR1; + __IO uint32_t INTE1; + __IO uint32_t INTF1; + __IO uint32_t INTS1; + __IO uint32_t TIMER[4]; + __IO uint32_t MULTI_CHAN_TRIGGER; + __IO uint32_t SNIFF_CTRL; + __IO uint32_t SNIFF_DATA; + __I uint32_t resvd43C; + __I uint32_t FIFO_LEVELS; + __IO uint32_t CHAN_ABORT; + __I uint32_t N_CHANNELS; + __I uint32_t resvd44C[237]; + DMA_Debug_TypeDef CH_DBG[12]; + __I uint32_t resvdB00[320]; + } SET; + struct { + DMA_Channel_TypeDef CH[12]; + __I uint32_t resvd300[64]; + __IO uint32_t INTR; + __IO uint32_t INTE0; + __IO uint32_t INTF0; + __IO uint32_t INTS0; + __IO uint32_t INTR1; + __IO uint32_t INTE1; + __IO uint32_t INTF1; + __IO uint32_t INTS1; + __IO uint32_t TIMER[4]; + __IO uint32_t MULTI_CHAN_TRIGGER; + __IO uint32_t SNIFF_CTRL; + __IO uint32_t SNIFF_DATA; + __I uint32_t resvd43C; + __I uint32_t FIFO_LEVELS; + __IO uint32_t CHAN_ABORT; + __I uint32_t N_CHANNELS; + __I uint32_t resvd44C[237]; + DMA_Debug_TypeDef CH_DBG[12]; + __I uint32_t resvdB00[320]; + } CLR; +} DMA_TypeDef; + +typedef struct { + struct { + __I uint32_t STATUS; + __IO uint32_t CTRL; + } GPIO[30]; + __IO uint32_t INTR[4]; + struct { + __IO uint32_t INTE[4]; + __IO uint32_t INTF[4]; + __I uint32_t INTS[4]; + } PROC[2]; + __IO uint32_t DW_INTE[4]; + __IO uint32_t DW_INTF[4]; + __I uint32_t DW_INTS[4]; +} IOUSER_TypeDef; + +typedef struct { + struct { + __I uint32_t STATUS; + __IO uint32_t CTRL; + } GPIO[6]; + __IO uint32_t INTR[1]; + struct { + __IO uint32_t INTE[1]; + __IO uint32_t INTF[1]; + __I uint32_t INTS[1]; + } PROC[2]; + __IO uint32_t DW_INTE[1]; + __IO uint32_t DW_INTF[1]; + __I uint32_t DW_INTS[1]; +} IOQSPI_TypeDef; + +typedef struct { + __IO uint32_t VOLTAGE_SELECT; + __IO uint32_t GPIO[30]; + __IO uint32_t SWCLK; + __IO uint32_t SWD; +} PADS_TypeDef; + +typedef struct { + __IO uint32_t VOLTAGE_SELECT; + __IO uint32_t GPIO_QSPI_SCLK; + __IO uint32_t GPIO_QSPI_SD0; + __IO uint32_t GPIO_QSPI_SD1; + __IO uint32_t GPIO_QSPI_SD2; + __IO uint32_t GPIO_QSPI_SD3; + __IO uint32_t GPIO_QSPI_SS; +} PADS_QSPI_TypeDef; + +/** + * @brief XIP SSI (Synchronous Serial Interface) register block. + * @note DWC SSI controller used for XIP flash access on RP2040. + * See RP2040 Datasheet 4.10.13 SSI List of Registers. + */ +typedef struct { + __IO uint32_t CTRLR0; /* 0x00 */ + __IO uint32_t CTRLR1; /* 0x04 */ + __IO uint32_t SSIENR; /* 0x08 */ + __IO uint32_t MWCR; /* 0x0C */ + __IO uint32_t SER; /* 0x10 */ + __IO uint32_t BAUDR; /* 0x14 */ + __IO uint32_t TXFTLR; /* 0x18 */ + __IO uint32_t RXFTLR; /* 0x1C */ + __I uint32_t TXFLR; /* 0x20 */ + __I uint32_t RXFLR; /* 0x24 */ + __I uint32_t SR; /* 0x28 */ + __IO uint32_t IMR; /* 0x2C */ + __I uint32_t ISR; /* 0x30 */ + __I uint32_t RISR; /* 0x34 */ + __I uint32_t TXOICR; /* 0x38 */ + __I uint32_t RXOICR; /* 0x3C */ + __I uint32_t RXUICR; /* 0x40 */ + __I uint32_t MSTICR; /* 0x44 */ + __I uint32_t ICR; /* 0x48 */ + __IO uint32_t DMACR; /* 0x4C */ + __IO uint32_t DMATDLR; /* 0x50 */ + __IO uint32_t DMARDLR; /* 0x54 */ + __I uint32_t IDR; /* 0x58 */ + __I uint32_t SSI_VERSION_ID; /* 0x5C */ + __IO uint32_t DR[36]; /* 0x60-0xEC */ + __IO uint32_t RX_SAMPLE_DLY; /* 0xF0 */ + __IO uint32_t SPI_CTRLR0; /* 0xF4 */ + __IO uint32_t TXD_DRIVE_EDGE; /* 0xF8 */ +} SSI_TypeDef; + +/** + * @brief XIP control register block. + * @note See RP2040 Datasheet 2.6.3.1 XIP Cache Control. + */ +typedef struct { + __IO uint32_t CTRL; /* 0x00 */ + __IO uint32_t FLUSH; /* 0x04 */ + __I uint32_t STAT; /* 0x08 */ + __IO uint32_t CTR_HIT; /* 0x0C */ + __IO uint32_t CTR_ACC; /* 0x10 */ + __IO uint32_t STREAM_ADDR; /* 0x14 */ + __IO uint32_t STREAM_CTR; /* 0x18 */ + __I uint32_t STREAM_FIFO; /* 0x1C */ +} XIP_CTRL_TypeDef; + +typedef struct { + __IO uint32_t FRCE_ON; + __IO uint32_t FRCE_OFF; + __IO uint32_t WDSEL; + __IO uint32_t DONE; + __I uint32_t resvd10[1020]; + struct { + __IO uint32_t FRCE_ON; + __IO uint32_t FRCE_OFF; + __IO uint32_t WDSEL; + __IO uint32_t DONE; + __I uint32_t resvd10[1020]; + } XOR; + struct { + __IO uint32_t FRCE_ON; + __IO uint32_t FRCE_OFF; + __IO uint32_t WDSEL; + __IO uint32_t DONE; + __I uint32_t resvd10[1020]; + } SET; + struct { + __IO uint32_t FRCE_ON; + __IO uint32_t FRCE_OFF; + __IO uint32_t WDSEL; + __IO uint32_t DONE; + __I uint32_t resvd10[1020]; + } CLR; +} PSM_TypeDef; + +typedef struct { + __IO uint32_t RESET; + __IO uint32_t WDSEL; + __I uint32_t RESET_DONE; + __I uint32_t resvdC[1021]; + struct { + __IO uint32_t RESET; + __IO uint32_t WDSEL; + __I uint32_t RESET_DONE; + __I uint32_t resvdC[1021]; + } XOR; + struct { + __IO uint32_t RESET; + __IO uint32_t WDSEL; + __I uint32_t RESET_DONE; + __I uint32_t resvdC[1021]; + } SET; + struct { + __IO uint32_t RESET; + __IO uint32_t WDSEL; + __I uint32_t RESET_DONE; + __I uint32_t resvdC[1021]; + } CLR; +} RESETS_TypeDef; + +typedef struct { + __I uint32_t CPUID; + __I uint32_t GPIO_IN; + __I uint32_t GPIO_HI_IN; + __I uint32_t resvdC; + __IO uint32_t GPIO_OUT; + __IO uint32_t GPIO_OUT_SET; + __IO uint32_t GPIO_OUT_CLR; + __IO uint32_t GPIO_OUT_XOR; + __IO uint32_t GPIO_OE; + __IO uint32_t GPIO_OE_SET; + __IO uint32_t GPIO_OE_CLR; + __IO uint32_t GPIO_OE_XOR; + __IO uint32_t GPIO_HI_OUT; + __IO uint32_t GPIO_HI_OUT_SET; + __IO uint32_t GPIO_HI_OUT_CLR; + __IO uint32_t GPIO_HI_OUT_XOR; + __IO uint32_t GPIO_HI_OE; + __IO uint32_t GPIO_HI_OE_SET; + __IO uint32_t GPIO_HI_OE_CLR; + __IO uint32_t GPIO_HI_OE_XOR; + __IO uint32_t FIFO_ST; + __IO uint32_t FIFO_WR; + __I uint32_t FIFO_RD; + __IO uint32_t SPINLOCK_ST; + __IO uint32_t DIV_UDIVIDEND; + __IO uint32_t DIV_UDIVISOR; + __IO uint32_t DIV_SDIVIDEND; + __IO uint32_t DIV_SDIVISOR; + __IO uint32_t DIV_QUOTIENT; + __IO uint32_t DIV_REMAINDER; + __I uint32_t DIV_CSR; + __I uint32_t resvd7C; + struct { + __IO uint32_t ACCUM0; + __IO uint32_t ACCUM1; + __IO uint32_t BASE0; + __IO uint32_t BASE1; + __IO uint32_t BASE2; + __I uint32_t POP_LANE0; + __I uint32_t POP_LANE1; + __I uint32_t POP_FULL; + __I uint32_t PEEK_LANE0; + __I uint32_t PEEK_LANE1; + __I uint32_t PEEK_FULL; + __IO uint32_t CTRL_LANE0; + __IO uint32_t CTRL_LANE1; + __IO uint32_t ACCUM0_ADD; + __IO uint32_t ACCUM1_ADD; + __IO uint32_t BASE_1AND0; + } INTERP[2]; + __IO uint32_t SPINLOCK[32]; /* NUM_SPIN_LOCKS */ +} SIO_TypeDef; + +typedef struct { + __IO uint32_t SSPCR0; + __IO uint32_t SSPCR1; + __IO uint32_t SSPDR; + __I uint32_t SSPSR; + __IO uint32_t SSPCPSR; + __IO uint32_t SSPIMSC; + __I uint32_t SSPRIS; + __I uint32_t SSPMIS; + __IO uint32_t SSPICR; + __IO uint32_t SSPDMACR; + __I uint32_t resvd28[1006]; + __I uint32_t SSPPERIPHID0; + __I uint32_t SSPPERIPHID1; + __I uint32_t SSPPERIPHID2; + __I uint32_t SSPPERIPHID3; + __I uint32_t SSPPCELLID0; + __I uint32_t SSPPCELLID1; + __I uint32_t SSPPCELLID2; + __I uint32_t SSPPCELLID3; + struct { + __IO uint32_t SSPCR0; + __IO uint32_t SSPCR1; + __IO uint32_t SSPDR; + __I uint32_t SSPSR; + __IO uint32_t SSPCPSR; + __IO uint32_t SSPIMSC; + __I uint32_t SSPRIS; + __I uint32_t SSPMIS; + __IO uint32_t SSPICR; + __IO uint32_t SSPDMACR; + __I uint32_t resvd28[1006]; + __I uint32_t SSPPERIPHID0; + __I uint32_t SSPPERIPHID1; + __I uint32_t SSPPERIPHID2; + __I uint32_t SSPPERIPHID3; + __I uint32_t SSPPCELLID0; + __I uint32_t SSPPCELLID1; + __I uint32_t SSPPCELLID2; + __I uint32_t SSPPCELLID3; + } XOR; + struct { + __IO uint32_t SSPCR0; + __IO uint32_t SSPCR1; + __IO uint32_t SSPDR; + __I uint32_t SSPSR; + __IO uint32_t SSPCPSR; + __IO uint32_t SSPIMSC; + __I uint32_t SSPRIS; + __I uint32_t SSPMIS; + __IO uint32_t SSPICR; + __IO uint32_t SSPDMACR; + __I uint32_t resvd28[1006]; + __I uint32_t SSPPERIPHID0; + __I uint32_t SSPPERIPHID1; + __I uint32_t SSPPERIPHID2; + __I uint32_t SSPPERIPHID3; + __I uint32_t SSPPCELLID0; + __I uint32_t SSPPCELLID1; + __I uint32_t SSPPCELLID2; + __I uint32_t SSPPCELLID3; + } SET; + struct { + __IO uint32_t SSPCR0; + __IO uint32_t SSPCR1; + __IO uint32_t SSPDR; + __I uint32_t SSPSR; + __IO uint32_t SSPCPSR; + __IO uint32_t SSPIMSC; + __I uint32_t SSPRIS; + __I uint32_t SSPMIS; + __IO uint32_t SSPICR; + __IO uint32_t SSPDMACR; + __I uint32_t resvd28[1006]; + __I uint32_t SSPPERIPHID0; + __I uint32_t SSPPERIPHID1; + __I uint32_t SSPPERIPHID2; + __I uint32_t SSPPERIPHID3; + __I uint32_t SSPPCELLID0; + __I uint32_t SSPPCELLID1; + __I uint32_t SSPPCELLID2; + __I uint32_t SSPPCELLID3; + } CLR; +} SPI_TypeDef; + +typedef struct { + __IO uint32_t TIMEHW; + __IO uint32_t TIMELW; + __I uint32_t TIMEHR; + __I uint32_t TIMELR; + __IO uint32_t ALARM[4]; /* NUM_TIMERS */ + __IO uint32_t ARMED; + __I uint32_t TIMERAWH; + __I uint32_t TIMERAWL; + __IO uint32_t DBGPAUSE; + __IO uint32_t PAUSE; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __I uint32_t INTS; + __I uint32_t resvd44[1007]; + struct { + __IO uint32_t TIMEHW; + __IO uint32_t TIMELW; + __I uint32_t TIMEHR; + __I uint32_t TIMELR; + __IO uint32_t ALARM[4]; /* NUM_TIMERS */ + __IO uint32_t ARMED; + __I uint32_t TIMERAWH; + __I uint32_t TIMERAWL; + __IO uint32_t DBGPAUSE; + __IO uint32_t PAUSE; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __I uint32_t INTS; + __I uint32_t resvd44[1007]; + } XOR; + struct { + __IO uint32_t TIMEHW; + __IO uint32_t TIMELW; + __I uint32_t TIMEHR; + __I uint32_t TIMELR; + __IO uint32_t ALARM[4]; /* NUM_TIMERS */ + __IO uint32_t ARMED; + __I uint32_t TIMERAWH; + __I uint32_t TIMERAWL; + __IO uint32_t DBGPAUSE; + __IO uint32_t PAUSE; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __I uint32_t INTS; + __I uint32_t resvd44[1007]; + } SET; + struct { + __IO uint32_t TIMEHW; + __IO uint32_t TIMELW; + __I uint32_t TIMEHR; + __I uint32_t TIMELR; + __IO uint32_t ALARM[4]; /* NUM_TIMERS */ + __IO uint32_t ARMED; + __I uint32_t TIMERAWH; + __I uint32_t TIMERAWL; + __IO uint32_t DBGPAUSE; + __IO uint32_t PAUSE; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __I uint32_t INTS; + __I uint32_t resvd44[1007]; + } CLR; +} TIMER_TypeDef; + +typedef struct { + __IO uint32_t UARTDR; + __IO uint32_t UARTRSR; + __I uint32_t resvd8; + __I uint32_t resvdC; + __I uint32_t resvd10; + __I uint32_t resvd14; + __I uint32_t UARTFR; + __I uint32_t resvd1C; + __IO uint32_t UARTILPR; + __IO uint32_t UARTIBRD; + __IO uint32_t UARTFBRD; + __IO uint32_t UARTLCR_H; + __IO uint32_t UARTCR; + __IO uint32_t UARTIFLS; + __IO uint32_t UARTIMSC; + __I uint32_t UARTRIS; + __I uint32_t UARTMIS; + __IO uint32_t UARTICR; + __IO uint32_t UARTDMACR; + __I uint32_t resvd4C[997]; + __I uint32_t UARTPERIPHID0; + __I uint32_t UARTPERIPHID1; + __I uint32_t UARTPERIPHID2; + __I uint32_t UARTPERIPHID3; + __I uint32_t UARTPCELLID0; + __I uint32_t UARTPCELLID1; + __I uint32_t UARTPCELLID2; + __I uint32_t UARTPCELLID3; + struct { + __IO uint32_t UARTDR; + __IO uint32_t UARTRSR; + __I uint32_t resvd8; + __I uint32_t resvdC; + __I uint32_t resvd10; + __I uint32_t resvd14; + __I uint32_t UARTFR; + __I uint32_t resvd1C; + __IO uint32_t UARTILPR; + __IO uint32_t UARTIBRD; + __IO uint32_t UARTFBRD; + __IO uint32_t UARTLCR_H; + __IO uint32_t UARTCR; + __IO uint32_t UARTIFLS; + __IO uint32_t UARTIMSC; + __I uint32_t UARTRIS; + __I uint32_t UARTMIS; + __IO uint32_t UARTICR; + __IO uint32_t UARTDMACR; + __I uint32_t resvd4C[997]; + __I uint32_t UARTPERIPHID0; + __I uint32_t UARTPERIPHID1; + __I uint32_t UARTPERIPHID2; + __I uint32_t UARTPERIPHID3; + __I uint32_t UARTPCELLID0; + __I uint32_t UARTPCELLID1; + __I uint32_t UARTPCELLID2; + __I uint32_t UARTPCELLID3; + } XOR; + struct { + __IO uint32_t UARTDR; + __IO uint32_t UARTRSR; + __I uint32_t resvd8; + __I uint32_t resvdC; + __I uint32_t resvd10; + __I uint32_t resvd14; + __I uint32_t UARTFR; + __I uint32_t resvd1C; + __IO uint32_t UARTILPR; + __IO uint32_t UARTIBRD; + __IO uint32_t UARTFBRD; + __IO uint32_t UARTLCR_H; + __IO uint32_t UARTCR; + __IO uint32_t UARTIFLS; + __IO uint32_t UARTIMSC; + __I uint32_t UARTRIS; + __I uint32_t UARTMIS; + __IO uint32_t UARTICR; + __IO uint32_t UARTDMACR; + __I uint32_t resvd4C[997]; + __I uint32_t UARTPERIPHID0; + __I uint32_t UARTPERIPHID1; + __I uint32_t UARTPERIPHID2; + __I uint32_t UARTPERIPHID3; + __I uint32_t UARTPCELLID0; + __I uint32_t UARTPCELLID1; + __I uint32_t UARTPCELLID2; + __I uint32_t UARTPCELLID3; + } SET; + struct { + __IO uint32_t UARTDR; + __IO uint32_t UARTRSR; + __I uint32_t resvd8; + __I uint32_t resvdC; + __I uint32_t resvd10; + __I uint32_t resvd14; + __I uint32_t UARTFR; + __I uint32_t resvd1C; + __IO uint32_t UARTILPR; + __IO uint32_t UARTIBRD; + __IO uint32_t UARTFBRD; + __IO uint32_t UARTLCR_H; + __IO uint32_t UARTCR; + __IO uint32_t UARTIFLS; + __IO uint32_t UARTIMSC; + __I uint32_t UARTRIS; + __I uint32_t UARTMIS; + __IO uint32_t UARTICR; + __IO uint32_t UARTDMACR; + __I uint32_t resvd4C[997]; + __I uint32_t UARTPERIPHID0; + __I uint32_t UARTPERIPHID1; + __I uint32_t UARTPERIPHID2; + __I uint32_t UARTPERIPHID3; + __I uint32_t UARTPCELLID0; + __I uint32_t UARTPCELLID1; + __I uint32_t UARTPCELLID2; + __I uint32_t UARTPCELLID3; + } CLR; +} UART_TypeDef; + +typedef struct { + __IO uint32_t CLKDIVM1; + __IO uint32_t SETUP0; + __IO uint32_t SETUP1; + __IO uint32_t CTRL; + __IO uint32_t IRQSETUP0; + __IO uint32_t IRQSETUP1; + __IO uint32_t RTC1; + __IO uint32_t RTC0; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __IO uint32_t INTS; + __I uint32_t resvd30[1012]; + struct { + __IO uint32_t CLKDIVM1; + __IO uint32_t SETUP0; + __IO uint32_t SETUP1; + __IO uint32_t CTRL; + __IO uint32_t IRQSETUP0; + __IO uint32_t IRQSETUP1; + __IO uint32_t RTC1; + __IO uint32_t RTC0; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __IO uint32_t INTS; + __I uint32_t resvd30[1012]; + } XOR; + struct { + __IO uint32_t CLKDIVM1; + __IO uint32_t SETUP0; + __IO uint32_t SETUP1; + __IO uint32_t CTRL; + __IO uint32_t IRQSETUP0; + __IO uint32_t IRQSETUP1; + __IO uint32_t RTC1; + __IO uint32_t RTC0; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __IO uint32_t INTS; + __I uint32_t resvd30[1012]; + } SET; + struct { + __IO uint32_t CLKDIVM1; + __IO uint32_t SETUP0; + __IO uint32_t SETUP1; + __IO uint32_t CTRL; + __IO uint32_t IRQSETUP0; + __IO uint32_t IRQSETUP1; + __IO uint32_t RTC1; + __IO uint32_t RTC0; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __IO uint32_t INTS; + __I uint32_t resvd30[1012]; + } CLR; +} RTC_TypeDef; + +typedef struct { + __IO uint32_t CON; + __IO uint32_t TAR; + __IO uint32_t SAR; + __I uint32_t resvdC; + __IO uint32_t DATACMD; + __IO uint32_t SSSCLHCNT; + __IO uint32_t SSSCLLCNT; + __IO uint32_t FSSCLHCNT; + __IO uint32_t FSSCLLCNT; + __I uint32_t resvd24[2]; + __IO uint32_t INTRSTAT; + __IO uint32_t INTRMASK; + __IO uint32_t RAWINTRSTAT; + __IO uint32_t RXTL; + __IO uint32_t TXTL; + __IO uint32_t CLRINTR; + __IO uint32_t CLRRXUNDER; + __IO uint32_t CLRRXOVER; + __IO uint32_t CLRTXOVER; + __IO uint32_t CLRRDREQ; + __IO uint32_t CLRTXABRT; + __IO uint32_t CLRRXDONE; + __IO uint32_t CLRACTIVITY; + __IO uint32_t CLRSTOPDET; + __IO uint32_t CLRSTARTDET; + __IO uint32_t CLRGENCALL; + __IO uint32_t ENABLE; + __IO uint32_t STATUS; + __IO uint32_t TXFLR; + __IO uint32_t RXFLR; + __IO uint32_t SDAHOLD; + __IO uint32_t TXABRTSOURCE; + __IO uint32_t SLVDATANACKONLY; + __IO uint32_t DMACR; + __IO uint32_t DMATDLR; + __IO uint32_t DMARDLR; + __IO uint32_t SDASETUP; + __IO uint32_t ACKGENERALCALL; + __IO uint32_t ENABLESTATUS; + __IO uint32_t FSSPKLEN; + __I uint32_t resvdA4; + __IO uint32_t CLRRESTARTDET; + __I uint32_t resvdac[981]; + struct { + __IO uint32_t CON; + __IO uint32_t TAR; + __IO uint32_t SAR; + __I uint32_t resvdC; + __IO uint32_t DATACMD; + __IO uint32_t SSSCLHCNT; + __IO uint32_t SSSCLLCNT; + __IO uint32_t FSSCLHCNT; + __IO uint32_t FSSCLLCNT; + __I uint32_t resvd24[2]; + __IO uint32_t INTRSTAT; + __IO uint32_t INTRMASK; + __IO uint32_t RAWINTRSTAT; + __IO uint32_t RXTL; + __IO uint32_t TXTL; + __IO uint32_t CLRINTR; + __IO uint32_t CLRRXUNDER; + __IO uint32_t CLRRXOVER; + __IO uint32_t CLRTXOVER; + __IO uint32_t CLRRDREQ; + __IO uint32_t CLRTXABRT; + __IO uint32_t CLRRXDONE; + __IO uint32_t CLRACTIVITY; + __IO uint32_t CLRSTOPDET; + __IO uint32_t CLRSTARTDET; + __IO uint32_t CLRGENCALL; + __IO uint32_t ENABLE; + __IO uint32_t STATUS; + __IO uint32_t TXFLR; + __IO uint32_t RXFLR; + __IO uint32_t SDAHOLD; + __IO uint32_t TXABRTSOURCE; + __IO uint32_t SLVDATANACKONLY; + __IO uint32_t DMACR; + __IO uint32_t DMATDLR; + __IO uint32_t DMARDLR; + __IO uint32_t SDASETUP; + __IO uint32_t ACKGENERALCALL; + __IO uint32_t ENABLESTATUS; + __IO uint32_t FSSPKLEN; + __I uint32_t resvdA4; + __IO uint32_t CLRRESTARTDET; + __I uint32_t resvdac[981]; + } XOR; + struct { + __IO uint32_t CON; + __IO uint32_t TAR; + __IO uint32_t SAR; + __I uint32_t resvdC; + __IO uint32_t DATACMD; + __IO uint32_t SSSCLHCNT; + __IO uint32_t SSSCLLCNT; + __IO uint32_t FSSCLHCNT; + __IO uint32_t FSSCLLCNT; + __I uint32_t resvd24[2]; + __IO uint32_t INTRSTAT; + __IO uint32_t INTRMASK; + __IO uint32_t RAWINTRSTAT; + __IO uint32_t RXTL; + __IO uint32_t TXTL; + __IO uint32_t CLRINTR; + __IO uint32_t CLRRXUNDER; + __IO uint32_t CLRRXOVER; + __IO uint32_t CLRTXOVER; + __IO uint32_t CLRRDREQ; + __IO uint32_t CLRTXABRT; + __IO uint32_t CLRRXDONE; + __IO uint32_t CLRACTIVITY; + __IO uint32_t CLRSTOPDET; + __IO uint32_t CLRSTARTDET; + __IO uint32_t CLRGENCALL; + __IO uint32_t ENABLE; + __IO uint32_t STATUS; + __IO uint32_t TXFLR; + __IO uint32_t RXFLR; + __IO uint32_t SDAHOLD; + __IO uint32_t TXABRTSOURCE; + __IO uint32_t SLVDATANACKONLY; + __IO uint32_t DMACR; + __IO uint32_t DMATDLR; + __IO uint32_t DMARDLR; + __IO uint32_t SDASETUP; + __IO uint32_t ACKGENERALCALL; + __IO uint32_t ENABLESTATUS; + __IO uint32_t FSSPKLEN; + __I uint32_t resvdA4; + __IO uint32_t CLRRESTARTDET; + __I uint32_t resvdac[981]; + } SET; + struct { + __IO uint32_t CON; + __IO uint32_t TAR; + __IO uint32_t SAR; + __I uint32_t resvdC; + __IO uint32_t DATACMD; + __IO uint32_t SSSCLHCNT; + __IO uint32_t SSSCLLCNT; + __IO uint32_t FSSCLHCNT; + __IO uint32_t FSSCLLCNT; + __I uint32_t resvd24[2]; + __IO uint32_t INTRSTAT; + __IO uint32_t INTRMASK; + __IO uint32_t RAWINTRSTAT; + __IO uint32_t RXTL; + __IO uint32_t TXTL; + __IO uint32_t CLRINTR; + __IO uint32_t CLRRXUNDER; + __IO uint32_t CLRRXOVER; + __IO uint32_t CLRTXOVER; + __IO uint32_t CLRRDREQ; + __IO uint32_t CLRTXABRT; + __IO uint32_t CLRRXDONE; + __IO uint32_t CLRACTIVITY; + __IO uint32_t CLRSTOPDET; + __IO uint32_t CLRSTARTDET; + __IO uint32_t CLRGENCALL; + __IO uint32_t ENABLE; + __IO uint32_t STATUS; + __IO uint32_t TXFLR; + __IO uint32_t RXFLR; + __IO uint32_t SDAHOLD; + __IO uint32_t TXABRTSOURCE; + __IO uint32_t SLVDATANACKONLY; + __IO uint32_t DMACR; + __IO uint32_t DMATDLR; + __IO uint32_t DMARDLR; + __IO uint32_t SDASETUP; + __IO uint32_t ACKGENERALCALL; + __IO uint32_t ENABLESTATUS; + __IO uint32_t FSSPKLEN; + __I uint32_t resvdA4; + __IO uint32_t CLRRESTARTDET; + __I uint32_t resvdac[981]; + } CLR; +} I2C_TypeDef; + +typedef struct { + __IO uint32_t CS; + __IO uint32_t RESULT; + __IO uint32_t FCS; + __IO uint32_t FIFO; + __IO uint32_t DIV; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __IO uint32_t INTS; + __I uint32_t resvd24[1015]; +struct { + __IO uint32_t CS; + __IO uint32_t RESULT; + __IO uint32_t FCS; + __IO uint32_t FIFO; + __IO uint32_t DIV; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __IO uint32_t INTS; + __I uint32_t resvd24[1015]; + } XOR; +struct { + __IO uint32_t CS; + __IO uint32_t RESULT; + __IO uint32_t FCS; + __IO uint32_t FIFO; + __IO uint32_t DIV; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __IO uint32_t INTS; + __I uint32_t resvd24[1015]; + } SET; +struct { + __IO uint32_t CS; + __IO uint32_t RESULT; + __IO uint32_t FCS; + __IO uint32_t FIFO; + __IO uint32_t DIV; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __IO uint32_t INTS; + __I uint32_t resvd24[1015]; + } CLR; +} ADC_TypeDef; + +typedef struct { + struct { + __IO uint32_t CSR; + __IO uint32_t DIV; + __IO uint32_t CTR; + __IO uint32_t CC; + __IO uint32_t TOP; + } CH[8]; + __IO uint32_t EN; + __IO uint32_t INTR; + union { + __IO uint32_t INTE; + __IO uint32_t IRQ0_INTE; + }; + union { + __IO uint32_t INTF; + __IO uint32_t IRQ0_INTF; + }; + union { + __I uint32_t INTS; + __I uint32_t IRQ0_INTS; + }; + __I uint32_t resvdpwm[979]; + struct { + struct { + __IO uint32_t CSR; + __IO uint32_t DIV; + __IO uint32_t CTR; + __IO uint32_t CC; + __IO uint32_t TOP; + } CH[8]; + __IO uint32_t EN; + __IO uint32_t INTR; + union { + __IO uint32_t INTE; + __IO uint32_t IRQ0_INTE; + }; + union { + __IO uint32_t INTF; + __IO uint32_t IRQ0_INTF; + }; + union { + __I uint32_t INTS; + __I uint32_t IRQ0_INTS; + }; + __I uint32_t resvdpwm[979]; + } XOR; + struct { + struct { + __IO uint32_t CSR; + __IO uint32_t DIV; + __IO uint32_t CTR; + __IO uint32_t CC; + __IO uint32_t TOP; + } CH[8]; + __IO uint32_t EN; + __IO uint32_t INTR; + union { + __IO uint32_t INTE; + __IO uint32_t IRQ0_INTE; + }; + union { + __IO uint32_t INTF; + __IO uint32_t IRQ0_INTF; + }; + union { + __I uint32_t INTS; + __I uint32_t IRQ0_INTS; + }; + __I uint32_t resvdpwm[979]; + } SET; + struct { + struct { + __IO uint32_t CSR; + __IO uint32_t DIV; + __IO uint32_t CTR; + __IO uint32_t CC; + __IO uint32_t TOP; + } CH[8]; + __IO uint32_t EN; + __IO uint32_t INTR; + union { + __IO uint32_t INTE; + __IO uint32_t IRQ0_INTE; + }; + union { + __IO uint32_t INTF; + __IO uint32_t IRQ0_INTF; + }; + union { + __I uint32_t INTS; + __I uint32_t IRQ0_INTS; + }; + __I uint32_t resvdpwm[979]; + } CLR; +} PWM_TypeDef; + +typedef struct { + __IO uint32_t DEVADDRCTRL; + __IO uint32_t INTEPADDRCTRL[15]; /* USB_HOST_INTERRUPT_ENDPOINTS */ + __IO uint32_t MAINCTRL; + __IO uint32_t SOFRW; + __I uint32_t SOFRD; + __IO uint32_t SIECTRL; + __IO uint32_t SIESTATUS; + __IO uint32_t INTEPCTRL; + __IO uint32_t BUFSTATUS; + __IO uint32_t BUFCPUSHOULDHANDLE; + __IO uint32_t ABORT; + __IO uint32_t ABORTDONE; + __IO uint32_t EPSTALLARM; + __IO uint32_t NAKPOLL; + __IO uint32_t EPNAKSTALLSTATUS; + __IO uint32_t MUXING; + __IO uint32_t PWR; + __IO uint32_t PHYDIRECT; + __IO uint32_t PHYDIRECTOVERRIDE; + __IO uint32_t PHYTRIM; + __IO uint32_t LINESTATETUNING; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __IO uint32_t INTS; + __I uint32_t resvd9c[985]; + struct { + __IO uint32_t DEVADDRCTRL; + __IO uint32_t INTEPADDRCTRL[15]; /* USB_HOST_INTERRUPT_ENDPOINTS */ + __IO uint32_t MAINCTRL; + __IO uint32_t SOFRW; + __I uint32_t SOFRD; + __IO uint32_t SIECTRL; + __IO uint32_t SIESTATUS; + __IO uint32_t INTEPCTRL; + __IO uint32_t BUFSTATUS; + __IO uint32_t BUFCPUSHOULDHANDLE; + __IO uint32_t ABORT; + __IO uint32_t ABORTDONE; + __IO uint32_t EPSTALLARM; + __IO uint32_t NAKPOLL; + __IO uint32_t EPNAKSTALLSTATUS; + __IO uint32_t MUXING; + __IO uint32_t PWR; + __IO uint32_t PHYDIRECT; + __IO uint32_t PHYDIRECTOVERRIDE; + __IO uint32_t PHYTRIM; + __IO uint32_t LINESTATETUNING; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __IO uint32_t INTS; + __I uint32_t resvd9c[985]; + } XOR; + struct { + __IO uint32_t DEVADDRCTRL; + __IO uint32_t INTEPADDRCTRL[15]; /* USB_HOST_INTERRUPT_ENDPOINTS */ + __IO uint32_t MAINCTRL; + __IO uint32_t SOFRW; + __I uint32_t SOFRD; + __IO uint32_t SIECTRL; + __IO uint32_t SIESTATUS; + __IO uint32_t INTEPCTRL; + __IO uint32_t BUFSTATUS; + __IO uint32_t BUFCPUSHOULDHANDLE; + __IO uint32_t ABORT; + __IO uint32_t ABORTDONE; + __IO uint32_t EPSTALLARM; + __IO uint32_t NAKPOLL; + __IO uint32_t EPNAKSTALLSTATUS; + __IO uint32_t MUXING; + __IO uint32_t PWR; + __IO uint32_t PHYDIRECT; + __IO uint32_t PHYDIRECTOVERRIDE; + __IO uint32_t PHYTRIM; + __IO uint32_t LINESTATETUNING; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __IO uint32_t INTS; + __I uint32_t resvd9c[985]; + } SET; + struct { + __IO uint32_t DEVADDRCTRL; + __IO uint32_t INTEPADDRCTRL[15]; /* USB_HOST_INTERRUPT_ENDPOINTS */ + __IO uint32_t MAINCTRL; + __IO uint32_t SOFRW; + __I uint32_t SOFRD; + __IO uint32_t SIECTRL; + __IO uint32_t SIESTATUS; + __IO uint32_t INTEPCTRL; + __IO uint32_t BUFSTATUS; + __IO uint32_t BUFCPUSHOULDHANDLE; + __IO uint32_t ABORT; + __IO uint32_t ABORTDONE; + __IO uint32_t EPSTALLARM; + __IO uint32_t NAKPOLL; + __IO uint32_t EPNAKSTALLSTATUS; + __IO uint32_t MUXING; + __IO uint32_t PWR; + __IO uint32_t PHYDIRECT; + __IO uint32_t PHYDIRECTOVERRIDE; + __IO uint32_t PHYTRIM; + __IO uint32_t LINESTATETUNING; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __IO uint32_t INTS; + __I uint32_t resvd9c[985]; + } CLR; +} USB_TypeDef; + +typedef struct { + __IO uint32_t CTRL; + __O uint32_t LOAD; + __I uint32_t REASON; + __IO uint32_t SCRATCH[8]; + __IO uint32_t TICK; + __I uint32_t resvd30[1012]; + struct { + __IO uint32_t CTRL; + __O uint32_t LOAD; + __I uint32_t REASON; + __IO uint32_t SCRATCH[8]; + __IO uint32_t TICK; + __I uint32_t resvd30[1012]; + } XOR; + struct { + __IO uint32_t CTRL; + __O uint32_t LOAD; + __I uint32_t REASON; + __IO uint32_t SCRATCH[8]; + __IO uint32_t TICK; + __I uint32_t resvd30[1012]; + } SET; + struct { + __IO uint32_t CTRL; + __O uint32_t LOAD; + __I uint32_t REASON; + __IO uint32_t SCRATCH[8]; + __IO uint32_t TICK; + __I uint32_t resvd30[1012]; + } CLR; +} WATCHDOG_TypeDef; + +/** + * @brief RP2040 VREG_AND_CHIP_RESET peripheral. + */ +typedef struct { + __IO uint32_t VREG; + __IO uint32_t BOD; + __IO uint32_t CHIP_RESET; +} VREG_AND_CHIP_RESET_TypeDef; + +typedef struct { + __IO uint32_t CTRL; + __I uint32_t FSTAT; + __IO uint32_t FDEBUG; + __I uint32_t FLEVEL; + __O uint32_t TXF[4]; /* NUM_PIO_STATE_MACHINES */ + __I uint32_t RXF[4]; /* NUM_PIO_STATE_MACHINES */ + __IO uint32_t IRQ; + __O uint32_t IRQ_FORCE; + __IO uint32_t INPUT_SYNC_BYPASS; + __IO uint32_t DBG_PADOUT; + __IO uint32_t DBG_PADOE; + __IO uint32_t DBG_CFGINFO; + __O uint32_t INSTR_MEM[32]; + struct { + __IO uint32_t CLKDIV; + __IO uint32_t EXECCTRL; + __IO uint32_t SHIFTCTRL; + __I uint32_t ADDR; + __IO uint32_t INSTR; + __IO uint32_t PINCTRL; + } SM[4]; /* NUM_PIO_STATE_MACHINES */ + __IO uint32_t INTR; + __IO uint32_t IRQ0_INTE; + __IO uint32_t IRQ0_INTF; + __I uint32_t IRQ0_INTS; + __IO uint32_t IRQ1_INTE; + __IO uint32_t IRQ1_INTF; + __I uint32_t IRQ1_INTS; + __I uint32_t resvd144[943]; + struct { + __IO uint32_t CTRL; + __I uint32_t FSTAT; + __IO uint32_t FDEBUG; + __I uint32_t FLEVEL; + __O uint32_t TXF[4]; /* NUM_PIO_STATE_MACHINES */ + __I uint32_t RXF[4]; /* NUM_PIO_STATE_MACHINES */ + __IO uint32_t IRQ; + __O uint32_t IRQ_FORCE; + __IO uint32_t INPUT_SYNC_BYPASS; + __IO uint32_t DBG_PADOUT; + __IO uint32_t DBG_PADOE; + __IO uint32_t DBG_CFGINFO; + __O uint32_t INSTR_MEM[32]; + struct { + __IO uint32_t CLKDIV; + __IO uint32_t EXECCTRL; + __IO uint32_t SHIFTCTRL; + __I uint32_t ADDR; + __IO uint32_t INSTR; + __IO uint32_t PINCTRL; + } SM[4]; /* NUM_PIO_STATE_MACHINES */ + __IO uint32_t INTR; + __IO uint32_t IRQ0_INTE; + __IO uint32_t IRQ0_INTF; + __I uint32_t IRQ0_INTS; + __IO uint32_t IRQ1_INTE; + __IO uint32_t IRQ1_INTF; + __I uint32_t IRQ1_INTS; + __I uint32_t resvd144[943]; + } XOR; + struct { + __IO uint32_t CTRL; + __I uint32_t FSTAT; + __IO uint32_t FDEBUG; + __I uint32_t FLEVEL; + __O uint32_t TXF[4]; /* NUM_PIO_STATE_MACHINES */ + __I uint32_t RXF[4]; /* NUM_PIO_STATE_MACHINES */ + __IO uint32_t IRQ; + __O uint32_t IRQ_FORCE; + __IO uint32_t INPUT_SYNC_BYPASS; + __IO uint32_t DBG_PADOUT; + __IO uint32_t DBG_PADOE; + __IO uint32_t DBG_CFGINFO; + __O uint32_t INSTR_MEM[32]; + struct { + __IO uint32_t CLKDIV; + __IO uint32_t EXECCTRL; + __IO uint32_t SHIFTCTRL; + __I uint32_t ADDR; + __IO uint32_t INSTR; + __IO uint32_t PINCTRL; + } SM[4]; /* NUM_PIO_STATE_MACHINES */ + __IO uint32_t INTR; + __IO uint32_t IRQ0_INTE; + __IO uint32_t IRQ0_INTF; + __I uint32_t IRQ0_INTS; + __IO uint32_t IRQ1_INTE; + __IO uint32_t IRQ1_INTF; + __I uint32_t IRQ1_INTS; + __I uint32_t resvd144[943]; + } SET; + struct { + __IO uint32_t CTRL; + __I uint32_t FSTAT; + __IO uint32_t FDEBUG; + __I uint32_t FLEVEL; + __O uint32_t TXF[4]; /* NUM_PIO_STATE_MACHINES */ + __I uint32_t RXF[4]; /* NUM_PIO_STATE_MACHINES */ + __IO uint32_t IRQ; + __O uint32_t IRQ_FORCE; + __IO uint32_t INPUT_SYNC_BYPASS; + __IO uint32_t DBG_PADOUT; + __IO uint32_t DBG_PADOE; + __IO uint32_t DBG_CFGINFO; + __O uint32_t INSTR_MEM[32]; + struct { + __IO uint32_t CLKDIV; + __IO uint32_t EXECCTRL; + __IO uint32_t SHIFTCTRL; + __I uint32_t ADDR; + __IO uint32_t INSTR; + __IO uint32_t PINCTRL; + } SM[4]; /* NUM_PIO_STATE_MACHINES */ + __IO uint32_t INTR; + __IO uint32_t IRQ0_INTE; + __IO uint32_t IRQ0_INTF; + __I uint32_t IRQ0_INTS; + __IO uint32_t IRQ1_INTE; + __IO uint32_t IRQ1_INTF; + __I uint32_t IRQ1_INTS; + __I uint32_t resvd144[943]; + } CLR; +} PIO_TypeDef; + +typedef struct { + __IO uint32_t CTRL; + __I uint32_t STATUS; + __IO uint32_t DORMANT; + __IO uint32_t STARTUP; + __I uint32_t resvd10[3]; + __IO uint32_t COUNT; + __I uint32_t resvd20[1016]; + struct { + __IO uint32_t CTRL; + __I uint32_t STATUS; + __IO uint32_t DORMANT; + __IO uint32_t STARTUP; + __I uint32_t resvd10[3]; + __IO uint32_t COUNT; + __I uint32_t resvd20[1016]; + } XOR; + struct { + __IO uint32_t CTRL; + __I uint32_t STATUS; + __IO uint32_t DORMANT; + __IO uint32_t STARTUP; + __I uint32_t resvd10[3]; + __IO uint32_t COUNT; + __I uint32_t resvd20[1016]; + } SET; + struct { + __IO uint32_t CTRL; + __I uint32_t STATUS; + __IO uint32_t DORMANT; + __IO uint32_t STARTUP; + __I uint32_t resvd10[3]; + __IO uint32_t COUNT; + __I uint32_t resvd20[1016]; + } CLR; +} XOSC_TypeDef; + +typedef struct { + __IO uint32_t CS; + __IO uint32_t PWR; + __IO uint32_t FBDIV_INT; + __IO uint32_t PRIM; + __I uint32_t resvd10[1020]; + struct { + __IO uint32_t CS; + __IO uint32_t PWR; + __IO uint32_t FBDIV_INT; + __IO uint32_t PRIM; + __I uint32_t resvd10[1020]; + } XOR; + struct { + __IO uint32_t CS; + __IO uint32_t PWR; + __IO uint32_t FBDIV_INT; + __IO uint32_t PRIM; + __I uint32_t resvd10[1020]; + } SET; + struct { + __IO uint32_t CS; + __IO uint32_t PWR; + __IO uint32_t FBDIV_INT; + __IO uint32_t PRIM; + __I uint32_t resvd10[1020]; + } CLR; +} PLL_TypeDef; + +typedef struct { + __IO uint32_t CTRL; + __IO uint32_t DIV; + __I uint32_t SELECTED; +} CLOCKS_CLK_TypeDef; + +typedef struct { + __IO uint32_t CTRL; + __I uint32_t STATUS; +} CLOCKS_RESUS_TypeDef; + +typedef struct { + __IO uint32_t REF_KHZ; + __IO uint32_t MIN_KHZ; + __IO uint32_t MAX_KHZ; + __IO uint32_t DELAY; + __IO uint32_t INTERVAL; + __IO uint32_t SRC; + __I uint32_t STATUS; + __I uint32_t RESULT; +} CLOCKS_FC0_TypeDef; + +typedef struct { + CLOCKS_CLK_TypeDef CLK[10]; + CLOCKS_RESUS_TypeDef RESUS; + CLOCKS_FC0_TypeDef FC0; + __IO uint32_t WAKE_EN0; + __IO uint32_t WAKE_EN1; + __IO uint32_t SLEEP_EN0; + __IO uint32_t SLEEP_EN1; + __I uint32_t ENABLED0; + __I uint32_t ENABLED1; + __I uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __I uint32_t INTS; + __I uint32_t resvdC8[974]; + struct { + CLOCKS_CLK_TypeDef CLK[10]; + CLOCKS_RESUS_TypeDef RESUS; + CLOCKS_FC0_TypeDef FC0; + __IO uint32_t WAKE_EN0; + __IO uint32_t WAKE_EN1; + __IO uint32_t SLEEP_EN0; + __IO uint32_t SLEEP_EN1; + __I uint32_t ENABLED0; + __I uint32_t ENABLED1; + __I uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __I uint32_t INTS; + __I uint32_t resvdC8[974]; + } XOR; + struct { + CLOCKS_CLK_TypeDef CLK[10]; + CLOCKS_RESUS_TypeDef RESUS; + CLOCKS_FC0_TypeDef FC0; + __IO uint32_t WAKE_EN0; + __IO uint32_t WAKE_EN1; + __IO uint32_t SLEEP_EN0; + __IO uint32_t SLEEP_EN1; + __I uint32_t ENABLED0; + __I uint32_t ENABLED1; + __I uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __I uint32_t INTS; + __I uint32_t resvdC8[974]; + } SET; + struct { + CLOCKS_CLK_TypeDef CLK[10]; + CLOCKS_RESUS_TypeDef RESUS; + CLOCKS_FC0_TypeDef FC0; + __IO uint32_t WAKE_EN0; + __IO uint32_t WAKE_EN1; + __IO uint32_t SLEEP_EN0; + __IO uint32_t SLEEP_EN1; + __I uint32_t ENABLED0; + __I uint32_t ENABLED1; + __I uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __I uint32_t INTS; + __I uint32_t resvdC8[974]; + } CLR; +} CLOCKS_TypeDef; +/** @} */ + +/** + * @name Base addresses + * @{ + */ +#define __APBPERIPH_BASE 0x40000000U +#define __AHBPERIPH_BASE 0x50000000U +#define __IOPORT_BASE 0xD0000000U + +#define __RESETS_BASE (__APBPERIPH_BASE + 0x0000C000U) +#define __IOUSER0_BASE (__APBPERIPH_BASE + 0x00014000U) +#define __IOQSPI_BASE (__APBPERIPH_BASE + 0x00018000U) +#define __PADSUSER0_BASE (__APBPERIPH_BASE + 0x0001C000U) +#define __PADSQSPI_BASE (__APBPERIPH_BASE + 0x00020000U) +#define __PSM_BASE (__APBPERIPH_BASE + 0x00010000U) +#define __TIMER0_BASE (__APBPERIPH_BASE + 0x00054000U) +#define __UART0_BASE (__APBPERIPH_BASE + 0x00034000U) +#define __UART1_BASE (__APBPERIPH_BASE + 0x00038000U) +#define __SPI0_BASE (__APBPERIPH_BASE + 0x0003C000U) +#define __SPI1_BASE (__APBPERIPH_BASE + 0x00040000U) +#define __I2C0_BASE (__APBPERIPH_BASE + 0x00044000U) +#define __I2C1_BASE (__APBPERIPH_BASE + 0x00048000U) +#define __ADC_BASE (__APBPERIPH_BASE + 0x0004C000U) +#define __PWM_BASE (__APBPERIPH_BASE + 0x00050000U) +#define __WATCHDOG_BASE (__APBPERIPH_BASE + 0x00058000U) +#define __RTC_BASE (__APBPERIPH_BASE + 0x0005C000U) +#define __VREG_AND_CHIP_RESET_BASE (__APBPERIPH_BASE + 0x00064000U) +#define __XOSC_BASE (__APBPERIPH_BASE + 0x00024000U) +#define __CLOCKS_BASE (__APBPERIPH_BASE + 0x00008000U) +#define __PLL_SYS_BASE (__APBPERIPH_BASE + 0x00028000U) +#define __PLL_USB_BASE (__APBPERIPH_BASE + 0x0002C000U) + +#define __XIP_CTRL_BASE 0x14000000U +#define __XIP_SSI_BASE 0x18000000U + +#define __DMA_BASE (__AHBPERIPH_BASE + 0x00000000U) +#define __USB_BASE (__AHBPERIPH_BASE + 0x00110000U) +#define __PIO0_BASE (__AHBPERIPH_BASE + 0x00200000U) +#define __PIO1_BASE (__AHBPERIPH_BASE + 0x00300000U) + +#define __SIO_BASE (__IOPORT_BASE + 0x00000000U) +/** @} */ + +/** + * @name Peripherals + * @{ + */ +#define DMA ((DMA_TypeDef *) __DMA_BASE) +#define IO_BANK0 ((IOUSER_TypeDef *) __IOUSER0_BASE) +#define IO_QSPI ((IOQSPI_TypeDef *) __IOQSPI_BASE) +#define PADS_BANK0 ((PADS_TypeDef *) __PADSUSER0_BASE) +#define PADS_QSPI ((PADS_QSPI_TypeDef *) __PADSQSPI_BASE) +#define PSM ((PSM_TypeDef *) __PSM_BASE) +#define RESETS ((RESETS_TypeDef *) __RESETS_BASE) +#define SIO ((SIO_TypeDef *) __SIO_BASE) +#define TIMER0 ((TIMER_TypeDef *) __TIMER0_BASE) +#define UART0 ((UART_TypeDef *) __UART0_BASE) +#define UART1 ((UART_TypeDef *) __UART1_BASE) +#define RTC ((RTC_TypeDef *) __RTC_BASE) +#define SPI0 ((SPI_TypeDef *) __SPI0_BASE) +#define SPI1 ((SPI_TypeDef *) __SPI1_BASE) +#define I2C0 ((I2C_TypeDef *) __I2C0_BASE) +#define I2C1 ((I2C_TypeDef *) __I2C1_BASE) +#define ADC ((ADC_TypeDef *) __ADC_BASE) +#define PWM ((PWM_TypeDef *) __PWM_BASE) +#define PIO0 ((PIO_TypeDef *) __PIO0_BASE) +#define PIO1 ((PIO_TypeDef *) __PIO1_BASE) +#define USB ((USB_TypeDef *) __USB_BASE) +#define VREG_AND_CHIP_RESET ((VREG_AND_CHIP_RESET_TypeDef *) __VREG_AND_CHIP_RESET_BASE) +#define WATCHDOG ((WATCHDOG_TypeDef *) __WATCHDOG_BASE) +#define XOSC ((XOSC_TypeDef *) __XOSC_BASE) +#define CLOCKS ((CLOCKS_TypeDef *) __CLOCKS_BASE) +#define PLL_SYS ((PLL_TypeDef *) __PLL_SYS_BASE) +#define PLL_USB ((PLL_TypeDef *) __PLL_USB_BASE) +#define XIP_SSI ((SSI_TypeDef *) __XIP_SSI_BASE) +#define XIP_CTRL ((XIP_CTRL_TypeDef *) __XIP_CTRL_BASE) +/** @} */ + +/** + * @name DMA bits definitions + * @{ + */ +#define DMA_CTRL_TRIG_AHB_ERROR (1U << 31) +#define DMA_CTRL_TRIG_READ_ERROR (1U << 30) +#define DMA_CTRL_TRIG_WRITE_ERROR (1U << 29) +#define DMA_CTRL_TRIG_BUSY (1U << 24) +#define DMA_CTRL_TRIG_SNIFF_EN (1U << 23) +#define DMA_CTRL_TRIG_BSWAP (1U << 22) +#define DMA_CTRL_TRIG_IRQ_QUIET (1U << 21) +#define DMA_CTRL_TRIG_TREQ_SEL_Pos 15U +#define DMA_CTRL_TRIG_TREQ_SEL_Msk (0x3FU << DMA_CTRL_TRIG_TREQ_SEL_Pos) +#define DMA_CTRL_TRIG_TREQ_SEL(n) ((n) << DMA_CTRL_TRIG_TREQ_SEL_Pos) +#define DMA_CTRL_TRIG_TREQ_PIO0_TX0 DMA_CTRL_TRIG_TREQ_SEL(0x00U) +#define DMA_CTRL_TRIG_TREQ_PIO0_TX1 DMA_CTRL_TRIG_TREQ_SEL(0x01U) +#define DMA_CTRL_TRIG_TREQ_PIO0_TX2 DMA_CTRL_TRIG_TREQ_SEL(0x02U) +#define DMA_CTRL_TRIG_TREQ_PIO0_TX3 DMA_CTRL_TRIG_TREQ_SEL(0x03U) +#define DMA_CTRL_TRIG_TREQ_PIO0_RX0 DMA_CTRL_TRIG_TREQ_SEL(0x04U) +#define DMA_CTRL_TRIG_TREQ_PIO0_RX1 DMA_CTRL_TRIG_TREQ_SEL(0x05U) +#define DMA_CTRL_TRIG_TREQ_PIO0_RX2 DMA_CTRL_TRIG_TREQ_SEL(0x06U) +#define DMA_CTRL_TRIG_TREQ_PIO0_RX3 DMA_CTRL_TRIG_TREQ_SEL(0x07U) +#define DMA_CTRL_TRIG_TREQ_PIO1_TX0 DMA_CTRL_TRIG_TREQ_SEL(0x08U) +#define DMA_CTRL_TRIG_TREQ_PIO1_TX1 DMA_CTRL_TRIG_TREQ_SEL(0x09U) +#define DMA_CTRL_TRIG_TREQ_PIO1_TX2 DMA_CTRL_TRIG_TREQ_SEL(0x0AU) +#define DMA_CTRL_TRIG_TREQ_PIO1_TX3 DMA_CTRL_TRIG_TREQ_SEL(0x0BU) +#define DMA_CTRL_TRIG_TREQ_PIO1_RX0 DMA_CTRL_TRIG_TREQ_SEL(0x0CU) +#define DMA_CTRL_TRIG_TREQ_PIO1_RX1 DMA_CTRL_TRIG_TREQ_SEL(0x0DU) +#define DMA_CTRL_TRIG_TREQ_PIO1_RX2 DMA_CTRL_TRIG_TREQ_SEL(0x0EU) +#define DMA_CTRL_TRIG_TREQ_PIO1_RX3 DMA_CTRL_TRIG_TREQ_SEL(0x0FU) +#define DMA_CTRL_TRIG_TREQ_SPI0_TX DMA_CTRL_TRIG_TREQ_SEL(0x10U) +#define DMA_CTRL_TRIG_TREQ_SPI0_RX DMA_CTRL_TRIG_TREQ_SEL(0x11U) +#define DMA_CTRL_TRIG_TREQ_SPI1_TX DMA_CTRL_TRIG_TREQ_SEL(0x12U) +#define DMA_CTRL_TRIG_TREQ_SPI1_RX DMA_CTRL_TRIG_TREQ_SEL(0x13U) +#define DMA_CTRL_TRIG_TREQ_UART0_TX DMA_CTRL_TRIG_TREQ_SEL(0x14U) +#define DMA_CTRL_TRIG_TREQ_UART0_RX DMA_CTRL_TRIG_TREQ_SEL(0x15U) +#define DMA_CTRL_TRIG_TREQ_UART1_TX DMA_CTRL_TRIG_TREQ_SEL(0x16U) +#define DMA_CTRL_TRIG_TREQ_UART1_RX DMA_CTRL_TRIG_TREQ_SEL(0x17U) +#define DMA_CTRL_TRIG_TREQ_PWM_WRAP0 DMA_CTRL_TRIG_TREQ_SEL(0x18U) +#define DMA_CTRL_TRIG_TREQ_PWM_WRAP1 DMA_CTRL_TRIG_TREQ_SEL(0x19U) +#define DMA_CTRL_TRIG_TREQ_PWM_WRAP2 DMA_CTRL_TRIG_TREQ_SEL(0x1AU) +#define DMA_CTRL_TRIG_TREQ_PWM_WRAP3 DMA_CTRL_TRIG_TREQ_SEL(0x1BU) +#define DMA_CTRL_TRIG_TREQ_PWM_WRAP4 DMA_CTRL_TRIG_TREQ_SEL(0x1CU) +#define DMA_CTRL_TRIG_TREQ_PWM_WRAP5 DMA_CTRL_TRIG_TREQ_SEL(0x1DU) +#define DMA_CTRL_TRIG_TREQ_PWM_WRAP6 DMA_CTRL_TRIG_TREQ_SEL(0x1EU) +#define DMA_CTRL_TRIG_TREQ_PWM_WRAP7 DMA_CTRL_TRIG_TREQ_SEL(0x1FU) +#define DMA_CTRL_TRIG_TREQ_I2C0_TX DMA_CTRL_TRIG_TREQ_SEL(0x20U) +#define DMA_CTRL_TRIG_TREQ_I2C0_RX DMA_CTRL_TRIG_TREQ_SEL(0x21U) +#define DMA_CTRL_TRIG_TREQ_I2C1_TX DMA_CTRL_TRIG_TREQ_SEL(0x22U) +#define DMA_CTRL_TRIG_TREQ_I2C1_RX DMA_CTRL_TRIG_TREQ_SEL(0x23U) +#define DMA_CTRL_TRIG_TREQ_ADC DMA_CTRL_TRIG_TREQ_SEL(0x24U) +#define DMA_CTRL_TRIG_TREQ_XIP_STREAM DMA_CTRL_TRIG_TREQ_SEL(0x25U) +#define DMA_CTRL_TRIG_TREQ_XIP_SSITX DMA_CTRL_TRIG_TREQ_SEL(0x26U) +#define DMA_CTRL_TRIG_TREQ_XIP_SSIRX DMA_CTRL_TRIG_TREQ_SEL(0x27U) +#define DMA_CTRL_TRIG_TREQ_TIMER0 DMA_CTRL_TRIG_TREQ_SEL(0x3BU) +#define DMA_CTRL_TRIG_TREQ_TIMER1 DMA_CTRL_TRIG_TREQ_SEL(0x3CU) +#define DMA_CTRL_TRIG_TREQ_TIMER2 DMA_CTRL_TRIG_TREQ_SEL(0x3DU) +#define DMA_CTRL_TRIG_TREQ_TIMER3 DMA_CTRL_TRIG_TREQ_SEL(0x3EU) +#define DMA_CTRL_TRIG_TREQ_PERMANENT DMA_CTRL_TRIG_TREQ_SEL(0x3FU) +#define DMA_CTRL_TRIG_CHAIN_TO_Pos 11U +#define DMA_CTRL_TRIG_CHAIN_TO_Msk (15U << DMA_CTRL_TRIG_CHAIN_TO_Pos) +#define DMA_CTRL_TRIG_CHAIN_TO(n) ((n) << DMA_CTRL_TRIG_CHAIN_TO_Pos) +#define DMA_CTRL_TRIG_RING_SEL (1U << 10) +#define DMA_CTRL_TRIG_RING_SIZE_Pos 6U +#define DMA_CTRL_TRIG_RING_SIZE_Msk (15U << DMA_CTRL_TRIG_RING_SIZE_Pos) +#define DMA_CTRL_TRIG_RING_SIZE(n) ((n) << DMA_CTRL_TRIG_RING_SIZE_Pos) +#define DMA_CTRL_TRIG_INCR_WRITE (1U << 5) +#define DMA_CTRL_TRIG_INCR_READ (1U << 4) +#define DMA_CTRL_TRIG_DATA_SIZE_Pos 2U +#define DMA_CTRL_TRIG_DATA_SIZE_Msk (3U << DMA_CTRL_TRIG_DATA_SIZE_Pos) +#define DMA_CTRL_TRIG_DATA_SIZE(n) ((n) << DMA_CTRL_TRIG_DATA_SIZE_Pos) +#define DMA_CTRL_TRIG_DATA_SIZE_BYTE DMA_CTRL_TRIG_DATA_SIZE(0U) +#define DMA_CTRL_TRIG_DATA_SIZE_HWORD DMA_CTRL_TRIG_DATA_SIZE(1U) +#define DMA_CTRL_TRIG_DATA_SIZE_WORD DMA_CTRL_TRIG_DATA_SIZE(2U) +#define DMA_CTRL_TRIG_HIGH_PRIORITY (1U << 1) +#define DMA_CTRL_TRIG_PRIORITY(n) ((n) << 1) +#define DMA_CTRL_TRIG_EN (1U << 0) +/** @} */ + +/** + * @name PSM bits definitions (dangerous) + * @{ + */ +#define PSM_ANY_PROC1 (1U << 16) +#define PSM_ANY_PROC0 (1U << 15) +#define PSM_ANY_SIO (1U << 14) +#define PSM_ANY_VREG_AND_CHIP_RESET (1U << 13) +#define PSM_ANY_XIP (1U << 12) +#define PSM_ANY_SRAM5 (1U << 11) +#define PSM_ANY_SRAM4 (1U << 10) +#define PSM_ANY_SRAM3 (1U << 9) +#define PSM_ANY_SRAM2 (1U << 8) +#define PSM_ANY_SRAM1 (1U << 7) +#define PSM_ANY_SRAM0 (1U << 6) +#define PSM_ANY_ROM (1U << 5) +#define PSM_ANY_BUSFABRIC (1U << 4) +#define PSM_ANY_RESETS (1U << 3) +#define PSM_ANY_CLOCKS (1U << 2) +#define PSM_ANY_XOSC (1U << 1) +#define PSM_ANY_ROSC (1U << 0) +/** @} */ + +/** + * @name RESETS bits definitions + * @{ + */ +#define RESETS_ALLREG_USBCTRL (1U << 24) +#define RESETS_ALLREG_UART1 (1U << 23) +#define RESETS_ALLREG_UART0 (1U << 22) +#define RESETS_ALLREG_TIMER0 (1U << 21) +#define RESETS_ALLREG_TBMAN (1U << 20) +#define RESETS_ALLREG_SYSINFO (1U << 19) +#define RESETS_ALLREG_SYSCFG (1U << 18) +#define RESETS_ALLREG_SPI1 (1U << 17) +#define RESETS_ALLREG_SPI0 (1U << 16) +#define RESETS_ALLREG_RTC (1U << 15) +#define RESETS_ALLREG_PWM (1U << 14) +#define RESETS_ALLREG_PLL_USB (1U << 13) +#define RESETS_ALLREG_PLL_SYS (1U << 12) +#define RESETS_ALLREG_PIO1 (1U << 11) +#define RESETS_ALLREG_PIO0 (1U << 10) +#define RESETS_ALLREG_PADS_QSPI (1U << 9) +#define RESETS_ALLREG_PADS_BANK0 (1U << 8) +#define RESETS_ALLREG_JTAG (1U << 7) +#define RESETS_ALLREG_IO_QSPI (1U << 6) +#define RESETS_ALLREG_IO_BANK0 (1U << 5) +#define RESETS_ALLREG_I2C1 (1U << 4) +#define RESETS_ALLREG_I2C0 (1U << 3) +#define RESETS_ALLREG_DMA (1U << 2) +#define RESETS_ALLREG_BUSCTRL (1U << 1) +#define RESETS_ALLREG_ADC (1U << 0) +/** @} */ + +/** + * @name SIO bits definitions + * @{ + */ +#define SIO_FIFO_ST_VLD_Pos 0U +#define SIO_FIFO_ST_VLD_Msk (1U << SIO_FIFO_ST_VLD_Pos) +#define SIO_FIFO_ST_VLD SIO_FIFO_ST_VLD_Msk +#define SIO_FIFO_ST_RDY_Pos 1U +#define SIO_FIFO_ST_RDY_Msk (1U << SIO_FIFO_ST_RDY_Pos) +#define SIO_FIFO_ST_RDY SIO_FIFO_ST_RDY_Msk +#define SIO_FIFO_ST_WOF_Pos 2U +#define SIO_FIFO_ST_WOF_Msk (1U << SIO_FIFO_ST_WOF_Pos) +#define SIO_FIFO_ST_WOF SIO_FIFO_ST_WOF_Msk +#define SIO_FIFO_ST_ROE_Pos 3U +#define SIO_FIFO_ST_ROE_Msk (1U << SIO_FIFO_ST_ROE_Pos) +#define SIO_FIFO_ST_ROE SIO_FIFO_ST_ROE_Msk +/** @} */ + +/** + * @name SPI bits definitions + * @{ + */ +#define SPI_SSPCR0_SCR_Pos 8U +#define SPI_SSPCR0_SCR_Msk (255U << SPI_SSPCR0_SCR_Pos) +#define SPI_SSPCR0_SCR(n) ((n) << SPI_SSPCR0_SCR_Pos) +#define SPI_SSPCR0_SPH_Pos 7U +#define SPI_SSPCR0_SPH_Msk (1U << SPI_SSPCR0_SPH_Pos) +#define SPI_SSPCR0_SPH SPI_SSPCR0_SPH_Msk +#define SPI_SSPCR0_SPO_Pos 6U +#define SPI_SSPCR0_SPO_Msk (1U << SPI_SSPCR0_SPO_Pos) +#define SPI_SSPCR0_SPO SPI_SSPCR0_SPO_Msk +#define SPI_SSPCR0_FRF_Pos 4U +#define SPI_SSPCR0_FRF_Msk (3U << SPI_SSPCR0_FRF_Pos) +#define SPI_SSPCR0_FRF(n) ((n) << SPI_SSPCR0_FRF_Pos) +#define SPI_SSPCR0_FRF_MOTOROLA SPI_SSPCR0_FRF(0U) +#define SPI_SSPCR0_FRF_TI SPI_SSPCR0_FRF(1U) +#define SPI_SSPCR0_FRF_NATIONAL SPI_SSPCR0_FRF(2U) +#define SPI_SSPCR0_DSS_Pos 0U +#define SPI_SSPCR0_DSS_Msk (15U << SPI_SSPCR0_DSS_Pos) +#define SPI_SSPCR0_DSS(n) ((n) << SPI_SSPCR0_DSS_Pos) +#define SPI_SSPCR0_DSS_4BIT SPI_SSPCR0_DSS(3U) +#define SPI_SSPCR0_DSS_5BIT SPI_SSPCR0_DSS(4U) +#define SPI_SSPCR0_DSS_6BIT SPI_SSPCR0_DSS(5U) +#define SPI_SSPCR0_DSS_7BIT SPI_SSPCR0_DSS(6U) +#define SPI_SSPCR0_DSS_8BIT SPI_SSPCR0_DSS(7U) +#define SPI_SSPCR0_DSS_9BIT SPI_SSPCR0_DSS(8U) +#define SPI_SSPCR0_DSS_10BIT SPI_SSPCR0_DSS(9U) +#define SPI_SSPCR0_DSS_11BIT SPI_SSPCR0_DSS(10U) +#define SPI_SSPCR0_DSS_12BIT SPI_SSPCR0_DSS(11U) +#define SPI_SSPCR0_DSS_13BIT SPI_SSPCR0_DSS(12U) +#define SPI_SSPCR0_DSS_14BIT SPI_SSPCR0_DSS(13U) +#define SPI_SSPCR0_DSS_15BIT SPI_SSPCR0_DSS(14U) +#define SPI_SSPCR0_DSS_16BIT SPI_SSPCR0_DSS(15U) + +#define SPI_SSPCR1_SOD_Pos 3U +#define SPI_SSPCR1_SOD_Msk (1U << SPI_SSPCR1_SOD_Pos) +#define SPI_SSPCR1_SOD SPI_SSPCR1_SOD_Msk +#define SPI_SSPCR1_MS_Pos 2U +#define SPI_SSPCR1_MS_Msk (1U << SPI_SSPCR1_MS_Pos) +#define SPI_SSPCR1_MS SPI_SSPCR1_MS_Msk +#define SPI_SSPCR1_SSE_Pos 1U +#define SPI_SSPCR1_SSE_Msk (1U << SPI_SSPCR1_SSE_Pos) +#define SPI_SSPCR1_SSE SPI_SSPCR1_SSE_Msk +#define SPI_SSPCR1_LBM_Pos 0U +#define SPI_SSPCR1_LBM_Msk (1U << SPI_SSPCR1_LBM_Pos) +#define SPI_SSPCR1_LBM SPI_SSPCR1_LBM_Msk + +#define SPI_SSPSR_BSY_Pos 4U +#define SPI_SSPSR_BSY_Msk (1U << SPI_SSPSR_BSY_Pos) +#define SPI_SSPSR_BSY SPI_SSPSR_BSY_Msk +#define SPI_SSPSR_RFF_Pos 3U +#define SPI_SSPSR_RFF_Msk (1U << SPI_SSPSR_RFF_Pos) +#define SPI_SSPSR_RFF SPI_SSPSR_RFF_Msk +#define SPI_SSPSR_RNE_Pos 2U +#define SPI_SSPSR_RNE_Msk (1U << SPI_SSPSR_RNE_Pos) +#define SPI_SSPSR_RNE SPI_SSPSR_RNE_Msk +#define SPI_SSPSR_TNF_Pos 1U +#define SPI_SSPSR_TNF_Msk (1U << SPI_SSPSR_TNF_Pos) +#define SPI_SSPSR_TNF SPI_SSPSR_TNF_Msk +#define SPI_SSPSR_TFE_Pos 0U +#define SPI_SSPSR_TFE_Msk (1U << SPI_SSPSR_TFE_Pos) +#define SPI_SSPSR_TFE SPI_SSPSR_TFE_Msk + +#define SPI_SSPCPSR_CPSDVSR_Pos 0U +#define SPI_SSPCPSR_CPSDVSR_Msk (255U << SPI_SSPCPSR_CPSDVSR_Pos) +#define SPI_SSPCPSR_CPSDVSR(n) ((n) << SPI_SSPCPSR_CPSDVSR_Pos) + +#define SPI_SSPIMSC_TXIM_Pos 3U +#define SPI_SSPIMSC_TXIM_Msk (1U << SPI_SSPIMSC_TXIM_Pos) +#define SPI_SSPIMSC_TXIM SPI_SSPIMSC_TXIM_Msk +#define SPI_SSPIMSC_RXIM_Pos 2U +#define SPI_SSPIMSC_RXIM_Msk (1U << SPI_SSPIMSC_RXIM_Pos) +#define SPI_SSPIMSC_RXIM SPI_SSPIMSC_RXIM_Msk +#define SPI_SSPIMSC_RTIM_Pos 1U +#define SPI_SSPIMSC_RTIM_Msk (1U << SPI_SSPIMSC_RTIM_Pos) +#define SPI_SSPIMSC_RTIM SPI_SSPIMSC_RTIM_Msk +#define SPI_SSPIMSC_RORIM_Pos 0U +#define SPI_SSPIMSC_RORIM_Msk (1U << SPI_SSPIMSC_RORIM_Pos) +#define SPI_SSPIMSC_RORIM SPI_SSPIMSC_RORIM_Msk + +#define SPI_SSPRIS_TXRIS_Pos 3U +#define SPI_SSPRIS_TXRIS_Msk (1U << SPI_SSPRIS_TXRIS_Pos) +#define SPI_SSPRIS_TXRIS SPI_SSPRIS_TXRIS_Msk +#define SPI_SSPRIS_RXRIS_Pos 2U +#define SPI_SSPRIS_RXRIS_Msk (1U << SPI_SSPRIS_RXRIS_Pos) +#define SPI_SSPRIS_RXRIS SPI_SSPRIS_RXRIS_Msk +#define SPI_SSPRIS_RTRIS_Pos 1U +#define SPI_SSPRIS_RTRIS_Msk (1U << SPI_SSPRIS_RTRIS_Pos) +#define SPI_SSPRIS_RTRIS SPI_SSPRIS_RTRIS_Msk +#define SPI_SSPRIS_RORRIS_Pos 0U +#define SPI_SSPRIS_RORRIS_Msk (1U << SPI_SSPRIS_RORRIS_Pos) +#define SPI_SSPRIS_RORRIS SPI_SSPRIS_RORRIS_Msk + +#define SPI_SSPMIS_TXMIS_Pos 3U +#define SPI_SSPMIS_TXMIS_Msk (1U << SPI_SSPMIS_TXMIS_Pos) +#define SPI_SSPMIS_TXMIS SPI_SSPMIS_TXMIS_Msk +#define SPI_SSPMIS_RXMIS_Pos 2U +#define SPI_SSPMIS_RXMIS_Msk (1U << SPI_SSPMIS_RXMIS_Pos) +#define SPI_SSPMIS_RXMIS SPI_SSPMIS_RXMIS_Msk +#define SPI_SSPMIS_RTMIS_Pos 1U +#define SPI_SSPMIS_RTMIS_Msk (1U << SPI_SSPMIS_RTMIS_Pos) +#define SPI_SSPMIS_RTMIS SPI_SSPMIS_RTMIS_Msk +#define SPI_SSPMIS_RORMIS_Pos 0U +#define SPI_SSPMIS_RORMIS_Msk (1U << SPI_SSPMIS_RORMIS_Pos) +#define SPI_SSPMIS_RORMIS SPI_SSPMIS_RORMIS_Msk + +#define SPI_SSPICR_RTIC_Pos 1U +#define SPI_SSPICR_RTIC_Msk (1U << SPI_SSPICR_RTIC_Pos) +#define SPI_SSPICR_RTIC SPI_SSPICR_RTIC_Msk +#define SPI_SSPICR_RORIC_Pos 0U +#define SPI_SSPICR_RORIC_Msk (1U << SPI_SSPICR_RORIC_Pos) +#define SPI_SSPICR_RORIC SPI_SSPICR_RORIC_Msk + +#define SPI_SSPDMACR_TXDMAE_Pos 1U +#define SPI_SSPDMACR_TXDMAE_Msk (1U << SPI_SSPDMACR_TXDMAE_Pos) +#define SPI_SSPDMACR_TXDMAE SPI_SSPDMACR_TXDMAE_Msk +#define SPI_SSPDMACR_RXDMAE_Pos 0U +#define SPI_SSPDMACR_RXDMAE_Msk (1U << SPI_SSPDMACR_RXDMAE_Pos) +#define SPI_SSPDMACR_RXDMAE SPI_SSPDMACR_RXDMAE_Msk +/** @} */ + +/** + * @name SSI CTRLR0 bits definitions + * @note See RP2040 Datasheet 4.10.13 SSI List of Registers. + * @{ + */ +#define SSI_CTRLR0_DFS_Pos 0U +#define SSI_CTRLR0_DFS_Msk (0xFU << SSI_CTRLR0_DFS_Pos) +#define SSI_CTRLR0_FRF_Pos 4U +#define SSI_CTRLR0_FRF_Msk (0x3U << SSI_CTRLR0_FRF_Pos) +#define SSI_CTRLR0_SCPH (1U << 6) +#define SSI_CTRLR0_SCPOL (1U << 7) +#define SSI_CTRLR0_TMOD_Pos 8U +#define SSI_CTRLR0_TMOD_Msk (0x3U << SSI_CTRLR0_TMOD_Pos) +#define SSI_CTRLR0_TMOD(n) ((n) << SSI_CTRLR0_TMOD_Pos) +#define SSI_CTRLR0_SLV_OE (1U << 10) +#define SSI_CTRLR0_SRL (1U << 11) +#define SSI_CTRLR0_CFS_Pos 12U +#define SSI_CTRLR0_CFS_Msk (0xFU << SSI_CTRLR0_CFS_Pos) +#define SSI_CTRLR0_DFS_32_Pos 16U +#define SSI_CTRLR0_DFS_32_Msk (0x1FU << SSI_CTRLR0_DFS_32_Pos) +#define SSI_CTRLR0_DFS_32(n) ((n) << SSI_CTRLR0_DFS_32_Pos) +#define SSI_CTRLR0_SPI_FRF_Pos 21U +#define SSI_CTRLR0_SPI_FRF_Msk (0x3U << SSI_CTRLR0_SPI_FRF_Pos) +#define SSI_CTRLR0_SPI_FRF(n) ((n) << SSI_CTRLR0_SPI_FRF_Pos) +#define SSI_CTRLR0_SSTE (1U << 24) + +/** TMOD encoded values. */ +#define SSI_CTRLR0_TMOD_TX_AND_RX 0U +#define SSI_CTRLR0_TMOD_TX_ONLY 1U +#define SSI_CTRLR0_TMOD_RX_ONLY 2U +#define SSI_CTRLR0_TMOD_EEPROM_READ 3U + +/** SPI_FRF encoded values. */ +#define SSI_CTRLR0_SPI_FRF_STD 0U +#define SSI_CTRLR0_SPI_FRF_DUAL 1U +#define SSI_CTRLR0_SPI_FRF_QUAD 2U +/** @} */ + +/** + * @name SSI SR (status register) bits definitions + * @{ + */ +#define SSI_SR_BUSY (1U << 0) +#define SSI_SR_TFNF (1U << 1) +#define SSI_SR_TFE (1U << 2) +#define SSI_SR_RFNE (1U << 3) +#define SSI_SR_RFF (1U << 4) +#define SSI_SR_TXE (1U << 5) +#define SSI_SR_DCOL (1U << 6) +/** @} */ + +/** + * @name SSI SPI_CTRLR0 bits definitions + * @{ + */ +#define SSI_SPI_CTRLR0_TRANS_TYPE_Pos 0U +#define SSI_SPI_CTRLR0_TRANS_TYPE_Msk (0x3U << SSI_SPI_CTRLR0_TRANS_TYPE_Pos) +#define SSI_SPI_CTRLR0_TRANS_TYPE(n) ((n) << SSI_SPI_CTRLR0_TRANS_TYPE_Pos) +#define SSI_SPI_CTRLR0_ADDR_L_Pos 2U +#define SSI_SPI_CTRLR0_ADDR_L_Msk (0xFU << SSI_SPI_CTRLR0_ADDR_L_Pos) +#define SSI_SPI_CTRLR0_ADDR_L(n) ((n) << SSI_SPI_CTRLR0_ADDR_L_Pos) +#define SSI_SPI_CTRLR0_INST_L_Pos 8U +#define SSI_SPI_CTRLR0_INST_L_Msk (0x3U << SSI_SPI_CTRLR0_INST_L_Pos) +#define SSI_SPI_CTRLR0_INST_L(n) ((n) << SSI_SPI_CTRLR0_INST_L_Pos) +#define SSI_SPI_CTRLR0_WAIT_CYCLES_Pos 11U +#define SSI_SPI_CTRLR0_WAIT_CYCLES_Msk (0x1FU << SSI_SPI_CTRLR0_WAIT_CYCLES_Pos) +#define SSI_SPI_CTRLR0_WAIT_CYCLES(n) ((n) << SSI_SPI_CTRLR0_WAIT_CYCLES_Pos) +#define SSI_SPI_CTRLR0_SPI_DDR_EN (1U << 16) +#define SSI_SPI_CTRLR0_INST_DDR_EN (1U << 17) +#define SSI_SPI_CTRLR0_SPI_RXDS_EN (1U << 18) +#define SSI_SPI_CTRLR0_XIP_CMD_Pos 24U +#define SSI_SPI_CTRLR0_XIP_CMD_Msk (0xFFU << SSI_SPI_CTRLR0_XIP_CMD_Pos) +#define SSI_SPI_CTRLR0_XIP_CMD(n) ((n) << SSI_SPI_CTRLR0_XIP_CMD_Pos) + +/** TRANS_TYPE encoded values. */ +#define SSI_SPI_CTRLR0_TRANS_TYPE_1C1A 0U +#define SSI_SPI_CTRLR0_TRANS_TYPE_1C2A 1U +#define SSI_SPI_CTRLR0_TRANS_TYPE_2C2A 2U + +/** INST_L encoded values. */ +#define SSI_SPI_CTRLR0_INST_L_NONE 0U +#define SSI_SPI_CTRLR0_INST_L_4B 1U +#define SSI_SPI_CTRLR0_INST_L_8B 2U +#define SSI_SPI_CTRLR0_INST_L_16B 3U +/** @} */ + +/** + * @name XIP_CTRL bits definitions + * @note See RP2040 Datasheet 2.6.3.1 XIP Cache Control. + * @{ + */ +#define XIP_CTRL_CTRL_EN (1U << 0) +#define XIP_CTRL_CTRL_ERR_BADWRITE (1U << 1) +#define XIP_CTRL_CTRL_POWER_DOWN (1U << 3) +#define XIP_CTRL_STAT_FLUSH_READY (1U << 0) +#define XIP_CTRL_STAT_FIFO_EMPTY (1U << 1) +#define XIP_CTRL_STAT_FIFO_FULL (1U << 2) +/** @} */ + +/** + * @name PADS QSPI control bits definitions + * @note See RP2040 Datasheet 2.19.6.3 PADS_QSPI. + * @{ + */ +#define PADS_QSPI_SLEWFAST (1U << 0) +#define PADS_QSPI_SCHMITT (1U << 1) +#define PADS_QSPI_PDE (1U << 2) +#define PADS_QSPI_PUE (1U << 3) +#define PADS_QSPI_DRIVE_Pos 4U +#define PADS_QSPI_DRIVE_Msk (0x3U << PADS_QSPI_DRIVE_Pos) +#define PADS_QSPI_DRIVE(n) ((n) << PADS_QSPI_DRIVE_Pos) +#define PADS_QSPI_IE (1U << 6) +#define PADS_QSPI_OD (1U << 7) +/** @} */ + +/** + * @name IO QSPI GPIO_QSPI_SS_CTRL OUTOVER values + * @note See RP2040 Datasheet 2.19.6.1 IO_QSPI Register List. + * @{ + */ +#define IOQSPI_CTRL_OUTOVER_Pos 8U +#define IOQSPI_CTRL_OUTOVER_Msk (0x3U << IOQSPI_CTRL_OUTOVER_Pos) +#define IOQSPI_CTRL_OUTOVER(n) ((n) << IOQSPI_CTRL_OUTOVER_Pos) +#define IOQSPI_CTRL_OUTOVER_NORMAL 0U +#define IOQSPI_CTRL_OUTOVER_INVERT 1U +#define IOQSPI_CTRL_OUTOVER_LOW 2U +#define IOQSPI_CTRL_OUTOVER_HIGH 3U +/** @} */ + +/** + * @name TIMER bits definitions + * @{ + */ +#define TIMER_ARMED_ALARM0_Pos 0U +#define TIMER_ARMED_ALARM0_Msk (1U << TIMER_ARMED_ALARM0_Pos) +#define TIMER_ARMED_ALARM0 TIMER_ARMED_ALARM0_Msk +#define TIMER_ARMED_ALARM1_Pos 1U +#define TIMER_ARMED_ALARM1_Msk (1U << TIMER_ARMED_ALARM1_Pos) +#define TIMER_ARMED_ALARM1 TIMER_ARMED_ALARM1_Msk +#define TIMER_ARMED_ALARM2_Pos 2U +#define TIMER_ARMED_ALARM2_Msk (1U << TIMER_ARMED_ALARM2_Pos) +#define TIMER_ARMED_ALARM2 TIMER_ARMED_ALARM2_Msk +#define TIMER_ARMED_ALARM3_Pos 3U +#define TIMER_ARMED_ALARM3_Msk (1U << TIMER_ARMED_ALARM3_Pos) +#define TIMER_ARMED_ALARM3 TIMER_ARMED_ALARM3_Msk + +#define TIMER_DBGPAUSE_DBG0_Pos 1U +#define TIMER_DBGPAUSE_DBG0_Msk (1U << TIMER_DBGPAUSE_DBG0_Pos) +#define TIMER_DBGPAUSE_DBG0 TIMER_DBGPAUSE_DBG0_Msk +#define TIMER_DBGPAUSE_DBG1_Pos 2U +#define TIMER_DBGPAUSE_DBG1_Msk (1U << TIMER_DBGPAUSE_DBG1_Pos) +#define TIMER_DBGPAUSE_DBG1 TIMER_DBGPAUSE_DBG1_Msk + +#define TIMER_PAUSE_PAUSE_Pos 0U +#define TIMER_PAUSE_PAUSE_Msk (1U << TIMER_PAUSE_PAUSE_Pos) +#define TIMER_PAUSE_PAUSE TIMER_PAUSE_PAUSE_Msk + +#define TIMER_INTR_ALARM0_Pos 0U +#define TIMER_INTR_ALARM0_Msk (1U << TIMER_INTR_ALARM0_Pos) +#define TIMER_INTR_ALARM0 TIMER_INTR_ALARM0_Msk +#define TIMER_INTR_ALARM1_Pos 1U +#define TIMER_INTR_ALARM1_Msk (1U << TIMER_INTR_ALARM1_Pos) +#define TIMER_INTR_ALARM1 TIMER_INTR_ALARM1_Msk +#define TIMER_INTR_ALARM2_Pos 2U +#define TIMER_INTR_ALARM2_Msk (1U << TIMER_INTR_ALARM2_Pos) +#define TIMER_INTR_ALARM2 TIMER_INTR_ALARM2_Msk +#define TIMER_INTR_ALARM3_Pos 3U +#define TIMER_INTR_ALARM3_Msk (1U << TIMER_INTR_ALARM3_Pos) +#define TIMER_INTR_ALARM3 TIMER_INTR_ALARM3_Msk + +#define TIMER_INTE_ALARM0_Pos 0U +#define TIMER_INTE_ALARM0_Msk (1U << TIMER_INTE_ALARM0_Pos) +#define TIMER_INTE_ALARM0 TIMER_INTE_ALARM0_Msk +#define TIMER_INTE_ALARM1_Pos 1U +#define TIMER_INTE_ALARM1_Msk (1U << TIMER_INTE_ALARM1_Pos) +#define TIMER_INTE_ALARM1 TIMER_INTE_ALARM1_Msk +#define TIMER_INTE_ALARM2_Pos 2U +#define TIMER_INTE_ALARM2_Msk (1U << TIMER_INTE_ALARM2_Pos) +#define TIMER_INTE_ALARM2 TIMER_INTE_ALARM2_Msk +#define TIMER_INTE_ALARM3_Pos 3U +#define TIMER_INTE_ALARM3_Msk (1U << TIMER_INTE_ALARM3_Pos) +#define TIMER_INTE_ALARM3 TIMER_INTE_ALARM3_Msk + +#define TIMER_INTF_ALARM0_Pos 0U +#define TIMER_INTF_ALARM0_Msk (1U << TIMER_INTF_ALARM0_Pos) +#define TIMER_INTF_ALARM0 TIMER_INTF_ALARM0_Msk +#define TIMER_INTF_ALARM1_Pos 1U +#define TIMER_INTF_ALARM1_Msk (1U << TIMER_INTF_ALARM1_Pos) +#define TIMER_INTF_ALARM1 TIMER_INTF_ALARM1_Msk +#define TIMER_INTF_ALARM2_Pos 2U +#define TIMER_INTF_ALARM2_Msk (1U << TIMER_INTF_ALARM2_Pos) +#define TIMER_INTF_ALARM2 TIMER_INTF_ALARM2_Msk +#define TIMER_INTF_ALARM3_Pos 3U +#define TIMER_INTF_ALARM3_Msk (1U << TIMER_INTF_ALARM3_Pos) +#define TIMER_INTF_ALARM3 TIMER_INTF_ALARM3_Msk + +#define TIMER_INTS_ALARM0_Pos 0U +#define TIMER_INTS_ALARM0_Msk (1U << TIMER_INTS_ALARM0_Pos) +#define TIMER_INTS_ALARM0 TIMER_INTS_ALARM0_Msk +#define TIMER_INTS_ALARM1_Pos 1U +#define TIMER_INTS_ALARM1_Msk (1U << TIMER_INTS_ALARM1_Pos) +#define TIMER_INTS_ALARM1 TIMER_INTS_ALARM1_Msk +#define TIMER_INTS_ALARM2_Pos 2U +#define TIMER_INTS_ALARM2_Msk (1U << TIMER_INTS_ALARM2_Pos) +#define TIMER_INTS_ALARM2 TIMER_INTS_ALARM2_Msk +#define TIMER_INTS_ALARM3_Pos 3U +#define TIMER_INTS_ALARM3_Msk (1U << TIMER_INTS_ALARM3_Pos) +#define TIMER_INTS_ALARM3 TIMER_INTS_ALARM3_Msk +/** @} */ + +/** + * @name UART bits definitions + * @{ + */ +#define UART_UARTDR_OE_Pos 11U +#define UART_UARTDR_OE_Msk (1U << UART_UARTDR_OE_Pos) +#define UART_UARTDR_OE UART_UARTDR_OE_Msk +#define UART_UARTDR_BE_Pos 10U +#define UART_UARTDR_BE_Msk (1U << UART_UARTDR_BE_Pos) +#define UART_UARTDR_BE UART_UARTDR_BE_Msk +#define UART_UARTDR_PE_Pos 9U +#define UART_UARTDR_PE_Msk (1U << UART_UARTDR_PE_Pos) +#define UART_UARTDR_PE UART_UARTDR_PE_Msk +#define UART_UARTDR_FE_Pos 8U +#define UART_UARTDR_FE_Msk (1U << UART_UARTDR_FE_Pos) +#define UART_UARTDR_FE UART_UARTDR_FE_Msk + +#define UART_UARTRSR_OE_Pos 3U +#define UART_UARTRSR_OE_Msk (1U << UART_UARTRSR_OE_Pos) +#define UART_UARTRSR_OE UART_UARTRSR_OE_Msk +#define UART_UARTRSR_BE_Pos 2U +#define UART_UARTRSR_BE_Msk (1U << UART_UARTRSR_BE_Pos) +#define UART_UARTRSR_BE UART_UARTRSR_BE_Msk +#define UART_UARTRSR_PE_Pos 1U +#define UART_UARTRSR_PE_Msk (1U << UART_UARTRSR_PE_Pos) +#define UART_UARTRSR_PE UART_UARTRSR_PE_Msk +#define UART_UARTRSR_FE_Pos 0U +#define UART_UARTRSR_FE_Msk (1U << UART_UARTRSR_FE_Pos) +#define UART_UARTRSR_FE UART_UARTRSR_FE_Msk + +#define UART_UARTFR_RI_Pos 8U +#define UART_UARTFR_RI_Msk (1U << UART_UARTFR_RI_Pos) +#define UART_UARTFR_RI UART_UARTFR_RI_Msk +#define UART_UARTFR_TXFE_Pos 7U +#define UART_UARTFR_TXFE_Msk (1U << UART_UARTFR_TXFE_Pos) +#define UART_UARTFR_TXFE UART_UARTFR_TXFE_Msk +#define UART_UARTFR_RXFF_Pos 6U +#define UART_UARTFR_RXFF_Msk (1U << UART_UARTFR_RXFF_Pos) +#define UART_UARTFR_RXFF UART_UARTFR_RXFF_Msk +#define UART_UARTFR_TXFF_Pos 5U +#define UART_UARTFR_TXFF_Msk (1U << UART_UARTFR_TXFF_Pos) +#define UART_UARTFR_TXFF UART_UARTFR_TXFF_Msk +#define UART_UARTFR_RXFE_Pos 4U +#define UART_UARTFR_RXFE_Msk (1U << UART_UARTFR_RXFE_Pos) +#define UART_UARTFR_RXFE UART_UARTFR_RXFE_Msk +#define UART_UARTFR_BUSY_Pos 3U +#define UART_UARTFR_BUSY_Msk (1U << UART_UARTFR_BUSY_Pos) +#define UART_UARTFR_BUSY UART_UARTFR_BUSY_Msk +#define UART_UARTFR_DCD_Pos 2U +#define UART_UARTFR_DCD_Msk (1U << UART_UARTFR_DCD_Pos) +#define UART_UARTFR_DCD UART_UARTFR_DCD_Msk +#define UART_UARTFR_DSR_Pos 1U +#define UART_UARTFR_DSR_Msk (1U << UART_UARTFR_DSR_Pos) +#define UART_UARTFR_DSR UART_UARTFR_DSR_Msk +#define UART_UARTFR_CTS_Pos 0U +#define UART_UARTFR_CTS_Msk (1U << UART_UARTFR_CTS_Pos) +#define UART_UARTFR_CTS UART_UARTFR_CTS_Msk + +#define UART_UARTILPR_ILPDVSR_Pos 0U +#define UART_UARTILPR_ILPDVSR_Msk (255U << UART_UARTILPR_ILPDVSR_Pos) +#define UART_UARTILPR_ILPDVSR(n) ((n) << UART_UARTILPR_ILPDVSR_Pos) + +#define UART_UARTIBRD_BAUD_DIVINT_Pos 0U +#define UART_UARTIBRD_BAUD_DIVINT_Msk (0xFFFFU << UART_UARTIBRD_BAUD_DIVINT_Pos) +#define UART_UARTIBRD_BAUD_DIVINT(n) ((n) << UART_UARTIBRD_BAUD_DIVINT_Pos) + +#define UART_UARTFBRD_BAUD_DIVFRAC_Pos 0U +#define UART_UARTFBRD_BAUD_DIVFRAC_Msk (63U << UART_UARTFBRD_BAUD_DIVFRAC_Pos) +#define UART_UARTFBRD_BAUD_DIVFRAC(n) ((n) << UART_UARTFBRD_BAUD_DIVFRAC_Pos) + +#define UART_UARTLCR_H_SPS_Pos 7U +#define UART_UARTLCR_H_SPS_Msk (1U << UART_UARTLCR_H_SPS_Pos) +#define UART_UARTLCR_H_SPS UART_UARTLCR_H_SPS_Msk +#define UART_UARTLCR_H_WLEN_Pos 5U +#define UART_UARTLCR_H_WLEN_Msk (1U << UART_UARTLCR_H_WLEN_Pos) +#define UART_UARTLCR_H_WLEN(n) ((n) << UART_UARTLCR_H_WLEN_Pos) +#define UART_UARTLCR_H_WLEN_5BITS UART_UARTLCR_H_WLEN(0U) +#define UART_UARTLCR_H_WLEN_6BITS UART_UARTLCR_H_WLEN(1U) +#define UART_UARTLCR_H_WLEN_7BITS UART_UARTLCR_H_WLEN(2U) +#define UART_UARTLCR_H_WLEN_8BITS UART_UARTLCR_H_WLEN(3U) +#define UART_UARTLCR_H_FEN_Pos 4U +#define UART_UARTLCR_H_FEN_Msk (1U << UART_UARTLCR_H_FEN_Pos) +#define UART_UARTLCR_H_FEN UART_UARTLCR_H_FEN_Msk +#define UART_UARTLCR_H_STP2_Pos 3U +#define UART_UARTLCR_H_STP2_Msk (1U << UART_UARTLCR_H_STP2_Pos) +#define UART_UARTLCR_H_STP2 UART_UARTLCR_H_STP2_Msk +#define UART_UARTLCR_H_EPS_Pos 2U +#define UART_UARTLCR_H_EPS_Msk (1U << UART_UARTLCR_H_EPS_Pos) +#define UART_UARTLCR_H_EPS UART_UARTLCR_H_EPS_Msk +#define UART_UARTLCR_H_PEN_Pos 1U +#define UART_UARTLCR_H_PEN_Msk (1U << UART_UARTLCR_H_PEN_Pos) +#define UART_UARTLCR_H_PEN UART_UARTLCR_H_PEN_Msk +#define UART_UARTLCR_H_BRK_Pos 0U +#define UART_UARTLCR_H_BRK_Msk (1U << UART_UARTLCR_H_BRK_Pos) +#define UART_UARTLCR_H_BRK UART_UARTLCR_H_BRK_Msk + +#define UART_UARTCR_CTSEN_Pos 15U +#define UART_UARTCR_CTSEN_Msk (1U << UART_UARTCR_CTSEN_Pos) +#define UART_UARTCR_CTSEN UART_UARTCR_CTSEN_Msk +#define UART_UARTCR_RTSEN_Pos 14U +#define UART_UARTCR_RTSEN_Msk (1U << UART_UARTCR_RTSEN_Pos) +#define UART_UARTCR_RTSEN UART_UARTCR_RTSEN_Msk +#define UART_UARTCR_OUT2_Pos 13U +#define UART_UARTCR_OUT2_Msk (1U << UART_UARTCR_OUT2_Pos) +#define UART_UARTCR_OUT2 UART_UARTCR_OUT2_Msk +#define UART_UARTCR_OUT1_Pos 12U +#define UART_UARTCR_OUT1_Msk (1U << UART_UARTCR_OUT1_Pos) +#define UART_UARTCR_OUT1 UART_UARTCR_OUT1_Msk +#define UART_UARTCR_RTS_Pos 11U +#define UART_UARTCR_RTS_Msk (1U << UART_UARTCR_RTS_Pos) +#define UART_UARTCR_RTS UART_UARTCR_RTS_Msk +#define UART_UARTCR_DTR_Pos 10U +#define UART_UARTCR_DTR_Msk (1U << UART_UARTCR_DTR_Pos) +#define UART_UARTCR_DTR UART_UARTCR_DTR_Msk +#define UART_UARTCR_RXE_Pos 9U +#define UART_UARTCR_RXE_Msk (1U << UART_UARTCR_RXE_Pos) +#define UART_UARTCR_RXE UART_UARTCR_RXE_Msk +#define UART_UARTCR_TXE_Pos 8U +#define UART_UARTCR_TXE_Msk (1U << UART_UARTCR_TXE_Pos) +#define UART_UARTCR_TXE UART_UARTCR_TXE_Msk +#define UART_UARTCR_LBE_Pos 7U +#define UART_UARTCR_LBE_Msk (1U << UART_UARTCR_LBE_Pos) +#define UART_UARTCR_LBE UART_UARTCR_LBE_Msk +#define UART_UARTCR_SIRLP_Pos 2U +#define UART_UARTCR_SIRLP_Msk (1U << UART_UARTCR_SIRLP_Pos) +#define UART_UARTCR_SIRLP UART_UARTCR_SIRLP_Msk +#define UART_UARTCR_SIREN_Pos 1U +#define UART_UARTCR_SIREN_Msk (1U << UART_UARTCR_SIREN_Pos) +#define UART_UARTCR_SIREN UART_UARTCR_SIREN_Msk +#define UART_UARTCR_UARTEN_Pos 0U +#define UART_UARTCR_UARTEN_Msk (1U << UART_UARTCR_UARTEN_Pos) +#define UART_UARTCR_UARTEN UART_UARTCR_UARTEN_Msk + +#define UART_UARTIFLS_RXIFLSEL_Pos 3U +#define UART_UARTIFLS_RXIFLSEL_Msk (1U << UART_UARTIFLS_RXIFLSEL_Pos) +#define UART_UARTIFLS_RXIFLSEL(n) ((n) << UART_UARTIFLS_RXIFLSEL_Pos) +#define UART_UARTIFLS_RXIFLSEL_1_8F UART_UARTIFLS_RXIFLSEL(0U) +#define UART_UARTIFLS_RXIFLSEL_1_4F UART_UARTIFLS_RXIFLSEL(1U) +#define UART_UARTIFLS_RXIFLSEL_1_2F UART_UARTIFLS_RXIFLSEL(2U) +#define UART_UARTIFLS_RXIFLSEL_3_4F UART_UARTIFLS_RXIFLSEL(3U) +#define UART_UARTIFLS_RXIFLSEL_7_8F UART_UARTIFLS_RXIFLSEL(4U) + +#define UART_UARTIFLS_TXIFLSEL_Pos 3U +#define UART_UARTIFLS_TXIFLSEL_Msk (1U << UART_UARTIFLS_TXIFLSEL_Pos) +#define UART_UARTIFLS_TXIFLSEL(n) ((n) << UART_UARTIFLS_TXIFLSEL_Pos) +#define UART_UARTIFLS_TXIFLSEL_1_8E UART_UARTIFLS_TXIFLSEL(0U) +#define UART_UARTIFLS_TXIFLSEL_1_4E UART_UARTIFLS_TXIFLSEL(1U) +#define UART_UARTIFLS_TXIFLSEL_1_2E UART_UARTIFLS_TXIFLSEL(2U) +#define UART_UARTIFLS_TXIFLSEL_3_4E UART_UARTIFLS_TXIFLSEL(3U) +#define UART_UARTIFLS_TXIFLSEL_7_8E UART_UARTIFLS_TXIFLSEL(4U) + +#define UART_UARTIMSC_OEIM_Pos 10U +#define UART_UARTIMSC_OEIM_Msk (1U << UART_UARTIMSC_OEIM_Pos) +#define UART_UARTIMSC_OEIM UART_UARTIMSC_OEIM_Msk +#define UART_UARTIMSC_BEIM_Pos 9U +#define UART_UARTIMSC_BEIM_Msk (1U << UART_UARTIMSC_BEIM_Pos) +#define UART_UARTIMSC_BEIM UART_UARTIMSC_BEIM_Msk +#define UART_UARTIMSC_PEIM_Pos 8U +#define UART_UARTIMSC_PEIM_Msk (1U << UART_UARTIMSC_PEIM_Pos) +#define UART_UARTIMSC_PEIM UART_UARTIMSC_PEIM_Msk +#define UART_UARTIMSC_FEIM_Pos 7U +#define UART_UARTIMSC_FEIM_Msk (1U << UART_UARTIMSC_FEIM_Pos) +#define UART_UARTIMSC_FEIM UART_UARTIMSC_FEIM_Msk +#define UART_UARTIMSC_RTIM_Pos 6U +#define UART_UARTIMSC_RTIM_Msk (1U << UART_UARTIMSC_RTIM_Pos) +#define UART_UARTIMSC_RTIM UART_UARTIMSC_RTIM_Msk +#define UART_UARTIMSC_TXIM_Pos 5U +#define UART_UARTIMSC_TXIM_Msk (1U << UART_UARTIMSC_TXIM_Pos) +#define UART_UARTIMSC_TXIM UART_UARTIMSC_TXIM_Msk +#define UART_UARTIMSC_RXIM_Pos 4U +#define UART_UARTIMSC_RXIM_Msk (1U << UART_UARTIMSC_RXIM_Pos) +#define UART_UARTIMSC_RXIM UART_UARTIMSC_RXIM_Msk +#define UART_UARTIMSC_DSRMIM_Pos 3U +#define UART_UARTIMSC_DSRMIM_Msk (1U << UART_UARTIMSC_DSRMIM_Pos) +#define UART_UARTIMSC_DSRMIM UART_UARTIMSC_DSRMIM_Msk +#define UART_UARTIMSC_DCDMIM_Pos 2U +#define UART_UARTIMSC_DCDMIM_Msk (1U << UART_UARTIMSC_DCDMIM_Pos) +#define UART_UARTIMSC_DCDMIM UART_UARTIMSC_DCDMIM_Msk +#define UART_UARTIMSC_CTSMIM_Pos 1U +#define UART_UARTIMSC_CTSMIM_Msk (1U << UART_UARTIMSC_CTSMIM_Pos) +#define UART_UARTIMSC_CTSMIM UART_UARTIMSC_CTSMIM_Msk +#define UART_UARTIMSC_RIMIM_Pos 0U +#define UART_UARTIMSC_RIMIM_Msk (1U << UART_UARTIMSC_RIMIM_Pos) +#define UART_UARTIMSC_RIMIM UART_UARTIMSC_RIMIM_Msk + +#define UART_UARTRIS_OERIS_Pos 10U +#define UART_UARTRIS_OERIS_Msk (1U << UART_UARTRIS_OERIS_Pos) +#define UART_UARTRIS_OERIS UART_UARTRIS_OERIS_Msk +#define UART_UARTRIS_BERIS_Pos 9U +#define UART_UARTRIS_BERIS_Msk (1U << UART_UARTRIS_BERIS_Pos) +#define UART_UARTRIS_BERIS UART_UARTRIS_BERIS_Msk +#define UART_UARTRIS_PERIS_Pos 8U +#define UART_UARTRIS_PERIS_Msk (1U << UART_UARTRIS_PERIS_Pos) +#define UART_UARTRIS_PERIS UART_UARTRIS_PERIS_Msk +#define UART_UARTRIS_FERIS_Pos 7U +#define UART_UARTRIS_FERIS_Msk (1U << UART_UARTRIS_FERIS_Pos) +#define UART_UARTRIS_FERIS UART_UARTRIS_FERIS_Msk +#define UART_UARTRIS_RTRIS_Pos 6U +#define UART_UARTRIS_RTRIS_Msk (1U << UART_UARTRIS_RTRIS_Pos) +#define UART_UARTRIS_RTRIS UART_UARTRIS_RTRIS_Msk +#define UART_UARTRIS_TXRIS_Pos 5U +#define UART_UARTRIS_TXRIS_Msk (1U << UART_UARTRIS_TXRIS_Pos) +#define UART_UARTRIS_TXRIS UART_UARTRIS_TXRIS_Msk +#define UART_UARTRIS_RXRIS_Pos 4U +#define UART_UARTRIS_RXRIS_Msk (1U << UART_UARTRIS_RXRIS_Pos) +#define UART_UARTRIS_RXRIS UART_UARTRIS_RXRIS_Msk +#define UART_UARTRIS_DSRRMIS_Pos 3U +#define UART_UARTRIS_DSRRMIS_Msk (1U << UART_UARTRIS_DSRRMIS_Pos) +#define UART_UARTRIS_DSRRMIS UART_UARTRIS_DSRRMIS_Msk +#define UART_UARTRIS_DCDRMIS_Pos 2U +#define UART_UARTRIS_DCDRMIS_Msk (1U << UART_UARTRIS_DCDRMIS_Pos) +#define UART_UARTRIS_DCDRMIS UART_UARTRIS_DCDRMIS_Msk +#define UART_UARTRIS_CTSRMIS_Pos 1U +#define UART_UARTRIS_CTSRMIS_Msk (1U << UART_UARTRIS_CTSRMIS_Pos) +#define UART_UARTRIS_CTSRMIS UART_UARTRIS_CTSRMIS_Msk +#define UART_UARTRIS_RIRMIS_Pos 0U +#define UART_UARTRIS_RIRMIS_Msk (1U << UART_UARTRIS_RIRMIS_Pos) +#define UART_UARTRIS_RIRMIS UART_UARTIMSC_RIRMIS_Msk + +#define UART_UARTMIS_OEMIS_Pos 10U +#define UART_UARTMIS_OEMIS_Msk (1U << UART_UARTMIS_OEMIS_Pos) +#define UART_UARTMIS_OEMIS UART_UARTMIS_OEMIS_Msk +#define UART_UARTMIS_BEMIS_Pos 9U +#define UART_UARTMIS_BEMIS_Msk (1U << UART_UARTMIS_BEMIS_Pos) +#define UART_UARTMIS_BEMIS UART_UARTMIS_BEMIS_Msk +#define UART_UARTMIS_PEMIS_Pos 8U +#define UART_UARTMIS_PEMIS_Msk (1U << UART_UARTMIS_PEMIS_Pos) +#define UART_UARTMIS_PEMIS UART_UARTMIS_PEMIS_Msk +#define UART_UARTMIS_FEMIS_Pos 7U +#define UART_UARTMIS_FEMIS_Msk (1U << UART_UARTMIS_FEMIS_Pos) +#define UART_UARTMIS_FEMIS UART_UARTMIS_FEMIS_Msk +#define UART_UARTMIS_RTMIS_Pos 6U +#define UART_UARTMIS_RTMIS_Msk (1U << UART_UARTMIS_RTMIS_Pos) +#define UART_UARTMIS_RTMIS UART_UARTMIS_RTMIS_Msk +#define UART_UARTMIS_TXMIS_Pos 5U +#define UART_UARTMIS_TXMIS_Msk (1U << UART_UARTMIS_TXMIS_Pos) +#define UART_UARTMIS_TXMIS UART_UARTMIS_TXMIS_Msk +#define UART_UARTMIS_RXMIS_Pos 4U +#define UART_UARTMIS_RXMIS_Msk (1U << UART_UARTMIS_RXMIS_Pos) +#define UART_UARTMIS_RXMIS UART_UARTMIS_RXMIS_Msk +#define UART_UARTMIS_DSRMMIS_Pos 3U +#define UART_UARTMIS_DSRMMIS_Msk (1U << UART_UARTMIS_DSRMMIS_Pos) +#define UART_UARTMIS_DSRRMIS UART_UARTMIS_DSRMMIS_Msk +#define UART_UARTMIS_DCDMMIS_Pos 2U +#define UART_UARTMIS_DCDMMIS_Msk (1U << UART_UARTMIS_DCDMMIS_Pos) +#define UART_UARTMIS_DCDMMIS UART_UARTMIS_DCDMMIS_Msk +#define UART_UARTMIS_CTSMMIS_Pos 1U +#define UART_UARTMIS_CTSMMIS_Msk (1U << UART_UARTMIS_CTSMMIS_Pos) +#define UART_UARTMIS_CTSMMIS UART_UARTMIS_CTSMMIS_Msk +#define UART_UARTMIS_RIMMIS_Pos 0U +#define UART_UARTMIS_RIMMIS_Msk (1U << UART_UARTMIS_RIMMIS_Pos) +#define UART_UARTMIS_RIMMIS UART_UARTIMSC_RIMMIS_Msk + +#define UART_UARTICR_OEIC_Pos 10U +#define UART_UARTICR_OEIC_Msk (1U << UART_UARTICR_OEIC_Pos) +#define UART_UARTICR_OEIC UART_UARTICR_OEIC_Msk +#define UART_UARTICR_BEIC_Pos 9U +#define UART_UARTICR_BEIC_Msk (1U << UART_UARTICR_BEIC_Pos) +#define UART_UARTICR_BEIC UART_UARTICR_BEIC_Msk +#define UART_UARTICR_PEIC_Pos 8U +#define UART_UARTICR_PEIC_Msk (1U << UART_UARTICR_PEIC_Pos) +#define UART_UARTICR_PEIC UART_UARTICR_PEIC_Msk +#define UART_UARTICR_FEIC_Pos 7U +#define UART_UARTICR_FEIC_Msk (1U << UART_UARTICR_FEIC_Pos) +#define UART_UARTICR_FEIC UART_UARTICR_FEIC_Msk +#define UART_UARTICR_RTIC_Pos 6U +#define UART_UARTICR_RTIC_Msk (1U << UART_UARTICR_RTIC_Pos) +#define UART_UARTICR_RTIC UART_UARTICR_RTIC_Msk +#define UART_UARTICR_TXIC_Pos 5U +#define UART_UARTICR_TXIC_Msk (1U << UART_UARTICR_TXIC_Pos) +#define UART_UARTICR_TXIC UART_UARTICR_TXIC_Msk +#define UART_UARTICR_RXIC_Pos 4U +#define UART_UARTICR_RXIC_Msk (1U << UART_UARTICR_RXIC_Pos) +#define UART_UARTICR_RXIC UART_UARTICR_RXIC_Msk +#define UART_UARTICR_DSRMIC_Pos 3U +#define UART_UARTICR_DSRMIC_Msk (1U << UART_UARTICR_DSRMIC_Pos) +#define UART_UARTICR_DSRMIC UART_UARTICR_DSRMIC_Msk +#define UART_UARTICR_DCDMIC_Pos 2U +#define UART_UARTICR_DCDMIC_Msk (1U << UART_UARTICR_DCDMIC_Pos) +#define UART_UARTICR_DCDMIC UART_UARTICR_DCDMIC_Msk +#define UART_UARTICR_CTSMIC_Pos 1U +#define UART_UARTICR_CTSMIC_Msk (1U << UART_UARTICR_CTSMIC_Pos) +#define UART_UARTICR_CTSMIC UART_UARTICR_CTSMIC_Msk +#define UART_UARTICR_RIMIC_Pos 0U +#define UART_UARTICR_RIMIC_Msk (1U << UART_UARTICR_RIMIC_Pos) +#define UART_UARTICR_RIMIC UART_UARTICR_RIMIC_Msk + +#define UART_UARTDMACR_DMAONERR_Pos 2U +#define UART_UARTDMACR_DMAONERR_Msk (1U << UART_UARTDMACR_DMAONERR_Pos) +#define UART_UARTDMACR_DMAONERR UART_UARTDMACR_DMAONERR_Msk +#define UART_UARTDMACR_TXDMAE_Pos 1U +#define UART_UARTDMACR_TXDMAE_Msk (1U << UART_UARTDMACR_TXDMAE_Pos) +#define UART_UARTDMACR_TXDMAE UART_UARTDMACR_TXDMAE_Msk +#define UART_UARTDMACR_RXDMAE_Pos 0U +#define UART_UARTDMACR_RXDMAE_Msk (1U << UART_UARTDMACR_RXDMAE_Pos) +#define UART_UARTDMACR_RXDMAE UART_UARTDMACR_RXDMAE_Msk +/** @} */ + +/** + * @name RTC bits definitions + * @{ + */ +#define RTC_CLKDIV_M1_Pos 0U +#define RTC_CLKDIV_M1_Msk (0xFFFFU << RTC_CLKDIV_M1_Pos) +#define RTC_CLKDIV_M1 RTC_CLKDIV_M1_Msk + +#define RTC_SETUP_0_YEAR_Pos 12U +#define RTC_SETUP_0_YEAR_Msk (0xFFFU << RTC_SETUP_0_YEAR_Pos) +#define RTC_SETUP_0_YEAR(n) ((n) << RTC_SETUP_0_YEAR_Pos) +#define RTC_SETUP_0_MONTH_Pos 8U +#define RTC_SETUP_0_MONTH_Msk (0xFU << RTC_SETUP_0_MONTH_Pos) +#define RTC_SETUP_0_MONTH(n) ((n) << RTC_SETUP_0_MONTH_Pos) +#define RTC_SETUP_0_DAY_Pos 0U +#define RTC_SETUP_0_DAY_Msk (0x1FU << RTC_SETUP_0_DAY_Pos) +#define RTC_SETUP_0_DAY(n) ((n) << RTC_SETUP_0_DAY_Pos) + +#define RTC_SETUP_1_DOTW_Pos 24U +#define RTC_SETUP_1_DOTW_Msk (0x7U << RTC_SETUP_1_DOTW_Pos) +#define RTC_SETUP_1_DOTW(n) ((n) << RTC_SETUP_1_DOTW_Pos) +#define RTC_SETUP_1_HOUR_Pos 16U +#define RTC_SETUP_1_HOUR_Msk (0x1FU << RTC_SETUP_1_HOUR_Pos) +#define RTC_SETUP_1_HOUR(n) ((n) << RTC_SETUP_1_HOUR_Pos) +#define RTC_SETUP_1_MIN_Pos 8U +#define RTC_SETUP_1_MIN_Msk (0x3FU << RTC_SETUP_1_MIN_Pos) +#define RTC_SETUP_1_MIN(n) ((n) << RTC_SETUP_1_MIN_Pos) +#define RTC_SETUP_1_SEC_Pos 0U +#define RTC_SETUP_1_SEC_Msk (0x3FU << RTC_SETUP_1_SEC_Pos) +#define RTC_SETUP_1_SEC(n) ((n) << RTC_SETUP_1_SEC_Pos) + +#define RTC_CTRL_FORCE_NOTLEAPYEAR_Pos 8U +#define RTC_CTRL_FORCE_NOTLEAPYEAR_Msk (1U << RTC_CTRL_FORCE_NOTLEAPYEAR_Pos) +#define RTC_CTRL_FORCE_NOTLEAPYEAR RTC_CTRL_FORCE_NOTLEAPYEAR_Msk + +#define RTC_CTRL_LOAD_Pos 4U +#define RTC_CTRL_LOAD_Msk (1U << RTC_CTRL_LOAD_Pos) +#define RTC_CTRL_LOAD RTC_CTRL_LOAD_Msk + +#define RTC_CTRL_RTC_ACTIVE_Pos 1U +#define RTC_CTRL_RTC_ACTIVE_Msk (1U << RTC_CTRL_RTC_ACTIVE_Pos) +#define RTC_CTRL_RTC_ACTIVE RTC_CTRL_RTC_ACTIVE_Msk + +#define RTC_CTRL_RTC_ENABLE_Pos 0U +#define RTC_CTRL_RTC_ENABLE_Msk (1U << RTC_CTRL_RTC_ENABLE_Pos) +#define RTC_CTRL_RTC_ENABLE RTC_CTRL_RTC_ENABLE_Msk + +#define RTC_IRQ_SETUP_0_MATCH_ACTIVE_Pos 29U +#define RTC_IRQ_SETUP_0_MATCH_ACTIVE_Msk (1U << RTC_IRQ_SETUP_0_MATCH_ACTIVE_Pos) +#define RTC_IRQ_SETUP_0_MATCH_ACTIVE RTC_IRQ_SETUP_0_MATCH_ACTIVE_Msk +#define RTC_IRQ_SETUP_0_MATCH_ENA_Pos 28U +#define RTC_IRQ_SETUP_0_MATCH_ENA_Msk (1U << RTC_IRQ_SETUP_0_MATCH_ENA_Pos) +#define RTC_IRQ_SETUP_0_MATCH_ENA RTC_IRQ_SETUP_0_MATCH_ENA_Msk +#define RTC_IRQ_SETUP_0_YEAR_ENA_Pos 26U +#define RTC_IRQ_SETUP_0_YEAR_ENA_Msk (1U << RTC_IRQ_SETUP_0_YEAR_ENA_Pos) +#define RTC_IRQ_SETUP_0_YEAR_ENA RTC_IRQ_SETUP_0_YEAR_ENA_Msk +#define RTC_IRQ_SETUP_0_MONTH_ENA_Pos 25U +#define RTC_IRQ_SETUP_0_MONTH_ENA_Msk (1U << RTC_IRQ_SETUP_0_MONTH_ENA_Pos) +#define RTC_IRQ_SETUP_0_MONTH_ENA RTC_IRQ_SETUP_0_MONTH_ENA_Msk +#define RTC_IRQ_SETUP_0_DAY_ENA_Pos 24U +#define RTC_IRQ_SETUP_0_DAY_ENA_Msk (1U << RTC_IRQ_SETUP_0_DAY_ENA_Pos) +#define RTC_IRQ_SETUP_0_DAY_ENA RTC_IRQ_SETUP_0_DAY_ENA_Msk + +#define RTC_IRQ_SETUP_0_YEAR_Pos 12U +#define RTC_IRQ_SETUP_0_YEAR_Msk (0xFFFU << RTC_IRQ_SETUP_0_YEAR_Pos) +#define RTC_IRQ_SETUP_0_YEAR(n) ((n) << RTC_IRQ_SETUP_0_YEAR_Pos) +#define RTC_IRQ_SETUP_0_MONTH_Pos 8U +#define RTC_IRQ_SETUP_0_MONTH_Msk (0xFU << RTC_IRQ_SETUP_0_MONTH_Pos) +#define RTC_IRQ_SETUP_0_MONTH(n) ((n) << RTC_IRQ_SETUP_0_MONTH_Pos) +#define RTC_IRQ_SETUP_0_DAY_Pos 0U +#define RTC_IRQ_SETUP_0_DAY_Msk (0x1FU << RTC_IRQ_SETUP_0_DAY_Pos) +#define RTC_IRQ_SETUP_0_DAY(n) ((n) << RTC_IRQ_SETUP_0_DAY_Pos) + +#define RTC_IRQ_SETUP_1_DOTW_ENA_Pos 31U +#define RTC_IRQ_SETUP_1_DOTW_ENA_Msk (1U << RTC_IRQ_SETUP_1_DOTW_ENA_Pos) +#define RTC_IRQ_SETUP_1_DOTW_ENA RTC_IRQ_SETUP_1_DOTW_ENA_Msk +#define RTC_IRQ_SETUP_1_HOUR_ENA_Pos 30U +#define RTC_IRQ_SETUP_1_HOUR_ENA_Msk (1U << RTC_IRQ_SETUP_1_HOUR_ENA_Pos) +#define RTC_IRQ_SETUP_1_HOUR_ENA RTC_IRQ_SETUP_1_HOUR_ENA_Msk +#define RTC_IRQ_SETUP_1_MIN_ENA_Pos 29U +#define RTC_IRQ_SETUP_1_MIN_ENA_Msk (1U << RTC_IRQ_SETUP_1_MIN_ENA_Pos) +#define RTC_IRQ_SETUP_1_MIN_ENA RTC_IRQ_SETUP_1_MIN_ENA_Msk +#define RTC_IRQ_SETUP_1_SEC_ENA_Pos 28U +#define RTC_IRQ_SETUP_1_SEC_ENA_Msk (1U << RTC_IRQ_SETUP_1_SEC_ENA_Pos) +#define RTC_IRQ_SETUP_1_SEC_ENA RTC_IRQ_SETUP_1_SEC_ENA_Msk + +#define RTC_IRQ_SETUP_1_DOTW_Pos 24U +#define RTC_IRQ_SETUP_1_DOTW_Msk (0x7U << RTC_IRQ_SETUP_1_DOTW_Pos) +#define RTC_IRQ_SETUP_1_DOTW(n) ((n) << RTC_IRQ_SETUP_1_DOTW_Pos) +#define RTC_IRQ_SETUP_1_HOUR_Pos 16U +#define RTC_IRQ_SETUP_1_HOUR_Msk (0x1FU << RTC_IRQ_SETUP_1_HOUR_Pos) +#define RTC_IRQ_SETUP_1_HOUR(n) ((n) << RTC_IRQ_SETUP_1_HOUR_Pos) +#define RTC_IRQ_SETUP_1_MIN_Pos 8U +#define RTC_IRQ_SETUP_1_MIN_Msk (0x3FU << RTC_IRQ_SETUP_1_MIN_Pos) +#define RTC_IRQ_SETUP_1_MIN(n) ((n) << RTC_IRQ_SETUP_1_MIN_Pos) +#define RTC_IRQ_SETUP_1_SEC_Pos 0U +#define RTC_IRQ_SETUP_1_SEC_Msk (0x3FU << RTC_IRQ_SETUP_1_SEC_Pos) +#define RTC_IRQ_SETUP_1_SEC(n) ((n) << RTC_IRQ_SETUP_1_SEC_Pos) + +#define RTC_INTR_RTC_Pos 0U +#define RTC_INTR_RTC_Msk (1U << RTC_INTR_RTC_Pos) +#define RTC_INTR_RTC RTC_INTR_RTC_Msk + +#define RTC_INTE_RTC_Pos 0U +#define RTC_INTE_RTC_Msk (1U << RTC_INTE_RTC_Pos) +#define RTC_INTE_RTC RTC_INTE_RTC_Msk + +#define RTC_INTF_RTC_Pos 0U +#define RTC_INTF_RTC_Msk (1U << RTC_INTF_RTC_Pos) +#define RTC_INTF_RTC RTC_INTF_RTC_Msk + +#define RTC_INTS_RTC_Pos 0U +#define RTC_INTS_RTC_Msk (1U << RTC_INTS_RTC_Pos) +#define RTC_INTS_RTC RTC_INTS_RTC_Msk + +/* Normalisation of RTC0 & RTC1 fields read from RTC. */ +#define RTC_RTC_1_YEAR_Pos 12U +#define RTC_RTC_1_YEAR_Msk (0xFFFU << RTC_RTC_1_YEAR_Pos) +#define RTC_RTC_1_YEAR(n) ((n & RTC_RTC_1_YEAR_Msk) >> \ + RTC_RTC_1_YEAR_Pos) +#define RTC_RTC_1_MONTH_Pos 8U +#define RTC_RTC_1_MONTH_Msk (0xFU << RTC_RTC_1_MONTH_Pos) +#define RTC_RTC_1_MONTH(n) ((n & RTC_RTC_1_MONTH_Msk) >> \ + RTC_RTC_1_MONTH_Pos) +#define RTC_RTC_1_DAY_Pos 0U +#define RTC_RTC_1_DAY_Msk (0x1FU << RTC_RTC_1_DAY_Pos) +#define RTC_RTC_1_DAY(n) ((n & RTC_RTC_1_DAY_Msk) >> \ + RTC_RTC_1_DAY_Pos) +#define RTC_RTC_0_DOTW_Pos 24U +#define RTC_RTC_0_DOTW_Msk (0x7U << RTC_RTC_0_DOTW_Pos) +#define RTC_RTC_0_DOTW(n) ((n & RTC_RTC_0_DOTW_Msk) >> \ + RTC_RTC_0_DOTW_Pos) +#define RTC_RTC_0_HOUR_Pos 16U +#define RTC_RTC_0_HOUR_Msk (0x1FU << RTC_RTC_0_HOUR_Pos) +#define RTC_RTC_0_HOUR(n) ((n & RTC_RTC_0_HOUR_Msk) >> \ + RTC_RTC_0_HOUR_Pos) +#define RTC_RTC_0_MIN_Pos 8U +#define RTC_RTC_0_MIN_Msk (0x3FU << RTC_RTC_0_MIN_Pos) +#define RTC_RTC_0_MIN(n) ((n & RTC_RTC_0_MIN_Msk) >> \ + RTC_RTC_0_MIN_Pos) +#define RTC_RTC_0_SEC_Pos 0U +#define RTC_RTC_0_SEC_Msk (0x3FU << RTC_RTC_0_SEC_Pos) +#define RTC_RTC_0_SEC(n) ((n & RTC_RTC_0_SEC_Msk) >> \ + RTC_RTC_0_SEC_Pos) +/** @} */ + +/** + * @name WATCHDOG bits definitions + * @{ + */ +#define WATCHDOG_CTRL_TRIGGER_Pos 31U +#define WATCHDOG_CTRL_TRIGGER_Msk (1U << WATCHDOG_CTRL_TRIGGER_Pos) +#define WATCHDOG_CTRL_TRIGGER WATCHDOG_CTRL_TRIGGER_Msk +#define WATCHDOG_CTRL_ENABLE_Pos 30U +#define WATCHDOG_CTRL_ENABLE_Msk (1U << WATCHDOG_CTRL_ENABLE_Pos) +#define WATCHDOG_CTRL_ENABLE WATCHDOG_CTRL_ENABLE_Msk +#define WATCHDOG_CTRL_PAUSE_DBG1_Pos 26U +#define WATCHDOG_CTRL_PAUSE_DBG1_Msk (1U << WATCHDOG_CTRL_PAUSE_DBG1_Pos) +#define WATCHDOG_CTRL_PAUSE_DBG1 WATCHDOG_CTRL_PAUSE_DBG1_Msk +#define WATCHDOG_CTRL_PAUSE_DBG0_Pos 25U +#define WATCHDOG_CTRL_PAUSE_DBG0_Msk (1U << WATCHDOG_CTRL_PAUSE_DBG0_Pos) +#define WATCHDOG_CTRL_PAUSE_DBG0 WATCHDOG_CTRL_PAUSE_DBG0_Msk +#define WATCHDOG_CTRL_PAUSE_JTAG_Pos 24U +#define WATCHDOG_CTRL_PAUSE_JTAG_Msk (1U << WATCHDOG_CTRL_PAUSE_JTAG_Pos) +#define WATCHDOG_CTRL_PAUSE_JTAG WATCHDOG_CTRL_PAUSE_JTAG_Msk +#define WATCHDOG_CTRL_TIME_Pos 0U +#define WATCHDOG_CTRL_TIME_Msk (0xFFFFFFU << WATCHDOG_CTRL_TIME_Pos) +#define WATCHDOG_CTRL_TIME WATCHDOG_CTRL_TIME_Msk + +#define WATCHDOG_LOAD_Pos 0U +#define WATCHDOG_LOAD_Msk (0xFFFFFFU << WATCHDOG_LOAD_Pos) +#define WATCHDOG_LOAD WATCHDOG_LOAD_Msk + +#define WATCHDOG_REASON_FORCE_Pos 1U +#define WATCHDOG_REASON_FORCE_Msk (1U << WATCHDOG_REASON_FORCE_Pos) +#define WATCHDOG_REASON_FORCE WATCHDOG_REASON_FORCE_Msk +#define WATCHDOG_REASON_TIMER_Pos 0U +#define WATCHDOG_REASON_TIMER_Msk (1U << WATCHDOG_REASON_TIMER_Pos) +#define WATCHDOG_REASON_TIMER WATCHDOG_REASON_TIMER_Msk + +#define WATCHDOG_TICK_COUNT_Pos 11U +#define WATCHDOG_TICK_COUNT_Msk (0xFF800U << WATCHDOG_TICK_COUNT_Pos) +#define WATCHDOG_TICK_COUNT WATCHDOG_TICK_COUNT_Msk +#define WATCHDOG_TICK_RUNNING_Pos 10U +#define WATCHDOG_TICK_RUNNING_Msk (1U << WATCHDOG_TICK_RUNNING_Pos) +#define WATCHDOG_TICK_RUNNING WATCHDOG_TICK_RUNNING_Msk +#define WATCHDOG_TICK_ENABLE_Pos 9U +#define WATCHDOG_TICK_ENABLE_Msk (1U << WATCHDOG_TICK_ENABLE_Pos) +#define WATCHDOG_TICK_ENABLE WATCHDOG_TICK_ENABLE_Msk +#define WATCHDOG_TICK_CYCLES_Pos 0U +#define WATCHDOG_TICK_CYCLES_Msk (0x1FFU << WATCHDOG_TICK_CYCLES_Pos) +#define WATCHDOG_TICK_CYCLES WATCHDOG_TICK_CYCLES_Msk +/** @} */ + +/** + * @name VREG_AND_CHIP_RESET VREG register bits definitions + * @{ + */ +#define VREG_ROK_Pos 12U +#define VREG_ROK_Msk (1U << VREG_ROK_Pos) +#define VREG_ROK VREG_ROK_Msk +#define VREG_VSEL_Pos 4U +#define VREG_VSEL_Msk (0xFU << VREG_VSEL_Pos) +#define VREG_HIZ_Pos 1U +#define VREG_HIZ_Msk (1U << VREG_HIZ_Pos) +#define VREG_HIZ VREG_HIZ_Msk +#define VREG_EN_Pos 0U +#define VREG_EN_Msk (1U << VREG_EN_Pos) +#define VREG_EN VREG_EN_Msk +/** @} */ + +/** + * @name I2C bits definitions + * @{ + */ +#define I2C_IC_CON_STOP_DET_IF_MASTER_ACTIVE_Pos 10U +#define I2C_IC_CON_STOP_DET_IF_MASTER_ACTIVE_Msk (1U << I2C_IC_CON_STOP_DET_IF_MASTER_ACTIVE_Pos) +#define I2C_IC_CON_STOP_DET_IF_MASTER_ACTIVE I2C_IC_CON_STOP_DET_IF_MASTER_ACTIVE_Msk +#define I2C_IC_CON_RX_FIFO_FULL_HLD_CTRL_Pos 9U +#define I2C_IC_CON_RX_FIFO_FULL_HLD_CTRL_Msk (1U << I2C_IC_CON_RX_FIFO_FULL_HLD_CTRL_Pos) +#define I2C_IC_CON_RX_FIFO_FULL_HLD_CTRL I2C_IC_CON_RX_FIFO_FULL_HLD_CTRL_Msk +#define I2C_IC_CON_TX_EMPTY_CTRL_Pos 8U +#define I2C_IC_CON_TX_EMPTY_CTRL_Msk (1U << I2C_IC_CON_TX_EMPTY_CTRL_Pos) +#define I2C_IC_CON_TX_EMPTY_CTRL I2C_IC_CON_TX_EMPTY_CTRL_Msk +#define I2C_IC_CON_STOP_DET_IFADDRESSED_Pos 7U +#define I2C_IC_CON_STOP_DET_IFADDRESSED_Msk (1U << I2C_IC_CON_STOP_DET_IFADDRESSED_Pos) +#define I2C_IC_CON_STOP_DET_IFADDRESSED I2C_IC_CON_STOP_DET_IFADDRESSED_Msk +#define I2C_IC_CON_IC_SLAVE_DISABLE_Pos 6U +#define I2C_IC_CON_IC_SLAVE_DISABLE_Msk (1U << I2C_IC_CON_IC_SLAVE_DISABLE_Pos) +#define I2C_IC_CON_IC_SLAVE_DISABLE I2C_IC_CON_IC_SLAVE_DISABLE_Msk +#define I2C_IC_CON_IC_RESTART_EN_Pos 5U +#define I2C_IC_CON_IC_RESTART_EN_Msk (1U << I2C_IC_CON_IC_RESTART_EN_Pos) +#define I2C_IC_CON_IC_RESTART_EN I2C_IC_CON_IC_RESTART_EN_Msk +#define I2C_IC_CON_IC_10BITADDR_MASTER_Pos 4U +#define I2C_IC_CON_IC_10BITADDR_MASTER_Msk (1U << I2C_IC_CON_IC_10BITADDR_MASTER_Pos) +#define I2C_IC_CON_IC_10BITADDR_MASTER I2C_IC_CON_IC_10BITADDR_MASTER_Msk +#define I2C_IC_CON_IC_10BITADDR_SLAVE_Pos 3U +#define I2C_IC_CON_IC_10BITADDR_SLAVE_Msk (1U << I2C_IC_CON_IC_10BITADDR_SLAVE_Pos) +#define I2C_IC_CON_IC_10BITADDR_SLAVE I2C_IC_CON_IC_10BITADDR_SLAVE_Msk +#define I2C_IC_CON_SPEED_Pos 1U +#define I2C_IC_CON_SPEED_Msk (3U << I2C_IC_CON_SPEED_Pos) +#define I2C_IC_CON_SPEED I2C_IC_CON_SPEED_Msk +#define I2C_IC_CON_MASTER_MODE_Pos 0U +#define I2C_IC_CON_MASTER_MODE_Msk (1U << I2C_IC_CON_MASTER_MODE_Pos) +#define I2C_IC_CON_MASTER_MODE I2C_IC_CON_MASTER_MODE_Msk + +#define I2C_IC_TAR_SPECIAL_Pos 11U +#define I2C_IC_TAR_SPECIAL_Msk (1U << I2C_IC_TAR_SPECIAL_Pos) +#define I2C_IC_TAR_SPECIAL I2C_IC_TAR_SPECIAL_Msk +#define I2C_IC_TAR_GC_OR_START_Pos 10U +#define I2C_IC_TAR_GC_OR_START_Msk (1U << I2C_IC_TAR_GC_OR_START_Pos) +#define I2C_IC_TAR_GC_OR_START I2C_IC_TAR_GC_OR_START_Msk +#define I2C_IC_TAR_IC_TAR_Pos 0U +#define I2C_IC_TAR_IC_TAR_Msk (0x3FFU << I2C_IC_TAR_IC_TAR_Pos) +#define I2C_IC_TAR_IC_TAR I2C_IC_TAR_IC_TAR_Msk + +#define I2C_IC_SAR_IC_SAR_Pos 0U +#define I2C_IC_SAR_IC_SAR_Msk (0x3FFU << I2C_IC_SAR_IC_SAR_Pos) +#define I2C_IC_SAR_IC_SAR I2C_IC_SAR_IC_SAR_Msk + +#define I2C_IC_DATA_CMD_FIRST_DATA_BYTE_Pos 11U +#define I2C_IC_DATA_CMD_FIRST_DATA_BYTE_Msk (1U << I2C_IC_DATA_CMD_FIRST_DATA_BYTE_Pos) +#define I2C_IC_DATA_CMD_FIRST_DATA_BYTE I2C_IC_DATA_CMD_FIRST_DATA_BYTE_Msk +#define I2C_IC_DATA_CMD_RESTART_Pos 10U +#define I2C_IC_DATA_CMD_RESTART_Msk (1U << I2C_IC_DATA_CMD_RESTART_Pos) +#define I2C_IC_DATA_CMD_RESTART I2C_IC_DATA_CMD_RESTART_Msk +#define I2C_IC_DATA_CMD_STOP_Pos 9U +#define I2C_IC_DATA_CMD_STOP_Msk (1U << I2C_IC_DATA_CMD_STOP_Pos) +#define I2C_IC_DATA_CMD_STOP I2C_IC_DATA_CMD_STOP_Msk +#define I2C_IC_DATA_CMD_CMD_Pos 8U +#define I2C_IC_DATA_CMD_CMD_Msk (1U << I2C_IC_DATA_CMD_CMD_Pos) +#define I2C_IC_DATA_CMD_CMD I2C_IC_DATA_CMD_CMD_Msk +#define I2C_IC_DATA_CMD_DAT_Pos 0U +#define I2C_IC_DATA_CMD_DAT_Msk (0xFFU << I2C_IC_DATA_CMD_DAT_Pos) +#define I2C_IC_DATA_CMD_DAT I2C_IC_DATA_CMD_DAT_Msk + +#define I2C_IC_SS_SCL_HCNT_Pos 0U +#define I2C_IC_SS_SCL_HCNT_Msk (0xFFFFU << I2C_IC_SS_SCL_HCNT_Pos) +#define I2C_IC_SS_SCL_HCNT I2C_IC_SS_SCL_HCNT_Msk + +#define I2C_IC_SS_SCL_LCNT_Pos 0U +#define I2C_IC_SS_SCL_LCNT_Msk (0xFFFFU << I2C_IC_SS_SCL_LCNT_Pos) +#define I2C_IC_SS_SCL_LCNT I2C_IC_SS_SCL_LCNT_Msk + +#define I2C_IC_SS_SCL_HCNT_IC_SS_SCL_HCNT_Pos 0U +#define I2C_IC_SS_SCL_HCNT_IC_SS_SCL_HCNT_Msk (0xFFFFU << I2C_IC_SS_SCL_HCNT_IC_SS_SCL_HCNT_Pos) +#define I2C_IC_SS_SCL_HCNT_IC_SS_SCL_HCNT I2C_IC_SS_SCL_HCNT_IC_SS_SCL_HCNT_Msk + +#define I2C_IC_SS_SCL_LCNT_IC_SS_SCL_LCNT_Pos 0U +#define I2C_IC_SS_SCL_LCNT_IC_SS_SCL_LCNT_Msk (0xFFFFU << I2C_IC_SS_SCL_LCNT_IC_SS_SCL_LCNT_Pos) +#define I2C_IC_SS_SCL_LCNT_IC_SS_SCL_LCNT I2C_IC_SS_SCL_LCNT_IC_SS_SCL_LCNT_Msk + +#define I2C_IC_FS_SCL_HCNT_Pos 0U +#define I2C_IC_FS_SCL_HCNT_Msk (0xFFFFU << I2C_IC_FS_SCL_HCNT_Pos) +#define I2C_IC_FS_SCL_HCNT I2C_IC_FS_SCL_HCNT_Msk + +#define I2C_IC_FS_SCL_LCNT_Pos 0U +#define I2C_IC_FS_SCL_LCNT_Msk (0xFFFFU << I2C_IC_FS_SCL_LCNT_Pos) +#define I2C_IC_FS_SCL_LCNT I2C_IC_FS_SCL_LCNT_Msk + +#define I2C_IC_FS_SCL_HCNT_IC_FS_SCL_HCNT_Pos 0U +#define I2C_IC_FS_SCL_HCNT_IC_FS_SCL_HCNT_Msk (0xFFFFU << I2C_IC_FS_SCL_HCNT_IC_FS_SCL_HCNT_Pos) +#define I2C_IC_FS_SCL_HCNT_IC_FS_SCL_HCNT I2C_IC_FS_SCL_HCNT_IC_FS_SCL_HCNT_Msk + +#define I2C_IC_FS_SCL_LCNT_IC_FS_SCL_LCNT_Pos 0U +#define I2C_IC_FS_SCL_LCNT_IC_FS_SCL_LCNT_Msk (0xFFFFU << I2C_IC_FS_SCL_LCNT_IC_FS_SCL_LCNT_Pos) +#define I2C_IC_FS_SCL_LCNT_IC_FS_SCL_LCNT I2C_IC_FS_SCL_LCNT_IC_FS_SCL_LCNT_Msk + +#define I2C_IC_INTR_STAT_R_MASTER_ON_HOLD_Pos 13U +#define I2C_IC_INTR_STAT_R_MASTER_ON_HOLD_Msk (1U << I2C_IC_INTR_STAT_R_MASTER_ON_HOLD_Pos) +#define I2C_IC_INTR_STAT_R_MASTER_ON_HOLD I2C_IC_INTR_STAT_R_MASTER_ON_HOLD_Msk +#define I2C_IC_INTR_STAT_R_RESTART_DET_Pos 12U +#define I2C_IC_INTR_STAT_R_RESTART_DET_Msk (1U << I2C_IC_INTR_STAT_R_RESTART_DET_Pos) +#define I2C_IC_INTR_STAT_R_RESTART_DET I2C_IC_INTR_STAT_R_RESTART_DET_Msk +#define I2C_IC_INTR_STAT_R_GEN_CALL_Pos 11U +#define I2C_IC_INTR_STAT_R_GEN_CALL_Msk (1U << I2C_IC_INTR_STAT_R_GEN_CALL_Pos) +#define I2C_IC_INTR_STAT_R_GEN_CALL I2C_IC_INTR_STAT_R_GEN_CALL_Msk +#define I2C_IC_INTR_STAT_R_START_DET_Pos 10U +#define I2C_IC_INTR_STAT_R_START_DET_Msk (1U << I2C_IC_INTR_STAT_R_START_DET_Pos) +#define I2C_IC_INTR_STAT_R_START_DET I2C_IC_INTR_STAT_R_START_DET_Msk +#define I2C_IC_INTR_STAT_R_STOP_DET_Pos 9U +#define I2C_IC_INTR_STAT_R_STOP_DET_Msk (1U << I2C_IC_INTR_STAT_R_STOP_DET_Pos) +#define I2C_IC_INTR_STAT_R_STOP_DET I2C_IC_INTR_STAT_R_STOP_DET_Msk +#define I2C_IC_INTR_STAT_R_ACTIVITY_Pos 8U +#define I2C_IC_INTR_STAT_R_ACTIVITY_Msk (1U << I2C_IC_INTR_STAT_R_ACTIVITY_Pos) +#define I2C_IC_INTR_STAT_R_ACTIVITY I2C_IC_INTR_STAT_R_ACTIVITY_Msk +#define I2C_IC_INTR_STAT_R_RX_DONE_Pos 7U +#define I2C_IC_INTR_STAT_R_RX_DONE_Msk (1U << I2C_IC_INTR_STAT_R_RX_DONE_Pos) +#define I2C_IC_INTR_STAT_R_RX_DONE I2C_IC_INTR_STAT_R_RX_DONE_Msk +#define I2C_IC_INTR_STAT_R_TX_ABRT_Pos 6U +#define I2C_IC_INTR_STAT_R_TX_ABRT_Msk (1U << I2C_IC_INTR_STAT_R_TX_ABRT_Pos) +#define I2C_IC_INTR_STAT_R_TX_ABRT I2C_IC_INTR_STAT_R_TX_ABRT_Msk +#define I2C_IC_INTR_STAT_R_RD_REQ_Pos 5U +#define I2C_IC_INTR_STAT_R_RD_REQ_Msk (1U << I2C_IC_INTR_STAT_R_RD_REQ_Pos) +#define I2C_IC_INTR_STAT_R_RD_REQ I2C_IC_INTR_STAT_R_RD_REQ_Msk +#define I2C_IC_INTR_STAT_R_TX_EMPTY_Pos 4U +#define I2C_IC_INTR_STAT_R_TX_EMPTY_Msk (1U << I2C_IC_INTR_STAT_R_TX_EMPTY_Pos) +#define I2C_IC_INTR_STAT_R_TX_EMPTY I2C_IC_INTR_STAT_R_TX_EMPTY_Msk +#define I2C_IC_INTR_STAT_R_TX_OVER_Pos 3U +#define I2C_IC_INTR_STAT_R_TX_OVER_Msk (1U << I2C_IC_INTR_STAT_R_TX_OVER_Pos) +#define I2C_IC_INTR_STAT_R_TX_OVER I2C_IC_INTR_STAT_R_TX_OVER_Msk +#define I2C_IC_INTR_STAT_R_RX_FULL_Pos 2U +#define I2C_IC_INTR_STAT_R_RX_FULL_Msk (1U << I2C_IC_INTR_STAT_R_RX_FULL_Pos) +#define I2C_IC_INTR_STAT_R_RX_FULL I2C_IC_INTR_STAT_R_RX_FULL_Msk +#define I2C_IC_INTR_STAT_R_RX_OVER_Pos 1U +#define I2C_IC_INTR_STAT_R_RX_OVER_Msk (1U << I2C_IC_INTR_STAT_R_RX_OVER_Pos) +#define I2C_IC_INTR_STAT_R_RX_OVER I2C_IC_INTR_STAT_R_RX_OVER_Msk +#define I2C_IC_INTR_STAT_R_RX_UNDER_Pos 0U +#define I2C_IC_INTR_STAT_R_RX_UNDER_Msk (1U << I2C_IC_INTR_STAT_R_RX_UNDER_Pos) +#define I2C_IC_INTR_STAT_R_RX_UNDER I2C_IC_INTR_STAT_R_RX_UNDER_Msk + +#define I2C_IC_INTR_MASK_M_MASTER_ON_HOLD_Pos 13U +#define I2C_IC_INTR_MASK_M_MASTER_ON_HOLD_Msk (1U << I2C_IC_INTR_MASK_M_MASTER_ON_HOLD_Pos) +#define I2C_IC_INTR_MASK_M_MASTER_ON_HOLD I2C_IC_INTR_MASK_M_MASTER_ON_HOLD_Msk +#define I2C_IC_INTR_MASK_M_MASTER_ON_HOLD_READ_ONLY I2C_IC_INTR_MASK_M_MASTER_ON_HOLD +#define I2C_IC_INTR_MASK_M_RESTART_DET_Pos 12U +#define I2C_IC_INTR_MASK_M_RESTART_DET_Msk (1U << I2C_IC_INTR_MASK_M_RESTART_DET_Pos) +#define I2C_IC_INTR_MASK_M_RESTART_DET I2C_IC_INTR_MASK_M_RESTART_DET_Msk +#define I2C_IC_INTR_MASK_M_GEN_CALL_Pos 11U +#define I2C_IC_INTR_MASK_M_GEN_CALL_Msk (1U << I2C_IC_INTR_MASK_M_GEN_CALL_Pos) +#define I2C_IC_INTR_MASK_M_GEN_CALL I2C_IC_INTR_MASK_M_GEN_CALL_Msk +#define I2C_IC_INTR_MASK_M_START_DET_Pos 10U +#define I2C_IC_INTR_MASK_M_START_DET_Msk (1U << I2C_IC_INTR_MASK_M_START_DET_Pos) +#define I2C_IC_INTR_MASK_M_START_DET I2C_IC_INTR_MASK_M_START_DET_Msk +#define I2C_IC_INTR_MASK_M_STOP_DET_Pos 9U +#define I2C_IC_INTR_MASK_M_STOP_DET_Msk (1U << I2C_IC_INTR_MASK_M_STOP_DET_Pos) +#define I2C_IC_INTR_MASK_M_STOP_DET I2C_IC_INTR_MASK_M_STOP_DET_Msk +#define I2C_IC_INTR_MASK_M_ACTIVITY_Pos 8U +#define I2C_IC_INTR_MASK_M_ACTIVITY_Msk (1U << I2C_IC_INTR_MASK_M_ACTIVITY_Pos) +#define I2C_IC_INTR_MASK_M_ACTIVITY I2C_IC_INTR_MASK_M_ACTIVITY_Msk +#define I2C_IC_INTR_MASK_M_RX_DONE_Pos 7U +#define I2C_IC_INTR_MASK_M_RX_DONE_Msk (1U << I2C_IC_INTR_MASK_M_RX_DONE_Pos) +#define I2C_IC_INTR_MASK_M_RX_DONE I2C_IC_INTR_MASK_M_RX_DONE_Msk +#define I2C_IC_INTR_MASK_M_TX_ABRT_Pos 6U +#define I2C_IC_INTR_MASK_M_TX_ABRT_Msk (1U << I2C_IC_INTR_MASK_M_TX_ABRT_Pos) +#define I2C_IC_INTR_MASK_M_TX_ABRT I2C_IC_INTR_MASK_M_TX_ABRT_Msk +#define I2C_IC_INTR_MASK_M_RD_REQ_Pos 5U +#define I2C_IC_INTR_MASK_M_RD_REQ_Msk (1U << I2C_IC_INTR_MASK_M_RD_REQ_Pos) +#define I2C_IC_INTR_MASK_M_RD_REQ I2C_IC_INTR_MASK_M_RD_REQ_Msk +#define I2C_IC_INTR_MASK_M_TX_EMPTY_Pos 4U +#define I2C_IC_INTR_MASK_M_TX_EMPTY_Msk (1U << I2C_IC_INTR_MASK_M_TX_EMPTY_Pos) +#define I2C_IC_INTR_MASK_M_TX_EMPTY I2C_IC_INTR_MASK_M_TX_EMPTY_Msk +#define I2C_IC_INTR_MASK_M_TX_OVER_Pos 3U +#define I2C_IC_INTR_MASK_M_TX_OVER_Msk (1U << I2C_IC_INTR_MASK_M_TX_OVER_Pos) +#define I2C_IC_INTR_MASK_M_TX_OVER I2C_IC_INTR_MASK_M_TX_OVER_Msk +#define I2C_IC_INTR_MASK_M_RX_FULL_Pos 2U +#define I2C_IC_INTR_MASK_M_RX_FULL_Msk (1U << I2C_IC_INTR_MASK_M_RX_FULL_Pos) +#define I2C_IC_INTR_MASK_M_RX_FULL I2C_IC_INTR_MASK_M_RX_FULL_Msk +#define I2C_IC_INTR_MASK_M_RX_OVER_Pos 1U +#define I2C_IC_INTR_MASK_M_RX_OVER_Msk (1U << I2C_IC_INTR_MASK_M_RX_OVER_Pos) +#define I2C_IC_INTR_MASK_M_RX_OVER I2C_IC_INTR_MASK_M_RX_OVER_Msk +#define I2C_IC_INTR_MASK_M_RX_UNDER_Pos 0U +#define I2C_IC_INTR_MASK_M_RX_UNDER_Msk (1U << I2C_IC_INTR_MASK_M_RX_UNDER_Pos) +#define I2C_IC_INTR_MASK_M_RX_UNDER I2C_IC_INTR_MASK_M_RX_UNDER_Msk +#define I2C_IC_RAW_INTR_STAT_MASTER_ON_HOLD_Pos 13U +#define I2C_IC_RAW_INTR_STAT_MASTER_ON_HOLD_Msk (1U << I2C_IC_RAW_INTR_STAT_MASTER_ON_HOLD_Pos) +#define I2C_IC_RAW_INTR_STAT_MASTER_ON_HOLD I2C_IC_RAW_INTR_STAT_MASTER_ON_HOLD_Msk +#define I2C_IC_INTR_STAT_M_RESTART_DET_Pos 12U +#define I2C_IC_INTR_STAT_M_RESTART_DET_Msk (1U << I2C_IC_INTR_STAT_M_RESTART_DET_Pos) +#define I2C_IC_INTR_STAT_M_RESTART_DET I2C_IC_INTR_STAT_M_RESTART_DET_Msk +#define I2C_IC_INTR_STAT_M_GEN_CALL_Pos 11U +#define I2C_IC_INTR_STAT_M_GEN_CALL_Msk (1U << I2C_IC_INTR_STAT_M_GEN_CALL_Pos) +#define I2C_IC_INTR_STAT_M_GEN_CALL I2C_IC_INTR_STAT_M_GEN_CALL_Msk +#define I2C_IC_INTR_STAT_M_START_DET_Pos 10U +#define I2C_IC_INTR_STAT_M_START_DET_Msk (1U << I2C_IC_INTR_STAT_M_START_DET_Pos) +#define I2C_IC_INTR_STAT_M_START_DET I2C_IC_INTR_STAT_M_START_DET_Msk +#define I2C_IC_INTR_STAT_M_STOP_DET_Pos 9U +#define I2C_IC_INTR_STAT_M_STOP_DET_Msk (1U << I2C_IC_INTR_STAT_M_STOP_DET_Pos) +#define I2C_IC_INTR_STAT_M_STOP_DET I2C_IC_INTR_STAT_M_STOP_DET_Msk +#define I2C_IC_INTR_STAT_M_ACTIVITY_Pos 8U +#define I2C_IC_INTR_STAT_M_ACTIVITY_Msk (1U << I2C_IC_INTR_STAT_M_ACTIVITY_Pos) +#define I2C_IC_INTR_STAT_M_ACTIVITY I2C_IC_INTR_STAT_M_ACTIVITY_Msk +#define I2C_IC_INTR_STAT_M_RX_DONE_Pos 7U +#define I2C_IC_INTR_STAT_M_RX_DONE_Msk (1U << I2C_IC_INTR_STAT_M_RX_DONE_Pos) +#define I2C_IC_INTR_STAT_M_RX_DONE I2C_IC_INTR_STAT_M_RX_DONE_Msk +#define I2C_IC_INTR_STAT_M_TX_ABRT_Pos 6U +#define I2C_IC_INTR_STAT_M_TX_ABRT_Msk (1U << I2C_IC_INTR_STAT_M_TX_ABRT_Pos) +#define I2C_IC_INTR_STAT_M_TX_ABRT I2C_IC_INTR_STAT_M_TX_ABRT_Msk +#define I2C_IC_INTR_STAT_M_RD_REQ_Pos 5U +#define I2C_IC_INTR_STAT_M_RD_REQ_Msk (1U << I2C_IC_INTR_STAT_M_RD_REQ_Pos) +#define I2C_IC_INTR_STAT_M_RD_REQ I2C_IC_INTR_STAT_M_RD_REQ_Msk +#define I2C_IC_INTR_STAT_M_TX_EMPTY_Pos 4U +#define I2C_IC_INTR_STAT_M_TX_EMPTY_Msk (1U << I2C_IC_INTR_STAT_M_TX_EMPTY_Pos) +#define I2C_IC_INTR_STAT_M_TX_EMPTY I2C_IC_INTR_STAT_M_TX_EMPTY_Msk +#define I2C_IC_INTR_STAT_M_TX_OVER_Pos 3U +#define I2C_IC_INTR_STAT_M_TX_OVER_Msk (1U << I2C_IC_INTR_STAT_M_TX_OVER_Pos) +#define I2C_IC_INTR_STAT_M_TX_OVER I2C_IC_INTR_STAT_M_TX_OVER_Msk +#define I2C_IC_INTR_STAT_M_RX_FULL_Pos 2U +#define I2C_IC_INTR_STAT_M_RX_FULL_Msk (1U << I2C_IC_INTR_STAT_M_RX_FULL_Pos) +#define I2C_IC_INTR_STAT_M_RX_FULL I2C_IC_INTR_STAT_M_RX_FULL_Msk +#define I2C_IC_INTR_STAT_M_RX_OVER_Pos 1U +#define I2C_IC_INTR_STAT_M_RX_OVER_Msk (1U << I2C_IC_INTR_STAT_M_RX_OVER_Pos) +#define I2C_IC_INTR_STAT_M_RX_OVER I2C_IC_INTR_STAT_M_RX_OVER_Msk +#define I2C_IC_INTR_STAT_M_RX_UNDER_Pos 0U +#define I2C_IC_INTR_STAT_M_RX_UNDER_Msk (1U << I2C_IC_INTR_STAT_M_RX_UNDER_Pos) +#define I2C_IC_INTR_STAT_M_RX_UNDER I2C_IC_INTR_STAT_M_RX_UNDER_Msk + +#define I2C_IC_RX_TL_RX_TL_Pos 0U +#define I2C_IC_RX_TL_RX_TL_Msk (0xFFU << I2C_IC_RX_TL_RX_TL_Pos) +#define I2C_IC_RX_TL_RX_TL I2C_IC_RX_TL_RX_TL_Msk + +#define I2C_IC_TX_TL_TX_TL_Pos 0U +#define I2C_IC_TX_TL_TX_TL_Msk (0xFFU << I2C_IC_TX_TL_TX_TL_Pos) +#define I2C_IC_TX_TL_TX_TL I2C_IC_TX_TL_TX_TL_Msk + +#define I2C_IC_ENABLE_TX_CMD_BLOCK_Pos 2U +#define I2C_IC_ENABLE_TX_CMD_BLOCK_Msk (1U << I2C_IC_ENABLE_TX_CMD_BLOCK_Pos) +#define I2C_IC_ENABLE_TX_CMD_BLOCK I2C_IC_ENABLE_TX_CMD_BLOCK_Msk +#define I2C_IC_ENABLE_ABORT_Pos 1U +#define I2C_IC_ENABLE_ABORT_Msk (1U << I2C_IC_ENABLE_ABORT_Pos) +#define I2C_IC_ENABLE_ABORT I2C_IC_ENABLE_ABORT_Msk +#define I2C_IC_ENABLE_ENABLE_Pos 0U +#define I2C_IC_ENABLE_ENABLE_Msk (1U << I2C_IC_ENABLE_ENABLE_Pos) +#define I2C_IC_ENABLE_ENABLE I2C_IC_ENABLE_ENABLE_Msk + +#define I2C_IC_STATUS_SLV_ACTIVITY_Pos 6U +#define I2C_IC_STATUS_SLV_ACTIVITY_Msk (1U << I2C_IC_STATUS_SLV_ACTIVITY_Pos) +#define I2C_IC_STATUS_SLV_ACTIVITY I2C_IC_STATUS_SLV_ACTIVITY_Msk +#define I2C_IC_STATUS_MST_ACTIVITY_Pos 5U +#define I2C_IC_STATUS_MST_ACTIVITY_Msk (1U << I2C_IC_STATUS_MST_ACTIVITY_Pos) +#define I2C_IC_STATUS_MST_ACTIVITY I2C_IC_STATUS_MST_ACTIVITY_Msk +#define I2C_IC_STATUS_RFF_Pos 4U +#define I2C_IC_STATUS_RFF_Msk (1U << I2C_IC_STATUS_RFF_Pos) +#define I2C_IC_STATUS_RFF I2C_IC_STATUS_RFF_Msk +#define I2C_IC_STATUS_RFNE_Pos 3U +#define I2C_IC_STATUS_RFNE_Msk (1U << I2C_IC_STATUS_RFNE_Pos) +#define I2C_IC_STATUS_RFNE I2C_IC_STATUS_RFNE_Msk +#define I2C_IC_STATUS_TFE_Pos 2U +#define I2C_IC_STATUS_TFE_Msk (1U << I2C_IC_STATUS_TFE_Pos) +#define I2C_IC_STATUS_TFE I2C_IC_STATUS_TFE_Msk +#define I2C_IC_STATUS_TFNF_Pos 1U +#define I2C_IC_STATUS_TFNF_Msk (1U << I2C_IC_STATUS_TFNF_Pos) +#define I2C_IC_STATUS_TFNF I2C_IC_STATUS_TFNF_Msk +#define I2C_IC_STATUS_ACTIVITY_Pos 0U +#define I2C_IC_STATUS_ACTIVITY_Msk (1U << I2C_IC_STATUS_ACTIVITY_Pos) +#define I2C_IC_STATUS_ACTIVITY I2C_IC_STATUS_ACTIVITY_Msk + +#define I2C_IC_TXFLR_TXFLR_Pos 0U +#define I2C_IC_TXFLR_TXFLR_Msk (0x1FU << I2C_IC_TXFLR_TXFLR_Pos) +#define I2C_IC_TXFLR_TXFLR I2C_IC_TXFLR_TXFLR_Msk + +#define I2C_IC_RXFLR_RXFLR_Pos 0U +#define I2C_IC_RXFLR_RXFLR_Msk (0x1FU << I2C_IC_RXFLR_RXFLR_Pos) +#define I2C_IC_RXFLR_RXFLR I2C_IC_RXFLR_RXFLR_Msk + +#define I2C_IC_SDA_HOLD_IC_SDA_RX_HOLD_Pos 16U +#define I2C_IC_SDA_HOLD_IC_SDA_RX_HOLD_Msk (0xFFU << I2C_IC_SDA_HOLD_IC_SDA_RX_HOLD_Pos) +#define I2C_IC_SDA_HOLD_IC_SDA_RX_HOLD I2C_IC_SDA_HOLD_IC_SDA_RX_HOLD_Msk +#define I2C_IC_SDA_HOLD_IC_SDA_TX_HOLD_Pos 0U +#define I2C_IC_SDA_HOLD_IC_SDA_TX_HOLD_Msk (0xFFU << I2C_IC_SDA_HOLD_IC_SDA_TX_HOLD_Pos) +#define I2C_IC_SDA_HOLD_IC_SDA_TX_HOLD I2C_IC_SDA_HOLD_IC_SDA_TX_HOLD_Msk + +#define I2C_IC_TX_ABRT_SOURCE_TX_FLUSH_CNT_Pos 23U +#define I2C_IC_TX_ABRT_SOURCE_TX_FLUSH_CNT_Msk (0x1FFU << I2C_IC_TX_ABRT_SOURCE_TX_FLUSH_CNT_Pos) +#define I2C_IC_TX_ABRT_SOURCE_TX_FLUSH_CNT I2C_IC_TX_ABRT_SOURCE_TX_FLUSH_CNT_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_USER_ABRT_Pos 16U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_USER_ABRT_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_USER_ABRT_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_USER_ABRT I2C_IC_TX_ABRT_SOURCE_ABRT_USER_ABRT_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX_Pos 15U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX I2C_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST_Pos 14U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST I2C_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO_Pos 13U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO I2C_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO_Msk +#define I2C_IC_TX_ABRT_SOURCE_ARB_LOST_Pos 12U +#define I2C_IC_TX_ABRT_SOURCE_ARB_LOST_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ARB_LOST_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ARB_LOST I2C_IC_TX_ABRT_SOURCE_ARB_LOST_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS_Pos 11U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS I2C_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT_Pos 10U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT I2C_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT_Pos 9U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT_Pos 8U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT I2C_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET_Pos 7U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET_Pos 6U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET I2C_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ_Pos 5U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK_Pos 4U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK_Pos 3U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK I2C_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK_Pos 2U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK_Pos 1U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK_Pos 0U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK_Msk + +#define I2C_IC_DMA_CR_TDMAE_Pos 1U +#define I2C_IC_DMA_CR_TDMAE_Msk (1U << I2C_IC_DMA_CR_TDMAE_Pos) +#define I2C_IC_DMA_CR_TDMAE I2C_IC_DMA_CR_TDMAE_Msk +#define I2C_IC_DMA_CR_RDMAE_Pos 0U +#define I2C_IC_DMA_CR_RDMAE_Msk (1U << I2C_IC_DMA_CR_RDMAE_Pos) +#define I2C_IC_DMA_CR_RDMAE I2C_IC_DMA_CR_RDMAE_Msk + +#define I2C_IC_DMA_TDLR_DMATDL_Pos 0U +#define I2C_IC_DMA_TDLR_DMATDL_Msk (0xFU << I2C_IC_DMA_TDLR_DMATDL_Pos) +#define I2C_IC_DMA_TDLR_DMATDL I2C_IC_DMA_TDLR_DMATDL_Msk + +#define I2C_IC_DMA_RDLR_DMARDL_Pos 0U +#define I2C_IC_DMA_RDLR_DMARDL_Msk (0xFU << I2C_IC_DMA_RDLR_DMARDL_Pos) +#define I2C_IC_DMA_RDLR_DMARDL I2C_IC_DMA_RDLR_DMARDL_Msk + +#define I2C_IC_SDA_SETUP_SDA_SETUP_Pos 0U +#define I2C_IC_SDA_SETUP_SDA_SETUP_Msk (0xFFU << I2C_IC_SDA_SETUP_SDA_SETUP_Pos) +#define I2C_IC_SDA_SETUP_SDA_SETUP I2C_IC_SDA_SETUP_SDA_SETUP_Msk + +#define I2C_IC_ACK_GENERAL_CALL_ACK_GEN_CALL_Pos 0U +#define I2C_IC_ACK_GENERAL_CALL_ACK_GEN_CALL_Msk (1U << I2C_IC_ACK_GENERAL_CALL_ACK_GEN_CALL_Pos) +#define I2C_IC_ACK_GENERAL_CALL_ACK_GEN_CALL I2C_IC_ACK_GENERAL_CALL_ACK_GEN_CALL_Msk + +#define I2C_IC_ENABLE_STATUS_SLV_RX_DATA_LOST_Pos 2U +#define I2C_IC_ENABLE_STATUS_SLV_RX_DATA_LOST_Msk (1U << I2C_IC_ENABLE_STATUS_SLV_RX_DATA_LOST_Pos) +#define I2C_IC_ENABLE_STATUS_SLV_RX_DATA_LOST I2C_IC_ENABLE_STATUS_SLV_RX_DATA_LOST_Msk +#define I2C_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY_Pos 1U +#define I2C_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY_Msk (1U << I2C_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY_Pos) +#define I2C_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY I2C_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY_Msk +#define I2C_IC_ENABLE_STATUS_IC_EN_Pos 0U +#define I2C_IC_ENABLE_STATUS_IC_EN_Msk (1U << I2C_IC_ENABLE_STATUS_IC_EN_Pos) +#define I2C_IC_ENABLE_STATUS_IC_EN I2C_IC_ENABLE_STATUS_IC_EN_Msk + +#define I2C_IC_FS_SPKLEN_IC_FS_SPKLEN_Pos 0U +#define I2C_IC_FS_SPKLEN_IC_FS_SPKLEN_Msk (0xFFU << I2C_IC_FS_SPKLEN_IC_FS_SPKLEN_Pos) +#define I2C_IC_FS_SPKLEN_IC_FS_SPKLEN I2C_IC_FS_SPKLEN_IC_FS_SPKLEN_Msk + +#define I2C_IC_COMP_PARAM_1_TX_BUFFER_DEPTH_Pos 16U +#define I2C_IC_COMP_PARAM_1_TX_BUFFER_DEPTH_Msk (0xFFU << I2C_IC_COMP_PARAM_1_TX_BUFFER_DEPTH_Pos) +#define I2C_IC_COMP_PARAM_1_TX_BUFFER_DEPTH I2C_IC_COMP_PARAM_1_TX_BUFFER_DEPTH_Msk +#define I2C_IC_COMP_PARAM_1_RX_BUFFER_DEPTH_Pos 0U +#define I2C_IC_COMP_PARAM_1_RX_BUFFER_DEPTH_Msk (0xFFU << I2C_IC_COMP_PARAM_1_RX_BUFFER_DEPTH_Pos) +#define I2C_IC_COMP_PARAM_1_RX_BUFFER_DEPTH I2C_IC_COMP_PARAM_1_RX_BUFFER_DEPTH_Msk + +#define I2C_IC_COMP_PARAM_1_ADD_ENCODED_PARAMS_Pos 7U +#define I2C_IC_COMP_PARAM_1_ADD_ENCODED_PARAMS_Msk (1U << I2C_IC_COMP_PARAM_1_ADD_ENCODED_PARAMS_Pos) +#define I2C_IC_COMP_PARAM_1_ADD_ENCODED_PARAMS I2C_IC_COMP_PARAM_1_ADD_ENCODED_PARAMS_Msk +#define I2C_IC_COMP_PARAM_1_HAS_DMA_Pos 6U +#define I2C_IC_COMP_PARAM_1_HAS_DMA_Msk (1U << I2C_IC_COMP_PARAM_1_HAS_DMA_Pos) +#define I2C_IC_COMP_PARAM_1_HAS_DMA I2C_IC_COMP_PARAM_1_HAS_DMA_Msk +#define I2C_IC_COMP_PARAM_1_INTR_IO_Pos 5U +#define I2C_IC_COMP_PARAM_1_INTR_IO_Msk (1U << I2C_IC_COMP_PARAM_1_INTR_IO_Pos) +#define I2C_IC_COMP_PARAM_1_INTR_IO I2C_IC_COMP_PARAM_1_INTR_IO_Msk +#define I2C_IC_COMP_PARAM_1_HC_COUNT_VALUES_Pos 4U +#define I2C_IC_COMP_PARAM_1_HC_COUNT_VALUES_Msk (1U << I2C_IC_COMP_PARAM_1_HC_COUNT_VALUES_Pos) +#define I2C_IC_COMP_PARAM_1_HC_COUNT_VALUES I2C_IC_COMP_PARAM_1_HC_COUNT_VALUES_Msk +#define I2C_IC_COMP_PARAM_1_MAX_SPEED_MODE_Pos 2U +#define I2C_IC_COMP_PARAM_1_MAX_SPEED_MODE_Msk (3U << I2C_IC_COMP_PARAM_1_MAX_SPEED_MODE_Pos) +#define I2C_IC_COMP_PARAM_1_MAX_SPEED_MODE I2C_IC_COMP_PARAM_1_MAX_SPEED_MODE_Msk +#define I2C_IC_COMP_PARAM_1_APB_DATA_WIDTH_Pos 0U +#define I2C_IC_COMP_PARAM_1_APB_DATA_WIDTH_Msk (3U << I2C_IC_COMP_PARAM_1_APB_DATA_WIDTH_Pos) +#define I2C_IC_COMP_PARAM_1_APB_DATA_WIDTH I2C_IC_COMP_PARAM_1_APB_DATA_WIDTH_Msk +/** @} */ + +/** + * @name PWM bits definitions + * @{ + */ +#define PWM_CSR_PH_ADV_Pos 7U +#define PWM_CSR_PH_ADV_Msk (1U << PWM_CSR_PH_ADV_Pos) +#define PWM_CSR_PH_ADV PWM_CSR_PH_ADV_Msk +#define PWM_CSR_PH_RET_Pos 6U +#define PWM_CSR_PH_RET_Msk (1U << PWM_CSR_PH_RET_Pos) +#define PWM_CSR_PH_RET PWM_CSR_PH_RET_Msk +#define PWM_CSR_DIVMODE_Pos 4U +#define PWM_CSR_DIVMODE_Msk (0x3U << PWM_CSR_DIVMODE_Pos) +#define PWM_CSR_DIVMODE(n) ((n) << PWM_CSR_DIVMODE_Pos) +#define PWM_CSR_B_INV_Pos 3U +#define PWM_CSR_B_INV_Msk (1U << PWM_CSR_B_INV_Pos) +#define PWM_CSR_B_INV PWM_CSR_B_INV_Msk +#define PWM_CSR_A_INV_Pos 2U +#define PWM_CSR_A_INV_Msk (1U << PWM_CSR_A_INV_Pos) +#define PWM_CSR_A_INV PWM_CSR_A_INV_Msk +#define PWM_CSR_PH_CORRECT_Pos 1U +#define PWM_CSR_PH_CORRECT_Msk (1U << PWM_CSR_PH_CORRECT_Pos) +#define PWM_CSR_PH_CORRECT PWM_CSR_PH_CORRECT_Msk +#define PWM_CSR_EN_Pos 0U +#define PWM_CSR_EN_Msk (1U << PWM_CSR_EN_Pos) +#define PWM_CSR_EN PWM_CSR_EN_Msk +#define PWM_CSR_PH_CORRECT_PHASE_CORRECT_MODULATION (1U << PWM_CSR_PH_CORRECT_Pos) +#define PWM_CSR_PH_CORRECT_TRAILING_EDGE (0U << PWM_CSR_PH_CORRECT_Pos) +#define PWM_CSR_DIVMODE_FREE PWM_CSR_DIVMODE(0U) +#define PWM_CSR_DIVMODE_GATED PWM_CSR_DIVMODE(1U) +#define PWM_CSR_DIVMODE_RISING_EDGE PWM_CSR_DIVMODE(2U) +#define PWM_CSR_DIVMODE_FALING_EDGE PWM_CSR_DIVMODE(3U) + +#define PWM_DIV_INT_Pos 4U +#define PWM_DIV_INT_Msk (0xFFU << PWM_DIV_INT_Pos) +#define PWM_DIV_INT PWM_DIV_INT_Msk +#define PWM_DIV_FRAC_Pos 0U +#define PWM_DIV_FRAC_Msk (0xFU << PWM_DIV_FRAC_Pos) +#define PWM_DIV_FRAC PWM_DIV_FRAC_Msk + +#define PWM_CTR_COUNTER_Pos 0U +#define PWM_CTR_COUNTER_Msk (0xFFFFU << PWM_CTR_COUNTER_Pos) +#define PWM_CTR_COUNTER PWM_CTR_COUNTER_Msk + +#define PWM_CC_B_Pos 16U +#define PWM_CC_B_Msk (0xFFFFU << PWM_CC_B_Pos) +#define PWM_CC_B PWM_CC_B_Msk +#define PWM_CC_A_Pos 0U +#define PWM_CC_A_Msk (0xFFFFU << PWM_CC_A_Pos) +#define PWM_CC_A PWM_CC_A_Msk + +#define PWM_TOP_VALUE_Pos 0U +#define PWM_TOP_VALUE_Msk (0xFFFFU << PWM_TOP_VALUE_Pos) +#define PWM_TOP_VALUE PWM_TOP_VALUE_Msk + +#define PWM_EN_CH7_Pos 7U +#define PWM_EN_CH7_Msk (1U << PWM_EN_CH7_Pos) +#define PWM_EN_CH7 PWM_EN_CH7_Msk +#define PWM_EN_CH6_Pos 6U +#define PWM_EN_CH6_Msk (1U << PWM_EN_CH6_Pos) +#define PWM_EN_CH6 PWM_EN_CH6_Msk +#define PWM_EN_CH5_Pos 5U +#define PWM_EN_CH5_Msk (1U << PWM_EN_CH5_Pos) +#define PWM_EN_CH5 PWM_EN_CH5_Msk +#define PWM_EN_CH4_Pos 4U +#define PWM_EN_CH4_Msk (1U << PWM_EN_CH4_Pos) +#define PWM_EN_CH4 PWM_EN_CH4_Msk +#define PWM_EN_CH3_Pos 3U +#define PWM_EN_CH3_Msk (1U << PWM_EN_CH3_Pos) +#define PWM_EN_CH3 PWM_EN_CH3_Msk +#define PWM_EN_CH2_Pos 2U +#define PWM_EN_CH2_Msk (1U << PWM_EN_CH2_Pos) +#define PWM_EN_CH2 PWM_EN_CH2_Msk +#define PWM_EN_CH1_Pos 1U +#define PWM_EN_CH1_Msk (1U << PWM_EN_CH1_Pos) +#define PWM_EN_CH1 PWM_EN_CH1_Msk +#define PWM_EN_CH0_Pos 0U +#define PWM_EN_CH0_Msk (1U << PWM_EN_CH0_Pos) +#define PWM_EN_CH0 PWM_EN_CH0_Msk + +#define PWM_INTR_CH7_Pos 7U +#define PWM_INTR_CH7_Msk (1U << PWM_INTR_CH7_Pos) +#define PWM_INTR_CH7 PWM_INTR_CH7_Msk +#define PWM_INTR_CH6_Pos 6U +#define PWM_INTR_CH6_Msk (1U << PWM_INTR_CH6_Pos) +#define PWM_INTR_CH6 PWM_INTR_CH6_Msk +#define PWM_INTR_CH5_Pos 5U +#define PWM_INTR_CH5_Msk (1U << PWM_INTR_CH5_Pos) +#define PWM_INTR_CH5 PWM_INTR_CH5_Msk +#define PWM_INTR_CH4_Pos 4U +#define PWM_INTR_CH4_Msk (1U << PWM_INTR_CH4_Pos) +#define PWM_INTR_CH4 PWM_INTR_CH4_Msk +#define PWM_INTR_CH3_Pos 3U +#define PWM_INTR_CH3_Msk (1U << PWM_INTR_CH3_Pos) +#define PWM_INTR_CH3 PWM_INTR_CH3_Msk +#define PWM_INTR_CH2_Pos 2U +#define PWM_INTR_CH2_Msk (1U << PWM_INTR_CH2_Pos) +#define PWM_INTR_CH2 PWM_INTR_CH2_Msk +#define PWM_INTR_CH1_Pos 1U +#define PWM_INTR_CH1_Msk (1U << PWM_INTR_CH1_Pos) +#define PWM_INTR_CH1 PWM_INTR_CH1_Msk +#define PWM_INTR_CH0_Pos 0U +#define PWM_INTR_CH0_Msk (1U << PWM_INTR_CH0_Pos) +#define PWM_INTR_CH0 PWM_INTR_CH0_Msk +#define PWM_INTR_CH(n) (1U << n) + +#define PWM_INTE_CH7_Pos 7U +#define PWM_INTE_CH7_Msk (1U << PWM_INTE_CH7_Pos) +#define PWM_INTE_CH7 PWM_INTE_CH7_Msk +#define PWM_INTE_CH6_Pos 6U +#define PWM_INTE_CH6_Msk (1U << PWM_INTE_CH6_Pos) +#define PWM_INTE_CH6 PWM_INTE_CH6_Msk +#define PWM_INTE_CH5_Pos 5U +#define PWM_INTE_CH5_Msk (1U << PWM_INTE_CH5_Pos) +#define PWM_INTE_CH5 PWM_INTE_CH5_Msk +#define PWM_INTE_CH4_Pos 4U +#define PWM_INTE_CH4_Msk (1U << PWM_INTE_CH4_Pos) +#define PWM_INTE_CH4 PWM_INTE_CH4_Msk +#define PWM_INTE_CH3_Pos 3U +#define PWM_INTE_CH3_Msk (1U << PWM_INTE_CH3_Pos) +#define PWM_INTE_CH3 PWM_INTE_CH3_Msk +#define PWM_INTE_CH2_Pos 2U +#define PWM_INTE_CH2_Msk (1U << PWM_INTE_CH2_Pos) +#define PWM_INTE_CH2 PWM_INTE_CH2_Msk +#define PWM_INTE_CH1_Pos 1U +#define PWM_INTE_CH1_Msk (1U << PWM_INTE_CH1_Pos) +#define PWM_INTE_CH1 PWM_INTE_CH1_Msk +#define PWM_INTE_CH0_Pos 0U +#define PWM_INTE_CH0_Msk (1U << PWM_INTE_CH0_Pos) +#define PWM_INTE_CH0 PWM_INTE_CH0_Msk +#define PWM_INTE_CH(n) (1U << n) + +#define PWM_INTF_CH7_Pos 7U +#define PWM_INTF_CH7_Msk (1U << PWM_INTF_CH7_Pos) +#define PWM_INTF_CH7 PWM_INTF_CH7_Msk +#define PWM_INTF_CH6_Pos 6U +#define PWM_INTF_CH6_Msk (1U << PWM_INTF_CH6_Pos) +#define PWM_INTF_CH6 PWM_INTF_CH6_Msk +#define PWM_INTF_CH5_Pos 5U +#define PWM_INTF_CH5_Msk (1U << PWM_INTF_CH5_Pos) +#define PWM_INTF_CH5 PWM_INTF_CH5_Msk +#define PWM_INTF_CH4_Pos 4U +#define PWM_INTF_CH4_Msk (1U << PWM_INTF_CH4_Pos) +#define PWM_INTF_CH4 PWM_INTF_CH4_Msk +#define PWM_INTF_CH3_Pos 3U +#define PWM_INTF_CH3_Msk (1U << PWM_INTF_CH3_Pos) +#define PWM_INTF_CH3 PWM_INTF_CH3_Msk +#define PWM_INTF_CH2_Pos 2U +#define PWM_INTF_CH2_Msk (1U << PWM_INTF_CH2_Pos) +#define PWM_INTF_CH2 PWM_INTF_CH2_Msk +#define PWM_INTF_CH1_Pos 1U +#define PWM_INTF_CH1_Msk (1U << PWM_INTF_CH1_Pos) +#define PWM_INTF_CH1 PWM_INTF_CH1_Msk +#define PWM_INTF_CH0_Pos 0U +#define PWM_INTF_CH0_Msk (1U << PWM_INTF_CH0_Pos) +#define PWM_INTF_CH0 PWM_INTF_CH0_Msk +#define PWM_INTF_CH(n) (1U << n) + +#define PWM_INTS_CH7_Pos 7U +#define PWM_INTS_CH7_Msk (1U << PWM_INTS_CH7_Pos) +#define PWM_INTS_CH7 PWM_INTS_CH7_Msk +#define PWM_INTS_CH6_Pos 6U +#define PWM_INTS_CH6_Msk (1U << PWM_INTS_CH6_Pos) +#define PWM_INTS_CH6 PWM_INTS_CH6_Msk +#define PWM_INTS_CH5_Pos 5U +#define PWM_INTS_CH5_Msk (1U << PWM_INTS_CH5_Pos) +#define PWM_INTS_CH5 PWM_INTS_CH5_Msk +#define PWM_INTS_CH4_Pos 4U +#define PWM_INTS_CH4_Msk (1U << PWM_INTS_CH4_Pos) +#define PWM_INTS_CH4 PWM_INTS_CH4_Msk +#define PWM_INTS_CH3_Pos 3U +#define PWM_INTS_CH3_Msk (1U << PWM_INTS_CH3_Pos) +#define PWM_INTS_CH3 PWM_INTS_CH3_Msk +#define PWM_INTS_CH2_Pos 2U +#define PWM_INTS_CH2_Msk (1U << PWM_INTS_CH2_Pos) +#define PWM_INTS_CH2 PWM_INTS_CH2_Msk +#define PWM_INTS_CH1_Pos 1U +#define PWM_INTS_CH1_Msk (1U << PWM_INTS_CH1_Pos) +#define PWM_INTS_CH1 PWM_INTS_CH1_Msk +#define PWM_INTS_CH0_Pos 0U +#define PWM_INTS_CH0_Msk (1U << PWM_INTS_CH0_Pos) +#define PWM_INTS_CH0 PWM_INTS_CH0_Msk +#define PWM_INTS_CH(n) (1U << n) +/** @} */ + +/** + * @name XOSC bits definitions + * @{ + */ +#define XOSC_CTRL_ENABLE_Pos 12U +#define XOSC_CTRL_ENABLE_Msk (0xFFFU << XOSC_CTRL_ENABLE_Pos) +#define XOSC_CTRL_ENABLE_DISABLE (0xD1EU << XOSC_CTRL_ENABLE_Pos) +#define XOSC_CTRL_ENABLE_ENABLE (0xFABU << XOSC_CTRL_ENABLE_Pos) +#define XOSC_CTRL_FREQ_RANGE_Pos 0U +#define XOSC_CTRL_FREQ_RANGE_Msk (0xFFFU << XOSC_CTRL_FREQ_RANGE_Pos) +#define XOSC_CTRL_FREQ_RANGE_1_15MHZ (0xAA0U << XOSC_CTRL_FREQ_RANGE_Pos) + +#define XOSC_STATUS_STABLE_Pos 31U +#define XOSC_STATUS_STABLE_Msk (1U << XOSC_STATUS_STABLE_Pos) +#define XOSC_STATUS_STABLE XOSC_STATUS_STABLE_Msk +#define XOSC_STATUS_BADWRITE_Pos 24U +#define XOSC_STATUS_BADWRITE_Msk (1U << XOSC_STATUS_BADWRITE_Pos) +#define XOSC_STATUS_BADWRITE XOSC_STATUS_BADWRITE_Msk +#define XOSC_STATUS_ENABLED_Pos 12U +#define XOSC_STATUS_ENABLED_Msk (1U << XOSC_STATUS_ENABLED_Pos) +#define XOSC_STATUS_ENABLED XOSC_STATUS_ENABLED_Msk + +#define XOSC_DORMANT_DORMANT 0x636F6D61U +#define XOSC_DORMANT_WAKE 0x77616B65U + +#define XOSC_STARTUP_X4_Pos 20U +#define XOSC_STARTUP_X4_Msk (1U << XOSC_STARTUP_X4_Pos) +#define XOSC_STARTUP_X4 XOSC_STARTUP_X4_Msk +#define XOSC_STARTUP_DELAY_Pos 0U +#define XOSC_STARTUP_DELAY_Msk (0x3FFFU << XOSC_STARTUP_DELAY_Pos) +#define XOSC_STARTUP_DELAY(n) ((n) << XOSC_STARTUP_DELAY_Pos) +/** @} */ + +/** + * @name PLL bits definitions + * @{ + */ +#define PLL_CS_LOCK_Pos 31U +#define PLL_CS_LOCK_Msk (1U << PLL_CS_LOCK_Pos) +#define PLL_CS_LOCK PLL_CS_LOCK_Msk +#define PLL_CS_BYPASS_Pos 8U +#define PLL_CS_BYPASS_Msk (1U << PLL_CS_BYPASS_Pos) +#define PLL_CS_BYPASS PLL_CS_BYPASS_Msk +#define PLL_CS_REFDIV_Pos 0U +#define PLL_CS_REFDIV_Msk (0x3FU << PLL_CS_REFDIV_Pos) +#define PLL_CS_REFDIV(n) ((n) << PLL_CS_REFDIV_Pos) + +#define PLL_PWR_VCOPD_Pos 5U +#define PLL_PWR_VCOPD_Msk (1U << PLL_PWR_VCOPD_Pos) +#define PLL_PWR_VCOPD PLL_PWR_VCOPD_Msk +#define PLL_PWR_POSTDIVPD_Pos 3U +#define PLL_PWR_POSTDIVPD_Msk (1U << PLL_PWR_POSTDIVPD_Pos) +#define PLL_PWR_POSTDIVPD PLL_PWR_POSTDIVPD_Msk +#define PLL_PWR_DSMPD_Pos 2U +#define PLL_PWR_DSMPD_Msk (1U << PLL_PWR_DSMPD_Pos) +#define PLL_PWR_DSMPD PLL_PWR_DSMPD_Msk +#define PLL_PWR_PD_Pos 0U +#define PLL_PWR_PD_Msk (1U << PLL_PWR_PD_Pos) +#define PLL_PWR_PD PLL_PWR_PD_Msk + +#define PLL_FBDIV_INT_Pos 0U +#define PLL_FBDIV_INT_Msk (0xFFFU << PLL_FBDIV_INT_Pos) +#define PLL_FBDIV_INT(n) ((n) << PLL_FBDIV_INT_Pos) + +#define PLL_PRIM_POSTDIV1_Pos 16U +#define PLL_PRIM_POSTDIV1_Msk (0x7U << PLL_PRIM_POSTDIV1_Pos) +#define PLL_PRIM_POSTDIV1(n) ((n) << PLL_PRIM_POSTDIV1_Pos) +#define PLL_PRIM_POSTDIV2_Pos 12U +#define PLL_PRIM_POSTDIV2_Msk (0x7U << PLL_PRIM_POSTDIV2_Pos) +#define PLL_PRIM_POSTDIV2(n) ((n) << PLL_PRIM_POSTDIV2_Pos) +/** @} */ + +/** + * @name CLOCKS bits definitions + * @{ + */ +/* CLK_REF CTRL */ +#define CLOCKS_CLK_REF_CTRL_SRC_Pos 0U +#define CLOCKS_CLK_REF_CTRL_SRC_Msk (0x3U << CLOCKS_CLK_REF_CTRL_SRC_Pos) +#define CLOCKS_CLK_REF_CTRL_SRC_ROSC (0x0U << CLOCKS_CLK_REF_CTRL_SRC_Pos) +#define CLOCKS_CLK_REF_CTRL_SRC_AUX (0x1U << CLOCKS_CLK_REF_CTRL_SRC_Pos) +#define CLOCKS_CLK_REF_CTRL_SRC_XOSC (0x2U << CLOCKS_CLK_REF_CTRL_SRC_Pos) +#define CLOCKS_CLK_REF_CTRL_AUXSRC_Pos 5U +#define CLOCKS_CLK_REF_CTRL_AUXSRC_Msk (0x3U << CLOCKS_CLK_REF_CTRL_AUXSRC_Pos) + +/* CLK_SYS CTRL */ +#define CLOCKS_CLK_SYS_CTRL_SRC_Pos 0U +#define CLOCKS_CLK_SYS_CTRL_SRC_Msk (0x1U << CLOCKS_CLK_SYS_CTRL_SRC_Pos) +#define CLOCKS_CLK_SYS_CTRL_SRC_REF (0x0U << CLOCKS_CLK_SYS_CTRL_SRC_Pos) +#define CLOCKS_CLK_SYS_CTRL_SRC_AUX (0x1U << CLOCKS_CLK_SYS_CTRL_SRC_Pos) +#define CLOCKS_CLK_SYS_CTRL_AUXSRC_Pos 5U +#define CLOCKS_CLK_SYS_CTRL_AUXSRC_Msk (0x7U << CLOCKS_CLK_SYS_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_SYS_CTRL_AUXSRC_PLL_SYS (0x0U << CLOCKS_CLK_SYS_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_SYS_CTRL_AUXSRC_PLL_USB (0x1U << CLOCKS_CLK_SYS_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_SYS_CTRL_AUXSRC_ROSC (0x2U << CLOCKS_CLK_SYS_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_SYS_CTRL_AUXSRC_XOSC (0x3U << CLOCKS_CLK_SYS_CTRL_AUXSRC_Pos) + +/* CLK_PERI CTRL */ +#define CLOCKS_CLK_PERI_CTRL_ENABLE_Pos 11U +#define CLOCKS_CLK_PERI_CTRL_ENABLE_Msk (1U << CLOCKS_CLK_PERI_CTRL_ENABLE_Pos) +#define CLOCKS_CLK_PERI_CTRL_ENABLE CLOCKS_CLK_PERI_CTRL_ENABLE_Msk +#define CLOCKS_CLK_PERI_CTRL_KILL_Pos 10U +#define CLOCKS_CLK_PERI_CTRL_KILL_Msk (1U << CLOCKS_CLK_PERI_CTRL_KILL_Pos) +#define CLOCKS_CLK_PERI_CTRL_KILL CLOCKS_CLK_PERI_CTRL_KILL_Msk +#define CLOCKS_CLK_PERI_CTRL_AUXSRC_Pos 5U +#define CLOCKS_CLK_PERI_CTRL_AUXSRC_Msk (0x7U << CLOCKS_CLK_PERI_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_PERI_CTRL_AUXSRC_SYS (0x0U << CLOCKS_CLK_PERI_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_PERI_CTRL_AUXSRC_PLL_SYS (0x1U << CLOCKS_CLK_PERI_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_PERI_CTRL_AUXSRC_PLL_USB (0x2U << CLOCKS_CLK_PERI_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_PERI_CTRL_AUXSRC_ROSC (0x3U << CLOCKS_CLK_PERI_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_PERI_CTRL_AUXSRC_XOSC (0x4U << CLOCKS_CLK_PERI_CTRL_AUXSRC_Pos) + +/* CLK_USB CTRL */ +#define CLOCKS_CLK_USB_CTRL_ENABLE_Pos 11U +#define CLOCKS_CLK_USB_CTRL_ENABLE_Msk (1U << CLOCKS_CLK_USB_CTRL_ENABLE_Pos) +#define CLOCKS_CLK_USB_CTRL_ENABLE CLOCKS_CLK_USB_CTRL_ENABLE_Msk +#define CLOCKS_CLK_USB_CTRL_KILL_Pos 10U +#define CLOCKS_CLK_USB_CTRL_KILL_Msk (1U << CLOCKS_CLK_USB_CTRL_KILL_Pos) +#define CLOCKS_CLK_USB_CTRL_KILL CLOCKS_CLK_USB_CTRL_KILL_Msk +#define CLOCKS_CLK_USB_CTRL_AUXSRC_Pos 5U +#define CLOCKS_CLK_USB_CTRL_AUXSRC_Msk (0x7U << CLOCKS_CLK_USB_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_USB_CTRL_AUXSRC_PLL_USB (0x0U << CLOCKS_CLK_USB_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_USB_CTRL_AUXSRC_PLL_SYS (0x1U << CLOCKS_CLK_USB_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_USB_CTRL_AUXSRC_ROSC (0x2U << CLOCKS_CLK_USB_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_USB_CTRL_AUXSRC_XOSC (0x3U << CLOCKS_CLK_USB_CTRL_AUXSRC_Pos) + +/* CLK_ADC CTRL */ +#define CLOCKS_CLK_ADC_CTRL_ENABLE_Pos 11U +#define CLOCKS_CLK_ADC_CTRL_ENABLE_Msk (1U << CLOCKS_CLK_ADC_CTRL_ENABLE_Pos) +#define CLOCKS_CLK_ADC_CTRL_ENABLE CLOCKS_CLK_ADC_CTRL_ENABLE_Msk +#define CLOCKS_CLK_ADC_CTRL_KILL_Pos 10U +#define CLOCKS_CLK_ADC_CTRL_KILL_Msk (1U << CLOCKS_CLK_ADC_CTRL_KILL_Pos) +#define CLOCKS_CLK_ADC_CTRL_KILL CLOCKS_CLK_ADC_CTRL_KILL_Msk +#define CLOCKS_CLK_ADC_CTRL_AUXSRC_Pos 5U +#define CLOCKS_CLK_ADC_CTRL_AUXSRC_Msk (0x7U << CLOCKS_CLK_ADC_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_ADC_CTRL_AUXSRC_PLL_USB (0x0U << CLOCKS_CLK_ADC_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_ADC_CTRL_AUXSRC_PLL_SYS (0x1U << CLOCKS_CLK_ADC_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_ADC_CTRL_AUXSRC_ROSC (0x2U << CLOCKS_CLK_ADC_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_ADC_CTRL_AUXSRC_XOSC (0x3U << CLOCKS_CLK_ADC_CTRL_AUXSRC_Pos) + +/* CLK_RTC CTRL */ +#define CLOCKS_CLK_RTC_CTRL_ENABLE_Pos 11U +#define CLOCKS_CLK_RTC_CTRL_ENABLE_Msk (1U << CLOCKS_CLK_RTC_CTRL_ENABLE_Pos) +#define CLOCKS_CLK_RTC_CTRL_ENABLE CLOCKS_CLK_RTC_CTRL_ENABLE_Msk +#define CLOCKS_CLK_RTC_CTRL_KILL_Pos 10U +#define CLOCKS_CLK_RTC_CTRL_KILL_Msk (1U << CLOCKS_CLK_RTC_CTRL_KILL_Pos) +#define CLOCKS_CLK_RTC_CTRL_KILL CLOCKS_CLK_RTC_CTRL_KILL_Msk +#define CLOCKS_CLK_RTC_CTRL_AUXSRC_Pos 5U +#define CLOCKS_CLK_RTC_CTRL_AUXSRC_Msk (0x7U << CLOCKS_CLK_RTC_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_RTC_CTRL_AUXSRC_PLL_USB (0x0U << CLOCKS_CLK_RTC_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_RTC_CTRL_AUXSRC_PLL_SYS (0x1U << CLOCKS_CLK_RTC_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_RTC_CTRL_AUXSRC_ROSC (0x2U << CLOCKS_CLK_RTC_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_RTC_CTRL_AUXSRC_XOSC (0x3U << CLOCKS_CLK_RTC_CTRL_AUXSRC_Pos) + +/* CLK DIV */ +#define CLOCKS_CLK_DIV_INT_Pos 8U +#define CLOCKS_CLK_DIV_INT_Msk (0xFFFFFFU << CLOCKS_CLK_DIV_INT_Pos) +#define CLOCKS_CLK_DIV_INT(n) ((n) << CLOCKS_CLK_DIV_INT_Pos) +#define CLOCKS_CLK_DIV_FRAC_Pos 0U +#define CLOCKS_CLK_DIV_FRAC_Msk (0xFFU << CLOCKS_CLK_DIV_FRAC_Pos) +#define CLOCKS_CLK_DIV_FRAC(n) ((n) << CLOCKS_CLK_DIV_FRAC_Pos) + +/* RESUS */ +#define CLOCKS_RESUS_CTRL_CLEAR_Pos 16U +#define CLOCKS_RESUS_CTRL_CLEAR_Msk (1U << CLOCKS_RESUS_CTRL_CLEAR_Pos) +#define CLOCKS_RESUS_CTRL_CLEAR CLOCKS_RESUS_CTRL_CLEAR_Msk +#define CLOCKS_RESUS_CTRL_FRCE_Pos 12U +#define CLOCKS_RESUS_CTRL_FRCE_Msk (1U << CLOCKS_RESUS_CTRL_FRCE_Pos) +#define CLOCKS_RESUS_CTRL_FRCE CLOCKS_RESUS_CTRL_FRCE_Msk +#define CLOCKS_RESUS_CTRL_ENABLE_Pos 8U +#define CLOCKS_RESUS_CTRL_ENABLE_Msk (1U << CLOCKS_RESUS_CTRL_ENABLE_Pos) +#define CLOCKS_RESUS_CTRL_ENABLE CLOCKS_RESUS_CTRL_ENABLE_Msk +#define CLOCKS_RESUS_CTRL_TIMEOUT_Pos 0U +#define CLOCKS_RESUS_CTRL_TIMEOUT_Msk (0xFFU << CLOCKS_RESUS_CTRL_TIMEOUT_Pos) +#define CLOCKS_RESUS_CTRL_TIMEOUT(n) ((n) << CLOCKS_RESUS_CTRL_TIMEOUT_Pos) + +#define CLOCKS_RESUS_STATUS_RESUSSED_Pos 0U +#define CLOCKS_RESUS_STATUS_RESUSSED_Msk (1U << CLOCKS_RESUS_STATUS_RESUSSED_Pos) +#define CLOCKS_RESUS_STATUS_RESUSSED CLOCKS_RESUS_STATUS_RESUSSED_Msk +/** @} */ + +/** + * @name Clock indexes for RP2040 + * @note These are array indices into the CLOCKS->CLK[] register array. + * @{ + */ +#define RP_CLK_GPOUT0 0U +#define RP_CLK_GPOUT1 1U +#define RP_CLK_GPOUT2 2U +#define RP_CLK_GPOUT3 3U +#define RP_CLK_REF 4U +#define RP_CLK_SYS 5U +#define RP_CLK_PERI 6U +#define RP_CLK_USB 7U +#define RP_CLK_ADC 8U +#define RP_CLK_RTC 9U +#define RP_CLK_COUNT 10U +/** @} */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* RP2040_H */ + +/** @} */ diff --git a/os/common/ext/RP/RP2040/system_rp2040.h b/os/common/ext/RP/RP2040/system_rp2040.h index 77badcba58..56ce6a860b 100644 --- a/os/common/ext/RP/RP2040/system_rp2040.h +++ b/os/common/ext/RP/RP2040/system_rp2040.h @@ -1,39 +1,39 @@ -/* - ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file RP/system_rp2040.h - * @brief CMSIS system device file for the RP2040. - * - * @defgroup CMSIS_RP2040 RP2040 System Device File - * @ingroup CMSIS_DEVICE - * @{ - */ - -#ifndef SYSTEM_RP2040_H -#define SYSTEM_RP2040_H - -extern uint32_t SystemCoreClock; - -#ifdef __cplusplus - extern "C" { -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* SYSTEM_RP2040_H */ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP/system_rp2040.h + * @brief CMSIS system device file for the RP2040. + * + * @defgroup CMSIS_RP2040 RP2040 System Device File + * @ingroup CMSIS_DEVICE + * @{ + */ + +#ifndef SYSTEM_RP2040_H +#define SYSTEM_RP2040_H + +extern uint32_t SystemCoreClock; + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* SYSTEM_RP2040_H */ diff --git a/os/common/ext/RP/RP2350/rp2350.h b/os/common/ext/RP/RP2350/rp2350.h new file mode 100644 index 0000000000..72a13d1b96 --- /dev/null +++ b/os/common/ext/RP/RP2350/rp2350.h @@ -0,0 +1,3044 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP/rp2350.h + * @brief CMSIS device file for the RP2350. + * @note This was created to roughly match the style and structure of the + * existing RP2040 CMSIS header. This allows for compatibility with + * existing RP LLD code and makes debugging and visual comparison + * easier. While not used in the final version the early work by + * @KarlK90 and @davidbuzz on the RP2350 cmsis header, particularly + * using svdtools to group registers, facilitated the creation of + * this header. + * + * @defgroup CMSIS_RP2350 RP2350 Device File + * @ingroup CMSIS_DEVICE + * @{ + */ + +#ifndef RP2350_H +#define RP2350_H + +#include + +#define __CM33_REV 0x0100U /* r1p0 */ +#define __MPU_PRESENT 1U +#define __VTOR_PRESENT 1U +#define __NVIC_PRIO_BITS 4U +#define __Vendor_SysTickConfig 0U +#define __FPU_PRESENT 1U +#define __DSP_PRESENT 1U +#define __SAU_PRESENT 1U +#define __SAUREGION_PRESENT 8U + +/** + * @brief Interrupt vector numbers. + * @note See RP2350 Datasheet 3.2 Interrupts (Table 95) + */ +typedef enum { + NonMaskableInt_IRQn = -14, + HardFault_IRQn = -13, + MemoryManagement_IRQn = -12, + BusFault_IRQn = -11, + UsageFault_IRQn = -10, + SecureFault_IRQn = -9, + SVCall_IRQn = -5, + DebugMonitor_IRQn = -4, + PendSV_IRQn = -2, + SysTick_IRQn = -1, + TIMER0_IRQ_0n = 0, + TIMER0_IRQ_1n = 1, + TIMER0_IRQ_2n = 2, + TIMER0_IRQ_3n = 3, + TIMER1_IRQ_0n = 4, + TIMER1_IRQ_1n = 5, + TIMER1_IRQ_2n = 6, + TIMER1_IRQ_3n = 7, + PWM_IRQ_WRAP_0n = 8, + PWM_IRQ_WRAP_1n = 9, + DMA_IRQ_0n = 10, + DMA_IRQ_1n = 11, + DMA_IRQ_2n = 12, + DMA_IRQ_3n = 13, + USBCTRL_IRQn = 14, + PIO0_IRQ_0n = 15, + PIO0_IRQ_1n = 16, + PIO1_IRQ_0n = 17, + PIO1_IRQ_1n = 18, + PIO2_IRQ_0n = 19, + PIO2_IRQ_1n = 20, + IO_IRQ_BANK0n = 21, + IO_IRQ_BANK0_NSn = 22, + IO_IRQ_QSPIn = 23, + IO_IRQ_QSPI_NSn = 24, + SIO_IRQ_FIFOn = 25, + SIO_IRQ_BELLn = 26, + SIO_IRQ_FIFO_NSn = 27, + SIO_IRQ_BELL_NSn = 28, + SIO_IRQ_MTIMECMPn = 29, + CLOCKS_IRQn = 30, + SPI0_IRQn = 31, + SPI1_IRQn = 32, + UART0_IRQn = 33, + UART1_IRQn = 34, + ADC_IRQ_FIFOn = 35, + I2C0_IRQn = 36, + I2C1_IRQn = 37, + OTP_IRQn = 38, + TRNG_IRQn = 39, + PROC0_IRQ_CTIn = 40, + PROC1_IRQ_CTIn = 41, + PLL_SYS_IRQn = 42, + PLL_USB_IRQn = 43, + POWMAN_IRQ_POWn = 44, + POWMAN_IRQ_TIMERn = 45, + SPARE_IRQ_0n = 46, + SPARE_IRQ_1n = 47, + SPARE_IRQ_2n = 48, + SPARE_IRQ_3n = 49, + SPARE_IRQ_4n = 50, + SPARE_IRQ_5n = 51 +} IRQn_Type; + +#define SVC_IRQn SVCall_IRQn + +#include "core_cm33.h" +#include "system_rp2350.h" + +/** + * @name Peripheral structures + * @{ + */ +typedef struct { + __IO uint32_t READ_ADDR; + __IO uint32_t WRITE_ADDR; + __IO uint32_t TRANS_COUNT; + __IO uint32_t CTRL_TRIG; + __IO uint32_t AL1_CTRL; + __IO uint32_t AL1_READ_ADDR; + __IO uint32_t AL1_WRITE_ADDR; + __IO uint32_t AL1_TRANSFER_COUNT_TRIG; + __IO uint32_t AL2_CTRL; + __IO uint32_t AL2_TRANSFER_COUNT; + __IO uint32_t AL2_READ_ADDR; + __IO uint32_t AL2_WRITE_ADDR_TRIG; + __IO uint32_t AL3_CTRL; + __IO uint32_t AL3_WRITE_ADDR; + __IO uint32_t AL3_TRANSFER_COUNT; + __IO uint32_t AL3_READ_ADDR_TRIG; +} DMA_Channel_TypeDef; + +typedef struct { + __I uint32_t CTDREQ; + __I uint32_t TCR; + __I uint32_t resvd8[14]; +} DMA_Debug_TypeDef; + +typedef struct { + DMA_Channel_TypeDef CH[16]; + __IO uint32_t INTR; + __IO uint32_t INTE0; + __IO uint32_t INTF0; + __IO uint32_t INTS0; + __IO uint32_t INTR1; + __IO uint32_t INTE1; + __IO uint32_t INTF1; + __IO uint32_t INTS1; + __IO uint32_t INTR2; + __IO uint32_t INTE2; + __IO uint32_t INTF2; + __IO uint32_t INTS2; + __IO uint32_t INTR3; + __IO uint32_t INTE3; + __IO uint32_t INTF3; + __IO uint32_t INTS3; + __IO uint32_t TIMER[4]; + __IO uint32_t MULTI_CHAN_TRIGGER; + __IO uint32_t SNIFF_CTRL; + __IO uint32_t SNIFF_DATA; + __I uint32_t resvd45C; + __I uint32_t FIFO_LEVELS; + __IO uint32_t CHAN_ABORT; + __I uint32_t N_CHANNELS; + __I uint32_t resvd46C[5]; + __IO uint32_t SECCFG_CH[16]; + __IO uint32_t SECCFG_IRQ[4]; + __IO uint32_t SECCFG_MISC; + __I uint32_t resvd4D4[203]; + DMA_Debug_TypeDef CH_DBG[16]; + __I uint32_t resvdC00[256]; + struct { + DMA_Channel_TypeDef CH[16]; + __IO uint32_t INTR; + __IO uint32_t INTE0; + __IO uint32_t INTF0; + __IO uint32_t INTS0; + __IO uint32_t INTR1; + __IO uint32_t INTE1; + __IO uint32_t INTF1; + __IO uint32_t INTS1; + __IO uint32_t INTR2; + __IO uint32_t INTE2; + __IO uint32_t INTF2; + __IO uint32_t INTS2; + __IO uint32_t INTR3; + __IO uint32_t INTE3; + __IO uint32_t INTF3; + __IO uint32_t INTS3; + __IO uint32_t TIMER[4]; + __IO uint32_t MULTI_CHAN_TRIGGER; + __IO uint32_t SNIFF_CTRL; + __IO uint32_t SNIFF_DATA; + __I uint32_t resvd45C; + __I uint32_t FIFO_LEVELS; + __IO uint32_t CHAN_ABORT; + __I uint32_t N_CHANNELS; + __I uint32_t resvd46C[5]; + __IO uint32_t SECCFG_CH[16]; + __IO uint32_t SECCFG_IRQ[4]; + __IO uint32_t SECCFG_MISC; + __I uint32_t resvd4D4[203]; + DMA_Debug_TypeDef CH_DBG[16]; + __I uint32_t resvdC00[256]; + } XOR; + struct { + DMA_Channel_TypeDef CH[16]; + __IO uint32_t INTR; + __IO uint32_t INTE0; + __IO uint32_t INTF0; + __IO uint32_t INTS0; + __IO uint32_t INTR1; + __IO uint32_t INTE1; + __IO uint32_t INTF1; + __IO uint32_t INTS1; + __IO uint32_t INTR2; + __IO uint32_t INTE2; + __IO uint32_t INTF2; + __IO uint32_t INTS2; + __IO uint32_t INTR3; + __IO uint32_t INTE3; + __IO uint32_t INTF3; + __IO uint32_t INTS3; + __IO uint32_t TIMER[4]; + __IO uint32_t MULTI_CHAN_TRIGGER; + __IO uint32_t SNIFF_CTRL; + __IO uint32_t SNIFF_DATA; + __I uint32_t resvd45C; + __I uint32_t FIFO_LEVELS; + __IO uint32_t CHAN_ABORT; + __I uint32_t N_CHANNELS; + __I uint32_t resvd46C[5]; + __IO uint32_t SECCFG_CH[16]; + __IO uint32_t SECCFG_IRQ[4]; + __IO uint32_t SECCFG_MISC; + __I uint32_t resvd4D4[203]; + DMA_Debug_TypeDef CH_DBG[16]; + __I uint32_t resvdC00[256]; + } SET; + struct { + DMA_Channel_TypeDef CH[16]; + __IO uint32_t INTR; + __IO uint32_t INTE0; + __IO uint32_t INTF0; + __IO uint32_t INTS0; + __IO uint32_t INTR1; + __IO uint32_t INTE1; + __IO uint32_t INTF1; + __IO uint32_t INTS1; + __IO uint32_t INTR2; + __IO uint32_t INTE2; + __IO uint32_t INTF2; + __IO uint32_t INTS2; + __IO uint32_t INTR3; + __IO uint32_t INTE3; + __IO uint32_t INTF3; + __IO uint32_t INTS3; + __IO uint32_t TIMER[4]; + __IO uint32_t MULTI_CHAN_TRIGGER; + __IO uint32_t SNIFF_CTRL; + __IO uint32_t SNIFF_DATA; + __I uint32_t resvd45C; + __I uint32_t FIFO_LEVELS; + __IO uint32_t CHAN_ABORT; + __I uint32_t N_CHANNELS; + __I uint32_t resvd46C[5]; + __IO uint32_t SECCFG_CH[16]; + __IO uint32_t SECCFG_IRQ[4]; + __IO uint32_t SECCFG_MISC; + __I uint32_t resvd4D4[203]; + DMA_Debug_TypeDef CH_DBG[16]; + __I uint32_t resvdC00[256]; + } CLR; +} DMA_TypeDef; + +typedef struct { + struct { + __I uint32_t STATUS; + __IO uint32_t CTRL; + } GPIO[48]; /* 0x000-0x17F */ + __I uint32_t resvd180[32]; /* 0x180-0x1FF */ + struct { + __I uint32_t SECURE[2]; + __I uint32_t NONSECURE[2]; + } IRQSUMMARY_PROC[2]; /* 0x200-0x21F */ + __I uint32_t IRQSUMMARY_DW_S[2]; /* 0x220-0x227 */ + __I uint32_t IRQSUMMARY_DW_NS[2]; /* 0x228-0x22F */ + __IO uint32_t INTR[6]; /* 0x230-0x247 */ + struct { + __IO uint32_t INTE[6]; + __IO uint32_t INTF[6]; + __I uint32_t INTS[6]; + } PROC[2]; /* 0x248-0x2D7 */ + __IO uint32_t DW_INTE[6]; /* 0x2D8-0x2EF */ + __IO uint32_t DW_INTF[6]; /* 0x2F0-0x307 */ + __I uint32_t DW_INTS[6]; /* 0x308-0x31F */ +} IOUSER_TypeDef; + +typedef struct { + struct { + __I uint32_t STATUS; + __IO uint32_t CTRL; + } USBPHY[2]; /* 0x000-0x00F */ + struct { + __I uint32_t STATUS; + __IO uint32_t CTRL; + } GPIO[6]; /* 0x010-0x03F */ + __I uint32_t resvd040[112]; /* 0x040-0x1FF */ + struct { + __I uint32_t SECURE; + __I uint32_t NONSECURE; + } IRQSUMMARY_PROC[2]; /* 0x200-0x20F */ + __I uint32_t IRQSUMMARY_DW_S; /* 0x210 */ + __I uint32_t IRQSUMMARY_DW_NS; /* 0x214 */ + __IO uint32_t INTR; /* 0x218 */ + struct { + __IO uint32_t INTE; + __IO uint32_t INTF; + __I uint32_t INTS; + } PROC[2]; /* 0x21C-0x233 */ + __IO uint32_t DW_INTE; /* 0x234 */ + __IO uint32_t DW_INTF; /* 0x238 */ + __I uint32_t DW_INTS; /* 0x23C */ +} IOQSPI_TypeDef; + +typedef struct { + __IO uint32_t VOLTAGE_SELECT; + __IO uint32_t GPIO[48]; + __IO uint32_t SWCLK; + __IO uint32_t SWD; +} PADS_TypeDef; + +typedef struct { + __IO uint32_t VOLTAGE_SELECT; + __IO uint32_t GPIO_QSPI_SCLK; + __IO uint32_t GPIO_QSPI_SD0; + __IO uint32_t GPIO_QSPI_SD1; + __IO uint32_t GPIO_QSPI_SD2; + __IO uint32_t GPIO_QSPI_SD3; + __IO uint32_t GPIO_QSPI_SS; +} PADS_QSPI_TypeDef; + +typedef struct { + __IO uint32_t FRCE_ON; + __IO uint32_t FRCE_OFF; + __IO uint32_t WDSEL; + __I uint32_t DONE; + __I uint32_t resvd10[1020]; + struct { + __IO uint32_t FRCE_ON; + __IO uint32_t FRCE_OFF; + __IO uint32_t WDSEL; + __I uint32_t DONE; + __I uint32_t resvd10[1020]; + } XOR; + struct { + __IO uint32_t FRCE_ON; + __IO uint32_t FRCE_OFF; + __IO uint32_t WDSEL; + __I uint32_t DONE; + __I uint32_t resvd10[1020]; + } SET; + struct { + __IO uint32_t FRCE_ON; + __IO uint32_t FRCE_OFF; + __IO uint32_t WDSEL; + __I uint32_t DONE; + __I uint32_t resvd10[1020]; + } CLR; +} PSM_TypeDef; + +typedef struct { + __IO uint32_t RESET; + __IO uint32_t WDSEL; + __I uint32_t RESET_DONE; + __I uint32_t resvdC[1021]; + struct { + __IO uint32_t RESET; + __IO uint32_t WDSEL; + __I uint32_t RESET_DONE; + __I uint32_t resvdC[1021]; + } XOR; + struct { + __IO uint32_t RESET; + __IO uint32_t WDSEL; + __I uint32_t RESET_DONE; + __I uint32_t resvdC[1021]; + } SET; + struct { + __IO uint32_t RESET; + __IO uint32_t WDSEL; + __I uint32_t RESET_DONE; + __I uint32_t resvdC[1021]; + } CLR; +} RESETS_TypeDef; + +/** + * @brief SIO peripheral. + * @note RP2350 interleaves base GPIO and GPIO_HI registers differently + * from RP2040. The base GPIO registers control GPIO 0-31, while + * GPIO_HI registers control GPIO 32-47 plus QSPI and USB. + */ +typedef struct { + __I uint32_t CPUID; + __I uint32_t GPIO_IN; + __I uint32_t GPIO_HI_IN; + __I uint32_t resvdC; + __IO uint32_t GPIO_OUT; + __IO uint32_t GPIO_HI_OUT; + __IO uint32_t GPIO_OUT_SET; + __IO uint32_t GPIO_HI_OUT_SET; + __IO uint32_t GPIO_OUT_CLR; + __IO uint32_t GPIO_HI_OUT_CLR; + __IO uint32_t GPIO_OUT_XOR; + __IO uint32_t GPIO_HI_OUT_XOR; + __IO uint32_t GPIO_OE; + __IO uint32_t GPIO_HI_OE; + __IO uint32_t GPIO_OE_SET; + __IO uint32_t GPIO_HI_OE_SET; + __IO uint32_t GPIO_OE_CLR; + __IO uint32_t GPIO_HI_OE_CLR; + __IO uint32_t GPIO_OE_XOR; + __IO uint32_t GPIO_HI_OE_XOR; + __IO uint32_t FIFO_ST; + __IO uint32_t FIFO_WR; + __I uint32_t FIFO_RD; + __IO uint32_t SPINLOCK_ST; + __I uint32_t resvd60[8]; + struct { + __IO uint32_t ACCUM0; + __IO uint32_t ACCUM1; + __IO uint32_t BASE0; + __IO uint32_t BASE1; + __IO uint32_t BASE2; + __I uint32_t POP_LANE0; + __I uint32_t POP_LANE1; + __I uint32_t POP_FULL; + __I uint32_t PEEK_LANE0; + __I uint32_t PEEK_LANE1; + __I uint32_t PEEK_FULL; + __IO uint32_t CTRL_LANE0; + __IO uint32_t CTRL_LANE1; + __IO uint32_t ACCUM0_ADD; + __IO uint32_t ACCUM1_ADD; + __IO uint32_t BASE_1AND0; + } INTERP[2]; + __IO uint32_t SPINLOCK[32]; + __IO uint32_t DOORBELL_OUT_SET; + __IO uint32_t DOORBELL_OUT_CLR; + __I uint32_t DOORBELL_IN_SET; + __I uint32_t DOORBELL_IN_CLR; + __IO uint32_t PERI_NONSEC; + __I uint32_t resvd194[3]; + __IO uint32_t RISCV_SOFTIRQ; + __IO uint32_t MTIME_CTRL; + __I uint32_t resvd1A8[2]; + __IO uint32_t MTIME; + __IO uint32_t MTIMEH; + __IO uint32_t MTIMECMP; + __IO uint32_t MTIMECMPH; + __IO uint32_t TMDS_CTRL; + __IO uint32_t TMDS_WDATA; + __I uint32_t TMDS_PEEK_SINGLE; + __I uint32_t TMDS_POP_SINGLE; + __I uint32_t TMDS_PEEK_DOUBLE_L0; + __I uint32_t TMDS_POP_DOUBLE_L0; + __I uint32_t TMDS_PEEK_DOUBLE_L1; + __I uint32_t TMDS_POP_DOUBLE_L1; + __I uint32_t TMDS_PEEK_DOUBLE_L2; + __I uint32_t TMDS_POP_DOUBLE_L2; +} SIO_TypeDef; + +typedef struct { + __IO uint32_t SSPCR0; + __IO uint32_t SSPCR1; + __IO uint32_t SSPDR; + __I uint32_t SSPSR; + __IO uint32_t SSPCPSR; + __IO uint32_t SSPIMSC; + __I uint32_t SSPRIS; + __I uint32_t SSPMIS; + __IO uint32_t SSPICR; + __IO uint32_t SSPDMACR; + __I uint32_t resvd28[1006]; + __I uint32_t SSPPERIPHID0; + __I uint32_t SSPPERIPHID1; + __I uint32_t SSPPERIPHID2; + __I uint32_t SSPPERIPHID3; + __I uint32_t SSPPCELLID0; + __I uint32_t SSPPCELLID1; + __I uint32_t SSPPCELLID2; + __I uint32_t SSPPCELLID3; + struct { + __IO uint32_t SSPCR0; + __IO uint32_t SSPCR1; + __IO uint32_t SSPDR; + __I uint32_t SSPSR; + __IO uint32_t SSPCPSR; + __IO uint32_t SSPIMSC; + __I uint32_t SSPRIS; + __I uint32_t SSPMIS; + __IO uint32_t SSPICR; + __IO uint32_t SSPDMACR; + __I uint32_t resvd28[1006]; + __I uint32_t SSPPERIPHID0; + __I uint32_t SSPPERIPHID1; + __I uint32_t SSPPERIPHID2; + __I uint32_t SSPPERIPHID3; + __I uint32_t SSPPCELLID0; + __I uint32_t SSPPCELLID1; + __I uint32_t SSPPCELLID2; + __I uint32_t SSPPCELLID3; + } XOR; + struct { + __IO uint32_t SSPCR0; + __IO uint32_t SSPCR1; + __IO uint32_t SSPDR; + __I uint32_t SSPSR; + __IO uint32_t SSPCPSR; + __IO uint32_t SSPIMSC; + __I uint32_t SSPRIS; + __I uint32_t SSPMIS; + __IO uint32_t SSPICR; + __IO uint32_t SSPDMACR; + __I uint32_t resvd28[1006]; + __I uint32_t SSPPERIPHID0; + __I uint32_t SSPPERIPHID1; + __I uint32_t SSPPERIPHID2; + __I uint32_t SSPPERIPHID3; + __I uint32_t SSPPCELLID0; + __I uint32_t SSPPCELLID1; + __I uint32_t SSPPCELLID2; + __I uint32_t SSPPCELLID3; + } SET; + struct { + __IO uint32_t SSPCR0; + __IO uint32_t SSPCR1; + __IO uint32_t SSPDR; + __I uint32_t SSPSR; + __IO uint32_t SSPCPSR; + __IO uint32_t SSPIMSC; + __I uint32_t SSPRIS; + __I uint32_t SSPMIS; + __IO uint32_t SSPICR; + __IO uint32_t SSPDMACR; + __I uint32_t resvd28[1006]; + __I uint32_t SSPPERIPHID0; + __I uint32_t SSPPERIPHID1; + __I uint32_t SSPPERIPHID2; + __I uint32_t SSPPERIPHID3; + __I uint32_t SSPPCELLID0; + __I uint32_t SSPPCELLID1; + __I uint32_t SSPPCELLID2; + __I uint32_t SSPPCELLID3; + } CLR; +} SPI_TypeDef; + +typedef struct { + __IO uint32_t TIMEHW; + __IO uint32_t TIMELW; + __I uint32_t TIMEHR; + __I uint32_t TIMELR; + __IO uint32_t ALARM[4]; + __IO uint32_t ARMED; + __I uint32_t TIMERAWH; + __I uint32_t TIMERAWL; + __IO uint32_t DBGPAUSE; + __IO uint32_t PAUSE; + __IO uint32_t LOCKED; + __IO uint32_t SOURCE; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __I uint32_t INTS; + __I uint32_t resvd4C[1005]; + struct { + __IO uint32_t TIMEHW; + __IO uint32_t TIMELW; + __I uint32_t TIMEHR; + __I uint32_t TIMELR; + __IO uint32_t ALARM[4]; + __IO uint32_t ARMED; + __I uint32_t TIMERAWH; + __I uint32_t TIMERAWL; + __IO uint32_t DBGPAUSE; + __IO uint32_t PAUSE; + __IO uint32_t LOCKED; + __IO uint32_t SOURCE; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __I uint32_t INTS; + __I uint32_t resvd4C[1005]; + } XOR; + struct { + __IO uint32_t TIMEHW; + __IO uint32_t TIMELW; + __I uint32_t TIMEHR; + __I uint32_t TIMELR; + __IO uint32_t ALARM[4]; + __IO uint32_t ARMED; + __I uint32_t TIMERAWH; + __I uint32_t TIMERAWL; + __IO uint32_t DBGPAUSE; + __IO uint32_t PAUSE; + __IO uint32_t LOCKED; + __IO uint32_t SOURCE; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __I uint32_t INTS; + __I uint32_t resvd4C[1005]; + } SET; + struct { + __IO uint32_t TIMEHW; + __IO uint32_t TIMELW; + __I uint32_t TIMEHR; + __I uint32_t TIMELR; + __IO uint32_t ALARM[4]; + __IO uint32_t ARMED; + __I uint32_t TIMERAWH; + __I uint32_t TIMERAWL; + __IO uint32_t DBGPAUSE; + __IO uint32_t PAUSE; + __IO uint32_t LOCKED; + __IO uint32_t SOURCE; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __I uint32_t INTS; + __I uint32_t resvd4C[1005]; + } CLR; +} TIMER_TypeDef; + +typedef struct { + __IO uint32_t UARTDR; + __IO uint32_t UARTRSR; + __I uint32_t resvd8[4]; + __I uint32_t UARTFR; + __I uint32_t resvd1C; + __IO uint32_t UARTILPR; + __IO uint32_t UARTIBRD; + __IO uint32_t UARTFBRD; + __IO uint32_t UARTLCR_H; + __IO uint32_t UARTCR; + __IO uint32_t UARTIFLS; + __IO uint32_t UARTIMSC; + __I uint32_t UARTRIS; + __I uint32_t UARTMIS; + __IO uint32_t UARTICR; + __IO uint32_t UARTDMACR; + __I uint32_t resvd4C[997]; + __I uint32_t UARTPERIPHID0; + __I uint32_t UARTPERIPHID1; + __I uint32_t UARTPERIPHID2; + __I uint32_t UARTPERIPHID3; + __I uint32_t UARTPCELLID0; + __I uint32_t UARTPCELLID1; + __I uint32_t UARTPCELLID2; + __I uint32_t UARTPCELLID3; + struct { + __IO uint32_t UARTDR; + __IO uint32_t UARTRSR; + __I uint32_t resvd8[4]; + __I uint32_t UARTFR; + __I uint32_t resvd1C; + __IO uint32_t UARTILPR; + __IO uint32_t UARTIBRD; + __IO uint32_t UARTFBRD; + __IO uint32_t UARTLCR_H; + __IO uint32_t UARTCR; + __IO uint32_t UARTIFLS; + __IO uint32_t UARTIMSC; + __I uint32_t UARTRIS; + __I uint32_t UARTMIS; + __IO uint32_t UARTICR; + __IO uint32_t UARTDMACR; + __I uint32_t resvd4C[997]; + __I uint32_t UARTPERIPHID0; + __I uint32_t UARTPERIPHID1; + __I uint32_t UARTPERIPHID2; + __I uint32_t UARTPERIPHID3; + __I uint32_t UARTPCELLID0; + __I uint32_t UARTPCELLID1; + __I uint32_t UARTPCELLID2; + __I uint32_t UARTPCELLID3; + } XOR; + struct { + __IO uint32_t UARTDR; + __IO uint32_t UARTRSR; + __I uint32_t resvd8[4]; + __I uint32_t UARTFR; + __I uint32_t resvd1C; + __IO uint32_t UARTILPR; + __IO uint32_t UARTIBRD; + __IO uint32_t UARTFBRD; + __IO uint32_t UARTLCR_H; + __IO uint32_t UARTCR; + __IO uint32_t UARTIFLS; + __IO uint32_t UARTIMSC; + __I uint32_t UARTRIS; + __I uint32_t UARTMIS; + __IO uint32_t UARTICR; + __IO uint32_t UARTDMACR; + __I uint32_t resvd4C[997]; + __I uint32_t UARTPERIPHID0; + __I uint32_t UARTPERIPHID1; + __I uint32_t UARTPERIPHID2; + __I uint32_t UARTPERIPHID3; + __I uint32_t UARTPCELLID0; + __I uint32_t UARTPCELLID1; + __I uint32_t UARTPCELLID2; + __I uint32_t UARTPCELLID3; + } SET; + struct { + __IO uint32_t UARTDR; + __IO uint32_t UARTRSR; + __I uint32_t resvd8[4]; + __I uint32_t UARTFR; + __I uint32_t resvd1C; + __IO uint32_t UARTILPR; + __IO uint32_t UARTIBRD; + __IO uint32_t UARTFBRD; + __IO uint32_t UARTLCR_H; + __IO uint32_t UARTCR; + __IO uint32_t UARTIFLS; + __IO uint32_t UARTIMSC; + __I uint32_t UARTRIS; + __I uint32_t UARTMIS; + __IO uint32_t UARTICR; + __IO uint32_t UARTDMACR; + __I uint32_t resvd4C[997]; + __I uint32_t UARTPERIPHID0; + __I uint32_t UARTPERIPHID1; + __I uint32_t UARTPERIPHID2; + __I uint32_t UARTPERIPHID3; + __I uint32_t UARTPCELLID0; + __I uint32_t UARTPCELLID1; + __I uint32_t UARTPCELLID2; + __I uint32_t UARTPCELLID3; + } CLR; +} UART_TypeDef; + +typedef struct { + __IO uint32_t CON; + __IO uint32_t TAR; + __IO uint32_t SAR; + __I uint32_t resvdC; + __IO uint32_t DATACMD; + __IO uint32_t SSSCLHCNT; + __IO uint32_t SSSCLLCNT; + __IO uint32_t FSSCLHCNT; + __IO uint32_t FSSCLLCNT; + __I uint32_t resvd24[2]; + __IO uint32_t INTRSTAT; + __IO uint32_t INTRMASK; + __IO uint32_t RAWINTRSTAT; + __IO uint32_t RXTL; + __IO uint32_t TXTL; + __IO uint32_t CLRINTR; + __IO uint32_t CLRRXUNDER; + __IO uint32_t CLRRXOVER; + __IO uint32_t CLRTXOVER; + __IO uint32_t CLRRDREQ; + __IO uint32_t CLRTXABRT; + __IO uint32_t CLRRXDONE; + __IO uint32_t CLRACTIVITY; + __IO uint32_t CLRSTOPDET; + __IO uint32_t CLRSTARTDET; + __IO uint32_t CLRGENCALL; + __IO uint32_t ENABLE; + __IO uint32_t STATUS; + __IO uint32_t TXFLR; + __IO uint32_t RXFLR; + __IO uint32_t SDAHOLD; + __IO uint32_t TXABRTSOURCE; + __IO uint32_t SLVDATANACKONLY; + __IO uint32_t DMACR; + __IO uint32_t DMATDLR; + __IO uint32_t DMARDLR; + __IO uint32_t SDASETUP; + __IO uint32_t ACKGENERALCALL; + __IO uint32_t ENABLESTATUS; + __IO uint32_t FSSPKLEN; + __I uint32_t resvdA4; + __IO uint32_t CLRRESTARTDET; + __I uint32_t resvdac[981]; + struct { + __IO uint32_t CON; + __IO uint32_t TAR; + __IO uint32_t SAR; + __I uint32_t resvdC; + __IO uint32_t DATACMD; + __IO uint32_t SSSCLHCNT; + __IO uint32_t SSSCLLCNT; + __IO uint32_t FSSCLHCNT; + __IO uint32_t FSSCLLCNT; + __I uint32_t resvd24[2]; + __IO uint32_t INTRSTAT; + __IO uint32_t INTRMASK; + __IO uint32_t RAWINTRSTAT; + __IO uint32_t RXTL; + __IO uint32_t TXTL; + __IO uint32_t CLRINTR; + __IO uint32_t CLRRXUNDER; + __IO uint32_t CLRRXOVER; + __IO uint32_t CLRTXOVER; + __IO uint32_t CLRRDREQ; + __IO uint32_t CLRTXABRT; + __IO uint32_t CLRRXDONE; + __IO uint32_t CLRACTIVITY; + __IO uint32_t CLRSTOPDET; + __IO uint32_t CLRSTARTDET; + __IO uint32_t CLRGENCALL; + __IO uint32_t ENABLE; + __IO uint32_t STATUS; + __IO uint32_t TXFLR; + __IO uint32_t RXFLR; + __IO uint32_t SDAHOLD; + __IO uint32_t TXABRTSOURCE; + __IO uint32_t SLVDATANACKONLY; + __IO uint32_t DMACR; + __IO uint32_t DMATDLR; + __IO uint32_t DMARDLR; + __IO uint32_t SDASETUP; + __IO uint32_t ACKGENERALCALL; + __IO uint32_t ENABLESTATUS; + __IO uint32_t FSSPKLEN; + __I uint32_t resvdA4; + __IO uint32_t CLRRESTARTDET; + __I uint32_t resvdac[981]; + } XOR; + struct { + __IO uint32_t CON; + __IO uint32_t TAR; + __IO uint32_t SAR; + __I uint32_t resvdC; + __IO uint32_t DATACMD; + __IO uint32_t SSSCLHCNT; + __IO uint32_t SSSCLLCNT; + __IO uint32_t FSSCLHCNT; + __IO uint32_t FSSCLLCNT; + __I uint32_t resvd24[2]; + __IO uint32_t INTRSTAT; + __IO uint32_t INTRMASK; + __IO uint32_t RAWINTRSTAT; + __IO uint32_t RXTL; + __IO uint32_t TXTL; + __IO uint32_t CLRINTR; + __IO uint32_t CLRRXUNDER; + __IO uint32_t CLRRXOVER; + __IO uint32_t CLRTXOVER; + __IO uint32_t CLRRDREQ; + __IO uint32_t CLRTXABRT; + __IO uint32_t CLRRXDONE; + __IO uint32_t CLRACTIVITY; + __IO uint32_t CLRSTOPDET; + __IO uint32_t CLRSTARTDET; + __IO uint32_t CLRGENCALL; + __IO uint32_t ENABLE; + __IO uint32_t STATUS; + __IO uint32_t TXFLR; + __IO uint32_t RXFLR; + __IO uint32_t SDAHOLD; + __IO uint32_t TXABRTSOURCE; + __IO uint32_t SLVDATANACKONLY; + __IO uint32_t DMACR; + __IO uint32_t DMATDLR; + __IO uint32_t DMARDLR; + __IO uint32_t SDASETUP; + __IO uint32_t ACKGENERALCALL; + __IO uint32_t ENABLESTATUS; + __IO uint32_t FSSPKLEN; + __I uint32_t resvdA4; + __IO uint32_t CLRRESTARTDET; + __I uint32_t resvdac[981]; + } SET; + struct { + __IO uint32_t CON; + __IO uint32_t TAR; + __IO uint32_t SAR; + __I uint32_t resvdC; + __IO uint32_t DATACMD; + __IO uint32_t SSSCLHCNT; + __IO uint32_t SSSCLLCNT; + __IO uint32_t FSSCLHCNT; + __IO uint32_t FSSCLLCNT; + __I uint32_t resvd24[2]; + __IO uint32_t INTRSTAT; + __IO uint32_t INTRMASK; + __IO uint32_t RAWINTRSTAT; + __IO uint32_t RXTL; + __IO uint32_t TXTL; + __IO uint32_t CLRINTR; + __IO uint32_t CLRRXUNDER; + __IO uint32_t CLRRXOVER; + __IO uint32_t CLRTXOVER; + __IO uint32_t CLRRDREQ; + __IO uint32_t CLRTXABRT; + __IO uint32_t CLRRXDONE; + __IO uint32_t CLRACTIVITY; + __IO uint32_t CLRSTOPDET; + __IO uint32_t CLRSTARTDET; + __IO uint32_t CLRGENCALL; + __IO uint32_t ENABLE; + __IO uint32_t STATUS; + __IO uint32_t TXFLR; + __IO uint32_t RXFLR; + __IO uint32_t SDAHOLD; + __IO uint32_t TXABRTSOURCE; + __IO uint32_t SLVDATANACKONLY; + __IO uint32_t DMACR; + __IO uint32_t DMATDLR; + __IO uint32_t DMARDLR; + __IO uint32_t SDASETUP; + __IO uint32_t ACKGENERALCALL; + __IO uint32_t ENABLESTATUS; + __IO uint32_t FSSPKLEN; + __I uint32_t resvdA4; + __IO uint32_t CLRRESTARTDET; + __I uint32_t resvdac[981]; + } CLR; +} I2C_TypeDef; + +typedef struct { + __IO uint32_t CS; + __IO uint32_t RESULT; + __IO uint32_t FCS; + __IO uint32_t FIFO; + __IO uint32_t DIV; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __IO uint32_t INTS; + __I uint32_t resvd24[1015]; + struct { + __IO uint32_t CS; + __IO uint32_t RESULT; + __IO uint32_t FCS; + __IO uint32_t FIFO; + __IO uint32_t DIV; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __IO uint32_t INTS; + __I uint32_t resvd24[1015]; + } XOR; + struct { + __IO uint32_t CS; + __IO uint32_t RESULT; + __IO uint32_t FCS; + __IO uint32_t FIFO; + __IO uint32_t DIV; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __IO uint32_t INTS; + __I uint32_t resvd24[1015]; + } SET; + struct { + __IO uint32_t CS; + __IO uint32_t RESULT; + __IO uint32_t FCS; + __IO uint32_t FIFO; + __IO uint32_t DIV; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __IO uint32_t INTS; + __I uint32_t resvd24[1015]; + } CLR; +} ADC_TypeDef; + +typedef struct { + struct { + __IO uint32_t CSR; + __IO uint32_t DIV; + __IO uint32_t CTR; + __IO uint32_t CC; + __IO uint32_t TOP; + } CH[12]; + __IO uint32_t EN; + __IO uint32_t INTR; + __IO uint32_t IRQ0_INTE; + __IO uint32_t IRQ0_INTF; + __I uint32_t IRQ0_INTS; + __IO uint32_t IRQ1_INTE; + __IO uint32_t IRQ1_INTF; + __I uint32_t IRQ1_INTS; + __I uint32_t resvdpwm[956]; + struct { + struct { + __IO uint32_t CSR; + __IO uint32_t DIV; + __IO uint32_t CTR; + __IO uint32_t CC; + __IO uint32_t TOP; + } CH[12]; + __IO uint32_t EN; + __IO uint32_t INTR; + __IO uint32_t IRQ0_INTE; + __IO uint32_t IRQ0_INTF; + __I uint32_t IRQ0_INTS; + __IO uint32_t IRQ1_INTE; + __IO uint32_t IRQ1_INTF; + __I uint32_t IRQ1_INTS; + __I uint32_t resvdpwm[956]; + } XOR; + struct { + struct { + __IO uint32_t CSR; + __IO uint32_t DIV; + __IO uint32_t CTR; + __IO uint32_t CC; + __IO uint32_t TOP; + } CH[12]; + __IO uint32_t EN; + __IO uint32_t INTR; + __IO uint32_t IRQ0_INTE; + __IO uint32_t IRQ0_INTF; + __I uint32_t IRQ0_INTS; + __IO uint32_t IRQ1_INTE; + __IO uint32_t IRQ1_INTF; + __I uint32_t IRQ1_INTS; + __I uint32_t resvdpwm[956]; + } SET; + struct { + struct { + __IO uint32_t CSR; + __IO uint32_t DIV; + __IO uint32_t CTR; + __IO uint32_t CC; + __IO uint32_t TOP; + } CH[12]; + __IO uint32_t EN; + __IO uint32_t INTR; + __IO uint32_t IRQ0_INTE; + __IO uint32_t IRQ0_INTF; + __I uint32_t IRQ0_INTS; + __IO uint32_t IRQ1_INTE; + __IO uint32_t IRQ1_INTF; + __I uint32_t IRQ1_INTS; + __I uint32_t resvdpwm[956]; + } CLR; +} PWM_TypeDef; + +typedef struct { + __IO uint32_t DEVADDRCTRL; + __IO uint32_t INTEPADDRCTRL[15]; + __IO uint32_t MAINCTRL; + __IO uint32_t SOFRW; + __I uint32_t SOFRD; + __IO uint32_t SIECTRL; + __IO uint32_t SIESTATUS; + __IO uint32_t INTEPCTRL; + __IO uint32_t BUFSTATUS; + __IO uint32_t BUFCPUSHOULDHANDLE; + __IO uint32_t ABORT; + __IO uint32_t ABORTDONE; + __IO uint32_t EPSTALLARM; + __IO uint32_t NAKPOLL; + __IO uint32_t EPNAKSTALLSTATUS; + __IO uint32_t MUXING; + __IO uint32_t PWR; + __IO uint32_t PHYDIRECT; + __IO uint32_t PHYDIRECTOVERRIDE; + __IO uint32_t PHYTRIM; + __IO uint32_t LINESTATETUNING; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __IO uint32_t INTS; + __I uint32_t resvd[985]; + struct { + __IO uint32_t DEVADDRCTRL; + __IO uint32_t INTEPADDRCTRL[15]; + __IO uint32_t MAINCTRL; + __IO uint32_t SOFRW; + __I uint32_t SOFRD; + __IO uint32_t SIECTRL; + __IO uint32_t SIESTATUS; + __IO uint32_t INTEPCTRL; + __IO uint32_t BUFSTATUS; + __IO uint32_t BUFCPUSHOULDHANDLE; + __IO uint32_t ABORT; + __IO uint32_t ABORTDONE; + __IO uint32_t EPSTALLARM; + __IO uint32_t NAKPOLL; + __IO uint32_t EPNAKSTALLSTATUS; + __IO uint32_t MUXING; + __IO uint32_t PWR; + __IO uint32_t PHYDIRECT; + __IO uint32_t PHYDIRECTOVERRIDE; + __IO uint32_t PHYTRIM; + __IO uint32_t LINESTATETUNING; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __IO uint32_t INTS; + __I uint32_t resvd[985]; + } XOR; + struct { + __IO uint32_t DEVADDRCTRL; + __IO uint32_t INTEPADDRCTRL[15]; + __IO uint32_t MAINCTRL; + __IO uint32_t SOFRW; + __I uint32_t SOFRD; + __IO uint32_t SIECTRL; + __IO uint32_t SIESTATUS; + __IO uint32_t INTEPCTRL; + __IO uint32_t BUFSTATUS; + __IO uint32_t BUFCPUSHOULDHANDLE; + __IO uint32_t ABORT; + __IO uint32_t ABORTDONE; + __IO uint32_t EPSTALLARM; + __IO uint32_t NAKPOLL; + __IO uint32_t EPNAKSTALLSTATUS; + __IO uint32_t MUXING; + __IO uint32_t PWR; + __IO uint32_t PHYDIRECT; + __IO uint32_t PHYDIRECTOVERRIDE; + __IO uint32_t PHYTRIM; + __IO uint32_t LINESTATETUNING; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __IO uint32_t INTS; + __I uint32_t resvd[985]; + } SET; + struct { + __IO uint32_t DEVADDRCTRL; + __IO uint32_t INTEPADDRCTRL[15]; + __IO uint32_t MAINCTRL; + __IO uint32_t SOFRW; + __I uint32_t SOFRD; + __IO uint32_t SIECTRL; + __IO uint32_t SIESTATUS; + __IO uint32_t INTEPCTRL; + __IO uint32_t BUFSTATUS; + __IO uint32_t BUFCPUSHOULDHANDLE; + __IO uint32_t ABORT; + __IO uint32_t ABORTDONE; + __IO uint32_t EPSTALLARM; + __IO uint32_t NAKPOLL; + __IO uint32_t EPNAKSTALLSTATUS; + __IO uint32_t MUXING; + __IO uint32_t PWR; + __IO uint32_t PHYDIRECT; + __IO uint32_t PHYDIRECTOVERRIDE; + __IO uint32_t PHYTRIM; + __IO uint32_t LINESTATETUNING; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __IO uint32_t INTS; + __I uint32_t resvd[985]; + } CLR; +} USB_TypeDef; + +/** + * @brief RP2350 WATCHDOG peripheral. + * @note RP2350 moved TICK to TICKS peripheral. + */ +typedef struct { + __IO uint32_t CTRL; + __O uint32_t LOAD; + __I uint32_t REASON; + __IO uint32_t SCRATCH[8]; + __I uint32_t resvd2c[1013]; + struct { + __IO uint32_t CTRL; + __O uint32_t LOAD; + __I uint32_t REASON; + __IO uint32_t SCRATCH[8]; + __I uint32_t resvd2c[1013]; + } XOR; + struct { + __IO uint32_t CTRL; + __O uint32_t LOAD; + __I uint32_t REASON; + __IO uint32_t SCRATCH[8]; + __I uint32_t resvd2c[1013]; + } SET; + struct { + __IO uint32_t CTRL; + __O uint32_t LOAD; + __I uint32_t REASON; + __IO uint32_t SCRATCH[8]; + __I uint32_t resvd2c[1013]; + } CLR; +} WATCHDOG_TypeDef; + +typedef struct { + __IO uint32_t CTRL; + __IO uint32_t CYCLES; + __I uint32_t COUNT; +} TICKS_TICK_TypeDef; + +typedef struct { + TICKS_TICK_TypeDef TICK[6]; +} TICKS_TypeDef; + +typedef struct { + __IO uint32_t CTRL; + __I uint32_t FSTAT; + __IO uint32_t FDEBUG; + __I uint32_t FLEVEL; + __IO uint32_t TXF[4]; + __I uint32_t RXF[4]; + __IO uint32_t IRQ; + __IO uint32_t IRQ_FORCE; + __IO uint32_t INPUT_SYNC_BYPASS; + __IO uint32_t DBG_PADOUT; + __IO uint32_t DBG_PADOE; + __IO uint32_t DBG_CFGINFO; + __IO uint32_t INSTR_MEM[32]; + struct { + __IO uint32_t CLKDIV; + __IO uint32_t EXECCTRL; + __IO uint32_t SHIFTCTRL; + __I uint32_t ADDR; + __IO uint32_t INSTR; + __IO uint32_t PINCTRL; + } SM[4]; + __IO uint32_t RXF_PUTGET[4][4]; + __I uint32_t GPIOBASE; + __IO uint32_t INTR; + __IO uint32_t IRQ0_INTE; + __IO uint32_t IRQ0_INTF; + __I uint32_t IRQ0_INTS; + __IO uint32_t IRQ1_INTE; + __IO uint32_t IRQ1_INTF; + __I uint32_t IRQ1_INTS; + __I uint32_t resvd188[926]; + struct { + __IO uint32_t CTRL; + __I uint32_t FSTAT; + __IO uint32_t FDEBUG; + __I uint32_t FLEVEL; + __IO uint32_t TXF[4]; + __I uint32_t RXF[4]; + __IO uint32_t IRQ; + __IO uint32_t IRQ_FORCE; + __IO uint32_t INPUT_SYNC_BYPASS; + __IO uint32_t DBG_PADOUT; + __IO uint32_t DBG_PADOE; + __IO uint32_t DBG_CFGINFO; + __IO uint32_t INSTR_MEM[32]; + struct { + __IO uint32_t CLKDIV; + __IO uint32_t EXECCTRL; + __IO uint32_t SHIFTCTRL; + __I uint32_t ADDR; + __IO uint32_t INSTR; + __IO uint32_t PINCTRL; + } SM[4]; + __IO uint32_t RXF_PUTGET[4][4]; + __I uint32_t GPIOBASE; + __IO uint32_t INTR; + __IO uint32_t IRQ0_INTE; + __IO uint32_t IRQ0_INTF; + __I uint32_t IRQ0_INTS; + __IO uint32_t IRQ1_INTE; + __IO uint32_t IRQ1_INTF; + __I uint32_t IRQ1_INTS; + __I uint32_t resvd188[926]; + } XOR; + struct { + __IO uint32_t CTRL; + __I uint32_t FSTAT; + __IO uint32_t FDEBUG; + __I uint32_t FLEVEL; + __IO uint32_t TXF[4]; + __I uint32_t RXF[4]; + __IO uint32_t IRQ; + __IO uint32_t IRQ_FORCE; + __IO uint32_t INPUT_SYNC_BYPASS; + __IO uint32_t DBG_PADOUT; + __IO uint32_t DBG_PADOE; + __IO uint32_t DBG_CFGINFO; + __IO uint32_t INSTR_MEM[32]; + struct { + __IO uint32_t CLKDIV; + __IO uint32_t EXECCTRL; + __IO uint32_t SHIFTCTRL; + __I uint32_t ADDR; + __IO uint32_t INSTR; + __IO uint32_t PINCTRL; + } SM[4]; + __IO uint32_t RXF_PUTGET[4][4]; + __I uint32_t GPIOBASE; + __IO uint32_t INTR; + __IO uint32_t IRQ0_INTE; + __IO uint32_t IRQ0_INTF; + __I uint32_t IRQ0_INTS; + __IO uint32_t IRQ1_INTE; + __IO uint32_t IRQ1_INTF; + __I uint32_t IRQ1_INTS; + __I uint32_t resvd188[926]; + } SET; + struct { + __IO uint32_t CTRL; + __I uint32_t FSTAT; + __IO uint32_t FDEBUG; + __I uint32_t FLEVEL; + __IO uint32_t TXF[4]; + __I uint32_t RXF[4]; + __IO uint32_t IRQ; + __IO uint32_t IRQ_FORCE; + __IO uint32_t INPUT_SYNC_BYPASS; + __IO uint32_t DBG_PADOUT; + __IO uint32_t DBG_PADOE; + __IO uint32_t DBG_CFGINFO; + __IO uint32_t INSTR_MEM[32]; + struct { + __IO uint32_t CLKDIV; + __IO uint32_t EXECCTRL; + __IO uint32_t SHIFTCTRL; + __I uint32_t ADDR; + __IO uint32_t INSTR; + __IO uint32_t PINCTRL; + } SM[4]; + __IO uint32_t RXF_PUTGET[4][4]; + __I uint32_t GPIOBASE; + __IO uint32_t INTR; + __IO uint32_t IRQ0_INTE; + __IO uint32_t IRQ0_INTF; + __I uint32_t IRQ0_INTS; + __IO uint32_t IRQ1_INTE; + __IO uint32_t IRQ1_INTF; + __I uint32_t IRQ1_INTS; + __I uint32_t resvd188[926]; + } CLR; +} PIO_TypeDef; + +typedef struct { + __IO uint32_t CTRL; + __I uint32_t STATUS; + __IO uint32_t DORMANT; + __IO uint32_t STARTUP; + __I uint32_t resvd10[3]; + __IO uint32_t COUNT; + __I uint32_t resvd20[1016]; + struct { + __IO uint32_t CTRL; + __I uint32_t STATUS; + __IO uint32_t DORMANT; + __IO uint32_t STARTUP; + __I uint32_t resvd10[3]; + __IO uint32_t COUNT; + __I uint32_t resvd20[1016]; + } XOR; + struct { + __IO uint32_t CTRL; + __I uint32_t STATUS; + __IO uint32_t DORMANT; + __IO uint32_t STARTUP; + __I uint32_t resvd10[3]; + __IO uint32_t COUNT; + __I uint32_t resvd20[1016]; + } SET; + struct { + __IO uint32_t CTRL; + __I uint32_t STATUS; + __IO uint32_t DORMANT; + __IO uint32_t STARTUP; + __I uint32_t resvd10[3]; + __IO uint32_t COUNT; + __I uint32_t resvd20[1016]; + } CLR; +} XOSC_TypeDef; + +typedef struct { + __IO uint32_t CS; + __IO uint32_t PWR; + __IO uint32_t FBDIV_INT; + __IO uint32_t PRIM; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __I uint32_t INTS; + __I uint32_t resvd20[1016]; + struct { + __IO uint32_t CS; + __IO uint32_t PWR; + __IO uint32_t FBDIV_INT; + __IO uint32_t PRIM; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __I uint32_t INTS; + __I uint32_t resvd20[1016]; + } XOR; + struct { + __IO uint32_t CS; + __IO uint32_t PWR; + __IO uint32_t FBDIV_INT; + __IO uint32_t PRIM; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __I uint32_t INTS; + __I uint32_t resvd20[1016]; + } SET; + struct { + __IO uint32_t CS; + __IO uint32_t PWR; + __IO uint32_t FBDIV_INT; + __IO uint32_t PRIM; + __IO uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __I uint32_t INTS; + __I uint32_t resvd20[1016]; + } CLR; +} PLL_TypeDef; + +typedef struct { + __IO uint32_t CTRL; + __IO uint32_t DIV; + __I uint32_t SELECTED; +} CLOCKS_CLK_TypeDef; + +typedef struct { + __IO uint32_t CTRL; + __I uint32_t STATUS; +} CLOCKS_RESUS_TypeDef; + +typedef struct { + __IO uint32_t REF_KHZ; + __IO uint32_t MIN_KHZ; + __IO uint32_t MAX_KHZ; + __IO uint32_t DELAY; + __IO uint32_t INTERVAL; + __IO uint32_t SRC; + __I uint32_t STATUS; + __I uint32_t RESULT; +} CLOCKS_FC0_TypeDef; + +typedef struct { + CLOCKS_CLK_TypeDef CLK[10]; + __IO uint32_t DFTCLK_XOSC_CTRL; + __IO uint32_t DFTCLK_ROSC_CTRL; + __IO uint32_t DFTCLK_LPOSC_CTRL; + CLOCKS_RESUS_TypeDef RESUS; + CLOCKS_FC0_TypeDef FC0; + __IO uint32_t WAKE_EN0; + __IO uint32_t WAKE_EN1; + __IO uint32_t SLEEP_EN0; + __IO uint32_t SLEEP_EN1; + __I uint32_t ENABLED0; + __I uint32_t ENABLED1; + __I uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __I uint32_t INTS; + __I uint32_t resvdD4[971]; + struct { + CLOCKS_CLK_TypeDef CLK[10]; + __IO uint32_t DFTCLK_XOSC_CTRL; + __IO uint32_t DFTCLK_ROSC_CTRL; + __IO uint32_t DFTCLK_LPOSC_CTRL; + CLOCKS_RESUS_TypeDef RESUS; + CLOCKS_FC0_TypeDef FC0; + __IO uint32_t WAKE_EN0; + __IO uint32_t WAKE_EN1; + __IO uint32_t SLEEP_EN0; + __IO uint32_t SLEEP_EN1; + __I uint32_t ENABLED0; + __I uint32_t ENABLED1; + __I uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __I uint32_t INTS; + __I uint32_t resvdD4[971]; + } XOR; + struct { + CLOCKS_CLK_TypeDef CLK[10]; + __IO uint32_t DFTCLK_XOSC_CTRL; + __IO uint32_t DFTCLK_ROSC_CTRL; + __IO uint32_t DFTCLK_LPOSC_CTRL; + CLOCKS_RESUS_TypeDef RESUS; + CLOCKS_FC0_TypeDef FC0; + __IO uint32_t WAKE_EN0; + __IO uint32_t WAKE_EN1; + __IO uint32_t SLEEP_EN0; + __IO uint32_t SLEEP_EN1; + __I uint32_t ENABLED0; + __I uint32_t ENABLED1; + __I uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __I uint32_t INTS; + __I uint32_t resvdD4[971]; + } SET; + struct { + CLOCKS_CLK_TypeDef CLK[10]; + __IO uint32_t DFTCLK_XOSC_CTRL; + __IO uint32_t DFTCLK_ROSC_CTRL; + __IO uint32_t DFTCLK_LPOSC_CTRL; + CLOCKS_RESUS_TypeDef RESUS; + CLOCKS_FC0_TypeDef FC0; + __IO uint32_t WAKE_EN0; + __IO uint32_t WAKE_EN1; + __IO uint32_t SLEEP_EN0; + __IO uint32_t SLEEP_EN1; + __I uint32_t ENABLED0; + __I uint32_t ENABLED1; + __I uint32_t INTR; + __IO uint32_t INTE; + __IO uint32_t INTF; + __I uint32_t INTS; + __I uint32_t resvdD4[971]; + } CLR; +} CLOCKS_TypeDef; + +/** + * @brief QMI (QSPI Memory Interface) register block. + * @note Controls execute-in-place (XIP) flash access for RP2350. + */ +typedef struct { + __IO uint32_t DIRECT_CSR; + __IO uint32_t DIRECT_TX; + __I uint32_t DIRECT_RX; + __IO uint32_t M0_TIMING; + __IO uint32_t M0_RFMT; + __IO uint32_t M0_RCMD; + __IO uint32_t M0_WFMT; + __IO uint32_t M0_WCMD; + __IO uint32_t M1_TIMING; + __IO uint32_t M1_RFMT; + __IO uint32_t M1_RCMD; + __IO uint32_t M1_WFMT; + __IO uint32_t M1_WCMD; + __IO uint32_t ATRANS[8]; +} QMI_TypeDef; + +/** + * @brief XIP control register block. + * @note See RP2350 Datasheet 12.3.8 XIP. + */ +typedef struct { + __IO uint32_t CTRL; /* 0x00 */ + __I uint32_t resvd04; /* 0x04 */ + __I uint32_t STAT; /* 0x08 */ + __IO uint32_t CTR_HIT; /* 0x0C */ + __IO uint32_t CTR_ACC; /* 0x10 */ + __IO uint32_t STREAM_ADDR; /* 0x14 */ + __IO uint32_t STREAM_CTR; /* 0x18 */ + __I uint32_t STREAM_FIFO; /* 0x1C */ +} XIP_CTRL_TypeDef; +/** @} */ + +/** + * @name Base addresses + * @{ + */ +#define __APBPERIPH_BASE 0x40000000U +#define __AHBPERIPH_BASE 0x50000000U +#define __IOPORT_BASE 0xD0000000U + +#define __SYSINFO_BASE (__APBPERIPH_BASE + 0x00000000U) +#define __SYSCFG_BASE (__APBPERIPH_BASE + 0x00008000U) +#define __CLOCKS_BASE (__APBPERIPH_BASE + 0x00010000U) +#define __PSM_BASE (__APBPERIPH_BASE + 0x00018000U) +#define __RESETS_BASE (__APBPERIPH_BASE + 0x00020000U) +#define __IOUSER0_BASE (__APBPERIPH_BASE + 0x00028000U) +#define __IOQSPI_BASE (__APBPERIPH_BASE + 0x00030000U) +#define __PADSUSER0_BASE (__APBPERIPH_BASE + 0x00038000U) +#define __PADSQSPI_BASE (__APBPERIPH_BASE + 0x00040000U) +#define __XOSC_BASE (__APBPERIPH_BASE + 0x00048000U) +#define __PLL_SYS_BASE (__APBPERIPH_BASE + 0x00050000U) +#define __PLL_USB_BASE (__APBPERIPH_BASE + 0x00058000U) +#define __ACCESSCTRL_BASE (__APBPERIPH_BASE + 0x00060000U) +#define __BUSCTRL_BASE (__APBPERIPH_BASE + 0x00068000U) +#define __UART0_BASE (__APBPERIPH_BASE + 0x00070000U) +#define __UART1_BASE (__APBPERIPH_BASE + 0x00078000U) +#define __SPI0_BASE (__APBPERIPH_BASE + 0x00080000U) +#define __SPI1_BASE (__APBPERIPH_BASE + 0x00088000U) +#define __I2C0_BASE (__APBPERIPH_BASE + 0x00090000U) +#define __I2C1_BASE (__APBPERIPH_BASE + 0x00098000U) +#define __ADC_BASE (__APBPERIPH_BASE + 0x000A0000U) +#define __PWM_BASE (__APBPERIPH_BASE + 0x000A8000U) +#define __TIMER0_BASE (__APBPERIPH_BASE + 0x000B0000U) +#define __TIMER1_BASE (__APBPERIPH_BASE + 0x000B8000U) +#define __HSTX_CTRL_BASE (__APBPERIPH_BASE + 0x000C0000U) +#define __XIP_CTRL_BASE (__APBPERIPH_BASE + 0x000C8000U) +#define __QMI_BASE (__APBPERIPH_BASE + 0x000D0000U) +#define __WATCHDOG_BASE (__APBPERIPH_BASE + 0x000D8000U) +#define __BOOTRAM_BASE (__APBPERIPH_BASE + 0x000E0000U) +#define __ROSC_BASE (__APBPERIPH_BASE + 0x000E8000U) +#define __TRNG_BASE (__APBPERIPH_BASE + 0x000F0000U) +#define __SHA256_BASE (__APBPERIPH_BASE + 0x000F8000U) +#define __POWMAN_BASE (__APBPERIPH_BASE + 0x00100000U) +#define __TICKS_BASE (__APBPERIPH_BASE + 0x00108000U) +#define __OTP_BASE (__APBPERIPH_BASE + 0x00120000U) +#define __OTP_DATA_BASE (__APBPERIPH_BASE + 0x00130000U) +#define __OTP_DATA_RAW_BASE (__APBPERIPH_BASE + 0x00134000U) +#define __GLITCH_DETECTOR_BASE (__APBPERIPH_BASE + 0x00158000U) +#define __TBMAN_BASE (__APBPERIPH_BASE + 0x00160000U) + +#define __DMA_BASE (__AHBPERIPH_BASE + 0x00000000U) +#define __USB_DPRAM_BASE (__AHBPERIPH_BASE + 0x00100000U) +#define __USB_BASE (__AHBPERIPH_BASE + 0x00110000U) +#define __PIO0_BASE (__AHBPERIPH_BASE + 0x00200000U) +#define __PIO1_BASE (__AHBPERIPH_BASE + 0x00300000U) +#define __PIO2_BASE (__AHBPERIPH_BASE + 0x00400000U) +#define __XIP_AUX_BASE (__AHBPERIPH_BASE + 0x00500000U) +#define __HSTX_FIFO_BASE (__AHBPERIPH_BASE + 0x00600000U) +#define __CORESIGHT_TRACE_BASE (__AHBPERIPH_BASE + 0x00700000U) + +#define __SIO_BASE (__IOPORT_BASE + 0x00000000U) +/** @} */ + +/** + * @name Peripherals + * @{ + */ +#define DMA ((DMA_TypeDef *) __DMA_BASE) +#define IO_BANK0 ((IOUSER_TypeDef *) __IOUSER0_BASE) +#define IO_QSPI ((IOQSPI_TypeDef *) __IOQSPI_BASE) +#define PADS_BANK0 ((PADS_TypeDef *) __PADSUSER0_BASE) +#define PADS_QSPI ((PADS_QSPI_TypeDef *) __PADSQSPI_BASE) +#define PSM ((PSM_TypeDef *) __PSM_BASE) +#define RESETS ((RESETS_TypeDef *) __RESETS_BASE) +#define SIO ((SIO_TypeDef *) __SIO_BASE) +#define TIMER0 ((TIMER_TypeDef *) __TIMER0_BASE) +#define TIMER1 ((TIMER_TypeDef *) __TIMER1_BASE) +#define UART0 ((UART_TypeDef *) __UART0_BASE) +#define UART1 ((UART_TypeDef *) __UART1_BASE) +#define SPI0 ((SPI_TypeDef *) __SPI0_BASE) +#define SPI1 ((SPI_TypeDef *) __SPI1_BASE) +#define I2C0 ((I2C_TypeDef *) __I2C0_BASE) +#define I2C1 ((I2C_TypeDef *) __I2C1_BASE) +#define ADC ((ADC_TypeDef *) __ADC_BASE) +#define PWM ((PWM_TypeDef *) __PWM_BASE) +#define PIO0 ((PIO_TypeDef *) __PIO0_BASE) +#define PIO1 ((PIO_TypeDef *) __PIO1_BASE) +#define PIO2 ((PIO_TypeDef *) __PIO2_BASE) +#define USB ((USB_TypeDef *) __USB_BASE) +#define WATCHDOG ((WATCHDOG_TypeDef *) __WATCHDOG_BASE) +#define PLL_SYS ((PLL_TypeDef *) __PLL_SYS_BASE) +#define PLL_USB ((PLL_TypeDef *) __PLL_USB_BASE) +#define XOSC ((XOSC_TypeDef *) __XOSC_BASE) +#define CLOCKS ((CLOCKS_TypeDef *) __CLOCKS_BASE) +#define TICKS ((TICKS_TypeDef *) __TICKS_BASE) +#define XIP_CTRL ((XIP_CTRL_TypeDef *) __XIP_CTRL_BASE) +#define QMI ((QMI_TypeDef *) __QMI_BASE) +/** @} */ + +/** + * @name DMA bits definitions + * @note See RP2350 Datasheet 12.6.10 DMA List of Registers + * @{ + */ +#define DMA_CTRL_TRIG_AHB_ERROR (1U << 31) +#define DMA_CTRL_TRIG_READ_ERROR (1U << 30) +#define DMA_CTRL_TRIG_WRITE_ERROR (1U << 29) +#define DMA_CTRL_TRIG_BUSY (1U << 26) +#define DMA_CTRL_TRIG_SNIFF_EN (1U << 25) +#define DMA_CTRL_TRIG_BSWAP (1U << 24) +#define DMA_CTRL_TRIG_IRQ_QUIET (1U << 23) +#define DMA_CTRL_TRIG_TREQ_SEL_Pos 17U +#define DMA_CTRL_TRIG_TREQ_SEL_Msk (0x3FU << DMA_CTRL_TRIG_TREQ_SEL_Pos) +#define DMA_CTRL_TRIG_TREQ_SEL(n) ((n) << DMA_CTRL_TRIG_TREQ_SEL_Pos) +#define DMA_CTRL_TRIG_TREQ_PIO0_TX0 DMA_CTRL_TRIG_TREQ_SEL(0x00U) +#define DMA_CTRL_TRIG_TREQ_PIO0_TX1 DMA_CTRL_TRIG_TREQ_SEL(0x01U) +#define DMA_CTRL_TRIG_TREQ_PIO0_TX2 DMA_CTRL_TRIG_TREQ_SEL(0x02U) +#define DMA_CTRL_TRIG_TREQ_PIO0_TX3 DMA_CTRL_TRIG_TREQ_SEL(0x03U) +#define DMA_CTRL_TRIG_TREQ_PIO0_RX0 DMA_CTRL_TRIG_TREQ_SEL(0x04U) +#define DMA_CTRL_TRIG_TREQ_PIO0_RX1 DMA_CTRL_TRIG_TREQ_SEL(0x05U) +#define DMA_CTRL_TRIG_TREQ_PIO0_RX2 DMA_CTRL_TRIG_TREQ_SEL(0x06U) +#define DMA_CTRL_TRIG_TREQ_PIO0_RX3 DMA_CTRL_TRIG_TREQ_SEL(0x07U) +#define DMA_CTRL_TRIG_TREQ_PIO1_TX0 DMA_CTRL_TRIG_TREQ_SEL(0x08U) +#define DMA_CTRL_TRIG_TREQ_PIO1_TX1 DMA_CTRL_TRIG_TREQ_SEL(0x09U) +#define DMA_CTRL_TRIG_TREQ_PIO1_TX2 DMA_CTRL_TRIG_TREQ_SEL(0x0AU) +#define DMA_CTRL_TRIG_TREQ_PIO1_TX3 DMA_CTRL_TRIG_TREQ_SEL(0x0BU) +#define DMA_CTRL_TRIG_TREQ_PIO1_RX0 DMA_CTRL_TRIG_TREQ_SEL(0x0CU) +#define DMA_CTRL_TRIG_TREQ_PIO1_RX1 DMA_CTRL_TRIG_TREQ_SEL(0x0DU) +#define DMA_CTRL_TRIG_TREQ_PIO1_RX2 DMA_CTRL_TRIG_TREQ_SEL(0x0EU) +#define DMA_CTRL_TRIG_TREQ_PIO1_RX3 DMA_CTRL_TRIG_TREQ_SEL(0x0FU) +#define DMA_CTRL_TRIG_TREQ_PIO2_TX0 DMA_CTRL_TRIG_TREQ_SEL(0x10U) +#define DMA_CTRL_TRIG_TREQ_PIO2_TX1 DMA_CTRL_TRIG_TREQ_SEL(0x11U) +#define DMA_CTRL_TRIG_TREQ_PIO2_TX2 DMA_CTRL_TRIG_TREQ_SEL(0x12U) +#define DMA_CTRL_TRIG_TREQ_PIO2_TX3 DMA_CTRL_TRIG_TREQ_SEL(0x13U) +#define DMA_CTRL_TRIG_TREQ_PIO2_RX0 DMA_CTRL_TRIG_TREQ_SEL(0x14U) +#define DMA_CTRL_TRIG_TREQ_PIO2_RX1 DMA_CTRL_TRIG_TREQ_SEL(0x15U) +#define DMA_CTRL_TRIG_TREQ_PIO2_RX2 DMA_CTRL_TRIG_TREQ_SEL(0x16U) +#define DMA_CTRL_TRIG_TREQ_PIO2_RX3 DMA_CTRL_TRIG_TREQ_SEL(0x17U) +#define DMA_CTRL_TRIG_TREQ_SPI0_TX DMA_CTRL_TRIG_TREQ_SEL(0x18U) +#define DMA_CTRL_TRIG_TREQ_SPI0_RX DMA_CTRL_TRIG_TREQ_SEL(0x19U) +#define DMA_CTRL_TRIG_TREQ_SPI1_TX DMA_CTRL_TRIG_TREQ_SEL(0x1AU) +#define DMA_CTRL_TRIG_TREQ_SPI1_RX DMA_CTRL_TRIG_TREQ_SEL(0x1BU) +#define DMA_CTRL_TRIG_TREQ_UART0_TX DMA_CTRL_TRIG_TREQ_SEL(0x1CU) +#define DMA_CTRL_TRIG_TREQ_UART0_RX DMA_CTRL_TRIG_TREQ_SEL(0x1DU) +#define DMA_CTRL_TRIG_TREQ_UART1_TX DMA_CTRL_TRIG_TREQ_SEL(0x1EU) +#define DMA_CTRL_TRIG_TREQ_UART1_RX DMA_CTRL_TRIG_TREQ_SEL(0x1FU) +#define DMA_CTRL_TRIG_TREQ_PWM_WRAP0 DMA_CTRL_TRIG_TREQ_SEL(0x20U) +#define DMA_CTRL_TRIG_TREQ_PWM_WRAP1 DMA_CTRL_TRIG_TREQ_SEL(0x21U) +#define DMA_CTRL_TRIG_TREQ_PWM_WRAP2 DMA_CTRL_TRIG_TREQ_SEL(0x22U) +#define DMA_CTRL_TRIG_TREQ_PWM_WRAP3 DMA_CTRL_TRIG_TREQ_SEL(0x23U) +#define DMA_CTRL_TRIG_TREQ_PWM_WRAP4 DMA_CTRL_TRIG_TREQ_SEL(0x24U) +#define DMA_CTRL_TRIG_TREQ_PWM_WRAP5 DMA_CTRL_TRIG_TREQ_SEL(0x25U) +#define DMA_CTRL_TRIG_TREQ_PWM_WRAP6 DMA_CTRL_TRIG_TREQ_SEL(0x26U) +#define DMA_CTRL_TRIG_TREQ_PWM_WRAP7 DMA_CTRL_TRIG_TREQ_SEL(0x27U) +#define DMA_CTRL_TRIG_TREQ_PWM_WRAP8 DMA_CTRL_TRIG_TREQ_SEL(0x28U) +#define DMA_CTRL_TRIG_TREQ_PWM_WRAP9 DMA_CTRL_TRIG_TREQ_SEL(0x29U) +#define DMA_CTRL_TRIG_TREQ_PWM_WRAP10 DMA_CTRL_TRIG_TREQ_SEL(0x2AU) +#define DMA_CTRL_TRIG_TREQ_PWM_WRAP11 DMA_CTRL_TRIG_TREQ_SEL(0x2BU) +#define DMA_CTRL_TRIG_TREQ_I2C0_TX DMA_CTRL_TRIG_TREQ_SEL(0x2CU) +#define DMA_CTRL_TRIG_TREQ_I2C0_RX DMA_CTRL_TRIG_TREQ_SEL(0x2DU) +#define DMA_CTRL_TRIG_TREQ_I2C1_TX DMA_CTRL_TRIG_TREQ_SEL(0x2EU) +#define DMA_CTRL_TRIG_TREQ_I2C1_RX DMA_CTRL_TRIG_TREQ_SEL(0x2FU) +#define DMA_CTRL_TRIG_TREQ_ADC DMA_CTRL_TRIG_TREQ_SEL(0x30U) +#define DMA_CTRL_TRIG_TREQ_XIP_STREAM DMA_CTRL_TRIG_TREQ_SEL(0x31U) +#define DMA_CTRL_TRIG_TREQ_XIP_QMITX DMA_CTRL_TRIG_TREQ_SEL(0x32U) +#define DMA_CTRL_TRIG_TREQ_XIP_QMIRX DMA_CTRL_TRIG_TREQ_SEL(0x33U) +#define DMA_CTRL_TRIG_TREQ_HSTX DMA_CTRL_TRIG_TREQ_SEL(0x34U) +#define DMA_CTRL_TRIG_TREQ_CORESIGHT DMA_CTRL_TRIG_TREQ_SEL(0x35U) +#define DMA_CTRL_TRIG_TREQ_SHA256 DMA_CTRL_TRIG_TREQ_SEL(0x36U) +#define DMA_CTRL_TRIG_TREQ_TIMER0 DMA_CTRL_TRIG_TREQ_SEL(0x3BU) +#define DMA_CTRL_TRIG_TREQ_TIMER1 DMA_CTRL_TRIG_TREQ_SEL(0x3CU) +#define DMA_CTRL_TRIG_TREQ_TIMER2 DMA_CTRL_TRIG_TREQ_SEL(0x3DU) +#define DMA_CTRL_TRIG_TREQ_TIMER3 DMA_CTRL_TRIG_TREQ_SEL(0x3EU) +#define DMA_CTRL_TRIG_TREQ_PERMANENT DMA_CTRL_TRIG_TREQ_SEL(0x3FU) +#define DMA_CTRL_TRIG_CHAIN_TO_Pos 13U +#define DMA_CTRL_TRIG_CHAIN_TO_Msk (0xFU << DMA_CTRL_TRIG_CHAIN_TO_Pos) +#define DMA_CTRL_TRIG_CHAIN_TO(n) ((n) << DMA_CTRL_TRIG_CHAIN_TO_Pos) +#define DMA_CTRL_TRIG_RING_SEL (1U << 12) +#define DMA_CTRL_TRIG_RING_SIZE_Pos 8U +#define DMA_CTRL_TRIG_RING_SIZE_Msk (0xFU << DMA_CTRL_TRIG_RING_SIZE_Pos) +#define DMA_CTRL_TRIG_RING_SIZE(n) ((n) << DMA_CTRL_TRIG_RING_SIZE_Pos) +#define DMA_CTRL_TRIG_INCR_WRITE_REV (1U << 7) +#define DMA_CTRL_TRIG_INCR_WRITE (1U << 6) +#define DMA_CTRL_TRIG_INCR_READ_REV (1U << 5) +#define DMA_CTRL_TRIG_INCR_READ (1U << 4) +#define DMA_CTRL_TRIG_DATA_SIZE_Pos 2U +#define DMA_CTRL_TRIG_DATA_SIZE_Msk (3U << DMA_CTRL_TRIG_DATA_SIZE_Pos) +#define DMA_CTRL_TRIG_DATA_SIZE(n) ((n) << DMA_CTRL_TRIG_DATA_SIZE_Pos) +#define DMA_CTRL_TRIG_DATA_SIZE_BYTE DMA_CTRL_TRIG_DATA_SIZE(0U) +#define DMA_CTRL_TRIG_DATA_SIZE_HWORD DMA_CTRL_TRIG_DATA_SIZE(1U) +#define DMA_CTRL_TRIG_DATA_SIZE_WORD DMA_CTRL_TRIG_DATA_SIZE(2U) +#define DMA_CTRL_TRIG_HIGH_PRIORITY (1U << 1) +#define DMA_CTRL_TRIG_PRIORITY(n) ((n) << 1) +#define DMA_CTRL_TRIG_EN (1U << 0) +/** @} */ + +/** + * @name PSM bits definitions (dangerous) + * @note See RP2350 Datasheet 7.4.4 PSM List of Registers + * @{ + */ +#define PSM_ANY_PROC1 (1U << 24) +#define PSM_ANY_PROC0 (1U << 23) +#define PSM_ANY_ACCESSCTRL (1U << 22) +#define PSM_ANY_SIO (1U << 21) +#define PSM_ANY_XIP (1U << 20) +#define PSM_ANY_SRAM9 (1U << 19) +#define PSM_ANY_SRAM8 (1U << 18) +#define PSM_ANY_SRAM7 (1U << 17) +#define PSM_ANY_SRAM6 (1U << 16) +#define PSM_ANY_SRAM5 (1U << 15) +#define PSM_ANY_SRAM4 (1U << 14) +#define PSM_ANY_SRAM3 (1U << 13) +#define PSM_ANY_SRAM2 (1U << 12) +#define PSM_ANY_SRAM1 (1U << 11) +#define PSM_ANY_SRAM0 (1U << 10) +#define PSM_ANY_BOOTRAM (1U << 9) +#define PSM_ANY_ROM (1U << 8) +#define PSM_ANY_BUSFABRIC (1U << 7) +#define PSM_ANY_PSM_READY (1U << 6) +#define PSM_ANY_CLOCKS (1U << 5) +#define PSM_ANY_RESETS (1U << 4) +#define PSM_ANY_XOSC (1U << 3) +#define PSM_ANY_ROSC (1U << 2) +#define PSM_ANY_OTP (1U << 1) +#define PSM_ANY_PROC_COLD (1U << 0) +/** @} */ + +/** + * @name RESETS bits definitions + * @note See RP2350 Datasheet 7.5.3 Resets List of Registers + * @{ + */ +#define RESETS_ALLREG_USBCTRL (1U << 28) +#define RESETS_ALLREG_UART1 (1U << 27) +#define RESETS_ALLREG_UART0 (1U << 26) +#define RESETS_ALLREG_TRNG (1U << 25) +#define RESETS_ALLREG_TIMER1 (1U << 24) +#define RESETS_ALLREG_TIMER0 (1U << 23) +#define RESETS_ALLREG_TBMAN (1U << 22) +#define RESETS_ALLREG_SYSINFO (1U << 21) +#define RESETS_ALLREG_SYSCFG (1U << 20) +#define RESETS_ALLREG_SPI1 (1U << 19) +#define RESETS_ALLREG_SPI0 (1U << 18) +#define RESETS_ALLREG_SHA256 (1U << 17) +#define RESETS_ALLREG_PWM (1U << 16) +#define RESETS_ALLREG_PLL_USB (1U << 15) +#define RESETS_ALLREG_PLL_SYS (1U << 14) +#define RESETS_ALLREG_PIO2 (1U << 13) +#define RESETS_ALLREG_PIO1 (1U << 12) +#define RESETS_ALLREG_PIO0 (1U << 11) +#define RESETS_ALLREG_PADS_QSPI (1U << 10) +#define RESETS_ALLREG_PADS_BANK0 (1U << 9) +#define RESETS_ALLREG_JTAG (1U << 8) +#define RESETS_ALLREG_IO_QSPI (1U << 7) +#define RESETS_ALLREG_IO_BANK0 (1U << 6) +#define RESETS_ALLREG_I2C1 (1U << 5) +#define RESETS_ALLREG_I2C0 (1U << 4) +#define RESETS_ALLREG_HSTX (1U << 3) +#define RESETS_ALLREG_DMA (1U << 2) +#define RESETS_ALLREG_BUSCTRL (1U << 1) +#define RESETS_ALLREG_ADC (1U << 0) +/** @} */ + +/** + * @name SIO bits definitions + * @note See RP2350 Datasheet 3.1.11 SIO List of Registers + * @{ + */ +#define SIO_FIFO_ST_VLD_Pos 0U +#define SIO_FIFO_ST_VLD_Msk (1U << SIO_FIFO_ST_VLD_Pos) +#define SIO_FIFO_ST_VLD SIO_FIFO_ST_VLD_Msk +#define SIO_FIFO_ST_RDY_Pos 1U +#define SIO_FIFO_ST_RDY_Msk (1U << SIO_FIFO_ST_RDY_Pos) +#define SIO_FIFO_ST_RDY SIO_FIFO_ST_RDY_Msk +#define SIO_FIFO_ST_WOF_Pos 2U +#define SIO_FIFO_ST_WOF_Msk (1U << SIO_FIFO_ST_WOF_Pos) +#define SIO_FIFO_ST_WOF SIO_FIFO_ST_WOF_Msk +#define SIO_FIFO_ST_ROE_Pos 3U +#define SIO_FIFO_ST_ROE_Msk (1U << SIO_FIFO_ST_ROE_Pos) +#define SIO_FIFO_ST_ROE SIO_FIFO_ST_ROE_Msk +/** @} */ + +/** + * @name SPI bits definitions + * @note See RP2350 Datasheet 12.3.5 SPI List of Registers + * @{ + */ +#define SPI_SSPCR0_SCR_Pos 8U +#define SPI_SSPCR0_SCR_Msk (255U << SPI_SSPCR0_SCR_Pos) +#define SPI_SSPCR0_SCR(n) ((n) << SPI_SSPCR0_SCR_Pos) +#define SPI_SSPCR0_SPH_Pos 7U +#define SPI_SSPCR0_SPH_Msk (1U << SPI_SSPCR0_SPH_Pos) +#define SPI_SSPCR0_SPH SPI_SSPCR0_SPH_Msk +#define SPI_SSPCR0_SPO_Pos 6U +#define SPI_SSPCR0_SPO_Msk (1U << SPI_SSPCR0_SPO_Pos) +#define SPI_SSPCR0_SPO SPI_SSPCR0_SPO_Msk +#define SPI_SSPCR0_FRF_Pos 4U +#define SPI_SSPCR0_FRF_Msk (3U << SPI_SSPCR0_FRF_Pos) +#define SPI_SSPCR0_FRF(n) ((n) << SPI_SSPCR0_FRF_Pos) +#define SPI_SSPCR0_FRF_MOTOROLA SPI_SSPCR0_FRF(0U) +#define SPI_SSPCR0_FRF_TI SPI_SSPCR0_FRF(1U) +#define SPI_SSPCR0_FRF_NATIONAL SPI_SSPCR0_FRF(2U) +#define SPI_SSPCR0_DSS_Pos 0U +#define SPI_SSPCR0_DSS_Msk (15U << SPI_SSPCR0_DSS_Pos) +#define SPI_SSPCR0_DSS(n) ((n) << SPI_SSPCR0_DSS_Pos) +#define SPI_SSPCR0_DSS_4BIT SPI_SSPCR0_DSS(3U) +#define SPI_SSPCR0_DSS_5BIT SPI_SSPCR0_DSS(4U) +#define SPI_SSPCR0_DSS_6BIT SPI_SSPCR0_DSS(5U) +#define SPI_SSPCR0_DSS_7BIT SPI_SSPCR0_DSS(6U) +#define SPI_SSPCR0_DSS_8BIT SPI_SSPCR0_DSS(7U) +#define SPI_SSPCR0_DSS_9BIT SPI_SSPCR0_DSS(8U) +#define SPI_SSPCR0_DSS_10BIT SPI_SSPCR0_DSS(9U) +#define SPI_SSPCR0_DSS_11BIT SPI_SSPCR0_DSS(10U) +#define SPI_SSPCR0_DSS_12BIT SPI_SSPCR0_DSS(11U) +#define SPI_SSPCR0_DSS_13BIT SPI_SSPCR0_DSS(12U) +#define SPI_SSPCR0_DSS_14BIT SPI_SSPCR0_DSS(13U) +#define SPI_SSPCR0_DSS_15BIT SPI_SSPCR0_DSS(14U) +#define SPI_SSPCR0_DSS_16BIT SPI_SSPCR0_DSS(15U) + +#define SPI_SSPCR1_SOD_Pos 3U +#define SPI_SSPCR1_SOD_Msk (1U << SPI_SSPCR1_SOD_Pos) +#define SPI_SSPCR1_SOD SPI_SSPCR1_SOD_Msk +#define SPI_SSPCR1_MS_Pos 2U +#define SPI_SSPCR1_MS_Msk (1U << SPI_SSPCR1_MS_Pos) +#define SPI_SSPCR1_MS SPI_SSPCR1_MS_Msk +#define SPI_SSPCR1_SSE_Pos 1U +#define SPI_SSPCR1_SSE_Msk (1U << SPI_SSPCR1_SSE_Pos) +#define SPI_SSPCR1_SSE SPI_SSPCR1_SSE_Msk +#define SPI_SSPCR1_LBM_Pos 0U +#define SPI_SSPCR1_LBM_Msk (1U << SPI_SSPCR1_LBM_Pos) +#define SPI_SSPCR1_LBM SPI_SSPCR1_LBM_Msk + +#define SPI_SSPSR_BSY_Pos 4U +#define SPI_SSPSR_BSY_Msk (1U << SPI_SSPSR_BSY_Pos) +#define SPI_SSPSR_BSY SPI_SSPSR_BSY_Msk +#define SPI_SSPSR_RFF_Pos 3U +#define SPI_SSPSR_RFF_Msk (1U << SPI_SSPSR_RFF_Pos) +#define SPI_SSPSR_RFF SPI_SSPSR_RFF_Msk +#define SPI_SSPSR_RNE_Pos 2U +#define SPI_SSPSR_RNE_Msk (1U << SPI_SSPSR_RNE_Pos) +#define SPI_SSPSR_RNE SPI_SSPSR_RNE_Msk +#define SPI_SSPSR_TNF_Pos 1U +#define SPI_SSPSR_TNF_Msk (1U << SPI_SSPSR_TNF_Pos) +#define SPI_SSPSR_TNF SPI_SSPSR_TNF_Msk +#define SPI_SSPSR_TFE_Pos 0U +#define SPI_SSPSR_TFE_Msk (1U << SPI_SSPSR_TFE_Pos) +#define SPI_SSPSR_TFE SPI_SSPSR_TFE_Msk + +#define SPI_SSPCPSR_CPSDVSR_Pos 0U +#define SPI_SSPCPSR_CPSDVSR_Msk (255U << SPI_SSPCPSR_CPSDVSR_Pos) +#define SPI_SSPCPSR_CPSDVSR(n) ((n) << SPI_SSPCPSR_CPSDVSR_Pos) + +#define SPI_SSPIMSC_TXIM_Pos 3U +#define SPI_SSPIMSC_TXIM_Msk (1U << SPI_SSPIMSC_TXIM_Pos) +#define SPI_SSPIMSC_TXIM SPI_SSPIMSC_TXIM_Msk +#define SPI_SSPIMSC_RXIM_Pos 2U +#define SPI_SSPIMSC_RXIM_Msk (1U << SPI_SSPIMSC_RXIM_Pos) +#define SPI_SSPIMSC_RXIM SPI_SSPIMSC_RXIM_Msk +#define SPI_SSPIMSC_RTIM_Pos 1U +#define SPI_SSPIMSC_RTIM_Msk (1U << SPI_SSPIMSC_RTIM_Pos) +#define SPI_SSPIMSC_RTIM SPI_SSPIMSC_RTIM_Msk +#define SPI_SSPIMSC_RORIM_Pos 0U +#define SPI_SSPIMSC_RORIM_Msk (1U << SPI_SSPIMSC_RORIM_Pos) +#define SPI_SSPIMSC_RORIM SPI_SSPIMSC_RORIM_Msk + +#define SPI_SSPDMACR_TXDMAE_Pos 1U +#define SPI_SSPDMACR_TXDMAE_Msk (1U << SPI_SSPDMACR_TXDMAE_Pos) +#define SPI_SSPDMACR_TXDMAE SPI_SSPDMACR_TXDMAE_Msk +#define SPI_SSPDMACR_RXDMAE_Pos 0U +#define SPI_SSPDMACR_RXDMAE_Msk (1U << SPI_SSPDMACR_RXDMAE_Pos) +#define SPI_SSPDMACR_RXDMAE SPI_SSPDMACR_RXDMAE_Msk +/** @} */ + +/** + * @name TIMER bits definitions + * @note See RP2350 Datasheet 12.8.5 TIMER List of Registers + * @{ + */ +#define TIMER_ARMED_ALARM0_Pos 0U +#define TIMER_ARMED_ALARM0_Msk (1U << TIMER_ARMED_ALARM0_Pos) +#define TIMER_ARMED_ALARM0 TIMER_ARMED_ALARM0_Msk +#define TIMER_ARMED_ALARM1_Pos 1U +#define TIMER_ARMED_ALARM1_Msk (1U << TIMER_ARMED_ALARM1_Pos) +#define TIMER_ARMED_ALARM1 TIMER_ARMED_ALARM1_Msk +#define TIMER_ARMED_ALARM2_Pos 2U +#define TIMER_ARMED_ALARM2_Msk (1U << TIMER_ARMED_ALARM2_Pos) +#define TIMER_ARMED_ALARM2 TIMER_ARMED_ALARM2_Msk +#define TIMER_ARMED_ALARM3_Pos 3U +#define TIMER_ARMED_ALARM3_Msk (1U << TIMER_ARMED_ALARM3_Pos) +#define TIMER_ARMED_ALARM3 TIMER_ARMED_ALARM3_Msk + +#define TIMER_DBGPAUSE_DBG0_Pos 1U +#define TIMER_DBGPAUSE_DBG0_Msk (1U << TIMER_DBGPAUSE_DBG0_Pos) +#define TIMER_DBGPAUSE_DBG0 TIMER_DBGPAUSE_DBG0_Msk +#define TIMER_DBGPAUSE_DBG1_Pos 2U +#define TIMER_DBGPAUSE_DBG1_Msk (1U << TIMER_DBGPAUSE_DBG1_Pos) +#define TIMER_DBGPAUSE_DBG1 TIMER_DBGPAUSE_DBG1_Msk + +#define TIMER_INTR_ALARM0_Pos 0U +#define TIMER_INTR_ALARM0_Msk (1U << TIMER_INTR_ALARM0_Pos) +#define TIMER_INTR_ALARM0 TIMER_INTR_ALARM0_Msk +#define TIMER_INTR_ALARM1_Pos 1U +#define TIMER_INTR_ALARM1_Msk (1U << TIMER_INTR_ALARM1_Pos) +#define TIMER_INTR_ALARM1 TIMER_INTR_ALARM1_Msk +#define TIMER_INTR_ALARM2_Pos 2U +#define TIMER_INTR_ALARM2_Msk (1U << TIMER_INTR_ALARM2_Pos) +#define TIMER_INTR_ALARM2 TIMER_INTR_ALARM2_Msk +#define TIMER_INTR_ALARM3_Pos 3U +#define TIMER_INTR_ALARM3_Msk (1U << TIMER_INTR_ALARM3_Pos) +#define TIMER_INTR_ALARM3 TIMER_INTR_ALARM3_Msk + +#define TIMER_INTS_ALARM0_Pos 0U +#define TIMER_INTS_ALARM0_Msk (1U << TIMER_INTS_ALARM0_Pos) +#define TIMER_INTS_ALARM0 TIMER_INTS_ALARM0_Msk +#define TIMER_INTS_ALARM1_Pos 1U +#define TIMER_INTS_ALARM1_Msk (1U << TIMER_INTS_ALARM1_Pos) +#define TIMER_INTS_ALARM1 TIMER_INTS_ALARM1_Msk +#define TIMER_INTS_ALARM2_Pos 2U +#define TIMER_INTS_ALARM2_Msk (1U << TIMER_INTS_ALARM2_Pos) +#define TIMER_INTS_ALARM2 TIMER_INTS_ALARM2_Msk +#define TIMER_INTS_ALARM3_Pos 3U +#define TIMER_INTS_ALARM3_Msk (1U << TIMER_INTS_ALARM3_Pos) +#define TIMER_INTS_ALARM3 TIMER_INTS_ALARM3_Msk +/** @} */ + +/** + * @name UART bits definitions + * @note See RP2350 Datasheet 12.1.8 UART List of Registers + * @{ + */ +#define UART_UARTDR_OE_Pos 11U +#define UART_UARTDR_OE_Msk (1U << UART_UARTDR_OE_Pos) +#define UART_UARTDR_OE UART_UARTDR_OE_Msk +#define UART_UARTDR_BE_Pos 10U +#define UART_UARTDR_BE_Msk (1U << UART_UARTDR_BE_Pos) +#define UART_UARTDR_BE UART_UARTDR_BE_Msk +#define UART_UARTDR_PE_Pos 9U +#define UART_UARTDR_PE_Msk (1U << UART_UARTDR_PE_Pos) +#define UART_UARTDR_PE UART_UARTDR_PE_Msk +#define UART_UARTDR_FE_Pos 8U +#define UART_UARTDR_FE_Msk (1U << UART_UARTDR_FE_Pos) +#define UART_UARTDR_FE UART_UARTDR_FE_Msk + +#define UART_UARTRSR_OE_Pos 3U +#define UART_UARTRSR_OE_Msk (1U << UART_UARTRSR_OE_Pos) +#define UART_UARTRSR_OE UART_UARTRSR_OE_Msk +#define UART_UARTRSR_BE_Pos 2U +#define UART_UARTRSR_BE_Msk (1U << UART_UARTRSR_BE_Pos) +#define UART_UARTRSR_BE UART_UARTRSR_BE_Msk +#define UART_UARTRSR_PE_Pos 1U +#define UART_UARTRSR_PE_Msk (1U << UART_UARTRSR_PE_Pos) +#define UART_UARTRSR_PE UART_UARTRSR_PE_Msk +#define UART_UARTRSR_FE_Pos 0U +#define UART_UARTRSR_FE_Msk (1U << UART_UARTRSR_FE_Pos) +#define UART_UARTRSR_FE UART_UARTRSR_FE_Msk + +#define UART_UARTFR_RI_Pos 8U +#define UART_UARTFR_RI_Msk (1U << UART_UARTFR_RI_Pos) +#define UART_UARTFR_RI UART_UARTFR_RI_Msk +#define UART_UARTFR_TXFE_Pos 7U +#define UART_UARTFR_TXFE_Msk (1U << UART_UARTFR_TXFE_Pos) +#define UART_UARTFR_TXFE UART_UARTFR_TXFE_Msk +#define UART_UARTFR_RXFF_Pos 6U +#define UART_UARTFR_RXFF_Msk (1U << UART_UARTFR_RXFF_Pos) +#define UART_UARTFR_RXFF UART_UARTFR_RXFF_Msk +#define UART_UARTFR_TXFF_Pos 5U +#define UART_UARTFR_TXFF_Msk (1U << UART_UARTFR_TXFF_Pos) +#define UART_UARTFR_TXFF UART_UARTFR_TXFF_Msk +#define UART_UARTFR_RXFE_Pos 4U +#define UART_UARTFR_RXFE_Msk (1U << UART_UARTFR_RXFE_Pos) +#define UART_UARTFR_RXFE UART_UARTFR_RXFE_Msk +#define UART_UARTFR_BUSY_Pos 3U +#define UART_UARTFR_BUSY_Msk (1U << UART_UARTFR_BUSY_Pos) +#define UART_UARTFR_BUSY UART_UARTFR_BUSY_Msk +#define UART_UARTFR_DCD_Pos 2U +#define UART_UARTFR_DCD_Msk (1U << UART_UARTFR_DCD_Pos) +#define UART_UARTFR_DCD UART_UARTFR_DCD_Msk +#define UART_UARTFR_DSR_Pos 1U +#define UART_UARTFR_DSR_Msk (1U << UART_UARTFR_DSR_Pos) +#define UART_UARTFR_DSR UART_UARTFR_DSR_Msk +#define UART_UARTFR_CTS_Pos 0U +#define UART_UARTFR_CTS_Msk (1U << UART_UARTFR_CTS_Pos) +#define UART_UARTFR_CTS UART_UARTFR_CTS_Msk + +#define UART_UARTILPR_ILPDVSR_Pos 0U +#define UART_UARTILPR_ILPDVSR_Msk (255U << UART_UARTILPR_ILPDVSR_Pos) +#define UART_UARTILPR_ILPDVSR(n) ((n) << UART_UARTILPR_ILPDVSR_Pos) + +#define UART_UARTIBRD_BAUD_DIVINT_Pos 0U +#define UART_UARTIBRD_BAUD_DIVINT_Msk (0xFFFFU << UART_UARTIBRD_BAUD_DIVINT_Pos) +#define UART_UARTIBRD_BAUD_DIVINT(n) ((n) << UART_UARTIBRD_BAUD_DIVINT_Pos) + +#define UART_UARTFBRD_BAUD_DIVFRAC_Pos 0U +#define UART_UARTFBRD_BAUD_DIVFRAC_Msk (63U << UART_UARTFBRD_BAUD_DIVFRAC_Pos) +#define UART_UARTFBRD_BAUD_DIVFRAC(n) ((n) << UART_UARTFBRD_BAUD_DIVFRAC_Pos) + +#define UART_UARTLCR_H_SPS_Pos 7U +#define UART_UARTLCR_H_SPS_Msk (1U << UART_UARTLCR_H_SPS_Pos) +#define UART_UARTLCR_H_SPS UART_UARTLCR_H_SPS_Msk +#define UART_UARTLCR_H_WLEN_Pos 5U +#define UART_UARTLCR_H_WLEN_Msk (3U << UART_UARTLCR_H_WLEN_Pos) +#define UART_UARTLCR_H_WLEN(n) ((n) << UART_UARTLCR_H_WLEN_Pos) +#define UART_UARTLCR_H_WLEN_5BITS UART_UARTLCR_H_WLEN(0U) +#define UART_UARTLCR_H_WLEN_6BITS UART_UARTLCR_H_WLEN(1U) +#define UART_UARTLCR_H_WLEN_7BITS UART_UARTLCR_H_WLEN(2U) +#define UART_UARTLCR_H_WLEN_8BITS UART_UARTLCR_H_WLEN(3U) +#define UART_UARTLCR_H_FEN_Pos 4U +#define UART_UARTLCR_H_FEN_Msk (1U << UART_UARTLCR_H_FEN_Pos) +#define UART_UARTLCR_H_FEN UART_UARTLCR_H_FEN_Msk +#define UART_UARTLCR_H_STP2_Pos 3U +#define UART_UARTLCR_H_STP2_Msk (1U << UART_UARTLCR_H_STP2_Pos) +#define UART_UARTLCR_H_STP2 UART_UARTLCR_H_STP2_Msk +#define UART_UARTLCR_H_EPS_Pos 2U +#define UART_UARTLCR_H_EPS_Msk (1U << UART_UARTLCR_H_EPS_Pos) +#define UART_UARTLCR_H_EPS UART_UARTLCR_H_EPS_Msk +#define UART_UARTLCR_H_PEN_Pos 1U +#define UART_UARTLCR_H_PEN_Msk (1U << UART_UARTLCR_H_PEN_Pos) +#define UART_UARTLCR_H_PEN UART_UARTLCR_H_PEN_Msk +#define UART_UARTLCR_H_BRK_Pos 0U +#define UART_UARTLCR_H_BRK_Msk (1U << UART_UARTLCR_H_BRK_Pos) +#define UART_UARTLCR_H_BRK UART_UARTLCR_H_BRK_Msk + +#define UART_UARTCR_CTSEN_Pos 15U +#define UART_UARTCR_CTSEN_Msk (1U << UART_UARTCR_CTSEN_Pos) +#define UART_UARTCR_CTSEN UART_UARTCR_CTSEN_Msk +#define UART_UARTCR_RTSEN_Pos 14U +#define UART_UARTCR_RTSEN_Msk (1U << UART_UARTCR_RTSEN_Pos) +#define UART_UARTCR_RTSEN UART_UARTCR_RTSEN_Msk +#define UART_UARTCR_OUT2_Pos 13U +#define UART_UARTCR_OUT2_Msk (1U << UART_UARTCR_OUT2_Pos) +#define UART_UARTCR_OUT2 UART_UARTCR_OUT2_Msk +#define UART_UARTCR_OUT1_Pos 12U +#define UART_UARTCR_OUT1_Msk (1U << UART_UARTCR_OUT1_Pos) +#define UART_UARTCR_OUT1 UART_UARTCR_OUT1_Msk +#define UART_UARTCR_RTS_Pos 11U +#define UART_UARTCR_RTS_Msk (1U << UART_UARTCR_RTS_Pos) +#define UART_UARTCR_RTS UART_UARTCR_RTS_Msk +#define UART_UARTCR_DTR_Pos 10U +#define UART_UARTCR_DTR_Msk (1U << UART_UARTCR_DTR_Pos) +#define UART_UARTCR_DTR UART_UARTCR_DTR_Msk +#define UART_UARTCR_RXE_Pos 9U +#define UART_UARTCR_RXE_Msk (1U << UART_UARTCR_RXE_Pos) +#define UART_UARTCR_RXE UART_UARTCR_RXE_Msk +#define UART_UARTCR_TXE_Pos 8U +#define UART_UARTCR_TXE_Msk (1U << UART_UARTCR_TXE_Pos) +#define UART_UARTCR_TXE UART_UARTCR_TXE_Msk +#define UART_UARTCR_LBE_Pos 7U +#define UART_UARTCR_LBE_Msk (1U << UART_UARTCR_LBE_Pos) +#define UART_UARTCR_LBE UART_UARTCR_LBE_Msk +#define UART_UARTCR_SIRLP_Pos 2U +#define UART_UARTCR_SIRLP_Msk (1U << UART_UARTCR_SIRLP_Pos) +#define UART_UARTCR_SIRLP UART_UARTCR_SIRLP_Msk +#define UART_UARTCR_SIREN_Pos 1U +#define UART_UARTCR_SIREN_Msk (1U << UART_UARTCR_SIREN_Pos) +#define UART_UARTCR_SIREN UART_UARTCR_SIREN_Msk +#define UART_UARTCR_UARTEN_Pos 0U +#define UART_UARTCR_UARTEN_Msk (1U << UART_UARTCR_UARTEN_Pos) +#define UART_UARTCR_UARTEN UART_UARTCR_UARTEN_Msk + +#define UART_UARTIFLS_RXIFLSEL_Pos 3U +#define UART_UARTIFLS_RXIFLSEL_Msk (7U << UART_UARTIFLS_RXIFLSEL_Pos) +#define UART_UARTIFLS_RXIFLSEL(n) ((n) << UART_UARTIFLS_RXIFLSEL_Pos) +#define UART_UARTIFLS_RXIFLSEL_1_8F UART_UARTIFLS_RXIFLSEL(0U) +#define UART_UARTIFLS_RXIFLSEL_1_4F UART_UARTIFLS_RXIFLSEL(1U) +#define UART_UARTIFLS_RXIFLSEL_1_2F UART_UARTIFLS_RXIFLSEL(2U) +#define UART_UARTIFLS_RXIFLSEL_3_4F UART_UARTIFLS_RXIFLSEL(3U) +#define UART_UARTIFLS_RXIFLSEL_7_8F UART_UARTIFLS_RXIFLSEL(4U) + +#define UART_UARTIFLS_TXIFLSEL_Pos 0U +#define UART_UARTIFLS_TXIFLSEL_Msk (7U << UART_UARTIFLS_TXIFLSEL_Pos) +#define UART_UARTIFLS_TXIFLSEL(n) ((n) << UART_UARTIFLS_TXIFLSEL_Pos) +#define UART_UARTIFLS_TXIFLSEL_1_8E UART_UARTIFLS_TXIFLSEL(0U) +#define UART_UARTIFLS_TXIFLSEL_1_4E UART_UARTIFLS_TXIFLSEL(1U) +#define UART_UARTIFLS_TXIFLSEL_1_2E UART_UARTIFLS_TXIFLSEL(2U) +#define UART_UARTIFLS_TXIFLSEL_3_4E UART_UARTIFLS_TXIFLSEL(3U) +#define UART_UARTIFLS_TXIFLSEL_7_8E UART_UARTIFLS_TXIFLSEL(4U) + +#define UART_UARTIMSC_OEIM_Pos 10U +#define UART_UARTIMSC_OEIM_Msk (1U << UART_UARTIMSC_OEIM_Pos) +#define UART_UARTIMSC_OEIM UART_UARTIMSC_OEIM_Msk +#define UART_UARTIMSC_BEIM_Pos 9U +#define UART_UARTIMSC_BEIM_Msk (1U << UART_UARTIMSC_BEIM_Pos) +#define UART_UARTIMSC_BEIM UART_UARTIMSC_BEIM_Msk +#define UART_UARTIMSC_PEIM_Pos 8U +#define UART_UARTIMSC_PEIM_Msk (1U << UART_UARTIMSC_PEIM_Pos) +#define UART_UARTIMSC_PEIM UART_UARTIMSC_PEIM_Msk +#define UART_UARTIMSC_FEIM_Pos 7U +#define UART_UARTIMSC_FEIM_Msk (1U << UART_UARTIMSC_FEIM_Pos) +#define UART_UARTIMSC_FEIM UART_UARTIMSC_FEIM_Msk +#define UART_UARTIMSC_RTIM_Pos 6U +#define UART_UARTIMSC_RTIM_Msk (1U << UART_UARTIMSC_RTIM_Pos) +#define UART_UARTIMSC_RTIM UART_UARTIMSC_RTIM_Msk +#define UART_UARTIMSC_TXIM_Pos 5U +#define UART_UARTIMSC_TXIM_Msk (1U << UART_UARTIMSC_TXIM_Pos) +#define UART_UARTIMSC_TXIM UART_UARTIMSC_TXIM_Msk +#define UART_UARTIMSC_RXIM_Pos 4U +#define UART_UARTIMSC_RXIM_Msk (1U << UART_UARTIMSC_RXIM_Pos) +#define UART_UARTIMSC_RXIM UART_UARTIMSC_RXIM_Msk +#define UART_UARTIMSC_DSRMIM_Pos 3U +#define UART_UARTIMSC_DSRMIM_Msk (1U << UART_UARTIMSC_DSRMIM_Pos) +#define UART_UARTIMSC_DSRMIM UART_UARTIMSC_DSRMIM_Msk +#define UART_UARTIMSC_DCDMIM_Pos 2U +#define UART_UARTIMSC_DCDMIM_Msk (1U << UART_UARTIMSC_DCDMIM_Pos) +#define UART_UARTIMSC_DCDMIM UART_UARTIMSC_DCDMIM_Msk +#define UART_UARTIMSC_CTSMIM_Pos 1U +#define UART_UARTIMSC_CTSMIM_Msk (1U << UART_UARTIMSC_CTSMIM_Pos) +#define UART_UARTIMSC_CTSMIM UART_UARTIMSC_CTSMIM_Msk +#define UART_UARTIMSC_RIMIM_Pos 0U +#define UART_UARTIMSC_RIMIM_Msk (1U << UART_UARTIMSC_RIMIM_Pos) +#define UART_UARTIMSC_RIMIM UART_UARTIMSC_RIMIM_Msk + +#define UART_UARTRIS_OERIS_Pos 10U +#define UART_UARTRIS_OERIS_Msk (1U << UART_UARTRIS_OERIS_Pos) +#define UART_UARTRIS_OERIS UART_UARTRIS_OERIS_Msk +#define UART_UARTRIS_BERIS_Pos 9U +#define UART_UARTRIS_BERIS_Msk (1U << UART_UARTRIS_BERIS_Pos) +#define UART_UARTRIS_BERIS UART_UARTRIS_BERIS_Msk +#define UART_UARTRIS_PERIS_Pos 8U +#define UART_UARTRIS_PERIS_Msk (1U << UART_UARTRIS_PERIS_Pos) +#define UART_UARTRIS_PERIS UART_UARTRIS_PERIS_Msk +#define UART_UARTRIS_FERIS_Pos 7U +#define UART_UARTRIS_FERIS_Msk (1U << UART_UARTRIS_FERIS_Pos) +#define UART_UARTRIS_FERIS UART_UARTRIS_FERIS_Msk +#define UART_UARTRIS_RTRIS_Pos 6U +#define UART_UARTRIS_RTRIS_Msk (1U << UART_UARTRIS_RTRIS_Pos) +#define UART_UARTRIS_RTRIS UART_UARTRIS_RTRIS_Msk +#define UART_UARTRIS_TXRIS_Pos 5U +#define UART_UARTRIS_TXRIS_Msk (1U << UART_UARTRIS_TXRIS_Pos) +#define UART_UARTRIS_TXRIS UART_UARTRIS_TXRIS_Msk +#define UART_UARTRIS_RXRIS_Pos 4U +#define UART_UARTRIS_RXRIS_Msk (1U << UART_UARTRIS_RXRIS_Pos) +#define UART_UARTRIS_RXRIS UART_UARTRIS_RXRIS_Msk +#define UART_UARTRIS_DSRRMIS_Pos 3U +#define UART_UARTRIS_DSRRMIS_Msk (1U << UART_UARTRIS_DSRRMIS_Pos) +#define UART_UARTRIS_DSRRMIS UART_UARTRIS_DSRRMIS_Msk +#define UART_UARTRIS_DCDRMIS_Pos 2U +#define UART_UARTRIS_DCDRMIS_Msk (1U << UART_UARTRIS_DCDRMIS_Pos) +#define UART_UARTRIS_DCDRMIS UART_UARTRIS_DCDRMIS_Msk +#define UART_UARTRIS_CTSRMIS_Pos 1U +#define UART_UARTRIS_CTSRMIS_Msk (1U << UART_UARTRIS_CTSRMIS_Pos) +#define UART_UARTRIS_CTSRMIS UART_UARTRIS_CTSRMIS_Msk +#define UART_UARTRIS_RIRMIS_Pos 0U +#define UART_UARTRIS_RIRMIS_Msk (1U << UART_UARTRIS_RIRMIS_Pos) +#define UART_UARTRIS_RIRMIS UART_UARTRIS_RIRMIS_Msk + +#define UART_UARTMIS_OEMIS_Pos 10U +#define UART_UARTMIS_OEMIS_Msk (1U << UART_UARTMIS_OEMIS_Pos) +#define UART_UARTMIS_OEMIS UART_UARTMIS_OEMIS_Msk +#define UART_UARTMIS_BEMIS_Pos 9U +#define UART_UARTMIS_BEMIS_Msk (1U << UART_UARTMIS_BEMIS_Pos) +#define UART_UARTMIS_BEMIS UART_UARTMIS_BEMIS_Msk +#define UART_UARTMIS_PEMIS_Pos 8U +#define UART_UARTMIS_PEMIS_Msk (1U << UART_UARTMIS_PEMIS_Pos) +#define UART_UARTMIS_PEMIS UART_UARTMIS_PEMIS_Msk +#define UART_UARTMIS_FEMIS_Pos 7U +#define UART_UARTMIS_FEMIS_Msk (1U << UART_UARTMIS_FEMIS_Pos) +#define UART_UARTMIS_FEMIS UART_UARTMIS_FEMIS_Msk +#define UART_UARTMIS_RTMIS_Pos 6U +#define UART_UARTMIS_RTMIS_Msk (1U << UART_UARTMIS_RTMIS_Pos) +#define UART_UARTMIS_RTMIS UART_UARTMIS_RTMIS_Msk +#define UART_UARTMIS_TXMIS_Pos 5U +#define UART_UARTMIS_TXMIS_Msk (1U << UART_UARTMIS_TXMIS_Pos) +#define UART_UARTMIS_TXMIS UART_UARTMIS_TXMIS_Msk +#define UART_UARTMIS_RXMIS_Pos 4U +#define UART_UARTMIS_RXMIS_Msk (1U << UART_UARTMIS_RXMIS_Pos) +#define UART_UARTMIS_RXMIS UART_UARTMIS_RXMIS_Msk +#define UART_UARTMIS_DSRMMIS_Pos 3U +#define UART_UARTMIS_DSRMMIS_Msk (1U << UART_UARTMIS_DSRMMIS_Pos) +#define UART_UARTMIS_DSRRMIS UART_UARTMIS_DSRMMIS_Msk +#define UART_UARTMIS_DCDMMIS_Pos 2U +#define UART_UARTMIS_DCDMMIS_Msk (1U << UART_UARTMIS_DCDMMIS_Pos) +#define UART_UARTMIS_DCDMMIS UART_UARTMIS_DCDMMIS_Msk +#define UART_UARTMIS_CTSMMIS_Pos 1U +#define UART_UARTMIS_CTSMMIS_Msk (1U << UART_UARTMIS_CTSMMIS_Pos) +#define UART_UARTMIS_CTSMMIS UART_UARTMIS_CTSMMIS_Msk +#define UART_UARTMIS_RIMMIS_Pos 0U +#define UART_UARTMIS_RIMMIS_Msk (1U << UART_UARTMIS_RIMMIS_Pos) +#define UART_UARTMIS_RIMMIS UART_UARTMIS_RIMMIS_Msk + +#define UART_UARTICR_OEIC_Pos 10U +#define UART_UARTICR_OEIC_Msk (1U << UART_UARTICR_OEIC_Pos) +#define UART_UARTICR_OEIC UART_UARTICR_OEIC_Msk +#define UART_UARTICR_BEIC_Pos 9U +#define UART_UARTICR_BEIC_Msk (1U << UART_UARTICR_BEIC_Pos) +#define UART_UARTICR_BEIC UART_UARTICR_BEIC_Msk +#define UART_UARTICR_PEIC_Pos 8U +#define UART_UARTICR_PEIC_Msk (1U << UART_UARTICR_PEIC_Pos) +#define UART_UARTICR_PEIC UART_UARTICR_PEIC_Msk +#define UART_UARTICR_FEIC_Pos 7U +#define UART_UARTICR_FEIC_Msk (1U << UART_UARTICR_FEIC_Pos) +#define UART_UARTICR_FEIC UART_UARTICR_FEIC_Msk +#define UART_UARTICR_RTIC_Pos 6U +#define UART_UARTICR_RTIC_Msk (1U << UART_UARTICR_RTIC_Pos) +#define UART_UARTICR_RTIC UART_UARTICR_RTIC_Msk +#define UART_UARTICR_TXIC_Pos 5U +#define UART_UARTICR_TXIC_Msk (1U << UART_UARTICR_TXIC_Pos) +#define UART_UARTICR_TXIC UART_UARTICR_TXIC_Msk +#define UART_UARTICR_RXIC_Pos 4U +#define UART_UARTICR_RXIC_Msk (1U << UART_UARTICR_RXIC_Pos) +#define UART_UARTICR_RXIC UART_UARTICR_RXIC_Msk +#define UART_UARTICR_DSRMIC_Pos 3U +#define UART_UARTICR_DSRMIC_Msk (1U << UART_UARTICR_DSRMIC_Pos) +#define UART_UARTICR_DSRMIC UART_UARTICR_DSRMIC_Msk +#define UART_UARTICR_DCDMIC_Pos 2U +#define UART_UARTICR_DCDMIC_Msk (1U << UART_UARTICR_DCDMIC_Pos) +#define UART_UARTICR_DCDMIC UART_UARTICR_DCDMIC_Msk +#define UART_UARTICR_CTSMIC_Pos 1U +#define UART_UARTICR_CTSMIC_Msk (1U << UART_UARTICR_CTSMIC_Pos) +#define UART_UARTICR_CTSMIC UART_UARTICR_CTSMIC_Msk +#define UART_UARTICR_RIMIC_Pos 0U +#define UART_UARTICR_RIMIC_Msk (1U << UART_UARTICR_RIMIC_Pos) +#define UART_UARTICR_RIMIC UART_UARTICR_RIMIC_Msk + +#define UART_UARTDMACR_DMAONERR_Pos 2U +#define UART_UARTDMACR_DMAONERR_Msk (1U << UART_UARTDMACR_DMAONERR_Pos) +#define UART_UARTDMACR_DMAONERR UART_UARTDMACR_DMAONERR_Msk +#define UART_UARTDMACR_TXDMAE_Pos 1U +#define UART_UARTDMACR_TXDMAE_Msk (1U << UART_UARTDMACR_TXDMAE_Pos) +#define UART_UARTDMACR_TXDMAE UART_UARTDMACR_TXDMAE_Msk +#define UART_UARTDMACR_RXDMAE_Pos 0U +#define UART_UARTDMACR_RXDMAE_Msk (1U << UART_UARTDMACR_RXDMAE_Pos) +#define UART_UARTDMACR_RXDMAE UART_UARTDMACR_RXDMAE_Msk +/** @} */ + +/** + * @name PADS QSPI control bits definitions + * @note See RP2350 Datasheet 9.11.4 PADS_QSPI List of Registers. + * @{ + */ +#define PADS_QSPI_SLEWFAST (1U << 0) +#define PADS_QSPI_SCHMITT (1U << 1) +#define PADS_QSPI_PDE (1U << 2) +#define PADS_QSPI_PUE (1U << 3) +#define PADS_QSPI_DRIVE_Pos 4U +#define PADS_QSPI_DRIVE_Msk (0x3U << PADS_QSPI_DRIVE_Pos) +#define PADS_QSPI_DRIVE(n) ((n) << PADS_QSPI_DRIVE_Pos) +#define PADS_QSPI_IE (1U << 6) +#define PADS_QSPI_OD (1U << 7) +/** @} */ + +/** + * @name QMI M0_TIMING / M1_TIMING bits definitions + * @note See RP2350 Datasheet 12.14.6 QMI List of Registers + * @{ + */ +#define QMI_TIMING_CLKDIV_Pos 0U +#define QMI_TIMING_CLKDIV_Msk (0xFFU << QMI_TIMING_CLKDIV_Pos) +#define QMI_TIMING_CLKDIV(n) ((n) << QMI_TIMING_CLKDIV_Pos) +#define QMI_TIMING_RXDELAY_Pos 8U +#define QMI_TIMING_RXDELAY_Msk (0x7U << QMI_TIMING_RXDELAY_Pos) +#define QMI_TIMING_RXDELAY(n) ((n) << QMI_TIMING_RXDELAY_Pos) +#define QMI_TIMING_MIN_DESELECT_Pos 12U +#define QMI_TIMING_MIN_DESELECT_Msk (0x1FU << QMI_TIMING_MIN_DESELECT_Pos) +#define QMI_TIMING_MIN_DESELECT(n) ((n) << QMI_TIMING_MIN_DESELECT_Pos) +#define QMI_TIMING_MAX_SELECT_Pos 17U +#define QMI_TIMING_MAX_SELECT_Msk (0x3FU << QMI_TIMING_MAX_SELECT_Pos) +#define QMI_TIMING_MAX_SELECT(n) ((n) << QMI_TIMING_MAX_SELECT_Pos) +#define QMI_TIMING_SELECT_HOLD_Pos 23U +#define QMI_TIMING_SELECT_HOLD_Msk (0x3U << QMI_TIMING_SELECT_HOLD_Pos) +#define QMI_TIMING_SELECT_HOLD(n) ((n) << QMI_TIMING_SELECT_HOLD_Pos) +#define QMI_TIMING_SELECT_SETUP (1U << 25) +#define QMI_TIMING_PAGEBREAK_Pos 28U +#define QMI_TIMING_PAGEBREAK_Msk (0x3U << QMI_TIMING_PAGEBREAK_Pos) +#define QMI_TIMING_PAGEBREAK(n) ((n) << QMI_TIMING_PAGEBREAK_Pos) +#define QMI_TIMING_COOLDOWN_Pos 30U +#define QMI_TIMING_COOLDOWN_Msk (0x3U << QMI_TIMING_COOLDOWN_Pos) +#define QMI_TIMING_COOLDOWN(n) ((n) << QMI_TIMING_COOLDOWN_Pos) + +/** PAGEBREAK encoded values. */ +#define QMI_TIMING_PAGEBREAK_NONE 0U +#define QMI_TIMING_PAGEBREAK_256 1U +#define QMI_TIMING_PAGEBREAK_1024 2U +#define QMI_TIMING_PAGEBREAK_4096 3U +/** @} */ + +/** + * @name QMI DIRECT_CSR bits definitions + * @{ + */ +#define QMI_DIRECT_CSR_EN (1U << 0) +#define QMI_DIRECT_CSR_BUSY (1U << 1) +#define QMI_DIRECT_CSR_ASSERT_CS0N (1U << 2) +#define QMI_DIRECT_CSR_ASSERT_CS1N (1U << 3) +#define QMI_DIRECT_CSR_AUTO_CS0N (1U << 6) +#define QMI_DIRECT_CSR_AUTO_CS1N (1U << 7) +#define QMI_DIRECT_CSR_RXDELAY_Pos 30U +#define QMI_DIRECT_CSR_RXDELAY_Msk (0x3U << QMI_DIRECT_CSR_RXDELAY_Pos) +#define QMI_DIRECT_CSR_RXDELAY(n) ((n) << QMI_DIRECT_CSR_RXDELAY_Pos) +#define QMI_DIRECT_CSR_TXFULL (1U << 10) +#define QMI_DIRECT_CSR_TXEMPTY (1U << 11) +#define QMI_DIRECT_CSR_TXLEVEL_Pos 12U +#define QMI_DIRECT_CSR_TXLEVEL_Msk (0x7U << QMI_DIRECT_CSR_TXLEVEL_Pos) +#define QMI_DIRECT_CSR_RXEMPTY (1U << 16) +#define QMI_DIRECT_CSR_RXFULL (1U << 17) +#define QMI_DIRECT_CSR_RXLEVEL_Pos 18U +#define QMI_DIRECT_CSR_RXLEVEL_Msk (0x7U << QMI_DIRECT_CSR_RXLEVEL_Pos) +#define QMI_DIRECT_CSR_CLKDIV_Pos 22U +#define QMI_DIRECT_CSR_CLKDIV_Msk (0xFFU << QMI_DIRECT_CSR_CLKDIV_Pos) +#define QMI_DIRECT_CSR_CLKDIV(n) ((n) << QMI_DIRECT_CSR_CLKDIV_Pos) +/** @} */ + +/** + * @name QMI DIRECT_TX bits definitions + * @{ + */ +#define QMI_DIRECT_TX_DATA_Msk 0x0000FFFFU +#define QMI_DIRECT_TX_IWIDTH_Pos 16U +#define QMI_DIRECT_TX_IWIDTH_Msk (0x3U << QMI_DIRECT_TX_IWIDTH_Pos) +#define QMI_DIRECT_TX_IWIDTH(n) ((n) << QMI_DIRECT_TX_IWIDTH_Pos) +#define QMI_DIRECT_TX_DWIDTH (1U << 18) +#define QMI_DIRECT_TX_OE (1U << 19) +#define QMI_DIRECT_TX_NOPUSH (1U << 20) + +/** IWIDTH encoded values. */ +#define QMI_DIRECT_TX_IWIDTH_S 0U +#define QMI_DIRECT_TX_IWIDTH_D 1U +#define QMI_DIRECT_TX_IWIDTH_Q 2U +/** @} */ + + +/** + * @name TICKS peripheral indexes + * @note See RP2350 Datasheet 8.5.2 TICKS List of Registers + * @{ + */ +#define TICKS_PROC0 0U +#define TICKS_PROC1 1U +#define TICKS_TIMER0 2U +#define TICKS_TIMER1 3U +#define TICKS_WATCHDOG 4U +#define TICKS_RISCV 5U +/** @} */ + +/** + * @name TICKS peripheral bits definitions + * @{ + */ +#define TICKS_CTRL_ENABLE (1U << 0) +#define TICKS_CTRL_RUNNING (1U << 1) +#define TICKS_DIV(n) ((n) << 0) +/** @} */ + +/** + * @name WATCHDOG bits definitions + * @note See RP2350 Datasheet 12.9.7 Watchdog List of Registers + * @{ + */ +#define WATCHDOG_CTRL_TRIGGER_Pos 31U +#define WATCHDOG_CTRL_TRIGGER_Msk (1U << WATCHDOG_CTRL_TRIGGER_Pos) +#define WATCHDOG_CTRL_TRIGGER WATCHDOG_CTRL_TRIGGER_Msk +#define WATCHDOG_CTRL_ENABLE_Pos 30U +#define WATCHDOG_CTRL_ENABLE_Msk (1U << WATCHDOG_CTRL_ENABLE_Pos) +#define WATCHDOG_CTRL_ENABLE WATCHDOG_CTRL_ENABLE_Msk +#define WATCHDOG_CTRL_PAUSE_DBG1_Pos 26U +#define WATCHDOG_CTRL_PAUSE_DBG1_Msk (1U << WATCHDOG_CTRL_PAUSE_DBG1_Pos) +#define WATCHDOG_CTRL_PAUSE_DBG1 WATCHDOG_CTRL_PAUSE_DBG1_Msk +#define WATCHDOG_CTRL_PAUSE_DBG0_Pos 25U +#define WATCHDOG_CTRL_PAUSE_DBG0_Msk (1U << WATCHDOG_CTRL_PAUSE_DBG0_Pos) +#define WATCHDOG_CTRL_PAUSE_DBG0 WATCHDOG_CTRL_PAUSE_DBG0_Msk +#define WATCHDOG_CTRL_PAUSE_JTAG_Pos 24U +#define WATCHDOG_CTRL_PAUSE_JTAG_Msk (1U << WATCHDOG_CTRL_PAUSE_JTAG_Pos) +#define WATCHDOG_CTRL_PAUSE_JTAG WATCHDOG_CTRL_PAUSE_JTAG_Msk +#define WATCHDOG_CTRL_TIME_Pos 0U +#define WATCHDOG_CTRL_TIME_Msk (0xFFFFFFU << WATCHDOG_CTRL_TIME_Pos) +#define WATCHDOG_CTRL_TIME WATCHDOG_CTRL_TIME_Msk + +#define WATCHDOG_LOAD_Pos 0U +#define WATCHDOG_LOAD_Msk (0xFFFFFFU << WATCHDOG_LOAD_Pos) +#define WATCHDOG_LOAD WATCHDOG_LOAD_Msk + +#define WATCHDOG_REASON_FORCE_Pos 1U +#define WATCHDOG_REASON_FORCE_Msk (1U << WATCHDOG_REASON_FORCE_Pos) +#define WATCHDOG_REASON_FORCE WATCHDOG_REASON_FORCE_Msk +#define WATCHDOG_REASON_TIMER_Pos 0U +#define WATCHDOG_REASON_TIMER_Msk (1U << WATCHDOG_REASON_TIMER_Pos) +#define WATCHDOG_REASON_TIMER WATCHDOG_REASON_TIMER_Msk + +#define WATCHDOG_TICK_COUNT_Pos 11U +#define WATCHDOG_TICK_COUNT_Msk (0x1FFU << WATCHDOG_TICK_COUNT_Pos) +#define WATCHDOG_TICK_COUNT WATCHDOG_TICK_COUNT_Msk +#define WATCHDOG_TICK_RUNNING_Pos 10U +#define WATCHDOG_TICK_RUNNING_Msk (1U << WATCHDOG_TICK_RUNNING_Pos) +#define WATCHDOG_TICK_RUNNING WATCHDOG_TICK_RUNNING_Msk +#define WATCHDOG_TICK_ENABLE_Pos 9U +#define WATCHDOG_TICK_ENABLE_Msk (1U << WATCHDOG_TICK_ENABLE_Pos) +#define WATCHDOG_TICK_ENABLE WATCHDOG_TICK_ENABLE_Msk +#define WATCHDOG_TICK_CYCLES_Pos 0U +#define WATCHDOG_TICK_CYCLES_Msk (0x1FFU << WATCHDOG_TICK_CYCLES_Pos) +#define WATCHDOG_TICK_CYCLES WATCHDOG_TICK_CYCLES_Msk +/** @} */ + +/** + * @name I2C bits definitions + * @note See RP2350 Datasheet 12.2.17 I2C List of Registers + * @{ + */ +#define I2C_IC_CON_STOP_DET_IF_MASTER_ACTIVE_Pos 10U +#define I2C_IC_CON_STOP_DET_IF_MASTER_ACTIVE_Msk (1U << I2C_IC_CON_STOP_DET_IF_MASTER_ACTIVE_Pos) +#define I2C_IC_CON_STOP_DET_IF_MASTER_ACTIVE I2C_IC_CON_STOP_DET_IF_MASTER_ACTIVE_Msk +#define I2C_IC_CON_RX_FIFO_FULL_HLD_CTRL_Pos 9U +#define I2C_IC_CON_RX_FIFO_FULL_HLD_CTRL_Msk (1U << I2C_IC_CON_RX_FIFO_FULL_HLD_CTRL_Pos) +#define I2C_IC_CON_RX_FIFO_FULL_HLD_CTRL I2C_IC_CON_RX_FIFO_FULL_HLD_CTRL_Msk +#define I2C_IC_CON_TX_EMPTY_CTRL_Pos 8U +#define I2C_IC_CON_TX_EMPTY_CTRL_Msk (1U << I2C_IC_CON_TX_EMPTY_CTRL_Pos) +#define I2C_IC_CON_TX_EMPTY_CTRL I2C_IC_CON_TX_EMPTY_CTRL_Msk +#define I2C_IC_CON_STOP_DET_IFADDRESSED_Pos 7U +#define I2C_IC_CON_STOP_DET_IFADDRESSED_Msk (1U << I2C_IC_CON_STOP_DET_IFADDRESSED_Pos) +#define I2C_IC_CON_STOP_DET_IFADDRESSED I2C_IC_CON_STOP_DET_IFADDRESSED_Msk +#define I2C_IC_CON_IC_SLAVE_DISABLE_Pos 6U +#define I2C_IC_CON_IC_SLAVE_DISABLE_Msk (1U << I2C_IC_CON_IC_SLAVE_DISABLE_Pos) +#define I2C_IC_CON_IC_SLAVE_DISABLE I2C_IC_CON_IC_SLAVE_DISABLE_Msk +#define I2C_IC_CON_IC_RESTART_EN_Pos 5U +#define I2C_IC_CON_IC_RESTART_EN_Msk (1U << I2C_IC_CON_IC_RESTART_EN_Pos) +#define I2C_IC_CON_IC_RESTART_EN I2C_IC_CON_IC_RESTART_EN_Msk +#define I2C_IC_CON_IC_10BITADDR_MASTER_Pos 4U +#define I2C_IC_CON_IC_10BITADDR_MASTER_Msk (1U << I2C_IC_CON_IC_10BITADDR_MASTER_Pos) +#define I2C_IC_CON_IC_10BITADDR_MASTER I2C_IC_CON_IC_10BITADDR_MASTER_Msk +#define I2C_IC_CON_IC_10BITADDR_SLAVE_Pos 3U +#define I2C_IC_CON_IC_10BITADDR_SLAVE_Msk (1U << I2C_IC_CON_IC_10BITADDR_SLAVE_Pos) +#define I2C_IC_CON_IC_10BITADDR_SLAVE I2C_IC_CON_IC_10BITADDR_SLAVE_Msk +#define I2C_IC_CON_SPEED_Pos 1U +#define I2C_IC_CON_SPEED_Msk (3U << I2C_IC_CON_SPEED_Pos) +#define I2C_IC_CON_SPEED I2C_IC_CON_SPEED_Msk +#define I2C_IC_CON_MASTER_MODE_Pos 0U +#define I2C_IC_CON_MASTER_MODE_Msk (1U << I2C_IC_CON_MASTER_MODE_Pos) +#define I2C_IC_CON_MASTER_MODE I2C_IC_CON_MASTER_MODE_Msk + +#define I2C_IC_TAR_SPECIAL_Pos 11U +#define I2C_IC_TAR_SPECIAL_Msk (1U << I2C_IC_TAR_SPECIAL_Pos) +#define I2C_IC_TAR_SPECIAL I2C_IC_TAR_SPECIAL_Msk +#define I2C_IC_TAR_GC_OR_START_Pos 10U +#define I2C_IC_TAR_GC_OR_START_Msk (1U << I2C_IC_TAR_GC_OR_START_Pos) +#define I2C_IC_TAR_GC_OR_START I2C_IC_TAR_GC_OR_START_Msk +#define I2C_IC_TAR_IC_TAR_Pos 0U +#define I2C_IC_TAR_IC_TAR_Msk (0x3FFU << I2C_IC_TAR_IC_TAR_Pos) +#define I2C_IC_TAR_IC_TAR I2C_IC_TAR_IC_TAR_Msk + +#define I2C_IC_SAR_IC_SAR_Pos 0U +#define I2C_IC_SAR_IC_SAR_Msk (0x3FFU << I2C_IC_SAR_IC_SAR_Pos) +#define I2C_IC_SAR_IC_SAR I2C_IC_SAR_IC_SAR_Msk + +#define I2C_IC_DATA_CMD_FIRST_DATA_BYTE_Pos 11U +#define I2C_IC_DATA_CMD_FIRST_DATA_BYTE_Msk (1U << I2C_IC_DATA_CMD_FIRST_DATA_BYTE_Pos) +#define I2C_IC_DATA_CMD_FIRST_DATA_BYTE I2C_IC_DATA_CMD_FIRST_DATA_BYTE_Msk +#define I2C_IC_DATA_CMD_RESTART_Pos 10U +#define I2C_IC_DATA_CMD_RESTART_Msk (1U << I2C_IC_DATA_CMD_RESTART_Pos) +#define I2C_IC_DATA_CMD_RESTART I2C_IC_DATA_CMD_RESTART_Msk +#define I2C_IC_DATA_CMD_STOP_Pos 9U +#define I2C_IC_DATA_CMD_STOP_Msk (1U << I2C_IC_DATA_CMD_STOP_Pos) +#define I2C_IC_DATA_CMD_STOP I2C_IC_DATA_CMD_STOP_Msk +#define I2C_IC_DATA_CMD_CMD_Pos 8U +#define I2C_IC_DATA_CMD_CMD_Msk (1U << I2C_IC_DATA_CMD_CMD_Pos) +#define I2C_IC_DATA_CMD_CMD I2C_IC_DATA_CMD_CMD_Msk +#define I2C_IC_DATA_CMD_DAT_Pos 0U +#define I2C_IC_DATA_CMD_DAT_Msk (0xFFU << I2C_IC_DATA_CMD_DAT_Pos) +#define I2C_IC_DATA_CMD_DAT I2C_IC_DATA_CMD_DAT_Msk + +#define I2C_IC_SS_SCL_HCNT_Pos 0U +#define I2C_IC_SS_SCL_HCNT_Msk (0xFFFFU << I2C_IC_SS_SCL_HCNT_Pos) +#define I2C_IC_SS_SCL_HCNT I2C_IC_SS_SCL_HCNT_Msk + +#define I2C_IC_SS_SCL_LCNT_Pos 0U +#define I2C_IC_SS_SCL_LCNT_Msk (0xFFFFU << I2C_IC_SS_SCL_LCNT_Pos) +#define I2C_IC_SS_SCL_LCNT I2C_IC_SS_SCL_LCNT_Msk + +#define I2C_IC_FS_SCL_HCNT_Pos 0U +#define I2C_IC_FS_SCL_HCNT_Msk (0xFFFFU << I2C_IC_FS_SCL_HCNT_Pos) +#define I2C_IC_FS_SCL_HCNT I2C_IC_FS_SCL_HCNT_Msk + +#define I2C_IC_FS_SCL_LCNT_Pos 0U +#define I2C_IC_FS_SCL_LCNT_Msk (0xFFFFU << I2C_IC_FS_SCL_LCNT_Pos) +#define I2C_IC_FS_SCL_LCNT I2C_IC_FS_SCL_LCNT_Msk + +#define I2C_IC_INTR_STAT_R_MASTER_ON_HOLD_Pos 13U +#define I2C_IC_INTR_STAT_R_MASTER_ON_HOLD_Msk (1U << I2C_IC_INTR_STAT_R_MASTER_ON_HOLD_Pos) +#define I2C_IC_INTR_STAT_R_MASTER_ON_HOLD I2C_IC_INTR_STAT_R_MASTER_ON_HOLD_Msk +#define I2C_IC_INTR_STAT_R_RESTART_DET_Pos 12U +#define I2C_IC_INTR_STAT_R_RESTART_DET_Msk (1U << I2C_IC_INTR_STAT_R_RESTART_DET_Pos) +#define I2C_IC_INTR_STAT_R_RESTART_DET I2C_IC_INTR_STAT_R_RESTART_DET_Msk +#define I2C_IC_INTR_STAT_R_GEN_CALL_Pos 11U +#define I2C_IC_INTR_STAT_R_GEN_CALL_Msk (1U << I2C_IC_INTR_STAT_R_GEN_CALL_Pos) +#define I2C_IC_INTR_STAT_R_GEN_CALL I2C_IC_INTR_STAT_R_GEN_CALL_Msk +#define I2C_IC_INTR_STAT_R_START_DET_Pos 10U +#define I2C_IC_INTR_STAT_R_START_DET_Msk (1U << I2C_IC_INTR_STAT_R_START_DET_Pos) +#define I2C_IC_INTR_STAT_R_START_DET I2C_IC_INTR_STAT_R_START_DET_Msk +#define I2C_IC_INTR_STAT_R_STOP_DET_Pos 9U +#define I2C_IC_INTR_STAT_R_STOP_DET_Msk (1U << I2C_IC_INTR_STAT_R_STOP_DET_Pos) +#define I2C_IC_INTR_STAT_R_STOP_DET I2C_IC_INTR_STAT_R_STOP_DET_Msk +#define I2C_IC_INTR_STAT_R_ACTIVITY_Pos 8U +#define I2C_IC_INTR_STAT_R_ACTIVITY_Msk (1U << I2C_IC_INTR_STAT_R_ACTIVITY_Pos) +#define I2C_IC_INTR_STAT_R_ACTIVITY I2C_IC_INTR_STAT_R_ACTIVITY_Msk +#define I2C_IC_INTR_STAT_R_RX_DONE_Pos 7U +#define I2C_IC_INTR_STAT_R_RX_DONE_Msk (1U << I2C_IC_INTR_STAT_R_RX_DONE_Pos) +#define I2C_IC_INTR_STAT_R_RX_DONE I2C_IC_INTR_STAT_R_RX_DONE_Msk +#define I2C_IC_INTR_STAT_R_TX_ABRT_Pos 6U +#define I2C_IC_INTR_STAT_R_TX_ABRT_Msk (1U << I2C_IC_INTR_STAT_R_TX_ABRT_Pos) +#define I2C_IC_INTR_STAT_R_TX_ABRT I2C_IC_INTR_STAT_R_TX_ABRT_Msk +#define I2C_IC_INTR_STAT_R_RD_REQ_Pos 5U +#define I2C_IC_INTR_STAT_R_RD_REQ_Msk (1U << I2C_IC_INTR_STAT_R_RD_REQ_Pos) +#define I2C_IC_INTR_STAT_R_RD_REQ I2C_IC_INTR_STAT_R_RD_REQ_Msk +#define I2C_IC_INTR_STAT_R_TX_EMPTY_Pos 4U +#define I2C_IC_INTR_STAT_R_TX_EMPTY_Msk (1U << I2C_IC_INTR_STAT_R_TX_EMPTY_Pos) +#define I2C_IC_INTR_STAT_R_TX_EMPTY I2C_IC_INTR_STAT_R_TX_EMPTY_Msk +#define I2C_IC_INTR_STAT_R_TX_OVER_Pos 3U +#define I2C_IC_INTR_STAT_R_TX_OVER_Msk (1U << I2C_IC_INTR_STAT_R_TX_OVER_Pos) +#define I2C_IC_INTR_STAT_R_TX_OVER I2C_IC_INTR_STAT_R_TX_OVER_Msk +#define I2C_IC_INTR_STAT_R_RX_FULL_Pos 2U +#define I2C_IC_INTR_STAT_R_RX_FULL_Msk (1U << I2C_IC_INTR_STAT_R_RX_FULL_Pos) +#define I2C_IC_INTR_STAT_R_RX_FULL I2C_IC_INTR_STAT_R_RX_FULL_Msk +#define I2C_IC_INTR_STAT_R_RX_OVER_Pos 1U +#define I2C_IC_INTR_STAT_R_RX_OVER_Msk (1U << I2C_IC_INTR_STAT_R_RX_OVER_Pos) +#define I2C_IC_INTR_STAT_R_RX_OVER I2C_IC_INTR_STAT_R_RX_OVER_Msk +#define I2C_IC_INTR_STAT_R_RX_UNDER_Pos 0U +#define I2C_IC_INTR_STAT_R_RX_UNDER_Msk (1U << I2C_IC_INTR_STAT_R_RX_UNDER_Pos) +#define I2C_IC_INTR_STAT_R_RX_UNDER I2C_IC_INTR_STAT_R_RX_UNDER_Msk + +#define I2C_IC_INTR_MASK_M_MASTER_ON_HOLD_Pos 13U +#define I2C_IC_INTR_MASK_M_MASTER_ON_HOLD_Msk (1U << I2C_IC_INTR_MASK_M_MASTER_ON_HOLD_Pos) +#define I2C_IC_INTR_MASK_M_MASTER_ON_HOLD I2C_IC_INTR_MASK_M_MASTER_ON_HOLD_Msk +#define I2C_IC_INTR_MASK_M_RESTART_DET_Pos 12U +#define I2C_IC_INTR_MASK_M_RESTART_DET_Msk (1U << I2C_IC_INTR_MASK_M_RESTART_DET_Pos) +#define I2C_IC_INTR_MASK_M_RESTART_DET I2C_IC_INTR_MASK_M_RESTART_DET_Msk +#define I2C_IC_INTR_MASK_M_GEN_CALL_Pos 11U +#define I2C_IC_INTR_MASK_M_GEN_CALL_Msk (1U << I2C_IC_INTR_MASK_M_GEN_CALL_Pos) +#define I2C_IC_INTR_MASK_M_GEN_CALL I2C_IC_INTR_MASK_M_GEN_CALL_Msk +#define I2C_IC_INTR_MASK_M_START_DET_Pos 10U +#define I2C_IC_INTR_MASK_M_START_DET_Msk (1U << I2C_IC_INTR_MASK_M_START_DET_Pos) +#define I2C_IC_INTR_MASK_M_START_DET I2C_IC_INTR_MASK_M_START_DET_Msk +#define I2C_IC_INTR_MASK_M_STOP_DET_Pos 9U +#define I2C_IC_INTR_MASK_M_STOP_DET_Msk (1U << I2C_IC_INTR_MASK_M_STOP_DET_Pos) +#define I2C_IC_INTR_MASK_M_STOP_DET I2C_IC_INTR_MASK_M_STOP_DET_Msk +#define I2C_IC_INTR_MASK_M_ACTIVITY_Pos 8U +#define I2C_IC_INTR_MASK_M_ACTIVITY_Msk (1U << I2C_IC_INTR_MASK_M_ACTIVITY_Pos) +#define I2C_IC_INTR_MASK_M_ACTIVITY I2C_IC_INTR_MASK_M_ACTIVITY_Msk +#define I2C_IC_INTR_MASK_M_RX_DONE_Pos 7U +#define I2C_IC_INTR_MASK_M_RX_DONE_Msk (1U << I2C_IC_INTR_MASK_M_RX_DONE_Pos) +#define I2C_IC_INTR_MASK_M_RX_DONE I2C_IC_INTR_MASK_M_RX_DONE_Msk +#define I2C_IC_INTR_MASK_M_TX_ABRT_Pos 6U +#define I2C_IC_INTR_MASK_M_TX_ABRT_Msk (1U << I2C_IC_INTR_MASK_M_TX_ABRT_Pos) +#define I2C_IC_INTR_MASK_M_TX_ABRT I2C_IC_INTR_MASK_M_TX_ABRT_Msk +#define I2C_IC_INTR_MASK_M_RD_REQ_Pos 5U +#define I2C_IC_INTR_MASK_M_RD_REQ_Msk (1U << I2C_IC_INTR_MASK_M_RD_REQ_Pos) +#define I2C_IC_INTR_MASK_M_RD_REQ I2C_IC_INTR_MASK_M_RD_REQ_Msk +#define I2C_IC_INTR_MASK_M_TX_EMPTY_Pos 4U +#define I2C_IC_INTR_MASK_M_TX_EMPTY_Msk (1U << I2C_IC_INTR_MASK_M_TX_EMPTY_Pos) +#define I2C_IC_INTR_MASK_M_TX_EMPTY I2C_IC_INTR_MASK_M_TX_EMPTY_Msk +#define I2C_IC_INTR_MASK_M_TX_OVER_Pos 3U +#define I2C_IC_INTR_MASK_M_TX_OVER_Msk (1U << I2C_IC_INTR_MASK_M_TX_OVER_Pos) +#define I2C_IC_INTR_MASK_M_TX_OVER I2C_IC_INTR_MASK_M_TX_OVER_Msk +#define I2C_IC_INTR_MASK_M_RX_FULL_Pos 2U +#define I2C_IC_INTR_MASK_M_RX_FULL_Msk (1U << I2C_IC_INTR_MASK_M_RX_FULL_Pos) +#define I2C_IC_INTR_MASK_M_RX_FULL I2C_IC_INTR_MASK_M_RX_FULL_Msk +#define I2C_IC_INTR_MASK_M_RX_OVER_Pos 1U +#define I2C_IC_INTR_MASK_M_RX_OVER_Msk (1U << I2C_IC_INTR_MASK_M_RX_OVER_Pos) +#define I2C_IC_INTR_MASK_M_RX_OVER I2C_IC_INTR_MASK_M_RX_OVER_Msk +#define I2C_IC_INTR_MASK_M_RX_UNDER_Pos 0U +#define I2C_IC_INTR_MASK_M_RX_UNDER_Msk (1U << I2C_IC_INTR_MASK_M_RX_UNDER_Pos) +#define I2C_IC_INTR_MASK_M_RX_UNDER I2C_IC_INTR_MASK_M_RX_UNDER_Msk + +#define I2C_IC_RX_TL_RX_TL_Pos 0U +#define I2C_IC_RX_TL_RX_TL_Msk (0xFFU << I2C_IC_RX_TL_RX_TL_Pos) +#define I2C_IC_RX_TL_RX_TL I2C_IC_RX_TL_RX_TL_Msk + +#define I2C_IC_TX_TL_TX_TL_Pos 0U +#define I2C_IC_TX_TL_TX_TL_Msk (0xFFU << I2C_IC_TX_TL_TX_TL_Pos) +#define I2C_IC_TX_TL_TX_TL I2C_IC_TX_TL_TX_TL_Msk + +#define I2C_IC_CLR_INTR_CLR_INTR_Pos 0U +#define I2C_IC_CLR_INTR_CLR_INTR_Msk (1U << I2C_IC_CLR_INTR_CLR_INTR_Pos) +#define I2C_IC_CLR_INTR_CLR_INTR I2C_IC_CLR_INTR_CLR_INTR_Msk + +#define I2C_IC_ENABLE_TX_CMD_BLOCK_Pos 2U +#define I2C_IC_ENABLE_TX_CMD_BLOCK_Msk (1U << I2C_IC_ENABLE_TX_CMD_BLOCK_Pos) +#define I2C_IC_ENABLE_TX_CMD_BLOCK I2C_IC_ENABLE_TX_CMD_BLOCK_Msk +#define I2C_IC_ENABLE_ABORT_Pos 1U +#define I2C_IC_ENABLE_ABORT_Msk (1U << I2C_IC_ENABLE_ABORT_Pos) +#define I2C_IC_ENABLE_ABORT I2C_IC_ENABLE_ABORT_Msk +#define I2C_IC_ENABLE_ENABLE_Pos 0U +#define I2C_IC_ENABLE_ENABLE_Msk (1U << I2C_IC_ENABLE_ENABLE_Pos) +#define I2C_IC_ENABLE_ENABLE I2C_IC_ENABLE_ENABLE_Msk + +#define I2C_IC_STATUS_SLV_ACTIVITY_Pos 6U +#define I2C_IC_STATUS_SLV_ACTIVITY_Msk (1U << I2C_IC_STATUS_SLV_ACTIVITY_Pos) +#define I2C_IC_STATUS_SLV_ACTIVITY I2C_IC_STATUS_SLV_ACTIVITY_Msk +#define I2C_IC_STATUS_MST_ACTIVITY_Pos 5U +#define I2C_IC_STATUS_MST_ACTIVITY_Msk (1U << I2C_IC_STATUS_MST_ACTIVITY_Pos) +#define I2C_IC_STATUS_MST_ACTIVITY I2C_IC_STATUS_MST_ACTIVITY_Msk +#define I2C_IC_STATUS_RFF_Pos 4U +#define I2C_IC_STATUS_RFF_Msk (1U << I2C_IC_STATUS_RFF_Pos) +#define I2C_IC_STATUS_RFF I2C_IC_STATUS_RFF_Msk +#define I2C_IC_STATUS_RFNE_Pos 3U +#define I2C_IC_STATUS_RFNE_Msk (1U << I2C_IC_STATUS_RFNE_Pos) +#define I2C_IC_STATUS_RFNE I2C_IC_STATUS_RFNE_Msk +#define I2C_IC_STATUS_TFE_Pos 2U +#define I2C_IC_STATUS_TFE_Msk (1U << I2C_IC_STATUS_TFE_Pos) +#define I2C_IC_STATUS_TFE I2C_IC_STATUS_TFE_Msk +#define I2C_IC_STATUS_TFNF_Pos 1U +#define I2C_IC_STATUS_TFNF_Msk (1U << I2C_IC_STATUS_TFNF_Pos) +#define I2C_IC_STATUS_TFNF I2C_IC_STATUS_TFNF_Msk +#define I2C_IC_STATUS_ACTIVITY_Pos 0U +#define I2C_IC_STATUS_ACTIVITY_Msk (1U << I2C_IC_STATUS_ACTIVITY_Pos) +#define I2C_IC_STATUS_ACTIVITY I2C_IC_STATUS_ACTIVITY_Msk + +#define I2C_IC_TXFLR_TXFLR_Pos 0U +#define I2C_IC_TXFLR_TXFLR_Msk (0x1FU << I2C_IC_TXFLR_TXFLR_Pos) +#define I2C_IC_TXFLR_TXFLR I2C_IC_TXFLR_TXFLR_Msk + +#define I2C_IC_RXFLR_RXFLR_Pos 0U +#define I2C_IC_RXFLR_RXFLR_Msk (0x1FU << I2C_IC_RXFLR_RXFLR_Pos) +#define I2C_IC_RXFLR_RXFLR I2C_IC_RXFLR_RXFLR_Msk + +#define I2C_IC_SDA_HOLD_IC_SDA_RX_HOLD_Pos 16U +#define I2C_IC_SDA_HOLD_IC_SDA_RX_HOLD_Msk (0xFFU << I2C_IC_SDA_HOLD_IC_SDA_RX_HOLD_Pos) +#define I2C_IC_SDA_HOLD_IC_SDA_RX_HOLD I2C_IC_SDA_HOLD_IC_SDA_RX_HOLD_Msk +#define I2C_IC_SDA_HOLD_IC_SDA_TX_HOLD_Pos 0U +#define I2C_IC_SDA_HOLD_IC_SDA_TX_HOLD_Msk (0xFFFFU << I2C_IC_SDA_HOLD_IC_SDA_TX_HOLD_Pos) +#define I2C_IC_SDA_HOLD_IC_SDA_TX_HOLD I2C_IC_SDA_HOLD_IC_SDA_TX_HOLD_Msk + +#define I2C_IC_DMA_CR_TDMAE_Pos 1U +#define I2C_IC_DMA_CR_TDMAE_Msk (1U << I2C_IC_DMA_CR_TDMAE_Pos) +#define I2C_IC_DMA_CR_TDMAE I2C_IC_DMA_CR_TDMAE_Msk +#define I2C_IC_DMA_CR_RDMAE_Pos 0U +#define I2C_IC_DMA_CR_RDMAE_Msk (1U << I2C_IC_DMA_CR_RDMAE_Pos) +#define I2C_IC_DMA_CR_RDMAE I2C_IC_DMA_CR_RDMAE_Msk + +#define I2C_IC_DMA_TDLR_DMATDL_Pos 0U +#define I2C_IC_DMA_TDLR_DMATDL_Msk (0xFU << I2C_IC_DMA_TDLR_DMATDL_Pos) +#define I2C_IC_DMA_TDLR_DMATDL I2C_IC_DMA_TDLR_DMATDL_Msk + +#define I2C_IC_DMA_RDLR_DMARDL_Pos 0U +#define I2C_IC_DMA_RDLR_DMARDL_Msk (0xFU << I2C_IC_DMA_RDLR_DMARDL_Pos) +#define I2C_IC_DMA_RDLR_DMARDL I2C_IC_DMA_RDLR_DMARDL_Msk + +#define I2C_IC_SDA_SETUP_SDA_SETUP_Pos 0U +#define I2C_IC_SDA_SETUP_SDA_SETUP_Msk (0xFFU << I2C_IC_SDA_SETUP_SDA_SETUP_Pos) +#define I2C_IC_SDA_SETUP_SDA_SETUP I2C_IC_SDA_SETUP_SDA_SETUP_Msk + +#define I2C_IC_ACK_GENERAL_CALL_ACK_GEN_CALL_Pos 0U +#define I2C_IC_ACK_GENERAL_CALL_ACK_GEN_CALL_Msk (1U << I2C_IC_ACK_GENERAL_CALL_ACK_GEN_CALL_Pos) +#define I2C_IC_ACK_GENERAL_CALL_ACK_GEN_CALL I2C_IC_ACK_GENERAL_CALL_ACK_GEN_CALL_Msk + +#define I2C_IC_ENABLE_STATUS_SLV_RX_DATA_LOST_Pos 2U +#define I2C_IC_ENABLE_STATUS_SLV_RX_DATA_LOST_Msk (1U << I2C_IC_ENABLE_STATUS_SLV_RX_DATA_LOST_Pos) +#define I2C_IC_ENABLE_STATUS_SLV_RX_DATA_LOST I2C_IC_ENABLE_STATUS_SLV_RX_DATA_LOST_Msk +#define I2C_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY_Pos 1U +#define I2C_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY_Msk (1U << I2C_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY_Pos) +#define I2C_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY I2C_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY_Msk +#define I2C_IC_ENABLE_STATUS_IC_EN_Pos 0U +#define I2C_IC_ENABLE_STATUS_IC_EN_Msk (1U << I2C_IC_ENABLE_STATUS_IC_EN_Pos) +#define I2C_IC_ENABLE_STATUS_IC_EN I2C_IC_ENABLE_STATUS_IC_EN_Msk + +#define I2C_IC_TX_ABRT_SOURCE_TX_FLUSH_CNT_Pos 23U +#define I2C_IC_TX_ABRT_SOURCE_TX_FLUSH_CNT_Msk (0x1FFU << I2C_IC_TX_ABRT_SOURCE_TX_FLUSH_CNT_Pos) +#define I2C_IC_TX_ABRT_SOURCE_TX_FLUSH_CNT I2C_IC_TX_ABRT_SOURCE_TX_FLUSH_CNT_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_USER_ABRT_Pos 16U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_USER_ABRT_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_USER_ABRT_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_USER_ABRT I2C_IC_TX_ABRT_SOURCE_ABRT_USER_ABRT_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX_Pos 15U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX I2C_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST_Pos 14U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST I2C_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO_Pos 13U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO I2C_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO_Msk +#define I2C_IC_TX_ABRT_SOURCE_ARB_LOST_Pos 12U +#define I2C_IC_TX_ABRT_SOURCE_ARB_LOST_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ARB_LOST_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ARB_LOST I2C_IC_TX_ABRT_SOURCE_ARB_LOST_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS_Pos 11U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS I2C_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT_Pos 10U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT I2C_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT_Pos 9U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT_Pos 8U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT I2C_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET_Pos 7U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET I2C_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET_Pos 6U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET I2C_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ_Pos 5U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK_Pos 4U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK I2C_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK_Pos 3U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK I2C_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK_Pos 2U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK_Pos 1U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK_Msk +#define I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK_Pos 0U +#define I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK_Msk (1U << I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK_Pos) +#define I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK_Msk + +#define I2C_IC_FS_SPKLEN_IC_FS_SPKLEN_Pos 0U +#define I2C_IC_FS_SPKLEN_IC_FS_SPKLEN_Msk (0xFFU << I2C_IC_FS_SPKLEN_IC_FS_SPKLEN_Pos) +#define I2C_IC_FS_SPKLEN_IC_FS_SPKLEN I2C_IC_FS_SPKLEN_IC_FS_SPKLEN_Msk +/** @} */ + +/** + * @name PWM bits definitions + * @note See RP2350 Datasheet 12.5.3 PWM List of Registers + * @{ + */ +#define PWM_CSR_PH_ADV_Pos 7U +#define PWM_CSR_PH_ADV_Msk (1U << PWM_CSR_PH_ADV_Pos) +#define PWM_CSR_PH_ADV PWM_CSR_PH_ADV_Msk +#define PWM_CSR_PH_RET_Pos 6U +#define PWM_CSR_PH_RET_Msk (1U << PWM_CSR_PH_RET_Pos) +#define PWM_CSR_PH_RET PWM_CSR_PH_RET_Msk +#define PWM_CSR_DIVMODE_Pos 4U +#define PWM_CSR_DIVMODE_Msk (0x3U << PWM_CSR_DIVMODE_Pos) +#define PWM_CSR_DIVMODE(n) ((n) << PWM_CSR_DIVMODE_Pos) +#define PWM_CSR_B_INV_Pos 3U +#define PWM_CSR_B_INV_Msk (1U << PWM_CSR_B_INV_Pos) +#define PWM_CSR_B_INV PWM_CSR_B_INV_Msk +#define PWM_CSR_A_INV_Pos 2U +#define PWM_CSR_A_INV_Msk (1U << PWM_CSR_A_INV_Pos) +#define PWM_CSR_A_INV PWM_CSR_A_INV_Msk +#define PWM_CSR_PH_CORRECT_Pos 1U +#define PWM_CSR_PH_CORRECT_Msk (1U << PWM_CSR_PH_CORRECT_Pos) +#define PWM_CSR_PH_CORRECT PWM_CSR_PH_CORRECT_Msk +#define PWM_CSR_EN_Pos 0U +#define PWM_CSR_EN_Msk (1U << PWM_CSR_EN_Pos) +#define PWM_CSR_EN PWM_CSR_EN_Msk +#define PWM_CSR_PH_CORRECT_PHASE_CORRECT_MODULATION (1U << PWM_CSR_PH_CORRECT_Pos) +#define PWM_CSR_PH_CORRECT_TRAILING_EDGE (0U << PWM_CSR_PH_CORRECT_Pos) +#define PWM_CSR_DIVMODE_FREE PWM_CSR_DIVMODE(0U) +#define PWM_CSR_DIVMODE_GATED PWM_CSR_DIVMODE(1U) +#define PWM_CSR_DIVMODE_RISING_EDGE PWM_CSR_DIVMODE(2U) +#define PWM_CSR_DIVMODE_FALING_EDGE PWM_CSR_DIVMODE(3U) + +#define PWM_DIV_INT_Pos 4U +#define PWM_DIV_INT_Msk (0xFFU << PWM_DIV_INT_Pos) +#define PWM_DIV_INT PWM_DIV_INT_Msk +#define PWM_DIV_FRAC_Pos 0U +#define PWM_DIV_FRAC_Msk (0xFU << PWM_DIV_FRAC_Pos) +#define PWM_DIV_FRAC PWM_DIV_FRAC_Msk + +#define PWM_CTR_COUNTER_Pos 0U +#define PWM_CTR_COUNTER_Msk (0xFFFFU << PWM_CTR_COUNTER_Pos) +#define PWM_CTR_COUNTER PWM_CTR_COUNTER_Msk + +#define PWM_CC_B_Pos 16U +#define PWM_CC_B_Msk (0xFFFFU << PWM_CC_B_Pos) +#define PWM_CC_B PWM_CC_B_Msk +#define PWM_CC_A_Pos 0U +#define PWM_CC_A_Msk (0xFFFFU << PWM_CC_A_Pos) +#define PWM_CC_A PWM_CC_A_Msk + +#define PWM_TOP_VALUE_Pos 0U +#define PWM_TOP_VALUE_Msk (0xFFFFU << PWM_TOP_VALUE_Pos) +#define PWM_TOP_VALUE PWM_TOP_VALUE_Msk + +#define PWM_EN_CH11_Pos 11U +#define PWM_EN_CH11_Msk (1U << PWM_EN_CH11_Pos) +#define PWM_EN_CH11 PWM_EN_CH11_Msk +#define PWM_EN_CH10_Pos 10U +#define PWM_EN_CH10_Msk (1U << PWM_EN_CH10_Pos) +#define PWM_EN_CH10 PWM_EN_CH10_Msk +#define PWM_EN_CH9_Pos 9U +#define PWM_EN_CH9_Msk (1U << PWM_EN_CH9_Pos) +#define PWM_EN_CH9 PWM_EN_CH9_Msk +#define PWM_EN_CH8_Pos 8U +#define PWM_EN_CH8_Msk (1U << PWM_EN_CH8_Pos) +#define PWM_EN_CH8 PWM_EN_CH8_Msk +#define PWM_EN_CH7_Pos 7U +#define PWM_EN_CH7_Msk (1U << PWM_EN_CH7_Pos) +#define PWM_EN_CH7 PWM_EN_CH7_Msk +#define PWM_EN_CH6_Pos 6U +#define PWM_EN_CH6_Msk (1U << PWM_EN_CH6_Pos) +#define PWM_EN_CH6 PWM_EN_CH6_Msk +#define PWM_EN_CH5_Pos 5U +#define PWM_EN_CH5_Msk (1U << PWM_EN_CH5_Pos) +#define PWM_EN_CH5 PWM_EN_CH5_Msk +#define PWM_EN_CH4_Pos 4U +#define PWM_EN_CH4_Msk (1U << PWM_EN_CH4_Pos) +#define PWM_EN_CH4 PWM_EN_CH4_Msk +#define PWM_EN_CH3_Pos 3U +#define PWM_EN_CH3_Msk (1U << PWM_EN_CH3_Pos) +#define PWM_EN_CH3 PWM_EN_CH3_Msk +#define PWM_EN_CH2_Pos 2U +#define PWM_EN_CH2_Msk (1U << PWM_EN_CH2_Pos) +#define PWM_EN_CH2 PWM_EN_CH2_Msk +#define PWM_EN_CH1_Pos 1U +#define PWM_EN_CH1_Msk (1U << PWM_EN_CH1_Pos) +#define PWM_EN_CH1 PWM_EN_CH1_Msk +#define PWM_EN_CH0_Pos 0U +#define PWM_EN_CH0_Msk (1U << PWM_EN_CH0_Pos) +#define PWM_EN_CH0 PWM_EN_CH0_Msk +#define PWM_INTR_CH(n) (1U << (n)) +#define PWM_INTE_CH(n) (1U << (n)) +#define PWM_INTF_CH(n) (1U << (n)) +#define PWM_INTS_CH(n) (1U << (n)) +/** @} */ + +/** + * @name XOSC bits definitions + * @note See RP2350 Datasheet 8.2.8 XOSC List of Registers + * @{ + */ +#define XOSC_CTRL_ENABLE_Pos 12U +#define XOSC_CTRL_ENABLE_Msk (0xFFFU << XOSC_CTRL_ENABLE_Pos) +#define XOSC_CTRL_ENABLE_DISABLE (0xD1EU << XOSC_CTRL_ENABLE_Pos) +#define XOSC_CTRL_ENABLE_ENABLE (0xFABU << XOSC_CTRL_ENABLE_Pos) +#define XOSC_CTRL_FREQ_RANGE_Pos 0U +#define XOSC_CTRL_FREQ_RANGE_Msk (0xFFFU << XOSC_CTRL_FREQ_RANGE_Pos) +#define XOSC_CTRL_FREQ_RANGE_1_15MHZ (0xAA0U << XOSC_CTRL_FREQ_RANGE_Pos) + +#define XOSC_STATUS_STABLE_Pos 31U +#define XOSC_STATUS_STABLE_Msk (1U << XOSC_STATUS_STABLE_Pos) +#define XOSC_STATUS_STABLE XOSC_STATUS_STABLE_Msk +#define XOSC_STATUS_BADWRITE_Pos 24U +#define XOSC_STATUS_BADWRITE_Msk (1U << XOSC_STATUS_BADWRITE_Pos) +#define XOSC_STATUS_BADWRITE XOSC_STATUS_BADWRITE_Msk +#define XOSC_STATUS_ENABLED_Pos 12U +#define XOSC_STATUS_ENABLED_Msk (1U << XOSC_STATUS_ENABLED_Pos) +#define XOSC_STATUS_ENABLED XOSC_STATUS_ENABLED_Msk + +#define XOSC_DORMANT_DORMANT 0x636F6D61U +#define XOSC_DORMANT_WAKE 0x77616B65U + +#define XOSC_STARTUP_X4_Pos 20U +#define XOSC_STARTUP_X4_Msk (1U << XOSC_STARTUP_X4_Pos) +#define XOSC_STARTUP_X4 XOSC_STARTUP_X4_Msk +#define XOSC_STARTUP_DELAY_Pos 0U +#define XOSC_STARTUP_DELAY_Msk (0x3FFFU << XOSC_STARTUP_DELAY_Pos) +#define XOSC_STARTUP_DELAY(n) ((n) << XOSC_STARTUP_DELAY_Pos) +/** @} */ + +/** + * @name PLL bits definitions + * @note See RP2350 Datasheet 8.6.5 PLL List of Registers + * @{ + */ +#define PLL_CS_LOCK_Pos 31U +#define PLL_CS_LOCK_Msk (1U << PLL_CS_LOCK_Pos) +#define PLL_CS_LOCK PLL_CS_LOCK_Msk +#define PLL_CS_BYPASS_Pos 8U +#define PLL_CS_BYPASS_Msk (1U << PLL_CS_BYPASS_Pos) +#define PLL_CS_BYPASS PLL_CS_BYPASS_Msk +#define PLL_CS_REFDIV_Pos 0U +#define PLL_CS_REFDIV_Msk (0x3FU << PLL_CS_REFDIV_Pos) +#define PLL_CS_REFDIV(n) ((n) << PLL_CS_REFDIV_Pos) + +#define PLL_PWR_VCOPD_Pos 5U +#define PLL_PWR_VCOPD_Msk (1U << PLL_PWR_VCOPD_Pos) +#define PLL_PWR_VCOPD PLL_PWR_VCOPD_Msk +#define PLL_PWR_POSTDIVPD_Pos 3U +#define PLL_PWR_POSTDIVPD_Msk (1U << PLL_PWR_POSTDIVPD_Pos) +#define PLL_PWR_POSTDIVPD PLL_PWR_POSTDIVPD_Msk +#define PLL_PWR_DSMPD_Pos 2U +#define PLL_PWR_DSMPD_Msk (1U << PLL_PWR_DSMPD_Pos) +#define PLL_PWR_DSMPD PLL_PWR_DSMPD_Msk +#define PLL_PWR_PD_Pos 0U +#define PLL_PWR_PD_Msk (1U << PLL_PWR_PD_Pos) +#define PLL_PWR_PD PLL_PWR_PD_Msk + +#define PLL_FBDIV_INT_Pos 0U +#define PLL_FBDIV_INT_Msk (0xFFFU << PLL_FBDIV_INT_Pos) +#define PLL_FBDIV_INT(n) ((n) << PLL_FBDIV_INT_Pos) + +#define PLL_PRIM_POSTDIV1_Pos 16U +#define PLL_PRIM_POSTDIV1_Msk (0x7U << PLL_PRIM_POSTDIV1_Pos) +#define PLL_PRIM_POSTDIV1(n) ((n) << PLL_PRIM_POSTDIV1_Pos) +#define PLL_PRIM_POSTDIV2_Pos 12U +#define PLL_PRIM_POSTDIV2_Msk (0x7U << PLL_PRIM_POSTDIV2_Pos) +#define PLL_PRIM_POSTDIV2(n) ((n) << PLL_PRIM_POSTDIV2_Pos) +/** @} */ + +/** + * @name CLOCKS bits definitions + * @note See RP2350 Datasheet 8.1.17 Clocks List of Registers + * @{ + */ +/* CLK_REF CTRL */ +#define CLOCKS_CLK_REF_CTRL_SRC_Pos 0U +#define CLOCKS_CLK_REF_CTRL_SRC_Msk (0x3U << CLOCKS_CLK_REF_CTRL_SRC_Pos) +#define CLOCKS_CLK_REF_CTRL_SRC_ROSC (0x0U << CLOCKS_CLK_REF_CTRL_SRC_Pos) +#define CLOCKS_CLK_REF_CTRL_SRC_AUX (0x1U << CLOCKS_CLK_REF_CTRL_SRC_Pos) +#define CLOCKS_CLK_REF_CTRL_SRC_XOSC (0x2U << CLOCKS_CLK_REF_CTRL_SRC_Pos) +#define CLOCKS_CLK_REF_CTRL_AUXSRC_Pos 5U +#define CLOCKS_CLK_REF_CTRL_AUXSRC_Msk (0x3U << CLOCKS_CLK_REF_CTRL_AUXSRC_Pos) + +/* CLK_SYS CTRL */ +#define CLOCKS_CLK_SYS_CTRL_SRC_Pos 0U +#define CLOCKS_CLK_SYS_CTRL_SRC_Msk (0x1U << CLOCKS_CLK_SYS_CTRL_SRC_Pos) +#define CLOCKS_CLK_SYS_CTRL_SRC_REF (0x0U << CLOCKS_CLK_SYS_CTRL_SRC_Pos) +#define CLOCKS_CLK_SYS_CTRL_SRC_AUX (0x1U << CLOCKS_CLK_SYS_CTRL_SRC_Pos) +#define CLOCKS_CLK_SYS_CTRL_AUXSRC_Pos 5U +#define CLOCKS_CLK_SYS_CTRL_AUXSRC_Msk (0x7U << CLOCKS_CLK_SYS_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_SYS_CTRL_AUXSRC_PLL_SYS (0x0U << CLOCKS_CLK_SYS_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_SYS_CTRL_AUXSRC_PLL_USB (0x1U << CLOCKS_CLK_SYS_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_SYS_CTRL_AUXSRC_ROSC (0x2U << CLOCKS_CLK_SYS_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_SYS_CTRL_AUXSRC_XOSC (0x3U << CLOCKS_CLK_SYS_CTRL_AUXSRC_Pos) + +/* CLK_PERI CTRL */ +#define CLOCKS_CLK_PERI_CTRL_ENABLE_Pos 11U +#define CLOCKS_CLK_PERI_CTRL_ENABLE_Msk (1U << CLOCKS_CLK_PERI_CTRL_ENABLE_Pos) +#define CLOCKS_CLK_PERI_CTRL_ENABLE CLOCKS_CLK_PERI_CTRL_ENABLE_Msk +#define CLOCKS_CLK_PERI_CTRL_KILL_Pos 10U +#define CLOCKS_CLK_PERI_CTRL_KILL_Msk (1U << CLOCKS_CLK_PERI_CTRL_KILL_Pos) +#define CLOCKS_CLK_PERI_CTRL_KILL CLOCKS_CLK_PERI_CTRL_KILL_Msk +#define CLOCKS_CLK_PERI_CTRL_AUXSRC_Pos 5U +#define CLOCKS_CLK_PERI_CTRL_AUXSRC_Msk (0x7U << CLOCKS_CLK_PERI_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_PERI_CTRL_AUXSRC_SYS (0x0U << CLOCKS_CLK_PERI_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_PERI_CTRL_AUXSRC_PLL_SYS (0x1U << CLOCKS_CLK_PERI_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_PERI_CTRL_AUXSRC_PLL_USB (0x2U << CLOCKS_CLK_PERI_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_PERI_CTRL_AUXSRC_ROSC (0x3U << CLOCKS_CLK_PERI_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_PERI_CTRL_AUXSRC_XOSC (0x4U << CLOCKS_CLK_PERI_CTRL_AUXSRC_Pos) + +/* CLK_USB CTRL */ +#define CLOCKS_CLK_USB_CTRL_ENABLE_Pos 11U +#define CLOCKS_CLK_USB_CTRL_ENABLE_Msk (1U << CLOCKS_CLK_USB_CTRL_ENABLE_Pos) +#define CLOCKS_CLK_USB_CTRL_ENABLE CLOCKS_CLK_USB_CTRL_ENABLE_Msk +#define CLOCKS_CLK_USB_CTRL_KILL_Pos 10U +#define CLOCKS_CLK_USB_CTRL_KILL_Msk (1U << CLOCKS_CLK_USB_CTRL_KILL_Pos) +#define CLOCKS_CLK_USB_CTRL_KILL CLOCKS_CLK_USB_CTRL_KILL_Msk +#define CLOCKS_CLK_USB_CTRL_AUXSRC_Pos 5U +#define CLOCKS_CLK_USB_CTRL_AUXSRC_Msk (0x7U << CLOCKS_CLK_USB_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_USB_CTRL_AUXSRC_PLL_USB (0x0U << CLOCKS_CLK_USB_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_USB_CTRL_AUXSRC_PLL_SYS (0x1U << CLOCKS_CLK_USB_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_USB_CTRL_AUXSRC_ROSC (0x2U << CLOCKS_CLK_USB_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_USB_CTRL_AUXSRC_XOSC (0x3U << CLOCKS_CLK_USB_CTRL_AUXSRC_Pos) + +/* CLK_ADC CTRL */ +#define CLOCKS_CLK_ADC_CTRL_ENABLE_Pos 11U +#define CLOCKS_CLK_ADC_CTRL_ENABLE_Msk (1U << CLOCKS_CLK_ADC_CTRL_ENABLE_Pos) +#define CLOCKS_CLK_ADC_CTRL_ENABLE CLOCKS_CLK_ADC_CTRL_ENABLE_Msk +#define CLOCKS_CLK_ADC_CTRL_KILL_Pos 10U +#define CLOCKS_CLK_ADC_CTRL_KILL_Msk (1U << CLOCKS_CLK_ADC_CTRL_KILL_Pos) +#define CLOCKS_CLK_ADC_CTRL_KILL CLOCKS_CLK_ADC_CTRL_KILL_Msk +#define CLOCKS_CLK_ADC_CTRL_AUXSRC_Pos 5U +#define CLOCKS_CLK_ADC_CTRL_AUXSRC_Msk (0x7U << CLOCKS_CLK_ADC_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_ADC_CTRL_AUXSRC_PLL_USB (0x0U << CLOCKS_CLK_ADC_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_ADC_CTRL_AUXSRC_PLL_SYS (0x1U << CLOCKS_CLK_ADC_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_ADC_CTRL_AUXSRC_ROSC (0x2U << CLOCKS_CLK_ADC_CTRL_AUXSRC_Pos) +#define CLOCKS_CLK_ADC_CTRL_AUXSRC_XOSC (0x3U << CLOCKS_CLK_ADC_CTRL_AUXSRC_Pos) +/** @} */ + +/** + * @name Clock indexes for RP2350 + * @{ + */ +#define RP_CLK_GPOUT0 0U +#define RP_CLK_GPOUT1 1U +#define RP_CLK_GPOUT2 2U +#define RP_CLK_GPOUT3 3U +#define RP_CLK_REF 4U +#define RP_CLK_SYS 5U +#define RP_CLK_PERI 6U +#define RP_CLK_HSTX 7U +#define RP_CLK_USB 8U +#define RP_CLK_ADC 9U +#define RP_CLK_COUNT 10U +/** @} */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* RP2350_H */ + +/** @} */ diff --git a/os/common/ext/RP/RP2350/system_rp2350.h b/os/common/ext/RP/RP2350/system_rp2350.h new file mode 100644 index 0000000000..36cb25fce9 --- /dev/null +++ b/os/common/ext/RP/RP2350/system_rp2350.h @@ -0,0 +1,39 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP/system_rp2350.h + * @brief CMSIS system device file for the RP2350. + * + * @defgroup CMSIS_RP2350 RP2350 System Device File + * @ingroup CMSIS_DEVICE + * @{ + */ + +#ifndef SYSTEM_RP2350_H +#define SYSTEM_RP2350_H + +extern uint32_t SystemCoreClock; + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* SYSTEM_RP2350_H */ diff --git a/os/common/ports/ARMv8-M-ML-ALT/chcore.c b/os/common/ports/ARMv8-M-ML-ALT/chcore.c new file mode 100644 index 0000000000..e5f24b97e1 --- /dev/null +++ b/os/common/ports/ARMv8-M-ML-ALT/chcore.c @@ -0,0 +1,240 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation version 3 of the License. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ARMv8-M-ML-ALT/chcore.c + * @brief ARMv8-M MainLine (alt) port code. + * + * @addtogroup ARMV8M_ML_ALT_CORE + * @{ + */ + +#include "ch.h" + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +#if (PORT_MPU_INITIALIZE == TRUE) || defined(__DOXYGEN__) +static void port_init_regions(const uint32_t *src, volatile uint32_t *dst) { + + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; +} +#endif + +/*===========================================================================*/ +/* Module interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +#if (PORT_USE_SYSCALL == TRUE) || defined(__DOXYGEN__) +CC_NO_INLINE void port_syslock_noinline(void) { + + port_lock(); + __stats_start_measure_crit_thd(); + __dbg_check_lock(); +} + +CC_NO_INLINE uint64_t port_get_s_psp(void) { + thread_t *tp = __sch_get_currthread(); + + return ((uint64_t)(uint32_t)(tp->wabase) << 32) | + ((uint64_t)(uint32_t)(tp->waend) << 0); +} + +CC_WEAK void __port_do_fastcall_entry(uint32_t n, struct port_extctx *ectxp) { + + (void)ectxp; + (void)n; + + chSysHalt("unimplemented fastcall"); +} + +CC_WEAK void __port_do_syscall_entry(uint32_t n, struct port_extctx *ectxp) { + + (void)ectxp; + (void)n; + + chSysHalt("unimplemented syscall"); +} + +CC_WEAK void __port_do_syscall_return(void) { + + chSysHalt("unimplemented syscall return"); +} +#endif /* PORT_USE_SYSCALL == TRUE */ + +/** + * @brief Tail ISR context switch code. + * + * @return The threads pointers encoded in a single 64 bits value. + */ +uint64_t __port_schedule_next(void) { + + /* Note, not an error, we are outside the ISR already.*/ + chSysLock(); + + if (likely(chSchIsPreemptionRequired())) { + thread_t *otp, *ntp; + + otp = chThdGetSelfX(); + ntp = chSchSelectFirst(); + + __trace_switch(ntp, otp); + __stats_ctxswc(ntp, otp); + CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp); + + return ((uint64_t)(uint32_t)otp << 32) | ((uint64_t)(uint32_t)ntp << 0); + } + + chSysUnlock(); + + return (uint64_t)0; +} + +/** + * @brief Port-related initialization code. + * + * @param[in, out] oip pointer to the @p os_instance_t structure + * + * @notapi + */ +void port_init(os_instance_t *oip) { + + (void)oip; + + /* Starting in a known IRQ configuration.*/ + port_suspend(); + +#if CORTEX_USE_FPU == TRUE + { + uint32_t control; + + /* Making sure to use the correct settings for FPU-related exception + handling, better do not rely on startup settings.*/ + FPU->FPDSCR = 0U; + __set_FPSCR(0U); +#if PORT_USE_FPU_FAST_SWITCHING == 0 + /* No lazy context saving, always long exception context.*/ + control = CONTROL_FPCA_Msk | CONTROL_SPSEL_Msk; + FPU->FPCCR = FPU_FPCCR_ASPEN_Msk; +#elif PORT_USE_FPU_FAST_SWITCHING == 1 + /* Lazy context saving enabled, always long exception context.*/ + control = CONTROL_FPCA_Msk | CONTROL_SPSEL_Msk; + FPU->FPCCR = FPU_FPCCR_ASPEN_Msk | FPU_FPCCR_LSPEN_Msk; +#else /*PORT_USE_FPU_FAST_SWITCHING >= 2 */ + /* Lazy context saving enabled, automatic FPCA control.*/ + control = CONTROL_SPSEL_Msk; + FPU->FPCCR = FPU_FPCCR_ASPEN_Msk | FPU_FPCCR_LSPEN_Msk; +#endif + __set_CONTROL(control); + __ISB(); + } +#endif /* CORTEX_USE_FPU == TRUE */ + + /* Initializing priority grouping.*/ + NVIC_SetPriorityGrouping(PORT_PRIGROUP_INIT); + + /* DWT cycle counter enable.*/ + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; + +#if defined(port_smp_init) + port_smp_init(oip); +#endif + + /* Initialization of the system vectors used by the port.*/ + NVIC_SetPriority(SVCall_IRQn, CORTEX_PRIORITY_SVCALL); + NVIC_SetPriority(PendSV_IRQn, CORTEX_PRIORITY_PENDSV); + +#if PORT_MPU_INITIALIZE == TRUE + /* MPU initialization as specified in port options.*/ + { + MPU->MAIR[0] = PORT_MPU_MAIR0_INIT; + MPU->MAIR[1] = PORT_MPU_MAIR1_INIT; + + static const uint32_t regs0[] = {MPU_RNR_REGION(0U), + PORT_MPU_RBAR0_INIT, PORT_MPU_RLAR0_INIT, + PORT_MPU_RBAR1_INIT, PORT_MPU_RLAR1_INIT, + PORT_MPU_RBAR2_INIT, PORT_MPU_RLAR2_INIT, + PORT_MPU_RBAR3_INIT, PORT_MPU_RLAR3_INIT}; + port_init_regions(regs0, &MPU->RNR); + +#if CORTEX_MPU_REGIONS > 4 + static const uint32_t regs4[] = {MPU_RNR_REGION(4U), + PORT_MPU_RBAR4_INIT, PORT_MPU_RLAR4_INIT, + PORT_MPU_RBAR5_INIT, PORT_MPU_RLAR5_INIT, + PORT_MPU_RBAR6_INIT, PORT_MPU_RLAR6_INIT, + PORT_MPU_RBAR7_INIT, PORT_MPU_RLAR7_INIT}; + port_init_regions(regs4, &MPU->RNR); + +#if CORTEX_MPU_REGIONS > 8 + static const uint32_t regs8[] = {MPU_RNR_REGION(8U), + PORT_MPU_RBAR8_INIT, PORT_MPU_RLAR8_INIT, + PORT_MPU_RBAR9_INIT, PORT_MPU_RLAR9_INIT, + PORT_MPU_RBAR10_INIT, PORT_MPU_RLAR10_INIT, + PORT_MPU_RBAR11_INIT, PORT_MPU_RLAR11_INIT}; + port_init_regions(regs8, &MPU->RNR); + +#if CORTEX_MPU_REGIONS > 12 + static const uint32_t regs12[] = {MPU_RNR_REGION(12U), + PORT_MPU_RBAR12_INIT, PORT_MPU_RLAR12_INIT, + PORT_MPU_RBAR13_INIT, PORT_MPU_RLAR13_INIT, + PORT_MPU_RBAR14_INIT, PORT_MPU_RLAR14_INIT, + PORT_MPU_RBAR15_INIT, PORT_MPU_RLAR15_INIT}; + port_init_regions(regs12, &MPU->RNR); +#endif +#endif +#endif + } +#endif + +#if (PORT_MPU_INITIALIZE == TRUE) || (PORT_SWITCHED_REGIONS_NUMBER > 0) + /* MPU is enabled.*/ + mpuEnable(MPU_CTRL_PRIVDEFENA); +#endif +} + +/** @} */ diff --git a/os/common/ports/ARMv8-M-ML-ALT/chcore.h b/os/common/ports/ARMv8-M-ML-ALT/chcore.h new file mode 100644 index 0000000000..d965c1a966 --- /dev/null +++ b/os/common/ports/ARMv8-M-ML-ALT/chcore.h @@ -0,0 +1,1356 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation version 3 of the License. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ARMv8-M-ML-ALT/chcore.h + * @brief ARMv8-M MainLine (alternate) port macros and structures. + * + * @addtogroup ARMV8M_ML_ALT_CORE + * @{ + */ + +#ifndef CHCORE_H +#define CHCORE_H + +/* Inclusion of the Cortex-Mx implementation specific parameters.*/ +#include "cmparams.h" +#include "mpu_v8m.h" + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/** + * @brief Compiler name and version. + */ +#if defined(__GNUC__) || defined(__DOXYGEN__) +#define PORT_COMPILER_NAME "GCC " __VERSION__ + +#elif defined(__ICCARM__) +#define PORT_COMPILER_NAME "IAR" + +#elif defined(__CC_ARM) +#define PORT_COMPILER_NAME "RVCT" + +#else +#error "unsupported compiler" +#endif + +/** + * @name Port Capabilities and Constants + * @{ + */ +/** + * @brief This port supports a realtime counter. + */ +#define PORT_SUPPORTS_RT TRUE + +/** + * @brief Natural alignment constant. + * @note It is the minimum alignment for pointer-size variables. + */ +#define PORT_NATURAL_ALIGN sizeof (void *) + +/** + * @brief Stack initial alignment constant. + * @note It is the alignment required for the initial stack pointer, + * must be a multiple of sizeof (port_stkline_t). + * @note It is set to 32 in this architecture in order to have stacks + * initially aligned with cache lines. + */ +#define PORT_STACK_ALIGN 32U + +/** + * @brief Working Areas alignment constant. + * @note It is the alignment to be enforced for thread working areas, + * must be a multiple of sizeof (port_stkline_t). + * @note It is set to 32 in this architecture in order to have working + * areas aligned with cache lines and MPU guard pages. + */ +#define PORT_WORKING_AREA_ALIGN 32U +/** @} */ + +/** + * @name Kernel modes + * @{ + */ +/** + * @brief Standard mode. + * @details The RTOS is running in secure state with no switch in non-secure + * state ever performed. This is also used on devices with no + * TrustZone support at all. + */ +#define PORT_KERNEL_MODE_NORMAL 0U +/** + * @brief Kernel running in secure state with TZ support. + * @details The RTOS is running in secure state. + */ +#define PORT_KERNEL_MODE_HOST 1U +/** + * @brief Kernel running in non-secure state. + * @details The RTOS is running in non-secure state with no access to secure + * resources. + */ +#define PORT_KERNEL_MODE_GUEST 2U +/** @} */ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Kernel mode selection. + */ +#if !defined(PORT_KERNEL_MODE) || defined(__DOXYGEN__) +#define PORT_KERNEL_MODE PORT_KERNEL_MODE_NORMAL +#endif + +/** + * @brief Implements a syscall interface on SVCALL. + */ +#if !defined(PORT_USE_SYSCALL) || defined(__DOXYGEN__) +#define PORT_USE_SYSCALL FALSE +#endif + +/** + * @brief Number of MPU regions to be saved/restored during context switch. + * @note The first region is always region zero. + * @note The use of this option has an overhead of 8 bytes for each + * region for each thread. + * @note Allowed values are 0..8, zero means none. + */ +#if !defined(PORT_SWITCHED_REGIONS_NUMBER) || defined(__DOXYGEN__) +#define PORT_SWITCHED_REGIONS_NUMBER 0 +#endif + +/** + * @brief Stack size for the system idle thread. + * @details This size depends on the idle thread implementation, usually + * the idle thread should take no more space than those reserved + * by @p PORT_INT_REQUIRED_STACK. + * @note In this port it is set to 64 because the idle thread does have + * a stack frame when compiling without optimizations. You may + * reduce this value to zero when compiling with optimizations. + */ +#if !defined(PORT_IDLE_THREAD_STACK_SIZE) || defined(__DOXYGEN__) +#define PORT_IDLE_THREAD_STACK_SIZE 64 +#endif + +/** + * @brief Per-thread stack overhead for interrupts servicing. + * @details This constant is used in the calculation of the correct working + * area size. + * @note This port requires no extra stack space for interrupt handling + * because switch is performed in an exception handler. + */ +#if !defined(PORT_INT_REQUIRED_STACK) || defined(__DOXYGEN__) +#define PORT_INT_REQUIRED_STACK 0 +#endif + +/** + * @brief Enables the use of the WFI instruction in the idle thread loop. + */ +#if !defined(PORT_ENABLE_WFI_IDLE) +#define PORT_ENABLE_WFI_IDLE FALSE +#endif + +/** + * @brief Number of upper priority levels reserved as fast interrupts. + * @note The default reserves no priority levels for fast interrupts. + */ +#if !defined(PORT_FAST_PRIORITIES) +#define PORT_FAST_PRIORITIES 0U +#endif + +/** + * @brief FPU support in context switch. + * @details Activating this option activates the FPU support in the kernel. + */ +#if !defined(CORTEX_USE_FPU) +#define CORTEX_USE_FPU CORTEX_HAS_FPU +#elif (CORTEX_USE_FPU == TRUE) && (CORTEX_HAS_FPU == FALSE) +/* This setting requires an FPU presence check in case it is externally + redefined.*/ +#error "the selected core does not have an FPU" +#endif + +/** + * @brief Partial context switching. + * @details This option skips saving FPU registers for those threads that + * do not use FPU. This can make context switch faster but can + * leak information among threads through uninitialized FPU + * registers, possible values: + * - 0: Always full and immediate switching (CONTROL_FPCA enforced). + * - 1: Activate lazy FPU registers stacking (CONTROL_FPCA enforced, + * FPU_FPCCR_LSPEN enabled). + * - 2: Uses short exception context when possible (FPU_FPCCR_ASPEN, + * FPU_FPCCR_LSPEN enabled). + * - 3: Uses short exception context when possible and also omits + * saving s16-s31 when it is not needed (FPU_FPCCR_ASPEN, + * FPU_FPCCR_LSPEN enabled and extra SW checks). + */ +#if !defined(PORT_USE_FPU_FAST_SWITCHING) || defined(__DOXYGEN__) +#define PORT_USE_FPU_FAST_SWITCHING 3 +#endif + +/** + * @brief NVIC PRIGROUP initialization expression. + * @details The default assigns all available priority bits as preemption + * priority with no sub-priority. + * @note Changing this value is not recommended. + */ +#if !defined(PORT_PRIGROUP_INIT) || defined(__DOXYGEN__) +#define PORT_PRIGROUP_INIT (7U - CORTEX_PRIORITY_BITS) +#endif + +/** + * @brief Enables MPU static initialization. + * @details The initialization is performed according to the various + * @p PORT_MPU_MAIRx_INIT, @p PORT_MPU_RBARx_INIT and + * @p PORT_MPU_RLARx_INIT settings. + */ +#if !defined(PORT_MPU_INITIALIZE) || defined(__DOXYGEN__) +#define PORT_MPU_INITIALIZE TRUE +#endif + +/** + * @brief MAIR0 register initialization. + * @note Default values of ATTR0...ATTR3 fields are those expected by the + * SB subsystem, do not change this setting if using SB. + * - ATTR0 is write-back cacheable memory. + * - ATTR1 is write-through cacheable memory. + * - ATTR2 is non-cacheable memory. + * - ATTR3 is device space. + * . + */ +#if !defined(PORT_MPU_MAIR0_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_MAIR0_INIT \ + (MPU_MAIR0_ATTR0(MPU_MAIR_MEM_OUTER_WB_NT_RWA | \ + MPU_MAIR_MEM_INNER_WB_NT_RWA) | \ + MPU_MAIR0_ATTR1(MPU_MAIR_MEM_OUTER_WT_NT_RWA | \ + MPU_MAIR_MEM_INNER_WT_NT_RWA) | \ + MPU_MAIR0_ATTR2(MPU_MAIR_MEM_OUTER_NC | \ + MPU_MAIR_MEM_INNER_NC) | \ + MPU_MAIR0_ATTR3(MPU_MAIR_DEVICE_nGnRE)) +#endif + +/** + * @brief MAIR1 register initialization. + */ +#if !defined(PORT_MPU_MAIR1_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_MAIR1_INIT \ + (MPU_MAIR1_ATTR4(0U) | \ + MPU_MAIR1_ATTR5(0U) | \ + MPU_MAIR1_ATTR6(0U) | \ + MPU_MAIR1_ATTR7(0U)) +#endif + +/** + * @brief RBAR register initialization for region 0. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RBAR0_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RBAR0_INIT 0U +#endif + +/** + * @brief RLAR register initialization for region 0. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RLAR0_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RLAR0_INIT 0U +#endif + +/** + * @brief RBAR register initialization for region 1. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RBAR1_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RBAR1_INIT 0U +#endif + +/** + * @brief RLAR register initialization for region 1. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RLAR1_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RLAR1_INIT 0U +#endif + +/** + * @brief RBAR register initialization for region 2. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RBAR2_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RBAR2_INIT 0U +#endif + +/** + * @brief RLAR register initialization for region 2. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RLAR2_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RLAR2_INIT 0U +#endif + +/** + * @brief RBAR register initialization for region 3. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RBAR3_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RBAR3_INIT 0U +#endif + +/** + * @brief RLAR register initialization for region 3. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RLAR3_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RLAR3_INIT 0U +#endif + +/** + * @brief RBAR register initialization for region 4. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RBAR4_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RBAR4_INIT 0U +#endif + +/** + * @brief RLAR register initialization for region 4. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RLAR4_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RLAR4_INIT 0U +#endif + +/** + * @brief RBAR register initialization for region 5. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RBAR5_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RBAR5_INIT 0U +#endif + +/** + * @brief RLAR register initialization for region 5. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RLAR5_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RLAR5_INIT 0U +#endif + +/** + * @brief RBAR register initialization for region 6. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RBAR6_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RBAR6_INIT 0U +#endif + +/** + * @brief RLAR register initialization for region 6. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RLAR6_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RLAR6_INIT 0U +#endif + +/** + * @brief RBAR register initialization for region 7. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RBAR7_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RBAR7_INIT 0U +#endif + +/** + * @brief RLAR register initialization for region 7. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RLAR7_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RLAR7_INIT 0U +#endif + +/** + * @brief RBAR register initialization for region 8. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RBAR8_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RBAR8_INIT 0U +#endif + +/** + * @brief RLAR register initialization for region 8. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RLAR8_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RLAR8_INIT 0U +#endif + +/** + * @brief RBAR register initialization for region 9. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RBAR9_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RBAR9_INIT 0U +#endif + +/** + * @brief RLAR register initialization for region 9. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RLAR9_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RLAR9_INIT 0U +#endif + +/** + * @brief RBAR register initialization for region 10. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RBAR10_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RBAR10_INIT 0U +#endif + +/** + * @brief RLAR register initialization for region 10. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RLAR10_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RLAR10_INIT 0U +#endif + +/** + * @brief RBAR register initialization for region 11. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RBAR11_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RBAR11_INIT 0U +#endif + +/** + * @brief RLAR register initialization for region 11. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RLAR11_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RLAR11_INIT 0U +#endif + +/** + * @brief RBAR register initialization for region 12. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RBAR12_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RBAR12_INIT 0U +#endif + +/** + * @brief RLAR register initialization for region 12. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RLAR12_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RLAR12_INIT 0U +#endif + +/** + * @brief RBAR register initialization for region 13. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RBAR13_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RBAR13_INIT 0U +#endif + +/** + * @brief RLAR register initialization for region 13. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RLAR13_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RLAR13_INIT 0U +#endif + +/** + * @brief RBAR register initialization for region 14. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RBAR14_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RBAR14_INIT 0U +#endif + +/** + * @brief RLAR register initialization for region 14. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RLAR14_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RLAR14_INIT 0U +#endif + +/** + * @brief RBAR register initialization for region 15. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RBAR15_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RBAR15_INIT 0U +#endif + +/** + * @brief RLAR register initialization for region 15. + * @note Memory regions must not overlap in ARMv8-M. + */ +#if !defined(PORT_MPU_RLAR15_INIT) || defined(__DOXYGEN__) +#define PORT_MPU_RLAR15_INIT 0U +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* Inclusion of SMP support, if enabled.*/ +#if (CH_CFG_SMP_MODE == TRUE) || defined(__DOXYGEN__) +#if !defined(_FROM_ASM_) +#if !defined(__CHIBIOS_RT__) +#error "SMP is supported in RT only" +#endif + +#include "chcoresmp.h" + +#if !defined(PORT_CORES_NUMBER) +#error "PORT_CORES_NUMBER not defined in chcoresmp.h" +#endif + +#endif +#else /* CH_CFG_SMP_MODE != TRUE */ +#endif /* CH_CFG_SMP_MODE != TRUE */ + +#if (PORT_SWITCHED_REGIONS_NUMBER < 0) || (PORT_SWITCHED_REGIONS_NUMBER > 8) + #error "invalid PORT_SWITCHED_REGIONS_NUMBER value" +#endif + +#if (PORT_USE_FPU_FAST_SWITCHING < 0) || (PORT_USE_FPU_FAST_SWITCHING > 3) +#error "invalid PORT_USE_FPU_FAST_SWITCHING value specified" +#endif + +#if (PORT_KERNEL_MODE != PORT_KERNEL_MODE_NORMAL) && \ + (PORT_KERNEL_MODE != PORT_KERNEL_MODE_HOST) && \ + (PORT_KERNEL_MODE != PORT_KERNEL_MODE_GUEST) +#error "invalid PORT_KERNEL_MODE value specified" +#endif + +#if PORT_KERNEL_MODE == PORT_KERNEL_MODE_HOST +#error "PORT_KERNEL_MODE_HOST not supported" +#endif + +#if (PORT_USE_SYSCALL == TRUE) || \ + ((CORTEX_USE_FPU == TRUE) && (PORT_USE_FPU_FAST_SWITCHING >= 2)) || \ + defined(__DOXYGEN__) +/** + * @brief CONTROL as part of the saved thread context. + * @note Saving control is only required when: + * - PORT_USE_SYSCALL is enabled because support for unprivileged + * mode. + * - PORT_USE_FPU is enabled with @p PORT_USE_FPU_FAST_SWITCHING + * modes 2 or 3 because CONTROL.FPCA needs to be handled for + * each thread. + */ +#define PORT_SAVE_CONTROL TRUE +#else +#define PORT_SAVE_CONTROL FALSE +#endif + +/** + * @brief PSPLIM as part of the saved thread context. + */ +#define PORT_SAVE_PSPLIM TRUE + +/** + * @name Architecture + * @{ + */ +/** + * @brief Macro defining a generic ARM architecture. + */ +#define PORT_ARCHITECTURE_ARM + +/** + * @brief Macro defining the specific ARM architecture. + */ +#define PORT_ARCHITECTURE_ARM_V8M_MAINLINE + +/** + * @brief Name of the implemented architecture. + */ +#define PORT_ARCHITECTURE_NAME "ARMv8-M Mainline" + +#if (CORTEX_MODEL == 33) || defined(__DOXYGEN__) + +#if !defined(CH_CUSTOMER_LIC_PORT_CM33) +#error "CH_CUSTOMER_LIC_PORT_CM33 not defined" +#endif + +#if CH_CUSTOMER_LIC_PORT_CM33 == FALSE +#error "ChibiOS Cortex-M33 port not licensed" +#endif + +/** + * @brief Name of the architecture variant. + */ +#if (CORTEX_USE_FPU == TRUE) || defined(__DOXYGEN__) +#define PORT_CORE_VARIANT_NAME "Cortex-M33 with FPU" +#else +#define PORT_CORE_VARIANT_NAME "Cortex-M33" +#endif + +#elif (CORTEX_MODEL == 55) || defined(__DOXYGEN__) + +#if !defined(CH_CUSTOMER_LIC_PORT_CM55) +#error "CH_CUSTOMER_LIC_PORT_CM55 not defined" +#endif + +#if CH_CUSTOMER_LIC_PORT_CM55 == FALSE +#error "ChibiOS Cortex-M55 port not licensed" +#endif + +/** + * @brief Name of the architecture variant. + */ +#if CORTEX_USE_FPU || defined(__DOXYGEN__) +#define PORT_CORE_VARIANT_NAME "Cortex-M55 with FPU" +#else +#define PORT_CORE_VARIANT_NAME "Cortex-M55" +#endif + +#else +#error "unknown ARMv8-M core variant" +#endif + +#if (PORT_KERNEL_MODE == PORT_KERNEL_MODE_NORMAL) || defined (__DOXYGEN__) +/** + * @brief Port-specific information string. + */ +#define PORT_INFO "Normal mode without TZ" +#elif PORT_KERNEL_MODE == PORT_KERNEL_MODE_HOST +#define PORT_INFO "TZ guest mode" +#elif PORT_KERNEL_MODE == PORT_KERNEL_MODE_GUEST +#define PORT_INFO "TZ guest mode" +#else +#error "invalid kernel security mode" +#endif +/** @} */ + +/** + * @name Priorities + * @{ + */ +/** + * @brief Priority level to priority mask conversion macro. + */ +#define CORTEX_PRIO_MASK(n) ((n) << (8U - CORTEX_PRIORITY_BITS)) + +/** + * @brief Disabled value for BASEPRI register. + */ +#define CORTEX_BASEPRI_DISABLED CORTEX_PRIO_MASK(0U) + +/** + * @brief BASEPRI level within kernel lock. + */ +#define CORTEX_BASEPRI_KERNEL CORTEX_PRIO_MASK(CORTEX_MAX_KERNEL_PRIORITY) + +/** + * @brief Total priority levels. + */ +#define CORTEX_PRIORITY_LEVELS (1U << CORTEX_PRIORITY_BITS) + +/** + * @brief Minimum priority level. + * @details This minimum priority level is calculated from the number of + * priority bits supported by the specific Cortex-Mx implementation. + */ +#define CORTEX_MINIMUM_PRIORITY (CORTEX_PRIORITY_LEVELS - 1U) + +/** + * @brief Maximum priority level. + * @details The maximum allowed priority level is always zero. + */ +#define CORTEX_MAXIMUM_PRIORITY 0U + +#if (PORT_KERNEL_MODE == PORT_KERNEL_MODE_NORMAL) || defined (__DOXYGEN__) +/** + * @brief SVCALL handler priority. + */ +#define CORTEX_PRIORITY_SVCALL (CORTEX_MAXIMUM_PRIORITY + \ + PORT_FAST_PRIORITIES) + +/** + * @brief PENDSV handler priority. + */ +#define CORTEX_PRIORITY_PENDSV (CORTEX_MINIMUM_PRIORITY) + +/** + * @brief Maximum usable priority for normal ISRs. + * @note Must be lower than @p CORTEX_PRIORITY_SVCALL. + */ +#define CORTEX_MAX_KERNEL_PRIORITY (CORTEX_PRIORITY_SVCALL + 1U) + +/** + * @brief Minimum usable priority for normal ISRs. + */ +#define CORTEX_MIN_KERNEL_PRIORITY (CORTEX_PRIORITY_PENDSV - 1U) + +#elif PORT_KERNEL_MODE == PORT_KERNEL_MODE_HOST + +/* TBD */ + +#elif PORT_KERNEL_MODE == PORT_KERNEL_MODE_GUEST +#define CORTEX_PRIORITY_SVCALL (CORTEX_MAXIMUM_PRIORITY + \ + PORT_FAST_PRIORITIES) +#define CORTEX_PRIORITY_PENDSV (CORTEX_MINIMUM_PRIORITY & 0xFFFFFFFEU) +#define CORTEX_MAX_KERNEL_PRIORITY ((CORTEX_PRIORITY_SVCALL | 1U) + 1U) +#define CORTEX_MIN_KERNEL_PRIORITY ((CORTEX_PRIORITY_PENDSV - 1U) & 0xFFFFFFFEU) +#else + /* Note, checked above.*/ +#endif +/** @} */ + +#if (PORT_FAST_PRIORITIES < 0U) || \ + (PORT_FAST_PRIORITIES > (CORTEX_PRIORITY_LEVELS / 4U)) +#error "invalid PORT_FAST_PRIORITIES value specified" +#endif + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +/** + * @brief Type of an MPU region registers structure. + * + */ +typedef struct { + uint32_t rbar; + uint32_t rlar; +} port_mpureg_t; + +/** + * @brief Integer-only external context. + */ +struct port_short_extctx { + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r12; + uint32_t lr_thd; + uint32_t pc; + uint32_t xpsr; +}; + +/** + * @brief Interrupt saved context. + * @details This structure represents the stack frame saved during a + * preemption-capable interrupt handler. + */ +struct port_extctx { + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r12; + uint32_t lr_thd; + uint32_t pc; + uint32_t xpsr; +#if (CORTEX_USE_FPU == TRUE) || defined(__DOXYGEN__) + uint32_t s0; + uint32_t s1; + uint32_t s2; + uint32_t s3; + uint32_t s4; + uint32_t s5; + uint32_t s6; + uint32_t s7; + uint32_t s8; + uint32_t s9; + uint32_t s10; + uint32_t s11; + uint32_t s12; + uint32_t s13; + uint32_t s14; + uint32_t s15; + uint32_t fpscr; + uint32_t reserved; +#endif /* CORTEX_USE_FPU == TRUE */ +}; + +/** + * @brief System saved context. + * @details This structure represents the inner context during a context + * switch. + */ +struct port_intctx { + /* Integer and special registers context.*/ + uint32_t basepri; + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r7; + uint32_t r8; + uint32_t r9; + uint32_t r10; + uint32_t r11; + uint32_t lr_exc; + /* Special registers context.*/ + uint32_t splim; +#if (PORT_SAVE_CONTROL == TRUE) || defined(__DOXYGEN__) + uint32_t control; +#endif +#if (CORTEX_USE_FPU == TRUE) || defined(__DOXYGEN__) + /* Floating point registers context.*/ + uint32_t s16; + uint32_t s17; + uint32_t s18; + uint32_t s19; + uint32_t s20; + uint32_t s21; + uint32_t s22; + uint32_t s23; + uint32_t s24; + uint32_t s25; + uint32_t s26; + uint32_t s27; + uint32_t s28; + uint32_t s29; + uint32_t s30; + uint32_t s31; +#endif /* CORTEX_USE_FPU == TRUE */ +}; + +/** + * @brief Platform dependent part of the @p thread_t structure. + * @details In this port the structure just holds a pointer to the + * @p port_intctx structure representing the stack pointer + * at context switch time. + */ +struct port_context { + struct port_extctx *sp; + struct port_intctx regs; +#if (PORT_SWITCHED_REGIONS_NUMBER > 0) || defined(__DOXYGEN__) + port_mpureg_t regions[PORT_SWITCHED_REGIONS_NUMBER]; +#endif +}; + +#endif /* !defined(_FROM_ASM_) */ + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @brief Priority level verification macro. + */ +#define PORT_IRQ_IS_VALID_PRIORITY(n) \ + (((n) >= 0U) && ((n) < CORTEX_PRIORITY_LEVELS)) + +/** + * @brief Priority level verification macro. + */ +#define PORT_IRQ_IS_VALID_KERNEL_PRIORITY(n) \ + (((n) >= CORTEX_MAX_KERNEL_PRIORITY) && ((n) <= CORTEX_MIN_KERNEL_PRIORITY)) + +/** + * @brief Optimized thread function declaration macro. + */ +#define PORT_THD_FUNCTION(tname, arg) void tname(void *arg) + +/** + * @brief Exception return value for threads creation. + * @note Enforcing a long context when FPU is enabled else using a + * short context. + */ +#if (PORT_KERNEL_MODE == PORT_KERNEL_MODE_NORMAL) || \ + (PORT_KERNEL_MODE == PORT_KERNEL_MODE_HOST) || defined (__DOXYGEN__) + #if (CORTEX_USE_FPU == TRUE) || defined(__DOXYGEN__) + #define CORTEX_EXC_RETURN 0xFFFFFFEDU + #else + #define CORTEX_EXC_RETURN 0xFFFFFFFDU + #endif +#elif PORT_KERNEL_MODE == PORT_KERNEL_MODE_GUEST + #if CORTEX_USE_FPU == TRUE + #define CORTEX_EXC_RETURN 0xFFFFFFACU + #else + #define CORTEX_EXC_RETURN 0xFFFFFFBCU + #endif +#endif + +/** + * @brief Initialization of CONTROL part of thread context. + */ +#if (PORT_SAVE_CONTROL == TRUE) || defined(__DOXYGEN__) + #if (CORTEX_USE_FPU == TRUE) || defined(__DOXYGEN__) + #define __PORT_SETUP_CONTEXT_CONTROL(tp) \ + (tp)->ctx.regs.control = CONTROL_FPCA_Msk + #else + #define __PORT_SETUP_CONTEXT_CONTROL(tp) \ + (tp)->ctx.regs.control = 0U + #endif +#else + #define __PORT_SETUP_CONTEXT_CONTROL(tp) +#endif + +/** + * @brief Initialization of stack check part of thread context. + */ +#define __PORT_SETUP_CONTEXT_SPLIM(tp, wbase) \ + (tp)->ctx.regs.splim = (uint32_t)(wbase) + +/** + * @brief Initialization of FPU part of thread context. + * @note The value of FPDSCR is used, it is meant to be the default. + */ +#if (CORTEX_USE_FPU == TRUE) || defined(__DOXYGEN__) + #define __PORT_SETUP_CONTEXT_FPU(tp) \ + (tp)->ctx.sp->fpscr = FPU->FPDSCR +#else + #define __PORT_SETUP_CONTEXT_FPU(tp) +#endif + +/** + * @brief Initialization of MPU part of thread context. + */ +#if (PORT_SWITCHED_REGIONS_NUMBER == 0) || defined(__DOXYGEN__) + #define __PORT_SETUP_CONTEXT_MPU(tp) + +#elif (PORT_SWITCHED_REGIONS_NUMBER == 1) || defined(__DOXYGEN__) + #define __PORT_SETUP_CONTEXT_MPU(tp) \ + (tp)->ctx.regions[0].rbar = 0U; \ + (tp)->ctx.regions[0].rlar = 0U + +#elif (PORT_SWITCHED_REGIONS_NUMBER == 2) || defined(__DOXYGEN__) + #define __PORT_SETUP_CONTEXT_MPU(tp) \ + (tp)->ctx.regions[0].rbar = 0U; \ + (tp)->ctx.regions[0].rlar = 0U; \ + (tp)->ctx.regions[1].rbar = 0U; \ + (tp)->ctx.regions[1].rlar = 0U + +#elif (PORT_SWITCHED_REGIONS_NUMBER == 3) || defined(__DOXYGEN__) + #define __PORT_SETUP_CONTEXT_MPU(tp) \ + (tp)->ctx.regions[0].rbar = 0U; \ + (tp)->ctx.regions[0].rlar = 0U; \ + (tp)->ctx.regions[1].rbar = 0U; \ + (tp)->ctx.regions[1].rlar = 0U; \ + (tp)->ctx.regions[2].rbar = 0U; \ + (tp)->ctx.regions[2].rlar = 0U + +#elif (PORT_SWITCHED_REGIONS_NUMBER == 4) || defined(__DOXYGEN__) + #define __PORT_SETUP_CONTEXT_MPU(tp) \ + (tp)->ctx.regions[0].rbar = 0U; \ + (tp)->ctx.regions[0].rlar = 0U; \ + (tp)->ctx.regions[1].rbar = 0U; \ + (tp)->ctx.regions[1].rlar = 0U; \ + (tp)->ctx.regions[2].rbar = 0U; \ + (tp)->ctx.regions[2].rlar = 0U; \ + (tp)->ctx.regions[3].rbar = 0U; \ + (tp)->ctx.regions[3].rlar = 0U + +#elif (PORT_SWITCHED_REGIONS_NUMBER == 5) || defined(__DOXYGEN__) + #define __PORT_SETUP_CONTEXT_MPU(tp) \ + (tp)->ctx.regions[0].rbar = 0U; \ + (tp)->ctx.regions[0].rlar = 0U; \ + (tp)->ctx.regions[1].rbar = 0U; \ + (tp)->ctx.regions[1].rlar = 0U; \ + (tp)->ctx.regions[2].rbar = 0U; \ + (tp)->ctx.regions[2].rlar = 0U; \ + (tp)->ctx.regions[3].rbar = 0U; \ + (tp)->ctx.regions[3].rlar = 0U; \ + (tp)->ctx.regions[4].rbar = 0U; \ + (tp)->ctx.regions[4].rlar = 0U + +#elif (PORT_SWITCHED_REGIONS_NUMBER == 6) || defined(__DOXYGEN__) + #define __PORT_SETUP_CONTEXT_MPU(tp) \ + (tp)->ctx.regions[0].rbar = 0U; \ + (tp)->ctx.regions[0].rlar = 0U; \ + (tp)->ctx.regions[1].rbar = 0U; \ + (tp)->ctx.regions[1].rlar = 0U; \ + (tp)->ctx.regions[2].rbar = 0U; \ + (tp)->ctx.regions[2].rlar = 0U; \ + (tp)->ctx.regions[3].rbar = 0U; \ + (tp)->ctx.regions[3].rlar = 0U; \ + (tp)->ctx.regions[4].rbar = 0U; \ + (tp)->ctx.regions[4].rlar = 0U; \ + (tp)->ctx.regions[5].rbar = 0U; \ + (tp)->ctx.regions[5].rlar = 0U + +#elif (PORT_SWITCHED_REGIONS_NUMBER == 7) || defined(__DOXYGEN__) + #define __PORT_SETUP_CONTEXT_MPU(tp) \ + (tp)->ctx.regions[0].rbar = 0U; \ + (tp)->ctx.regions[0].rlar = 0U; \ + (tp)->ctx.regions[1].rbar = 0U; \ + (tp)->ctx.regions[1].rlar = 0U; \ + (tp)->ctx.regions[2].rbar = 0U; \ + (tp)->ctx.regions[2].rlar = 0U; \ + (tp)->ctx.regions[3].rbar = 0U; \ + (tp)->ctx.regions[3].rlar = 0U; \ + (tp)->ctx.regions[4].rbar = 0U; \ + (tp)->ctx.regions[4].rlar = 0U; \ + (tp)->ctx.regions[5].rbar = 0U; \ + (tp)->ctx.regions[5].rlar = 0U; \ + (tp)->ctx.regions[6].rbar = 0U; \ + (tp)->ctx.regions[6].rlar = 0U + +#elif (PORT_SWITCHED_REGIONS_NUMBER == 8) || defined(__DOXYGEN__) + #define __PORT_SETUP_CONTEXT_MPU(tp) \ + (tp)->ctx.regions[0].rbar = 0U; \ + (tp)->ctx.regions[0].rlar = 0U; \ + (tp)->ctx.regions[1].rbar = 0U; \ + (tp)->ctx.regions[1].rlar = 0U; \ + (tp)->ctx.regions[2].rbar = 0U; \ + (tp)->ctx.regions[2].rlar = 0U; \ + (tp)->ctx.regions[3].rbar = 0U; \ + (tp)->ctx.regions[3].rlar = 0U; \ + (tp)->ctx.regions[4].rbar = 0U; \ + (tp)->ctx.regions[4].rlar = 0U; \ + (tp)->ctx.regions[5].rbar = 0U; \ + (tp)->ctx.regions[5].rlar = 0U; \ + (tp)->ctx.regions[6].rbar = 0U; \ + (tp)->ctx.regions[6].rlar = 0U; \ + (tp)->ctx.regions[7].rbar = 0U; \ + (tp)->ctx.regions[7].rlar = 0U + +#else + /* Note, checked above.*/ +#endif + +/** + * @brief Platform dependent part of the thread creation API. + */ +#define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) do { \ + (tp)->ctx.sp = (struct port_extctx *)(void *) \ + ((uint8_t *)(wtop) - sizeof (struct port_extctx)); \ + (tp)->ctx.regs.basepri = CORTEX_BASEPRI_KERNEL; \ + (tp)->ctx.regs.r4 = (uint32_t)(pf); \ + (tp)->ctx.regs.r5 = (uint32_t)(arg); \ + (tp)->ctx.regs.lr_exc = (uint32_t)CORTEX_EXC_RETURN; \ + (tp)->ctx.sp->pc = (uint32_t)__port_thread_start; \ + (tp)->ctx.sp->xpsr = (uint32_t)0x01000000; \ + __PORT_SETUP_CONTEXT_SPLIM(tp, wbase); \ + __PORT_SETUP_CONTEXT_CONTROL(tp); \ + __PORT_SETUP_CONTEXT_FPU(tp); \ + __PORT_SETUP_CONTEXT_MPU(tp); \ +} while (false) + +/** + * @brief Context switch area size. + */ +#define PORT_WA_CTX_SIZE sizeof (struct port_extctx) + +/** + * @brief Computes the thread working area global size. + * @note There is no need to perform alignments in this macro. + */ +#define PORT_WA_SIZE(n) ((size_t)PORT_WA_CTX_SIZE + \ + (size_t)(n) + \ + (size_t)PORT_INT_REQUIRED_STACK) + +/** + * @brief Static working area allocation. + * @details This macro is used to allocate a static thread working area + * aligned as both position and size. + * + * @param[in] s the name to be assigned to the stack array + * @param[in] n the stack size to be assigned to the thread + */ +#define PORT_WORKING_AREA(s, n) \ + ALIGNED_VAR(PORT_WORKING_AREA_ALIGN) \ + stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)] + +/** + * @brief IRQ prologue code. + * @details This macro must be inserted at the start of all IRQ handlers + * enabled to invoke system APIs. + */ +#define PORT_IRQ_PROLOGUE() + +/** + * @brief IRQ epilogue code. + * @details This macro must be inserted at the end of all IRQ handlers + * enabled to invoke system APIs. + */ +#if 0 +#define PORT_IRQ_EPILOGUE() do { \ + port_lock_from_isr(); \ + if (chSchIsPreemptionRequired()) { \ + SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; \ + } \ + port_unlock_from_isr(); \ +} while (false) +#else +#define PORT_IRQ_EPILOGUE() do { \ + SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; \ +} while (false) +#endif + +/** + * @brief IRQ handler function declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + */ +#ifdef __cplusplus + #define PORT_IRQ_HANDLER(id) extern "C" void id(void) + +#else + #define PORT_IRQ_HANDLER(id) void id(void) +#endif + +/** + * @brief Fast IRQ handler function declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + */ +#ifdef __cplusplus + #define PORT_FAST_IRQ_HANDLER(id) extern "C" void id(void) + +#else + #define PORT_FAST_IRQ_HANDLER(id) void id(void) +#endif + +/** + * @brief Performs a context switch between two threads. + * @details This is the most critical code in any port, this function + * is responsible for the context switch between 2 threads. + * @note The implementation of this code affects directly the context + * switch performance so optimize here as much as you can. + * + * @param[in] ntp the thread to be switched in + * @param[in] otp the thread to be switched out + */ +/*lint -e438 -e529 -e586 [4.3, 2.2] The keyword is required, parameters are + referenced by the final asm and are used.*/ +#define port_switch(ntp, otp) do { \ + register thread_t *_ntp asm ("r0") = (ntp); \ + register thread_t *_otp asm ("r1") = (otp); \ + asm volatile ("svc #0" : : "r" (_otp), "r" (_ntp) : "memory"); \ +} while (false) + +/** + * @brief Returns a word representing a critical section status. + * + * @return The critical section status. + */ +#define port_get_lock_status() __port_get_irq_status() + +/** + * @brief Determines if in a critical section. + * + * @param[in] sts status word returned by @p port_get_lock_status() + * @return The current status. + * @retval false if running outside a critical section. + * @retval true if running within a critical section. + */ +#define port_is_locked(sts) !__port_irq_enabled(sts) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(_FROM_ASM_) + +#ifdef __cplusplus +extern "C" { +#endif + void port_init(os_instance_t *oip); + void __port_thread_start(void); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/*lint -save -e718 -e746 [17.3] The MISRA parser cannot see the function + declarations in CMSIS headers, CMSIS parsing is disabled in those headers + because the whole thing is not MISRA compliant and it is not uder our + control.*/ + +/** + * @brief Returns a word encoding the current interrupts status. + * + * @return The interrupts status. + */ +__STATIC_FORCEINLINE syssts_t __port_get_irq_status(void) { + + return (syssts_t)__get_BASEPRI(); +} + +/** + * @brief Checks the interrupt status. + * + * @param[in] sts the interrupt status word + * + * @return The interrupt status. + * @retval false the word specified a disabled interrupts status. + * @retval true the word specified an enabled interrupts status. + */ +__STATIC_FORCEINLINE bool __port_irq_enabled(syssts_t sts) { + + return (bool)(sts == (syssts_t)CORTEX_BASEPRI_DISABLED); +} + +/** + * @brief Determines the current execution context. + * + * @return The execution context. + * @retval false not running in ISR mode. + * @retval true running in ISR mode. + */ +__STATIC_FORCEINLINE bool port_is_isr_context(void) { + + return (bool)((__get_IPSR() & 0x1FFU) != 0U); +} + +/** + * @brief Kernel-lock action. + * @details In this port this function raises the base priority to kernel + * level. + */ +__STATIC_FORCEINLINE void port_lock(void) { + + __set_BASEPRI(CORTEX_BASEPRI_KERNEL); +#if CH_CFG_SMP_MODE == TRUE + port_spinlock_take(); +#endif +} + +/** + * @brief Kernel-unlock action. + * @details In this port this function lowers the base priority to user + * level. + */ +__STATIC_FORCEINLINE void port_unlock(void) { + +#if CH_CFG_SMP_MODE == TRUE + port_spinlock_release(); +#endif + __set_BASEPRI(CORTEX_BASEPRI_DISABLED); +} + +/** + * @brief Kernel-lock action from an interrupt handler. + * @details In this port this function raises the base priority to kernel + * level. + * @note Same as @p port_lock() in this port. + */ +__STATIC_FORCEINLINE void port_lock_from_isr(void) { + + port_lock(); +} + +/** + * @brief Kernel-unlock action from an interrupt handler. + * @details In this port this function lowers the base priority to user + * level. + * @note Same as @p port_unlock() in this port. + */ +__STATIC_FORCEINLINE void port_unlock_from_isr(void) { + + port_unlock(); +} + +/** + * @brief Disables all the interrupt sources. + * @note In this port it disables all the interrupt sources by raising + * the priority mask to level 0. + */ +__STATIC_FORCEINLINE void port_disable(void) { + + __disable_irq(); +} + +/** + * @brief Disables the interrupt sources below kernel-level priority. + * @note Interrupt sources above kernel level remains enabled. + * @note In this port it raises/lowers the base priority to kernel level. + */ +__STATIC_FORCEINLINE void port_suspend(void) { + + __set_BASEPRI(CORTEX_BASEPRI_KERNEL); + __enable_irq(); +} + +/** + * @brief Enables all the interrupt sources. + * @note In this port it lowers the base priority to user level. + */ +__STATIC_FORCEINLINE void port_enable(void) { + + __set_BASEPRI(CORTEX_BASEPRI_DISABLED); + __enable_irq(); +} + +/** + * @brief Enters an architecture-dependent IRQ-waiting mode. + * @details The function is meant to return when an interrupt becomes pending. + * The simplest implementation is an empty function or macro but this + * would not take advantage of architecture-specific power saving + * modes. + * @note Implemented as an inlined @p WFI instruction. + */ +__STATIC_FORCEINLINE void port_wait_for_interrupt(void) { + +#if PORT_ENABLE_WFI_IDLE == TRUE + __WFI(); +#endif +} + +#if !defined(port_rt_get_counter_value) +/** + * @brief Returns the current value of the realtime counter. + * + * @return The realtime counter value. + */ +__STATIC_FORCEINLINE rtcnt_t port_rt_get_counter_value(void) { + + return DWT->CYCCNT; +} +#endif + +/*lint -restore*/ + +#endif /* !defined(_FROM_ASM_) */ + +/*===========================================================================*/ +/* Module late inclusions. */ +/*===========================================================================*/ + +#if !defined(_FROM_ASM_) + +#if CH_CFG_ST_TIMEDELTA > 0 +#if (CH_CFG_SMP_MODE == TRUE) && (PORT_CORES_NUMBER > 1) +#include "chcoresmp_timer.h" +#else +#include "chcore_timer.h" +#endif +#endif /* CH_CFG_ST_TIMEDELTA > 0 */ + +#endif /* !defined(_FROM_ASM_) */ + +#endif /* CHCORE_H */ + +/** @} */ diff --git a/os/common/ports/ARMv8-M-ML-ALT/compilers/GCC/chcoreasm.S b/os/common/ports/ARMv8-M-ML-ALT/compilers/GCC/chcoreasm.S new file mode 100644 index 0000000000..4f39242f2f --- /dev/null +++ b/os/common/ports/ARMv8-M-ML-ALT/compilers/GCC/chcoreasm.S @@ -0,0 +1,406 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation version 3 of the License. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ARMv8-M-ML-ALT/compilers/GCC/chcoreasm.S + * @brief ARMv8-M MainLine (alt) architecture port low level code. + * + * @addtogroup ARMV8M_ML_ALT_GCC_CORE + * @{ + */ + +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE 1 +#endif + +#define _FROM_ASM_ +#include "chlicense.h" +#include "chconf.h" +#include "chcore.h" + +#if !defined(__DOXYGEN__) + +/* + * RTOS-specific context offset. + */ +#if defined(_CHIBIOS_RT_CONF_) +#define CURRENT_OFFSET 12 +#define CONTEXT_OFFSET 12 + +#elif defined(_CHIBIOS_NIL_CONF_) +#define CURRENT_OFFSET 0 /* nil.current */ +#define CONTEXT_OFFSET 0 + +#else +#error "invalid chconf.h" +#endif + +/* MPU-related constants.*/ +#define MPU_RNR 0xE000ED98 +#define MPU_RBAR 0xE000ED9C +#define MPU_RLAR 0xE000EDA0 + +/* Calculating the MPU regions array offset within the port_context + structure.*/ +#if CORTEX_USE_FPU + #if PORT_SAVE_CONTROL + #define MPU_OFFSET 116 + #else + #define MPU_OFFSET 112 + #endif +#else + #if PORT_SAVE_CONTROL + #define MPU_OFFSET 52 + #else + #define MPU_OFFSET 48 + #endif +#endif + + .syntax unified + .cpu cortex-m33 +#if CORTEX_USE_FPU + .fpu fpv5-sp-d16 +#else + .fpu softvfp +#endif + + .thumb + .text + +/*--------------------------------------------------------------------------* + * Context switch macros depending on various options. + *--------------------------------------------------------------------------*/ + + /* Store integer context through R1. + On entry R2=PSP, R3=BASEPRI.*/ + .macro PORT_STORE_INTEGER_CONTEXT + stmia r1!, {r2-r11,lr} + .endm + + /* Load integer context through R0.*/ + .macro PORT_LOAD_INTEGER_CONTEXT + ldmia r0!, {r2-r11,lr} + msr PSP, r2 + msr BASEPRI, r3 + .endm + + /* Store special registers context through R1. + On entry R12=CONTROL.*/ + .macro PORT_STORE_SPECIAL_CONTEXT + mrs r2, PSPLIM +#if PORT_SAVE_CONTROL + stmia r1!, {r2, r12} +#else + stmia r1!, {r2} +#endif + .endm + + /* Load special context through R0.*/ + .macro PORT_LOAD_SPECIAL_CONTEXT +#if PORT_SAVE_CONTROL + ldmia r0!, {r2, r12} + msr PSPLIM, r2 + msr CONTROL, r12 +#else + ldmia r0!, {r2} + msr PSPLIM, r2 +#endif + .endm + + /* Store float context through R1.*/ + .macro PORT_STORE_FLOAT_CONTEXT +#if CORTEX_USE_FPU +#if PORT_USE_FPU_FAST_SWITCHING > 2 + tst lr, #16 + it eq + vstmiaeq r1!, {s16-s31} +#else + vstmia r1!, {s16-s31} +#endif +#endif + .endm + + /* Load float context through R0.*/ + .macro PORT_LOAD_FLOAT_CONTEXT +#if CORTEX_USE_FPU +#if PORT_USE_FPU_FAST_SWITCHING > 2 + tst lr, #16 + it eq + vldmiaeq r0!, {s16-s31} +#else + vldmia r0!, {s16-s31} +#endif +#endif + .endm + + /* Store MPU context through R1.*/ + .macro PORT_STORE_MPU_CONTEXT +#if PORT_SWITCHED_REGIONS_NUMBER > 0 + ldr r2, =MPU_RBAR + mov r3, #0 + str r3, [r2, #-4] /* RNR */ +#if PORT_SWITCHED_REGIONS_NUMBER == 1 + ldm r2, {r4-r5} /* RBAR0, RLAR0 */ + stmia r1!, {r4-r5} +#elif PORT_SWITCHED_REGIONS_NUMBER == 2 + ldm r2, {r4-r7} /* RBAR0, RLAR0 ... RBAR1, RLAR1 */ + stmia r1!, {r4-r7} /* RBAR0, RLAR0 ... RBAR1, RLAR1 */ +#elif PORT_SWITCHED_REGIONS_NUMBER == 3 + ldm r2, {r4-r9} /* RBAR0, RLAR0 ... RBAR2, RLAR2 */ + stmia r1!, {r4-r9} /* RBAR0, RLAR0 ... RBAR2, RLAR2 */ +#else + ldm r2, {r4-r11} /* RBAR0, RLAR0 ... RBAR3, RLAR3 */ + stmia r1!, {r4-r11} /* RBAR0, RLAR0 ... RBAR3, RLAR3 */ +#endif +#endif /* PORT_SWITCHED_REGIONS_NUMBER > 0 */ +#if PORT_SWITCHED_REGIONS_NUMBER > 4 + mov r3, #4 + str r3, [r2, #-4] /* RNR */ +#if PORT_SWITCHED_REGIONS_NUMBER == 5 + ldm r2, {r4-r5} /* RBAR4, RLAR4 */ + stmia r1!, {r4-r5} +#elif PORT_SWITCHED_REGIONS_NUMBER == 6 + ldm r2, {r4-r7} /* RBAR4, RLAR4 ... RBAR5, RLAR5 */ + stmia r1!, {r4-r7} /* RBAR4, RLAR4 ... RBAR5, RLAR5 */ +#elif PORT_SWITCHED_REGIONS_NUMBER == 7 + ldm r2, {r4-r9} /* RBAR4, RLAR4 ... RBAR6, RLAR6 */ + stmia r1!, {r4-r9} /* RBAR4, RLAR4 ... RBAR6, RLAR6 */ +#else + ldm r2, {r4-r11} /* RBAR4, RLAR4 ... RBAR7, RLAR7 */ + stmia r1!, {r4-r11} /* RBAR4, RLAR4 ... RBAR7, RLAR7 */ +#endif +#endif /* PORT_SWITCHED_REGIONS_NUMBER > 4 */ + .endm + + /* Load MPU context through R0.*/ + .macro PORT_LOAD_MPU_CONTEXT +#if PORT_SWITCHED_REGIONS_NUMBER > 0 + add r1, r0, #MPU_OFFSET + ldr r2, =MPU_RNR + mov r3, #0 +#if PORT_SWITCHED_REGIONS_NUMBER == 1 + ldmia r1!, {r4-r5} /* RBAR0, RLAR0 */ + stm r2, {r3-r5} /* RNR, RBAR0, RLAR0 */ +#elif PORT_SWITCHED_REGIONS_NUMBER == 2 + ldmia r1!, {r4-r7} /* RBAR0, RLAR0 ... RBAR1, RLAR1 */ + stm r2, {r3-r7} /* RNR, RBAR0, RLAR0 ... RBAR1, RLAR1 */ +#elif PORT_SWITCHED_REGIONS_NUMBER == 3 + ldmia r1!, {r4-r9} /* RBAR0, RLAR0 ... RBAR2, RLAR2 */ + stm r2, {r3-r9} /* RNR, RBAR0, RLAR0 ... RBAR2, RLAR2 */ +#else + ldmia r1!, {r4-r11} /* RBAR0, RLAR0 ... RBAR3, RLAR3 */ + stm r2, {r3-r11} /* RNR, RBAR0, RLAR0 ... RBAR3, RLAR3 */ +#endif +#endif /* PORT_SWITCHED_REGIONS_NUMBER > 0 */ +#if PORT_SWITCHED_REGIONS_NUMBER > 4 + mov r3, #4 +#if PORT_SWITCHED_REGIONS_NUMBER == 5 + ldmia r1!, {r4-r5} /* RBAR4, RLAR4 */ + stm r2, {r3-r5} /* RNR, RBAR4, RLAR4 */ +#elif PORT_SWITCHED_REGIONS_NUMBER == 6 + ldmia r1!, {r4-r7} /* RBAR4, RLAR4 ... RBAR5, RLAR5 */ + stm r2, {r3-r7} /* RNR, RBAR4, RLAR4 ... RBAR5, RLAR5 */ +#elif PORT_SWITCHED_REGIONS_NUMBER == 7 + ldmia r1!, {r4-r9} /* RBAR4, RLAR4 ... RBAR6, RLAR6 */ + stm r2, {r3-r9} /* RNR, RBAR4, RLAR4 ... RBAR6, RLAR6 */ +#else + ldmia r1!, {r4-r11} /* RBAR4, RLAR4 ... RBAR7, RLAR7 */ + stm r2, {r3-r11} /* RNR, RBAR4, RLAR4 ... RBAR7, RLAR7 */ +#endif +#endif /* PORT_SWITCHED_REGIONS_NUMBER > 4 */ + .endm + +/*--------------------------------------------------------------------------* + * Performs a context switch between two threads using SVC. + *--------------------------------------------------------------------------*/ + .thumb_func + .globl SVC_Handler +SVC_Handler: +#if PORT_USE_SYSCALL + mrs r12, CONTROL + tst r12, #1 + beq .Lfrompriv + /* SVC called from non-privileged mode for a syscall.*/ + /* Note, LR already contains the return address.*/ + mrs r1, PSP /* Position of the exc.frame.*/ + ldr r3, [r1, #24] /* PC position.*/ + ldrb r0, [r3, #-2] /* SVC parameter.*/ + cmp r0, #0x80 + blt __port_do_fastcall_entry + bic r12, #1 + msr CONTROL, r12 /* Switching to privileged.*/ + b __port_do_syscall_entry + +.Lfrompriv: + /* SVC called from privileged mode for unprivileged return.*/ + mrs r2, PSP /* Position of the exc.frame.*/ + ldr r3, [r2, #24] /* PC position.*/ + ldrb r3, [r3, #-2] /* SVC immediate.*/ + cbz r3, .Lctxswitch + /* Called for non-privileged mode change.*/ + orr r12, #1 + msr CONTROL, r12 /* Switching to non-privileged. */ + b __port_do_syscall_return + +.Lctxswitch: + /* SVC called from privilege mode for context switch.*/ +#else +#if PORT_SAVE_CONTROL + mrs r12, CONTROL +#endif + mrs r2, PSP /* Position of the exc.frame.*/ +#endif + /* Retrieving pointers to old and new context from the + saved stack frame.*/ + ldmia r2, {r0, r1} /* R0/R1 on SVC context (ntp/otp) */ + adds r1, #CONTEXT_OFFSET + adds r0, #CONTEXT_OFFSET + + /* Context store for old thread through R1.*/ + mrs r3, BASEPRI + PORT_STORE_INTEGER_CONTEXT + PORT_STORE_SPECIAL_CONTEXT + PORT_STORE_FLOAT_CONTEXT + PORT_STORE_MPU_CONTEXT + +#if CH_DBG_SYSTEM_STATE_CHECK || CH_DBG_STATISTICS || CH_CFG_SMP_MODE + ldr r3, [r0, #4] /* BASEPRI offset */ + cmp r3, #0 /* CORTEX_BASEPRI_DISABLED */ + bne 1f + mov r4, r0 + /* Returning to a preempted thread, performing a logical + "unlock", handling statistics and releasing spinlock.*/ +#if CH_DBG_SYSTEM_STATE_CHECK + bl __dbg_check_unlock +#endif +#if CH_DBG_STATISTICS + bl __stats_stop_measure_crit_thd +#endif +#if CH_CFG_SMP_MODE == TRUE + bl __port_spinlock_release +#endif + mov r0, r4 +1: +#endif /* CH_DBG_SYSTEM_STATE_CHECK || CH_DBG_STATISTICS || CH_CFG_SMP_MODE */ + + /* Context load for new thread through R0.*/ + PORT_LOAD_MPU_CONTEXT + PORT_LOAD_INTEGER_CONTEXT + PORT_LOAD_SPECIAL_CONTEXT + PORT_LOAD_FLOAT_CONTEXT + + bx lr + +/*--------------------------------------------------------------------------* + * Tail preemption check using PENDSV. + *--------------------------------------------------------------------------*/ + .thumb_func + .globl PendSV_Handler +PendSV_Handler: + push {r3, lr} + + bl __port_schedule_next + cmp r0, #0 + it eq + popeq {r3, pc} + pop {r3, lr} + + /* Context store for old thread through R1.*/ + adds r1, #CONTEXT_OFFSET + + mrs r2, PSP + mov r3, #0 /* CORTEX_BASEPRI_DISABLED */ +#if PORT_SAVE_CONTROL + mrs r12, CONTROL +#endif + PORT_STORE_INTEGER_CONTEXT + PORT_STORE_SPECIAL_CONTEXT + PORT_STORE_FLOAT_CONTEXT + PORT_STORE_MPU_CONTEXT + + /* Context load for new thread through R0.*/ + adds r0, #CONTEXT_OFFSET + +#if CH_DBG_SYSTEM_STATE_CHECK || CH_DBG_STATISTICS || CH_CFG_SMP_MODE + ldr r3, [r0, #4] /* BASEPRI offset */ + cmp r3, #0 /* CORTEX_BASEPRI_DISABLED */ + bne 1f + mov r4, r0 + /* Returning to a preempted thread, performing a logical + "unlock", handling statistics and releasing spinlock.*/ +#if CH_DBG_SYSTEM_STATE_CHECK + bl __dbg_check_unlock +#endif +#if CH_DBG_STATISTICS + bl __stats_stop_measure_crit_thd +#endif +#if CH_CFG_SMP_MODE == TRUE + bl __port_spinlock_release +#endif + mov r0, r4 +1: +#endif /* CH_DBG_SYSTEM_STATE_CHECK || CH_DBG_STATISTICS || CH_CFG_SMP_MODE */ + + PORT_LOAD_MPU_CONTEXT + PORT_LOAD_INTEGER_CONTEXT + PORT_LOAD_SPECIAL_CONTEXT + PORT_LOAD_FLOAT_CONTEXT + + bx lr + +/*--------------------------------------------------------------------------* + * Start a thread by invoking its work function. + * + * Threads execution starts here, the code leaves the system critical zone + * and then jumps into the thread function passed in register R4. The + * register R5 contains the thread parameter. The function chThdExit() is + * called on thread function return. + *--------------------------------------------------------------------------*/ + .thumb_func + .globl __port_thread_start +__port_thread_start: +#if CORTEX_USE_FPU && (PORT_USE_FPU_FAST_SWITCHING >= 2) + /* Clearing FPCA for the new thread, it is initially set + because a long context is used for starting it.*/ + mov r0, #2 + msr CONTROL, r0 +#endif +#if CH_DBG_SYSTEM_STATE_CHECK + bl __dbg_check_unlock +#endif +#if CH_DBG_STATISTICS + bl __stats_stop_measure_crit_thd +#endif +#if CH_CFG_SMP_MODE == TRUE + bl __port_spinlock_release +#endif + movs r3, #0 /* CORTEX_BASEPRI_DISABLED */ + msr BASEPRI, r3 + mov r0, r5 + blx r4 + movs r0, #0 /* MSG_OK */ + bl chThdExit +1: b 1b + +#endif /* !defined(__DOXYGEN__) */ + +/** @} */ diff --git a/os/common/ports/ARMv8-M-ML-ALT/compilers/GCC/mk/port.mk b/os/common/ports/ARMv8-M-ML-ALT/compilers/GCC/mk/port.mk new file mode 100644 index 0000000000..3fe25538fb --- /dev/null +++ b/os/common/ports/ARMv8-M-ML-ALT/compilers/GCC/mk/port.mk @@ -0,0 +1,13 @@ +# List of the ChibiOS/RT ARMv8-M mainline generic port files. +PORTSRC = $(CHIBIOS)/os/common/ports/ARMv8-M-ML-ALT/chcore.c + +PORTASM = $(CHIBIOS)/os/common/ports/ARMv8-M-ML-ALT/compilers/GCC/chcoreasm.S + +PORTINC = $(CHIBIOS)/os/common/portability/GCC \ + $(CHIBIOS)/os/common/ports/ARM-common \ + $(CHIBIOS)/os/common/ports/ARMv8-M-ML-ALT + +# Shared variables +ALLXASMSRC += $(PORTASM) +ALLCSRC += $(PORTSRC) +ALLINC += $(PORTINC) diff --git a/os/common/ports/ARMv8-M-ML-ALT/compilers/GCC/mk/port_rp2.mk b/os/common/ports/ARMv8-M-ML-ALT/compilers/GCC/mk/port_rp2.mk new file mode 100644 index 0000000000..6659352ed3 --- /dev/null +++ b/os/common/ports/ARMv8-M-ML-ALT/compilers/GCC/mk/port_rp2.mk @@ -0,0 +1,15 @@ +# List of the ChibiOS/RT ARMv8-M-ML-ALT RP2 SMP port files. +PORTSRC = $(CHIBIOS)/os/common/ports/ARMv8-M-ML-ALT/chcore.c \ + $(CHIBIOS)/os/common/ports/ARMv8-M-ML-ALT/smp/rp2/chcoresmp.c + +PORTASM = $(CHIBIOS)/os/common/ports/ARMv8-M-ML-ALT/compilers/GCC/chcoreasm.S + +PORTINC = $(CHIBIOS)/os/common/portability/GCC \ + $(CHIBIOS)/os/common/ports/ARM-common \ + $(CHIBIOS)/os/common/ports/ARMv8-M-ML-ALT \ + $(CHIBIOS)/os/common/ports/ARMv8-M-ML-ALT/smp/rp2 + +# Shared variables +ALLXASMSRC += $(PORTASM) +ALLCSRC += $(PORTSRC) +ALLINC += $(PORTINC) diff --git a/os/common/ports/ARMv8-M-ML-ALT/smp/rp2/chcoresmp.c b/os/common/ports/ARMv8-M-ML-ALT/smp/rp2/chcoresmp.c new file mode 100644 index 0000000000..7f0efaa94d --- /dev/null +++ b/os/common/ports/ARMv8-M-ML-ALT/smp/rp2/chcoresmp.c @@ -0,0 +1,143 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation version 3 of the License. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ARMv8-M-ML-ALT/smp/rp2/chcoresmp.c + * @brief ARMv8-M-ML-ALT RP2 SMP code. + * + * @addtogroup ARMV8M_ML_ALT_CORE_SMP_RP2 + * @{ + */ + +#include "ch.h" + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +static void port_local_halt(void) { + const char *reason = "remote panic"; + + port_disable(); + + __trace_halt("remote panic"); + + currcore->dbg.panic_msg = reason; + + CH_CFG_SYSTEM_HALT_HOOK(reason); + + while (true) { + } +} + +/*===========================================================================*/ +/* Module interrupt handlers. */ +/*===========================================================================*/ + +/** + * @brief Single FIFO interrupt handler for both cores (RP2350). + * @note RP2350 uses a shared SIO_IRQ_FIFO (IRQ 25) unlike RP2040 which + * has separate IRQs per core. + * + * @isr + */ +CH_IRQ_HANDLER(VectorA4) { + + CH_IRQ_PROLOGUE(); + + SIO->FIFO_ST = SIO_FIFO_ST_ROE | SIO_FIFO_ST_WOF; + + while ((SIO->FIFO_ST & SIO_FIFO_ST_VLD) != 0U) { + uint32_t message = SIO->FIFO_RD; + /* Core 1 checks for panic from Core 0.*/ + if ((message == PORT_FIFO_PANIC_MESSAGE) && (port_get_core_id() == 1U)) { + port_local_halt(); + } +#if defined(PORT_HANDLE_FIFO_MESSAGE) + if (message != PORT_FIFO_RESCHEDULE_MESSAGE) { + PORT_HANDLE_FIFO_MESSAGE(port_get_core_id() ^ 1U, message); + } +#else + (void)message; +#endif + } + + __SEV(); + + CH_IRQ_EPILOGUE(); +} + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** + * @brief SMP-related port initialization. + * + * @param[in, out] oip pointer to the @p os_instance_t structure + */ +void __port_smp_init(os_instance_t *oip) { + +#if CH_CFG_ST_TIMEDELTA > 0 + /* Activating timer for this instance.*/ + port_timer_enable(oip); +#endif + +#if CH_CFG_SMP_MODE == TRUE + /* FIFO handler for this core. RP2350 uses a single shared IRQ 25.*/ + SIO->FIFO_ST = SIO_FIFO_ST_ROE | SIO_FIFO_ST_WOF; + NVIC_SetPriority(SIO_IRQ_FIFOn, CORTEX_MINIMUM_PRIORITY); + NVIC_EnableIRQ(SIO_IRQ_FIFOn); +#endif + + (void)oip; +} + +/** + * @brief Takes the kernel spinlock. + */ +void __port_spinlock_take(void) { + + port_spinlock_take(); +} + +/** + * @brief Releases the kernel spinlock. + */ +void __port_spinlock_release(void) { + + port_spinlock_release(); +} + +/** @} */ diff --git a/os/common/ports/ARMv8-M-ML-ALT/smp/rp2/chcoresmp.h b/os/common/ports/ARMv8-M-ML-ALT/smp/rp2/chcoresmp.h new file mode 100644 index 0000000000..80fd5aa751 --- /dev/null +++ b/os/common/ports/ARMv8-M-ML-ALT/smp/rp2/chcoresmp.h @@ -0,0 +1,220 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation version 3 of the License. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ARMv8-M-ML-ALT/smp/rp2/chcoresmp.h + * @brief ARMv8-M-ML-ALT-RP2 SMP macros and structures. + * + * @addtogroup ARMV8M_ML_ALT_CORE_SMP_RP2 + * @{ + */ + +#ifndef CHCORESMP_H +#define CHCORESMP_H + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/** + * @brief Number of SMP cores. + */ +#define PORT_CORES_NUMBER 2 + +/* RP2350 supports a realtime counter via TIMER0 unit, overriding the + default in chcore.h.*/ +#undef PORT_SUPPORTS_RT +#define PORT_SUPPORTS_RT TRUE + +/** + * @name IPC FIFO messages + * @{ + */ +#define PORT_FIFO_RESCHEDULE_MESSAGE 0xFFFFFFFFU +#define PORT_FIFO_PANIC_MESSAGE 0xFFFFFFFEU +/** @} */ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Spinlock to be used by the port layer. + */ +#if !defined(PORT_SPINLOCK_NUMBER) +#define PORT_SPINLOCK_NUMBER 31 +#endif + +/** + * @brief Preferential local and coherent BSS section for core zero. + */ +#if !defined(PORT_MEM_LOCAL_COHERENT_BSS0) +#define PORT_MEM_LOCAL_COHERENT_BSS0 CC_SECTION(".ram4_clear.core0") +#endif + +/** + * @brief Preferential local and coherent BSS section for core one. + */ +#if !defined(PORT_MEM_LOCAL_COHERENT_BSS1) +#define PORT_MEM_LOCAL_COHERENT_BSS1 CC_SECTION(".ram5_clear.core1") +#endif + +/** + * @brief Preferential local BSS section for core zero. + */ +#if !defined(PORT_MEM_LOCAL_BSS0) +#define PORT_MEM_LOCAL_BSS0 CC_SECTION(".ram4_clear.core0") +#endif + +/** + * @brief Preferential local BSS section for core one. + */ +#if !defined(PORT_MEM_LOCAL_BSS1) +#define PORT_MEM_LOCAL_BSS1 CC_SECTION(".ram5_clear.core1") +#endif + +/** + * @brief Core zero BSS section, RT name for the same scratch bank. + */ +#if !defined(PORT_CORE0_BSS_SECTION) +#define PORT_CORE0_BSS_SECTION PORT_MEM_LOCAL_COHERENT_BSS0 +#endif + +/** + * @brief Core one BSS section, RT name for the same scratch bank. + */ +#if !defined(PORT_CORE1_BSS_SECTION) +#define PORT_CORE1_BSS_SECTION PORT_MEM_LOCAL_COHERENT_BSS1 +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if (PORT_SPINLOCK_NUMBER < 0) || (PORT_SPINLOCK_NUMBER > 31) + #error "invalid PORT_SPINLOCK_NUMBER value" +#endif + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @brief Panic notification. + * @note It is sent without polling for FIFO space because the other side + * could be unable to empty the FIFO after a catastrophic error. + */ +#define PORT_SYSTEM_HALT_HOOK() do { \ + SIO->FIFO_WR = PORT_FIFO_PANIC_MESSAGE; \ + } while (false) + +/** + * @brief SMP-related port initialization. + * @note The port checks on presence of this macro so this + * must be a macro. + * + * @param[in, out] oip pointer to the @p os_instance_t structure + */ +#define port_smp_init(oip) __port_smp_init(oip) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void __port_smp_init(os_instance_t *oip); + void __port_spinlock_take(void); + void __port_spinlock_release(void); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Triggers an inter-core notification. + * + * @param[in] oip pointer to the @p os_instance_t structure + */ +__STATIC_INLINE void port_notify_instance(os_instance_t *oip) { + + (void)oip; + + /* Sending a reschedule order to the other core if there is space in + the FIFO.*/ + if ((SIO->FIFO_ST & SIO_FIFO_ST_RDY) != 0U) { + SIO->FIFO_WR = PORT_FIFO_RESCHEDULE_MESSAGE; + } +} + +/** + * @brief Takes the kernel spinlock. + */ +__STATIC_INLINE void port_spinlock_take(void) { + + while (SIO->SPINLOCK[PORT_SPINLOCK_NUMBER] == 0U) { + } + __DMB(); +} + +/** + * @brief Releases the kernel spinlock. + */ +__STATIC_INLINE void port_spinlock_release(void) { + + __DMB(); + SIO->SPINLOCK[PORT_SPINLOCK_NUMBER] = (uint32_t)SIO; +} + +/** + * @brief Returns the current value of the realtime counter. + * @note In this port the RT counter is the same counter used for + * system time in tick-less mode, resolution is always 1uS. + * + * @return The realtime counter value. + */ +#define port_rt_get_counter_value port_rt_get_counter_value +__STATIC_FORCEINLINE rtcnt_t port_rt_get_counter_value(void) { + + return TIMER0->TIMERAWL; +} + +/** + * @brief Returns a core index. + * @return The core identifier from 0 to @p PORT_CORES_NUMBER - 1. + */ +__STATIC_INLINE core_id_t port_get_core_id(void) { + + return SIO->CPUID; +} + +/*===========================================================================*/ +/* Module late inclusions. */ +/*===========================================================================*/ + +#endif /* CHCORESMP_H */ + +/** @} */ diff --git a/os/common/ports/ARMv8-M-ML-ALT/smp/rp2/chcoresmp_timer.h b/os/common/ports/ARMv8-M-ML-ALT/smp/rp2/chcoresmp_timer.h new file mode 100644 index 0000000000..e0b9d81de9 --- /dev/null +++ b/os/common/ports/ARMv8-M-ML-ALT/smp/rp2/chcoresmp_timer.h @@ -0,0 +1,137 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation version 3 of the License. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ARMv8-M-ML-ALT/smp/rp2/chcoresmp_timer.h + * @brief System timer header file. + * + * @addtogroup ARMV8M_ML_ALT_SMP_RP2_TIMER + * @{ + */ + +#ifndef CHCORESMP_TIMER_H +#define CHCORESMP_TIMER_H + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +#if (CH_CFG_ST_TIMEDELTA > 0) || defined(__DOXYGEN__) +/** + * @brief Enables the system timer for the specified OS instance. + */ +#define port_timer_enable(oip) stBindAlarmN((unsigned)(oip)->core_id) + +/** + * @brief Disables the system timer for the specified OS instance. + */ +#define port_timer_disable(oip) + +/** + * @brief Starts the alarm. + * @note Makes sure that no spurious alarms are triggered after + * this call. + * + * @param[in] time the time to be set for the first alarm + * + * @notapi + */ +#define port_timer_start_alarm(time) stStartAlarmN((unsigned)currcore->core_id, time) + +/** + * @brief Stops the alarm interrupt. + * + * @notapi + */ +#define port_timer_stop_alarm() stStopAlarmN((unsigned)currcore->core_id) + +/** + * @brief Sets the alarm time. + * + * @param[in] time the time to be set for the next alarm + * + * @notapi + */ +#define port_timer_set_alarm(time) stSetAlarmN((unsigned)currcore->core_id, time) + +/** + * @brief Returns the current alarm time. + * + * @return The currently set alarm time. + * + * @notapi + */ +#define port_timer_get_alarm() stGetAlarmN((unsigned)currcore->core_id) + +/** + * @brief Returns the system time. + * + * @return The system time. + * + * @notapi + */ +#define port_timer_get_time() stGetCounter() + +#else +#define port_timer_enable(oip) stBind() +#define port_timer_disable(oip) +#endif + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void stBind(void); +#if CH_CFG_ST_TIMEDELTA > 0 + void stBindAlarmN(unsigned alarm); + void stStartAlarmN(unsigned alarm, systime_t time); + void stStopAlarmN(unsigned alarm); + void stSetAlarmN(unsigned alarm, systime_t time); + systime_t stGetAlarmN(unsigned alarm); + systime_t stGetCounter(void); +#endif +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +#endif /* CHCORESMP_TIMER_H */ + +/** @} */ diff --git a/os/common/startup/ARMCMx/compilers/GCC/ld/RP2040_FLASH.ld b/os/common/startup/ARMCMx/compilers/GCC/ld/RP2040_FLASH.ld new file mode 100644 index 0000000000..e11b269313 --- /dev/null +++ b/os/common/startup/ARMCMx/compilers/GCC/ld/RP2040_FLASH.ld @@ -0,0 +1,123 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* The RP2040 requires 256-byte vector table alignment to run from flash. */ +__vectors_align__ = 256; + +/* + * RP2040 memory setup. + */ +MEMORY +{ + flash0 (rx) : org = 0x00000000, len = 16k /* ROM */ + flash1 (rx) : org = 0x10000000, len = DEFINED(FLASH_LEN) ? FLASH_LEN : 2048k /* XIP */ + flash2 (rx) : org = 0x00000000, len = 0 + flash3 (rx) : org = 0x00000000, len = 0 + flash4 (rx) : org = 0x00000000, len = 0 + flash5 (rx) : org = 0x00000000, len = 0 + flash6 (rx) : org = 0x00000000, len = 0 + flash7 (rx) : org = 0x00000000, len = 0 + ram0 (wx) : org = 0x20000000, len = 256k /* SRAM0 striped */ + ram1 (wx) : org = 0x00000000, len = 256k /* SRAM0 non striped */ + ram2 (wx) : org = 0x00000000, len = 0 + ram3 (wx) : org = 0x00000000, len = 0 + ram4 (wx) : org = 0x20040000, len = 4k /* SRAM4 */ + ram5 (wx) : org = 0x20041000, len = 4k /* SRAM5 */ + ram6 (wx) : org = 0x00000000, len = 0 + ram7 (wx) : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash1); +REGION_ALIAS("VECTORS_FLASH_LMA", flash1); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash1); +REGION_ALIAS("XTORS_FLASH_LMA", flash1); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash1); +REGION_ALIAS("TEXT_FLASH_LMA", flash1); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash1); +REGION_ALIAS("RODATA_FLASH_LMA", flash1); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash1); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash1); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash1); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram4); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram4); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("C1_MAIN_STACK_RAM", ram5); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("C1_PROCESS_STACK_RAM", ram5); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash1); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +SECTIONS +{ + .flash_begin : { + __flash_binary_start = .; + } > flash1 + + .boot2 : { + __boot2_start__ = .; + KEEP (*(.boot2)) + __boot2_end__ = .; + } > flash1 + + ASSERT(__boot2_end__ - __boot2_start__ <= 256, + "ERROR: The Pico second stage bootloader must be 256 bytes in size") +} + +/* Generic rules inclusion.*/ +INCLUDE rules_stacks.ld +INCLUDE rules_stacks_c1.ld +INCLUDE rules_code.ld +INCLUDE rules_data.ld +INCLUDE rules_memory.ld + +SECTIONS +{ + .flash_end : { + __flash_binary_end = .; + } > flash1 +} diff --git a/os/common/startup/ARMCMx/compilers/GCC/ld/RP2350_FLASH.ld b/os/common/startup/ARMCMx/compilers/GCC/ld/RP2350_FLASH.ld new file mode 100644 index 0000000000..1188897015 --- /dev/null +++ b/os/common/startup/ARMCMx/compilers/GCC/ld/RP2350_FLASH.ld @@ -0,0 +1,118 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * RP2350 memory setup for XIP + */ + +MEMORY +{ + flash0 (rx) : org = 0x00000000, len = 16k /* ROM */ + flash1 (rx) : org = 0x10000000, len = DEFINED(FLASH_LEN) ? FLASH_LEN : 4096k /* XIP */ + flash2 (rx) : org = 0x00000000, len = 0 + flash3 (rx) : org = 0x00000000, len = 0 + flash4 (rx) : org = 0x00000000, len = 0 + flash5 (rx) : org = 0x00000000, len = 0 + flash6 (rx) : org = 0x00000000, len = 0 + flash7 (rx) : org = 0x00000000, len = 0 + ram0 (wx) : org = 0x20000000, len = 512k /* SRAM */ + ram1 (wx) : org = 0x00000000, len = 0 + ram2 (wx) : org = 0x00000000, len = 0 + ram3 (wx) : org = 0x00000000, len = 0 + ram4 (wx) : org = 0x20080000, len = 4k /* SCRATCH_X */ + ram5 (wx) : org = 0x20081000, len = 4k /* SCRATCH_Y */ + ram6 (wx) : org = 0x00000000, len = 0 + ram7 (wx) : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash1); +REGION_ALIAS("VECTORS_FLASH_LMA", flash1); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash1); +REGION_ALIAS("XTORS_FLASH_LMA", flash1); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash1); +REGION_ALIAS("TEXT_FLASH_LMA", flash1); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash1); +REGION_ALIAS("RODATA_FLASH_LMA", flash1); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash1); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash1); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash1); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram4); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram4); + +/* RAM region to be used for Core 1 Main stack. This stack accommodates the + processing of all exceptions and interrupts on core 1.*/ +REGION_ALIAS("C1_MAIN_STACK_RAM", ram5); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("C1_PROCESS_STACK_RAM", ram5); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash1); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +SECTIONS +{ + .flash_begin : { + __flash_binary_start = .; + } > flash1 + + /* Must be within first 4KB for bootrom detection */ + .embedded_block : ALIGN(4) + { + KEEP(*(.embedded_block)) + } > flash1 +} + +/* Generic rules inclusion.*/ +INCLUDE rules_stacks.ld +INCLUDE rules_stacks_c1.ld +INCLUDE rules_code.ld +INCLUDE rules_data.ld +INCLUDE rules_memory.ld + +SECTIONS +{ + .flash_end : { + __flash_binary_end = .; + } > flash1 +} diff --git a/os/common/startup/ARMCMx/compilers/GCC/ld/RP2350_RAM.ld b/os/common/startup/ARMCMx/compilers/GCC/ld/RP2350_RAM.ld new file mode 100644 index 0000000000..a742787802 --- /dev/null +++ b/os/common/startup/ARMCMx/compilers/GCC/ld/RP2350_RAM.ld @@ -0,0 +1,98 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * RP2350 memory setup for RAM + */ + +MEMORY +{ + flash0 (rx) : org = 0x00000000, len = 16k /* ROM */ + flash1 (rx) : org = 0x10000000, len = DEFINED(FLASH_LEN) ? FLASH_LEN : 4096k /* XIP */ + flash2 (rx) : org = 0x00000000, len = 0 + flash3 (rx) : org = 0x00000000, len = 0 + flash4 (rx) : org = 0x00000000, len = 0 + flash5 (rx) : org = 0x00000000, len = 0 + flash6 (rx) : org = 0x00000000, len = 0 + flash7 (rx) : org = 0x00000000, len = 0 + ram0 (wx) : org = 0x20000000, len = 512k /* SRAM */ + ram1 (wx) : org = 0x00000000, len = 0 + ram2 (wx) : org = 0x00000000, len = 0 + ram3 (wx) : org = 0x00000000, len = 0 + ram4 (wx) : org = 0x20080000, len = 4k /* SCRATCH_X */ + ram5 (wx) : org = 0x20081000, len = 4k /* SCRATCH_Y */ + ram6 (wx) : org = 0x00000000, len = 0 + ram7 (wx) : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", ram0); +REGION_ALIAS("VECTORS_FLASH_LMA", ram0); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", ram0); +REGION_ALIAS("XTORS_FLASH_LMA", ram0); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", ram0); +REGION_ALIAS("TEXT_FLASH_LMA", ram0); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", ram0); +REGION_ALIAS("RODATA_FLASH_LMA", ram0); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", ram0); +REGION_ALIAS("VARIOUS_FLASH_LMA", ram0); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", ram0); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram4); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram4); + +/* RAM region to be used for Core 1 Main stack. This stack accommodates the + processing of all exceptions and interrupts on core 1.*/ +REGION_ALIAS("C1_MAIN_STACK_RAM", ram5); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("C1_PROCESS_STACK_RAM", ram5); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", ram0); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Generic rules inclusion.*/ +INCLUDE rules_stacks.ld +INCLUDE rules_stacks_c1.ld +INCLUDE rules_code.ld +INCLUDE rules_data.ld +INCLUDE rules_memory.ld diff --git a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_rp2040.mk b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_rp2040.mk index 1570a2b327..9860eb4415 100644 --- a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_rp2040.mk +++ b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_rp2040.mk @@ -1,17 +1,25 @@ # List of the ChibiOS generic RP2040 startup and CMSIS files. STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c - + +# Second stage bootloader file, can be overridden by the project. +RP2040_BOOT_STAGE2 ?= $(CHIBIOS)/os/common/startup/ARMCMx/devices/RP2040/bs2_default_padded_checksummed.S + STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v6m.S \ - $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.S + $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.S \ + $(RP2040_BOOT_STAGE2) STARTUPINC = $(CHIBIOS)/os/common/portability/GCC \ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \ $(CHIBIOS)/os/common/startup/ARMCMx/devices/RP2040 \ $(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \ + $(CHIBIOS)/os/common/ext/RP \ $(CHIBIOS)/os/common/ext/RP/RP2040 STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld +USE_EXCEPTIONS_STACKSIZE ?= 0x800 +USE_PROCESS_STACKSIZE ?= 0x800 + # Shared variables ALLXASMSRC += $(STARTUPASM) ALLCSRC += $(STARTUPSRC) diff --git a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_rp2350.mk b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_rp2350.mk new file mode 100644 index 0000000000..c4f8e9d539 --- /dev/null +++ b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_rp2350.mk @@ -0,0 +1,23 @@ +# List of the ChibiOS generic RP2350 startup and CMSIS files. +STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c + +STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v8m-ml.S \ + $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.S \ + $(CHIBIOS)/os/common/startup/ARMCMx/devices/RP2350/rp2350_imagedef.S + +STARTUPINC = $(CHIBIOS)/os/common/portability/GCC \ + $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \ + $(CHIBIOS)/os/common/startup/ARMCMx/devices/RP2350 \ + $(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \ + $(CHIBIOS)/os/common/ext/RP \ + $(CHIBIOS)/os/common/ext/RP/RP2350 + +STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld + +USE_EXCEPTIONS_STACKSIZE ?= 0x800 +USE_PROCESS_STACKSIZE ?= 0x800 + +# Shared variables +ALLXASMSRC += $(STARTUPASM) +ALLCSRC += $(STARTUPSRC) +ALLINC += $(STARTUPINC) diff --git a/os/common/startup/ARMCMx/devices/RP2040/bs2_default_padded_checksummed.S b/os/common/startup/ARMCMx/devices/RP2040/bs2_default_padded_checksummed.S new file mode 100644 index 0000000000..5c7a70007f --- /dev/null +++ b/os/common/startup/ARMCMx/devices/RP2040/bs2_default_padded_checksummed.S @@ -0,0 +1,27 @@ +/* + * Padded RP2040 Stage2 Bootloader + * Copyright (c) 2025 Raspberry Pi (Trading) Ltd. + * SPDX-License-Identifier: BSD-3-Clause + */ + +.cpu cortex-m0plus +.thumb + +.section .boot2, "ax" + +.byte 0x00, 0xb5, 0x32, 0x4b, 0x21, 0x20, 0x58, 0x60, 0x98, 0x68, 0x02, 0x21, 0x88, 0x43, 0x98, 0x60 +.byte 0xd8, 0x60, 0x18, 0x61, 0x58, 0x61, 0x2e, 0x4b, 0x00, 0x21, 0x99, 0x60, 0x02, 0x21, 0x59, 0x61 +.byte 0x01, 0x21, 0xf0, 0x22, 0x99, 0x50, 0x2b, 0x49, 0x19, 0x60, 0x01, 0x21, 0x99, 0x60, 0x35, 0x20 +.byte 0x00, 0xf0, 0x44, 0xf8, 0x02, 0x22, 0x90, 0x42, 0x14, 0xd0, 0x06, 0x21, 0x19, 0x66, 0x00, 0xf0 +.byte 0x34, 0xf8, 0x19, 0x6e, 0x01, 0x21, 0x19, 0x66, 0x00, 0x20, 0x18, 0x66, 0x1a, 0x66, 0x00, 0xf0 +.byte 0x2c, 0xf8, 0x19, 0x6e, 0x19, 0x6e, 0x19, 0x6e, 0x05, 0x20, 0x00, 0xf0, 0x2f, 0xf8, 0x01, 0x21 +.byte 0x08, 0x42, 0xf9, 0xd1, 0x00, 0x21, 0x99, 0x60, 0x1b, 0x49, 0x19, 0x60, 0x00, 0x21, 0x59, 0x60 +.byte 0x1a, 0x49, 0x1b, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0xeb, 0x21, 0x19, 0x66, 0xa0, 0x21 +.byte 0x19, 0x66, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0x21, 0x99, 0x60, 0x16, 0x49, 0x14, 0x48, 0x01, 0x60 +.byte 0x01, 0x21, 0x99, 0x60, 0x01, 0xbc, 0x00, 0x28, 0x00, 0xd0, 0x00, 0x47, 0x12, 0x48, 0x13, 0x49 +.byte 0x08, 0x60, 0x03, 0xc8, 0x80, 0xf3, 0x08, 0x88, 0x08, 0x47, 0x03, 0xb5, 0x99, 0x6a, 0x04, 0x20 +.byte 0x01, 0x42, 0xfb, 0xd0, 0x01, 0x20, 0x01, 0x42, 0xf8, 0xd1, 0x03, 0xbd, 0x02, 0xb5, 0x18, 0x66 +.byte 0x18, 0x66, 0xff, 0xf7, 0xf2, 0xff, 0x18, 0x6e, 0x18, 0x6e, 0x02, 0xbd, 0x00, 0x00, 0x02, 0x40 +.byte 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x5f, 0x00, 0x21, 0x22, 0x00, 0x00 +.byte 0xf4, 0x00, 0x00, 0x18, 0x22, 0x20, 0x00, 0xa0, 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0 +.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0xb2, 0x4e, 0x7a diff --git a/os/common/startup/ARMCMx/devices/RP2350/cmparams.h b/os/common/startup/ARMCMx/devices/RP2350/cmparams.h new file mode 100644 index 0000000000..9f6c426830 --- /dev/null +++ b/os/common/startup/ARMCMx/devices/RP2350/cmparams.h @@ -0,0 +1,93 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2350/cmparams.h + * @brief ARM Cortex-M33 parameters for the RP2350. + * + * @defgroup ARMCMx_RP2350 RP2350 Specific Parameters + * @ingroup ARMCMx_SPECIFIC + * @details This file contains the Cortex-M33 specific parameters for the + * RP2350 platform. + * @{ + */ + +#ifndef CMPARAMS_H +#define CMPARAMS_H + +/** + * @brief Cortex core model. + */ +#define CORTEX_MODEL 33 + +/** + * @brief Floating Point unit presence. + */ +#define CORTEX_HAS_FPU 1 + +/** + * @brief Number of bits in priority masks. + */ +#define CORTEX_PRIORITY_BITS 4U + +/* If the device type is not externally defined, for example from the Makefile, + then a file named board.h is included. This file must contain a device + definition compatible with the vendor include file.*/ +#if !defined(RP2350) +#include "board.h" +#endif + +/** + * @brief Number of interrupt vectors. + * @note This number does not include the 16 system vectors and must be + * rounded to a multiple of 8. + */ +#define CORTEX_NUM_VECTORS 56 + +/** + * @brief Number of MPU regions. + */ +#define CORTEX_MPU_REGIONS 8 + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +/* Including the device CMSIS header. Note, we are not using the definitions + from this header because we need this file to be usable also from + assembler source files. We verify that the info matches instead.*/ +#include "rp2350.h" + +/*lint -save -e9029 [10.4] Signedness comes from external files, it is + unpredictable but gives no problems.*/ +#if CORTEX_MODEL != __CORTEX_M +#error "CMSIS __CORTEX_M mismatch" +#endif + +#if CORTEX_HAS_FPU != __FPU_PRESENT +#error "CMSIS __FPU_PRESENT mismatch" +#endif + +#if CORTEX_PRIORITY_BITS != __NVIC_PRIO_BITS +#error "CMSIS __NVIC_PRIO_BITS mismatch" +#endif +/*lint -restore*/ + +#endif /* !defined(_FROM_ASM_) */ + +#endif /* CMPARAMS_H */ + +/** @} */ diff --git a/os/common/startup/ARMCMx/devices/RP2350/rp2350_imagedef.S b/os/common/startup/ARMCMx/devices/RP2350/rp2350_imagedef.S new file mode 100644 index 0000000000..39c46fadca --- /dev/null +++ b/os/common/startup/ARMCMx/devices/RP2350/rp2350_imagedef.S @@ -0,0 +1,105 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file rp2350_imagedef.S + * @brief RP2350 PICOBIN boot block definitions. + * @note See RP2350 Datasheet 5.1.5 Blocks and block loops + * @note See RP2350 Datasheet 5.9.1 Blocks and block loops + * @note See RP2350 Datasheet 5.9.5 Minimum viable image metadata + * + * @addtogroup ARMCMx_RP2350_IMAGEDEF + * @{ + */ + +/* Block markers */ +#define PICOBIN_BLOCK_MARKER_START 0xffffded3 +#define PICOBIN_BLOCK_MARKER_END 0xab123579 + +/* Block item type IDs */ +#define PICOBIN_BLOCK_ITEM_1BS_IMAGE_TYPE 0x42 +#define PICOBIN_BLOCK_ITEM_1BS_VECTOR_TABLE 0x03 +#define PICOBIN_BLOCK_ITEM_1BS_ENTRY_POINT 0x44 +#define PICOBIN_BLOCK_ITEM_2BS_LAST 0xff + +/* Image type field values */ +#define PICOBIN_IMAGE_TYPE_IMAGE_TYPE_EXE 0x0001 /* bits 0-3: type = 1 exe */ +#define PICOBIN_IMAGE_TYPE_EXE_CPU_ARM 0x0000 /* bits 8-10: cpu = 0 ARM */ +#define PICOBIN_IMAGE_TYPE_EXE_CPU_RISCV 0x0100 /* bits 8-10: cpu = 1 RISC-V */ +#define PICOBIN_IMAGE_TYPE_EXE_CHIP_RP2350 0x1000 /* bits 12-14: chip = 1 RP2350 */ +#define PICOBIN_IMAGE_TYPE_EXE_SECURITY_NS 0x0010 /* bits 4-5: security = 1 Non-Secure */ +#define PICOBIN_IMAGE_TYPE_EXE_SECURITY_S 0x0020 /* bits 4-5: security = 2 Secure */ + +/* + * The RP2350 supports ARM TrustZone with two security states: + * PICOBIN_IMAGE_TYPE_EXE_SECURITY_S (0x0020) - Secure mode (default) + * PICOBIN_IMAGE_TYPE_EXE_SECURITY_NS (0x0010) - Non-Secure mode + * + * Unless you know what you are doing with TrustZone you want Secure Mode! + */ +#if !defined(RP2350_IMAGE_TYPE) || defined(__DOXYGEN__) +#define RP2350_IMAGE_TYPE (PICOBIN_IMAGE_TYPE_IMAGE_TYPE_EXE | \ + PICOBIN_IMAGE_TYPE_EXE_CPU_ARM | \ + PICOBIN_IMAGE_TYPE_EXE_CHIP_RP2350 | \ + PICOBIN_IMAGE_TYPE_EXE_SECURITY_S) +#endif + +/*===========================================================================*/ +/* Imagedef block - placed at start of flash */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) + + .syntax unified + .thumb + +/* + * PICOBIN image definition block. + * The bootrom searches for this block within the first 4KB of flash. + * + * For our ChibiOS we use the following block structure: + * - MARKER_START + * - IMAGE_TYPE + * - VECTOR_TABLE + * - LAST + * - MARKER_END + */ + .section .embedded_block, "a", %progbits + .align 2 + .global __embedded_block +__embedded_block: + .word PICOBIN_BLOCK_MARKER_START + + .byte PICOBIN_BLOCK_ITEM_1BS_IMAGE_TYPE + .byte 0x01 + .hword RP2350_IMAGE_TYPE + + .byte PICOBIN_BLOCK_ITEM_1BS_VECTOR_TABLE + .byte 0x02 + .hword 0x0000 + .word __vectors_base__ + + .byte PICOBIN_BLOCK_ITEM_2BS_LAST + .hword ((__embedded_block_end - __embedded_block - 16) / 4) + .byte 0x00 + .word 0x00000000 + + .word PICOBIN_BLOCK_MARKER_END +__embedded_block_end: + +#endif /* !defined(__DOXYGEN__) */ + +/** @} */ diff --git a/os/hal/boards/RP_PICO2_RP2350/board.c b/os/hal/boards/RP_PICO2_RP2350/board.c new file mode 100644 index 0000000000..0a168d712d --- /dev/null +++ b/os/hal/boards/RP_PICO2_RP2350/board.c @@ -0,0 +1,110 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Early initialization code. + * @note Called before DATA/BSS init and stack fill. + */ +void __early_init(void) { + + /* Disable the bootrom watchdog. */ + WATCHDOG->CLR.CTRL = WATCHDOG_CTRL_ENABLE; + +#if RP_NO_INIT == FALSE + /* Reset of all peripherals. + Note, IO_QSPI, PADS_QSPI, PLL_SYS and PLL_USB are not reset because + the system is executing from flash via XIP and needs clock sources to + remain active. PLLs are handled by rp_clock_init() after switching to + safe sources.*/ + rp_peripheral_reset(~(RESETS_ALLREG_IO_QSPI | RESETS_ALLREG_PADS_QSPI | + RESETS_ALLREG_PLL_SYS | RESETS_ALLREG_PLL_USB)); + + rp_clock_init(); +#endif +} + +#if HAL_USE_SDC || defined(__DOXYGEN__) +/** + * @brief SDC card detection. + */ +bool sdc_lld_is_card_inserted(SDCDriver *sdcp) { + + (void)sdcp; + return true; +} + +/** + * @brief SDC card write protection detection. + */ +bool sdc_lld_is_write_protected(SDCDriver *sdcp) { + + (void)sdcp; + return false; +} +#endif /* HAL_USE_SDC */ + +#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) +/** + * @brief MMC_SPI card detection. + */ +bool mmc_lld_is_card_inserted(MMCDriver *mmcp) { + + (void)mmcp; + return true; +} + +/** + * @brief MMC_SPI card write protection detection. + */ +bool mmc_lld_is_write_protected(MMCDriver *mmcp) { + + (void)mmcp; + return false; +} +#endif + +/** + * @brief Board-specific initialization code. + */ +void boardInit(void) { + +} diff --git a/os/hal/boards/RP_PICO2_RP2350/board.h b/os/hal/boards/RP_PICO2_RP2350/board.h new file mode 100644 index 0000000000..d303f32f3c --- /dev/null +++ b/os/hal/boards/RP_PICO2_RP2350/board.h @@ -0,0 +1,84 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef BOARD_H +#define BOARD_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/* + * Setup for Raspberry Pi Pico 2 board. + */ + +/* + * Board identifier. + */ +#define BOARD_RP_PICO2_RP2350 +#define BOARD_NAME "Raspberry Pi Pico 2" + +/* + * Board oscillators-related settings. + */ +#if !defined(RP_XOSCCLK) +#define RP_XOSCCLK 12000000U +#endif + +/* + * MCU type. + */ +#define RP2350 + +/* + * IO pins assignments. + */ + +/* + * IO lines assignments. + */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(_FROM_ASM_) +#ifdef __cplusplus +extern "C" { +#endif + void boardInit(void); +#ifdef __cplusplus +} +#endif +#endif /* _FROM_ASM_ */ + +#endif /* BOARD_H */ diff --git a/os/hal/boards/RP_PICO2_RP2350/board.mk b/os/hal/boards/RP_PICO2_RP2350/board.mk new file mode 100644 index 0000000000..84f6d10bec --- /dev/null +++ b/os/hal/boards/RP_PICO2_RP2350/board.mk @@ -0,0 +1,9 @@ +# List of all the board related files. +BOARDSRC = $(CHIBIOS)/os/hal/boards/RP_PICO2_RP2350/board.c + +# Required include directories +BOARDINC = $(CHIBIOS)/os/hal/boards/RP_PICO2_RP2350 + +# Shared variables +ALLCSRC += $(BOARDSRC) +ALLINC += $(BOARDINC) diff --git a/os/hal/boards/RP_PICO_RP2040/board.c b/os/hal/boards/RP_PICO_RP2040/board.c index 2cfb58c258..7e82f5e6c7 100644 --- a/os/hal/boards/RP_PICO_RP2040/board.c +++ b/os/hal/boards/RP_PICO_RP2040/board.c @@ -47,12 +47,24 @@ /** * @brief Early initialization code. - * @details GPIO ports and system clocks are initialized before everything - * else. + * @note Called before DATA/BSS init and stack fill. */ void __early_init(void) { -// rp_gpio_init(); + /* Disable the bootrom watchdog. */ + WATCHDOG->CLR.CTRL = WATCHDOG_CTRL_ENABLE; + +#if RP_NO_INIT == FALSE + /* Reset of all peripherals. + Note, IO_QSPI, PADS_QSPI, PLL_SYS and PLL_USB are not reset because + the system is executing from flash via XIP and needs clock sources to + remain active. PLLs are handled by rp_clock_init() after switching to + safe sources.*/ + rp_peripheral_reset(~(RESETS_ALLREG_IO_QSPI | RESETS_ALLREG_PADS_QSPI | + RESETS_ALLREG_PLL_SYS | RESETS_ALLREG_PLL_USB)); + + rp_clock_init(); +#endif } #if HAL_USE_SDC || defined(__DOXYGEN__) diff --git a/os/hal/include/hal_usb.h b/os/hal/include/hal_usb.h index a2991e9214..2cb0e60132 100644 --- a/os/hal/include/hal_usb.h +++ b/os/hal/include/hal_usb.h @@ -245,6 +245,15 @@ #define USB_USE_WAIT FALSE #endif +/** + * @brief Moves EP0 request handling to thread context. + * @note Not implemented, the RP USB LLD tests this switch so it needs a + * defined default. + */ +#if !defined(USB_USE_EP0_THREAD) || defined(__DOXYGEN__) +#define USB_USE_EP0_THREAD FALSE +#endif + /*===========================================================================*/ /* Derived constants and error checks. */ /*===========================================================================*/ diff --git a/os/hal/ports/RP/LLD/ADCv1/driver.mk b/os/hal/ports/RP/LLD/ADCv1/driver.mk new file mode 100644 index 0000000000..ca71331b6e --- /dev/null +++ b/os/hal/ports/RP/LLD/ADCv1/driver.mk @@ -0,0 +1,9 @@ +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/RP/LLD/ADCv1 diff --git a/os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.c b/os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.c new file mode 100644 index 0000000000..556ff20604 --- /dev/null +++ b/os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.c @@ -0,0 +1,430 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file ADCv1/hal_adc_lld.c + * @brief RP2040/RP2350 ADC subsystem low level driver source. + * + * @addtogroup ADC + * @{ + */ + +#include "hal.h" + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/** + * @name PAD control register bits + * @{ + */ +#define PADS_GPIO_IE (1U << 6) +#define PADS_GPIO_OD (1U << 7) +#define PADS_GPIO_PUE (1U << 3) +#define PADS_GPIO_PDE (1U << 2) +/** @} */ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief ADC1 driver identifier.*/ +#if RP_ADC_USE_ADC1 || defined(__DOXYGEN__) +ADCDriver ADCD1; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Drains the ADC FIFO. + * @note Waits for any in-progress conversion to complete before draining. + * + * @param[in] adc pointer to the ADC registers block + */ +static void adc_lld_drain_fifo(ADC_TypeDef *adc) { + + /* Wait for any in-progress conversion to complete.*/ + while ((adc->CS & ADC_CS_READY) == 0U) { + } + + /* Drain all samples from FIFO.*/ + while ((adc->FCS & ADC_FCS_EMPTY) == 0U) { + (void)adc->FIFO; + } +} + +/** + * @brief ADC DMA service routine. + * + * @param[in] p parameter for the registered function + * @param[in] ct content of the CTRL_TRIG register + */ +static void adc_lld_serve_dma_interrupt(void *p, uint32_t ct) { + ADCDriver *adcp = (ADCDriver *)p; + + /* DMA errors handling.*/ + if ((ct & (DMA_CTRL_TRIG_READ_ERROR | DMA_CTRL_TRIG_WRITE_ERROR)) != 0U) { + _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); + } + else { + /* Conversion group may have been reset by error handler.*/ + if (adcp->grpp != NULL) { + /* Checking for DMA transfer complete.*/ + if ((ct & DMA_CTRL_TRIG_BUSY) == 0U) { + /* Check for ADC-level errors during transfer.*/ + adcerror_t emask = 0U; + if ((adcp->adc->FCS & ADC_FCS_OVER) != 0U) { + emask |= ADC_ERR_OVERFLOW; + } + if ((adcp->adc->CS & ADC_CS_ERR_STICKY) != 0U) { + emask |= ADC_ERR_CONVERSION; + } + if (emask != 0U) { + _adc_isr_error_code(adcp, emask); + } + else if (adcp->grpp->circular) { + /* Circular mode: re-arm DMA before callback.*/ + const ADCConversionGroup *grpp = adcp->grpp; + size_t total = (size_t)grpp->num_channels * adcp->depth; + adcsample_t *dest; + size_t count; + bool notify_half = false; + + if (adcp->depth > 1U) { + /* Double-buffer mode with half-transfer notifications.*/ + size_t half_count = total / 2U; + if (!adcp->half) { + /* First half complete, re-arm DMA for second half.*/ + adcp->half = true; + dest = adcp->samples + half_count; + count = total - half_count; + notify_half = true; + } + else { + /* Second half complete, re-arm DMA for first half.*/ + adcp->half = false; + dest = adcp->samples; + count = half_count; + } + } + else { + /* depth == 1: no half-buffer, just re-arm full buffer.*/ + dest = adcp->samples; + count = total; + } + + dmaChannelSetDestinationX(adcp->dma, (uint32_t)dest); + dmaChannelSetCounterX(adcp->dma, (uint32_t)count); + dmaChannelSetModeX(adcp->dma, adcp->dmamode); + dmaChannelEnableX(adcp->dma); + + if (notify_half) { + _adc_isr_half_code(adcp); + } + else { + _adc_isr_full_code(adcp); + } + } + else { + /* Linear mode: transfer complete.*/ + _adc_isr_full_code(adcp); + } + } + } + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level ADC driver initialization. + * + * @notapi + */ +void adc_lld_init(void) { + +#if RP_ADC_USE_ADC1 + /* Driver initialization.*/ + adcObjectInit(&ADCD1); + ADCD1.adc = ADC; + ADCD1.dma = NULL; + ADCD1.dmamode = DMA_CTRL_TRIG_DATA_SIZE_HWORD | + DMA_CTRL_TRIG_INCR_WRITE | + DMA_CTRL_TRIG_TREQ_ADC | +#if RP_ADC_ADC1_DMA_PRIORITY > 0 + DMA_CTRL_TRIG_HIGH_PRIORITY | +#endif + 0U; + ADCD1.half = false; +#endif +} + +/** + * @brief Configures and activates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_start(ADCDriver *adcp) { + + /* If in stopped state then enables the ADC and DMA clocks.*/ + if (adcp->state == ADC_STOP) { +#if RP_ADC_USE_ADC1 + if (&ADCD1 == adcp) { + /* Allocate DMA channel.*/ + adcp->dma = dmaChannelAllocI(RP_DMA_CHANNEL_ID_ANY, + RP_ADC_ADC1_DMA_IRQ_PRIORITY, + adc_lld_serve_dma_interrupt, + (void *)adcp); + osalDbgAssert(adcp->dma != NULL, "unable to allocate DMA channel"); + + if (adcp->dma == NULL) { + return; + } + + /* Reset ADC peripheral.*/ + rp_peripheral_reset(RESETS_ALLREG_ADC); + rp_peripheral_unreset(RESETS_ALLREG_ADC); + + /* Enable ADC.*/ + adcp->adc->CS = ADC_CS_EN; + + /* Wait for ADC ready.*/ + while ((adcp->adc->CS & ADC_CS_READY) == 0U) { + } + + /* Clear any pending FIFO errors.*/ + adcp->adc->FCS = ADC_FCS_UNDER | ADC_FCS_OVER; + + /* Drain any samples in FIFO.*/ + adc_lld_drain_fifo(adcp->adc); + + /* Set DMA source to ADC FIFO (constant across conversions).*/ + dmaChannelSetSourceX(adcp->dma, (uint32_t)&adcp->adc->FIFO); + } +#endif /* RP_ADC_USE_ADC1 */ + } +} + +/** + * @brief Deactivates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_stop(ADCDriver *adcp) { + + /* If in ready state then disables the ADC peripheral and clock.*/ + if (adcp->state == ADC_READY) { +#if RP_ADC_USE_ADC1 + if (&ADCD1 == adcp) { + /* Stop conversions. NOTE: CLR alias may also clear W1C ERR_STICKY + as a side-effect; acceptable during shutdown.*/ + adcp->adc->CLR.CS = ADC_CS_START_MANY | ADC_CS_TS_EN; + + /* Disable FIFO and DMA.*/ + adcp->adc->FCS = 0U; + + /* Drain FIFO.*/ + adc_lld_drain_fifo(adcp->adc); + + /* Disable ADC.*/ + adcp->adc->CS = 0U; + + /* Release DMA channel.*/ + dmaChannelFreeI(adcp->dma); + adcp->dma = NULL; + + /* Hold ADC in reset to gate the peripheral clock.*/ + rp_peripheral_reset(RESETS_ALLREG_ADC); + } +#endif + } +} + +/** + * @brief Starts an ADC conversion. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_start_conversion(ADCDriver *adcp) { + uint32_t cs_val; + uint32_t fcs_val; + uint32_t mode; + uint32_t dma_count; + const ADCConversionGroup *grpp = adcp->grpp; + + /* Clear any previous errors (SET alias writes 1 to W1C bits).*/ + adcp->adc->SET.CS = ADC_CS_ERR_STICKY; + adcp->adc->FCS = ADC_FCS_UNDER | ADC_FCS_OVER; + + /* Drain FIFO.*/ + adc_lld_drain_fifo(adcp->adc); + + /* Build CS register value.*/ + cs_val = ADC_CS_EN | + ((grpp->channel << ADC_CS_AINSEL_POS) & ADC_CS_AINSEL_MASK); + + /* Enable temperature sensor if needed.*/ + if (grpp->ts_enabled) { + cs_val |= ADC_CS_TS_EN; + } + + /* Configure round-robin if multiple channels.*/ + if (grpp->rrobin != 0U) { + cs_val |= (grpp->rrobin << ADC_CS_RROBIN_POS) & RP_ADC_RROBIN_MASK; + } + + /* Write CS without START_MANY first. AINSEL must be stable when + START_MANY transitions 0->1 to set the round-robin starting channel.*/ + adcp->adc->CS = cs_val; + + /* Configure clock divisor.*/ + adcp->adc->DIV = grpp->div; + + /* Configure FIFO: enable, DMA request, threshold = 1.*/ + fcs_val = ADC_FCS_EN | ADC_FCS_DREQ_EN | (1U << ADC_FCS_THRESH_POS); + adcp->adc->FCS = fcs_val; + + /* DMA setup.*/ + mode = adcp->dmamode; + adcp->half = false; + + /* Circular with depth > 1: DMA first half, ISR re-arms second half. + Otherwise: DMA full buffer.*/ + if (grpp->circular && (adcp->depth > 1U)) { + dma_count = ((uint32_t)grpp->num_channels * (uint32_t)adcp->depth) / 2U; + } + else { + dma_count = (uint32_t)grpp->num_channels * (uint32_t)adcp->depth; + } + + /* Configure DMA transfer (source address set once in adc_lld_start).*/ + dmaChannelSetDestinationX(adcp->dma, (uint32_t)adcp->samples); + dmaChannelSetCounterX(adcp->dma, dma_count); + dmaChannelSetModeX(adcp->dma, mode); + + /* Enable DMA channel interrupt.*/ + dmaChannelEnableInterruptX(adcp->dma); + + /* Enable DMA channel.*/ + dmaChannelEnableX(adcp->dma); + + /* Wait for ADC ready before starting conversion.*/ + while ((adcp->adc->CS & ADC_CS_READY) == 0U) { + } + + /* Start continuous conversion (second step: add START_MANY).*/ + adcp->adc->CS = cs_val | ADC_CS_START_MANY; +} + +/** + * @brief Stops an ongoing conversion. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adc_lld_stop_conversion(ADCDriver *adcp) { + + /* Stop conversions. Using CLR alias for atomic bit clear.*/ + adcp->adc->CLR.CS = ADC_CS_START_MANY; + + /* Disable DMA channel.*/ + dmaChannelDisableX(adcp->dma); + dmaChannelDisableInterruptX(adcp->dma); + + /* Disable FIFO.*/ + adcp->adc->FCS = 0U; + + /* Drain FIFO.*/ + adc_lld_drain_fifo(adcp->adc); +} + +/** + * @brief Enables the temperature sensor. + * @note Must be called after @p adcStart(). + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcRPEnableTS(ADCDriver *adcp) { + + adcp->adc->SET.CS = ADC_CS_TS_EN; +} + +/** + * @brief Disables the temperature sensor. + * @note Must be called after @p adcStart(). + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +void adcRPDisableTS(ADCDriver *adcp) { + + adcp->adc->CLR.CS = ADC_CS_TS_EN; +} + +/** + * @brief Configures a GPIO pin for ADC input. + * @note Disables digital I/O and pulls for proper analog operation. + * + * @param[in] gpio GPIO pin number (26-29 RP2040, 26-29/40-47 RP2350) + * + * @api + */ +void adcRPGpioInit(uint32_t gpio) { + uint32_t padbits; + + /* Validate GPIO range. NUM_CHANNELS includes the temperature sensor + which has no GPIO pin, hence the -1.*/ + osalDbgCheck(gpio >= RP_ADC_BASE_PIN); + osalDbgCheck(gpio < (RP_ADC_BASE_PIN + RP_ADC_NUM_CHANNELS - 1U)); + + /* FUNCSEL = NULL (31): disconnect digital output driver.*/ + IO_BANK0->GPIO[gpio].CTRL = 31U; + + /* Disable pulls and digital input, enable output disable.*/ + padbits = PADS_BANK0->GPIO[gpio]; + padbits &= ~(PADS_GPIO_PUE | PADS_GPIO_PDE | PADS_GPIO_IE); + padbits |= PADS_GPIO_OD; + PADS_BANK0->GPIO[gpio] = padbits; +} + +#endif /* HAL_USE_ADC */ + +/** @} */ diff --git a/os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.h b/os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.h new file mode 100644 index 0000000000..298a0a682a --- /dev/null +++ b/os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.h @@ -0,0 +1,305 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file ADCv1/hal_adc_lld.h + * @brief RP2040/RP2350 ADC subsystem low level driver header. + * + * @addtogroup ADC + * @{ + */ + +#ifndef HAL_ADC_LLD_H +#define HAL_ADC_LLD_H + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name ADC CS register bits + * @{ + */ +#define ADC_CS_EN (1U << 0) +#define ADC_CS_TS_EN (1U << 1) +#define ADC_CS_START_ONCE (1U << 2) +#define ADC_CS_START_MANY (1U << 3) +#define ADC_CS_READY (1U << 8) +#define ADC_CS_ERR (1U << 9) +#define ADC_CS_ERR_STICKY (1U << 10) +#define ADC_CS_AINSEL_POS 12U +#if RP_ADC_NUM_CHANNELS > 5U +#define ADC_CS_AINSEL_MASK (0xFU << ADC_CS_AINSEL_POS) +#else +#define ADC_CS_AINSEL_MASK (0x7U << ADC_CS_AINSEL_POS) +#endif +#define ADC_CS_RROBIN_POS 16U +/** @} */ + +/** + * @name ADC FCS register bits + * @{ + */ +#define ADC_FCS_EN (1U << 0) +#define ADC_FCS_SHIFT (1U << 1) +#define ADC_FCS_ERR (1U << 2) +#define ADC_FCS_DREQ_EN (1U << 3) +#define ADC_FCS_EMPTY (1U << 8) +#define ADC_FCS_FULL (1U << 9) +#define ADC_FCS_UNDER (1U << 10) +#define ADC_FCS_OVER (1U << 11) +#define ADC_FCS_LEVEL_POS 16U +#define ADC_FCS_LEVEL_MASK (0xFU << ADC_FCS_LEVEL_POS) +#define ADC_FCS_THRESH_POS 24U +#define ADC_FCS_THRESH_MASK (0xFU << ADC_FCS_THRESH_POS) +/** @} */ + +/** + * @name ADC DIV register bits + * @{ + */ +#define ADC_DIV_FRAC_POS 0U +#define ADC_DIV_FRAC_MASK (0xFFU << ADC_DIV_FRAC_POS) +#define ADC_DIV_INT_POS 8U +#define ADC_DIV_INT_MASK (0xFFFFU << ADC_DIV_INT_POS) +/** @} */ + +/** + * @name ADC FIFO register bits + * @{ + */ +#define ADC_FIFO_VAL_MASK 0x0FFFU +#define ADC_FIFO_ERR (1U << 15) +/** @} */ + +/** + * @name Possible ADC errors mask bits + * @{ + */ +#define ADC_ERR_DMAFAILURE 1U /**< DMA operations failure. */ +#define ADC_ERR_OVERFLOW 2U /**< ADC FIFO overflow. */ +#define ADC_ERR_UNDERFLOW 4U /**< ADC FIFO underflow. */ +#define ADC_ERR_CONVERSION 8U /**< ADC conversion error. */ +/** @} */ + +/** + * @name ADC channel definitions + * @{ + */ +#define ADC_CHANNEL_IN0 0U +#define ADC_CHANNEL_IN1 1U +#define ADC_CHANNEL_IN2 2U +#define ADC_CHANNEL_IN3 3U +#define ADC_CHANNEL_TEMPSENSOR RP_ADC_TEMPERATURE_CHANNEL + +#if RP_ADC_NUM_CHANNELS > 5U +#define ADC_CHANNEL_IN4 4U +#define ADC_CHANNEL_IN5 5U +#define ADC_CHANNEL_IN6 6U +#define ADC_CHANNEL_IN7 7U +#endif +/** @} */ + +/** + * @name Channel selection helper macros + * @{ + */ +#define ADC_CHSELR_CHSEL(n) (1U << (n)) +#define ADC_CHSELR_CHSEL0 (1U << 0) +#define ADC_CHSELR_CHSEL1 (1U << 1) +#define ADC_CHSELR_CHSEL2 (1U << 2) +#define ADC_CHSELR_CHSEL3 (1U << 3) +#define ADC_CHSELR_CHSEL4 (1U << 4) + +#if RP_ADC_NUM_CHANNELS > 5U +#define ADC_CHSELR_CHSEL5 (1U << 5) +#define ADC_CHSELR_CHSEL6 (1U << 6) +#define ADC_CHSELR_CHSEL7 (1U << 7) +#define ADC_CHSELR_CHSEL8 (1U << 8) +#endif +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief ADC1 driver enable switch. + * @details If set to @p TRUE the support for ADC1 is included. + * @note The default is @p FALSE. + */ +#if !defined(RP_ADC_USE_ADC1) || defined(__DOXYGEN__) +#define RP_ADC_USE_ADC1 FALSE +#endif + +/** + * @brief ADC1 DMA priority (0..1). + */ +#if !defined(RP_ADC_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define RP_ADC_ADC1_DMA_PRIORITY 0 +#endif + +/** + * @brief ADC1 DMA interrupt priority level setting. + */ +#if !defined(RP_ADC_ADC1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define RP_ADC_ADC1_DMA_IRQ_PRIORITY 3 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* Registry checks.*/ +#if !defined(RP_HAS_ADC) +#error "RP_HAS_ADC not defined in registry" +#endif + +#if !RP_HAS_ADC +#error "ADC not present in the selected device" +#endif + +#if RP_ADC_USE_ADC1 && !RP_HAS_ADC +#error "ADC1 not present in the selected device" +#endif + +/* At least one ADC must be assigned.*/ +#if !RP_ADC_USE_ADC1 +#error "ADC driver activated but no ADC peripheral assigned" +#endif + +/* DMA priority checks.*/ +#if RP_ADC_USE_ADC1 && \ + !RP_DMA_IS_VALID_PRIORITY(RP_ADC_ADC1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to ADC1" +#endif + +/* IRQ priority checks.*/ +#if RP_ADC_USE_ADC1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(RP_ADC_ADC1_DMA_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to ADC1" +#endif + +#if !defined(RP_DMA_REQUIRED) +#define RP_DMA_REQUIRED +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief ADC sample data type. + */ +typedef uint16_t adcsample_t; + +/** + * @brief Channels number in a conversion group. + */ +typedef uint16_t adc_channels_num_t; + +/** + * @brief Type of an ADC error mask. + */ +typedef uint32_t adcerror_t; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Low level fields of the ADC driver structure. + */ +#define adc_lld_driver_fields \ + /* Pointer to the ADC registers block.*/ \ + ADC_TypeDef *adc; \ + /* Pointer to associated DMA channel.*/ \ + const rp_dma_channel_t *dma; \ + /* DMA mode bit mask.*/ \ + uint32_t dmamode; \ + /* Circular mode half-buffer tracking flag. \ + false = filling first half, true = filling second half.*/ \ + bool half; + +/** + * @brief Low level fields of the ADC configuration structure. + */ +#define adc_lld_config_fields \ + /* Dummy configuration, it is not needed.*/ \ + uint32_t dummy; + +/** + * @brief Low level fields of the ADC configuration group structure. + * + * @note The ADC FIFO contains no channel tag; round-robin ordering + * depends on @p channel and @p rrobin (see field comments). + */ +#define adc_lld_configuration_group_fields \ + /* ADC channel number (0-4 RP2040, 0-8 RP2350B). \ + Single-channel: the channel to sample. Round-robin: first channel.*/ \ + uint32_t channel; \ + /* Round-robin channel mask (0 = single-channel mode). \ + Channels are sampled in ascending bit order, e.g. 0x0F = ch0-3.*/ \ + uint32_t rrobin; \ + /* Clock divisor: 0 = free-running 500 kS/s, else \ + rate = 48 MHz / (1 + INT + FRAC/256). Use @p ADC_DIV(i, f).*/ \ + uint32_t div; \ + /* Enable temperature sensor (set to true when using temp sensor ch).*/ \ + bool ts_enabled; + +/** + * @brief Macro to build clock divisor value. + * + * @param[in] i integer part of divisor (0-65535) + * @param[in] f fractional part of divisor (0-255) + */ +#define ADC_DIV(i, f) (((uint32_t)(i) << 8U) | (uint32_t)(f)) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if RP_ADC_USE_ADC1 && !defined(__DOXYGEN__) +extern ADCDriver ADCD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void adc_lld_init(void); + void adc_lld_start(ADCDriver *adcp); + void adc_lld_stop(ADCDriver *adcp); + void adc_lld_start_conversion(ADCDriver *adcp); + void adc_lld_stop_conversion(ADCDriver *adcp); + void adcRPEnableTS(ADCDriver *adcp); + void adcRPDisableTS(ADCDriver *adcp); + void adcRPGpioInit(uint32_t gpio); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_ADC */ + +#endif /* HAL_ADC_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/RP/LLD/DMAv1/rp_dma.c b/os/hal/ports/RP/LLD/DMAv1/rp_dma.c index 968f9ad03d..217ecec3ed 100644 --- a/os/hal/ports/RP/LLD/DMAv1/rp_dma.c +++ b/os/hal/ports/RP/LLD/DMAv1/rp_dma.c @@ -43,7 +43,7 @@ /** * @brief DMA channel descriptors. */ -const rp_dma_channel_t __rp_dma_channels[RP_DMA_CHANNELS] = { +const rp_dma_channel_t __rp_dma_channels[RP_DMA_NUM_CHANNELS] = { {DMA, &DMA->CH[0], 0U, 1U << 0}, {DMA, &DMA->CH[1], 1U, 1U << 1}, {DMA, &DMA->CH[2], 2U, 1U << 2}, @@ -56,6 +56,13 @@ const rp_dma_channel_t __rp_dma_channels[RP_DMA_CHANNELS] = { {DMA, &DMA->CH[9], 9U, 1U << 9}, {DMA, &DMA->CH[10], 10U, 1U << 10}, {DMA, &DMA->CH[11], 11U, 1U << 11} +#if RP_DMA_NUM_CHANNELS > 12 + , + {DMA, &DMA->CH[12], 12U, 1U << 12}, + {DMA, &DMA->CH[13], 13U, 1U << 13}, + {DMA, &DMA->CH[14], 14U, 1U << 14}, + {DMA, &DMA->CH[15], 15U, 1U << 15} +#endif }; /*===========================================================================*/ @@ -86,7 +93,7 @@ static struct { * @brief DMA callback parameter. */ void *param; - } channels[RP_DMA_CHANNELS]; + } channels[RP_DMA_NUM_CHANNELS]; } dma; /*===========================================================================*/ @@ -184,7 +191,7 @@ void dmaInit(void) { dma.c0_allocated_mask = 0U; dma.c1_allocated_mask = 0U; - for (i = 0U; i < RP_DMA_CHANNELS; i++) { + for (i = 0U; i < RP_DMA_NUM_CHANNELS; i++) { dma.channels[i].func = NULL; } } @@ -235,6 +242,11 @@ const rp_dma_channel_t *dmaChannelAllocI(uint32_t id, dma.channels[i].func = func; dma.channels[i].param = param; + /* Releasing DMA reset if it is the 1st channel taken.*/ + if (prevmask == 0U) { + rp_peripheral_unreset(RESETS_ALLREG_DMA); + } + if (SIO->CPUID == 0U) { /* Channel taken by core 0.*/ if (dma.c0_allocated_mask == 0U) { @@ -250,11 +262,6 @@ const rp_dma_channel_t *dmaChannelAllocI(uint32_t id, dma.c1_allocated_mask |= dmachp->chnmask; } - /* Releasing DMA reset if it is the 1st channel taken.*/ - if (prevmask == 0U) { - hal_lld_peripheral_unreset(RESETS_ALLREG_DMA); - } - return dmachp; } } @@ -335,7 +342,7 @@ void dmaChannelFreeI(const rp_dma_channel_t *dmachp) { /* Shutting down clocks that are no more required, if any.*/ if ((dma.c0_allocated_mask | dma.c1_allocated_mask) == 0U) { - hal_lld_peripheral_reset(RESETS_ALLREG_DMA); + rp_peripheral_reset(RESETS_ALLREG_DMA); } } diff --git a/os/hal/ports/RP/LLD/DMAv1/rp_dma.h b/os/hal/ports/RP/LLD/DMAv1/rp_dma.h index e9353bad72..3582cb1ac5 100644 --- a/os/hal/ports/RP/LLD/DMAv1/rp_dma.h +++ b/os/hal/ports/RP/LLD/DMAv1/rp_dma.h @@ -29,11 +29,6 @@ /* Driver constants. */ /*===========================================================================*/ -/** - * @brief Total number of DMA channels. - */ -#define RP_DMA_CHANNELS 12U - /** * @brief Checks if a DMA channels id is within the valid range. * @@ -43,7 +38,7 @@ * @retval true correct DMA channel. */ #define RP_DMA_IS_VALID_CHANNEL(chn) (((chn) >= 0U) && \ - ((id) <= (RP_DMA_CHANNELS + 1U))) + ((chn) <= RP_DMA_NUM_CHANNELS)) /** * @brief Checks if a DMA priority is within the valid range. @@ -58,7 +53,7 @@ /** * @brief Any channel selector. */ -#define RP_DMA_CHANNEL_ID_ANY RP_DMA_CHANNELS +#define RP_DMA_CHANNEL_ID_ANY RP_DMA_NUM_CHANNELS /** * @brief Returns a pointer to a @p rp_dma_channel_t structure. @@ -94,7 +89,7 @@ typedef void (*rp_dmaisr_t)(void *p, uint32_t ct); */ typedef struct { DMA_TypeDef *dma; /**< @brief Associated DMA. */ - DMA_Channel_Typedef *channel; /**< @brief Associated DMA channel. */ + DMA_Channel_TypeDef *channel; /**< @brief Associated DMA channel. */ uint32_t chnidx; /**< @brief Index to self in array. */ uint32_t chnmask; /**< @brief Channel bit mask. */ } rp_dma_channel_t; @@ -108,7 +103,7 @@ typedef struct { /*===========================================================================*/ #if !defined(__DOXYGEN__) -extern const rp_dma_channel_t __rp_dma_channels[RP_DMA_CHANNELS]; +extern const rp_dma_channel_t __rp_dma_channels[RP_DMA_NUM_CHANNELS]; #endif #ifdef __cplusplus @@ -150,6 +145,8 @@ __STATIC_INLINE bool dmaChannelIsBusyX(const rp_dma_channel_t *dmachp) { /** * @brief Get and clears channel interrupts state. + * @note Also clears INTR via INTS0/ISTS1 (W1C) to prevent stale + * interrupts left by @p dmaChannelAbortX(). * * @param[in] dmachp pointer to a rp_dma_channel_t structure * @return The content of @p CTRL_TRIG register before clearing @@ -165,6 +162,9 @@ __STATIC_INLINE uint32_t dmaChannelGetAndClearInterrupts(const rp_dma_channel_t DMA_CTRL_TRIG_READ_ERROR | DMA_CTRL_TRIG_WRITE_ERROR; + dmachp->dma->INTS0 = dmachp->chnmask; + dmachp->dma->INTS1 = dmachp->chnmask; + return ctrl_trig; } @@ -268,6 +268,8 @@ __STATIC_INLINE void dmaChannelSetModeX(const rp_dma_channel_t *dmachp, /** * @brief Aborts the current transfer on a DMA channel. + * @note EN and CHAIN_TO are cleared before asserting CHAN_ABORT to + * prevent post-abort re-triggering (RP2350-E5). * * @param[in] dmachp pointer to a rp_dma_channel_t structure * @@ -275,6 +277,14 @@ __STATIC_INLINE void dmaChannelSetModeX(const rp_dma_channel_t *dmachp, */ __STATIC_INLINE void dmaChannelAbortX(const rp_dma_channel_t *dmachp) { + /* Clear EN and set CHAIN_TO to self (no chaining) per RP2350-E5. + W1C error flags are masked to zero to preserve them. */ + dmachp->channel->CTRL_TRIG = (dmachp->channel->CTRL_TRIG & + ~(DMA_CTRL_TRIG_EN | + DMA_CTRL_TRIG_CHAIN_TO_Msk | + DMA_CTRL_TRIG_READ_ERROR | + DMA_CTRL_TRIG_WRITE_ERROR)) | + DMA_CTRL_TRIG_CHAIN_TO(dmachp->chnidx); dmachp->dma->SET.CHAN_ABORT = dmachp->chnmask; while ((dmachp->dma->CHAN_ABORT & dmachp->chnmask) != 0U) { } diff --git a/os/hal/ports/RP/LLD/EFLv1/driver.mk b/os/hal/ports/RP/LLD/EFLv1/driver.mk new file mode 100644 index 0000000000..7b5236bdf3 --- /dev/null +++ b/os/hal/ports/RP/LLD/EFLv1/driver.mk @@ -0,0 +1,9 @@ +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_EFL TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/RP/LLD/EFLv1/rp_efl_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/RP/LLD/EFLv1/rp_efl_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/RP/LLD/EFLv1 diff --git a/os/hal/ports/RP/LLD/EFLv1/rp_efl_lld.c b/os/hal/ports/RP/LLD/EFLv1/rp_efl_lld.c new file mode 100644 index 0000000000..c637f60afa --- /dev/null +++ b/os/hal/ports/RP/LLD/EFLv1/rp_efl_lld.c @@ -0,0 +1,481 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file EFLv1/rp_efl_lld.c + * @brief RP shared Embedded Flash subsystem low level driver source. + * + * @addtogroup HAL_EFL + * @{ + */ + +#include + +#include "hal.h" +#include "rp_efl_lld.h" + +#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +static const flash_descriptor_t efl_lld_descriptor = { + .attributes = FLASH_ATTR_ERASED_IS_ONE | + FLASH_ATTR_MEMORY_MAPPED | + FLASH_ATTR_REWRITABLE, + .page_size = RP_FLASH_PAGE_SIZE, + .sectors_count = RP_FLASH_SECTORS_COUNT, + .sectors = NULL, + .sectors_size = RP_FLASH_SECTOR_SIZE, + .address = (uint8_t *)RP_FLASH_BASE, + .size = RP_FLASH_SIZE +}; + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level Embedded Flash driver initialization. + * + * @notapi + */ +void efl_lld_init(void) { + + /* Driver initialization. */ + eflObjectInit(&EFLD1); + + /* Platform-specific one-time initialization (e.g. RP2040 boot2 copy). */ + rp_efl_lld_init(); +} + +/** + * @brief Configures and activates the Embedded Flash peripheral. + * + * @param[in] eflp pointer to a @p EFlashDriver structure + * + * @notapi + */ +void efl_lld_start(EFlashDriver *eflp) { + + rp_efl_lld_start(eflp); +} + +/** + * @brief Deactivates the Embedded Flash peripheral. + * + * @param[in] eflp pointer to a @p EFlashDriver structure + * + * @notapi + */ +void efl_lld_stop(EFlashDriver *eflp) { + + (void)eflp; + + /* Nothing to do. */ +} + +/** + * @brief Gets the flash descriptor structure. + * + * @param[in] instance pointer to a @p EFlashDriver instance + * @return A flash device descriptor. + * + * @notapi + */ +const flash_descriptor_t *efl_lld_get_descriptor(void *instance) { + + (void)instance; + + return &efl_lld_descriptor; +} + +/** + * @brief Read operation. + * + * @param[in] instance pointer to a @p EFlashDriver instance + * @param[in] offset offset within full flash address space + * @param[in] n number of bytes to be read + * @param[out] rp pointer to the data buffer + * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_READ if the read operation failed. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @notapi + */ +flash_error_t efl_lld_read(void *instance, flash_offset_t offset, + size_t n, uint8_t *rp) { + EFlashDriver *devp = (EFlashDriver *)instance; + flash_error_t err = FLASH_NO_ERROR; + + osalDbgCheck((instance != NULL) && (rp != NULL) && (n > 0U)); + osalDbgCheck((size_t)offset + n <= (size_t)efl_lld_descriptor.size); + osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), + "invalid state"); + + /* No reading while erasing. */ + if (devp->state == FLASH_ERASE) { + return FLASH_BUSY_ERASING; + } + + /* FLASH_READ state while the operation is performed. */ + devp->state = FLASH_READ; + + /* Read from memory-mapped XIP region. */ + memcpy((void *)rp, (const void *)(efl_lld_descriptor.address + offset), n); + + /* Ready state again. */ + devp->state = FLASH_READY; + + return err; +} + +/** + * @brief Program operation. + * + * @param[in] instance pointer to a @p EFlashDriver instance + * @param[in] offset offset within full flash address space + * @param[in] n number of bytes to be programmed + * @param[in] pp pointer to the data buffer + * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_PROGRAM if the program operation failed. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @notapi + */ +flash_error_t efl_lld_program(void *instance, flash_offset_t offset, + size_t n, const uint8_t *pp) { + EFlashDriver *devp = (EFlashDriver *)instance; + syssts_t sts; + + osalDbgCheck((instance != NULL) && (pp != NULL) && (n > 0U)); + osalDbgCheck((size_t)offset + n <= (size_t)efl_lld_descriptor.size); + osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), + "invalid state"); + + /* No programming while erasing. */ + if (devp->state == FLASH_ERASE) { + return FLASH_BUSY_ERASING; + } + + /* FLASH_PGM state while the operation is performed. */ + devp->state = FLASH_PGM; + + /* Allow the application to prepare for XIP becoming unavailable. */ + rpEflBeforeXipOff(); + + /* Program in page-sized chunks. The source data copy is intentionally + * done outside the system lock while XIP is still enabled; only the + * RAM-resident page transaction itself is bracketed by syslock. */ + while (n > 0U) { + uint8_t page_buf[RP_FLASH_PAGE_SIZE]; + uint32_t page_base = offset & ~(uint32_t)(RP_FLASH_PAGE_SIZE - 1U); + size_t page_offset = offset & (RP_FLASH_PAGE_SIZE - 1U); + size_t page_remaining = RP_FLASH_PAGE_SIZE - page_offset; + size_t chunk = (n < page_remaining) ? n : page_remaining; + + /* + * Programming is done page-by-page. Fill the untouched bytes with + * 0xFF (all ones) so a partial write still emits a full page. + */ + memset(page_buf, 0xFF, sizeof(page_buf)); + memcpy(page_buf + page_offset, pp, chunk); + + sts = osalSysGetStatusAndLockX(); + + /* Program the page. */ + rp_efl_lld_program_page_full(devp, page_base, page_buf, + RP_FLASH_PAGE_SIZE); + + osalSysRestoreStatusX(sts); + + offset += chunk; + pp += chunk; + n -= chunk; + } + + /* Notify the application that XIP is available again. */ + rpEflAfterXipOn(); + + /* Ready state again. */ + devp->state = FLASH_READY; + + return FLASH_NO_ERROR; +} + +/** + * @brief Starts a whole-device erase operation. + * @note This is not implemented for safety reasons - erasing the entire + * flash would destroy the running firmware. + * + * @param[in] instance pointer to a @p EFlashDriver instance + * @return An error code. + * + * @notapi + */ +flash_error_t efl_lld_start_erase_all(void *instance) { + + (void)instance; + + return FLASH_ERROR_UNIMPLEMENTED; +} + +/** + * @brief Starts a sector erase operation. + * + * @param[in] instance pointer to a @p EFlashDriver instance + * @param[in] sector sector to be erased + * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @notapi + */ +flash_error_t efl_lld_start_erase_sector(void *instance, + flash_sector_t sector) { + EFlashDriver *devp = (EFlashDriver *)instance; + flash_offset_t offset; + syssts_t sts; + + osalDbgCheck(instance != NULL); + osalDbgCheck(sector < efl_lld_descriptor.sectors_count); + osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), + "invalid state"); + + /* No erasing while erasing. */ + if (devp->state == FLASH_ERASE) { + return FLASH_BUSY_ERASING; + } + + /* FLASH_ERASE state while the operation is performed. */ + devp->state = FLASH_ERASE; + + /* Calculate sector offset. */ + offset = sector * RP_FLASH_SECTOR_SIZE; + + /* Allow the application to prepare for XIP becoming unavailable. */ + rpEflBeforeXipOff(); + + /* Lock the system around the single RAM-resident erase sequence. */ + sts = osalSysGetStatusAndLockX(); + + /* Perform the entire erase sequence in RAM. */ + rp_efl_lld_erase_full(devp, RP_FLASH_CMD_SECTOR_ERASE, offset); + + /* Restore system state. */ + osalSysRestoreStatusX(sts); + + /* Notify the application that XIP is available again. */ + rpEflAfterXipOn(); + + /* Back to ready state. */ + devp->state = FLASH_READY; + + return FLASH_NO_ERROR; +} + +/** + * @brief Starts a block erase operation. + * + * @param[in] instance pointer to a @p EFlashDriver instance + * @param[in] cmd JEDEC erase command byte + * @param[in] erase_size erase unit size in bytes + * @param[in] block block number to be erased + * @return An error code. + * @retval FLASH_NO_ERROR if the block erase completed. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * + * @notapi + */ +flash_error_t efl_lld_start_erase_block(void *instance, + uint8_t cmd, + uint32_t erase_size, + uint32_t block) { + EFlashDriver *devp = (EFlashDriver *)instance; + flash_offset_t offset; + syssts_t sts; + + osalDbgCheck(instance != NULL); + osalDbgCheck(block < (RP_FLASH_SIZE / erase_size)); + osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), + "invalid state"); + + if (devp->state == FLASH_ERASE) { + return FLASH_BUSY_ERASING; + } + + devp->state = FLASH_ERASE; + + offset = block * erase_size; + + /* Allow the application to prepare for XIP becoming unavailable. */ + rpEflBeforeXipOff(); + + /* Erase is one uninterrupted RAM-resident XIP-off transaction, so the + * whole helper runs under syslock. */ + sts = osalSysGetStatusAndLockX(); + rp_efl_lld_erase_full(devp, cmd, offset); + osalSysRestoreStatusX(sts); + + /* Notify the application that XIP is available again. */ + rpEflAfterXipOn(); + + devp->state = FLASH_READY; + + return FLASH_NO_ERROR; +} + +/** + * @brief Queries the driver for erase operation progress. + * + * @param[in] instance pointer to a @p EFlashDriver instance + * @param[out] msec recommended time, in milliseconds, that + * should be spent before calling this + * function again, can be @p NULL + * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_ERASE if the erase operation failed. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @notapi + */ +flash_error_t efl_lld_query_erase(void *instance, uint32_t *msec) { + EFlashDriver *devp = (EFlashDriver *)instance; + + /* If there is an erase in progress then the device must be checked. */ + if (devp->state == FLASH_ERASE) { + /* + * Note: Our implementation waits for erase completion in + * efl_lld_start_erase_sector(), so we should never actually + * be in FLASH_ERASE state when this is called. However, we + * handle it properly for interface compliance. + */ + if (msec != NULL) { + *msec = RP_FLASH_WAIT_TIME_MS; + } + return FLASH_BUSY_ERASING; + } + + return FLASH_NO_ERROR; +} + +/** + * @brief Returns the erase state of a sector. + * + * @param[in] instance pointer to a @p EFlashDriver instance + * @param[in] sector sector to be verified + * @return An error code. + * @retval FLASH_NO_ERROR if the sector is erased. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_VERIFY if the verify operation failed. + * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed. + * + * @notapi + */ +flash_error_t efl_lld_verify_erase(void *instance, flash_sector_t sector) { + EFlashDriver *devp = (EFlashDriver *)instance; + const uint32_t *address; + flash_error_t err = FLASH_NO_ERROR; + unsigned i; + + osalDbgCheck(instance != NULL); + osalDbgCheck(sector < efl_lld_descriptor.sectors_count); + osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE), + "invalid state"); + + /* No verifying while erasing. */ + if (devp->state == FLASH_ERASE) { + return FLASH_BUSY_ERASING; + } + + /* Address of the sector in XIP space. */ + address = (const uint32_t *)(efl_lld_descriptor.address + + flashGetSectorOffset(getBaseFlash(devp), sector)); + + /* FLASH_READ state while the operation is performed. */ + devp->state = FLASH_READ; + + /* Scanning the sector space. */ + for (i = 0U; i < RP_FLASH_SECTOR_SIZE / sizeof(uint32_t); i++) { + if (address[i] != 0xFFFFFFFFU) { + err = FLASH_ERROR_VERIFY; + break; + } + } + + /* Ready state again. */ + devp->state = FLASH_READY; + + return err; +} + +/** + * @brief Reads the flash chip's unique ID. + * @note The JEDEC 0x4B command is issued at runtime, which requires + * exiting and re-entering XIP mode. + * + * @param[in] eflp pointer to a @p EFlashDriver structure + * @param[out] uid pointer to an 8-byte buffer for the unique ID + * + * @api + */ +void efl_lld_read_unique_id(EFlashDriver *eflp, uint8_t *uid) { + uint8_t rx[4U + RP_FLASH_UNIQUE_ID_SIZE]; + syssts_t sts; + + osalDbgCheck((eflp != NULL) && (uid != NULL)); + + /* Allow the application to prepare for XIP becoming unavailable. */ + rpEflBeforeXipOff(); + + sts = osalSysGetStatusAndLockX(); + rp_efl_lld_read_uid_full(eflp, rx, sizeof(rx)); + osalSysRestoreStatusX(sts); + + /* Notify the application that XIP is available again. */ + rpEflAfterXipOn(); + + memcpy(uid, rx + 4U, RP_FLASH_UNIQUE_ID_SIZE); +} + +/** + * @brief Default RP EFL pre-XIP-off hook. + * @details Weak no-op implementation applications may override. + */ +CC_WEAK void rpEflBeforeXipOff(void) { +} + +/** + * @brief Default RP EFL post-XIP-on hook. + * @details Weak no-op implementation applications may override. + */ +CC_WEAK void rpEflAfterXipOn(void) { +} + +#endif /* HAL_USE_EFL == TRUE */ + +/** @} */ diff --git a/os/hal/ports/RP/LLD/EFLv1/rp_efl_lld.h b/os/hal/ports/RP/LLD/EFLv1/rp_efl_lld.h new file mode 100644 index 0000000000..d2df4292a3 --- /dev/null +++ b/os/hal/ports/RP/LLD/EFLv1/rp_efl_lld.h @@ -0,0 +1,52 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file EFLv1/rp_efl_lld.h + * @brief RP EFL shared internal interfaces. + */ + +#ifndef RP_EFL_LLD_H +#define RP_EFL_LLD_H + +#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__) + +#if !defined(__ASSEMBLER__) + +#ifdef __cplusplus +extern "C" { +#endif + void rp_efl_lld_init(void); + void rp_efl_lld_start(EFlashDriver *eflp); + void rp_efl_lld_program_page_full(EFlashDriver *eflp, + uint32_t offset, + const uint8_t *data, + size_t len); + void rp_efl_lld_erase_full(EFlashDriver *eflp, + uint8_t cmd, + uint32_t offset); + void rp_efl_lld_read_uid_full(EFlashDriver *eflp, + uint8_t *rx, + size_t count); +#ifdef __cplusplus +} +#endif + +#endif /* !__ASSEMBLER__ */ + +#endif /* HAL_USE_EFL == TRUE */ + +#endif /* RP_EFL_LLD_H */ diff --git a/os/hal/ports/RP/LLD/EFLv1/rp_efl_lld_api.inc b/os/hal/ports/RP/LLD/EFLv1/rp_efl_lld_api.inc new file mode 100644 index 0000000000..498d1ba051 --- /dev/null +++ b/os/hal/ports/RP/LLD/EFLv1/rp_efl_lld_api.inc @@ -0,0 +1,35 @@ +/** + * @brief Hook invoked immediately before the RP EFL driver disables XIP. + * @details Applications may override this weak hook in order to coordinate + * other cores, park threads, or perform any other preparation + * required before flash becomes temporarily unavailable through XIP. + * @note This hook is called in thread context while XIP is still enabled. + */ +void rpEflBeforeXipOff(void); + +/** + * @brief Hook invoked immediately after the RP EFL driver restores XIP. + * @details Applications may override this weak hook in order to resume the + * coordination established by @p rpEflBeforeXipOff(). + * @note This hook is called in thread context after XIP has been restored. + */ +void rpEflAfterXipOn(void); + +void efl_lld_init(void); +void efl_lld_start(EFlashDriver *eflp); +void efl_lld_stop(EFlashDriver *eflp); +const flash_descriptor_t *efl_lld_get_descriptor(void *instance); +flash_error_t efl_lld_read(void *instance, flash_offset_t offset, + size_t n, uint8_t *rp); +flash_error_t efl_lld_program(void *instance, flash_offset_t offset, + size_t n, const uint8_t *pp); +flash_error_t efl_lld_start_erase_all(void *instance); +flash_error_t efl_lld_start_erase_sector(void *instance, + flash_sector_t sector); +flash_error_t efl_lld_start_erase_block(void *instance, + uint8_t cmd, + uint32_t erase_size, + uint32_t block); +flash_error_t efl_lld_query_erase(void *instance, uint32_t *wait_time); +flash_error_t efl_lld_verify_erase(void *instance, flash_sector_t sector); +void efl_lld_read_unique_id(EFlashDriver *eflp, uint8_t *uid); diff --git a/os/hal/ports/RP/LLD/GPIOv1/hal_pal_lld.c b/os/hal/ports/RP/LLD/GPIOv1/hal_pal_lld.c index e8997f62ec..778bd303ee 100644 --- a/os/hal/ports/RP/LLD/GPIOv1/hal_pal_lld.c +++ b/os/hal/ports/RP/LLD/GPIOv1/hal_pal_lld.c @@ -30,15 +30,21 @@ /* Driver local definitions. */ /*===========================================================================*/ +#define RP_PAL_LINE_REG(line) ((uint32_t)(line) >> 3U) +#define RP_PAL_LINE_SHIFT(line) (4U * ((uint32_t)(line) & 0x07U)) +#define RP_PAL_LINE_MASK(line) (0x0FU << RP_PAL_LINE_SHIFT(line)) +#define RP_PAL_REG_ALIAS_SET 0x2000U +#define RP_PAL_REG_ALIAS_CLR 0x3000U + /*===========================================================================*/ /* Driver exported variables. */ /*===========================================================================*/ #if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__) /** - * @brief Event records for the 30 GPIO lines. + * @brief Event records for GPIO lines. */ -palevent_t _pal_events[30]; +palevent_t _pal_events[RP_GPIO_NUM_LINES]; #endif /*===========================================================================*/ @@ -49,13 +55,51 @@ palevent_t _pal_events[30]; /* Driver local functions. */ /*===========================================================================*/ +static inline void rp_pal_reg_set(volatile uint32_t *reg, uint32_t mask) { + + *(volatile uint32_t *)((uintptr_t)reg + RP_PAL_REG_ALIAS_SET) = mask; +} + +static inline void rp_pal_reg_clr(volatile uint32_t *reg, uint32_t mask) { + + *(volatile uint32_t *)((uintptr_t)reg + RP_PAL_REG_ALIAS_CLR) = mask; +} + +static void rp_pal_pad_set_mode(ioportid_t port, + iopadid_t pad, + iomode_t mode) { + uint32_t ctrlbits, padbits, oebits, bit, abspad; + + ctrlbits = mode & 0x007FFFFFU; + oebits = (mode >> 23U) & 1U; + padbits = mode >> 24U; + bit = 1U << pad; + abspad = ((uint32_t)port << 5U) | (uint32_t)pad; + + if ((pad >= PAL_IOPORTS_WIDTH) || + (((RP_PAL_VALID_MASK(port) >> pad) & 1U) == 0U) || + (abspad >= RP_GPIO_NUM_LINES)) { + return; + } + + /* Release the output driver while reprogramming mux and pad control. */ + RP_PAL_SIO_REG(GPIO_OE_CLR, port) = bit; + + IO_BANK0->GPIO[abspad].CTRL = ctrlbits; + PADS_BANK0->GPIO[abspad] = padbits; + + if (oebits != 0U) { + RP_PAL_SIO_REG(GPIO_OE_SET, port) = bit; + } +} + /*===========================================================================*/ /* Driver interrupt handlers. */ /*===========================================================================*/ #if (PAL_USE_WAIT || PAL_USE_CALLBACKS) || defined(__DOXYGEN__) /** - * @brief EXTI[0], EXTI[1] interrupt handler. + * @brief IO_BANK0 GPIO interrupt handler. * * @isr */ @@ -63,7 +107,7 @@ OSAL_IRQ_HANDLER(RP_IO_IRQ_BANK0_HANDLER) { OSAL_IRQ_PROLOGUE(); - for(int i=0; i < 4; ++i) { + for (int i = 0; i < RP_GPIO_INTR_REGS; ++i) { int line; uint32_t ints = IO_BANK0->PROC[RP_PAL_EVENT_CORE_AFFINITY].INTS[i]; @@ -75,8 +119,8 @@ OSAL_IRQ_HANDLER(RP_IO_IRQ_BANK0_HANDLER) { } ints >>= 4; ++line; - }; - }; + } + } OSAL_IRQ_EPILOGUE(); } @@ -91,15 +135,18 @@ OSAL_IRQ_HANDLER(RP_IO_IRQ_BANK0_HANDLER) { * * @notapi */ -void __pal_lld_init(void) { +void _pal_lld_init(void) { - hal_lld_peripheral_unreset(RESETS_ALLREG_IO_BANK0); - hal_lld_peripheral_unreset(RESETS_ALLREG_PADS_BANK0); + /* Ensures a clean peripheral state */ + rp_peripheral_reset(RESETS_ALLREG_IO_BANK0); + rp_peripheral_reset(RESETS_ALLREG_PADS_BANK0); + rp_peripheral_unreset(RESETS_ALLREG_IO_BANK0); + rp_peripheral_unreset(RESETS_ALLREG_PADS_BANK0); #if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__) unsigned i; - for (i = 0; i < 30; i++) { + for (i = 0U; i < RP_GPIO_NUM_LINES; i++) { _pal_init_event(i); } @@ -107,55 +154,81 @@ void __pal_lld_init(void) { #endif } +/** + * @brief Pads group mode setup. + * @details Programs each selected pad in the specified port using the + * RP pad/mux configuration helper. + * + * @param[in] port port identifier + * @param[in] mask group mask, already shifted to port bit positions + * @param[in] mode group mode + * + * @notapi + */ +void _pal_lld_setgroupmode(ioportid_t port, + ioportmask_t mask, + iomode_t mode) { + iopadid_t pad = 0U; + + while (mask != 0U) { + if ((mask & 1U) != 0U) { + rp_pal_pad_set_mode(port, pad, mode); + } + mask >>= 1U; + pad++; + } +} + #if (PAL_USE_WAIT || PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +bool _pal_lld_ispadeventenabled(ioportid_t port, iopadid_t pad) { + ioline_t line = PAL_LINE(port, pad); + + return (bool)((IO_BANK0->PROC[RP_PAL_EVENT_CORE_AFFINITY] + .INTE[RP_PAL_LINE_REG(line)] & + RP_PAL_LINE_MASK(line)) != 0U); +} + /** - * @brief Pad event enable. + * @brief Line event enable. * @note Programming an unknown or unsupported mode is silently ignored. * - * @param[in] line line number within the port + * @param[in] line line identifier * @param[in] mode line event mode * * @notapi */ void _pal_lld_enablelineevent(ioline_t line, ioeventmode_t mode) { - osalDbgAssert( - !(IO_BANK0->PROC[RP_PAL_EVENT_CORE_AFFINITY].INTE[line/8] & (0x0FU << (4U*(line & 0x07U)))), - "channel in use"); - - uint32_t mode_set = 0; - uint32_t mode_clr = 0; - - /* Programming the edge and level triggers.*/ - if (mode & PAL_EVENT_MODE_RISING_EDGE) - mode_set |= 8; - else - mode_clr |= 8; - - if (mode & PAL_EVENT_MODE_FALLING_EDGE) - mode_set |= 4; - else - mode_clr |= 4; - - if (mode & RP_PAL_EVENT_MODE_LEVEL_LOW) - mode_set |= 1; - else - mode_clr |= 1; - - if (mode & RP_PAL_EVENT_MODE_LEVEL_HIGH) - mode_set |= 2; - else - mode_clr |= 2; - + uint32_t inte = 0U; + uint32_t reg = RP_PAL_LINE_REG(line); + uint32_t shift = RP_PAL_LINE_SHIFT(line); + uint32_t mask = RP_PAL_LINE_MASK(line); + volatile uint32_t *inte_reg = + &IO_BANK0->PROC[RP_PAL_EVENT_CORE_AFFINITY].INTE[reg]; + + osalDbgAssert((IO_BANK0->PROC[RP_PAL_EVENT_CORE_AFFINITY].INTE[reg] & + mask) == 0U, "channel in use"); + + if (mode & PAL_EVENT_MODE_RISING_EDGE) { + inte |= 8U; + } + if (mode & PAL_EVENT_MODE_FALLING_EDGE) { + inte |= 4U; + } + if (mode & RP_PAL_EVENT_MODE_LEVEL_LOW) { + inte |= 1U; + } + if (mode & RP_PAL_EVENT_MODE_LEVEL_HIGH) { + inte |= 2U; + } - IO_BANK0->PROC[RP_PAL_EVENT_CORE_AFFINITY].INTE[line/8] &= - ~(mode_clr << (4*(line & 0x07))); - IO_BANK0->PROC[RP_PAL_EVENT_CORE_AFFINITY].INTE[line/8] |= - mode_set << (4*(line & 0x07)); -}; + IO_BANK0->INTR[reg] = mask; + rp_pal_reg_clr(inte_reg, mask); + rp_pal_reg_set(inte_reg, inte << shift); +} /** - * @brief Pad event disable. + * @brief Line event disable. * @details This function disables previously programmed event callbacks. * * @param[in] line line identifier @@ -163,9 +236,21 @@ void _pal_lld_enablelineevent(ioline_t line, ioeventmode_t mode) { * @notapi */ void _pal_lld_disablelineevent(ioline_t line) { - IO_BANK0->PROC[RP_PAL_EVENT_CORE_AFFINITY].INTE[line/8] &= - ~(0x0FU << (4*(line & 0x07))); -}; + uint32_t reg = RP_PAL_LINE_REG(line); + uint32_t mask = RP_PAL_LINE_MASK(line); + volatile uint32_t *inte_reg = + &IO_BANK0->PROC[RP_PAL_EVENT_CORE_AFFINITY].INTE[reg]; + + rp_pal_reg_clr(inte_reg, mask); + + /* Clear pending interrupt status. INTR is W1C.*/ + IO_BANK0->INTR[reg] = mask; + +#if PAL_USE_CALLBACKS || PAL_USE_WAIT + /* Callback cleared and/or thread reset.*/ + _pal_clear_event(line); +#endif +} /** * @brief Force a trigger event on the line. @@ -173,13 +258,16 @@ void _pal_lld_disablelineevent(ioline_t line) { * @param[in] line identifier */ void _pal_lld_forcelineevent(ioline_t line) { - uint32_t force_mask = - IO_BANK0->PROC[RP_PAL_EVENT_CORE_AFFINITY].INTE[line/8] & - (0x0FU << (4*(line & 0x07))); - - IO_BANK0->PROC[RP_PAL_EVENT_CORE_AFFINITY].INTF[line/8] &= ~force_mask; - IO_BANK0->PROC[RP_PAL_EVENT_CORE_AFFINITY].INTF[line/8] |= force_mask; -}; + uint32_t reg = RP_PAL_LINE_REG(line); + volatile uint32_t *intf = + &IO_BANK0->PROC[RP_PAL_EVENT_CORE_AFFINITY].INTF[reg]; + uint32_t force_mask = IO_BANK0->PROC[RP_PAL_EVENT_CORE_AFFINITY].INTE[reg] & + RP_PAL_LINE_MASK(line); + + /* Clear then set only the target bits, without an RMW race on sibling bits. */ + rp_pal_reg_clr(intf, force_mask); + rp_pal_reg_set(intf, force_mask); +} /** * @brief Clear all forced trigger event on the line. @@ -187,12 +275,14 @@ void _pal_lld_forcelineevent(ioline_t line) { * @param[in] line identifier */ void _pal_lld_unforcelineevent(ioline_t line) { - uint32_t force_mask = - IO_BANK0->PROC[RP_PAL_EVENT_CORE_AFFINITY].INTE[line/8] & - (0x0FU << (4*(line & 0x07))); + uint32_t reg = RP_PAL_LINE_REG(line); + volatile uint32_t *intf = + &IO_BANK0->PROC[RP_PAL_EVENT_CORE_AFFINITY].INTF[reg]; + uint32_t force_mask = IO_BANK0->PROC[RP_PAL_EVENT_CORE_AFFINITY].INTE[reg] & + RP_PAL_LINE_MASK(line); - IO_BANK0->PROC[RP_PAL_EVENT_CORE_AFFINITY].INTF[line/8] &= ~force_mask; -}; + rp_pal_reg_clr(intf, force_mask); +} #endif diff --git a/os/hal/ports/RP/LLD/GPIOv1/hal_pal_lld.h b/os/hal/ports/RP/LLD/GPIOv1/hal_pal_lld.h index 8418c9d919..6da515c966 100644 --- a/os/hal/ports/RP/LLD/GPIOv1/hal_pal_lld.h +++ b/os/hal/ports/RP/LLD/GPIOv1/hal_pal_lld.h @@ -53,15 +53,15 @@ #define PAL_RP_IOCTRL_INOVER_DRVLOW (2U << 16) #define PAL_RP_IOCTRL_INOVER_DRVHIGH (3U << 16) -#define PAL_RP_IOCTRL_OEOVER_DRVPERI (0U << 12) -#define PAL_RP_IOCTRL_OEOVER_DRVINVPERI (1U << 12) -#define PAL_RP_IOCTRL_OEOVER_DISABLE (2U << 12) -#define PAL_RP_IOCTRL_OEOVER_ENABLE (3U << 12) +#define PAL_RP_IOCTRL_OEOVER_DRVPERI (0U << RP_GPIO_IOCTRL_OEOVER_Pos) +#define PAL_RP_IOCTRL_OEOVER_DRVINVPERI (1U << RP_GPIO_IOCTRL_OEOVER_Pos) +#define PAL_RP_IOCTRL_OEOVER_DISABLE (2U << RP_GPIO_IOCTRL_OEOVER_Pos) +#define PAL_RP_IOCTRL_OEOVER_ENABLE (3U << RP_GPIO_IOCTRL_OEOVER_Pos) -#define PAL_RP_IOCTRL_OUTOVER_DRVPERI (0U << 8) -#define PAL_RP_IOCTRL_OUTOVER_DRVINVPERI (1U << 8) -#define PAL_RP_IOCTRL_OUTOVER_DRVLOW (2U << 8) -#define PAL_RP_IOCTRL_OUTOVER_DRVHIGH (3U << 8) +#define PAL_RP_IOCTRL_OUTOVER_DRVPERI (0U << RP_GPIO_IOCTRL_OUTOVER_Pos) +#define PAL_RP_IOCTRL_OUTOVER_DRVINVPERI (1U << RP_GPIO_IOCTRL_OUTOVER_Pos) +#define PAL_RP_IOCTRL_OUTOVER_DRVLOW (2U << RP_GPIO_IOCTRL_OUTOVER_Pos) +#define PAL_RP_IOCTRL_OUTOVER_DRVHIGH (3U << RP_GPIO_IOCTRL_OUTOVER_Pos) #define PAL_RP_IOCTRL_FUNCSEL(n) ((n) << 0) #define PAL_RP_IOCTRL_FUNCSEL_SPI PAL_RP_IOCTRL_FUNCSEL(1U) @@ -71,7 +71,6 @@ #define PAL_RP_IOCTRL_FUNCSEL_SIO PAL_RP_IOCTRL_FUNCSEL(5U) #define PAL_RP_IOCTRL_FUNCSEL_PIO0 PAL_RP_IOCTRL_FUNCSEL(6U) #define PAL_RP_IOCTRL_FUNCSEL_PIO1 PAL_RP_IOCTRL_FUNCSEL(7U) -#define PAL_RP_IOCTRL_FUNCSEL_USB PAL_RP_IOCTRL_FUNCSEL(9U) #define PAL_RP_IOCTRL_FUNCSEL_NULL PAL_RP_IOCTRL_FUNCSEL(31U) #define PAL_RP_GPIO_OE (1U << (23 + 0)) @@ -94,6 +93,8 @@ #define PAL_RP_PAD_SLEWFAST (1U << (24 + 0)) /** @} */ +#include "rp_pal_lld.h" + /** * @name RP-specific I/O event flags * @{ @@ -102,6 +103,11 @@ #define RP_PAL_EVENT_MODE_LEVEL_HIGH 8U /** @} */ +#if !defined(RP_PAL_EVENT_CORE_AFFINITY) + /** @brief Core that handles all the PAL event interrupts. */ + #define RP_PAL_EVENT_CORE_AFFINITY 0 +#endif + /** * @name Alternate functions * @{ @@ -117,8 +123,6 @@ #define PAL_MODE_ALTERNATE_SIO (PAL_MODE_ALTERNATE(5U)) #define PAL_MODE_ALTERNATE_PIO0 (PAL_MODE_ALTERNATE(6U)) #define PAL_MODE_ALTERNATE_PIO1 (PAL_MODE_ALTERNATE(7U)) -#define PAL_MODE_ALTERNATE_CLK (PAL_MODE_ALTERNATE(8U)) -#define PAL_MODE_ALTERNATE_USB (PAL_MODE_ALTERNATE(9U)) /** @} */ /** @@ -158,6 +162,9 @@ /** * @brief Input pad with weak pull down resistor. + * @note On RP2350 revisions affected by erratum RP2350-E9, the internal + * pull-down may not behave as expected with the input buffer + * enabled. This driver does not apply a workaround automatically. */ #define PAL_MODE_INPUT_PULLDOWN (PAL_RP_IOCTRL_FUNCSEL_SIO | \ PAL_RP_PAD_IE | \ @@ -197,35 +204,6 @@ #define PAL_WHOLE_PORT ((ioportmask_t)0xFFFFFFFF) /** @} */ -/** - * @name Line handling macros - * @{ - */ -/** - * @brief Forms a line identifier. - * @details A port/pad pair are encoded into an @p ioline_t type. The encoding - * of this type is platform-dependent. - * @note In this driver the pad number is encoded in the lower 4 bits of - * the GPIO address which are guaranteed to be zero. - */ -#define PAL_LINE(port, pad) ((pad), (port)) - -/** - * @brief Decodes a port identifier from a line identifier. - */ -#define PAL_PORT(line) 0U - -/** - * @brief Decodes a pad identifier from a line identifier. - */ -#define PAL_PAD(line) (line) - -/** - * @brief Value identifying an invalid line. - */ -#define PAL_NOLINE 0U -/** @} */ - /** * @brief Type of digital I/O port sized unsigned integer. */ @@ -259,17 +237,71 @@ typedef uint32_t ioportid_t; */ typedef uint32_t iopadid_t; +#define RP_PAL_IOPORTS_COUNT ((RP_GPIO_NUM_LINES + 31U) / 32U) + +#if RP_GPIO_NUM_LINES >= 32U + #define RP_PAL_PORT0_VALID_MASK 0xFFFFFFFFU +#else + #define RP_PAL_PORT0_VALID_MASK ((1U << RP_GPIO_NUM_LINES) - 1U) +#endif + +#if RP_GPIO_NUM_LINES > 32U + #define RP_PAL_PORT1_VALID_MASK ((1U << (RP_GPIO_NUM_LINES - 32U)) - 1U) + #define RP_PAL_VALID_MASK(port) \ + ((uint32_t)(port) == 0U ? RP_PAL_PORT0_VALID_MASK : RP_PAL_PORT1_VALID_MASK) +#else + #define RP_PAL_VALID_MASK(port) RP_PAL_PORT0_VALID_MASK +#endif + +/** + * @name Line handling macros + * @{ + */ +/** + * @brief Forms a line identifier. + * @details A port/pad pair are encoded into an @p ioline_t type. The encoding + * of this type is platform-dependent. + * @note In this driver a line is the absolute GPIO number obtained by + * adding the port base to the port-relative pad number. + */ +#define PAL_LINE(port, pad) \ + ((ioline_t)(((uint32_t)(port) << 5U) | (uint32_t)(pad))) + +/** + * @brief Decodes a port identifier from a line identifier. + */ +#define PAL_PORT(line) \ + ((ioportid_t)((uint32_t)(line) >> 5U)) + +/** + * @brief Decodes a pad identifier from a line identifier. + */ +#define PAL_PAD(line) \ + ((iopadid_t)((uint32_t)(line) & 31U)) + +/** + * @brief Value identifying an invalid line. + */ +#define PAL_NOLINE 0xFFFFFFFFU +/** @} */ + /*===========================================================================*/ /* I/O Ports Identifiers. */ -/* The low level driver wraps the definitions already present in the STM32 */ -/* firmware library. */ +/* The low level driver exposes RP GPIO banks as PAL ports. */ /*===========================================================================*/ /** - * @brief User port identifier. + * @brief RP GPIO low port identifier. */ #define IOPORT1 0U +#if RP_GPIO_NUM_LINES > 32U || defined(__DOXYGEN__) +/** + * @brief RP GPIO high port identifier. + */ +#define IOPORT2 1U +#endif + /*===========================================================================*/ /* Implementation, some of the following macros could be implemented as */ /* functions, if so please put them in pal_lld.c. */ @@ -280,7 +312,7 @@ typedef uint32_t iopadid_t; * * @notapi */ -#define pal_lld_init() __pal_lld_init() +#define pal_lld_init() _pal_lld_init() /** * @brief Reads the physical I/O port states. @@ -290,7 +322,8 @@ typedef uint32_t iopadid_t; * * @notapi */ -#define pal_lld_readport(port) (SIO->GPIO_IN) +#define pal_lld_readport(port) \ + ((ioportmask_t)RP_PAL_SIO_REG(GPIO_IN, (port))) /** * @brief Reads the output latch. @@ -302,7 +335,8 @@ typedef uint32_t iopadid_t; * * @notapi */ -#define pal_lld_readlatch(port) (SIO->GPIO_OUT) +#define pal_lld_readlatch(port) \ + ((ioportmask_t)RP_PAL_SIO_REG(GPIO_OUT, (port))) /** * @brief Writes a bits mask on a I/O port. @@ -312,10 +346,14 @@ typedef uint32_t iopadid_t; * * @notapi */ +/* @note On RP2350, IOPORT2 maps to SIO GPIO_HI_OUT which is shared with + * QSPI/USB outputs in bits 31:16. This is a raw full-register write; + * use palSetPort()/palClearPort()/palTogglePort() when non-PAL high + * bits must be preserved. + */ #define pal_lld_writeport(port, bits) \ do { \ - (void)port; \ - SIO->GPIO_OUT = (bits); \ + RP_PAL_SIO_REG(GPIO_OUT, (port)) = (uint32_t)(bits); \ } while (false) /** @@ -331,8 +369,9 @@ typedef uint32_t iopadid_t; */ #define pal_lld_setport(port, bits) \ do { \ - (void)port; \ - SIO->GPIO_OUT_SET = (bits); \ + osalDbgAssert(((uint32_t)(bits) & ~(uint32_t)RP_PAL_VALID_MASK(port)) \ + == 0U, "invalid port bits"); \ + RP_PAL_SIO_REG(GPIO_OUT_SET, (port)) = (uint32_t)(bits); \ } while (false) /** @@ -348,8 +387,9 @@ typedef uint32_t iopadid_t; */ #define pal_lld_clearport(port, bits) \ do { \ - (void)port; \ - SIO->GPIO_OUT_CLR = (bits); \ + osalDbgAssert(((uint32_t)(bits) & ~(uint32_t)RP_PAL_VALID_MASK(port)) \ + == 0U, "invalid port bits"); \ + RP_PAL_SIO_REG(GPIO_OUT_CLR, (port)) = (uint32_t)(bits); \ } while (false) /** @@ -365,60 +405,34 @@ typedef uint32_t iopadid_t; */ #define pal_lld_toggleport(port, bits) \ do { \ - (void)port; \ - SIO->GPIO_OUT_XOR = (bits); \ + osalDbgAssert(((uint32_t)(bits) & ~(uint32_t)RP_PAL_VALID_MASK(port)) \ + == 0U, "invalid port bits"); \ + RP_PAL_SIO_REG(GPIO_OUT_XOR, (port)) = (uint32_t)(bits); \ } while (false) /** - * @brief Pad mode setup. - * @details This function programs a pad with the specified mode. - * @note The operation is not guaranteed to be atomic on all the - * architectures, for atomicity and/or portability reasons you may - * need to enclose port I/O operations between @p osalSysLock() and - * @p osalSysUnlock(). - * @note Programming an unknown or unsupported mode is silently ignored. - * @note The function can be called from any context. + * @brief Pads group mode setup. * * @param[in] port port identifier - * @param[in] pad pad number within the port - * @param[in] mode pad mode + * @param[in] mask group mask + * @param[in] offset group bit offset within the port + * @param[in] mode group mode * * @notapi */ -#define pal_lld_setpadmode(port, pad, mode) \ - __pal_lld_pad_set_mode(port, pad, mode) - -__STATIC_INLINE void __pal_lld_pad_set_mode(ioportid_t port, - iopadid_t pad, - iomode_t mode) { - uint32_t ctrlbits, padbits, oebits; - - (void)port; - - ctrlbits = (mode & 0x007FFFFFU) >> 0U; - oebits = (mode & 0x00800000U) >> 23U; - padbits = (mode & 0xFF000000U) >> 24U; +#define pal_lld_setgroupmode(port, mask, offset, mode) \ + _pal_lld_setgroupmode(port, (mask) << (offset), mode) - /* Setting up GPIO direction first.*/ - if (oebits != 0U) { - SIO->GPIO_OE_SET = 1U << pad; - } - else { - SIO->GPIO_OE_CLR = 1U << pad; - } +#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) - /* Then IO and PAD settings.*/ - IO_BANK0->GPIO[pad].CTRL = ctrlbits; - PADS_BANK0->GPIO[pad] = padbits; -} +#define pal_lld_enablepadevent(port, pad, mode) \ + _pal_lld_enablelineevent(PAL_LINE(port, pad), mode) +#define pal_lld_disablepadevent(port, pad) \ + _pal_lld_disablelineevent(PAL_LINE(port, pad)) -#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) - -#if !defined(RP_PAL_EVENT_CORE_AFFINITY) - /** @brief Core that handles all the PAL event interrupts. */ - #define RP_PAL_EVENT_CORE_AFFINITY 0 -#endif +#define pal_lld_ispadeventenabled(port, pad) \ + _pal_lld_ispadeventenabled(port, pad) #if !defined(RP_IO_IRQ_BANK0_PRIORITY) /** @brief IRQ priority of the external pad events. */ @@ -426,7 +440,7 @@ __STATIC_INLINE void __pal_lld_pad_set_mode(ioportid_t port, #endif #if !defined(__DOXYGEN__) -extern palevent_t _pal_events[30]; +extern palevent_t _pal_events[RP_GPIO_NUM_LINES]; #endif /** @@ -448,30 +462,7 @@ extern palevent_t _pal_events[30]; * @notapi */ #define pal_lld_get_pad_event(port, pad) \ - &_pal_events[pad]; (void)(port) - -/** - * @brief Line event enable. - * @note Programming an unknown or unsupported mode is silently ignored. - * - * @param[in] line line number - * @param[in] mode line event mode - * - * @notapi - */ -#define pal_lld_enablelineevent(line, mode) \ - _pal_lld_enablelineevent(line, mode) - -/** - * @brief Line event disable. - * @details This function disables previously programmed event callbacks. - * - * @param[in] line line identifier - * - * @notapi - */ -#define pal_lld_disablelineevent(line) \ - _pal_lld_disablelineevent(line) + &_pal_events[PAL_LINE(port, pad)] /** * @brief Force a trigger event on the line. @@ -480,7 +471,7 @@ extern palevent_t _pal_events[30]; * * @notapi */ -#define pal_lld_forcelineevent(line) \ +#define pal_lld_forcelineevent(line) \ _pal_lld_forcelineevent(line) /** @@ -490,7 +481,7 @@ extern palevent_t _pal_events[30]; * * @notapi */ -#define pal_lld_unforcelineevent(line) \ +#define pal_lld_unforcelineevent(line) \ _pal_lld_unforcelineevent(line) #endif /* (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) */ @@ -498,17 +489,17 @@ extern palevent_t _pal_events[30]; #ifdef __cplusplus extern "C" { #endif + void _pal_lld_setgroupmode(ioportid_t port, + ioportmask_t mask, + iomode_t mode); + void _pal_lld_init(void); +#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) + bool _pal_lld_ispadeventenabled(ioportid_t port, iopadid_t pad); void _pal_lld_enablelineevent(ioline_t line, ioeventmode_t mode); void _pal_lld_disablelineevent(ioline_t line); -#ifdef __cplusplus -} -#endif - - -#ifdef __cplusplus -extern "C" { + void _pal_lld_forcelineevent(ioline_t line); + void _pal_lld_unforcelineevent(ioline_t line); #endif - void __pal_lld_init(void); #ifdef __cplusplus } #endif diff --git a/os/hal/ports/RP/LLD/I2Cv1/driver.mk b/os/hal/ports/RP/LLD/I2Cv1/driver.mk new file mode 100644 index 0000000000..9dba193f43 --- /dev/null +++ b/os/hal/ports/RP/LLD/I2Cv1/driver.mk @@ -0,0 +1,9 @@ +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/RP/LLD/I2Cv1/hal_i2c_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/RP/LLD/I2Cv1/hal_i2c_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/RP/LLD/I2Cv1 diff --git a/os/hal/ports/RP/LLD/I2Cv1/hal_i2c_lld.c b/os/hal/ports/RP/LLD/I2Cv1/hal_i2c_lld.c index 967a692907..b9b62f39cd 100644 --- a/os/hal/ports/RP/LLD/I2Cv1/hal_i2c_lld.c +++ b/os/hal/ports/RP/LLD/I2Cv1/hal_i2c_lld.c @@ -1,4 +1,6 @@ /* + ChibiOS - Copyright (C) 2022 Stefan Kerkmann. + ChibiOS - Copyright (C) 2021 Hanya. ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,8 +17,8 @@ */ /** - * @file hal_i2c_lld.c - * @brief RP2040 I2C subsystem low level driver source. + * @file I2Cv1/hal_i2c_lld.c + * @brief RP I2C subsystem low level driver source. * * @addtogroup I2C * @{ @@ -34,10 +36,17 @@ /* Driver exported variables. */ /*===========================================================================*/ +/** + * @brief I2C0 driver identifier. + */ +#if (RP_I2C_USE_I2C0 == TRUE) || defined(__DOXYGEN__) +I2CDriver I2CD0; +#endif + /** * @brief I2C1 driver identifier. */ -#if (PLATFORM_I2C_USE_I2C1 == TRUE) || defined(__DOXYGEN__) +#if (RP_I2C_USE_I2C1 == TRUE) || defined(__DOXYGEN__) I2CDriver I2CD1; #endif @@ -45,14 +54,334 @@ I2CDriver I2CD1; /* Driver local variables and types. */ /*===========================================================================*/ +#define I2C_OVERRUN_ERRORS \ + (I2C_IC_INTR_STAT_R_RX_OVER | I2C_IC_INTR_STAT_R_RX_UNDER | \ + I2C_IC_INTR_STAT_R_TX_OVER) + +#define I2C_ERROR_INTERRUPTS \ + (I2C_IC_INTR_MASK_M_TX_ABRT | I2C_IC_INTR_MASK_M_TX_OVER | \ + I2C_IC_INTR_MASK_M_RX_OVER | I2C_IC_INTR_MASK_M_RX_UNDER) + /*===========================================================================*/ /* Driver local functions. */ /*===========================================================================*/ +/** + * @brief Calculates the waiting time which is 10 times the SCL period + * duration. + */ +static sysinterval_t i2c_lld_get_wait_time(I2CDriver *i2cp) { + uint32_t baudrate = i2cp->config->baudrate; + if (baudrate <= 100000U) { + return OSAL_US2I(100); + } else if (baudrate <= 400000U) { + return OSAL_US2I(25); + } else { + return OSAL_US2I(10); + } +} + +/** + * @brief Tries to disable the I2C peripheral. + */ +static msg_t i2c_lld_disableS(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + systime_t start, end; + msg_t ok = MSG_OK; + + /* Calculating the time window for the timeout on the enable condition. */ + start = osalOsGetSystemTimeX(); + end = osalTimeAddX(start, i2c_lld_get_wait_time(i2cp)); + + dp->ENABLE &= ~I2C_IC_ENABLE_ENABLE; + + osalSysUnlock(); + while ((dp->ENABLESTATUS & I2C_IC_ENABLE_STATUS_IC_EN) != 0U) { + osalSysLock(); + if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { + ok = MSG_TIMEOUT; + } + osalSysUnlock(); + + if (ok != MSG_OK) { + break; + } + } + osalSysLock(); + + return ok; +} + +/** + * @brief Aborts any ongoing transmission of the I2C peripheral. + */ +static msg_t i2c_lld_abort_transmissionS(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + systime_t start, end; + msg_t ok = MSG_OK; + + /* Calculating the time window for the timeout on the abort condition. */ + start = osalOsGetSystemTimeX(); + end = osalTimeAddX(start, i2c_lld_get_wait_time(i2cp)); + + /* Disable all interrupts as a pre-caution. */ + dp->INTRMASK = 0U; + /* Enable peripheral to issue abort. */ + dp->ENABLE |= I2C_IC_ENABLE_ENABLE; + /* Issue abort. */ + dp->ENABLE |= I2C_IC_ENABLE_ABORT; + + osalSysUnlock(); + /* Wait for the transmission to be aborted. */ + while ((dp->RAWINTRSTAT & I2C_IC_INTR_STAT_R_TX_ABRT) == 0U) { + osalSysLock(); + if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { + ok = MSG_TIMEOUT; + } + osalSysUnlock(); + if (ok != MSG_OK) { + break; + } + } + osalSysLock(); + + (void)dp->CLRTXABRT; + return ok; +} + +/** + * @brief Handles transmission errors by waking the sleeping thread + * and setting the error reasons. + */ +static void i2c_lld_handle_errors(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + + if (dp->TXABRTSOURCE & I2C_IC_TX_ABRT_SOURCE_ARB_LOST) { + i2cp->errors |= I2C_ARBITRATION_LOST; + } + + if (dp->RAWINTRSTAT & I2C_OVERRUN_ERRORS) { + i2cp->errors |= I2C_OVERRUN; + } + + /* Disable all interrupts. */ + dp->INTRMASK = 0U; + (void)dp->CLRINTR; + (void)dp->CLRTXABRT; + _i2c_wakeup_error_isr(i2cp); +} + +/** + * @brief Calculates and set up clock settings. + */ +static void i2c_lld_setup_frequency(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + + halfreq_t freq_in = halClockGetPointX(RP_CLK_SYS); + + const uint32_t baudrate = i2cp->config->baudrate; + const uint32_t period = (freq_in + baudrate / 2U) / baudrate; + + uint32_t lcnt, hcnt, sda_tx_hold_count; + + if (baudrate <= 100000U) { + /* Standard Mode: H: 4000ns, L: 4700ns ~ 0.54. */ + lcnt = period * 54U / 100U; + } else if (baudrate <= 400000U) { + /* Fast Mode: H: 600ns, L: 1300ns ~ 0.68. */ + lcnt = period * 68U / 100U; + } else { + /* Fast Mode Plus: H: 500ns, L: 760ns ~ 0.60. */ + lcnt = period * 60U / 100U; + } + hcnt = period - lcnt; + + osalDbgAssert((lcnt >= 8) && + (lcnt <= I2C_IC_FS_SCL_LCNT) && + (hcnt >= 8) && + (hcnt <= I2C_IC_FS_SCL_HCNT), + "Invalid I2C clock parameters."); + + if (baudrate < 1000000U) { + /* Standard and Fast Mode: + sda_tx_hold_count = freq_in [cycles/s] * 300ns * (1s / 1e9ns) + Reduce 300/1e9 to 3/1e7 to avoid numbers that don't fit in u32. + Add 1 to avoid division truncation. */ + sda_tx_hold_count = ((freq_in * 3U) / 10000000U) + 1U; + } else { + /* Fast Mode Plus: + sda_tx_hold_count = freq_in [cycles/s] * 120ns * (1s / 1e9ns) + Reduce 120/1e9 to 3/25e6 to avoid numbers that don't fit in u32. + Add 1 to avoid division truncation. */ + sda_tx_hold_count = ((freq_in * 3U) / 25000000U) + 1U; + } + osalDbgCheck(sda_tx_hold_count <= lcnt - 2U); + + dp->FSSCLHCNT = hcnt & I2C_IC_FS_SCL_HCNT; + dp->FSSCLLCNT = lcnt & I2C_IC_FS_SCL_LCNT; + dp->FSSPKLEN = (lcnt < 16 ? 1 : lcnt / 16) & I2C_IC_FS_SPKLEN_IC_FS_SPKLEN; + dp->SDAHOLD = sda_tx_hold_count & I2C_IC_SDA_HOLD_IC_SDA_TX_HOLD; +} + +/** + * @brief Requests data to be received, actual reception is done in the + * interrupt handler. + */ +static void i2c_lld_request_data(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + uint32_t data = I2C_IC_DATA_CMD_CMD; + + /* RP Designware I2C peripheral has FIFO depth of 16 elements. As we + specify that the TX_EMPTY interrupt only fires if the TX FIFO is + truly empty we don't need to check the current fill level. */ + uint32_t batch = i2cp->rxbytes < 16U ? (uint32_t)i2cp->rxbytes : 16U; + + if (i2cp->send_restart) { + data |= I2C_IC_DATA_CMD_RESTART; + i2cp->send_restart = false; + } + + /* Setup RX FIFO trigger level to only trigger when the batch has been + completely received. Therefore we don't need to check if there are any + bytes still pending to be received. */ + dp->RXTL = batch > 1U ? batch - 1U : 0U; + + while (batch > 0U) { + /* Send STOP after last byte. */ + if (i2cp->rxbytes == 1U) { + data |= I2C_IC_DATA_CMD_STOP; + } + dp->DATACMD = data; + + batch--; + i2cp->rxbytes--; + data = I2C_IC_DATA_CMD_CMD; + } + + /* Clear TX FIFO empty interrupt, it will be re-activated when data has + been received. */ + dp->CLR.INTRMASK = I2C_IC_INTR_MASK_M_TX_EMPTY; + /* Enable RX FULL interrupt to process received data. */ + dp->SET.INTRMASK = I2C_IC_INTR_STAT_R_RX_FULL; +} + +/** + * @brief Fills TX FIFO with data to be sent. + */ +static void i2c_lld_transmit_data(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + uint32_t data; + + while (i2cp->txbytes > 0U && dp->STATUS & I2C_IC_STATUS_TFNF) { + data = (uint32_t)*i2cp->txptr; + + /* Send STOP after last byte. */ + if (i2cp->txbytes == 1U) { + data |= I2C_IC_DATA_CMD_STOP; + } + dp->DATACMD = data; + + i2cp->txptr++; + i2cp->txbytes--; + } + + /* Nothing more to send, disable TX FIFO empty interrupt. */ + if (i2cp->txbytes == 0U) { + dp->CLR.INTRMASK = I2C_IC_INTR_MASK_M_TX_EMPTY; + } +} + +/** + * @brief I2C shared ISR code. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ +static void i2c_lld_serve_interrupt(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + uint32_t intr = dp->INTRSTAT; + + /* Transmission error detected. */ + if (intr & I2C_ERROR_INTERRUPTS) { + return i2c_lld_handle_errors(i2cp); + } + + /* If the TX FIFO is empty we can request or send more data. */ + if (intr & I2C_IC_INTR_STAT_R_TX_EMPTY) { + if (i2cp->state == I2C_ACTIVE_TX) { + i2c_lld_transmit_data(i2cp); + } else { + i2c_lld_request_data(i2cp); + } + return; + } + + if (intr & I2C_IC_INTR_STAT_R_RX_FULL) { + while (dp->STATUS & I2C_IC_STATUS_RFNE) { + /* Read out received data. */ + *i2cp->rxptr = (uint8_t)dp->DATACMD; + i2cp->rxptr++; + } + + if (i2cp->rxbytes == 0U) { + /* Everything is received, therefore disable all FIFO IRQs. */ + dp->CLR.INTRMASK = I2C_IC_INTR_MASK_M_RX_FULL | + I2C_IC_INTR_STAT_R_TX_EMPTY; + } else { + /* Enable TX FIFO empty IRQ to request more data. */ + dp->SET.INTRMASK = I2C_IC_INTR_STAT_R_TX_EMPTY; + } + return; + } + + if (intr & I2C_IC_INTR_STAT_R_STOP_DET) { + /* Clear irq flag. */ + (void)dp->CLRSTOPDET; + if (i2cp->state == I2C_ACTIVE_TX && i2cp->rxbytes > 0U) { + /* State change to RX. */ + i2cp->state = I2C_ACTIVE_RX; + /* Restart communication. */ + i2cp->send_restart = true; + + /* Enable TX FIFO empty IRQ to request more data to be received. */ + dp->SET.INTRMASK = I2C_IC_INTR_STAT_R_TX_EMPTY; + return; + } + } + + /* Transmission complete, disable and clear all interrupts. */ + dp->INTRMASK = 0U; + (void)dp->CLRINTR; + _i2c_wakeup_isr(i2cp); +} + /*===========================================================================*/ /* Driver interrupt handlers. */ /*===========================================================================*/ +#if (RP_I2C_USE_I2C0 == TRUE) || defined(__DOXYGEN__) + +OSAL_IRQ_HANDLER(RP_I2C0_IRQ_HANDLER) { + OSAL_IRQ_PROLOGUE(); + + i2c_lld_serve_interrupt(&I2CD0); + + OSAL_IRQ_EPILOGUE(); +} + +#endif + +#if (RP_I2C_USE_I2C1 == TRUE) || defined(__DOXYGEN__) + +OSAL_IRQ_HANDLER(RP_I2C1_IRQ_HANDLER) { + OSAL_IRQ_PROLOGUE(); + + i2c_lld_serve_interrupt(&I2CD1); + + OSAL_IRQ_EPILOGUE(); +} + +#endif + /*===========================================================================*/ /* Driver exported functions. */ /*===========================================================================*/ @@ -64,8 +393,22 @@ I2CDriver I2CD1; */ void i2c_lld_init(void) { -#if PLATFORM_I2C_USE_I2C1 == TRUE +#if RP_I2C_USE_I2C0 == TRUE + i2cObjectInit(&I2CD0); + I2CD0.i2c = I2C0; + I2CD0.thread = NULL; + + /* Reset I2C. */ + rp_peripheral_reset(RESETS_ALLREG_I2C0); +#endif + +#if RP_I2C_USE_I2C1 == TRUE i2cObjectInit(&I2CD1); + I2CD1.i2c = I2C1; + I2CD1.thread = NULL; + + /* Reset I2C. */ + rp_peripheral_reset(RESETS_ALLREG_I2C1); #endif } @@ -77,16 +420,69 @@ void i2c_lld_init(void) { * @notapi */ void i2c_lld_start(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; if (i2cp->state == I2C_STOP) { - /* Enables the peripheral.*/ -#if PLATFORM_I2C_USE_I2C1 == TRUE + +#if RP_I2C_USE_I2C0 == TRUE + if (&I2CD0 == i2cp) { + rp_peripheral_unreset(RESETS_ALLREG_I2C0); + + nvicEnableVector(RP_I2C0_IRQ_NUMBER, RP_IRQ_I2C0_PRIORITY); + } +#endif + +#if RP_I2C_USE_I2C1 == TRUE if (&I2CD1 == i2cp) { + rp_peripheral_unreset(RESETS_ALLREG_I2C1); + nvicEnableVector(RP_I2C1_IRQ_NUMBER, RP_IRQ_I2C1_PRIORITY); } #endif } + /* Disable I2C peripheral for setup phase. */ + if (i2c_lld_disableS(i2cp) != MSG_OK) { + return; + } + + dp->CON = I2C_IC_CON_IC_SLAVE_DISABLE | + I2C_IC_CON_IC_RESTART_EN | +#if RP_I2C_ADDRESS_MODE_10BIT == TRUE + I2C_IC_CON_IC_10BITADDR_MASTER | +#endif + (2U << I2C_IC_CON_SPEED_Pos) | /* Always Fast Mode. */ + I2C_IC_CON_MASTER_MODE | + I2C_IC_CON_STOP_DET_IF_MASTER_ACTIVE | + I2C_IC_CON_TX_EMPTY_CTRL; + + dp->RXTL = 0U; + dp->TXTL = 0U; + + i2c_lld_setup_frequency(i2cp); + + /* Clear interrupt mask. */ + dp->INTRMASK = 0U; + + /* Enable peripheral. */ + dp->ENABLE = I2C_IC_ENABLE_ENABLE; + + /* Clear interrupts. */ + (void)dp->CLRINTR; +} + +/** + * @brief Soft-stops the I2C peripheral. + * @note The RP I2C LLD does not allocate resources that need releasing + * while leaving the peripheral enabled. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +void i2c_lld_soft_stop(I2CDriver *i2cp) { + + (void)i2cp; } /** @@ -99,11 +495,22 @@ void i2c_lld_start(I2CDriver *i2cp) { void i2c_lld_stop(I2CDriver *i2cp) { if (i2cp->state != I2C_STOP) { + if (i2c_lld_disableS(i2cp) != MSG_OK) { + i2c_lld_abort_transmissionS(i2cp); + } +#if RP_I2C_USE_I2C0 == TRUE + if (&I2CD0 == i2cp) { + nvicDisableVector(RP_I2C0_IRQ_NUMBER); + + rp_peripheral_reset(RESETS_ALLREG_I2C0); + } +#endif - /* Disables the peripheral.*/ -#if PLATFORM_I2C_USE_I2C1 == TRUE +#if RP_I2C_USE_I2C1 == TRUE if (&I2CD1 == i2cp) { + nvicDisableVector(RP_I2C1_IRQ_NUMBER); + rp_peripheral_reset(RESETS_ALLREG_I2C1); } #endif } @@ -133,14 +540,75 @@ void i2c_lld_stop(I2CDriver *i2cp) { msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, uint8_t *rxbuf, size_t rxbytes, sysinterval_t timeout) { + msg_t msg; + systime_t start, end; + I2C_TypeDef *dp = i2cp->i2c; - (void)i2cp; - (void)addr; - (void)rxbuf; - (void)rxbytes; - (void)timeout; + /* Releases the lock from high level driver. */ + osalSysUnlock(); + + /* Calculating the time window for the timeout on the busy bus condition. */ + start = osalOsGetSystemTimeX(); + end = osalTimeAddX(start, OSAL_MS2I(RP_I2C_BUSY_TIMEOUT)); + + while (true) { + osalSysLock(); + + if ((dp->STATUS & I2C_IC_STATUS_ACTIVITY) == 0) { + break; + } + + /* Attempt to clear activity bit. */ + (void)dp->CLRACTIVITY; + + /* If the system time went outside the allowed window then a timeout + condition is returned. */ + if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { + return MSG_TIMEOUT; + } - return MSG_OK; + osalSysUnlock(); + } + + i2cp->txbytes = 0U; + i2cp->txptr = NULL; + i2cp->rxbytes = rxbytes; + i2cp->rxptr = rxbuf; + i2cp->send_restart = false; + + /* Disable I2C peripheral during setup phase. */ + msg = i2c_lld_disableS(i2cp); + if (msg != MSG_OK) { + return msg; + } + + /* Set address. */ + dp->TAR = addr & I2C_IC_TAR_IC_TAR_Msk; + + /* Clear interrupt mask. */ + dp->INTRMASK = 0U; + + /* Enable peripheral. */ + dp->ENABLE = I2C_IC_ENABLE_ENABLE; + + /* Clear interrupts. */ + (void)dp->CLRINTR; + + /* Set interrupt mask. */ + dp->INTRMASK = I2C_IC_INTR_MASK_M_STOP_DET | + I2C_IC_INTR_MASK_M_TX_EMPTY | + I2C_ERROR_INTERRUPTS; + + /* Waits for the operation completion or a timeout. */ + msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout); + + if (msg == MSG_TIMEOUT) { + /* Disable and clear interrupts. */ + dp->INTRMASK = 0U; + (void)dp->CLRINTR; + } + + return msg; } /** @@ -171,15 +639,74 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, uint8_t *rxbuf, size_t rxbytes, sysinterval_t timeout) { - (void)i2cp; - (void)addr; - (void)txbuf; - (void)txbytes; - (void)rxbuf; - (void)rxbytes; - (void)timeout; - - return MSG_OK; + msg_t msg; + systime_t start, end; + I2C_TypeDef *dp = i2cp->i2c; + + /* Releases the lock from high level driver. */ + osalSysUnlock(); + + /* Calculating the time window for the timeout on the busy bus condition. */ + start = osalOsGetSystemTimeX(); + end = osalTimeAddX(start, OSAL_MS2I(RP_I2C_BUSY_TIMEOUT)); + + while (true) { + osalSysLock(); + + if ((dp->STATUS & I2C_IC_STATUS_ACTIVITY) == 0U) { + break; + } + /* Attempt to clear activity bit. */ + (void)dp->CLRACTIVITY; + + /* If the system time went outside the allowed window then a timeout + condition is returned. */ + if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { + return MSG_TIMEOUT; + } + + osalSysUnlock(); + } + + i2cp->txbytes = txbytes; + i2cp->txptr = txbuf; + i2cp->rxbytes = rxbytes; + i2cp->rxptr = rxbuf; + i2cp->send_restart = false; + + /* Disable I2C peripheral during setup phase. */ + msg = i2c_lld_disableS(i2cp); + if (msg != MSG_OK) { + return msg; + } + + /* Set target address. */ + dp->TAR = addr & I2C_IC_TAR_IC_TAR; + + /* Clear interrupt mask. */ + dp->INTRMASK = 0U; + + /* Enable peripheral. */ + dp->ENABLE = I2C_IC_ENABLE_ENABLE; + + /* Clear interrupts. */ + (void)dp->CLRINTR; + + /* Set interrupt mask. */ + dp->INTRMASK = I2C_IC_INTR_MASK_M_STOP_DET | + I2C_IC_INTR_MASK_M_TX_EMPTY | + I2C_ERROR_INTERRUPTS; + + /* Waits for the operation completion or a timeout. */ + msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout); + + if (msg == MSG_TIMEOUT) { + /* Disable and clear interrupts. */ + dp->INTRMASK = 0U; + (void)dp->CLRINTR; + } + + return msg; } #endif /* HAL_USE_I2C == TRUE */ diff --git a/os/hal/ports/RP/LLD/I2Cv1/hal_i2c_lld.h b/os/hal/ports/RP/LLD/I2Cv1/hal_i2c_lld.h index 41a9ba968d..f307b34a67 100644 --- a/os/hal/ports/RP/LLD/I2Cv1/hal_i2c_lld.h +++ b/os/hal/ports/RP/LLD/I2Cv1/hal_i2c_lld.h @@ -15,8 +15,8 @@ */ /** - * @file hal_i2c_lld.h - * @brief RP2040 I2C subsystem low level driver header. + * @file I2Cv1/hal_i2c_lld.h + * @brief RP I2C subsystem low level driver header. * * @addtogroup I2C * @{ @@ -36,23 +36,82 @@ /*===========================================================================*/ /** - * @name PLATFORM configuration options + * @name RP configuration options * @{ */ + /** - * @brief I2C1 driver enable switch. - * @details If set to @p TRUE the support for I2C1 is included. + * @brief I2C timeout on busy condition in milliseconds. + */ +#if !defined(RP_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__) +#define RP_I2C_BUSY_TIMEOUT 50 +#endif + +/** + * @brief I2C 10-bit address mode switch. + * @details If set to @p TRUE 10-bit address mode is enabled. * @note The default is @p FALSE. */ -#if !defined(PLATFORM_I2C_USE_I2C1) || defined(__DOXYGEN__) -#define PLATFORM_I2C_USE_I2C1 FALSE +#if !defined(RP_I2C_ADDRESS_MODE_10BIT) || defined(__DOXYGEN__) +#define RP_I2C_ADDRESS_MODE_10BIT FALSE #endif + /** @} */ /*===========================================================================*/ /* Derived constants and error checks. */ /*===========================================================================*/ +/* Registry checks for robustness. */ +#if !defined(RP_HAS_I2C0) +#error "RP_HAS_I2C0 not defined in registry" +#endif + +#if !defined(RP_HAS_I2C1) +#error "RP_HAS_I2C1 not defined in registry" +#endif + +/* Mcuconf.h checks. */ +#if !defined(RP_I2C_USE_I2C0) +#error "RP_I2C_USE_I2C0 not defined in mcuconf.h" +#endif + +#if !defined(RP_I2C_USE_I2C1) +#error "RP_I2C_USE_I2C1 not defined in mcuconf.h" +#endif + +#if !defined(RP_IRQ_I2C0_PRIORITY) +#error "RP_IRQ_I2C0_PRIORITY not defined in mcuconf.h" +#endif + +#if !defined(RP_IRQ_I2C1_PRIORITY) +#error "RP_IRQ_I2C1_PRIORITY not defined in mcuconf.h" +#endif + +/* Device selection checks. */ +#if RP_I2C_USE_I2C0 && !RP_HAS_I2C0 +#error "I2C0 not present in the selected device" +#endif + +#if RP_I2C_USE_I2C1 && !RP_HAS_I2C1 +#error "I2C1 not present in the selected device" +#endif + +#if !RP_I2C_USE_I2C0 && !RP_I2C_USE_I2C1 +#error "I2C driver activated but no I2C peripheral assigned" +#endif + +/* IRQ priority checks. */ +#if RP_I2C_USE_I2C0 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(RP_IRQ_I2C0_PRIORITY) +#error "Invalid IRQ priority assigned to I2C0" +#endif + +#if RP_I2C_USE_I2C1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(RP_IRQ_I2C1_PRIORITY) +#error "Invalid IRQ priority assigned to I2C1" +#endif + /*===========================================================================*/ /* Driver data structures and types. */ /*===========================================================================*/ @@ -68,29 +127,24 @@ typedef uint16_t i2caddr_t; typedef uint32_t i2cflags_t; /** - * @brief I2C driver configuration structure. + * @brief Type of I2C driver configuration structure. * @note Implementations may extend this structure to contain more, * architecture dependent, fields. */ -struct hal_i2c_config { - /* End of the mandatory fields.*/ - uint32_t dummy; -}; - -/** - * @brief Type of a structure representing an I2C configuration. - */ -typedef struct hal_i2c_config I2CConfig; +typedef struct { + /* Baudrate setting. */ + uint32_t baudrate; +} I2CConfig; /** * @brief Type of a structure representing an I2C driver. */ -typedef struct hal_i2c_driver I2CDriver; +typedef struct I2CDriver I2CDriver; /** * @brief Structure representing an I2C driver. */ -struct hal_i2c_driver { +struct I2CDriver { /** * @brief Driver state. */ @@ -110,6 +164,34 @@ struct hal_i2c_driver { I2C_DRIVER_EXT_FIELDS #endif /* End of the mandatory fields.*/ + /** + * @brief Pointer to the I2Cx registers block. + */ + I2C_TypeDef *i2c; + /** + * @brief Thread waiting for I/O completion. + */ + thread_reference_t thread; + /** + * @brief Number of bytes in TX phase. + */ + size_t txbytes; + /** + * @brief Number of bytes in RX phase. + */ + size_t rxbytes; + /** + * @brief Send restart on next transmission. + */ + bool send_restart; + /** + * @brief Buffer for TX. + */ + const uint8_t *txptr; + /** + * @brief Buffer for RX. + */ + uint8_t *rxptr; }; /*===========================================================================*/ @@ -129,7 +211,11 @@ struct hal_i2c_driver { /* External declarations. */ /*===========================================================================*/ -#if (PLATFORM_I2C_USE_I2C1 == TRUE) && !defined(__DOXYGEN__) +#if (RP_I2C_USE_I2C0 == TRUE) && !defined(__DOXYGEN__) +extern I2CDriver I2CD0; +#endif + +#if (RP_I2C_USE_I2C1 == TRUE) && !defined(__DOXYGEN__) extern I2CDriver I2CD1; #endif @@ -138,6 +224,7 @@ extern "C" { #endif void i2c_lld_init(void); void i2c_lld_start(I2CDriver *i2cp); + void i2c_lld_soft_stop(I2CDriver *i2cp); void i2c_lld_stop(I2CDriver *i2cp); msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, const uint8_t *txbuf, size_t txbytes, diff --git a/os/hal/ports/RP/LLD/PIOv1/driver.mk b/os/hal/ports/RP/LLD/PIOv1/driver.mk new file mode 100644 index 0000000000..cfd21f464b --- /dev/null +++ b/os/hal/ports/RP/LLD/PIOv1/driver.mk @@ -0,0 +1,2 @@ +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/RP/LLD/PIOv1/rp_pio.c +PLATFORMINC += $(CHIBIOS)/os/hal/ports/RP/LLD/PIOv1 diff --git a/os/hal/ports/RP/LLD/PIOv1/rp_pio.c b/os/hal/ports/RP/LLD/PIOv1/rp_pio.c new file mode 100644 index 0000000000..fae713aa54 --- /dev/null +++ b/os/hal/ports/RP/LLD/PIOv1/rp_pio.c @@ -0,0 +1,577 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file PIOv1/rp_pio.c + * @brief PIO helper driver code. + * + * @addtogroup RP_PIO + * @details PIO state machine allocation driver. + * @{ + */ + +#include "hal.h" + +#if defined(RP_PIO_REQUIRED) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief PIO block descriptors. + */ +const rp_pio_block_t __rp_pio_blocks[RP_PIO_NUM_BLOCKS] = { + {PIO0, 0U, RESETS_ALLREG_PIO0}, + {PIO1, 1U, RESETS_ALLREG_PIO1}, +#if RP_HAS_PIO2 == TRUE + {PIO2, 2U, RESETS_ALLREG_PIO2}, +#endif +}; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief PIO state machine descriptors. + */ +static rp_pio_sm_t pio_sms[RP_PIO_NUM_BLOCKS][RP_PIO_NUM_STATE_MACHINES]; + +/** + * @brief Global PIO-related data structures. + */ +static struct { + struct { + /** + * @brief Mask of the allocated state machines for core 0. + */ + uint32_t c0_allocated_mask; + /** + * @brief Mask of the allocated state machines for core 1. + */ + uint32_t c1_allocated_mask; + /** + * @brief Instruction memory allocation bitmap. + */ + uint32_t imem_allocated; + /** + * @brief PIO state machine IRQ redirectors. + */ + struct { + /** + * @brief PIO state Machine callback function. + */ + rp_pioisr_t func; + /** + * @brief PIO state machine callback parameter. + */ + void *param; + } sm[RP_PIO_NUM_STATE_MACHINES]; + } blocks[RP_PIO_NUM_BLOCKS]; +} pio; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static void serve_pio_irq(uint32_t blockidx, __I uint32_t *ints_reg) { + uint32_t ints; + + ints = *ints_reg; + + if (ints != 0U) { + unsigned i; + + for (i = 0U; i < RP_PIO_NUM_STATE_MACHINES; i++) { + if (pio.blocks[blockidx].sm[i].func != NULL) { + pio.blocks[blockidx].sm[i].func(pio.blocks[blockidx].sm[i].param,ints); + } + } + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/** + * @brief PIO0 IRQ0 handler for core 0. + * + * @isr + */ +OSAL_IRQ_HANDLER(RP_PIO0_IRQ_0_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + serve_pio_irq(0U, &PIO0->IRQ0_INTS); + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief PIO0 IRQ1 handler for core 1. + * + * @isr + */ +OSAL_IRQ_HANDLER(RP_PIO0_IRQ_1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + serve_pio_irq(0U, &PIO0->IRQ1_INTS); + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief PIO1 IRQ0 handler for core 0. + * + * @isr + */ +OSAL_IRQ_HANDLER(RP_PIO1_IRQ_0_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + serve_pio_irq(1U, &PIO1->IRQ0_INTS); + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief PIO1 IRQ1 handler for core 1. + * + * @isr + */ +OSAL_IRQ_HANDLER(RP_PIO1_IRQ_1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + serve_pio_irq(1U, &PIO1->IRQ1_INTS); + OSAL_IRQ_EPILOGUE(); +} + +#if RP_HAS_PIO2 == TRUE +/** + * @brief PIO2 IRQ0 handler for core 0. + * + * @isr + */ +OSAL_IRQ_HANDLER(RP_PIO2_IRQ_0_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + serve_pio_irq(2U, &PIO2->IRQ0_INTS); + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief PIO2 IRQ1 handler for core 1. + * + * @isr + */ +OSAL_IRQ_HANDLER(RP_PIO2_IRQ_1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + serve_pio_irq(2U, &PIO2->IRQ1_INTS); + OSAL_IRQ_EPILOGUE(); +} +#endif /* RP_HAS_PIO2 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief PIO helper initialization. + * + * @init + */ +void pioInit(void) { + unsigned b, s; + + for (b = 0U; b < RP_PIO_NUM_BLOCKS; b++) { + pio.blocks[b].c0_allocated_mask = 0U; + pio.blocks[b].c1_allocated_mask = 0U; + pio.blocks[b].imem_allocated = 0U; + for (s = 0U; s < RP_PIO_NUM_STATE_MACHINES; s++) { + pio.blocks[b].sm[s].func = NULL; + + /* Initialize state machine descriptors.*/ + pio_sms[b][s].block = &__rp_pio_blocks[b]; + pio_sms[b][s].smidx = s; + pio_sms[b][s].smmask = 1U << s; + } + } +} + +/** + * @brief Allocates a PIO state machine. + * + * @param[in] block pointer to the PIO block descriptor + * @param[in] smid numeric identifier of a specific state machine or: + * - @p RP_PIO_SM_ID_ANY for any state machine. + * . + * @param[in] irq_priority IRQ priority for the PIO state machine + * @param[in] func handling function pointer, can be @p NULL + * @param[in] param a parameter to be passed to the handling function + * @return Pointer to the allocated @p rp_pio_sm_t structure. + * @retval NULL if state machine is not available. + * + * @iclass + */ +const rp_pio_sm_t *pioSmAllocI(const rp_pio_block_t *block, + uint32_t smid, + uint32_t irq_priority, + rp_pioisr_t func, void *param) { + uint32_t b, i, startid, endid; + + osalDbgCheckClassI(); + osalDbgCheck(block != NULL); + + b = block->pioidx; + + if (smid < RP_PIO_SM_ID_ANY) { + startid = smid; + endid = smid; + } + else if (smid == RP_PIO_SM_ID_ANY) { + startid = 0U; + endid = RP_PIO_SM_ID_ANY - 1U; + } + else { + osalDbgCheck(false); + return NULL; + } + + for (i = startid; i <= endid; i++) { + uint32_t prevmask = pio.blocks[b].c0_allocated_mask | + pio.blocks[b].c1_allocated_mask; + uint32_t smmask = 1U << i; + + if ((prevmask & smmask) == 0U) { + + /* Installs the PIO handler.*/ + pio.blocks[b].sm[i].func = func; + pio.blocks[b].sm[i].param = param; + + /* Releasing PIO reset if this is the first state machine taken.*/ + if (prevmask == 0U) { + rp_peripheral_unreset(block->resets_mask); + } + + if (SIO->CPUID == 0U) { + /* state machine taken by core 0.*/ + if (pio.blocks[b].c0_allocated_mask == 0U) { + switch (b) { + case 0U: + nvicEnableVector(RP_PIO0_IRQ_0_NUMBER, irq_priority); + break; + case 1U: + nvicEnableVector(RP_PIO1_IRQ_0_NUMBER, irq_priority); + break; +#if RP_HAS_PIO2 == TRUE + case 2U: + nvicEnableVector(RP_PIO2_IRQ_0_NUMBER, irq_priority); + break; +#endif + default: + break; + } + } + pio.blocks[b].c0_allocated_mask |= smmask; + } + else { + /* state machine taken by core 1.*/ + if (pio.blocks[b].c1_allocated_mask == 0U) { + switch (b) { + case 0U: + nvicEnableVector(RP_PIO0_IRQ_1_NUMBER, irq_priority); + break; + case 1U: + nvicEnableVector(RP_PIO1_IRQ_1_NUMBER, irq_priority); + break; +#if RP_HAS_PIO2 == TRUE + case 2U: + nvicEnableVector(RP_PIO2_IRQ_1_NUMBER, irq_priority); + break; +#endif + default: + break; + } + } + pio.blocks[b].c1_allocated_mask |= smmask; + } + + return &pio_sms[b][i]; + } + } + + return NULL; +} + +/** + * @brief Allocates a PIO state machine. + * + * @param[in] block pointer to the PIO block descriptor + * @param[in] smid numeric identifier of a specific state machine or: + * - @p RP_PIO_SM_ID_ANY for any state machine. + * . + * @param[in] irq_priority IRQ priority for the PIO state machine + * @param[in] func handling function pointer, can be @p NULL + * @param[in] param a parameter to be passed to the handling function + * @return Pointer to the allocated @p rp_pio_sm_t structure. + * @retval NULL if state machine is not available. + * + * @api + */ +const rp_pio_sm_t *pioSmAlloc(const rp_pio_block_t *block, + uint32_t smid, + uint32_t irq_priority, + rp_pioisr_t func, void *param) { + const rp_pio_sm_t *smp; + + osalSysLock(); + smp = pioSmAllocI(block, smid, irq_priority, func, param); + osalSysUnlock(); + + return smp; +} + +/** + * @brief Releases a PIO state machine. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * + * @iclass + */ +void pioSmFreeI(const rp_pio_sm_t *smp) { + uint32_t b; + + osalDbgCheck(smp != NULL); + + b = smp->block->pioidx; + + /* Check if the state machine is allocated.*/ + osalDbgAssert(((pio.blocks[b].c0_allocated_mask | + pio.blocks[b].c1_allocated_mask) & smp->smmask) != 0U, + "not allocated"); + + /* Disable the state machine.*/ + pioSmDisableX(smp); + + /* Disabling state machine interrupts for both cores.*/ + pioSmDisableInterruptX(smp, PIO_IRQ_RXNEMPTY(smp->smidx) | + PIO_IRQ_TXNFULL(smp->smidx) | + PIO_IRQ_SM(smp->smidx)); + + if (SIO->CPUID == 0U) { + /* state machine released by core 0.*/ + pio.blocks[b].c0_allocated_mask &= ~smp->smmask; + if (pio.blocks[b].c0_allocated_mask == 0U) { + switch (b) { + case 0U: + nvicDisableVector(RP_PIO0_IRQ_0_NUMBER); + break; + case 1U: + nvicDisableVector(RP_PIO1_IRQ_0_NUMBER); + break; +#if RP_HAS_PIO2 == TRUE + case 2U: + nvicDisableVector(RP_PIO2_IRQ_0_NUMBER); + break; +#endif + default: + break; + } + } + } + else { + /* state machine released by core 1.*/ + pio.blocks[b].c1_allocated_mask &= ~smp->smmask; + if (pio.blocks[b].c1_allocated_mask == 0U) { + switch (b) { + case 0U: + nvicDisableVector(RP_PIO0_IRQ_1_NUMBER); + break; + case 1U: + nvicDisableVector(RP_PIO1_IRQ_1_NUMBER); + break; +#if RP_HAS_PIO2 == TRUE + case 2U: + nvicDisableVector(RP_PIO2_IRQ_1_NUMBER); + break; +#endif + default: + break; + } + } + } + + /* Remove the PIO handler.*/ + pio.blocks[b].sm[smp->smidx].func = NULL; + pio.blocks[b].sm[smp->smidx].param = NULL; + + /* Reset PIO block if no state machines remain.*/ + if ((pio.blocks[b].c0_allocated_mask | + pio.blocks[b].c1_allocated_mask) == 0U) { + rp_peripheral_reset(smp->block->resets_mask); + } +} + +/** + * @brief Releases a PIO state machine. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * + * @api + */ +void pioSmFree(const rp_pio_sm_t *smp) { + + osalSysLock(); + pioSmFreeI(smp); + osalSysUnlock(); +} + +/** + * @brief Loads a PIO program into instruction memory. + * + * @param[in] block pointer to the PIO block descriptor + * @param[in] program pointer to the program descriptor + * @return The offset at which the program was loaded. + * @retval -1 if the program could not be loaded. + * + * @iclass + */ +int32_t pioProgramLoadI(const rp_pio_block_t *block, + const rp_pio_program_t *program) { + uint32_t b, i, offset, length, mask; + + osalDbgCheckClassI(); + osalDbgCheck(block != NULL); + osalDbgCheck(program != NULL); + osalDbgCheck(program->length > 0U); + osalDbgCheck(program->length <= RP_PIO_NUM_INSTR_MEM); + + b = block->pioidx; + length = program->length; + + if (program->origin >= 0) { + /* Check that the requested slots are free.*/ + offset = (uint32_t)program->origin; + osalDbgCheck(offset + length <= RP_PIO_NUM_INSTR_MEM); + + mask = ((1U << length) - 1U) << offset; + if ((pio.blocks[b].imem_allocated & mask) != 0U) { + return -1; + } + } + else { + /* Find first contiguous run of free slots.*/ + uint32_t found = 0U; + + for (offset = 0U; offset <= RP_PIO_NUM_INSTR_MEM - length; offset++) { + mask = ((1U << length) - 1U) << offset; + if ((pio.blocks[b].imem_allocated & mask) == 0U) { + found = 1U; + break; + } + } + if (found == 0U) { + return -1; + } + } + + /* Write the instructions to memory.*/ + for (i = 0U; i < length; i++) { + block->pio->INSTR_MEM[offset + i] = program->instructions[i]; + } + + /* Mark slots as used.*/ + pio.blocks[b].imem_allocated |= ((1U << length) - 1U) << offset; + + return (int32_t)offset; +} + +/** + * @brief Unloads a PIO program from instruction memory. + * + * @param[in] block pointer to the PIO block descriptor + * @param[in] offset the offset at which the program was loaded + * @param[in] length number of instructions to free + * + * @iclass + */ +void pioProgramUnloadI(const rp_pio_block_t *block, + int32_t offset, uint32_t length) { + uint32_t b, i, mask; + + osalDbgCheckClassI(); + osalDbgCheck(block != NULL); + osalDbgCheck(offset >= 0); + osalDbgCheck(((uint32_t)offset + length) <= RP_PIO_NUM_INSTR_MEM); + + b = block->pioidx; + mask = ((1U << length) - 1U) << (uint32_t)offset; + + osalDbgAssert((pio.blocks[b].imem_allocated & mask) == mask, + "not allocated"); + + /* Zero out memory.*/ + for (i = 0U; i < length; i++) { + block->pio->INSTR_MEM[(uint32_t)offset + i] = 0U; + } + + /* Free slots.*/ + pio.blocks[b].imem_allocated &= ~mask; +} + +/** + * @brief Loads a PIO program into instruction memory. + * + * @param[in] block pointer to the PIO block descriptor + * @param[in] program pointer to the program descriptor + * @return The offset at which the program was loaded. + * @retval -1 if the program could not be loaded. + * + * @api + */ +int32_t pioProgramLoad(const rp_pio_block_t *block, + const rp_pio_program_t *program) { + int32_t offset; + + osalSysLock(); + offset = pioProgramLoadI(block, program); + osalSysUnlock(); + + return offset; +} + +/** + * @brief Unloads a PIO program from instruction memory. + * + * @param[in] block pointer to the PIO block descriptor + * @param[in] offset the offset at which the program was loaded + * @param[in] length number of instructions to free + * + * @api + */ +void pioProgramUnload(const rp_pio_block_t *block, + int32_t offset, uint32_t length) { + + osalSysLock(); + pioProgramUnloadI(block, offset, length); + osalSysUnlock(); +} + +#endif /* RP_PIO_REQUIRED */ + +/** @} */ diff --git a/os/hal/ports/RP/LLD/PIOv1/rp_pio.h b/os/hal/ports/RP/LLD/PIOv1/rp_pio.h new file mode 100644 index 0000000000..a55488bb66 --- /dev/null +++ b/os/hal/ports/RP/LLD/PIOv1/rp_pio.h @@ -0,0 +1,649 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file PIOv1/rp_pio.h + * @brief PIO helper driver header. + * + * @addtogroup RP_PIO + * @{ + */ + +#ifndef RP_PIO_H +#define RP_PIO_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name PIO GPIO function select values + * @{ + */ +#define RP_PIO_FUNCSEL_PIO0 6U +#define RP_PIO_FUNCSEL_PIO1 7U +#if RP_HAS_PIO2 == TRUE +#define RP_PIO_FUNCSEL_PIO2 8U +#endif +#define RP_PIO_FUNCSEL_NULL 31U +/** @} */ + +/** + * @name PIO resource constants + * @{ + */ +#define RP_PIO_NUM_STATE_MACHINES 4U +#define RP_PIO_NUM_INSTR_MEM 32U + +/** + * @brief Any state machine selector. + */ +#define RP_PIO_SM_ID_ANY RP_PIO_NUM_STATE_MACHINES +/** @} */ + +/** + * @name PIO CTRL register bits + * @{ + */ +#define PIO_CTRL_SM_ENABLE(n) (1U << (n)) +#define PIO_CTRL_SM_RESTART(n) (1U << ((n) + 4U)) +#define PIO_CTRL_CLKDIV_RESTART(n) (1U << ((n) + 8U)) +/** @} */ + +/** + * @name PIO FSTAT register bits + * @{ + */ +#define PIO_FSTAT_RXFULL(n) (1U << ((n) + 0U)) +#define PIO_FSTAT_RXEMPTY(n) (1U << ((n) + 8U)) +#define PIO_FSTAT_TXFULL(n) (1U << ((n) + 16U)) +#define PIO_FSTAT_TXEMPTY(n) (1U << ((n) + 24U)) +/** @} */ + +/** + * @name PIO FDEBUG register bits (W1C) + * @{ + */ +#define PIO_FDEBUG_RXSTALL(n) (1U << ((n) + 0U)) +#define PIO_FDEBUG_RXUNDER(n) (1U << ((n) + 8U)) +#define PIO_FDEBUG_TXOVER(n) (1U << ((n) + 16U)) +#define PIO_FDEBUG_TXSTALL(n) (1U << ((n) + 24U)) +/** @} */ + +/** + * @name PIO state machine CLKDIV register bits + * @{ + */ +#define PIO_SM_CLKDIV_FRAC_Pos 8U +#define PIO_SM_CLKDIV_FRAC_Msk (0xFFU << PIO_SM_CLKDIV_FRAC_Pos) +#define PIO_SM_CLKDIV_INT_Pos 16U +#define PIO_SM_CLKDIV_INT_Msk (0xFFFFU << PIO_SM_CLKDIV_INT_Pos) + +/** + * @brief Builds a CLKDIV register value from integer and fractional parts. + */ +#define PIO_SM_CLKDIV(intdiv, frac) (((uint32_t)(intdiv) << PIO_SM_CLKDIV_INT_Pos) | \ + ((uint32_t)(frac) << PIO_SM_CLKDIV_FRAC_Pos)) +/** @} */ + +/** + * @name PIO state machine EXECCTRL register bits + * @{ + */ +#define PIO_SM_EXECCTRL_STATUS_N_Pos 0U +#define PIO_SM_EXECCTRL_STATUS_N_Msk (0xFU << PIO_SM_EXECCTRL_STATUS_N_Pos) +#define PIO_SM_EXECCTRL_STATUS_SEL (1U << 4U) +#define PIO_SM_EXECCTRL_WRAP_BOTTOM_Pos 7U +#define PIO_SM_EXECCTRL_WRAP_BOTTOM_Msk (0x1FU << PIO_SM_EXECCTRL_WRAP_BOTTOM_Pos) +#define PIO_SM_EXECCTRL_WRAP_TOP_Pos 12U +#define PIO_SM_EXECCTRL_WRAP_TOP_Msk (0x1FU << PIO_SM_EXECCTRL_WRAP_TOP_Pos) +#define PIO_SM_EXECCTRL_OUT_STICKY (1U << 17U) +#define PIO_SM_EXECCTRL_INLINE_OUT_EN (1U << 18U) +#define PIO_SM_EXECCTRL_OUT_EN_SEL_Pos 19U +#define PIO_SM_EXECCTRL_OUT_EN_SEL_Msk (0x1FU << PIO_SM_EXECCTRL_OUT_EN_SEL_Pos) +#define PIO_SM_EXECCTRL_JMP_PIN_Pos 24U +#define PIO_SM_EXECCTRL_JMP_PIN_Msk (0x1FU << PIO_SM_EXECCTRL_JMP_PIN_Pos) +#define PIO_SM_EXECCTRL_SIDE_PINDIR (1U << 29U) +#define PIO_SM_EXECCTRL_SIDE_EN (1U << 30U) +#define PIO_SM_EXECCTRL_EXEC_STALLED (1U << 31U) + +/** + * @brief Helper to build wrap range for EXECCTRL. + */ +#define PIO_SM_EXECCTRL_WRAP(bottom, top) \ + (((uint32_t)(bottom) << PIO_SM_EXECCTRL_WRAP_BOTTOM_Pos) | \ + ((uint32_t)(top) << PIO_SM_EXECCTRL_WRAP_TOP_Pos)) +/** @} */ + +/** + * @name PIO state machine SHIFTCTRL register bits + * @{ + */ +#define PIO_SM_SHIFTCTRL_AUTOPUSH (1U << 16U) +#define PIO_SM_SHIFTCTRL_AUTOPULL (1U << 17U) +#define PIO_SM_SHIFTCTRL_IN_SHIFTDIR (1U << 18U) +#define PIO_SM_SHIFTCTRL_OUT_SHIFTDIR (1U << 19U) +#define PIO_SM_SHIFTCTRL_PUSH_THRESH_Pos 20U +#define PIO_SM_SHIFTCTRL_PUSH_THRESH_Msk (0x1FU << PIO_SM_SHIFTCTRL_PUSH_THRESH_Pos) +#define PIO_SM_SHIFTCTRL_PULL_THRESH_Pos 25U +#define PIO_SM_SHIFTCTRL_PULL_THRESH_Msk (0x1FU << PIO_SM_SHIFTCTRL_PULL_THRESH_Pos) +#define PIO_SM_SHIFTCTRL_FJOIN_TX (1U << 30U) +#define PIO_SM_SHIFTCTRL_FJOIN_RX (1U << 31U) +/** @} */ + +/** + * @name PIO state machine PINCTRL register bits + * @{ + */ +#define PIO_SM_PINCTRL_OUT_BASE_Pos 0U +#define PIO_SM_PINCTRL_OUT_BASE_Msk (0x1FU << PIO_SM_PINCTRL_OUT_BASE_Pos) +#define PIO_SM_PINCTRL_SET_BASE_Pos 5U +#define PIO_SM_PINCTRL_SET_BASE_Msk (0x1FU << PIO_SM_PINCTRL_SET_BASE_Pos) +#define PIO_SM_PINCTRL_SIDESET_BASE_Pos 10U +#define PIO_SM_PINCTRL_SIDESET_BASE_Msk (0x1FU << PIO_SM_PINCTRL_SIDESET_BASE_Pos) +#define PIO_SM_PINCTRL_IN_BASE_Pos 15U +#define PIO_SM_PINCTRL_IN_BASE_Msk (0x1FU << PIO_SM_PINCTRL_IN_BASE_Pos) +#define PIO_SM_PINCTRL_OUT_COUNT_Pos 20U +#define PIO_SM_PINCTRL_OUT_COUNT_Msk (0x3FU << PIO_SM_PINCTRL_OUT_COUNT_Pos) +#define PIO_SM_PINCTRL_SET_COUNT_Pos 26U +#define PIO_SM_PINCTRL_SET_COUNT_Msk (0x7U << PIO_SM_PINCTRL_SET_COUNT_Pos) +#define PIO_SM_PINCTRL_SIDESET_COUNT_Pos 29U +#define PIO_SM_PINCTRL_SIDESET_COUNT_Msk (0x7U << PIO_SM_PINCTRL_SIDESET_COUNT_Pos) +/** @} */ + +/** + * @name PIO interrupt bits (for IRQ0_INTE/IRQ1_INTE/IRQ0_INTS/IRQ1_INTS) + * @{ + */ +#define PIO_IRQ_RXNEMPTY(n) (1U << (n)) +#define PIO_IRQ_TXNFULL(n) (1U << ((n) + 4U)) +#define PIO_IRQ_SM(n) (1U << ((n) + 8U)) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a PIO ISR callback. + * + * @param[in] p parameter for the registered function + * @param[in] ints content of the IRQn_INTS register + */ +typedef void (*rp_pioisr_t)(void *p, uint32_t ints); + +/** + * @brief RP PIO block descriptor structure. + */ +typedef struct { + PIO_TypeDef *pio; /**< @brief Associated PIO block. */ + uint32_t pioidx; /**< @brief Block index (0..2). */ + uint32_t resets_mask; /**< @brief RESETS bit for this PIO.*/ +} rp_pio_block_t; + +/** + * @brief RP PIO state machine descriptor structure. + */ +typedef struct { + const rp_pio_block_t *block; /**< @brief Owning PIO block. */ + uint32_t smidx; /**< @brief state machine index within block. */ + uint32_t smmask; /**< @brief state machine bit mask (1 << idx).*/ +} rp_pio_sm_t; + +/** + * @brief PIO program descriptor. + */ +typedef struct { + const uint16_t *instructions; /**< @brief Instruction array. */ + uint32_t length; /**< @brief Number of instructions.*/ + int32_t origin; /**< @brief Load offset, -1 = any. */ +} rp_pio_program_t; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Returns a pointer to a PIO block descriptor. + * + * @param[in] n the PIO block index (0, 1, or 2) + */ +#define RP_PIO_BLOCK(n) (&__rp_pio_blocks[n]) + +#define RP_PIO0_BLOCK RP_PIO_BLOCK(0) +#define RP_PIO1_BLOCK RP_PIO_BLOCK(1) +#if RP_HAS_PIO2 == TRUE +#define RP_PIO2_BLOCK RP_PIO_BLOCK(2) +#endif + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern const rp_pio_block_t __rp_pio_blocks[RP_PIO_NUM_BLOCKS]; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void pioInit(void); + const rp_pio_sm_t *pioSmAllocI(const rp_pio_block_t *block, + uint32_t smid, + uint32_t irq_priority, + rp_pioisr_t func, void *param); + const rp_pio_sm_t *pioSmAlloc(const rp_pio_block_t *block, + uint32_t smid, + uint32_t irq_priority, + rp_pioisr_t func, void *param); + void pioSmFreeI(const rp_pio_sm_t *smp); + void pioSmFree(const rp_pio_sm_t *smp); + int32_t pioProgramLoadI(const rp_pio_block_t *block, + const rp_pio_program_t *program); + void pioProgramUnloadI(const rp_pio_block_t *block, + int32_t offset, uint32_t length); + int32_t pioProgramLoad(const rp_pio_block_t *block, + const rp_pio_program_t *program); + void pioProgramUnload(const rp_pio_block_t *block, + int32_t offset, uint32_t length); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Driver inline functions. */ +/*===========================================================================*/ + +/** + * @brief Enables a state machine. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * + * @special + */ +__STATIC_INLINE void pioSmEnableX(const rp_pio_sm_t *smp) { + + smp->block->pio->SET.CTRL = PIO_CTRL_SM_ENABLE(smp->smidx); +} + +/** + * @brief Disables a state machine. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * + * @special + */ +__STATIC_INLINE void pioSmDisableX(const rp_pio_sm_t *smp) { + + smp->block->pio->CLR.CTRL = PIO_CTRL_SM_ENABLE(smp->smidx); +} + +/** + * @brief Restarts a state machine. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * + * @special + */ +__STATIC_INLINE void pioSmRestartX(const rp_pio_sm_t *smp) { + + smp->block->pio->SET.CTRL = PIO_CTRL_SM_RESTART(smp->smidx); +} + +/** + * @brief Restarts the clock divider of a state machine. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * + * @special + */ +__STATIC_INLINE void pioSmClkdivRestartX(const rp_pio_sm_t *smp) { + + smp->block->pio->SET.CTRL = PIO_CTRL_CLKDIV_RESTART(smp->smidx); +} + +/** + * @brief Sets the clock divider of a state machine. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * @param[in] clkdiv CLKDIV register value + * + * @special + */ +__STATIC_INLINE void pioSmSetClkdivX(const rp_pio_sm_t *smp, + uint32_t clkdiv) { + + smp->block->pio->SM[smp->smidx].CLKDIV = clkdiv; +} + +/** + * @brief Sets the execution control of a state machine. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * @param[in] execctrl EXECCTRL register value + * + * @special + */ +__STATIC_INLINE void pioSmSetExecctrlX(const rp_pio_sm_t *smp, + uint32_t execctrl) { + + smp->block->pio->SM[smp->smidx].EXECCTRL = execctrl; +} + +/** + * @brief Sets the shift control of a state machine. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * @param[in] shiftctrl SHIFTCTRL register value + * + * @special + */ +__STATIC_INLINE void pioSmSetShiftctrlX(const rp_pio_sm_t *smp, + uint32_t shiftctrl) { + + smp->block->pio->SM[smp->smidx].SHIFTCTRL = shiftctrl; +} + +/** + * @brief Sets the pin control of a state machine. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * @param[in] pinctrl PINCTRL register value + * + * @special + */ +__STATIC_INLINE void pioSmSetPinctrlX(const rp_pio_sm_t *smp, + uint32_t pinctrl) { + + smp->block->pio->SM[smp->smidx].PINCTRL = pinctrl; +} + +/** + * @brief Executes an instruction immediately on a state machine. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * @param[in] instr 16-bit PIO instruction + * + * @special + */ +__STATIC_INLINE void pioSmExecX(const rp_pio_sm_t *smp, + uint16_t instr) { + + smp->block->pio->SM[smp->smidx].INSTR = instr; +} + +/** + * @brief Returns the current instruction address of a state machine. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * @return The current program counter value. + * + * @special + */ +__STATIC_INLINE uint32_t pioSmGetAddrX(const rp_pio_sm_t *smp) { + + return smp->block->pio->SM[smp->smidx].ADDR; +} + +/** + * @brief Writes a word to a state machine's TX FIFO. + * @pre The TX FIFO must not be full. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * @param[in] data word to write + * + * @special + */ +__STATIC_INLINE void pioSmPutX(const rp_pio_sm_t *smp, uint32_t data) { + + smp->block->pio->TXF[smp->smidx] = data; +} + +/** + * @brief Reads a word from a state machine's RX FIFO. + * @pre The RX FIFO must not be empty. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * @return The word read from the FIFO. + * + * @special + */ +__STATIC_INLINE uint32_t pioSmGetX(const rp_pio_sm_t *smp) { + + return smp->block->pio->RXF[smp->smidx]; +} + +/** + * @brief Checks if the TX FIFO of a state machine is full. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * @return The FIFO full state. + * @retval false if the FIFO is not full. + * @retval true if the FIFO is full. + * + * @special + */ +__STATIC_INLINE bool pioSmIsTxFullX(const rp_pio_sm_t *smp) { + + return (bool)((smp->block->pio->FSTAT & PIO_FSTAT_TXFULL(smp->smidx)) != 0U); +} + +/** + * @brief Checks if the TX FIFO of a state machine is empty. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * @return The FIFO empty state. + * @retval false if the FIFO is not empty. + * @retval true if the FIFO is empty. + * + * @special + */ +__STATIC_INLINE bool pioSmIsTxEmptyX(const rp_pio_sm_t *smp) { + + return (bool)((smp->block->pio->FSTAT & PIO_FSTAT_TXEMPTY(smp->smidx)) != 0U); +} + +/** + * @brief Checks if the RX FIFO of a state machine is full. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * @return The FIFO full state. + * @retval false if the FIFO is not full. + * @retval true if the FIFO is full. + * + * @special + */ +__STATIC_INLINE bool pioSmIsRxFullX(const rp_pio_sm_t *smp) { + + return (bool)((smp->block->pio->FSTAT & PIO_FSTAT_RXFULL(smp->smidx)) != 0U); +} + +/** + * @brief Checks if the RX FIFO of a state machine is empty. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * @return The FIFO empty state. + * @retval false if the FIFO is not empty. + * @retval true if the FIFO is empty. + * + * @special + */ +__STATIC_INLINE bool pioSmIsRxEmptyX(const rp_pio_sm_t *smp) { + + return (bool)((smp->block->pio->FSTAT & PIO_FSTAT_RXEMPTY(smp->smidx)) != 0U); +} + +/** + * @brief Clears the TX and RX FIFOs of a state machine. + * @note Toggling FJOIN_TX clears both FIFOs (per datasheet). + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * + * @special + */ +__STATIC_INLINE void pioSmClearFifosX(const rp_pio_sm_t *smp) { + uint32_t shiftctrl = smp->block->pio->SM[smp->smidx].SHIFTCTRL; + + /* Toggle FJOIN_TX to flush, then restore.*/ + smp->block->pio->SM[smp->smidx].SHIFTCTRL = shiftctrl ^ PIO_SM_SHIFTCTRL_FJOIN_TX; + smp->block->pio->SM[smp->smidx].SHIFTCTRL = shiftctrl; +} + +/** + * @brief Clears FDEBUG flags for a state machine. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * + * @special + */ +__STATIC_INLINE void pioClearDebugX(const rp_pio_sm_t *smp) { + + smp->block->pio->FDEBUG = PIO_FDEBUG_RXSTALL(smp->smidx) | + PIO_FDEBUG_RXUNDER(smp->smidx) | + PIO_FDEBUG_TXOVER(smp->smidx) | + PIO_FDEBUG_TXSTALL(smp->smidx); +} + +/** + * @brief Enables interrupts for a state machine on the current core. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * @param[in] mask interrupt mask (combination of PIO_IRQ_* bits) + * + * @special + */ +__STATIC_INLINE void pioSmEnableInterruptX(const rp_pio_sm_t *smp, + uint32_t mask) { + + if (SIO->CPUID == 0U) { + smp->block->pio->SET.IRQ0_INTE = mask; + } + else { + smp->block->pio->SET.IRQ1_INTE = mask; + } +} + +/** + * @brief Disables interrupts for a state machine. + * @note Clears both cores' INTE unconditionally (avoids CPUID check). + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * @param[in] mask interrupt mask (combination of PIO_IRQ_* bits) + * + * @special + */ +__STATIC_INLINE void pioSmDisableInterruptX(const rp_pio_sm_t *smp, + uint32_t mask) { + + smp->block->pio->CLR.IRQ0_INTE = mask; + smp->block->pio->CLR.IRQ1_INTE = mask; +} + +/** + * @brief Writes a word to the TX FIFO, blocking while full. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * @param[in] data word to write + * + * @special + */ +__STATIC_INLINE void pioSmPut(const rp_pio_sm_t *smp, uint32_t data) { + + while (pioSmIsTxFullX(smp)) + ; + pioSmPutX(smp, data); +} + +/** + * @brief Reads a word from the RX FIFO, blocking while empty. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * @return The word read from the FIFO. + * + * @special + */ +__STATIC_INLINE uint32_t pioSmGet(const rp_pio_sm_t *smp) { + + while (pioSmIsRxEmptyX(smp)) + ; + return pioSmGetX(smp); +} + +/** + * @brief Routes a GPIO pin to the PIO block that owns this state machine. + * @details Sets IO_BANK0 FUNCSEL for the given pin to PIO0, PIO1, or PIO2 + * based on the block index of the state machine. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * @param[in] gpio GPIO pin number + * + * @special + */ +__STATIC_INLINE void pioSmSetPinFunctionX(const rp_pio_sm_t *smp, + uint32_t gpio) { + static const uint32_t funcsel[] = { + RP_PIO_FUNCSEL_PIO0, + RP_PIO_FUNCSEL_PIO1, +#if RP_HAS_PIO2 == TRUE + RP_PIO_FUNCSEL_PIO2, +#endif + }; + + IO_BANK0->GPIO[gpio].CTRL = funcsel[smp->block->pioidx]; +} + +/** + * @brief Sets the program counter of a state machine. + * @details Executes a JMP instruction to the given address. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * @param[in] addr target instruction address (0..31) + * + * @special + */ +__STATIC_INLINE void pioSmSetPCX(const rp_pio_sm_t *smp, uint32_t addr) { + pioSmExecX(smp, (uint16_t)(addr & 0x1FU)); +} + +/** + * @brief Sets the clock divider from a target frequency. + * @details Computes the integer and fractional divider from the system + * clock frequency and the desired PIO clock rate. + * + * @param[in] smp pointer to a rp_pio_sm_t structure + * @param[in] freq_hz desired PIO clock frequency in Hz + * + * @special + */ +__STATIC_INLINE void pioSmSetFrequencyX(const rp_pio_sm_t *smp, uint32_t freq_hz) { + uint32_t div_fp8 = ((uint64_t)RP_CLK_SYS_FREQ << 8) / freq_hz; + uint32_t int_part = div_fp8 >> 8; + uint32_t frac_part = div_fp8 & 0xFFU; + + pioSmSetClkdivX(smp, PIO_SM_CLKDIV(int_part, frac_part)); +} + +#endif /* RP_PIO_H */ + +/** @} */ diff --git a/os/hal/ports/RP/LLD/PWMv1/driver.mk b/os/hal/ports/RP/LLD/PWMv1/driver.mk new file mode 100644 index 0000000000..3c1aeea12e --- /dev/null +++ b/os/hal/ports/RP/LLD/PWMv1/driver.mk @@ -0,0 +1,9 @@ +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_PWM TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/RP/LLD/PWMv1/hal_pwm_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/RP/LLD/PWMv1/hal_pwm_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/RP/LLD/PWMv1 diff --git a/os/hal/ports/RP/LLD/PWMv1/hal_pwm_lld.c b/os/hal/ports/RP/LLD/PWMv1/hal_pwm_lld.c new file mode 100644 index 0000000000..595c026c0c --- /dev/null +++ b/os/hal/ports/RP/LLD/PWMv1/hal_pwm_lld.c @@ -0,0 +1,555 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file PWMv1/hal_pwm_lld.c + * @brief RP PWM subsystem low level driver source. + * + * @addtogroup PWM + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_PWM == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief PWMD0 driver identifier. + * @note The driver PWMD0 allocates the PWM slice 0 when enabled. + */ +#if (RP_PWM_USE_PWM0 == TRUE) || defined(__DOXYGEN__) +PWMDriver PWMD0; +#endif + +/** + * @brief PWMD1 driver identifier. + * @note The driver PWMD1 allocates the PWM slice 1 when enabled. + */ +#if (RP_PWM_USE_PWM1 == TRUE) || defined(__DOXYGEN__) +PWMDriver PWMD1; +#endif + +/** + * @brief PWMD2 driver identifier. + * @note The driver PWMD2 allocates the PWM slice 2 when enabled. + */ +#if (RP_PWM_USE_PWM2 == TRUE) || defined(__DOXYGEN__) +PWMDriver PWMD2; +#endif + +/** + * @brief PWMD3 driver identifier. + * @note The driver PWMD3 allocates the PWM slice 3 when enabled. + */ +#if (RP_PWM_USE_PWM3 == TRUE) || defined(__DOXYGEN__) +PWMDriver PWMD3; +#endif + +/** + * @brief PWMD4 driver identifier. + * @note The driver PWMD4 allocates the PWM slice 4 when enabled. + */ +#if (RP_PWM_USE_PWM4 == TRUE) || defined(__DOXYGEN__) +PWMDriver PWMD4; +#endif + +/** + * @brief PWMD5 driver identifier. + * @note The driver PWMD5 allocates the PWM slice 5 when enabled. + */ +#if (RP_PWM_USE_PWM5 == TRUE) || defined(__DOXYGEN__) +PWMDriver PWMD5; +#endif + +/** + * @brief PWMD6 driver identifier. + * @note The driver PWMD6 allocates the PWM slice 6 when enabled. + */ +#if (RP_PWM_USE_PWM6 == TRUE) || defined(__DOXYGEN__) +PWMDriver PWMD6; +#endif + +/** + * @brief PWMD7 driver identifier. + * @note The driver PWMD7 allocates the PWM slice 7 when enabled. + */ +#if (RP_PWM_USE_PWM7 == TRUE) || defined(__DOXYGEN__) +PWMDriver PWMD7; +#endif + +/** + * @brief PWMD8 driver identifier. + * @note The driver PWMD8 allocates the PWM slice 8 when enabled. + */ +#if (RP_PWM_USE_PWM8 == TRUE) || defined(__DOXYGEN__) +PWMDriver PWMD8; +#endif + +/** + * @brief PWMD9 driver identifier. + * @note The driver PWMD9 allocates the PWM slice 9 when enabled. + */ +#if (RP_PWM_USE_PWM9 == TRUE) || defined(__DOXYGEN__) +PWMDriver PWMD9; +#endif + +/** + * @brief PWMD10 driver identifier. + * @note The driver PWMD10 allocates the PWM slice 10 when enabled. + */ +#if (RP_PWM_USE_PWM10 == TRUE) || defined(__DOXYGEN__) +PWMDriver PWMD10; +#endif + +/** + * @brief PWMD11 driver identifier. + * @note The driver PWMD11 allocates the PWM slice 11 when enabled. + */ +#if (RP_PWM_USE_PWM11 == TRUE) || defined(__DOXYGEN__) +PWMDriver PWMD11; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if (RP_PWM_USE_PWM0 == TRUE) || (RP_PWM_USE_PWM1 == TRUE) || \ + (RP_PWM_USE_PWM2 == TRUE) || (RP_PWM_USE_PWM3 == TRUE) || \ + (RP_PWM_USE_PWM4 == TRUE) || (RP_PWM_USE_PWM5 == TRUE) || \ + (RP_PWM_USE_PWM6 == TRUE) || (RP_PWM_USE_PWM7 == TRUE) || \ + defined(__DOXYGEN__) +#define RP_PWM_USE_ANY_PWM07 TRUE +#else +#define RP_PWM_USE_ANY_PWM07 FALSE +#endif + +#if (RP_HAS_PWM8 == TRUE) +#if (RP_PWM_USE_PWM8 == TRUE) || (RP_PWM_USE_PWM9 == TRUE) || \ + (RP_PWM_USE_PWM10 == TRUE) || (RP_PWM_USE_PWM11 == TRUE) +#define RP_PWM_USE_ANY_PWM811 TRUE +#else +#define RP_PWM_USE_ANY_PWM811 FALSE +#endif +#else +#define RP_PWM_USE_ANY_PWM811 FALSE +#endif + +#if (RP_PWM_USE_ANY_PWM07 == TRUE) || (RP_PWM_USE_ANY_PWM811 == TRUE) || \ + defined(__DOXYGEN__) + +OSAL_IRQ_HANDLER(RP_PWM_IRQ_WRAP_0_HANDLER) { + OSAL_IRQ_PROLOGUE(); + + uint32_t ints = PWM->IRQ0_INTS; + PWM->INTR = ints; + +#if RP_PWM_USE_PWM0 == TRUE + if (((ints & PWM_INTS_CH(0)) != 0) && (PWMD0.config->callback != NULL)) { + PWMD0.config->callback(&PWMD0); + } +#endif + +#if RP_PWM_USE_PWM1 == TRUE + if (((ints & PWM_INTS_CH(1)) != 0) && (PWMD1.config->callback != NULL)) { + PWMD1.config->callback(&PWMD1); + } +#endif + +#if RP_PWM_USE_PWM2 == TRUE + if (((ints & PWM_INTS_CH(2)) != 0) && (PWMD2.config->callback != NULL)) { + PWMD2.config->callback(&PWMD2); + } +#endif + +#if RP_PWM_USE_PWM3 == TRUE + if (((ints & PWM_INTS_CH(3)) != 0) && (PWMD3.config->callback != NULL)) { + PWMD3.config->callback(&PWMD3); + } +#endif + +#if RP_PWM_USE_PWM4 == TRUE + if (((ints & PWM_INTS_CH(4)) != 0) && (PWMD4.config->callback != NULL)) { + PWMD4.config->callback(&PWMD4); + } +#endif + +#if RP_PWM_USE_PWM5 == TRUE + if (((ints & PWM_INTS_CH(5)) != 0) && (PWMD5.config->callback != NULL)) { + PWMD5.config->callback(&PWMD5); + } +#endif + +#if RP_PWM_USE_PWM6 == TRUE + if (((ints & PWM_INTS_CH(6)) != 0) && (PWMD6.config->callback != NULL)) { + PWMD6.config->callback(&PWMD6); + } +#endif + +#if RP_PWM_USE_PWM7 == TRUE + if (((ints & PWM_INTS_CH(7)) != 0) && (PWMD7.config->callback != NULL)) { + PWMD7.config->callback(&PWMD7); + } +#endif + +#if RP_PWM_USE_PWM8 == TRUE + if (((ints & PWM_INTS_CH(8)) != 0) && (PWMD8.config->callback != NULL)) { + PWMD8.config->callback(&PWMD8); + } +#endif + +#if RP_PWM_USE_PWM9 == TRUE + if (((ints & PWM_INTS_CH(9)) != 0) && (PWMD9.config->callback != NULL)) { + PWMD9.config->callback(&PWMD9); + } +#endif + +#if RP_PWM_USE_PWM10 == TRUE + if (((ints & PWM_INTS_CH(10)) != 0) && (PWMD10.config->callback != NULL)) { + PWMD10.config->callback(&PWMD10); + } +#endif + +#if RP_PWM_USE_PWM11 == TRUE + if (((ints & PWM_INTS_CH(11)) != 0) && (PWMD11.config->callback != NULL)) { + PWMD11.config->callback(&PWMD11); + } +#endif + + OSAL_IRQ_EPILOGUE(); +} + +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level PWM driver initialization. + * + * @notapi + */ +void pwm_lld_init(void) { + + /* Reset PWM peripheral once for all slices. */ + rp_peripheral_reset(RESETS_ALLREG_PWM); + +#if RP_PWM_USE_PWM0 == TRUE + pwmObjectInit(&PWMD0); + PWMD0.pwm = PWM; + PWMD0.timer_id = 0; + PWMD0.channels = PWM_CHANNELS; +#endif + +#if RP_PWM_USE_PWM1 == TRUE + pwmObjectInit(&PWMD1); + PWMD1.pwm = PWM; + PWMD1.timer_id = 1; + PWMD1.channels = PWM_CHANNELS; +#endif + +#if RP_PWM_USE_PWM2 == TRUE + pwmObjectInit(&PWMD2); + PWMD2.pwm = PWM; + PWMD2.timer_id = 2; + PWMD2.channels = PWM_CHANNELS; +#endif + +#if RP_PWM_USE_PWM3 == TRUE + pwmObjectInit(&PWMD3); + PWMD3.pwm = PWM; + PWMD3.timer_id = 3; + PWMD3.channels = PWM_CHANNELS; +#endif + +#if RP_PWM_USE_PWM4 == TRUE + pwmObjectInit(&PWMD4); + PWMD4.pwm = PWM; + PWMD4.timer_id = 4; + PWMD4.channels = PWM_CHANNELS; +#endif + +#if RP_PWM_USE_PWM5 == TRUE + pwmObjectInit(&PWMD5); + PWMD5.pwm = PWM; + PWMD5.timer_id = 5; + PWMD5.channels = PWM_CHANNELS; +#endif + +#if RP_PWM_USE_PWM6 == TRUE + pwmObjectInit(&PWMD6); + PWMD6.pwm = PWM; + PWMD6.timer_id = 6; + PWMD6.channels = PWM_CHANNELS; +#endif + +#if RP_PWM_USE_PWM7 == TRUE + pwmObjectInit(&PWMD7); + PWMD7.pwm = PWM; + PWMD7.timer_id = 7; + PWMD7.channels = PWM_CHANNELS; +#endif + +#if RP_PWM_USE_PWM8 == TRUE + pwmObjectInit(&PWMD8); + PWMD8.pwm = PWM; + PWMD8.timer_id = 8; + PWMD8.channels = PWM_CHANNELS; +#endif + +#if RP_PWM_USE_PWM9 == TRUE + pwmObjectInit(&PWMD9); + PWMD9.pwm = PWM; + PWMD9.timer_id = 9; + PWMD9.channels = PWM_CHANNELS; +#endif + +#if RP_PWM_USE_PWM10 == TRUE + pwmObjectInit(&PWMD10); + PWMD10.pwm = PWM; + PWMD10.timer_id = 10; + PWMD10.channels = PWM_CHANNELS; +#endif + +#if RP_PWM_USE_PWM11 == TRUE + pwmObjectInit(&PWMD11); + PWMD11.pwm = PWM; + PWMD11.timer_id = 11; + PWMD11.channels = PWM_CHANNELS; +#endif +} + +/** + * @brief Configures and activates the PWM peripheral. + * @note Starting a driver that is already in the @p PWM_READY state + * disables all the active channels. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @notapi + */ +void pwm_lld_start(PWMDriver *pwmp) { + PWM_TypeDef *p = pwmp->pwm; + + if (pwmp->state == PWM_STOP) { + /* Clock activation and timer reset. */ + rp_peripheral_unreset(RESETS_ALLREG_PWM); + nvicEnableVector(RP_PWM_IRQ_WRAP_0_NUMBER, RP_PWM_IRQ_WRAP_NUMBER_PRIORITY); + } else { + /* Driver re-configuration scenario, it must be stopped first. */ + p->CH[pwmp->timer_id].CSR = 0; + p->CH[pwmp->timer_id].CTR = 0; + p->CH[pwmp->timer_id].CC = 0; + } + + /* Counter clock divider. */ + halfreq_t sys_clk = halClockGetPointX(RP_CLK_SYS); + halfreq_t pwm_freq_min = sys_clk / 256; + + osalDbgAssert(pwmp->config->frequency >= pwm_freq_min, + "PWM counter frequency too low"); + + /* Integer part must not be zero. */ + halfreq_t integer = sys_clk / pwmp->config->frequency; + integer = integer == 0 ? 1 : integer; + + halfreq_t fraction = (sys_clk << 4) / pwmp->config->frequency; + p->CH[pwmp->timer_id].DIV = (integer << 4 | (fraction & 0xF)); + p->CH[pwmp->timer_id].TOP = pwmp->period; + + uint32_t csr = PWM_CSR_EN | PWM_CSR_DIVMODE_FREE; + csr &= ~PWM_CSR_PH_CORRECT; + + switch (pwmp->config->channels[0].mode & PWM_OUTPUT_MASK) { + case PWM_OUTPUT_ACTIVE_LOW: + csr |= PWM_CSR_A_INV; + break; + case PWM_OUTPUT_ACTIVE_HIGH: + csr &= ~PWM_CSR_A_INV; + break; + default: + ; + } + + switch (pwmp->config->channels[1].mode & PWM_OUTPUT_MASK) { + case PWM_OUTPUT_ACTIVE_LOW: + csr |= PWM_CSR_B_INV; + break; + case PWM_OUTPUT_ACTIVE_HIGH: + csr &= ~PWM_CSR_B_INV; + break; + default: + ; + } + + p->CH[pwmp->timer_id].CSR = csr; +} + +/** + * @brief Deactivates the PWM peripheral. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @notapi + */ +void pwm_lld_stop(PWMDriver *pwmp) { + PWM_TypeDef *p = pwmp->pwm; + + /* If in ready state then disables the PWM clock. */ + if (pwmp->state == PWM_READY) { + p->CH[pwmp->timer_id].CSR = 0U; + p->CH[pwmp->timer_id].CTR = 0U; + p->CH[pwmp->timer_id].CC = 0U; + p->CH[pwmp->timer_id].DIV = 1U; + p->CH[pwmp->timer_id].TOP = 0xFFFF; + } + + /* If all timers are disabled, disable the interrupt and reset + PWM peripheral. */ + if (!p->EN) { + nvicDisableVector(RP_PWM_IRQ_WRAP_0_NUMBER); + rp_peripheral_reset(RESETS_ALLREG_PWM); + } +} + +/** + * @brief Enables a PWM channel. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The channel is active using the specified configuration. + * @note The function has effect at the next cycle start. + * @note Channel notification is not enabled. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * @param[in] width PWM pulse width as clock pulses number + * + * @notapi + */ +void pwm_lld_enable_channel(PWMDriver *pwmp, + pwmchannel_t channel, + pwmcnt_t width) { + uint32_t current_cc = pwmp->pwm->CH[pwmp->timer_id].CC; + + if (channel == 0) { + pwmp->pwm->CH[pwmp->timer_id].CC = (width & PWM_CC_A) | + (current_cc & PWM_CC_B); + } else { + pwmp->pwm->CH[pwmp->timer_id].CC = (current_cc & PWM_CC_A) | + ((width << PWM_CC_B_Pos) & PWM_CC_B); + } +} + +/** + * @brief Disables a PWM channel and its notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The channel is disabled and its output line returned to the + * idle state. + * @note The function has effect at the next cycle start. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * + * @notapi + */ +void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) { + if (channel == 0) { + pwmp->pwm->CH[pwmp->timer_id].CC &= ~PWM_CC_A | PWM_CC_B; + } else { + pwmp->pwm->CH[pwmp->timer_id].CC &= PWM_CC_A | ~PWM_CC_B; + } +} + +/** + * @brief Enables the periodic activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @note If the notification is already enabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @notapi + */ +void pwm_lld_enable_periodic_notification(PWMDriver *pwmp) { + pwmp->pwm->IRQ0_INTE |= PWM_INTE_CH(pwmp->timer_id); +} + +/** + * @brief Disables the periodic activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @note If the notification is already disabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @notapi + */ +void pwm_lld_disable_periodic_notification(PWMDriver *pwmp) { + pwmp->pwm->IRQ0_INTE &= ~PWM_INTE_CH(pwmp->timer_id); +} + +/** + * @brief Enables a channel de-activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @pre The channel must have been activated using @p pwmEnableChannel(). + * @note If the notification is already enabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * + * @notapi + */ +void pwm_lld_enable_channel_notification(PWMDriver *pwmp, + pwmchannel_t channel) { + (void)pwmp; + (void)channel; + osalDbgAssert(false, "Individual channel notifications are not available."); +} + +/** + * @brief Disables a channel de-activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @pre The channel must have been activated using @p pwmEnableChannel(). + * @note If the notification is already disabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * + * @notapi + */ +void pwm_lld_disable_channel_notification(PWMDriver *pwmp, + pwmchannel_t channel) { + (void)pwmp; + (void)channel; + osalDbgAssert(false, "Individual channel notifications are not available."); +} + +#endif /* HAL_USE_PWM == TRUE */ + +/** @} */ diff --git a/os/hal/ports/RP/LLD/PWMv1/hal_pwm_lld.h b/os/hal/ports/RP/LLD/PWMv1/hal_pwm_lld.h new file mode 100644 index 0000000000..f04ee5f77b --- /dev/null +++ b/os/hal/ports/RP/LLD/PWMv1/hal_pwm_lld.h @@ -0,0 +1,478 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file PWMv1/hal_pwm_lld.h + * @brief RP PWM subsystem low level driver header. + * + * @addtogroup PWM + * @{ + */ + +#ifndef HAL_PWM_LLD_H +#define HAL_PWM_LLD_H + +#if (HAL_USE_PWM == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Number of PWM channels per PWM driver. + */ +#define PWM_CHANNELS 2 + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name RP configuration options + * @{ + */ + +/** + * @brief PWMD0 driver enable switch. + * @details If set to @p TRUE the support for PWM0 is included. + * @note The default is @p FALSE. + */ +#if !defined(RP_PWM_USE_PWM0) || defined(__DOXYGEN__) +#define RP_PWM_USE_PWM0 FALSE +#endif + +/** + * @brief PWMD1 driver enable switch. + * @details If set to @p TRUE the support for PWM1 is included. + * @note The default is @p FALSE. + */ +#if !defined(RP_PWM_USE_PWM1) || defined(__DOXYGEN__) +#define RP_PWM_USE_PWM1 FALSE +#endif + +/** + * @brief PWMD2 driver enable switch. + * @details If set to @p TRUE the support for PWM2 is included. + * @note The default is @p FALSE. + */ +#if !defined(RP_PWM_USE_PWM2) || defined(__DOXYGEN__) +#define RP_PWM_USE_PWM2 FALSE +#endif + +/** + * @brief PWMD3 driver enable switch. + * @details If set to @p TRUE the support for PWM3 is included. + * @note The default is @p FALSE. + */ +#if !defined(RP_PWM_USE_PWM3) || defined(__DOXYGEN__) +#define RP_PWM_USE_PWM3 FALSE +#endif + +/** + * @brief PWMD4 driver enable switch. + * @details If set to @p TRUE the support for PWM4 is included. + * @note The default is @p FALSE. + */ +#if !defined(RP_PWM_USE_PWM4) || defined(__DOXYGEN__) +#define RP_PWM_USE_PWM4 FALSE +#endif + +/** + * @brief PWMD5 driver enable switch. + * @details If set to @p TRUE the support for PWM5 is included. + * @note The default is @p FALSE. + */ +#if !defined(RP_PWM_USE_PWM5) || defined(__DOXYGEN__) +#define RP_PWM_USE_PWM5 FALSE +#endif + +/** + * @brief PWMD6 driver enable switch. + * @details If set to @p TRUE the support for PWM6 is included. + * @note The default is @p FALSE. + */ +#if !defined(RP_PWM_USE_PWM6) || defined(__DOXYGEN__) +#define RP_PWM_USE_PWM6 FALSE +#endif + +/** + * @brief PWMD7 driver enable switch. + * @details If set to @p TRUE the support for PWM7 is included. + * @note The default is @p FALSE. + */ +#if !defined(RP_PWM_USE_PWM7) || defined(__DOXYGEN__) +#define RP_PWM_USE_PWM7 FALSE +#endif + +/** + * @brief PWMD8 driver enable switch. + * @details If set to @p TRUE the support for PWM8 is included. + * @note The default is @p FALSE. + */ +#if !defined(RP_PWM_USE_PWM8) || defined(__DOXYGEN__) +#define RP_PWM_USE_PWM8 FALSE +#endif + +/** + * @brief PWMD9 driver enable switch. + * @details If set to @p TRUE the support for PWM9 is included. + * @note The default is @p FALSE. + */ +#if !defined(RP_PWM_USE_PWM9) || defined(__DOXYGEN__) +#define RP_PWM_USE_PWM9 FALSE +#endif + +/** + * @brief PWMD10 driver enable switch. + * @details If set to @p TRUE the support for PWM10 is included. + * @note The default is @p FALSE. + */ +#if !defined(RP_PWM_USE_PWM10) || defined(__DOXYGEN__) +#define RP_PWM_USE_PWM10 FALSE +#endif + +/** + * @brief PWMD11 driver enable switch. + * @details If set to @p TRUE the support for PWM11 is included. + * @note The default is @p FALSE. + */ +#if !defined(RP_PWM_USE_PWM11) || defined(__DOXYGEN__) +#define RP_PWM_USE_PWM11 FALSE +#endif + +/** + * @brief PWM interrupt priority level setting. + */ +#if !defined(RP_PWM_IRQ_WRAP_NUMBER_PRIORITY) || defined(__DOXYGEN__) +#define RP_PWM_IRQ_WRAP_NUMBER_PRIORITY 3 +#endif + +/** @} */ + +/*===========================================================================*/ +/* Configuration checks. */ +/*===========================================================================*/ + +/* Registry checks for robustness. */ +#if !defined(RP_HAS_PWM) +#error "RP_HAS_PWM not defined in registry" +#endif + +#if !defined(RP_HAS_PWM0) +#error "RP_HAS_PWM0 not defined in registry" +#endif + +#if !defined(RP_HAS_PWM1) +#error "RP_HAS_PWM1 not defined in registry" +#endif + +#if !defined(RP_HAS_PWM2) +#error "RP_HAS_PWM2 not defined in registry" +#endif + +#if !defined(RP_HAS_PWM3) +#error "RP_HAS_PWM3 not defined in registry" +#endif + +#if !defined(RP_HAS_PWM4) +#error "RP_HAS_PWM4 not defined in registry" +#endif + +#if !defined(RP_HAS_PWM5) +#error "RP_HAS_PWM5 not defined in registry" +#endif + +#if !defined(RP_HAS_PWM6) +#error "RP_HAS_PWM6 not defined in registry" +#endif + +#if !defined(RP_HAS_PWM7) +#error "RP_HAS_PWM7 not defined in registry" +#endif + +#if !defined(RP_HAS_PWM8) +#error "RP_HAS_PWM8 not defined in registry" +#endif + +#if !defined(RP_HAS_PWM9) +#error "RP_HAS_PWM9 not defined in registry" +#endif + +#if !defined(RP_HAS_PWM10) +#error "RP_HAS_PWM10 not defined in registry" +#endif + +#if !defined(RP_HAS_PWM11) +#error "RP_HAS_PWM11 not defined in registry" +#endif + +#if (RP_PWM_USE_PWM0 == TRUE) && (RP_HAS_PWM0 != TRUE) +#error "PWM0 not present in the selected device" +#endif + +#if (RP_PWM_USE_PWM1 == TRUE) && (RP_HAS_PWM1 != TRUE) +#error "PWM1 not present in the selected device" +#endif + +#if (RP_PWM_USE_PWM2 == TRUE) && (RP_HAS_PWM2 != TRUE) +#error "PWM2 not present in the selected device" +#endif + +#if (RP_PWM_USE_PWM3 == TRUE) && (RP_HAS_PWM3 != TRUE) +#error "PWM3 not present in the selected device" +#endif + +#if (RP_PWM_USE_PWM4 == TRUE) && (RP_HAS_PWM4 != TRUE) +#error "PWM4 not present in the selected device" +#endif + +#if (RP_PWM_USE_PWM5 == TRUE) && (RP_HAS_PWM5 != TRUE) +#error "PWM5 not present in the selected device" +#endif + +#if (RP_PWM_USE_PWM6 == TRUE) && (RP_HAS_PWM6 != TRUE) +#error "PWM6 not present in the selected device" +#endif + +#if (RP_PWM_USE_PWM7 == TRUE) && (RP_HAS_PWM7 != TRUE) +#error "PWM7 not present in the selected device" +#endif + +#if (RP_PWM_USE_PWM8 == TRUE) && (RP_HAS_PWM8 != TRUE) +#error "PWM8 not present in the selected device" +#endif + +#if (RP_PWM_USE_PWM9 == TRUE) && (RP_HAS_PWM9 != TRUE) +#error "PWM9 not present in the selected device" +#endif + +#if (RP_PWM_USE_PWM10 == TRUE) && (RP_HAS_PWM10 != TRUE) +#error "PWM10 not present in the selected device" +#endif + +#if (RP_PWM_USE_PWM11 == TRUE) && (RP_HAS_PWM11 != TRUE) +#error "PWM11 not present in the selected device" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a PWM mode. + */ +typedef uint32_t pwmmode_t; + +/** + * @brief Type of a PWM channel. + */ +typedef uint8_t pwmchannel_t; + +/** + * @brief Type of a channels mask. + */ +typedef uint32_t pwmchnmsk_t; + +/** + * @brief Type of a PWM counter. + */ +typedef uint16_t pwmcnt_t; + +/** + * @brief Type of a PWM driver channel configuration structure. + */ +typedef struct { + /** + * @brief Channel active logic level. + */ + pwmmode_t mode; + /** + * @brief Channel callback pointer. + * @note This callback is invoked on the channel compare event. If set to + * @p NULL then the callback is disabled. + */ + pwmcallback_t callback; + /* End of the mandatory fields.*/ +} PWMChannelConfig; + +/** + * @brief Type of a PWM driver configuration structure. + */ +typedef struct { + /** + * @brief Timer clock in Hz. + * @note The low level can use assertions in order to catch invalid + * frequency specifications. + */ + uint32_t frequency; + /** + * @brief PWM period in ticks. + * @note The low level can use assertions in order to catch invalid + * period specifications. + */ + pwmcnt_t period; + /** + * @brief Periodic callback pointer. + * @note This callback is invoked on PWM counter reset. If set to + * @p NULL then the callback is disabled. + */ + pwmcallback_t callback; + /** + * @brief Channels configurations. + */ + PWMChannelConfig channels[PWM_CHANNELS]; + /* End of the mandatory fields.*/ +} PWMConfig; + +/** + * @brief Structure representing a PWM driver. + */ +struct PWMDriver { + /** + * @brief Driver state. + */ + pwmstate_t state; + /** + * @brief Current driver configuration data. + */ + const PWMConfig *config; + /** + * @brief Current PWM period in ticks. + */ + pwmcnt_t period; + /** + * @brief Mask of the enabled channels. + */ + pwmchnmsk_t enabled; + /** + * @brief Number of channels in this instance. + */ + pwmchannel_t channels; +#if defined(PWM_DRIVER_EXT_FIELDS) + PWM_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the PWM registers block. + */ + PWM_TypeDef *pwm; + + /** + * @brief Index of the associated PWM timer. + */ + pwmchannel_t timer_id; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Changes the period the PWM peripheral. + * @details This function changes the period of a PWM unit that has already + * been activated using @p pwmStart(). + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The PWM unit period is changed to the new value. + * @note The function has effect at the next cycle start. + * @note If a period is specified that is shorter than the pulse width + * programmed in one of the channels then the behavior is not + * guaranteed. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] period new cycle time in ticks + * + * @notapi + */ +#define pwm_lld_change_period(pwmp, period) \ + ((pwmp)->pwm->CH[(pwmp)->timer_id].TOP = (period)) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if (RP_PWM_USE_PWM0 == TRUE) && !defined(__DOXYGEN__) +extern PWMDriver PWMD0; +#endif + +#if (RP_PWM_USE_PWM1 == TRUE) && !defined(__DOXYGEN__) +extern PWMDriver PWMD1; +#endif + +#if (RP_PWM_USE_PWM2 == TRUE) && !defined(__DOXYGEN__) +extern PWMDriver PWMD2; +#endif + +#if (RP_PWM_USE_PWM3 == TRUE) && !defined(__DOXYGEN__) +extern PWMDriver PWMD3; +#endif + +#if (RP_PWM_USE_PWM4 == TRUE) && !defined(__DOXYGEN__) +extern PWMDriver PWMD4; +#endif + +#if (RP_PWM_USE_PWM5 == TRUE) && !defined(__DOXYGEN__) +extern PWMDriver PWMD5; +#endif + +#if (RP_PWM_USE_PWM6 == TRUE) && !defined(__DOXYGEN__) +extern PWMDriver PWMD6; +#endif + +#if (RP_PWM_USE_PWM7 == TRUE) && !defined(__DOXYGEN__) +extern PWMDriver PWMD7; +#endif + +#if (RP_PWM_USE_PWM8 == TRUE) && !defined(__DOXYGEN__) +extern PWMDriver PWMD8; +#endif + +#if (RP_PWM_USE_PWM9 == TRUE) && !defined(__DOXYGEN__) +extern PWMDriver PWMD9; +#endif + +#if (RP_PWM_USE_PWM10 == TRUE) && !defined(__DOXYGEN__) +extern PWMDriver PWMD10; +#endif + +#if (RP_PWM_USE_PWM11 == TRUE) && !defined(__DOXYGEN__) +extern PWMDriver PWMD11; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void pwm_lld_init(void); + void pwm_lld_start(PWMDriver *pwmp); + void pwm_lld_stop(PWMDriver *pwmp); + void pwm_lld_enable_channel(PWMDriver *pwmp, + pwmchannel_t channel, + pwmcnt_t width); + void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel); + void pwm_lld_enable_periodic_notification(PWMDriver *pwmp); + void pwm_lld_disable_periodic_notification(PWMDriver *pwmp); + void pwm_lld_enable_channel_notification(PWMDriver *pwmp, + pwmchannel_t channel); + void pwm_lld_disable_channel_notification(PWMDriver *pwmp, + pwmchannel_t channel); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_PWM == TRUE */ + +#endif /* HAL_PWM_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/RP/LLD/RTCv1/hal_rtc_lld.c b/os/hal/ports/RP/LLD/RTCv1/hal_rtc_lld.c index 3e2f1ddf57..b31763b642 100644 --- a/os/hal/ports/RP/LLD/RTCv1/hal_rtc_lld.c +++ b/os/hal/ports/RP/LLD/RTCv1/hal_rtc_lld.c @@ -119,11 +119,11 @@ void rtc_lld_init(void) { RTCD1.rtc = RTC; /* Get clock parameters. */ - uint32_t clock = hal_lld_get_clock_point(clk_rtc); - osalDbgAssert((clock > 0U) || (clock - 1 <= RTC_CLKDIV_M1), "bad clock"); + uint32_t clock = hal_lld_get_clock_point(RP_CLK_RTC); + osalDbgAssert((clock > 0U) && (clock - 1 <= RTC_CLKDIV_M1), "bad clock"); /* Take RTC out of reset. */ - hal_lld_peripheral_unreset(RESETS_ALLREG_RTC); + rp_peripheral_unreset(RESETS_ALLREG_RTC); /* Set divider. */ RTCD1.rtc->CLKDIVM1 = clock - 1; @@ -157,7 +157,7 @@ void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec) { syssts_t sts = osalSysGetStatusAndLockX(); /* Disable RTC. */ - rtcp->rtc->CTRL &= ~RTC_CTRL_RTC_ENABLE; + rtcp->rtc->CTRL = 0; /* Wait for RTC to go inactive. */ while ((rtcp->rtc->CTRL & RTC_CTRL_RTC_ACTIVE) != 0) @@ -167,16 +167,18 @@ void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec) { rtcp->rtc->SETUP0 = (RTC_SETUP_0_YEAR(timespec->year + RTC_BASE_YEAR)) | (RTC_SETUP_0_MONTH(timespec->month)) | (RTC_SETUP_0_DAY(timespec->day)); - rtcp->rtc->SETUP1 = (RTC_SETUP_1_DOTW(timespec->dayofweek - 1)) | - (RTC_SETUP_1_HOUR(hour)) | - (RTC_SETUP_1_MIN(min)) | - (RTC_SETUP_1_SEC(sec)); + rtcp->rtc->SETUP1 = (RTC_SETUP_1_DOTW(timespec->dayofweek > 0U ? + timespec->dayofweek - 1U : 0U) + & RTC_SETUP_1_DOTW_Msk) | + (RTC_SETUP_1_HOUR(hour) & RTC_SETUP_1_HOUR_Msk) | + (RTC_SETUP_1_MIN(min) & RTC_SETUP_1_MIN_Msk) | + (RTC_SETUP_1_SEC(sec) & RTC_SETUP_1_SEC_Msk); /* Move setup values into RTC clock domain. */ rtcp->rtc->CTRL = RTC_CTRL_LOAD; /* Enable RTC and wait for active. */ - rtcp->rtc->CTRL |= RTC_CTRL_RTC_ENABLE; + rtcp->rtc->CTRL = RTC_CTRL_RTC_ENABLE; /* Leaving a reentrant critical zone.*/ osalSysRestoreStatusX(sts); @@ -258,13 +260,14 @@ void rtc_lld_set_alarm(RTCDriver *rtcp, year = timespec->year + RTC_BASE_YEAR; /* Setup register data. */ - setup0 = (RTC_IRQ_SETUP_0_YEAR(year)) | - (RTC_IRQ_SETUP_0_MONTH(month)) | - (RTC_IRQ_SETUP_0_DAY(day)); - setup1 = (RTC_IRQ_SETUP_1_DOTW(dotw - 1)) | - (RTC_IRQ_SETUP_1_HOUR(hour)) | - (RTC_IRQ_SETUP_1_MIN(min)) | - (RTC_IRQ_SETUP_1_SEC(sec)); + setup0 = (RTC_IRQ_SETUP_0_YEAR(year) & RTC_IRQ_SETUP_0_YEAR_Msk) | + (RTC_IRQ_SETUP_0_MONTH(month) & RTC_IRQ_SETUP_0_MONTH_Msk) | + (RTC_IRQ_SETUP_0_DAY(day) & RTC_IRQ_SETUP_0_DAY_Msk); + setup1 = (RTC_IRQ_SETUP_1_DOTW(dotw > 0U ? dotw - 1U : 0U) + & RTC_IRQ_SETUP_1_DOTW_Msk) | + (RTC_IRQ_SETUP_1_HOUR(hour) & RTC_IRQ_SETUP_1_HOUR_Msk) | + (RTC_IRQ_SETUP_1_MIN(min) & RTC_IRQ_SETUP_1_MIN_Msk) | + (RTC_IRQ_SETUP_1_SEC(sec) & RTC_IRQ_SETUP_1_SEC_Msk); /* Check and set match enable bits. */ if (RTC_ALARM_TEST_MATCH(dtmask, RTC_DT_ALARM_YEAR)) diff --git a/os/hal/ports/RP/LLD/SPIv1/driver.mk b/os/hal/ports/RP/LLD/SPIv1/driver.mk index 9dc5e28a28..e1e8e081d6 100644 --- a/os/hal/ports/RP/LLD/SPIv1/driver.mk +++ b/os/hal/ports/RP/LLD/SPIv1/driver.mk @@ -1,2 +1,9 @@ +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_SPI TRUE,$(HALCONF)),) PLATFORMSRC += $(CHIBIOS)/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.c +endif + PLATFORMINC += $(CHIBIOS)/os/hal/ports/RP/LLD/SPIv1 diff --git a/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.c b/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.c index fe77e3bc95..c0016d6bbb 100644 --- a/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.c +++ b/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.c @@ -175,7 +175,7 @@ void spi_lld_start(SPIDriver *spip) { osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); dmaChannelEnableInterruptX(spip->dmarx); dmaChannelEnableInterruptX(spip->dmatx); - hal_lld_peripheral_unreset(RESETS_ALLREG_SPI0); + rp_peripheral_unreset(RESETS_ALLREG_SPI0); } #endif #if RP_SPI_USE_SPI1 == TRUE @@ -192,7 +192,7 @@ void spi_lld_start(SPIDriver *spip) { osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); dmaChannelEnableInterruptX(spip->dmarx); dmaChannelEnableInterruptX(spip->dmatx); - hal_lld_peripheral_unreset(RESETS_ALLREG_SPI1); + rp_peripheral_unreset(RESETS_ALLREG_SPI1); } #endif else { @@ -251,12 +251,12 @@ void spi_lld_stop(SPIDriver *spip) { } #if RP_SPI_USE_SPI0 == TRUE else if (&SPID0 == spip) { - hal_lld_peripheral_reset(RESETS_ALLREG_SPI0); + rp_peripheral_reset(RESETS_ALLREG_SPI0); } #endif #if RP_SPI_USE_SPI1 == TRUE else if (&SPID1 == spip) { - hal_lld_peripheral_reset(RESETS_ALLREG_SPI1); + rp_peripheral_reset(RESETS_ALLREG_SPI1); } #endif else { @@ -431,10 +431,10 @@ void spi_lld_abort(SPIDriver *spip) { */ uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) { - (void)spip; - (void)frame; - - return 0; + spip->spi->SSPDR = (uint32_t)frame; + while ((spip->spi->SSPSR & SPI_SSPSR_RNE) == 0U) + ; + return (uint16_t)spip->spi->SSPDR; } #endif /* HAL_USE_SPI == TRUE */ diff --git a/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.h b/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.h index 560f405124..551a129339 100644 --- a/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.h +++ b/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.h @@ -79,11 +79,11 @@ #endif #if !defined(RP_SPI_SPI1_RX_DMA_CHANNEL) -#error "RP_SPI_SPI0_RX_DMA_CHANNEL not defined in mcuconf.h" +#error "RP_SPI_SPI1_RX_DMA_CHANNEL not defined in mcuconf.h" #endif #if !defined(RP_SPI_SPI1_TX_DMA_CHANNEL) -#error "RP_SPI_SPI0_TX_DMA_CHANNEL not defined in mcuconf.h" +#error "RP_SPI_SPI1_TX_DMA_CHANNEL not defined in mcuconf.h" #endif #if !defined(RP_SPI_SPI0_DMA_PRIORITY) diff --git a/os/hal/ports/RP/LLD/TIMERv1/hal_st_lld.c b/os/hal/ports/RP/LLD/TIMERv1/hal_st_lld.c index 6bace37fc0..4c8c507136 100644 --- a/os/hal/ports/RP/LLD/TIMERv1/hal_st_lld.c +++ b/os/hal/ports/RP/LLD/TIMERv1/hal_st_lld.c @@ -58,10 +58,10 @@ typedef struct { #if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) || defined(__DOXYGEN__) #if (ST_LLD_NUM_ALARMS > 1) || defined(__DOXYGEN__) static const alarm_irq_t alarm_irqs[ST_LLD_NUM_ALARMS] = { - {RP_TIMER_IRQ0_NUMBER, RP_IRQ_TIMER_ALARM0_PRIORITY}, - {RP_TIMER_IRQ1_NUMBER, RP_IRQ_TIMER_ALARM1_PRIORITY}, - {RP_TIMER_IRQ2_NUMBER, RP_IRQ_TIMER_ALARM2_PRIORITY}, - {RP_TIMER_IRQ3_NUMBER, RP_IRQ_TIMER_ALARM3_PRIORITY} + {RP_TIMER0_IRQ0_NUMBER, RP_IRQ_TIMER0_ALARM0_PRIORITY}, + {RP_TIMER0_IRQ1_NUMBER, RP_IRQ_TIMER0_ALARM1_PRIORITY}, + {RP_TIMER0_IRQ2_NUMBER, RP_IRQ_TIMER0_ALARM2_PRIORITY}, + {RP_TIMER0_IRQ3_NUMBER, RP_IRQ_TIMER0_ALARM3_PRIORITY} }; #endif #endif @@ -101,13 +101,13 @@ OSAL_IRQ_HANDLER(SysTick_Handler) { * * @isr */ -OSAL_IRQ_HANDLER(RP_TIMER_IRQ0_HANDLER) { +OSAL_IRQ_HANDLER(RP_TIMER0_IRQ0_HANDLER) { OSAL_IRQ_PROLOGUE(); - osalDbgAssert((TIMER->INTS & TIMER_INTS_ALARM0) != 0U, "not pending"); + osalDbgAssert((TIMER0->INTS & TIMER_INTS_ALARM0) != 0U, "not pending"); - TIMER->INTR = TIMER_INTR_ALARM0; + TIMER0->INTR = TIMER_INTR_ALARM0; #if defined(ST_LLD_ALARM0_STATIC_CB) ST_LLD_ALARM0_STATIC_CB(); @@ -127,13 +127,13 @@ OSAL_IRQ_HANDLER(RP_TIMER_IRQ0_HANDLER) { * * @isr */ -OSAL_IRQ_HANDLER(RP_TIMER_IRQ1_HANDLER) { +OSAL_IRQ_HANDLER(RP_TIMER0_IRQ1_HANDLER) { OSAL_IRQ_PROLOGUE(); - osalDbgAssert((TIMER->INTS & TIMER_INTS_ALARM1) != 0U, "not pending"); + osalDbgAssert((TIMER0->INTS & TIMER_INTS_ALARM1) != 0U, "not pending"); - TIMER->INTR = TIMER_INTR_ALARM1; + TIMER0->INTR = TIMER_INTR_ALARM1; #if defined(ST_LLD_ALARM1_STATIC_CB) ST_LLD_ALARM1_STATIC_CB(); @@ -153,13 +153,13 @@ OSAL_IRQ_HANDLER(RP_TIMER_IRQ1_HANDLER) { * * @isr */ -OSAL_IRQ_HANDLER(RP_TIMER_IRQ2_HANDLER) { +OSAL_IRQ_HANDLER(RP_TIMER0_IRQ2_HANDLER) { OSAL_IRQ_PROLOGUE(); - osalDbgAssert((TIMER->INTS & TIMER_INTS_ALARM2) != 0U, "not pending"); + osalDbgAssert((TIMER0->INTS & TIMER_INTS_ALARM2) != 0U, "not pending"); - TIMER->INTR = TIMER_INTR_ALARM2; + TIMER0->INTR = TIMER_INTR_ALARM2; #if defined(ST_LLD_ALARM2_STATIC_CB) ST_LLD_ALARM2_STATIC_CB(); @@ -179,13 +179,13 @@ OSAL_IRQ_HANDLER(RP_TIMER_IRQ2_HANDLER) { * * @isr */ -OSAL_IRQ_HANDLER(RP_TIMER_IRQ3_HANDLER) { +OSAL_IRQ_HANDLER(RP_TIMER0_IRQ3_HANDLER) { OSAL_IRQ_PROLOGUE(); - osalDbgAssert((TIMER->INTS & TIMER_INTS_ALARM3) != 0U, "not pending"); + osalDbgAssert((TIMER0->INTS & TIMER_INTS_ALARM3) != 0U, "not pending"); - TIMER->INTR = TIMER_INTR_ALARM3; + TIMER0->INTR = TIMER_INTR_ALARM3; #if defined(ST_LLD_ALARM3_STATIC_CB) ST_LLD_ALARM3_STATIC_CB(); @@ -215,17 +215,17 @@ void st_lld_init(void) { #if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING /* The timer needs to stop during debug or the virtual timers list would go out of sync.*/ - TIMER->DBGPAUSE = TIMER_DBGPAUSE_DBG0 | TIMER_DBGPAUSE_DBG1; + TIMER0->DBGPAUSE = TIMER_DBGPAUSE_DBG0 | TIMER_DBGPAUSE_DBG1; /* Comparators and counter initially at zero.*/ - TIMER->TIMELW = 0U; - TIMER->TIMEHW = 0U; - TIMER->ALARM[0] = 0U; - TIMER->ALARM[1] = 0U; - TIMER->ALARM[2] = 0U; - TIMER->ALARM[3] = 0U; - TIMER->INTE = 0U; - TIMER->INTR = TIMER_INTR_ALARM3 | TIMER_INTR_ALARM2 | + TIMER0->TIMELW = 0U; + TIMER0->TIMEHW = 0U; + TIMER0->ALARM[0] = 0U; + TIMER0->ALARM[1] = 0U; + TIMER0->ALARM[2] = 0U; + TIMER0->ALARM[3] = 0U; + TIMER0->INTE = 0U; + TIMER0->INTR = TIMER_INTR_ALARM3 | TIMER_INTR_ALARM2 | TIMER_INTR_ALARM1 | TIMER_INTR_ALARM0; #endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */ @@ -240,7 +240,7 @@ void st_lld_init(void) { void st_lld_bind(void) { #if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING - nvicEnableVector(RP_TIMER_IRQ0_NUMBER, RP_IRQ_TIMER_ALARM0_PRIORITY); + nvicEnableVector(RP_TIMER0_IRQ0_NUMBER, RP_IRQ_TIMER0_ALARM0_PRIORITY); #endif #if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC uint32_t timer_clk = RP_CORE_CLK; diff --git a/os/hal/ports/RP/LLD/TIMERv1/hal_st_lld.h b/os/hal/ports/RP/LLD/TIMERv1/hal_st_lld.h index dd27d64fcf..3e2f67b46c 100644 --- a/os/hal/ports/RP/LLD/TIMERv1/hal_st_lld.h +++ b/os/hal/ports/RP/LLD/TIMERv1/hal_st_lld.h @@ -34,7 +34,7 @@ /** * @brief Number of supported alarms. */ -#define ST_LLD_NUM_ALARMS 4U +#define ST_LLD_NUM_ALARMS RP_ST_NUM_ALARMS /** * @brief Static callback for alarm 0. @@ -77,31 +77,31 @@ #endif /** - * @brief TIMER alarm 0 IRQ priority. + * @brief TIMER0 alarm 0 IRQ priority. */ -#if !defined(RP_IRQ_TIMER_ALARM0_PRIORITY) || defined(__DOXYGEN__) -#define RP_IRQ_TIMER_ALARM0_PRIORITY 2 +#if !defined(RP_IRQ_TIMER0_ALARM0_PRIORITY) || defined(__DOXYGEN__) +#define RP_IRQ_TIMER0_ALARM0_PRIORITY 2 #endif /** - * @brief TIMER alarm 1 IRQ priority. + * @brief TIMER0 alarm 1 IRQ priority. */ -#if !defined(RP_IRQ_TIMER_ALARM1_PRIORITY) || defined(__DOXYGEN__) -#define RP_IRQ_TIMER_ALARM1_PRIORITY 2 +#if !defined(RP_IRQ_TIMER0_ALARM1_PRIORITY) || defined(__DOXYGEN__) +#define RP_IRQ_TIMER0_ALARM1_PRIORITY 2 #endif /** - * @brief TIMER alarm 2 IRQ priority. + * @brief TIMER0 alarm 2 IRQ priority. */ -#if !defined(RP_IRQ_TIMER_ALARM2_PRIORITY) || defined(__DOXYGEN__) -#define RP_IRQ_TIMER_ALARM2_PRIORITY 2 +#if !defined(RP_IRQ_TIMER0_ALARM2_PRIORITY) || defined(__DOXYGEN__) +#define RP_IRQ_TIMER0_ALARM2_PRIORITY 2 #endif /** - * @brief TIMER alarm 3 IRQ priority. + * @brief TIMER0 alarm 3 IRQ priority. */ -#if !defined(RP_IRQ_TIMER_ALARM3_PRIORITY) || defined(__DOXYGEN__) -#define RP_IRQ_TIMER_ALARM3_PRIORITY 2 +#if !defined(RP_IRQ_TIMER0_ALARM3_PRIORITY) || defined(__DOXYGEN__) +#define RP_IRQ_TIMER0_ALARM3_PRIORITY 2 #endif /** @} */ @@ -170,13 +170,14 @@ extern "C" { */ __STATIC_INLINE systime_t st_lld_get_counter(void) { - return (systime_t)TIMER->TIMERAWL; + return (systime_t)TIMER0->TIMERAWL; } /** * @brief Starts the alarm. * @note Makes sure that no spurious alarms are triggered after * this call. + * @note Uses atomic SET/CLR registers for dual-core safe INTE access. * * @param[in] abstime the time to be set for the first alarm * @@ -184,19 +185,24 @@ __STATIC_INLINE systime_t st_lld_get_counter(void) { */ __STATIC_INLINE void st_lld_start_alarm(systime_t abstime) { - TIMER->ALARM[0] = (uint32_t)abstime; - TIMER->INTR = (1U << 0); - TIMER->INTE |= (1U << 0); + TIMER0->ALARM[0] = (uint32_t)abstime; + TIMER0->INTR = (1U << 0); + TIMER0->SET.INTE = (1U << 0); + /* Re-arm if abstime already past to avoid ~71 min wait for counter wrap. */ + if ((int32_t)(abstime - TIMER0->TIMERAWL) <= 0) { + TIMER0->ALARM[0] = TIMER0->TIMERAWL + 2U; + } } /** * @brief Stops the alarm interrupt. + * @note Uses atomic CLR register for dual-core safe INTE access. * * @notapi */ __STATIC_INLINE void st_lld_stop_alarm(void) { - TIMER->INTE &= ~(1U << 0); + TIMER0->CLR.INTE = (1U << 0); } /** @@ -208,7 +214,7 @@ __STATIC_INLINE void st_lld_stop_alarm(void) { */ __STATIC_INLINE void st_lld_set_alarm(systime_t abstime) { - TIMER->ALARM[0] = (uint32_t)abstime; + TIMER0->ALARM[0] = (uint32_t)abstime; } /** @@ -220,7 +226,7 @@ __STATIC_INLINE void st_lld_set_alarm(systime_t abstime) { */ __STATIC_INLINE systime_t st_lld_get_alarm(void) { - return (systime_t)TIMER->ALARM[0]; + return (systime_t)TIMER0->ALARM[0]; } /** @@ -234,7 +240,7 @@ __STATIC_INLINE systime_t st_lld_get_alarm(void) { */ __STATIC_INLINE bool st_lld_is_alarm_active(void) { - return (bool)((TIMER->INTE & (1U << 0)) != 0U); + return (bool)((TIMER0->INTE & (1U << 0)) != 0U); } #if (ST_LLD_NUM_ALARMS > 1) || defined(__DOXYGEN__) @@ -252,10 +258,13 @@ __STATIC_INLINE bool st_lld_is_alarm_active(void) { */ __STATIC_INLINE void st_lld_start_alarm_n(unsigned alarm, systime_t abstime) { - - TIMER->ALARM[alarm] = (uint32_t)abstime; - TIMER->INTR = (1U << alarm); - TIMER->INTE |= (1U << alarm); + TIMER0->ALARM[alarm] = (uint32_t)abstime; + TIMER0->INTR = (1U << alarm); + TIMER0->SET.INTE = (1U << alarm); + /* Re-arm if abstime already past to avoid ~71 min wait for counter wrap. */ + if ((int32_t)(abstime - TIMER0->TIMERAWL) <= 0) { + TIMER0->ALARM[alarm] = TIMER0->TIMERAWL + 2U; + } } /** @@ -269,7 +278,7 @@ __STATIC_INLINE void st_lld_start_alarm_n(unsigned alarm, systime_t abstime) { */ __STATIC_INLINE void st_lld_stop_alarm_n(unsigned alarm) { - TIMER->INTE &= ~(1U << alarm); + TIMER0->CLR.INTE = (1U << alarm); } /** @@ -284,7 +293,7 @@ __STATIC_INLINE void st_lld_stop_alarm_n(unsigned alarm) { */ __STATIC_INLINE void st_lld_set_alarm_n(unsigned alarm, systime_t abstime) { - TIMER->ALARM[alarm] = (uint32_t)abstime; + TIMER0->ALARM[alarm] = (uint32_t)abstime; } /** @@ -299,7 +308,7 @@ __STATIC_INLINE void st_lld_set_alarm_n(unsigned alarm, systime_t abstime) { */ __STATIC_INLINE systime_t st_lld_get_alarm_n(unsigned alarm) { - return (systime_t)TIMER->ALARM[alarm]; + return (systime_t)TIMER0->ALARM[alarm]; } /** @@ -314,7 +323,7 @@ __STATIC_INLINE systime_t st_lld_get_alarm_n(unsigned alarm) { */ static inline bool st_lld_is_alarm_active_n(unsigned alarm) { - return (bool)((TIMER->INTE & (1U << alarm)) != 0U); + return (bool)((TIMER0->INTE & (1U << alarm)) != 0U); } #endif /* ST_LLD_NUM_ALARMS > 1 */ #endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */ diff --git a/os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.c b/os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.c index 07fe040391..b80bd8067c 100644 --- a/os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.c +++ b/os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.c @@ -112,7 +112,7 @@ __STATIC_INLINE void uart_init(SIODriver *siop) { uint32_t div, idiv, fdiv; halfreq_t clock; - clock = halClockGetPointX(clk_peri); + clock = halClockGetPointX(RP_CLK_PERI); osalDbgAssert(clock > 0U, "no clock"); @@ -125,14 +125,15 @@ __STATIC_INLINE void uart_init(SIODriver *siop) { siop->uart->UARTIBRD = idiv; siop->uart->UARTFBRD = fdiv; + uint32_t cr = siop->config->UARTCR & ~UART_CR_CFG_FORBIDDEN; + /* Registers settings, the LCR_H write also latches dividers values.*/ siop->uart->UARTLCR_H = siop->config->UARTLCR_H & ~UART_LCRH_CFG_FORBIDDEN; - siop->uart->UARTCR = siop->config->UARTCR & ~UART_CR_CFG_FORBIDDEN; + siop->uart->UARTCR = cr; /* Setting up the operation.*/ siop->uart->UARTICR = siop->uart->UARTRIS; - siop->uart->UARTCR = siop->config->UARTCR | - UART_UARTCR_RXE | UART_UARTCR_TXE | UART_UARTCR_UARTEN; + siop->uart->UARTCR = cr | UART_UARTCR_RXE | UART_UARTCR_TXE | UART_UARTCR_UARTEN; } /*===========================================================================*/ @@ -154,12 +155,12 @@ void sio_lld_init(void) { #if RP_SIO_USE_UART0 == TRUE sioObjectInit(&SIOD0); SIOD0.uart = UART0; - hal_lld_peripheral_reset(RESETS_ALLREG_UART0); + rp_peripheral_reset(RESETS_ALLREG_UART0); #endif #if RP_SIO_USE_UART1 == TRUE sioObjectInit(&SIOD1); SIOD1.uart = UART1; - hal_lld_peripheral_reset(RESETS_ALLREG_UART1); + rp_peripheral_reset(RESETS_ALLREG_UART1); #endif } @@ -186,13 +187,13 @@ msg_t sio_lld_start(SIODriver *siop) { } #if RP_SIO_USE_UART0 == TRUE else if (&SIOD0 == siop) { - hal_lld_peripheral_unreset(RESETS_ALLREG_UART0); + rp_peripheral_unreset(RESETS_ALLREG_UART0); nvicEnableVector(RP_UART0_IRQ_NUMBER, RP_IRQ_UART0_PRIORITY); } #endif #if RP_SIO_USE_UART1 == TRUE else if (&SIOD1 == siop) { - hal_lld_peripheral_unreset(RESETS_ALLREG_UART1); + rp_peripheral_unreset(RESETS_ALLREG_UART1); nvicEnableVector(RP_UART1_IRQ_NUMBER, RP_IRQ_UART1_PRIORITY); } #endif @@ -225,13 +226,13 @@ void sio_lld_stop(SIODriver *siop) { #if RP_SIO_USE_UART0 == TRUE else if (&SIOD0 == siop) { nvicDisableVector(RP_UART0_IRQ_NUMBER); - hal_lld_peripheral_reset(RESETS_ALLREG_UART0); + rp_peripheral_reset(RESETS_ALLREG_UART0); } #endif #if RP_SIO_USE_UART1 == TRUE else if (&SIOD1 == siop) { nvicDisableVector(RP_UART1_IRQ_NUMBER); - hal_lld_peripheral_reset(RESETS_ALLREG_UART1); + rp_peripheral_reset(RESETS_ALLREG_UART1); } #endif else { @@ -541,6 +542,9 @@ void sio_lld_serve_interrupt(SIODriver *siop) { /* Idle RX event.*/ if ((mis & UART_UARTMIS_RTMIS) != 0U) { + /* Explicitly clear RTRIS to prevent race on reentry */ + u->UARTICR = UART_UARTICR_RTIC; + /* Called once then the interrupt source is disabled.*/ imsc &= ~UART_UARTIMSC_RTIM; diff --git a/os/hal/ports/RP/LLD/USBv1/driver.mk b/os/hal/ports/RP/LLD/USBv1/driver.mk new file mode 100644 index 0000000000..15b995e24d --- /dev/null +++ b/os/hal/ports/RP/LLD/USBv1/driver.mk @@ -0,0 +1,9 @@ +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_USB TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/RP/LLD/USBv1/hal_usb_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/RP/LLD/USBv1/hal_usb_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/RP/LLD/USBv1 diff --git a/os/hal/ports/RP/LLD/USBv1/hal_usb_lld.c b/os/hal/ports/RP/LLD/USBv1/hal_usb_lld.c new file mode 100644 index 0000000000..752e125b45 --- /dev/null +++ b/os/hal/ports/RP/LLD/USBv1/hal_usb_lld.c @@ -0,0 +1,911 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file hal_usb_lld.c + * @brief RP USB subsystem low level driver source. + * @note This driver is based on the RP2040 USB LLD originally created by + * @hanya and @xyzz wth significant improvements by @KarlK90. It has + * been updated for the RP2350 and to fix a few defects and errata. + * + * @addtogroup USB + * @{ + */ + +#include + +#include "hal.h" + +#if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/** + * @brief Get endpoint control register. + */ +#define EP_CTRL(ep) (USB_DPSRAM->EPCTRL[ep - 1]) +/** + * @brief Get buffer control register for endpoint. + */ +#define BUF_CTRL(ep) (USB_DPSRAM->BUFCTRL[ep]) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief USB1 driver identifier. + */ +#if (RP_USB_USE_USB1 == TRUE) || defined(__DOXYGEN__) +USBDriver USBD1; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief EP0 state. + * @note Both IN and OUT states are needed separately for control transfers + * where SETUP, DATA, and STATUS phases use different directions. + */ +static struct { + /** + * @brief IN EP0 state. + */ + USBInEndpointState in; + /** + * @brief OUT EP0 state. + */ + USBOutEndpointState out; +} ep0_state; + +/** + * @brief EP0 initialization structure. + */ +static const USBEndpointConfig ep0config = { + .ep_mode = USB_EP_MODE_TYPE_CTRL, + .setup_cb = _usb_ep0setup, + .in_cb = _usb_ep0in, + .out_cb = _usb_ep0out, + .in_maxsize = 0x40U, + .out_maxsize = 0x40U, + .in_state = &ep0_state.in, + .out_state = &ep0_state.out +}; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +#if defined(__ARM_ARCH_8M_MAIN__) || defined(__riscv) +/** + * @brief Copy memory using byte accesses. + * @note On RP2350 USB DPRAM requires strict alignment. + */ +static inline void usb_dpram_memcpy(void *dst, const void *src, size_t n) { + volatile uint8_t *d = (volatile uint8_t *)dst; + const volatile uint8_t *s = (const volatile uint8_t *)src; + while (n-- > 0) { + *d++ = *s++; + } +} +#else +/** + * @brief Copy memory using memcpy + * @note On RP2040 USB DPRAM is normal memory. + */ +#define usb_dpram_memcpy(dst, src, n) memcpy(dst, src, n) +#endif + +/** + * @brief Buffer mode for isochronous in buffer control register. + */ +static uint16_t usb_isochronous_buffer_mode(uint16_t size) { + switch (size) { + case 128: + return 0; + case 256: + return 1; + case 512: + return 2; + case 1024: + return 3; + default: + return 0; + } +} + +/** + * @brief Calculate isochronous buffer size in valid step. + * @details Valid buffer size is one of 128, 256, 512 or 1024. + */ +static uint16_t usb_isochronous_buffer_size(uint16_t max_size) { + uint16_t size; + + /* Double buffer offset must be one of 128, 256, 512 or 1024. */ + size = ((max_size - 1) / 128 + 1) * 128; + if (size == 384) { + size = 512; + } else if (size == 640 || size == 768 || size > 1024) { + size = 1024; + } + return size; +} + +/** + * @brief Calculate next offset for buffer data, 64 bytes aligned. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] size buffer size to allocate + * @param[in] is_double true if double-buffered (allocates size * 2) + * @return offset into DATA region for the buffer + */ +static uint16_t usb_buffer_next_offset(USBDriver *usbp, uint16_t size, bool is_double) { + uint16_t offset; + uint16_t alloc; + + offset = usbp->noffset; + alloc = is_double ? (uint16_t)(size * 2U) : size; + + osalDbgAssert((uint32_t)offset + alloc <= USB_DPRAM_DATA_SIZE, + "USB DPRAM buffer overflow"); + + usbp->noffset += alloc; + + return offset; +} + +/** + * @brief Reset endpoint 0. + */ +static void reset_ep0(USBDriver *usbp) { + usbp->epc[0]->out_state->next_pid = 1U; + usbp->epc[0]->in_state->next_pid = 1U; +} + +/** + * @brief Prepare buffer for receiving data. + */ +static uint32_t usb_prepare_out_ep_buffer(USBDriver *usbp, usbep_t ep, uint8_t buffer_index) { + uint32_t buf_ctrl = 0; + const USBEndpointConfig *epcp = usbp->epc[ep]; + USBOutEndpointState *oesp = usbp->epc[ep]->out_state; + + /* PID */ + buf_ctrl |= oesp->next_pid ? USB_BUFFER_BUFFER0_DATA_PID : 0; + oesp->next_pid ^= 1U; + + uint16_t buf_len = oesp->rxsize < epcp->out_maxsize ? oesp->rxsize : epcp->out_maxsize; + buf_ctrl |= USB_BUFFER_BUFFER0_AVAILABLE | buf_len; + buf_ctrl &= ~USB_BUFFER_BUFFER0_FULL; + + if (oesp->rxcnt + buf_len >= oesp->rxsize) { + /* Last buffer */ + buf_ctrl |= USB_BUFFER_BUFFER0_LAST; + } + + if (buffer_index) { + buf_ctrl = buf_ctrl << 16; + } + + return buf_ctrl; +} + +/** + * @brief Prepare for receiving data from host. + */ +static void usb_prepare_out_ep(USBDriver *usbp, usbep_t ep) { + uint32_t buf_ctrl; + uint32_t ep_ctrl; + + if (ep == 0) { + ep_ctrl = USB->SIECTRL; + } else { + ep_ctrl = EP_CTRL(ep).OUT; + } + + /* Fill first buffer */ + buf_ctrl = usb_prepare_out_ep_buffer(usbp, ep, 0); + + /* To avoid short packet, we use single buffered here. */ + /* Single buffered */ + ep_ctrl &= ~(USB_EP_BUFFER_DOUBLE | USB_EP_BUFFER_IRQ_DOUBLE_EN); + ep_ctrl |= USB_EP_BUFFER_IRQ_EN; + + if (ep == 0) { + USB->SIECTRL = ep_ctrl; + } else { + EP_CTRL(ep).OUT = ep_ctrl; + } + + BUF_CTRL(ep).OUT = buf_ctrl; + __DSB(); +} + +/** + * @brief Prepare buffer for sending data. + */ +static uint32_t usb_prepare_in_ep_buffer(USBDriver *usbp, usbep_t ep, uint8_t buffer_index) { + uint8_t *buff; + uint16_t buf_len; + uint32_t buf_ctrl = 0; + const USBEndpointConfig *epcp = usbp->epc[ep]; + USBInEndpointState *iesp = usbp->epc[ep]->in_state; + + /* txsize - txlast gives size of data to be sent but not yet in the buffer */ + buf_len = epcp->in_maxsize < iesp->txsize - iesp->txlast ? + epcp->in_maxsize : iesp->txsize - iesp->txlast; + + iesp->txlast += buf_len; + + /* Host only? */ + if (iesp->txsize <= iesp->txlast) { + /* Last buffer */ + buf_ctrl |= USB_BUFFER_BUFFER0_LAST; + } + + /* PID */ + buf_ctrl |= iesp->next_pid ? USB_BUFFER_BUFFER0_DATA_PID : 0; + iesp->next_pid ^= 1U; + + /* Copy data into hardware buffer */ + buff = (uint8_t*)iesp->hw_buf + (buffer_index == 0 ? 0 : iesp->buf_size); + usb_dpram_memcpy((void *)buff, (void *)iesp->txbuf, buf_len); + iesp->txbuf += buf_len; + + buf_ctrl |= USB_BUFFER_BUFFER0_FULL | + USB_BUFFER_BUFFER0_AVAILABLE | + buf_len; + + if (buffer_index) { + buf_ctrl = buf_ctrl << 16; + } + + return buf_ctrl; +} + +/** + * @brief Prepare endpoint for sending data. + */ +static void usb_prepare_in_ep(USBDriver *usbp, usbep_t ep) { + uint32_t buf_ctrl; + uint32_t ep_ctrl; + USBInEndpointState *iesp = usbp->epc[ep]->in_state; + + if (ep == 0) { + ep_ctrl = USB->SIECTRL; + } else { + ep_ctrl = EP_CTRL(ep).IN; + } + + /* Fill first buffer */ + buf_ctrl = usb_prepare_in_ep_buffer(usbp, ep, 0); + + /* Second buffer if required */ + /* iesp->txsize - iesp->txlast gives size even not in buffer */ + if (iesp->txsize - iesp->txlast > 0) { + buf_ctrl |= usb_prepare_in_ep_buffer(usbp, ep, 1); + } + + if (buf_ctrl & USB_BUFFER_BUFFER1_AVAILABLE) { + /* Double buffered */ + ep_ctrl &= ~USB_EP_BUFFER_IRQ_EN; + ep_ctrl |= USB_EP_BUFFER_DOUBLE | USB_EP_BUFFER_IRQ_DOUBLE_EN; + } else { + /* Single buffered */ + ep_ctrl &= ~(USB_EP_BUFFER_DOUBLE | USB_EP_BUFFER_IRQ_DOUBLE_EN); + ep_ctrl |= USB_EP_BUFFER_IRQ_EN; + } + + if (ep == 0) { + USB->SIECTRL = ep_ctrl; + } else { + EP_CTRL(ep).IN = ep_ctrl; + } + + BUF_CTRL(ep).IN = buf_ctrl; + __DSB(); +} + +/** + * @brief Work on an endpoint after transfer. + */ +static void usb_serve_endpoint(USBDriver *usbp, usbep_t ep, bool is_in) { + const USBEndpointConfig *epcp = usbp->epc[ep]; + USBOutEndpointState *oesp; + USBInEndpointState *iesp; + uint16_t n; + + if (is_in) { + /* IN endpoint */ + iesp = usbp->epc[ep]->in_state; + + /* txlast is size sent + size of last buffer */ + iesp->txcnt = iesp->txlast; + n = iesp->txsize - iesp->txcnt; + if (n > 0) { + /* Transfer not completed, there are more packets to send. */ + usb_prepare_in_ep(usbp, ep); + } else { + /* Transfer complete */ + _usb_isr_invoke_in_cb(usbp, ep); + } + } else { + /* OUT endpoint */ + oesp = usbp->epc[ep]->out_state; + + /* Length received */ + n = BUF_CTRL(ep).OUT & USB_BUFFER_BUFFER0_TRANS_LENGTH_Msk; + + /* Copy received data into user buffer */ + usb_dpram_memcpy((void *)oesp->rxbuf, (void *)oesp->hw_buf, n); + oesp->rxbuf += n; + oesp->rxcnt += n; + oesp->rxsize -= n; + + oesp->rxpkts -= 1; + + /* Short packet or all packets have been received. */ + if (oesp->rxpkts == 0 || n < epcp->out_maxsize) { + /* Transfer complete */ + _usb_isr_invoke_out_cb(usbp, ep); + } else { + /* Receive remained data */ + usb_prepare_out_ep(usbp, ep); + } + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers and threads. */ +/*===========================================================================*/ + +#if RP_USB_USE_USB1 || defined(__DOXYGEN__) + +/** + * @brief USB interrupt service routine. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +static void usb_lld_serve_interrupt(USBDriver *usbp) { + uint32_t ints; + + ints = USB->INTS; + + /* Endpoint events handling. */ + if (ints & USB_INTS_BUFF_STATUS) { + uint32_t buf_status = USB->BUFSTATUS; + uint32_t bit = 1U; + for (uint8_t i = 0; buf_status && i < 32; i++) { + if (buf_status & bit) { + /* Clear flag. */ + USB->CLR.BUFSTATUS = bit; + /* Finish on the endpoint or transfer remained data. */ + usb_serve_endpoint(usbp, i >> 1U, (i & 1U) == 0); + + buf_status &= ~bit; + } + bit <<= 1U; + } + } + + /* Bus reset must be handled before SETUP_REQ: when both are pending, + * processing SETUP first queues a response that _usb_reset() destroys. */ + if (ints & USB_INTS_BUS_RESET) { + USB->CLR.SIESTATUS = USB_SIE_STATUS_BUS_RESET; + + _usb_reset(usbp); + } + + /* USB setup packet handling. */ + if (ints & USB_INTS_SETUP_REQ) { + USB->CLR.SIESTATUS = USB_SIE_STATUS_SETUP_REC; + + reset_ep0(usbp); + + _usb_isr_invoke_setup_cb(usbp, 0); + } + + /* USB bus SUSPEND condition handling.*/ + if (ints & USB_INTS_DEV_SUSPEND) { + USB->CLR.SIESTATUS = USB_SIE_STATUS_SUSPENDED; + + _usb_suspend(usbp); + } + + /* Resume condition handling */ + if (ints & USB_INTS_DEV_RESUME_FROM_HOST) { + USB->CLR.SIESTATUS = USB_SIE_STATUS_RESUME; + + _usb_wakeup(usbp); + } + + /* SOF handling.*/ + if (ints & USB_INTS_DEV_SOF) { + /* SOF interrupt was used to detect resume of the USB bus after issuing a + * remote wake up of the host, therefore we disable it again. */ + if (usbp->config->sof_cb == NULL) { + USB->CLR.INTE = USB_INTE_DEV_SOF; + } + if (usbp->state == USB_SUSPENDED) { + _usb_wakeup(usbp); + } + + _usb_isr_invoke_sof_cb(usbp); + + /* + * Clear SOF flag by reading SOF_RD + * This helps avoid the RP2040-E15 Errata and is harmless on the RP2350. + */ + (void)USB->SOFRD; + } + +#if RP_USB_USE_ERROR_DATA_SEQ_INTR == TRUE + if (ints & USB_INTS_ERROR_DATA_SEQ) { + USB->CLR.SIESTATUS = USB_SIE_STATUS_DATA_SEQ_ERROR; + } +#endif /* RP_USB_USE_ERROR_DATA_SEQ_INTR */ +} + +/** + * @brief USB interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(RP_USBCTRL_IRQ_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + usb_lld_serve_interrupt(&USBD1); + + OSAL_IRQ_EPILOGUE(); +} + +#endif /* RP_USB_USE_USB1 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level USB driver initialization. + * + * @notapi + */ +void usb_lld_init(void) { +#if RP_USB_USE_USB1 == TRUE + /* Driver initialization.*/ + usbObjectInit(&USBD1); + + /* Reset buffer offset. */ + USBD1.noffset = 0; +#endif +} + +/** + * @brief Configures and activates the USB peripheral. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_start(USBDriver *usbp) { +#if RP_USB_USE_USB1 == TRUE + if (&USBD1 == usbp) { + if (usbp->state == USB_STOP) { + + osalDbgAssert(RP_USB_CLK == 48000000U, + "invalid USB clock frequency"); + + /* Reset usb controller. */ + rp_peripheral_reset(RESETS_ALLREG_USBCTRL); + rp_peripheral_unreset(RESETS_ALLREG_USBCTRL); + + /* Clear any previous state in dpram and hw regs */ + memset(USB, 0, sizeof(*USB)); + memset(USB_DPSRAM, 0, sizeof(*USB_DPSRAM)); + + /* Mux the controller to the onboard usb phy */ + USB->MUXING = USB_USB_MUXING_SOFTCON | USB_USB_MUXING_TO_PHY; + +#if RP_USB_FORCE_VBUS_DETECT == TRUE + /* Force VBUS detect so the device thinks it is plugged into a host */ + USB->PWR = USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN | USB_USB_PWR_VBUS_DETECT; +#else +#if RP_USE_EXTERNAL_VBUS_DETECT == TRUE + /* If VBUS is detected by pin without USB VBUS DET pin, + * define usb_vbus_detect which returns true if VBUS is enabled. + */ + if (usb_vbus_detect()) { + USB->PWR = USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN | USB_USB_PWR_VBUS_DETECT; + } +#endif /* RP_USE_EXTERNAL_VBUS_DETECT */ +#endif /* RP_USB_FORCE_VBUS_DETECT */ + + /* Reset procedure enforced on driver start.*/ + usb_lld_reset(usbp); + + /* Enable the USB controller in device mode. */ + USB->MAINCTRL = USB_MAIN_CTRL_CONTROLLER_EN; + + /* Enable an interrupt per EP0 transaction */ + USB->SIECTRL = USB_SIE_CTRL_EP0_INT_1BUF; + + /* Enable interrupts */ + USB->INTE = USB_INTE_SETUP_REQ | + USB_INTE_DEV_RESUME_FROM_HOST | + USB_INTE_DEV_SUSPEND | + USB_INTE_BUS_RESET | + USB_INTE_BUFF_STATUS; + + if (usbp->config->sof_cb != NULL) { + USB->SET.INTE = USB_INTE_DEV_SOF; + } + +#if RP_USB_USE_ERROR_DATA_SEQ_INTR == TRUE + USB->SET.INTE = USB_INTE_ERROR_DATA_SEQ; +#endif /* RP_USB_USE_ERROR_DATA_SEQ_INTR */ + + /* Enable USB interrupt. */ + nvicEnableVector(RP_USBCTRL_IRQ_NUMBER, RP_IRQ_USB0_PRIORITY); + } + } +#endif +} + +/** + * @brief Deactivates the USB peripheral. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_stop(USBDriver *usbp) { +#if RP_USB_USE_USB1 == TRUE + if (&USBD1 == usbp) { + if (usbp->state != USB_STOP) { + /* Disable USB interrupt */ + USB->INTE = 0; + nvicDisableVector(RP_USBCTRL_IRQ_NUMBER); + + /* Disable controller */ + USB->CLR.MAINCTRL = USB_MAIN_CTRL_CONTROLLER_EN; + } + } +#endif +} + +/** + * @brief USB low level reset routine. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_reset(USBDriver *usbp) { + /* EP0 initialization.*/ + usbp->epc[0] = &ep0config; + usb_lld_init_endpoint(usbp, 0U); + + /* Reset device address. */ + USB->DEVADDRCTRL = 0U; + + /* Reset USB memory */ + usbp->noffset = 0U; + + /* Clear all non control endpoint registers */ + for (int ep = 1; ep <= USB_MAX_ENDPOINTS; ep++) { + EP_CTRL(ep).IN = 0U; + BUF_CTRL(ep).IN = 0U; + EP_CTRL(ep).OUT = 0U; + BUF_CTRL(ep).OUT = 0U; + } +} + +/** + * @brief Sets the USB address. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_set_address(USBDriver *usbp) { + /* Set address to hardware here. */ + USB->DEVADDRCTRL = USB_ADDR_ENDP0_ADDRESS_Msk & (usbp->address << USB_ADDR_ENDP0_ADDRESS_Pos); +} + +/** + * @brief Enables an endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) { + uint16_t buf_size; + uint16_t buf_offset; + uint32_t buf_ctrl; + const USBEndpointConfig *epcp = usbp->epc[ep]; + + if (ep == 0) { + epcp->in_state->hw_buf = (uint8_t *)&USB_DPSRAM->EP0BUF0; + epcp->in_state->buf_size = 64; + epcp->in_state->next_pid = 0U; + epcp->out_state->hw_buf = (uint8_t *)&USB_DPSRAM->EP0BUF0; + epcp->out_state->buf_size = 64; + epcp->out_state->next_pid = 0U; + USB->SET.SIECTRL = USB_EP_BUFFER_IRQ_EN; + return; + } + + /* Isochronous endpoints cannot be bidirectional per USB 2.0 specification. */ + if (epcp->ep_mode == USB_EP_MODE_TYPE_ISOC) { + osalDbgAssert((epcp->in_state == NULL) || (epcp->out_state == NULL), + "isochronous EP cannot be IN and OUT"); + } + + if (epcp->in_state) { + buf_ctrl = 0U; + BUF_CTRL(ep).IN = buf_ctrl; + epcp->in_state->next_pid = 0U; + + if (epcp->ep_mode == USB_EP_MODE_TYPE_ISOC) { + buf_size = usb_isochronous_buffer_size(epcp->in_maxsize); + buf_ctrl |= usb_isochronous_buffer_mode(buf_size) << USB_BUFFER_DOUBLE_BUFFER_OFFSET_Pos; + } else { + buf_size = 64; + } + buf_offset = usb_buffer_next_offset(usbp, buf_size, true); + epcp->in_state->hw_buf = (uint8_t *)&USB_DPSRAM->DATA[buf_offset]; + epcp->in_state->buf_size = buf_size; + + EP_CTRL(ep).IN = USB_EP_EN | (epcp->ep_mode << USB_EP_TYPE_Pos) | ((uint8_t *)epcp->in_state->hw_buf - (uint8_t *)USB_DPSRAM); + BUF_CTRL(ep).IN = buf_ctrl; + } + + if (epcp->out_state) { + buf_ctrl = 0U; + BUF_CTRL(ep).OUT = buf_ctrl; + epcp->out_state->next_pid = 0U; + + if (epcp->ep_mode == USB_EP_MODE_TYPE_ISOC) { + buf_size = usb_isochronous_buffer_size(epcp->out_maxsize); + buf_ctrl |= usb_isochronous_buffer_mode(buf_size) << USB_BUFFER_DOUBLE_BUFFER_OFFSET_Pos; + } else { + buf_size = 64; + } + buf_offset = usb_buffer_next_offset(usbp, buf_size, false); + epcp->out_state->hw_buf = (uint8_t *)&USB_DPSRAM->DATA[buf_offset]; + epcp->out_state->buf_size = buf_size; + + EP_CTRL(ep).OUT = USB_EP_EN | (epcp->ep_mode << USB_EP_TYPE_Pos) | ((uint8_t *)epcp->out_state->hw_buf - (uint8_t *)USB_DPSRAM); + BUF_CTRL(ep).OUT = buf_ctrl; + } +} + +/** + * @brief Disables all the active endpoints except the endpoint zero. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_disable_endpoints(USBDriver *usbp) { + + /* Reset the packet memory allocator. */ + usbp->noffset = 0U; + + for (uint8_t ep = 1; ep <= USB_MAX_ENDPOINTS; ep++) { + EP_CTRL(ep).IN &= ~USB_EP_EN; + EP_CTRL(ep).OUT &= ~USB_EP_EN; + } +} + +/** + * @brief Returns the status of an OUT endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return The endpoint status. + * @retval EP_STATUS_DISABLED The endpoint is not active. + * @retval EP_STATUS_STALLED The endpoint is stalled. + * @retval EP_STATUS_ACTIVE The endpoint is active. + * + * @notapi + */ +usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep) { + (void)usbp; + + if (BUF_CTRL(ep).OUT & USB_BUFFER_STALL) { + return EP_STATUS_STALLED; + } + /* EP0 is always active once USB is started - it has no EPCTRL entry. */ + if (ep == 0U) { + return EP_STATUS_ACTIVE; + } + if (EP_CTRL(ep).OUT & USB_EP_EN) { + return EP_STATUS_ACTIVE; + } + return EP_STATUS_DISABLED; +} + +/** + * @brief Returns the status of an IN endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return The endpoint status. + * @retval EP_STATUS_DISABLED The endpoint is not active. + * @retval EP_STATUS_STALLED The endpoint is stalled. + * @retval EP_STATUS_ACTIVE The endpoint is active. + * + * @notapi + */ +usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) { + (void)usbp; + + if (BUF_CTRL(ep).IN & USB_BUFFER_STALL) { + return EP_STATUS_STALLED; + } + /* EP0 is always active once USB is started - it has no EPCTRL entry. */ + if (ep == 0U) { + return EP_STATUS_ACTIVE; + } + if (EP_CTRL(ep).IN & USB_EP_EN) { + return EP_STATUS_ACTIVE; + } + return EP_STATUS_DISABLED; +} + +/** + * @brief Reads a setup packet from the dedicated packet buffer. + * @details This function must be invoked in the context of the @p setup_cb + * callback in order to read the received setup packet. + * @pre In order to use this function the endpoint must have been + * initialized as a control endpoint. + * @post The endpoint is ready to accept another packet. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[out] buf buffer where to copy the packet data + * + * @notapi + */ +void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) { + (void)usbp; + (void)ep; + /* Copy data from hardware buffer to user buffer */ + usb_dpram_memcpy(buf, (void *)USB_DPSRAM->SETUPPACKET, 8); +} + +/** + * @brief Starts a receive operation on an OUT endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_start_out(USBDriver *usbp, usbep_t ep) { + USBOutEndpointState *oesp = usbp->epc[ep]->out_state; + + /* Transfer initialization.*/ + if (oesp->rxsize == 0U) { + /* Special case for zero sized packets.*/ + oesp->rxpkts = 1U; + } else { + oesp->rxpkts = (uint16_t)((oesp->rxsize + usbp->epc[ep]->out_maxsize - 1) / + usbp->epc[ep]->out_maxsize); + } + + usb_prepare_out_ep(usbp, ep); +} + +/** + * @brief Starts a transmit operation on an IN endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_start_in(USBDriver *usbp, usbep_t ep) { + USBInEndpointState *iesp = usbp->epc[ep]->in_state; + iesp->txlast = 0; + + /* Prepare IN endpoint. */ + usb_prepare_in_ep(usbp, ep); +} + +/** + * @brief Brings an OUT endpoint in the stalled state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) { + (void)usbp; + + if (ep == 0) { + USB->SET.EPSTALLARM = USB_EP_STALL_ARM_EP0_OUT; + } + BUF_CTRL(ep).OUT |= USB_BUFFER_STALL; + __DSB(); +} + +/** + * @brief Brings an IN endpoint in the stalled state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_stall_in(USBDriver *usbp, usbep_t ep) { + (void)usbp; + + if (ep == 0) { + USB->SET.EPSTALLARM = USB_EP_STALL_ARM_EP0_IN; + } + BUF_CTRL(ep).IN |= USB_BUFFER_STALL; + __DSB(); +} + +/** + * @brief Brings an OUT endpoint in the active state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_clear_out(USBDriver *usbp, usbep_t ep) { + if (ep > 0) { + BUF_CTRL(ep).OUT &= ~USB_BUFFER_STALL; + } + usbp->epc[ep]->out_state->next_pid = 0U; +} + +/** + * @brief Brings an IN endpoint in the active state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) { + if (ep > 0) { + BUF_CTRL(ep).IN &= ~USB_BUFFER_STALL; + } + usbp->epc[ep]->in_state->next_pid = 0U; +} + +#endif /* HAL_USE_USB == TRUE */ + +/** @} */ diff --git a/os/hal/ports/RP/LLD/USBv1/hal_usb_lld.h b/os/hal/ports/RP/LLD/USBv1/hal_usb_lld.h new file mode 100644 index 0000000000..17b80ea451 --- /dev/null +++ b/os/hal/ports/RP/LLD/USBv1/hal_usb_lld.h @@ -0,0 +1,495 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file hal_usb_lld.h + * @brief RP USB subsystem low level driver header. + * @note This driver is based on the RP2040 USB LLD originally created by + * @hanya and @xyzz with significant improvements by @KarlK90. It has + * been updated for the RP2350 and to fix a few defects and errata. + * + * @addtogroup USB + * @{ + */ + +#ifndef HAL_USB_LLD_H +#define HAL_USB_LLD_H + +#if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__) + +#include "rp_usb.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Maximum endpoint address. + */ +#define USB_MAX_ENDPOINTS 15 + +/** + * @brief Status stage handling method. + */ +#define USB_EP0_STATUS_STAGE USB_EP0_STATUS_STAGE_SW + +/** + * @brief The address can be changed immediately upon packet reception. + */ +#define USB_SET_ADDRESS_MODE USB_LATE_SET_ADDRESS + +/** + * @brief Method for set address acknowledge. + */ +#define USB_SET_ADDRESS_ACK_HANDLING USB_SET_ADDRESS_ACK_SW + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name RP configuration options + * @{ + */ +/** + * @brief USB driver enable switch. + * @details If set to @p TRUE the support for USB1 is included. + * @note The default is @p FALSE. + */ +#if !defined(RP_USB_USE_USB1) || defined(__DOXYGEN__) +#define RP_USB_USE_USB1 FALSE +#endif + +/** + * @brief Force to set VBUS detect register. + * @details If you want to use non VBUS DETECT pin for this purpose, + set this flag to FALSE and define bool usb_vbus_detect(void) function + which returns true to force VBUS DETECT. + See RP_USE_EXTERNAL_VBUS_DETECT. + */ +#if !defined(RP_USB_FORCE_VBUS_DETECT) || defined(__DOXYGEN__) +#define RP_USB_FORCE_VBUS_DETECT TRUE +#endif +/** @} */ + +/** + * @brief Use custom VBUS detection. + @details If RP_USB_FORCE_VBUS_DETECT is FALSE, this flag can be TRUE + to detect custom function to detect VBUS. + */ +#if !defined(RP_USE_EXTERNAL_VBUS_DETECT) || defined(__DOXYGEN__) +#define RP_USE_EXTERNAL_VBUS_DETECT FALSE +#endif + +#if RP_USE_EXTERNAL_VBUS_DETECT == TRUE +extern bool usb_vbus_detect(void); +#endif + +/** + * @brief Enables the error data sequence interrupt. + * @details This flag is useful if you develop low level driver. + */ +#if !defined(RP_USB_USE_ERROR_DATA_SEQ_INTR) || defined(__DOXYGEN__) +#define RP_USB_USE_ERROR_DATA_SEQ_INTR FALSE +#endif + +#if !defined(RP_IRQ_USB0_PRIORITY) +#error "RP_IRQ_USB0_PRIORITY not defined in mcuconf.h" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of an IN endpoint state structure. + */ +typedef struct { + /** + * @brief Requested transmit transfer size. + */ + size_t txsize; + /** + * @brief Transmitted bytes so far. + */ + size_t txcnt; + /** + * @brief Pointer to the transmission linear buffer. + */ + const uint8_t *txbuf; +#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__) + /** + * @brief Waiting thread. + */ + thread_reference_t thread; +#endif + /* End of the mandatory fields.*/ + /** + * @brief Size of the last transmitted packet. + */ + size_t txlast; + /** + * @brief Data PID used by next transfer. + */ + uint8_t next_pid; + /** + * @brief Buffer in the hardware. + */ + uint8_t *hw_buf; + /** + * @brief Buffer size. + */ + uint16_t buf_size; +} USBInEndpointState; + +/** + * @brief Type of an OUT endpoint state structure. + */ +typedef struct { + /** + * @brief Requested receive transfer size. + */ + size_t rxsize; + /** + * @brief Received bytes so far. + */ + size_t rxcnt; + /** + * @brief Pointer to the receive linear buffer. + */ + uint8_t *rxbuf; +#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__) + /** + * @brief Waiting thread. + */ + thread_reference_t thread; +#endif + /* End of the mandatory fields.*/ + /** + * @brief Number of packets to receive. + */ + uint16_t rxpkts; + /** + * @brief Data PID used by next transfer. + */ + uint8_t next_pid; + /** + * @brief Buffer in the hardware. + */ + uint8_t *hw_buf; + /** + * @brief Buffer size. + */ + uint16_t buf_size; +} USBOutEndpointState; + +/** + * @brief Type of an USB endpoint configuration structure. + * @note Platform specific restrictions may apply to endpoints. + */ +typedef struct { + /** + * @brief Type and mode of the endpoint. + */ + uint32_t ep_mode; + /** + * @brief Setup packet notification callback. + * @details This callback is invoked when a setup packet has been + * received. + * @post The application must immediately call @p usbReadPacket() in + * order to access the received packet. + * @note This field is only valid for @p USB_EP_MODE_TYPE_CTRL + * endpoints, it should be set to @p NULL for other endpoint + * types. + */ + usbepcallback_t setup_cb; + /** + * @brief IN endpoint notification callback. + * @details This field must be set to @p NULL if the IN endpoint is not + * used. + */ + usbepcallback_t in_cb; + /** + * @brief OUT endpoint notification callback. + * @details This field must be set to @p NULL if the OUT endpoint is not + * used. + */ + usbepcallback_t out_cb; + /** + * @brief IN endpoint maximum packet size. + * @details This field must be set to zero if the IN endpoint is not + * used. + */ + uint16_t in_maxsize; + /** + * @brief OUT endpoint maximum packet size. + * @details This field must be set to zero if the OUT endpoint is not + * used. + */ + uint16_t out_maxsize; + /** + * @brief @p USBEndpointState associated to the IN endpoint. + * @details This structure maintains the state of the IN endpoint. + */ + USBInEndpointState *in_state; + /** + * @brief @p USBEndpointState associated to the OUT endpoint. + * @details This structure maintains the state of the OUT endpoint. + */ + USBOutEndpointState *out_state; + /* End of the mandatory fields.*/ +} USBEndpointConfig; + +/** + * @brief Type of an USB driver configuration structure. + */ +typedef struct { + /** + * @brief USB events callback. + * @details This callback is invoked when an USB driver event is registered. + */ + usbeventcb_t event_cb; + /** + * @brief Device GET_DESCRIPTOR request callback. + * @note This callback is mandatory and cannot be set to @p NULL. + */ + usbgetdescriptor_t get_descriptor_cb; +#if (USB_USE_EP0_THREAD == FALSE) || defined(__DOXYGEN__) + /** + * @brief Requests hook callback. + * @details This hook allows to be notified of standard requests or to + * handle non standard requests. + */ + usbreqhandler_t requests_hook_cb; +#endif + /** + * @brief Start Of Frame callback. + */ + usbcallback_t sof_cb; + /* End of the mandatory fields.*/ +} USBConfig; + +/** + * @brief Structure representing an USB driver. + */ +struct USBDriver { + /** + * @brief Driver state. + */ + usbstate_t state; + /** + * @brief Current configuration data. + */ + const USBConfig *config; + /** + * @brief Bit map of the transmitting IN endpoints. + */ + uint16_t transmitting; + /** + * @brief Bit map of the receiving OUT endpoints. + */ + uint16_t receiving; + /** + * @brief Active endpoints configurations. + */ + const USBEndpointConfig *epc[USB_MAX_ENDPOINTS + 1]; + /** + * @brief Fields available to user, it can be used to associate an + * application-defined handler to an IN endpoint. + * @note The base index is one, the endpoint zero does not have a + * reserved element in this array. + */ + void *in_params[USB_MAX_ENDPOINTS]; + /** + * @brief Fields available to user, it can be used to associate an + * application-defined handler to an OUT endpoint. + * @note The base index is one, the endpoint zero does not have a + * reserved element in this array. + */ + void *out_params[USB_MAX_ENDPOINTS]; + /** + * @brief Endpoint 0 state. + */ + usbep0state_t ep0state; + /** + * @brief Next position in the buffer to be transferred through endpoint 0. + */ + uint8_t *ep0next; + /** + * @brief Number of bytes yet to be transferred through endpoint 0. + */ + size_t ep0n; + /** + * @brief Endpoint 0 end transaction callback. + */ + usbcallback_t ep0endcb; +#if (USB_USE_EP0_THREAD == TRUE) || defined(__DOXYGEN__) + /** + * @brief Waiting thread for EP0 operations. + */ + thread_reference_t ep0thread; + /** + * @brief Current EP0 sequence number. + */ + uint8_t ep0seq; + /** + * @brief EP0 sequence number owned by the worker thread. + */ + uint8_t ep0rseq; + /** + * @brief Pending setup notification for the worker thread. + */ + uint8_t ep0setup; + /** + * @brief Pending reset notification for the worker thread. + */ + uint8_t ep0reset; +#endif + /** + * @brief Setup packet buffer. + */ + uint8_t setup[8]; + /** + * @brief Current USB device status. + */ + uint16_t status; + /** + * @brief Assigned USB address. + */ + uint8_t address; + /** + * @brief Current USB device configuration. + */ + uint8_t configuration; + /** + * @brief State of the driver when a suspend happened. + */ + usbstate_t saved_state; +#if defined(USB_DRIVER_EXT_FIELDS) + USB_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Next offset of buffer. + */ + uint16_t noffset; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Returns the current frame number. + * + * @param[in] usbp pointer to the @p USBDriver object + * @return The current frame number. + * + * @notapi + */ +#define usb_lld_get_frame_number(usbp) \ + (USB->SOFRD & USB_SOF_RD_COUNT_Msk) + +/** + * @brief Returns the exact size of a receive transaction. + * @details The received size can be different from the size specified in + * @p usbStartReceiveI() because the last packet could have a size + * different from the expected one. + * @pre The OUT endpoint must have been configured in transaction mode + * in order to use this function. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return Received data size. + * + * @notapi + */ +#define usb_lld_get_transaction_size(usbp, ep) \ + ((usbp)->epc[ep]->out_state->rxcnt) + +/** + * @brief Connects the USB device. + * + * @api + */ +#if !defined(usb_lld_connect_bus) +#define usb_lld_connect_bus(usbp) \ + do { \ + USB->SET.SIECTRL = USB_SIE_CTRL_PULLUP_EN; \ + } while (false) +#endif + +/** + * @brief Disconnect the USB device. + * + * @api + */ +#if !defined(usb_lld_disconnect_bus) +#define usb_lld_disconnect_bus(usbp) \ + do { \ + USB->CLR.SIECTRL = USB_SIE_CTRL_PULLUP_EN; \ + } while (false) +#endif + +/** + * @brief Start of host wake-up procedure. + * + * @notapi + */ +#define usb_lld_wakeup_host(usbp) \ + do { \ + /* remote wakeup doesn't trigger the wakeup interrupt, therefore \ + * we use the SOF interrupt to detect resume of the bus. */ \ + USB->SET.INTE = USB_INTE_DEV_SOF; \ + USB->SET.SIECTRL = USB_SIE_CTRL_RESUME; \ + } while (false) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if (RP_USB_USE_USB1 == TRUE) && !defined(__DOXYGEN__) +extern USBDriver USBD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void usb_lld_init(void); + void usb_lld_start(USBDriver *usbp); + void usb_lld_stop(USBDriver *usbp); + void usb_lld_reset(USBDriver *usbp); + void usb_lld_set_address(USBDriver *usbp); + void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep); + void usb_lld_disable_endpoints(USBDriver *usbp); + usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep); + usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep); + void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf); + void usb_lld_start_out(USBDriver *usbp, usbep_t ep); + void usb_lld_start_in(USBDriver *usbp, usbep_t ep); + void usb_lld_stall_out(USBDriver *usbp, usbep_t ep); + void usb_lld_stall_in(USBDriver *usbp, usbep_t ep); + void usb_lld_clear_out(USBDriver *usbp, usbep_t ep); + void usb_lld_clear_in(USBDriver *usbp, usbep_t ep); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_USB == TRUE */ + +#endif /* HAL_USB_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/RP/LLD/USBv1/rp_usb.h b/os/hal/ports/RP/LLD/USBv1/rp_usb.h new file mode 100644 index 0000000000..42a346c38a --- /dev/null +++ b/os/hal/ports/RP/LLD/USBv1/rp_usb.h @@ -0,0 +1,366 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file USBv1/rp_usb.h + * @brief RP2040/RP2350 USB registers layout header. + * @note This file provides unified USB register definitions for both + * RP2040 and RP2350 platforms. + * + * @addtogroup USB + * @{ + */ + +#ifndef RP_USB_H +#define RP_USB_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* DPRAM memory structure. */ +/*===========================================================================*/ + +/** + * @brief USB DPRAM base address. + */ +#define USB_DPRAM_BASE 0x50100000U + +/** + * @brief USB DPRAM size in bytes. + */ +#define USB_DPRAM_SIZE 4096U + +/** + * @brief USB DPRAM data buffer region size. + * @details This is the size of the DATA region used for EP1-15 buffers. + * EP0 has separate dedicated buffers (EP0BUF0/EP0BUF1) and does + * not consume space from this region. + */ +#define USB_DPRAM_DATA_SIZE 3712U + +/** + * @brief USB DPRAM structure for device mode. + */ +typedef struct { + __IO uint8_t SETUPPACKET[8]; /**< @brief Setup packet buffer. */ + struct { + __IO uint32_t IN; /**< @brief IN endpoint control. */ + __IO uint32_t OUT; /**< @brief OUT endpoint control. */ + } EPCTRL[15]; /**< @brief EP1-15 control regs. */ + struct { + __IO uint32_t IN; /**< @brief IN buffer control. */ + __IO uint32_t OUT; /**< @brief OUT buffer control. */ + } BUFCTRL[16]; /**< @brief EP0-15 buffer control. */ + __IO uint8_t EP0BUF0[64]; /**< @brief EP0 buffer A. */ + __IO uint8_t EP0BUF1[64]; /**< @brief EP0 buffer B. */ + __IO uint8_t DATA[USB_DPRAM_DATA_SIZE]; /**< @brief EP1-15 data buffers. */ +} USB_DPRAM_TypeDef; + +/** + * @brief USB DPRAM pointer. + */ +#define USB_DPSRAM ((USB_DPRAM_TypeDef *)USB_DPRAM_BASE) + +/*===========================================================================*/ +/* Address and endpoint register bits. */ +/*===========================================================================*/ + +#define USB_ADDR_ENDP0_ENDPOINT_Pos 16U +#define USB_ADDR_ENDP0_ENDPOINT_Msk (0xFU << USB_ADDR_ENDP0_ENDPOINT_Pos) +#define USB_ADDR_ENDP0_ADDRESS_Pos 0U +#define USB_ADDR_ENDP0_ADDRESS_Msk (0x7FU << USB_ADDR_ENDP0_ADDRESS_Pos) + +#define USB_ADDR_ENDP_INTEP_PREAMBLE (1U << 26) +#define USB_ADDR_ENDP_INTEP_DIR (1U << 25) +#define USB_ADDR_ENDP_ENDPOINT_Pos 16U +#define USB_ADDR_ENDP_ENDPOINT_Msk (0xFU << USB_ADDR_ENDP_ENDPOINT_Pos) +#define USB_ADDR_ENDP_ADDRESS_Pos 0U +#define USB_ADDR_ENDP_ADDRESS_Msk (0x7FU << USB_ADDR_ENDP_ADDRESS_Pos) + +/*===========================================================================*/ +/* Main control register bits. */ +/*===========================================================================*/ + +#define USB_MAIN_CTRL_SIM_TIMING (1U << 31) +#define USB_MAIN_CTRL_HOST_NDEVICE (1U << 1) +#define USB_MAIN_CTRL_CONTROLLER_EN (1U << 0) + +/*===========================================================================*/ +/* SOF register bits. */ +/*===========================================================================*/ + +#define USB_SOF_WR_COUNT_Pos 0U +#define USB_SOF_WR_COUNT_Msk (0x3FFU << USB_SOF_WR_COUNT_Pos) + +#define USB_SOF_RD_COUNT_Pos 0U +#define USB_SOF_RD_COUNT_Msk (0x3FFU << USB_SOF_RD_COUNT_Pos) + +/*===========================================================================*/ +/* SIE control register bits. */ +/*===========================================================================*/ + +#define USB_SIE_CTRL_EP0_INT_STALL (1U << 31) +#define USB_SIE_CTRL_EP0_DOUBLE_BUF (1U << 30) +#define USB_SIE_CTRL_EP0_INT_1BUF (1U << 29) +#define USB_SIE_CTRL_EP0_INT_2BUF (1U << 28) +#define USB_SIE_CTRL_EP0_INT_NAK (1U << 27) +#define USB_SIE_CTRL_DIRECT_EN (1U << 26) +#define USB_SIE_CTRL_DIRECT_DP (1U << 25) +#define USB_SIE_CTRL_DIRECT_DM (1U << 24) +#define USB_SIE_CTRL_TRANSCEIVER_PD (1U << 18) +#define USB_SIE_CTRL_RPU_OPT (1U << 17) +#define USB_SIE_CTRL_PULLUP_EN (1U << 16) +#define USB_SIE_CTRL_PULLDOWN_EN (1U << 15) +#define USB_SIE_CTRL_RESET_BUS (1U << 13) +#define USB_SIE_CTRL_RESUME (1U << 12) +#define USB_SIE_CTRL_VBUS_EN (1U << 11) +#define USB_SIE_CTRL_KEEP_ALIVE_EN (1U << 10) +#define USB_SIE_CTRL_SOF_EN (1U << 9) +#define USB_SIE_CTRL_SOF_SYNC (1U << 8) +#define USB_SIE_CTRL_PREAMBLE_EN (1U << 6) +#define USB_SIE_CTRL_STOP_TRANS (1U << 4) +#define USB_SIE_CTRL_RECEIVE_DATA (1U << 3) +#define USB_SIE_CTRL_SEND_DATA (1U << 2) +#define USB_SIE_CTRL_SEND_SETUP (1U << 1) +#define USB_SIE_CTRL_START_TRANS (1U << 0) + +/*===========================================================================*/ +/* SIE status register bits. */ +/*===========================================================================*/ + +#define USB_SIE_STATUS_DATA_SEQ_ERROR (1U << 31) +#define USB_SIE_STATUS_ACK_REC (1U << 30) +#define USB_SIE_STATUS_STALL_REC (1U << 29) +#define USB_SIE_STATUS_NAK_REC (1U << 28) +#define USB_SIE_STATUS_RX_TIMEOUT (1U << 27) +#define USB_SIE_STATUS_RX_OVERFLOW (1U << 26) +#define USB_SIE_STATUS_BIT_STUFF_ERROR (1U << 25) +#define USB_SIE_STATUS_CRC_ERROR (1U << 24) +#define USB_SIE_STATUS_BUS_RESET (1U << 19) +#define USB_SIE_STATUS_TRANS_COMPLETE (1U << 18) +#define USB_SIE_STATUS_SETUP_REC (1U << 17) +#define USB_SIE_STATUS_CONNECTED (1U << 16) +#define USB_SIE_STATUS_RESUME (1U << 11) +#define USB_SIE_STATUS_VBUS_OVER_CURR (1U << 10) +#define USB_SIE_STATUS_SPEED_Pos 8U +#define USB_SIE_STATUS_SPEED_Msk (0x3U << USB_SIE_STATUS_SPEED_Pos) +#define USB_SIE_STATUS_SUSPENDED (1U << 4) +#define USB_SIE_STATUS_LINE_STATE_Pos 2U +#define USB_SIE_STATUS_LINE_STATE_Msk (0x3U << USB_SIE_STATUS_LINE_STATE_Pos) +#define USB_SIE_STATUS_VBUS_DETECTED (1U << 0) + +/*===========================================================================*/ +/* Buffer status register bits. */ +/*===========================================================================*/ + +#define USB_BUFF_STATUS_EP15_OUT (1U << 31) +#define USB_BUFF_STATUS_EP15_IN (1U << 30) +#define USB_BUFF_STATUS_EP14_OUT (1U << 29) +#define USB_BUFF_STATUS_EP14_IN (1U << 28) +#define USB_BUFF_STATUS_EP13_OUT (1U << 27) +#define USB_BUFF_STATUS_EP13_IN (1U << 26) +#define USB_BUFF_STATUS_EP12_OUT (1U << 25) +#define USB_BUFF_STATUS_EP12_IN (1U << 24) +#define USB_BUFF_STATUS_EP11_OUT (1U << 23) +#define USB_BUFF_STATUS_EP11_IN (1U << 22) +#define USB_BUFF_STATUS_EP10_OUT (1U << 21) +#define USB_BUFF_STATUS_EP10_IN (1U << 20) +#define USB_BUFF_STATUS_EP9_OUT (1U << 19) +#define USB_BUFF_STATUS_EP9_IN (1U << 18) +#define USB_BUFF_STATUS_EP8_OUT (1U << 17) +#define USB_BUFF_STATUS_EP8_IN (1U << 16) +#define USB_BUFF_STATUS_EP7_OUT (1U << 15) +#define USB_BUFF_STATUS_EP7_IN (1U << 14) +#define USB_BUFF_STATUS_EP6_OUT (1U << 13) +#define USB_BUFF_STATUS_EP6_IN (1U << 12) +#define USB_BUFF_STATUS_EP5_OUT (1U << 11) +#define USB_BUFF_STATUS_EP5_IN (1U << 10) +#define USB_BUFF_STATUS_EP4_OUT (1U << 9) +#define USB_BUFF_STATUS_EP4_IN (1U << 8) +#define USB_BUFF_STATUS_EP3_OUT (1U << 7) +#define USB_BUFF_STATUS_EP3_IN (1U << 6) +#define USB_BUFF_STATUS_EP2_OUT (1U << 5) +#define USB_BUFF_STATUS_EP2_IN (1U << 4) +#define USB_BUFF_STATUS_EP1_OUT (1U << 3) +#define USB_BUFF_STATUS_EP1_IN (1U << 2) +#define USB_BUFF_STATUS_EP0_OUT (1U << 1) +#define USB_BUFF_STATUS_EP0_IN (1U << 0) + +/*===========================================================================*/ +/* EP stall arm register bits. */ +/*===========================================================================*/ + +#define USB_EP_STALL_ARM_EP0_OUT (1U << 1) +#define USB_EP_STALL_ARM_EP0_IN (1U << 0) + +/*===========================================================================*/ +/* NAK poll register bits. */ +/*===========================================================================*/ + +#define USB_NAK_POLL_DELAY_FS_Pos 16U +#define USB_NAK_POLL_DELAY_FS_Msk (0x3FFU << USB_NAK_POLL_DELAY_FS_Pos) +#define USB_NAK_POLL_DELAY_LS_Pos 0U +#define USB_NAK_POLL_DELAY_LS_Msk (0x3FFU << USB_NAK_POLL_DELAY_LS_Pos) + +/*===========================================================================*/ +/* USB muxing register bits. */ +/*===========================================================================*/ + +#define USB_USB_MUXING_SOFTCON (1U << 3) +#define USB_USB_MUXING_TO_DIGITAL_PAD (1U << 2) +#define USB_USB_MUXING_TO_EXTPHY (1U << 1) +#define USB_USB_MUXING_TO_PHY (1U << 0) + +/*===========================================================================*/ +/* USB power register bits. */ +/*===========================================================================*/ + +#define USB_USB_PWR_OVERCURR_DETECT_EN (1U << 5) +#define USB_USB_PWR_OVERCURR_DETECT (1U << 4) +#define USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN (1U << 3) +#define USB_USB_PWR_VBUS_DETECT (1U << 2) +#define USB_USB_PWR_VBUS_EN_OVERRIDE_EN (1U << 1) +#define USB_USB_PWR_VBUS_EN (1U << 0) + +/*===========================================================================*/ +/* Interrupt register bits. */ +/*===========================================================================*/ + +#define USB_INTR_EP_STALL_NAK (1U << 19) +#define USB_INTR_ABORT_DONE (1U << 18) +#define USB_INTR_DEV_SOF (1U << 17) +#define USB_INTR_SETUP_REQ (1U << 16) +#define USB_INTR_DEV_RESUME_FROM_HOST (1U << 15) +#define USB_INTR_DEV_SUSPEND (1U << 14) +#define USB_INTR_DEV_CONN_DIS (1U << 13) +#define USB_INTR_BUS_RESET (1U << 12) +#define USB_INTR_VBUS_DETECT (1U << 11) +#define USB_INTR_STALL (1U << 10) +#define USB_INTR_ERROR_CRC (1U << 9) +#define USB_INTR_ERROR_BIT_STUFF (1U << 8) +#define USB_INTR_ERROR_RX_OVERFLOW (1U << 7) +#define USB_INTR_ERROR_RX_TIMEOUT (1U << 6) +#define USB_INTR_ERROR_DATA_SEQ (1U << 5) +#define USB_INTR_BUFF_STATUS (1U << 4) +#define USB_INTR_TRANS_COMPLETE (1U << 3) +#define USB_INTR_HOST_SOF (1U << 2) +#define USB_INTR_HOST_RESUME (1U << 1) +#define USB_INTR_HOST_CONN_DIS (1U << 0) + +#define USB_INTE_EP_STALL_NAK (1U << 19) +#define USB_INTE_ABORT_DONE (1U << 18) +#define USB_INTE_DEV_SOF (1U << 17) +#define USB_INTE_SETUP_REQ (1U << 16) +#define USB_INTE_DEV_RESUME_FROM_HOST (1U << 15) +#define USB_INTE_DEV_SUSPEND (1U << 14) +#define USB_INTE_DEV_CONN_DIS (1U << 13) +#define USB_INTE_BUS_RESET (1U << 12) +#define USB_INTE_VBUS_DETECT (1U << 11) +#define USB_INTE_STALL (1U << 10) +#define USB_INTE_ERROR_CRC (1U << 9) +#define USB_INTE_ERROR_BIT_STUFF (1U << 8) +#define USB_INTE_ERROR_RX_OVERFLOW (1U << 7) +#define USB_INTE_ERROR_RX_TIMEOUT (1U << 6) +#define USB_INTE_ERROR_DATA_SEQ (1U << 5) +#define USB_INTE_BUFF_STATUS (1U << 4) +#define USB_INTE_TRANS_COMPLETE (1U << 3) +#define USB_INTE_HOST_SOF (1U << 2) +#define USB_INTE_HOST_RESUME (1U << 1) +#define USB_INTE_HOST_CONN_DIS (1U << 0) + +#define USB_INTF_EP_STALL_NAK (1U << 19) +#define USB_INTF_ABORT_DONE (1U << 18) +#define USB_INTF_DEV_SOF (1U << 17) +#define USB_INTF_SETUP_REQ (1U << 16) +#define USB_INTF_DEV_RESUME_FROM_HOST (1U << 15) +#define USB_INTF_DEV_SUSPEND (1U << 14) +#define USB_INTF_DEV_CONN_DIS (1U << 13) +#define USB_INTF_BUS_RESET (1U << 12) +#define USB_INTF_VBUS_DETECT (1U << 11) +#define USB_INTF_STALL (1U << 10) +#define USB_INTF_ERROR_CRC (1U << 9) +#define USB_INTF_ERROR_BIT_STUFF (1U << 8) +#define USB_INTF_ERROR_RX_OVERFLOW (1U << 7) +#define USB_INTF_ERROR_RX_TIMEOUT (1U << 6) +#define USB_INTF_ERROR_DATA_SEQ (1U << 5) +#define USB_INTF_BUFF_STATUS (1U << 4) +#define USB_INTF_TRANS_COMPLETE (1U << 3) +#define USB_INTF_HOST_SOF (1U << 2) +#define USB_INTF_HOST_RESUME (1U << 1) +#define USB_INTF_HOST_CONN_DIS (1U << 0) + +#define USB_INTS_EP_STALL_NAK (1U << 19) +#define USB_INTS_ABORT_DONE (1U << 18) +#define USB_INTS_DEV_SOF (1U << 17) +#define USB_INTS_SETUP_REQ (1U << 16) +#define USB_INTS_DEV_RESUME_FROM_HOST (1U << 15) +#define USB_INTS_DEV_SUSPEND (1U << 14) +#define USB_INTS_DEV_CONN_DIS (1U << 13) +#define USB_INTS_BUS_RESET (1U << 12) +#define USB_INTS_VBUS_DETECT (1U << 11) +#define USB_INTS_STALL (1U << 10) +#define USB_INTS_ERROR_CRC (1U << 9) +#define USB_INTS_ERROR_BIT_STUFF (1U << 8) +#define USB_INTS_ERROR_RX_OVERFLOW (1U << 7) +#define USB_INTS_ERROR_RX_TIMEOUT (1U << 6) +#define USB_INTS_ERROR_DATA_SEQ (1U << 5) +#define USB_INTS_BUFF_STATUS (1U << 4) +#define USB_INTS_TRANS_COMPLETE (1U << 3) +#define USB_INTS_HOST_SOF (1U << 2) +#define USB_INTS_HOST_RESUME (1U << 1) +#define USB_INTS_HOST_CONN_DIS (1U << 0) + +/*===========================================================================*/ +/* Endpoint control register bits (DPRAM). */ +/*===========================================================================*/ + +#define USB_EP_EN (1U << 31) +#define USB_EP_BUFFER_DOUBLE (1U << 30) +#define USB_EP_BUFFER_IRQ_EN (1U << 29) +#define USB_EP_BUFFER_IRQ_DOUBLE_EN (1U << 28) +#define USB_EP_TYPE_Pos 26U +#define USB_EP_TYPE_Msk (0x3U << USB_EP_TYPE_Pos) +#define USB_EP_IRQ_STALL (1U << 17) +#define USB_EP_IRQ_NAK (1U << 16) +#define USB_EP_ADDR_OFFSET_Pos 0U +#define USB_EP_ADDR_OFFSET_Msk (0xFFFFU << USB_EP_ADDR_OFFSET_Pos) + +/*===========================================================================*/ +/* Buffer control register bits (DPRAM). */ +/*===========================================================================*/ + +#define USB_BUFFER_BUFFER1_FULL (1U << 31) +#define USB_BUFFER_BUFFER1_LAST (1U << 30) +#define USB_BUFFER_BUFFER1_DATA_PID (1U << 29) +#define USB_BUFFER_DOUBLE_BUFFER_OFFSET_Pos 27U +#define USB_BUFFER_DOUBLE_BUFFER_OFFSET_Msk (0x3U << USB_BUFFER_DOUBLE_BUFFER_OFFSET_Pos) +#define USB_BUFFER_BUFFER1_AVAILABLE (1U << 26) +#define USB_BUFFER_BUFFER1_TRANS_LENGTH_Pos 16U +#define USB_BUFFER_BUFFER1_TRANS_LENGTH_Msk (0x3FFU << USB_BUFFER_BUFFER1_TRANS_LENGTH_Pos) +#define USB_BUFFER_BUFFER0_FULL (1U << 15) +#define USB_BUFFER_BUFFER0_LAST (1U << 14) +#define USB_BUFFER_BUFFER0_DATA_PID (1U << 13) +#define USB_BUFFER_RESET_BUFFER (1U << 12) +#define USB_BUFFER_STALL (1U << 11) +#define USB_BUFFER_BUFFER0_AVAILABLE (1U << 10) +#define USB_BUFFER_BUFFER0_TRANS_LENGTH_Pos 0U +#define USB_BUFFER_BUFFER0_TRANS_LENGTH_Msk (0x3FFU << USB_BUFFER_BUFFER0_TRANS_LENGTH_Pos) + +#endif /* RP_USB_H */ + +/** @} */ diff --git a/os/hal/ports/RP/LLD/WDGv1/hal_wdg_lld.c b/os/hal/ports/RP/LLD/WDGv1/hal_wdg_lld.c index c39cea7737..c3fe0c2675 100644 --- a/os/hal/ports/RP/LLD/WDGv1/hal_wdg_lld.c +++ b/os/hal/ports/RP/LLD/WDGv1/hal_wdg_lld.c @@ -16,7 +16,7 @@ /** * @file hal_wdg_lld.c - * @brief RP2040 watchdog low level driver source. + * @brief RP watchdog low level driver source. * * @addtogroup WDG * @{ @@ -51,11 +51,14 @@ WDGDriver WDGD1; */ static void set_wdg_counter(WDGDriver *wdgp) { - /* Set the time. */ + /* Set the time in milliseconds, default to 50ms */ uint32_t time = wdgp->config->rlr; + time = ((time == 0U) ? 50U : time) * 1000U; - /* Due to a silicon bug (see errata RP2040-E1) WDG decrements at each edge.*/ - time = ((time == 0U) ? 50 : time) * 2 * 1000; +#if RP_WDG_HAS_E1_ERRATA + /* RP2040-E1 Errata: Watchdog counter decrements on both clock edges. */ + time = time * 2U; +#endif /* Set ceiling if greater than count capability.*/ time = (time > WATCHDOG_CTRL_TIME) ? WATCHDOG_CTRL_TIME : time; @@ -101,22 +104,8 @@ void wdg_lld_start(WDGDriver *wdgp) { /* Set the watchdog counter.*/ set_wdg_counter(wdgp); - /* When watchdog fires reset everything except ROSC and XOS.*/ - PSM->WDSEL = PSM_ANY_PROC1 | - PSM_ANY_PROC0 | - PSM_ANY_SIO | - PSM_ANY_VREG_AND_CHIP_RESET | - PSM_ANY_XIP | - PSM_ANY_SRAM5 | - PSM_ANY_SRAM4 | - PSM_ANY_SRAM3 | - PSM_ANY_SRAM2 | - PSM_ANY_SRAM1 | - PSM_ANY_SRAM0 | - PSM_ANY_ROM | - PSM_ANY_BUSFABRIC | - PSM_ANY_RESETS | - PSM_ANY_CLOCKS; + /* When watchdog fires, reset everything except ROSC and XOSC. */ + PSM->WDSEL = RP_PSM_WDSEL_ALL_BITS & ~(PSM_ANY_ROSC | PSM_ANY_XOSC); /* Set control bits and enable WDG.*/ wdgp->wdg->CTRL = WATCHDOG_CTRL_PAUSE_DBG0 | diff --git a/os/hal/ports/RP/LLD/WDGv1/hal_wdg_lld.h b/os/hal/ports/RP/LLD/WDGv1/hal_wdg_lld.h index 6f7a730060..576dbc04d1 100644 --- a/os/hal/ports/RP/LLD/WDGv1/hal_wdg_lld.h +++ b/os/hal/ports/RP/LLD/WDGv1/hal_wdg_lld.h @@ -62,7 +62,7 @@ typedef struct { * @brief Configuration of the WATCHDOG LOAD register. * @details See the RP2040 data sheet for details. */ - uint32_t rlr; + uint32_t rlr; } WDGConfig; /** diff --git a/os/hal/ports/RP/RP2040/hal_efl_lld.c b/os/hal/ports/RP/RP2040/hal_efl_lld.c new file mode 100644 index 0000000000..60827064bc --- /dev/null +++ b/os/hal/ports/RP/RP2040/hal_efl_lld.c @@ -0,0 +1,601 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2040/hal_efl_lld.c + * @brief RP2040 Embedded Flash subsystem low level driver source. + * @note This is a self-contained flash driver that directly manipulates + * the SSI peripheral. + * + * @addtogroup HAL_EFL + * @{ + */ + +#include + +#include "hal.h" +#include "rp_efl_lld.h" + +#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/** + * @brief Macro to place functions in RAM. + */ +#define RAMFUNC __attribute__((noinline, section(".ramtext"))) + +/** + * @name SSI configuration for direct SPI mode + * @{ + */ +#define SSI_BAUDR_DEFAULT 6U +/** @} */ + +/** + * @name IO QSPI register indexes + * @{ + */ +#define RP2040_IO_QSPI_SS_INDEX 1U +/** @} */ + +/** + * @name Standard JEDEC Flash commands + * @{ + */ +#define FLASHCMD_WRITE_ENABLE 0x06U +#define FLASHCMD_READ_STATUS 0x05U +#define FLASHCMD_PAGE_PROGRAM 0x02U +#define FLASHCMD_SECTOR_ERASE 0x20U +#define FLASHCMD_BLOCK_ERASE_32K 0x52U +#define FLASHCMD_BLOCK_ERASE_64K 0xD8U +#define FLASHCMD_READ_UNIQUE_ID 0x4BU +/** @} */ + +/** + * @name Flash status register bits + * @{ + */ +#define FLASH_STATUS_BUSY (1U << 0) +#define FLASH_STATUS_WEL (1U << 1) +/** @} */ + +/** + * @name Page alignment + * @{ + */ +#define RP_FLASH_PAGE_MASK (RP_FLASH_PAGE_SIZE - 1U) +/** @} */ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief EFL1 driver identifier. + * @note EFLD1.ssi is statically initialized to allow use before hal init + */ +EFlashDriver EFLD1 = { + .ssi = XIP_SSI +}; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief Copy of boot2 stage2 image for XIP restoration after flash ops. + * @details 252 bytes (full 256-byte image minus 4-byte CRC). + * See RP2040 Datasheet 2.8.1.3 and rp_flash_enter_xip(). + */ +CC_ALIGN_DATA(4) static uint8_t rp_boot2[252]; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Force chip select high or low + * @note This function MUST be in RAM. + * + * @param[in] eflp pointer to the EFlashDriver object + * @param[in] high true for CS high (deassert), false for CS low (assert) + */ +RAMFUNC static void rp_flash_cs_force(EFlashDriver *eflp, bool high) { + (void)eflp; + uint32_t val = high ? IOQSPI_CTRL_OUTOVER_HIGH : IOQSPI_CTRL_OUTOVER_LOW; + + IO_QSPI->GPIO[RP2040_IO_QSPI_SS_INDEX].CTRL = + (IO_QSPI->GPIO[RP2040_IO_QSPI_SS_INDEX].CTRL & + ~IOQSPI_CTRL_OUTOVER_Msk) | + IOQSPI_CTRL_OUTOVER(val); + + /* Read back to ensure write is flushed */ + (void)IO_QSPI->GPIO[RP2040_IO_QSPI_SS_INDEX].CTRL; +} + +/** + * @brief Transfer data to/from flash + * @note This function MUST be in RAM. + * + * @param[in] eflp pointer to the EFlashDriver object + * @param[in] tx transmit buffer (NULL to send zeros) + * @param[out] rx receive buffer (NULL to discard) + * @param[in] count number of bytes to transfer + */ +RAMFUNC static void rp_flash_put_get(EFlashDriver *eflp, const uint8_t *tx, + uint8_t *rx, size_t count) { + SSI_TypeDef *ssi = eflp->ssi; + size_t tx_remaining = count; + size_t rx_remaining = count; + const size_t max_in_flight = 14U; /* FIFO is 16 deep so we leave a margin */ + + while ((tx_remaining > 0U) || (rx_remaining > 0U)) { + size_t in_flight = (count - tx_remaining) - (count - rx_remaining); + + while ((tx_remaining > 0U) && (in_flight < max_in_flight)) { + uint8_t data = (tx != NULL) ? *tx++ : 0U; + ssi->DR[0] = data; + tx_remaining--; + in_flight++; + } + + while ((rx_remaining > 0U) && (ssi->RXFLR > 0U)) { + uint8_t data = (uint8_t)ssi->DR[0]; + if (rx != NULL) { + *rx++ = data; + } + rx_remaining--; + } + } +} + +/** + * @brief Execute a flash command. + * @note This function MUST be in RAM. + * + * @param[in] eflp pointer to the EFlashDriver object + * @param[in] cmd command byte + * @param[in] tx transmit data after command (NULL if none) + * @param[out] rx receive buffer (NULL to discard) + * @param[in] count number of bytes to transfer after command + */ +RAMFUNC static void rp_flash_do_cmd(EFlashDriver *eflp, uint8_t cmd, + const uint8_t *tx, uint8_t *rx, + size_t count) { + /* Assert CS. */ + rp_flash_cs_force(eflp, false); + + /* Send command byte. */ + eflp->ssi->DR[0] = cmd; + while (eflp->ssi->RXFLR == 0U) { + } + (void)eflp->ssi->DR[0]; + + /* Transfer remaining data. */ + if (count > 0U) { + rp_flash_put_get(eflp, tx, rx, count); + } + + /* Deassert CS. */ + rp_flash_cs_force(eflp, true); +} + +/** + * @brief Wait for flash to become ready. + * @note This function MUST be in RAM. + * + * @param[in] eflp pointer to the EFlashDriver object + */ +RAMFUNC static void rp_flash_wait_ready(EFlashDriver *eflp) { + uint8_t status; + + do { + rp_flash_do_cmd(eflp, FLASHCMD_READ_STATUS, NULL, &status, 1U); + } while ((status & FLASH_STATUS_BUSY) != 0U); +} + +/** + * @brief Send write enable command. + * @note This function MUST be in RAM. + * + * @param[in] eflp pointer to the EFlashDriver object + */ +RAMFUNC static void rp_flash_write_enable(EFlashDriver *eflp) { + + rp_flash_do_cmd(eflp, FLASHCMD_WRITE_ENABLE, NULL, NULL, 0U); +} + +/** + * @brief Flush XIP cache + * @note This function MUST be in RAM. + */ +RAMFUNC static void rp_flash_flush_cache(void) { + uint32_t ctrl; + + /* Write to flush register to trigger cache flush. */ + XIP_CTRL->FLUSH = 1U; + + /* Read back blocks until flush is complete. */ + (void)XIP_CTRL->FLUSH; + + /* Re-enable the cache while preserving the remaining policy bits. */ + ctrl = XIP_CTRL->CTRL; + ctrl |= XIP_CTRL_CTRL_EN; + XIP_CTRL->CTRL = ctrl; +} + +/** + * @brief Reset QSPI pads and mux to connect SSI to internal flash. + * @note This function MUST be in RAM. + */ +RAMFUNC static void rp_flash_connect_internal(void) { + uint32_t bits = RESETS_ALLREG_IO_QSPI | RESETS_ALLREG_PADS_QSPI; + unsigned i; + + /* Hard-reset IO_QSPI and PADS_QSPI. */ + RESETS->SET.RESET = bits; + RESETS->CLR.RESET = bits; + while ((RESETS->RESET_DONE & bits) != bits) { + } + + /* Mux all QSPI GPIOs to function 0 (XIP). */ + for (i = 0U; i < 6U; i++) { + IO_QSPI->GPIO[i].CTRL = 0U; + } +} + +/** + * @brief Exit XIP mode and configure for direct access. + * @note This function MUST be in RAM. + * @note This follows a similar pattern to the ROM's flash_exit_xip() + * + * @param[in] eflp pointer to the EFlashDriver object + */ +RAMFUNC static void rp_flash_exit_xip(EFlashDriver *eflp) { + SSI_TypeDef *ssi = eflp->ssi; + PADS_QSPI_TypeDef *pads_qspi = PADS_QSPI; + uint32_t padctrl_save; + uint32_t padctrl_tmp; + unsigned i; + volatile unsigned delay; + + /* Wait for any pending work.*/ + while ((ssi->SR & SSI_SR_BUSY) != 0U) { + } + + /* Default non XIP SPI configuration */ + ssi->SSIENR = 0U; + (void)ssi->SR; /* Clear sticky errors (clear-on-read). */ + (void)ssi->ICR; + ssi->BAUDR = SSI_BAUDR_DEFAULT; + ssi->CTRLR0 = SSI_CTRLR0_SPI_FRF_STD | + SSI_CTRLR0_TMOD_TX_AND_RX | + SSI_CTRLR0_DFS_32(7U); + ssi->SER = 1U; + ssi->SSIENR = 1U; + + /* + * Exit continuous read mode sequence: + * 1. CS high 32 clocks with IO pulled down + * 2. CS low 32 clocks with IO pulled up + * 3. Send 0xFF, 0xFF + */ + + /* Save pad control and configure with output disabled.*/ + padctrl_save = pads_qspi->GPIO_QSPI_SD0; + padctrl_tmp = (padctrl_save & ~(PADS_QSPI_OD | PADS_QSPI_PUE | + PADS_QSPI_PDE)) + | PADS_QSPI_OD | PADS_QSPI_PDE; + + /* 1. CS high */ + rp_flash_cs_force(eflp, true); + + pads_qspi->GPIO_QSPI_SD0 = padctrl_tmp; + pads_qspi->GPIO_QSPI_SD1 = padctrl_tmp; + pads_qspi->GPIO_QSPI_SD2 = padctrl_tmp; + pads_qspi->GPIO_QSPI_SD3 = padctrl_tmp; + + /* Delay of ~6000 cycles */ + for (delay = 0U; delay < 2048U; delay++) { + } + + /* Send 4 bytes / 32 clocks */ + for (i = 0U; i < 4U; i++) { + ssi->DR[0] = 0U; + while (ssi->RXFLR == 0U) { + } + (void)ssi->DR[0]; + } + + padctrl_tmp = (padctrl_tmp & ~PADS_QSPI_PDE) | PADS_QSPI_PUE; + + /* 2. CS low */ + rp_flash_cs_force(eflp, false); + + pads_qspi->GPIO_QSPI_SD0 = padctrl_tmp; + pads_qspi->GPIO_QSPI_SD1 = padctrl_tmp; + pads_qspi->GPIO_QSPI_SD2 = padctrl_tmp; + pads_qspi->GPIO_QSPI_SD3 = padctrl_tmp; + + /* Delay of ~6000 cycles */ + for (delay = 0U; delay < 2048U; delay++) { + } + + /* Send 4 bytes / 32 clocks */ + for (i = 0U; i < 4U; i++) { + ssi->DR[0] = 0U; + while (ssi->RXFLR == 0U) { + } + (void)ssi->DR[0]; + } + + /* Restore pad controls. */ + pads_qspi->GPIO_QSPI_SD0 = padctrl_save; + pads_qspi->GPIO_QSPI_SD1 = padctrl_save; + padctrl_save = (padctrl_save & ~PADS_QSPI_PDE) | PADS_QSPI_PUE; + pads_qspi->GPIO_QSPI_SD2 = padctrl_save; + pads_qspi->GPIO_QSPI_SD3 = padctrl_save; + + /* 3. Send 0xFF, 0xFF */ + rp_flash_cs_force(eflp, false); + ssi->DR[0] = 0xFFU; + ssi->DR[0] = 0xFFU; + while (ssi->RXFLR < 2U) { + } + (void)ssi->DR[0]; + (void)ssi->DR[0]; + rp_flash_cs_force(eflp, true); +} + +/** + * @brief Enter XIP mode by re-executing the boot2 stage2 code. + * @note This function MUST be in RAM. + * @details The SSI SPI_CTRLR0 register XIP_CMD field (bits 31:24) does + * not read back on RP2040 — it always returns zero regardless + * of the value written. Because the boot2 stores the QSPI + * continuous-read mode byte (typically 0xA0) in this field, + * a register save/restore approach cannot recover the original + * XIP configuration. + * + * Instead, the boot2 stage2 code is copied to RAM during + * driver init and re-executed here. This is the same technique used + * by the Pico SDK (flash_enable_xip_via_boot2 in + * hardware_flash/flash.c). + * + * Per RP2040 Datasheet section 2.8.1.3, the 256-byte boot2 + * image is position-independent Thumb code — the bootrom + * copies it to SRAM and calls it during the boot sequence. + * All standard boot2 variants (w25q080, generic_03h, + * at25sf128a, is25lp080) follow the Pico SDK convention of + * checking the saved LR on exit: if non-zero (called from + * user code) the boot2 returns to the caller; if zero (called + * from the bootrom) it jumps to the application entry point. + * Custom boot2 implementations that do not follow this + * convention will not work with this driver. + * + * @param[in] eflp pointer to the EFlashDriver object + */ +RAMFUNC static void rp_flash_enter_xip(EFlashDriver *eflp) { + (void)eflp; + + /* Reset CS control to normal. */ + IO_QSPI->GPIO[RP2040_IO_QSPI_SS_INDEX].CTRL = + (IO_QSPI->GPIO[RP2040_IO_QSPI_SS_INDEX].CTRL & + ~IOQSPI_CTRL_OUTOVER_Msk) | + IOQSPI_CTRL_OUTOVER(IOQSPI_CTRL_OUTOVER_NORMAL); + + /* Re-execute the boot2 to fully restore the SSI configuration + * including QSPI mode, continuous read, and baud rate. The OR + * with 1 sets the Thumb bit required by BX on ARMv6-M. */ + ((void (*)(void))((uintptr_t)rp_boot2 | 1U))(); + + rp_flash_flush_cache(); +} + +/** + * @brief Program a page of flash. + * @note This function MUST be in RAM. + * + * @param[in] eflp pointer to the EFlashDriver object + * @param[in] offset flash offset (must be page-aligned or within page) + * @param[in] data data to program + * @param[in] len number of bytes (must not cross page boundary) + */ +RAMFUNC static void rp_flash_program_page(EFlashDriver *eflp, uint32_t offset, + const uint8_t *data, size_t len) { + SSI_TypeDef *ssi = eflp->ssi; + uint8_t addr[3]; + + /* Send write enable. */ + rp_flash_write_enable(eflp); + + /* Prepare 24-bit address (big-endian). */ + addr[0] = (uint8_t)(offset >> 16); + addr[1] = (uint8_t)(offset >> 8); + addr[2] = (uint8_t)offset; + + /* Assert CS. */ + rp_flash_cs_force(eflp, false); + + /* Send page program command. */ + ssi->DR[0] = FLASHCMD_PAGE_PROGRAM; + while (ssi->RXFLR == 0U) { + } + (void)ssi->DR[0]; + + /* Send address. */ + rp_flash_put_get(eflp, addr, NULL, 3U); + + /* Send data. */ + rp_flash_put_get(eflp, data, NULL, len); + + /* Deassert CS. */ + rp_flash_cs_force(eflp, true); + + /* Wait for program to complete. */ + rp_flash_wait_ready(eflp); +} + +/** + * @brief Send an erase command to flash. + * @note This function MUST be in RAM. + * + * @param[in] eflp pointer to the EFlashDriver object + * @param[in] cmd JEDEC erase command byte + * @param[in] offset flash offset (must be aligned to erase unit) + */ +RAMFUNC static void rp_flash_erase_cmd(EFlashDriver *eflp, uint8_t cmd, + uint32_t offset) { + uint8_t addr[3]; + + /* Send write enable. */ + rp_flash_write_enable(eflp); + + /* Prepare 24-bit address (big-endian). */ + addr[0] = (uint8_t)(offset >> 16); + addr[1] = (uint8_t)(offset >> 8); + addr[2] = (uint8_t)offset; + + /* Send erase command with address. */ + rp_flash_do_cmd(eflp, cmd, addr, NULL, 3U); +} + +/** + * @brief Complete erase operation (runs entirely in RAM). + * @note This function MUST be in RAM. It handles the entire sequence + * from exit XIP to enter XIP so no flash code executes while + * XIP is disabled. + * + * @param[in] eflp pointer to the EFlashDriver object + * @param[in] cmd JEDEC erase command byte + * @param[in] offset flash offset (must be aligned to erase unit) + */ +RAMFUNC static void rp_flash_erase_full(EFlashDriver *eflp, uint8_t cmd, + uint32_t offset) { + + /* Connect SSI to flash and exit XIP mode. */ + rp_flash_connect_internal(); + rp_flash_exit_xip(eflp); + + /* Send erase command. */ + rp_flash_erase_cmd(eflp, cmd, offset); + + /* Wait for erase to complete. */ + rp_flash_wait_ready(eflp); + + /* Re-enter XIP mode. */ + rp_flash_enter_xip(eflp); +} + +/** + * @brief Single-page program operation that runs entirely in RAM. + * @note This function MUST be in RAM. It handles the entire sequence + * from exit XIP to enter XIP so no flash code executes while + * XIP is disabled. + * + * @param[in] eflp pointer to the EFlashDriver object + * @param[in] offset flash offset (must not cross page boundary) + * @param[in] data pointer to data in RAM + * @param[in] len number of bytes to program + */ +RAMFUNC static void rp_flash_program_page_full(EFlashDriver *eflp, + uint32_t offset, + const uint8_t *data, + size_t len) { + + /* Connect SSI to flash and exit XIP mode. */ + rp_flash_connect_internal(); + rp_flash_exit_xip(eflp); + + /* Program the page. */ + rp_flash_program_page(eflp, offset, data, len); + + /* Re-enter XIP mode. */ + rp_flash_enter_xip(eflp); +} + +/** + * @brief Read flash unique ID (runs entirely in RAM). + * @note This function MUST be in RAM. It handles the entire sequence + * from exit XIP to enter XIP so no flash code executes while + * XIP is disabled. + * + * @param[in] eflp pointer to the EFlashDriver object + * @param[out] rx receive buffer + * @param[in] count number of bytes to transfer after command + */ +RAMFUNC static void rp_flash_read_uid_full(EFlashDriver *eflp, + uint8_t *rx, size_t count) { + + /* Connect SSI to flash and exit XIP mode. */ + rp_flash_connect_internal(); + rp_flash_exit_xip(eflp); + + /* Send read unique ID command. */ + rp_flash_do_cmd(eflp, FLASHCMD_READ_UNIQUE_ID, NULL, rx, count); + + /* Re-enter XIP mode. */ + rp_flash_enter_xip(eflp); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +void rp_efl_lld_init(void) { + + /* Copy the boot2 stage2 image (first 252 bytes of flash, excluding + * the 4-byte CRC) into a RAM buffer while XIP is still functional. + * After flash program/erase operations, rp_flash_enter_xip() + * re-executes this copy to restore the SSI/XIP configuration. + * See RP2040 Datasheet section 2.8.1.3 for boot2 requirements. */ + memcpy(rp_boot2, (const void *)RP_FLASH_BASE, sizeof(rp_boot2)); +} + +void rp_efl_lld_start(EFlashDriver *eflp) { + + (void)eflp; + + /* Nothing to do - boot2 is copied during init. */ +} + +void rp_efl_lld_program_page_full(EFlashDriver *eflp, + uint32_t offset, + const uint8_t *data, + size_t len) { + rp_flash_program_page_full(eflp, offset, data, len); +} + +void rp_efl_lld_erase_full(EFlashDriver *eflp, uint8_t cmd, uint32_t offset) { + rp_flash_erase_full(eflp, cmd, offset); +} + +void rp_efl_lld_read_uid_full(EFlashDriver *eflp, + uint8_t *rx, + size_t count) { + rp_flash_read_uid_full(eflp, rx, count); +} + +#endif /* HAL_USE_EFL == TRUE */ + +/** @} */ diff --git a/os/hal/ports/RP/RP2040/hal_efl_lld.h b/os/hal/ports/RP/RP2040/hal_efl_lld.h new file mode 100644 index 0000000000..2198406a36 --- /dev/null +++ b/os/hal/ports/RP/RP2040/hal_efl_lld.h @@ -0,0 +1,186 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2040/hal_efl_lld.h + * @brief RP2040 Embedded Flash subsystem low level driver header. + * + * @addtogroup HAL_EFL + * @{ + */ + +#ifndef HAL_EFL_LLD_H +#define HAL_EFL_LLD_H + +#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Flash page size (minimum write unit). + */ +#define RP_FLASH_PAGE_SIZE 256U + +/** + * @brief Flash sector size (minimum erase unit). + */ +#define RP_FLASH_SECTOR_SIZE 4096U + +/** + * @brief Flash sector erase command (JEDEC 0x20). + */ +#define RP_FLASH_CMD_SECTOR_ERASE 0x20U + +/** + * @brief Flash 32KB block erase command (JEDEC 0x52). + */ +#define RP_FLASH_CMD_BLOCK_ERASE_32K 0x52U + +/** + * @brief Flash 64KB block erase command (JEDEC 0xD8). + */ +#define RP_FLASH_CMD_BLOCK_ERASE_64K 0xD8U + +/** + * @brief Flash 32KB block size. + */ +#define RP_FLASH_BLOCK_32K_SIZE (32U * 1024U) + +/** + * @brief Flash 64KB block size. + */ +#define RP_FLASH_BLOCK_64K_SIZE 65536U + +/** + * @brief XIP base address. + */ +#define RP_FLASH_BASE 0x10000000U + +/** + * @brief SSI base address. + */ +#define RP_SSI_BASE 0x18000000U + +/** + * @brief XIP control base address. + */ +#define RP_XIP_CTRL_BASE 0x14000000U + +/** + * @brief Flash unique ID size in bytes. + */ +#define RP_FLASH_UNIQUE_ID_SIZE 8U + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name RP2040 configuration options + * @{ + */ + +/** + * @brief Total flash size in bytes. + * @note Default is 2MB for standard Raspberry Pi Pico. + * Override in mcuconf.h for boards with different flash sizes. + */ +#if !defined(RP_FLASH_SIZE) || defined(__DOXYGEN__) +#define RP_FLASH_SIZE (2U * 1024U * 1024U) +#endif + +/** + * @brief Suggested wait time during erase operations polling. + */ +#if !defined(RP_FLASH_WAIT_TIME_MS) || defined(__DOXYGEN__) +#define RP_FLASH_WAIT_TIME_MS 1U +#endif + +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* Registry checks for robustness. */ +#if !defined(RP_HAS_FLASH) +#error "RP_HAS_FLASH not defined in registry" +#endif + +#if RP_HAS_FLASH != TRUE +#error "RP_HAS_FLASH is not TRUE" +#endif + +/** + * @brief Number of sectors in flash. + */ +#define RP_FLASH_SECTORS_COUNT (RP_FLASH_SIZE / RP_FLASH_SECTOR_SIZE) + +/** + * @brief Number of 64KB blocks in flash. + */ +#define RP_FLASH_BLOCKS_COUNT (RP_FLASH_SIZE / RP_FLASH_BLOCK_64K_SIZE) + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +#include "rp_efl_lld.h" + +/** + * @brief Low level fields of the embedded flash driver structure. + */ +#define efl_lld_driver_fields \ + /* Pointer to SSI registers. */ \ + SSI_TypeDef *ssi; + +/** + * @brief Low level fields of the embedded flash configuration structure. + */ +#define efl_lld_config_fields \ + /* Dummy configuration, it is not needed.*/ \ + uint32_t dummy; + +/*===========================================================================*/ +/* Application hooks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#if !defined(__DOXYGEN__) +extern EFlashDriver EFLD1; +#endif +#include "rp_efl_lld_api.inc" +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_EFL == TRUE */ + +#endif /* HAL_EFL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/RP/RP2040/hal_lld.c b/os/hal/ports/RP/RP2040/hal_lld.c index fe50cdfe6f..02388b9980 100644 --- a/os/hal/ports/RP/RP2040/hal_lld.c +++ b/os/hal/ports/RP/RP2040/hal_lld.c @@ -17,12 +17,16 @@ /** * @file RP2040/hal_lld.c * @brief RP2040 HAL subsystem low level driver source. + * @note The Core 1 launch sequence follows the multicore launch protocol + * documented in RP2040 Datasheet 2.8.2 "Launching Code On + * Processor Core 1". * * @addtogroup HAL * @{ */ #include "hal.h" +#include "rp_clocks.h" /*===========================================================================*/ /* Driver local definitions. */ @@ -36,7 +40,7 @@ * @brief CMSIS system core clock variable. * @note It is declared in system_rp2040.h. */ -uint32_t SystemCoreClock; +uint32_t SystemCoreClock = RP_CLK_SYS_FREQ; /*===========================================================================*/ /* Driver local variables and types. */ @@ -47,7 +51,6 @@ uint32_t SystemCoreClock; /*===========================================================================*/ #if RP_CORE1_START == TRUE -/* Courtesy of Pico-SDK.*/ static void start_core1(void) { extern uint32_t RP_CORE1_STACK_END; extern uint32_t RP_CORE1_VECTORS_TABLE; @@ -58,13 +61,22 @@ static void start_core1(void) { (uint32_t)RP_CORE1_ENTRY_POINT}; unsigned seq; -#if 0 - /* Resetting core1.*/ - PSM_SET->FRCE_OFF = PSM_ANY_PROC1; - while ((PSM->FRCE_OFF & PSM_ANY_PROC1) == 0U) { - } - PSM_CLR->FRCE_OFF = PSM_ANY_PROC1; -#endif + /* Force-reset core1 via PSM before starting the FIFO launch handshake. + * + * If core1 survived a preceding soft reset (e.g. a bootloader that uses + * BX to jump to the application rather than SYSRESETREQ), it may still + * be executing application code from a previous run. In that case the + * ROM FIFO handshake protocol will deadlock: core0 sends the sync + * sequence but core1 is not in the ROM wait-for-launch loop so it never + * echoes back. + * + * PSM FRCE_OFF holds core1 in reset (powered-off state). Clearing it + * releases core1 into the ROM boot-path which immediately enters the + * wait-for-launch loop. The PSM DONE bit falls while the core is held + * off, and rises again once it has been released and is running.*/ + PSM->SET.FRCE_OFF = PSM_ANY_PROC1; /* assert reset to core1 */ + while (PSM->DONE & PSM_ANY_PROC1) {} /* wait until it powers off */ + PSM->CLR.FRCE_OFF = PSM_ANY_PROC1; /* release — core1 enters ROM */ /* Starting core 1.*/ seq = 0; @@ -80,7 +92,7 @@ static void start_core1(void) { response = fifoBlockingRead(); /* Checking response, going forward or back to first step.*/ seq = cmd == response ? seq + 1U : 0U; - } while (seq < count_of(cmd_sequence)); + } while (seq < 6U); } #endif @@ -100,20 +112,27 @@ static void start_core1(void) { void hal_lld_init(void) { #if RP_NO_INIT == FALSE - clocks_init(); - - SystemCoreClock = RP_CORE_CLK; - - hal_lld_peripheral_unreset(RESETS_ALLREG_BUSCTRL); - hal_lld_peripheral_unreset(RESETS_ALLREG_SYSINFO); - hal_lld_peripheral_unreset(RESETS_ALLREG_SYSCFG); + rp_peripheral_unreset(RESETS_ALLREG_BUSCTRL); + rp_peripheral_unreset(RESETS_ALLREG_SYSINFO); + rp_peripheral_unreset(RESETS_ALLREG_SYSCFG); #endif /* RP_NO_INIT */ - /* Common subsystems initialization.*/ + /* NVIC initialization.*/ + nvicInit(); + + /* IRQ subsystem initialization.*/ irqInit(); #if defined(RP_DMA_REQUIRED) dmaInit(); #endif +#if defined(RP_PIO_REQUIRED) + pioInit(); +#endif + + /* Bind the system timer IRQ to this core for tickless mode.*/ +#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING + stBind(); +#endif #if RP_CORE1_START == TRUE start_core1(); diff --git a/os/hal/ports/RP/RP2040/hal_lld.h b/os/hal/ports/RP/RP2040/hal_lld.h index 0736923d38..313405b2a7 100644 --- a/os/hal/ports/RP/RP2040/hal_lld.h +++ b/os/hal/ports/RP/RP2040/hal_lld.h @@ -29,9 +29,7 @@ * Registry definitions. */ #include "rp_registry.h" - -/* From Pico-SDK */ -#include "hardware/clocks.h" +#include "rp_clocks.h" /*===========================================================================*/ /* Driver constants. */ @@ -56,6 +54,14 @@ #define RP_ROSCCLK 6500000 /**< 6.5MHz internal clock. */ /** @} */ +/** + * @name GPIO IOCTRL register field positions + * @{ + */ +#define RP_GPIO_IOCTRL_OEOVER_Pos 12 +#define RP_GPIO_IOCTRL_OUTOVER_Pos 8 +/** @} */ + /** * @brief Dynamic clock supported. */ @@ -103,6 +109,7 @@ #if !defined(RP_CORE1_STACK_END) || defined(__DOXYGEN__) #define RP_CORE1_STACK_END __c1_main_stack_end__ #endif +/** @} */ /*===========================================================================*/ /* Derived constants and error checks. */ @@ -122,20 +129,76 @@ #error "RP_XOSCCLK not defined in board.h" #endif +#if (RP_XOSCCLK < 1000000) || (RP_XOSCCLK > 15000000) +#error "RP_XOSCCLK out of valid range (1-15 MHz)" +#endif + +/* + * PLL_SYS configuration checks. + */ +#if (RP_PLL_SYS_REFDIV < 1) || (RP_PLL_SYS_REFDIV > 63) +#error "RP_PLL_SYS_REFDIV out of valid range (1-63)" +#endif + +#if (RP_PLL_SYS_VCO_FREQ < RP_PLL_VCO_MIN_FREQ) || \ + (RP_PLL_SYS_VCO_FREQ > RP_PLL_VCO_MAX_FREQ) +#error "RP_PLL_SYS_VCO_FREQ out of valid range (750-1600 MHz)" +#endif + +#if (RP_PLL_SYS_POSTDIV1 < 1) || (RP_PLL_SYS_POSTDIV1 > 7) +#error "RP_PLL_SYS_POSTDIV1 out of valid range (1-7)" +#endif + +#if (RP_PLL_SYS_POSTDIV2 < 1) || (RP_PLL_SYS_POSTDIV2 > 7) +#error "RP_PLL_SYS_POSTDIV2 out of valid range (1-7)" +#endif + +#if RP_PLL_SYS_POSTDIV1 < RP_PLL_SYS_POSTDIV2 +#error "RP_PLL_SYS_POSTDIV1 must be >= RP_PLL_SYS_POSTDIV2" +#endif + +/* + * PLL_USB configuration checks. + */ +#if (RP_PLL_USB_REFDIV < 1) || (RP_PLL_USB_REFDIV > 63) +#error "RP_PLL_USB_REFDIV out of valid range (1-63)" +#endif + +#if (RP_PLL_USB_VCO_FREQ < RP_PLL_VCO_MIN_FREQ) || \ + (RP_PLL_USB_VCO_FREQ > RP_PLL_VCO_MAX_FREQ) +#error "RP_PLL_USB_VCO_FREQ out of valid range (750-1600 MHz)" +#endif + +#if (RP_PLL_USB_POSTDIV1 < 1) || (RP_PLL_USB_POSTDIV1 > 7) +#error "RP_PLL_USB_POSTDIV1 out of valid range (1-7)" +#endif + +#if (RP_PLL_USB_POSTDIV2 < 1) || (RP_PLL_USB_POSTDIV2 > 7) +#error "RP_PLL_USB_POSTDIV2 out of valid range (1-7)" +#endif + +#if RP_PLL_USB_POSTDIV1 < RP_PLL_USB_POSTDIV2 +#error "RP_PLL_USB_POSTDIV1 must be >= RP_PLL_USB_POSTDIV2" +#endif + +#if RP_PLL_USB_CLK != 48000000 +#error "RP_PLL_USB_CLK must be 48 MHz for USB to work" +#endif + /** * @name Various clock points. * @{ */ -#define RP_GPOUT0_CLK hal_lld_get_clock_point(clk_gpout0) -#define RP_GPOUT1_CLK hal_lld_get_clock_point(clk_gpout1) -#define RP_GPOUT2_CLK hal_lld_get_clock_point(clk_gpout2) -#define RP_GPOUT3_CLK hal_lld_get_clock_point(clk_gpout3) -#define RP_REF_CLK hal_lld_get_clock_point(clk_ref) -#define RP_CORE_CLK hal_lld_get_clock_point(clk_sys) -#define RP_PERI_CLK hal_lld_get_clock_point(clk_peri) -#define RP_USB_CLK hal_lld_get_clock_point(clk_usb) -#define RP_ADC_CLK hal_lld_get_clock_point(clk_adc) -#define RP_RTC_CLK hal_lld_get_clock_point(clk_rtc) +#define RP_GPOUT0_CLK hal_lld_get_clock_point(RP_CLK_GPOUT0) +#define RP_GPOUT1_CLK hal_lld_get_clock_point(RP_CLK_GPOUT1) +#define RP_GPOUT2_CLK hal_lld_get_clock_point(RP_CLK_GPOUT2) +#define RP_GPOUT3_CLK hal_lld_get_clock_point(RP_CLK_GPOUT3) +#define RP_REF_CLK hal_lld_get_clock_point(RP_CLK_REF) +#define RP_CORE_CLK hal_lld_get_clock_point(RP_CLK_SYS) +#define RP_PERI_CLK hal_lld_get_clock_point(RP_CLK_PERI) +#define RP_USB_CLK hal_lld_get_clock_point(RP_CLK_USB) +#define RP_ADC_CLK hal_lld_get_clock_point(RP_CLK_ADC) +#define RP_RTC_CLK hal_lld_get_clock_point(RP_CLK_RTC) /** @} */ /*===========================================================================*/ @@ -155,6 +218,32 @@ typedef struct { /* Driver macros. */ /*===========================================================================*/ +/** + * @name Safety module counter support + * @note Uses TIMER0 peripheral which counts at 1 us resolution. + * During early clock init, accuracy depends on ROSC variance. + * After clock init completes, timing is precise. + * @{ + */ + +/** + * @brief Counter type for safety timeouts. + */ +typedef uint32_t halcnt_t; + +/** + * @brief Returns the counter frequency in Hz. + * @note Always returns 1 MHz (1 us ticks). + */ +#define HAL_LLD_GET_CNT_FREQUENCY() 1000000U + +/** + * @brief Returns the current counter value. + */ +#define HAL_LLD_GET_CNT_VALUE() ((halcnt_t)TIMER0->TIMERAWL) + +/** @} */ + /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ @@ -165,6 +254,8 @@ typedef struct { #include "rp_isr.h" #include "rp_fifo.h" #include "rp_dma.h" +#include "rp_pio.h" +#include "rp_bootrom.h" #ifdef __cplusplus extern "C" { @@ -178,16 +269,16 @@ extern "C" { /* Driver inline functions. */ /*===========================================================================*/ -__STATIC_INLINE void hal_lld_peripheral_reset(uint32_t mask) { +__STATIC_INLINE void rp_peripheral_reset(uint32_t mask) { - RESETS->RESET |= mask; + RESETS->SET.RESET = mask; } -__STATIC_INLINE void hal_lld_peripheral_unreset(uint32_t mask) { +__STATIC_INLINE void rp_peripheral_unreset(uint32_t mask) { - RESETS->RESET &= ~mask; - while ((RESETS->RESET_DONE & mask) == 0U) { - /* Waiting for reset.*/ + RESETS->CLR.RESET = mask; + while ((RESETS->RESET_DONE & mask) != mask) { + /* Waiting for peripheral to come out of reset */ } } @@ -220,9 +311,9 @@ __STATIC_INLINE bool hal_lld_clock_switch_mode(const halclkcfg_t *ccp) { */ __STATIC_INLINE halfreq_t hal_lld_get_clock_point(halclkpt_t clkpt) { - osalDbgAssert(clkpt < CLK_COUNT, "invalid clock point"); + osalDbgAssert(clkpt < RP_CLK_COUNT, "invalid clock point"); - return clock_get_hz(clkpt); + return rp_clock_get_hz(clkpt); } #endif /* defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ diff --git a/os/hal/ports/RP/RP2040/platform.mk b/os/hal/ports/RP/RP2040/platform.mk index 701ed2c1bb..d54395db53 100644 --- a/os/hal/ports/RP/RP2040/platform.mk +++ b/os/hal/ports/RP/RP2040/platform.mk @@ -1,11 +1,16 @@ # Required platform files. PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ + $(CHIBIOS)/os/hal/ports/RP/rp_bootrom.c \ + $(CHIBIOS)/os/hal/ports/RP/RP2040/rp_clocks.c \ $(CHIBIOS)/os/hal/ports/RP/RP2040/rp_isr.c \ + $(CHIBIOS)/os/hal/ports/RP/RP2040/rp_pll.c \ + $(CHIBIOS)/os/hal/ports/RP/RP2040/rp_xosc.c \ $(CHIBIOS)/os/hal/ports/RP/RP2040/hal_lld.c # Required include directories. PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ - $(CHIBIOS)/os/hal/ports/RP/RP2040 + $(CHIBIOS)/os/hal/ports/RP/RP2040 \ + $(CHIBIOS)/os/hal/ports/RP # Optional platform files. ifeq ($(USE_SMART_BUILD),yes) @@ -21,17 +26,27 @@ endif HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) +ifneq ($(findstring HAL_USE_EFL TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/RP/RP2040/hal_efl_lld.c +endif else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/RP/RP2040/hal_efl_lld.c endif # Drivers compatible with the platform. +include $(CHIBIOS)/os/hal/ports/RP/LLD/EFLv1/driver.mk include $(CHIBIOS)/os/hal/ports/RP/LLD/DMAv1/driver.mk +include $(CHIBIOS)/os/hal/ports/RP/LLD/PIOv1/driver.mk include $(CHIBIOS)/os/hal/ports/RP/LLD/GPIOv1/driver.mk include $(CHIBIOS)/os/hal/ports/RP/LLD/SPIv1/driver.mk include $(CHIBIOS)/os/hal/ports/RP/LLD/TIMERv1/driver.mk include $(CHIBIOS)/os/hal/ports/RP/LLD/UARTv1/driver.mk include $(CHIBIOS)/os/hal/ports/RP/LLD/RTCv1/driver.mk include $(CHIBIOS)/os/hal/ports/RP/LLD/WDGv1/driver.mk +include $(CHIBIOS)/os/hal/ports/RP/LLD/USBv1/driver.mk +include $(CHIBIOS)/os/hal/ports/RP/LLD/I2Cv1/driver.mk +include $(CHIBIOS)/os/hal/ports/RP/LLD/PWMv1/driver.mk +include $(CHIBIOS)/os/hal/ports/RP/LLD/ADCv1/driver.mk # Shared variables ALLCSRC += $(PLATFORMSRC) diff --git a/os/hal/ports/RP/RP2040/rp_clocks.c b/os/hal/ports/RP/RP2040/rp_clocks.c new file mode 100644 index 0000000000..f0b90f26fb --- /dev/null +++ b/os/hal/ports/RP/RP2040/rp_clocks.c @@ -0,0 +1,214 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2040/rp_clocks.c + * @brief RP2040 clocks driver source. + * @note See RP2040 Datasheet 2.15 Clocks + * + * @addtogroup RP_CLOCKS + * @{ + */ + +#include "hal.h" +#include "rp_clocks.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/** + * @brief Estimated ROSC frequency for early timing. + * @note RP2040 ROSC varies 1.8-12 MHz, we assume ~6 MHz. + * This gives roughly +/-50% accuracy which is acceptable for + * safety timeouts during early clock initialization. + */ +#define RP_ROSC_ASSUMED_HZ 6000000U + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +#if RP_SYS_VREG_VOLTAGE > 0U +static void delay_us(uint32_t delay) { + uint32_t start = TIMER0->TIMERAWL; + + while ((TIMER0->TIMERAWL - start) < delay) { + } +} +#endif + +static void set_vreg(void) { +#if RP_SYS_VREG_VOLTAGE > 0U + uint32_t current_vsel; + + current_vsel = (VREG_AND_CHIP_RESET->VREG & VREG_VSEL_Msk) >> VREG_VSEL_Pos; + if (current_vsel < RP_SYS_VREG_VOLTAGE) { + VREG_AND_CHIP_RESET->VREG = + (VREG_AND_CHIP_RESET->VREG & ~VREG_VSEL_Msk) | + (RP_SYS_VREG_VOLTAGE << VREG_VSEL_Pos); + delay_us(RP_SYS_VREG_SETTLE_DELAY_US); + } +#endif +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes all clocks. + * @note Most of this is derived from the RP2040 datasheet which directly + * references suggested code from the Pico SDK which is Copyright + * 2020 Raspberry Pi (Trading) Ltd and licensed under the + * BSD-3-Clause license. We always start with ROSC and then switch + * to XOSC. With the RP2040 WATCHDOG->TICK services the watchdog, + * the system timer and SYSTICK. + * @note See RP2040 Datasheet 2.15.3.1 Clock Instances (Table 205) + */ +void rp_clock_init(void) { + + /* Start early tick generator for safety module timeouts. */ + rp_peripheral_unreset(RESETS_ALLREG_TIMER0); + + /* Configure tick generator for ~1 us ticks. */ + WATCHDOG->TICK = WATCHDOG_TICK_ENABLE | (RP_ROSC_ASSUMED_HZ / RP_ROSC_ASSUMED_HZ); + + /* Clear clock resus that may be in an unkown state */ + CLOCKS->RESUS.CTRL = 0U; + + rp_xosc_init(); + + /* Switch clk_sys and clk_ref to safe sources */ + CLOCKS->CLR.CLK[RP_CLK_SYS].CTRL = CLOCKS_CLK_SYS_CTRL_SRC_Msk; + while ((CLOCKS->CLK[RP_CLK_SYS].SELECTED & 1U) == 0U) { + /* Wait for clk_sys to switch to clk_ref */ + } + CLOCKS->CLR.CLK[RP_CLK_REF].CTRL = CLOCKS_CLK_REF_CTRL_SRC_Msk; + while ((CLOCKS->CLK[RP_CLK_REF].SELECTED & 1U) == 0U) { + /* Wait for clk_ref to switch to ROSC */ + } + + /* Initialize PLL_SYS: 12 MHz * 125 / 6 / 2 = 125 MHz. */ + rp_pll_init(PLL_SYS, RP_PLL_SYS_REFDIV, RP_PLL_SYS_VCO_FREQ, + RP_PLL_SYS_POSTDIV1, RP_PLL_SYS_POSTDIV2); + + /* Initialize PLL_USB: 12 MHz * 100 / 5 / 5 = 48 MHz. */ + rp_pll_init(PLL_USB, RP_PLL_USB_REFDIV, RP_PLL_USB_VCO_FREQ, + RP_PLL_USB_POSTDIV1, RP_PLL_USB_POSTDIV2); + + /* CLK_REF = XOSC = 12 MHz */ + { + uint32_t src = CLOCKS_CLK_REF_CTRL_SRC_XOSC >> CLOCKS_CLK_REF_CTRL_SRC_Pos; + CLOCKS->CLK[RP_CLK_REF].DIV = 1U << 8; + CLOCKS->XOR.CLK[RP_CLK_REF].CTRL = + (CLOCKS->CLK[RP_CLK_REF].CTRL ^ (src << CLOCKS_CLK_REF_CTRL_SRC_Pos)) & + CLOCKS_CLK_REF_CTRL_SRC_Msk; + while ((CLOCKS->CLK[RP_CLK_REF].SELECTED & (1U << src)) == 0U) { + /* Wait for switch to XOSC */ + } + } + + /* Reconfigure tick generator for accurate 1 us ticks now that clk_ref + * is on XOSC, then raise core voltage if needed before the fast + * clk_sys switch. */ + WATCHDOG->TICK = WATCHDOG_TICK_ENABLE | (RP_XOSCCLK / 1000000U); + set_vreg(); + + /* CLK_SYS = PLL_SYS */ + CLOCKS->CLR.CLK[RP_CLK_SYS].CTRL = CLOCKS_CLK_SYS_CTRL_SRC_Msk; + while ((CLOCKS->CLK[RP_CLK_SYS].SELECTED & 1U) == 0U) { + /* Wait for switch to clk_ref */ + } + CLOCKS->XOR.CLK[RP_CLK_SYS].CTRL = + (CLOCKS->CLK[RP_CLK_SYS].CTRL ^ CLOCKS_CLK_SYS_CTRL_AUXSRC_PLL_SYS) & + CLOCKS_CLK_SYS_CTRL_AUXSRC_Msk; + CLOCKS->SET.CLK[RP_CLK_SYS].CTRL = CLOCKS_CLK_SYS_CTRL_SRC_AUX; + while ((CLOCKS->CLK[RP_CLK_SYS].SELECTED & 2U) == 0U) { + /* Wait for switch to aux */ + } + + /* CLK_USB = PLL_USB = 48 MHz */ + CLOCKS->XOR.CLK[RP_CLK_USB].CTRL = + (CLOCKS->CLK[RP_CLK_USB].CTRL ^ CLOCKS_CLK_USB_CTRL_AUXSRC_PLL_USB) & + CLOCKS_CLK_USB_CTRL_AUXSRC_Msk; + CLOCKS->CLK[RP_CLK_USB].DIV = 1U << 8; + CLOCKS->SET.CLK[RP_CLK_USB].CTRL = CLOCKS_CLK_PERI_CTRL_ENABLE; + + /* CLK_ADC = PLL_USB = 48 MHz */ + CLOCKS->XOR.CLK[RP_CLK_ADC].CTRL = + (CLOCKS->CLK[RP_CLK_ADC].CTRL ^ CLOCKS_CLK_ADC_CTRL_AUXSRC_PLL_USB) & + CLOCKS_CLK_ADC_CTRL_AUXSRC_Msk; + CLOCKS->CLK[RP_CLK_ADC].DIV = 1U << 8; + CLOCKS->SET.CLK[RP_CLK_ADC].CTRL = CLOCKS_CLK_PERI_CTRL_ENABLE; + + /* CLK_RTC = PLL_USB / 1024 = 46875Hz */ + CLOCKS->XOR.CLK[RP_CLK_RTC].CTRL = + (CLOCKS->CLK[RP_CLK_RTC].CTRL ^ CLOCKS_CLK_RTC_CTRL_AUXSRC_PLL_USB) & + CLOCKS_CLK_RTC_CTRL_AUXSRC_Msk; + CLOCKS->CLK[RP_CLK_RTC].DIV = RP_RTC_CLK_DIV << 8; + CLOCKS->SET.CLK[RP_CLK_RTC].CTRL = CLOCKS_CLK_PERI_CTRL_ENABLE; + + /* CLK_PERI = PLL_SYS = 125 MHz */ + CLOCKS->XOR.CLK[RP_CLK_PERI].CTRL = + (CLOCKS->CLK[RP_CLK_PERI].CTRL ^ CLOCKS_CLK_PERI_CTRL_AUXSRC_SYS) & + CLOCKS_CLK_PERI_CTRL_AUXSRC_Msk; + CLOCKS->CLK[RP_CLK_PERI].DIV = 1U << 8; + CLOCKS->SET.CLK[RP_CLK_PERI].CTRL = CLOCKS_CLK_PERI_CTRL_ENABLE; + + /* Calculate cycles for 1us tick based on clk_ref frequency. */ + WATCHDOG->TICK = WATCHDOG_TICK_ENABLE | (RP_XOSCCLK / 1000000U); +} + +/** + * @brief Returns the frequency of a clock in Hz. + * @note Uses compile-time constants so this function is safe to call + * before BSS/DATA initialization. + * + * @param[in] clk_index clock index (RP_CLK_xxx) + * @return clock frequency in Hz + */ +uint32_t rp_clock_get_hz(uint32_t clk_index) { + + osalDbgAssert(clk_index < RP_CLK_COUNT, "invalid clock index"); + + switch (clk_index) { + case RP_CLK_REF: + return RP_CLK_REF_FREQ; + case RP_CLK_SYS: + return RP_CLK_SYS_FREQ; + case RP_CLK_PERI: + return RP_CLK_PERI_FREQ; + case RP_CLK_USB: + return RP_CLK_USB_FREQ; + case RP_CLK_ADC: + return RP_CLK_ADC_FREQ; + case RP_CLK_RTC: + return RP_CLK_RTC_FREQ; + default: + return 0U; + } +} + +/** @} */ diff --git a/os/hal/ports/RP/RP2040/rp_clocks.h b/os/hal/ports/RP/RP2040/rp_clocks.h new file mode 100644 index 0000000000..4415341fe2 --- /dev/null +++ b/os/hal/ports/RP/RP2040/rp_clocks.h @@ -0,0 +1,192 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2040/rp_clocks.h + * @brief RP2040 clocks header. + * + * @addtogroup RP_CLOCKS + * @{ + */ + +#ifndef RP_CLOCKS_H +#define RP_CLOCKS_H + +#include "rp_xosc.h" +#include "rp_pll.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief RTC clock divisor + */ +#define RP_RTC_CLK_DIV 1024U + +/** + * @name PLL_SYS configuration + * @note Default configuration produces 125 MHz system clock + * @{ + */ +#if !defined(RP_PLL_SYS_REFDIV) || defined(__DOXYGEN__) +#define RP_PLL_SYS_REFDIV 1U +#endif +#if !defined(RP_PLL_SYS_VCO_FREQ) || defined(__DOXYGEN__) +#define RP_PLL_SYS_VCO_FREQ 1500000000U /* 1500 MHz VCO */ +#endif +#if !defined(RP_PLL_SYS_POSTDIV1) || defined(__DOXYGEN__) +#define RP_PLL_SYS_POSTDIV1 6U /* 125 MHz output */ +#endif +#if !defined(RP_PLL_SYS_POSTDIV2) || defined(__DOXYGEN__) +#define RP_PLL_SYS_POSTDIV2 2U +#endif +/** @} */ + +/** + * @name PLL_USB configuration + * @{ + */ +#if !defined(RP_PLL_USB_REFDIV) || defined(__DOXYGEN__) +#define RP_PLL_USB_REFDIV 1U +#endif +#if !defined(RP_PLL_USB_VCO_FREQ) || defined(__DOXYGEN__) +#define RP_PLL_USB_VCO_FREQ 1200000000U /* 1200 MHz VCO */ +#endif +#if !defined(RP_PLL_USB_POSTDIV1) || defined(__DOXYGEN__) +#define RP_PLL_USB_POSTDIV1 5U +#endif +#if !defined(RP_PLL_USB_POSTDIV2) || defined(__DOXYGEN__) +#define RP_PLL_USB_POSTDIV2 5U +#endif +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/** + * @name PLL output frequencies + * @{ + */ +/** + * @brief PLL_SYS output frequency in Hz. + */ +#define RP_PLL_SYS_CLK (RP_PLL_SYS_VCO_FREQ / \ + (RP_PLL_SYS_POSTDIV1 * \ + RP_PLL_SYS_POSTDIV2)) + +/** + * @brief PLL_USB output frequency in Hz (must be 48 MHz for USB). + */ +#define RP_PLL_USB_CLK (RP_PLL_USB_VCO_FREQ / \ + (RP_PLL_USB_POSTDIV1 * \ + RP_PLL_USB_POSTDIV2)) +/** @} */ + +/** + * @name VREG voltage configuration for high-speed operation + * @note 200 MHz is supported by the pico-sdk and requires 1.15V. + * Frequencies above 200 MHz are not officially supported. + * Automatically selected based on RP_PLL_SYS_CLK. + * Set to 0 to disable VREG adjustment. + * @{ + */ +#if !defined(RP_SYS_VREG_VOLTAGE) || defined(__DOXYGEN__) +#if RP_PLL_SYS_CLK >= 250000000U +#define RP_SYS_VREG_VOLTAGE 13U /* 1.20V */ +#elif RP_PLL_SYS_CLK >= 200000000U +#define RP_SYS_VREG_VOLTAGE 12U /* 1.15V */ +#else +#define RP_SYS_VREG_VOLTAGE 0U /* No adjustment */ +#endif +#endif + +#if !defined(RP_SYS_VREG_SETTLE_DELAY_US) || defined(__DOXYGEN__) +#define RP_SYS_VREG_SETTLE_DELAY_US 1000U /* 1 ms */ +#endif +/** @} */ + +/** + * @name Compile-time clock frequencies + * @note These are compile-time constants derived from PLL configuration. + * For runtime clock queries, use the hal_lld_get_clock_point() API. + * @{ + */ +/** + * @brief System core clock frequency in Hz. + */ +#define RP_CLK_SYS_FREQ RP_PLL_SYS_CLK + +/** + * @brief Reference clock frequency in Hz. + */ +#define RP_CLK_REF_FREQ RP_XOSCCLK + +/** + * @brief Peripheral clock frequency in Hz. + * @note CLK_PERI runs at CLK_SYS frequency by default. + */ +#define RP_CLK_PERI_FREQ RP_PLL_SYS_CLK + +/** + * @brief USB clock frequency in Hz (must be 48 MHz). + */ +#define RP_CLK_USB_FREQ RP_PLL_USB_CLK + +/** + * @brief ADC clock frequency in Hz (must be 48 MHz). + */ +#define RP_CLK_ADC_FREQ RP_PLL_USB_CLK + +/** + * @brief RTC clock frequency in Hz. + * @note Derived from PLL_USB (48 MHz) because it provides a stable + * reference independent of system clock changes. 48 MHz / 1024 + * = 46875 Hz, which divides evenly into seconds for accurate + * timekeeping. + */ +#define RP_CLK_RTC_FREQ (RP_PLL_USB_CLK / RP_RTC_CLK_DIV) +/** @} */ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void rp_clock_init(void); + uint32_t rp_clock_get_hz(uint32_t clk_index); +#ifdef __cplusplus +} +#endif + +#endif /* RP_CLOCKS_H */ + +/** @} */ diff --git a/os/hal/ports/RP/RP2040/rp_isr.c b/os/hal/ports/RP/RP2040/rp_isr.c index 55d8828825..812364fec3 100644 --- a/os/hal/ports/RP/RP2040/rp_isr.c +++ b/os/hal/ports/RP/RP2040/rp_isr.c @@ -52,14 +52,14 @@ /*===========================================================================*/ /** - * @brief Enables IRQ sources. + * @brief IRQ subsystem initialization. + * @details Puts the IRQ controller in a known clean state before any + * HAL drivers enable their individual interrupts. * * @notapi */ void irqInit(void) { -// uart0_irq_init(); -// uart1_irq_init(); } /** @@ -69,8 +69,6 @@ void irqInit(void) { */ void irqDeinit(void) { -// uart0_irq_deinit(); -// uart1_irq_deinit(); } /** @} */ diff --git a/os/hal/ports/RP/RP2040/rp_isr.h b/os/hal/ports/RP/RP2040/rp_isr.h index 9a473cdc9c..bbc2856176 100644 --- a/os/hal/ports/RP/RP2040/rp_isr.h +++ b/os/hal/ports/RP/RP2040/rp_isr.h @@ -33,38 +33,63 @@ * @name ISR names and numbers * @{ */ -#define RP_TIMER_IRQ0_HANDLER Vector40 -#define RP_TIMER_IRQ1_HANDLER Vector44 -#define RP_TIMER_IRQ2_HANDLER Vector48 -#define RP_TIMER_IRQ3_HANDLER Vector4C -#define RP_PWM_IRQ_WRAP_HANDLER Vector50 + +/* TIMER0 interrupts (4 alarms) */ +#define RP_TIMER0_IRQ0_HANDLER Vector40 +#define RP_TIMER0_IRQ1_HANDLER Vector44 +#define RP_TIMER0_IRQ2_HANDLER Vector48 +#define RP_TIMER0_IRQ3_HANDLER Vector4C + +/* PWM interrupts */ +#define RP_PWM_IRQ_WRAP_0_HANDLER Vector50 + +/* DMA interrupts */ +#define RP_DMA_IRQ_0_HANDLER Vector6C +#define RP_DMA_IRQ_1_HANDLER Vector70 + +/* USB interrupt */ #define RP_USBCTRL_IRQ_HANDLER Vector54 #define RP_XIP_IRQ_HANDLER Vector58 + +/* PIO interrupts */ #define RP_PIO0_IRQ_0_HANDLER Vector5C #define RP_PIO0_IRQ_1_HANDLER Vector60 #define RP_PIO1_IRQ_0_HANDLER Vector64 #define RP_PIO1_IRQ_1_HANDLER Vector68 -#define RP_DMA_IRQ_0_HANDLER Vector6C -#define RP_DMA_IRQ_1_HANDLER Vector70 + +/* IO Bank interrupts */ #define RP_IO_IRQ_BANK0_HANDLER Vector74 #define RP_IO_IRQ_QSPI_HANDLER Vector78 + +/* SIO interrupts */ #define RP_SIO_IRQ_PROC0_HANDLER Vector7C #define RP_SIO_IRQ_PROC1_HANDLER Vector80 + +/* Clocks interrupt */ #define RP_CLOCKS_IRQ_HANDLER Vector84 + +/* SPI interrupts */ #define RP_SPI0_IRQ_HANDLER Vector88 #define RP_SPI1_IRQ_HANDLER Vector8C + +/* UART interrupts */ #define RP_UART0_IRQ_HANDLER Vector90 #define RP_UART1_IRQ_HANDLER Vector94 + +/* ADC interrupt */ #define RP_ADC_IRQ_FIFO_HANDLER Vector98 + +/* I2C interrupts */ #define RP_I2C0_IRQ_HANDLER Vector9C #define RP_I2C1_IRQ_HANDLER VectorA0 #define RP_RTC_IRQ_HANDLER VectorA4 -#define RP_TIMER_IRQ0_NUMBER 0 -#define RP_TIMER_IRQ1_NUMBER 1 -#define RP_TIMER_IRQ2_NUMBER 2 -#define RP_TIMER_IRQ3_NUMBER 3 -#define RP_PWM_IRQ_WRAP_NUMBER 4 +/* IRQ numbers */ +#define RP_TIMER0_IRQ0_NUMBER 0 +#define RP_TIMER0_IRQ1_NUMBER 1 +#define RP_TIMER0_IRQ2_NUMBER 2 +#define RP_TIMER0_IRQ3_NUMBER 3 +#define RP_PWM_IRQ_WRAP_0_NUMBER 4 #define RP_USBCTRL_IRQ_NUMBER 5 #define RP_XIP_IRQ_NUMBER 6 #define RP_PIO0_IRQ_0_NUMBER 7 diff --git a/os/hal/ports/RP/RP2040/rp_pal_lld.h b/os/hal/ports/RP/RP2040/rp_pal_lld.h new file mode 100644 index 0000000000..b26c6dc2fc --- /dev/null +++ b/os/hal/ports/RP/RP2040/rp_pal_lld.h @@ -0,0 +1,54 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2040/rp_pal_lld.h + * @brief RP2040-specific PAL low level driver definitions. + */ + +#ifndef RP2040_RP_PAL_LLD_H +#define RP2040_RP_PAL_LLD_H + +/** + * @name RP2040-specific alternate function selectors + * @{ + */ +#define PAL_RP_IOCTRL_FUNCSEL_CLK PAL_RP_IOCTRL_FUNCSEL(8U) +#define PAL_RP_IOCTRL_FUNCSEL_USB PAL_RP_IOCTRL_FUNCSEL(9U) + +#define PAL_MODE_ALTERNATE_CLK (PAL_RP_IOCTRL_FUNCSEL_CLK | \ + PAL_RP_PAD_IE | \ + PAL_RP_PAD_SCHMITT) +#define PAL_MODE_ALTERNATE_USB (PAL_RP_IOCTRL_FUNCSEL_USB | \ + PAL_RP_PAD_IE | \ + PAL_RP_PAD_SCHMITT) +/** @} */ + +/** + * @brief Access a SIO GPIO register by port. + * @details Given a register name (field of SIO) and port (0, 1), produce a + * reference to the correct GPIO register for the port. On the RP2040 + * every "hi" output and output-enable register is eight uint32_t's + * after the corresponding "low" register. The input registers + * GPIO_IN / GPIO_HI_IN are only one apart, but port 1 does not exist + * on RP2040 (only 30 GPIO lines) so the offset is never applied. + * + * @notapi + */ +#define RP_PAL_SIO_REG(reg, port) \ + ((&SIO->reg)[(port) ? 8U : 0U]) + +#endif /* RP2040_RP_PAL_LLD_H */ diff --git a/os/hal/ports/RP/RP2040/rp_pll.c b/os/hal/ports/RP/RP2040/rp_pll.c new file mode 100644 index 0000000000..2cda38b12b --- /dev/null +++ b/os/hal/ports/RP/RP2040/rp_pll.c @@ -0,0 +1,132 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2040/rp_pll.c + * @brief RP2040 PLL source. + * + * @addtogroup RP_PLL + * @{ + */ + +#include "hal.h" +#include "hal_safety.h" +#include "rp_pll.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/** + * @brief Timeout for PLL lock in microseconds. + * @note PLL lock typically takes <1 ms. We allow up to 10 ms + * to account for ROSC timing variance during early init. + */ +#define RP_PLL_LOCK_TIMEOUT_US 10000U + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes a PLL. + * + * @param[in] pll pointer to PLL registers (PLL_SYS or PLL_USB) + * @param[in] refdiv reference divider (1-63) + * @param[in] vco_freq target VCO frequency in Hz (750-1600 MHz) + * @param[in] postdiv1 post divider 1 (1-7) + * @param[in] postdiv2 post divider 2 (1-7) + * + * @note Output frequency = vco_freq / (postdiv1 * postdiv2) + * @note VCO frequency = (XOSC / refdiv) * fbdiv + * @note See RP2040 Datasheet 2.18 PLL + */ +void rp_pll_init(PLL_TypeDef *pll, uint32_t refdiv, uint32_t vco_freq, + uint32_t postdiv1, uint32_t postdiv2) { + + uint32_t ref_freq = RP_XOSCCLK / refdiv; + uint32_t fbdiv = vco_freq / ref_freq; + uint32_t pdiv = PLL_PRIM_POSTDIV1(postdiv1) | PLL_PRIM_POSTDIV2(postdiv2); + + osalDbgAssert(vco_freq >= RP_PLL_VCO_MIN_FREQ && + vco_freq <= RP_PLL_VCO_MAX_FREQ, + "VCO frequency out of range"); + osalDbgAssert(fbdiv >= 16U && fbdiv <= 320U, "FBDIV out of range"); + osalDbgAssert(postdiv1 >= 1U && postdiv1 <= 7U, "POSTDIV1 out of range"); + osalDbgAssert(postdiv2 >= 1U && postdiv2 <= 7U, "POSTDIV2 out of range"); + osalDbgAssert(ref_freq <= (vco_freq / 16U), "Reference frequency too high"); + + /* Check if PLL is already configured */ + if ((pll->CS & PLL_CS_LOCK) && + (refdiv == (pll->CS & PLL_CS_REFDIV_Msk)) && + (fbdiv == (pll->FBDIV_INT & PLL_FBDIV_INT_Msk)) && + (pdiv == (pll->PRIM & (PLL_PRIM_POSTDIV1_Msk | PLL_PRIM_POSTDIV2_Msk)))) { + return; + } + + /* Reset the PLL */ + if (pll == PLL_SYS) { + rp_peripheral_reset(RESETS_ALLREG_PLL_SYS); + rp_peripheral_unreset(RESETS_ALLREG_PLL_SYS); + } else { + rp_peripheral_reset(RESETS_ALLREG_PLL_USB); + rp_peripheral_unreset(RESETS_ALLREG_PLL_USB); + } + + /* Set VCO divider */ + pll->CS = refdiv; + pll->FBDIV_INT = fbdiv; + + /* Turn on PLL */ + pll->CLR.PWR = PLL_PWR_PD | PLL_PWR_VCOPD; + + /* Wait for PLL lock */ + if (halRegWaitAnySet32X(&pll->CS, PLL_CS_LOCK, + RP_PLL_LOCK_TIMEOUT_US, NULL)) { + halSftFail("PLL lock timeout"); + } + + /* Set post divider */ + pll->PRIM = pdiv; + + /* Turn on post divider */ + pll->CLR.PWR = PLL_PWR_POSTDIVPD; +} + +/** + * @brief Deinitialize a PLL. + * + * @param[in] pll pointer to PLL register + */ +void rp_pll_deinit(PLL_TypeDef *pll) { + + /* Power down the PLL */ + pll->PWR = PLL_PWR_PD | PLL_PWR_VCOPD | PLL_PWR_POSTDIVPD | PLL_PWR_DSMPD; +} + +/** @} */ diff --git a/os/hal/ports/RP/RP2040/rp_pll.h b/os/hal/ports/RP/RP2040/rp_pll.h new file mode 100644 index 0000000000..70fcc9f9ca --- /dev/null +++ b/os/hal/ports/RP/RP2040/rp_pll.h @@ -0,0 +1,74 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2040/rp_pll.h + * @brief RP2040 PLL header. + * + * @addtogroup RP_PLL + * @{ + */ + +#ifndef RP_PLL_H +#define RP_PLL_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Minimum VCO frequency in Hz. + */ +#define RP_PLL_VCO_MIN_FREQ 750000000U + +/** + * @brief Maximum VCO frequency in Hz. + */ +#define RP_PLL_VCO_MAX_FREQ 1600000000U + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void rp_pll_init(PLL_TypeDef *pll, uint32_t refdiv, uint32_t vco_freq, + uint32_t postdiv1, uint32_t postdiv2); + void rp_pll_deinit(PLL_TypeDef *pll); +#ifdef __cplusplus +} +#endif + +#endif /* RP_PLL_H */ + +/** @} */ diff --git a/os/hal/ports/RP/RP2040/rp_registry.h b/os/hal/ports/RP/RP2040/rp_registry.h index fac5bdf8a0..43d14b9f29 100644 --- a/os/hal/ports/RP/RP2040/rp_registry.h +++ b/os/hal/ports/RP/RP2040/rp_registry.h @@ -42,12 +42,23 @@ /* RP2040. */ /*===========================================================================*/ +/* GPIO attributes.*/ +#define RP_GPIO_NUM_LINES 30 +#define RP_GPIO_INTR_REGS 4 + /* UART attributes.*/ #define RP_HAS_UART0 TRUE #define RP_HAS_UART1 TRUE +/* PIO attributes.*/ +#define RP_HAS_PIO0 TRUE +#define RP_HAS_PIO1 TRUE +#define RP_HAS_PIO2 FALSE +#define RP_PIO_NUM_BLOCKS 2 + /* TIMER attributes.*/ -#define RP_HAS_TIMER TRUE +#define RP_HAS_TIMER0 TRUE +#define RP_ST_NUM_ALARMS 4 /* RTC attributes.*/ #define RP_HAS_RTC TRUE @@ -56,9 +67,53 @@ #define RP_HAS_SPI0 TRUE #define RP_HAS_SPI1 TRUE +/* I2C attributes.*/ +#define RP_HAS_I2C0 TRUE +#define RP_HAS_I2C1 TRUE + +/* DMA attributes.*/ +#define RP_HAS_DMA TRUE +#define RP_DMA_NUM_CHANNELS 12 + /* WDG attributes.*/ #define RP_HAS_WDG TRUE #define RP_WDG_STORAGE_SIZE 32U +#define RP_PSM_WDSEL_ALL_BITS 0x1FFFFU +#define RP_WDG_HAS_E1_ERRATA TRUE + +/* USB attributes.*/ +#define RP_HAS_USB TRUE +#define USB_ENDPOINTS_NUMBER 15 + +/* Flash attributes.*/ +#define RP_HAS_FLASH TRUE + +/* PWM attributes.*/ +#define RP_HAS_PWM TRUE +#define RP_PWM_NUM_SLICES 8 +#define RP_HAS_PWM0 TRUE +#define RP_HAS_PWM1 TRUE +#define RP_HAS_PWM2 TRUE +#define RP_HAS_PWM3 TRUE +#define RP_HAS_PWM4 TRUE +#define RP_HAS_PWM5 TRUE +#define RP_HAS_PWM6 TRUE +#define RP_HAS_PWM7 TRUE +#define RP_HAS_PWM8 FALSE +#define RP_HAS_PWM9 FALSE +#define RP_HAS_PWM10 FALSE +#define RP_HAS_PWM11 FALSE + +/* ADC attributes.*/ +#define RP_HAS_ADC TRUE +#define RP_ADC_NUM_CHANNELS 5U +#define RP_ADC_HAS_TEMPERATURE_SENSOR TRUE +#define RP_ADC_TEMPERATURE_CHANNEL 4U +#define RP_ADC_FIFO_DEPTH 4U +#define RP_ADC_BASE_PIN 26U +#define RP_ADC_DREQ 36U +#define RP_ADC_AINSEL_BITS 3U +#define RP_ADC_RROBIN_MASK 0x001F0000U /** @} */ diff --git a/os/hal/ports/RP/RP2040/rp_xosc.c b/os/hal/ports/RP/RP2040/rp_xosc.c new file mode 100644 index 0000000000..a660004480 --- /dev/null +++ b/os/hal/ports/RP/RP2040/rp_xosc.c @@ -0,0 +1,89 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2040/rp_xosc.c + * @brief RP2040 XOSC source. + * + * @addtogroup RP_XOSC + * @{ + */ + +#include "hal.h" +#include "hal_safety.h" +#include "rp_xosc.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/** + * @brief Timeout for XOSC stabilization in microseconds. + * @note Crystal startup typically takes 1-2 ms. We allow up to 100 ms + * to account for slow crystals and ROSC timing variance. + */ +#define RP_XOSC_STABLE_TIMEOUT_US 100000U + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the XOSC + * @note Assumes 1-15 MHz crystal is attached. + * @note See RP2040 Datasheet 2.16 XOSC + */ +void rp_xosc_init(void) { + + /* Set frequency range */ + XOSC->CTRL = XOSC_CTRL_FREQ_RANGE_1_15MHZ; + + /* Set startup delay */ + XOSC->STARTUP = RP_XOSC_STARTUP_DELAY; + + /* Enable the XOSC */ + XOSC->SET.CTRL = XOSC_CTRL_ENABLE_ENABLE; + + /* Wait for XOSC to be stable with timeout protection. */ + if (halRegWaitAnySet32X((volatile uint32_t *)&XOSC->STATUS, XOSC_STATUS_STABLE, + RP_XOSC_STABLE_TIMEOUT_US, NULL)) { + halSftFail("XOSC stable timeout"); + } +} + +/** + * @brief Disable the XOSC + * @pre The XOSC must not be the current source for CLK_REF. + */ +void rp_xosc_disable(void) { + + /* Disable XOSC */ + XOSC->XOR.CTRL = (XOSC->CTRL ^ XOSC_CTRL_ENABLE_DISABLE) & XOSC_CTRL_ENABLE_Msk; +} + +/** @} */ diff --git a/os/hal/ports/RP/RP2040/rp_xosc.h b/os/hal/ports/RP/RP2040/rp_xosc.h new file mode 100644 index 0000000000..3793831228 --- /dev/null +++ b/os/hal/ports/RP/RP2040/rp_xosc.h @@ -0,0 +1,80 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2040/rp_xosc.h + * @brief RP2040 XOSC header. + * + * @addtogroup RP_XOSC + * @{ + */ + +#ifndef RP_XOSC_H +#define RP_XOSC_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief XOSC startup delay multiplier. + * @note Default value of 6 matches the pico-sdk default, giving extra + * margin for slow-starting crystals on power-up. + */ +#if !defined(RP_XOSC_STARTUP_DELAY_MULTIPLIER) +#define RP_XOSC_STARTUP_DELAY_MULTIPLIER 6U +#endif + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/** + * @brief XOSC startup delay value. + * @note Delay is in multiples of 256 crystal periods + * For 12MHz, each count is ~21.3us. Default gives 1ms startup. + */ +#define RP_XOSC_STARTUP_DELAY \ + ((((RP_XOSCCLK / 1000U) + 128U) / 256U) * RP_XOSC_STARTUP_DELAY_MULTIPLIER) + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void rp_xosc_init(void); + void rp_xosc_disable(void); +#ifdef __cplusplus +} +#endif + +#endif /* RP_XOSC_H */ + +/** @} */ diff --git a/os/hal/ports/RP/RP2350/hal_efl_lld.c b/os/hal/ports/RP/RP2350/hal_efl_lld.c new file mode 100644 index 0000000000..5e7a63b82d --- /dev/null +++ b/os/hal/ports/RP/RP2350/hal_efl_lld.c @@ -0,0 +1,600 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2350/hal_efl_lld.c + * @brief RP2350 Embedded Flash subsystem low level driver source. + * @note This is a self-contained flash driver that directly manipulates + * the QMI peripheral. + * + * @addtogroup HAL_EFL + * @{ + */ + +#include + +#include "hal.h" +#include "rp_efl_lld.h" + +#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/** + * @brief Macro to place functions in RAM. + */ +#define RAMFUNC __attribute__((noinline, section(".ramtext"))) + +/* QMI DIRECT_CSR and DIRECT_TX bit definitions are in rp2350.h. */ + +/** + * @name XIP cache constants + * @{ + */ +#define RP_XIP_MAINTENANCE_BASE 0x18000000U +#define RP_XIP_CACHE_LINE_SIZE 8U +#define RP_XIP_CACHE_SIZE (16U * 1024U) +#define RP_XIP_ADDRESS_SPACE_SIZE 0x04000000U +#define RP_XIP_SET_WAY_BASE (RP_XIP_ADDRESS_SPACE_SIZE - RP_XIP_CACHE_SIZE) +/** @} */ + +/** + * @name XIP cache maintenance operations + * @{ + */ +#define RP_XIP_CACHE_INVALIDATE_BY_SET_WAY 0U +#define RP_XIP_CACHE_CLEAN_BY_SET_WAY 1U +/** @} */ + +/** + * @name Standard JEDEC Flash commands + * @{ + */ +#define FLASHCMD_WRITE_ENABLE 0x06U +#define FLASHCMD_READ_STATUS 0x05U +#define FLASHCMD_PAGE_PROGRAM 0x02U +#define FLASHCMD_SECTOR_ERASE 0x20U +#define FLASHCMD_BLOCK_ERASE_32K 0x52U +#define FLASHCMD_BLOCK_ERASE_64K 0xD8U +#define FLASHCMD_READ_UNIQUE_ID 0x4BU +/** @} */ + +/** + * @name Flash status register bits + * @{ + */ +#define FLASH_STATUS_BUSY (1U << 0) +#define FLASH_STATUS_WEL (1U << 1) +/** @} */ + +/** + * @name Page alignment + * @{ + */ +#define RP_FLASH_PAGE_MASK (RP_FLASH_PAGE_SIZE - 1U) +/** @} */ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief EFL1 driver identifier. + * @note EFLD1.ssi is statically initialized to allow use before hal init + */ +EFlashDriver EFLD1 = { + .qmi = QMI +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Force chip select high or low + * @note This function MUST be in RAM. + * + * @param[in] eflp pointer to the EFlashDriver object + * @param[in] high true for CS high (deassert), false for CS low (assert) + */ +RAMFUNC static void rp_flash_cs_force(EFlashDriver *eflp, bool high) { + QMI_TypeDef *qmi = eflp->qmi; + + if (high) { + qmi->DIRECT_CSR &= ~QMI_DIRECT_CSR_ASSERT_CS0N; + } else { + qmi->DIRECT_CSR |= QMI_DIRECT_CSR_ASSERT_CS0N; + } + + /* Read back to ensure write is flushed */ + (void)qmi->DIRECT_CSR; +} + +/** + * @brief Transfer data to/from flash + * @note This function MUST be in RAM. + * + * @param[in] eflp pointer to the EFlashDriver object + * @param[in] tx transmit buffer (NULL to send zeros) + * @param[out] rx receive buffer (NULL to discard) + * @param[in] count number of bytes to transfer + */ +RAMFUNC static void rp_flash_put_get(EFlashDriver *eflp, const uint8_t *tx, + uint8_t *rx, size_t count) { + QMI_TypeDef *qmi = eflp->qmi; + size_t tx_remaining = count; + size_t rx_remaining = count; + + while ((tx_remaining > 0U) || (rx_remaining > 0U)) { + uint32_t csr = qmi->DIRECT_CSR; + + /* Send if TX FIFO not full and data remaining. */ + if ((tx_remaining > 0U) && ((csr & QMI_DIRECT_CSR_TXFULL) == 0U)) { + uint8_t data = (tx != NULL) ? *tx++ : 0U; + qmi->DIRECT_TX = data; + tx_remaining--; + } + + if ((rx_remaining > 0U) && ((csr & QMI_DIRECT_CSR_RXEMPTY) == 0U)) { + uint8_t data = (uint8_t)qmi->DIRECT_RX; + if (rx != NULL) { + *rx++ = data; + } + rx_remaining--; + } + } +} + +/** + * @brief Execute a flash command. + * @note This function MUST be in RAM. + * + * @param[in] eflp pointer to the EFlashDriver object + * @param[in] cmd command byte + * @param[in] tx transmit data after command (NULL if none) + * @param[out] rx receive buffer (NULL to discard) + * @param[in] count number of bytes to transfer after command + */ +RAMFUNC static void rp_flash_do_cmd(EFlashDriver *eflp, uint8_t cmd, + const uint8_t *tx, uint8_t *rx, + size_t count) { + QMI_TypeDef *qmi = eflp->qmi; + + /* Assert CS. */ + rp_flash_cs_force(eflp, false); + + /* Send command byte. */ + qmi->DIRECT_TX = cmd; + while ((qmi->DIRECT_CSR & QMI_DIRECT_CSR_RXEMPTY) != 0U) { + } + (void)qmi->DIRECT_RX; + + /* Transfer remaining data. */ + if (count > 0U) { + rp_flash_put_get(eflp, tx, rx, count); + } + + /* Deassert CS. */ + rp_flash_cs_force(eflp, true); +} + +/** + * @brief Wait for flash to become ready. + * @note This function MUST be in RAM. + * + * @param[in] eflp pointer to the EFlashDriver object + */ +RAMFUNC static void rp_flash_wait_ready(EFlashDriver *eflp) { + uint8_t status; + + do { + rp_flash_do_cmd(eflp, FLASHCMD_READ_STATUS, NULL, &status, 1U); + } while ((status & FLASH_STATUS_BUSY) != 0U); +} + +/** + * @brief Send write enable command. + * @note This function MUST be in RAM. + * + * @param[in] eflp pointer to the EFlashDriver object + */ +RAMFUNC static void rp_flash_write_enable(EFlashDriver *eflp) { + + rp_flash_do_cmd(eflp, FLASHCMD_WRITE_ENABLE, NULL, NULL, 0U); +} + +/** + * @brief Flush XIP cache and restore cache policy. + * @note This function MUST be in RAM. + */ +RAMFUNC static void rp_flash_flush_cache(EFlashDriver *eflp) { + volatile uint8_t *maint = (volatile uint8_t *)RP_XIP_MAINTENANCE_BASE; + XIP_CTRL_TypeDef *xip_ctrl = XIP_CTRL; + uint32_t offset; + + for (offset = RP_XIP_SET_WAY_BASE; + offset < RP_XIP_ADDRESS_SPACE_SIZE; + offset += RP_XIP_CACHE_LINE_SIZE) { +#if RP_EFL_HAS_PSRAM == TRUE + /* + * Write back dirty PSRAM (CS1) cache lines before invalidating. + * The XIP cache is shared between CS0 (flash, read-only) and + * CS1 (PSRAM, write-back). Without this clean step, cached + * PSRAM writes would be lost on invalidation. + * + * The clean and invalidate must be adjacent per-line: clean-by- + * set/way corrupts the cache tag, so a cleaned-but-not-yet- + * invalidated line can cause spurious cache hits. + */ + maint[offset + RP_XIP_CACHE_CLEAN_BY_SET_WAY] = 0U; + __DSB(); +#endif + maint[offset + RP_XIP_CACHE_INVALIDATE_BY_SET_WAY] = 0U; + } + + __DSB(); + __ISB(); + + /* Restore the saved cache policy after maintenance. */ + xip_ctrl->CTRL = eflp->xip_ctrl; +} + +/** + * @brief Exit XIP mode and configure for direct access. + * @note This function MUST be in RAM. + * @note This follows a similar pattern to the ROM's flash_exit_xip() + * + * @param[in] eflp pointer to the EFlashDriver object + */ +RAMFUNC static void rp_flash_exit_xip(EFlashDriver *eflp) { + QMI_TypeDef *qmi = eflp->qmi; + XIP_CTRL_TypeDef *xip_ctrl = XIP_CTRL; + PADS_QSPI_TypeDef *pads_qspi = PADS_QSPI; + uint32_t padctrl_save; + uint32_t padctrl_tmp; + unsigned i; + volatile unsigned delay; + + /* Save current XIP configuration (CS0 and CS1) before switching + * to direct mode. */ + eflp->xip_ctrl = xip_ctrl->CTRL; + eflp->xip_timing = qmi->M0_TIMING; + eflp->xip_rfmt = qmi->M0_RFMT; + eflp->xip_rcmd = qmi->M0_RCMD; + eflp->xip_m1_timing = qmi->M1_TIMING; + eflp->xip_m1_rfmt = qmi->M1_RFMT; + eflp->xip_m1_rcmd = qmi->M1_RCMD; + eflp->xip_m1_wfmt = qmi->M1_WFMT; + eflp->xip_m1_wcmd = qmi->M1_WCMD; + + /* Wait for any pending work.*/ + while ((qmi->DIRECT_CSR & QMI_DIRECT_CSR_BUSY) != 0U) { + } + + /* Default non XIP SPI configuration */ + qmi->DIRECT_CSR = QMI_DIRECT_CSR_EN | QMI_DIRECT_CSR_CLKDIV(6U); + + /* + * Exit continuous read / QPI mode sequence: + * 1. CS high 32 clocks with IO pulled down + * 2. CS low 32 clocks with IO pulled up + * 3. F5h QPI exit in quad width, 16x NOP ones, FFh QPI exit in quad width + */ + + /* Save pad control and configure with output disabled.*/ + padctrl_save = pads_qspi->GPIO_QSPI_SD0; + padctrl_tmp = (padctrl_save & ~(PADS_QSPI_OD | PADS_QSPI_PUE | + PADS_QSPI_PDE)) + | PADS_QSPI_OD | PADS_QSPI_PDE; + + /* 1. CS high */ + rp_flash_cs_force(eflp, true); + + pads_qspi->GPIO_QSPI_SD0 = padctrl_tmp; + pads_qspi->GPIO_QSPI_SD1 = padctrl_tmp; + pads_qspi->GPIO_QSPI_SD2 = padctrl_tmp; + pads_qspi->GPIO_QSPI_SD3 = padctrl_tmp; + + /* Delay of ~6000 cycles */ + for (delay = 0U; delay < 2048U; delay++) { + } + + /* Send 4 bytes / 32 clocks */ + for (i = 0U; i < 4U; i++) { + qmi->DIRECT_TX = 0U; + while ((qmi->DIRECT_CSR & QMI_DIRECT_CSR_RXEMPTY) != 0U) { + } + (void)qmi->DIRECT_RX; + } + + padctrl_tmp = (padctrl_tmp & ~PADS_QSPI_PDE) | PADS_QSPI_PUE; + + /* 2. CS low */ + rp_flash_cs_force(eflp, false); + + pads_qspi->GPIO_QSPI_SD0 = padctrl_tmp; + pads_qspi->GPIO_QSPI_SD1 = padctrl_tmp; + pads_qspi->GPIO_QSPI_SD2 = padctrl_tmp; + pads_qspi->GPIO_QSPI_SD3 = padctrl_tmp; + + /* Delay of ~6000 cycles */ + for (delay = 0U; delay < 2048U; delay++) { + } + + /* Send 4 bytes / 32 clocks */ + for (i = 0U; i < 4U; i++) { + qmi->DIRECT_TX = 0U; + while ((qmi->DIRECT_CSR & QMI_DIRECT_CSR_RXEMPTY) != 0U) { + } + (void)qmi->DIRECT_RX; + } + + /* Restore pad controls. */ + pads_qspi->GPIO_QSPI_SD0 = padctrl_save; + pads_qspi->GPIO_QSPI_SD1 = padctrl_save; + padctrl_save = (padctrl_save & ~PADS_QSPI_PDE) | PADS_QSPI_PUE; + pads_qspi->GPIO_QSPI_SD2 = padctrl_save; + pads_qspi->GPIO_QSPI_SD3 = padctrl_save; + + /* 3. QPI exit: F5h in quad width on CS0. Exits flash chips that use + * this command to leave QPI mode (e.g. some Winbond, ISSI parts). + * PSRAM on CS1 is unaffected — its CS is not asserted here and its + * QPI state is preserved across the flash operation via M1 + * save/restore. */ + rp_flash_cs_force(eflp, false); + qmi->DIRECT_TX = 0xF5U | QMI_DIRECT_TX_IWIDTH(QMI_DIRECT_TX_IWIDTH_Q) | + QMI_DIRECT_TX_OE | QMI_DIRECT_TX_NOPUSH; + while ((qmi->DIRECT_CSR & QMI_DIRECT_CSR_BUSY) != 0U) { + } + rp_flash_cs_force(eflp, true); + + /* Continuous-read recovery: CSn=0, MOSI=1, all other IOs Hi-Z, 16 + * clocks in single-width (Hardware Design with RP2350: Section 3.3, + * RP2350 Datasheet: 5.4.8.7). Exits devices stuck in continuous-read + * mode; QPI exit is handled separately by the FFh quad command below. */ + rp_flash_cs_force(eflp, false); + for (i = 0U; i < 2U; i++) { + while ((qmi->DIRECT_CSR & QMI_DIRECT_CSR_TXFULL) != 0U) { + } + qmi->DIRECT_TX = 0xFFU | QMI_DIRECT_TX_NOPUSH; + } + while ((qmi->DIRECT_CSR & QMI_DIRECT_CSR_BUSY) != 0U) { + } + rp_flash_cs_force(eflp, true); + + /* QPI exit: FFh in quad width (catches devices that ignore F5h). */ + rp_flash_cs_force(eflp, false); + qmi->DIRECT_TX = 0xFFU | QMI_DIRECT_TX_IWIDTH(QMI_DIRECT_TX_IWIDTH_Q) | + QMI_DIRECT_TX_OE | QMI_DIRECT_TX_NOPUSH; + while ((qmi->DIRECT_CSR & QMI_DIRECT_CSR_BUSY) != 0U) { + } + rp_flash_cs_force(eflp, true); +} + +/** + * @brief Enter XIP mode + * @note This function MUST be in RAM. + * @note Restores the XIP configuration that was saved when exit_xip + * was called, preserving whatever mode the bootrom configured + * (e.g. QSPI fast read). + * + * @param[in] eflp pointer to the EFlashDriver object + */ +RAMFUNC static void rp_flash_enter_xip(EFlashDriver *eflp) { + QMI_TypeDef *qmi = eflp->qmi; + + /* Wait for transfers to complete */ + while ((qmi->DIRECT_CSR & QMI_DIRECT_CSR_BUSY) != 0U) { + } + + /* Disable direct mode and restore saved XIP configuration (CS0 and CS1). */ + qmi->DIRECT_CSR = 0U; + qmi->M0_TIMING = eflp->xip_timing; + qmi->M0_RFMT = eflp->xip_rfmt; + qmi->M0_RCMD = eflp->xip_rcmd; + qmi->M1_TIMING = eflp->xip_m1_timing; + qmi->M1_RFMT = eflp->xip_m1_rfmt; + qmi->M1_RCMD = eflp->xip_m1_rcmd; + qmi->M1_WFMT = eflp->xip_m1_wfmt; + qmi->M1_WCMD = eflp->xip_m1_wcmd; + + rp_flash_flush_cache(eflp); +} + +/** + * @brief Program a page of flash. + * @note This function MUST be in RAM. + * + * @param[in] eflp pointer to the EFlashDriver object + * @param[in] offset flash offset (must be page-aligned or within page) + * @param[in] data data to program + * @param[in] len number of bytes (must not cross page boundary) + */ +RAMFUNC static void rp_flash_program_page(EFlashDriver *eflp, uint32_t offset, + const uint8_t *data, size_t len) { + QMI_TypeDef *qmi = eflp->qmi; + uint8_t addr[3]; + + /* Send write enable. */ + rp_flash_write_enable(eflp); + + /* Prepare 24-bit address (big-endian). */ + addr[0] = (uint8_t)(offset >> 16); + addr[1] = (uint8_t)(offset >> 8); + addr[2] = (uint8_t)offset; + + /* Assert CS. */ + rp_flash_cs_force(eflp, false); + + /* Send page program command. */ + qmi->DIRECT_TX = FLASHCMD_PAGE_PROGRAM; + while ((qmi->DIRECT_CSR & QMI_DIRECT_CSR_RXEMPTY) != 0U) { + } + (void)qmi->DIRECT_RX; + + /* Send address. */ + rp_flash_put_get(eflp, addr, NULL, 3U); + + /* Send data. */ + rp_flash_put_get(eflp, data, NULL, len); + + /* Deassert CS. */ + rp_flash_cs_force(eflp, true); + + /* Wait for program to complete. */ + rp_flash_wait_ready(eflp); +} + +/** + * @brief Send an erase command to flash. + * @note This function MUST be in RAM. + * + * @param[in] eflp pointer to the EFlashDriver object + * @param[in] cmd JEDEC erase command byte + * @param[in] offset flash offset (must be aligned to erase unit) + */ +RAMFUNC static void rp_flash_erase_cmd(EFlashDriver *eflp, uint8_t cmd, + uint32_t offset) { + uint8_t addr[3]; + + /* Send write enable. */ + rp_flash_write_enable(eflp); + + /* Prepare 24-bit address (big-endian). */ + addr[0] = (uint8_t)(offset >> 16); + addr[1] = (uint8_t)(offset >> 8); + addr[2] = (uint8_t)offset; + + /* Send erase command with address. */ + rp_flash_do_cmd(eflp, cmd, addr, NULL, 3U); +} + +/** + * @brief Complete erase operation (runs entirely in RAM). + * @note This function MUST be in RAM. It handles the entire sequence + * from exit XIP to enter XIP so no flash code executes while + * XIP is disabled. + * + * @param[in] eflp pointer to the EFlashDriver object + * @param[in] cmd JEDEC erase command byte + * @param[in] offset flash offset (must be aligned to erase unit) + */ +RAMFUNC static void rp_flash_erase_full(EFlashDriver *eflp, uint8_t cmd, + uint32_t offset) { + + /* Exit XIP mode. */ + rp_flash_exit_xip(eflp); + + /* Send erase command. */ + rp_flash_erase_cmd(eflp, cmd, offset); + + /* Wait for erase to complete. */ + rp_flash_wait_ready(eflp); + + /* Re-enter XIP mode. */ + rp_flash_enter_xip(eflp); +} + +/** + * @brief Single-page program operation that runs entirely in RAM. + * @note This function MUST be in RAM. It handles the entire sequence + * from exit XIP to enter XIP so no flash code executes while + * XIP is disabled. + * + * @param[in] eflp pointer to the EFlashDriver object + * @param[in] offset flash offset (must not cross page boundary) + * @param[in] data pointer to data in RAM + * @param[in] len number of bytes to program + */ +RAMFUNC static void rp_flash_program_page_full(EFlashDriver *eflp, + uint32_t offset, + const uint8_t *data, + size_t len) { + + /* Exit XIP mode. */ + rp_flash_exit_xip(eflp); + + /* Program the page. */ + rp_flash_program_page(eflp, offset, data, len); + + /* Re-enter XIP mode. */ + rp_flash_enter_xip(eflp); +} + +/** + * @brief Read flash unique ID (runs entirely in RAM). + * @note This function MUST be in RAM. It handles the entire sequence + * from exit XIP to enter XIP so no flash code executes while + * XIP is disabled. + * + * @param[in] eflp pointer to the EFlashDriver object + * @param[out] rx receive buffer + * @param[in] count number of bytes to transfer after command + */ +RAMFUNC static void rp_flash_read_uid_full(EFlashDriver *eflp, + uint8_t *rx, size_t count) { + + /* Exit XIP mode. */ + rp_flash_exit_xip(eflp); + + /* Send read unique ID command. */ + rp_flash_do_cmd(eflp, FLASHCMD_READ_UNIQUE_ID, NULL, rx, count); + + /* Re-enter XIP mode. */ + rp_flash_enter_xip(eflp); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +void rp_efl_lld_init(void) { + + /* Nothing to do - RP2350 uses QMI register save/restore. */ +} + +void rp_efl_lld_start(EFlashDriver *eflp) { + + (void)eflp; + + /* Nothing to do - flash is always accessible via XIP. */ +} +void rp_efl_lld_program_page_full(EFlashDriver *eflp, + uint32_t offset, + const uint8_t *data, + size_t len) { + rp_flash_program_page_full(eflp, offset, data, len); +} + +void rp_efl_lld_erase_full(EFlashDriver *eflp, uint8_t cmd, uint32_t offset) { + rp_flash_erase_full(eflp, cmd, offset); +} + +void rp_efl_lld_read_uid_full(EFlashDriver *eflp, + uint8_t *rx, + size_t count) { + rp_flash_read_uid_full(eflp, rx, count); +} + +#endif /* HAL_USE_EFL == TRUE */ + +/** @} */ diff --git a/os/hal/ports/RP/RP2350/hal_efl_lld.h b/os/hal/ports/RP/RP2350/hal_efl_lld.h new file mode 100644 index 0000000000..e08f791ae0 --- /dev/null +++ b/os/hal/ports/RP/RP2350/hal_efl_lld.h @@ -0,0 +1,215 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2350/hal_efl_lld.h + * @brief RP2350 Embedded Flash subsystem low level driver header. + * + * @addtogroup HAL_EFL + * @{ + */ + +#ifndef HAL_EFL_LLD_H +#define HAL_EFL_LLD_H + +#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Flash page size (minimum write unit). + */ +#define RP_FLASH_PAGE_SIZE 256U + +/** + * @brief Flash sector size (minimum erase unit). + */ +#define RP_FLASH_SECTOR_SIZE 4096U + +/** + * @brief Flash sector erase command (JEDEC 0x20). + */ +#define RP_FLASH_CMD_SECTOR_ERASE 0x20U + +/** + * @brief Flash 32KB block erase command (JEDEC 0x52). + */ +#define RP_FLASH_CMD_BLOCK_ERASE_32K 0x52U + +/** + * @brief Flash 64KB block erase command (JEDEC 0xD8). + */ +#define RP_FLASH_CMD_BLOCK_ERASE_64K 0xD8U + +/** + * @brief Flash 32KB block size. + */ +#define RP_FLASH_BLOCK_32K_SIZE (32U * 1024U) + +/** + * @brief Flash 64KB block size. + */ +#define RP_FLASH_BLOCK_64K_SIZE 65536U + +/** + * @brief XIP base address. + */ +#define RP_FLASH_BASE 0x10000000U + +/** + * @brief QMI base address. + */ +#define RP_QMI_BASE 0x400D0000U + +/** + * @brief XIP control base address. + */ +#define RP_XIP_CTRL_BASE 0x400C8000U + +/** + * @brief Flash unique ID size in bytes. + */ +#define RP_FLASH_UNIQUE_ID_SIZE 8U + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name RP2350 configuration options + * @{ + */ + +/** + * @brief Total flash size in bytes. + * @note Default is 4MB for standard Raspberry Pi Pico 2. + * Override in mcuconf.h for boards with different flash sizes. + */ +#if !defined(RP_FLASH_SIZE) || defined(__DOXYGEN__) +#define RP_FLASH_SIZE (4U * 1024U * 1024U) +#endif + +/** + * @brief Suggested wait time during erase operations polling. + */ +#if !defined(RP_FLASH_WAIT_TIME_MS) || defined(__DOXYGEN__) +#define RP_FLASH_WAIT_TIME_MS 1U +#endif + +/** + * @brief Enables PSRAM (CS1) cache handling in the EFL driver. + * @details When enabled, the XIP cache flush performs a clean-before- + * invalidate sequence to write back dirty PSRAM cache lines + * before invalidation. When disabled, only invalidation is + * performed (flash cache lines are never dirty). + * @note Set to @p TRUE in mcuconf.h for boards with PSRAM on QMI CS1. + * @note PSRAM must be initialized (QMI M1 registers configured, + * XIP_CTRL WRITABLE_M1 set) before the first EFL operation. + * The EFL driver saves XIP_CTRL on entry to flash operations + * and restores it on exit; if WRITABLE_M1 is not yet set at + * the time of the first save, it will be cleared on restore. + */ +#if !defined(RP_EFL_HAS_PSRAM) || defined(__DOXYGEN__) +#define RP_EFL_HAS_PSRAM FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* Registry checks for robustness. */ +#if !defined(RP_HAS_FLASH) +#error "RP_HAS_FLASH not defined in registry" +#endif + +#if RP_HAS_FLASH != TRUE +#error "RP_HAS_FLASH is not TRUE" +#endif + +/** + * @brief Number of sectors in flash. + */ +#define RP_FLASH_SECTORS_COUNT (RP_FLASH_SIZE / RP_FLASH_SECTOR_SIZE) + +/** + * @brief Number of 64KB blocks in flash. + */ +#define RP_FLASH_BLOCKS_COUNT (RP_FLASH_SIZE / RP_FLASH_BLOCK_64K_SIZE) + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +#include "rp_efl_lld.h" + +/** + * @brief Low level fields of the embedded flash driver structure. + */ +#define efl_lld_driver_fields \ + /* Pointer to QMI registers. */ \ + QMI_TypeDef *qmi; \ + /* Saved XIP control register. */ \ + uint32_t xip_ctrl; \ + /* Saved CS0 (flash) XIP configuration registers. */ \ + uint32_t xip_timing; \ + uint32_t xip_rfmt; \ + uint32_t xip_rcmd; \ + /* Saved CS1 (PSRAM) XIP configuration registers. */ \ + uint32_t xip_m1_timing; \ + uint32_t xip_m1_rfmt; \ + uint32_t xip_m1_rcmd; \ + uint32_t xip_m1_wfmt; \ + uint32_t xip_m1_wcmd; + +/** + * @brief Low level fields of the embedded flash configuration structure. + */ +#define efl_lld_config_fields \ + /* Dummy configuration, it is not needed.*/ \ + uint32_t dummy; + +/*===========================================================================*/ +/* Application hooks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#if !defined(__DOXYGEN__) +extern EFlashDriver EFLD1; +#endif +#include "rp_efl_lld_api.inc" +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_EFL == TRUE */ + +#endif /* HAL_EFL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/RP/RP2350/hal_lld.c b/os/hal/ports/RP/RP2350/hal_lld.c new file mode 100644 index 0000000000..8258f235cb --- /dev/null +++ b/os/hal/ports/RP/RP2350/hal_lld.c @@ -0,0 +1,141 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2350/hal_lld.c + * @brief RP2350 HAL subsystem low level driver source. + * @note The Core 1 launch sequence follows the multicore launch protocol + * documented in RP2350 Datasheet 3.5 "Multicore Launch". + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" +#include "rp_clocks.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief CMSIS system core clock variable. + * @note It is declared in system_rp2350.h. + */ +uint32_t SystemCoreClock = RP_CLK_SYS_FREQ; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +#if RP_CORE1_START == TRUE +static void start_core1(void) { + extern uint32_t RP_CORE1_STACK_END; + extern uint32_t RP_CORE1_VECTORS_TABLE; + extern void RP_CORE1_ENTRY_POINT(void); + static const uint32_t cmd_sequence[] = {0, 0, 1, + (uint32_t)&RP_CORE1_VECTORS_TABLE, + (uint32_t)&RP_CORE1_STACK_END, + (uint32_t)RP_CORE1_ENTRY_POINT}; + unsigned seq; + + /* Force-reset core1 via PSM before starting the FIFO launch handshake. + * + * If core1 survived a preceding soft reset (e.g. a bootloader that uses + * BX to jump to the application rather than SYSRESETREQ), it may still + * be executing application code from a previous run. In that case the + * ROM FIFO handshake protocol will deadlock: core0 sends the sync + * sequence but core1 is not in the ROM wait-for-launch loop so it never + * echoes back. + * + * PSM FRCE_OFF holds core1 in reset (powered-off state). Clearing it + * releases core1 into the ROM boot-path which immediately enters the + * wait-for-launch loop. The PSM DONE bit falls while the core is held + * off, and rises again once it has been released and is running.*/ + PSM->SET.FRCE_OFF = PSM_ANY_PROC1; /* assert reset to core1 */ + while (PSM->DONE & PSM_ANY_PROC1) {} /* wait until it powers off */ + PSM->CLR.FRCE_OFF = PSM_ANY_PROC1; /* release — core1 enters ROM */ + + /* Starting core 1.*/ + seq = 0; + do { + uint32_t response; + uint32_t cmd = cmd_sequence[seq]; + + /* Flushing the FIFO state before sending a zero.*/ + if (!cmd) { + fifoFlushRead(); + } + fifoBlockingWrite(cmd); + response = fifoBlockingRead(); + /* Checking response, going forward or back to first step.*/ + seq = cmd == response ? seq + 1U : 0U; + } while (seq < 6U); +} +#endif + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level HAL driver initialization. + * + * @notapi + */ +void hal_lld_init(void) { + +#if RP_NO_INIT == FALSE + rp_peripheral_unreset(RESETS_ALLREG_BUSCTRL); + rp_peripheral_unreset(RESETS_ALLREG_SYSINFO); + rp_peripheral_unreset(RESETS_ALLREG_SYSCFG); +#endif /* RP_NO_INIT */ + + /* NVIC initialization.*/ + nvicInit(); + + /* IRQ subsystem initialization.*/ + irqInit(); +#if defined(RP_DMA_REQUIRED) + dmaInit(); +#endif +#if defined(RP_PIO_REQUIRED) + pioInit(); +#endif + + /* Bind the system timer IRQ to this core for tickless mode. */ +#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING + stBind(); +#endif + +#if RP_CORE1_START == TRUE + start_core1(); +#endif +} + +/** @} */ diff --git a/os/hal/ports/RP/RP2350/hal_lld.h b/os/hal/ports/RP/RP2350/hal_lld.h new file mode 100644 index 0000000000..18ffa1c165 --- /dev/null +++ b/os/hal/ports/RP/RP2350/hal_lld.h @@ -0,0 +1,322 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2350/hal_lld.h + * @brief RP2350 HAL subsystem low level driver header. + * + * @addtogroup HAL + * @{ + */ + +#ifndef HAL_LLD_H +#define HAL_LLD_H + +/* + * Registry definitions. + */ +#include "rp_registry.h" +#include "rp_clocks.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Platform identification macros + * @{ + */ +#if defined(RP2350) || defined(__DOXYGEN__) +#define PLATFORM_NAME "RP2350" + +#else +#error "RP2350 device not specified" +#endif +/** @} */ + +/** + * @name Internal clock sources + * @{ + */ +#define RP_ROSCCLK 6500000 /**< 6.5MHz internal clock. */ +/** @} */ + +/** + * @name GPIO IOCTRL register field positions + * @{ + */ +#define RP_GPIO_IOCTRL_OEOVER_Pos 14 +#define RP_GPIO_IOCTRL_OUTOVER_Pos 12 +/** @} */ + +/** + * @brief Dynamic clock supported. + */ +#define HAL_LLD_USE_CLOCK_MANAGEMENT + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief Disables the clocks initialization in the HAL. + */ +#if !defined(RP_NO_INIT) || defined(__DOXYGEN__) +#define RP_NO_INIT FALSE +#endif + +/** + * @brief Starts core 1 after initialization. + */ +#if !defined(RP_CORE1_START) || defined(__DOXYGEN__) +#define RP_CORE1_START FALSE +#endif + +/** + * @brief Symbol for core 1 vectors table. + */ +#if !defined(RP_CORE1_VECTORS_TABLE) || defined(__DOXYGEN__) +#define RP_CORE1_VECTORS_TABLE _vectors +#endif + +/** + * @brief Symbol for core 1 entry point. + */ +#if !defined(RP_CORE1_ENTRY_POINT) || defined(__DOXYGEN__) +#define RP_CORE1_ENTRY_POINT _crt0_c1_entry +#endif + +/** + * @brief Symbol for core 1 initial MSP position. + */ +#if !defined(RP_CORE1_STACK_END) || defined(__DOXYGEN__) +#define RP_CORE1_STACK_END __c1_main_stack_end__ +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* + * Configuration-related checks. + */ +#if !defined(RP2350_MCUCONF) +#error "Using a wrong mcuconf.h file, RP2350_MCUCONF not defined" +#endif + +/* + * Board files sanity checks. + */ +#if !defined(RP_XOSCCLK) +#error "RP_XOSCCLK not defined in board.h" +#endif + +#if (RP_XOSCCLK < 1000000) || (RP_XOSCCLK > 15000000) +#error "RP_XOSCCLK out of valid range (1-15 MHz)" +#endif + +/* + * PLL_SYS configuration checks. + */ +#if (RP_PLL_SYS_REFDIV < 1) || (RP_PLL_SYS_REFDIV > 63) +#error "RP_PLL_SYS_REFDIV out of valid range (1-63)" +#endif + +#if (RP_PLL_SYS_VCO_FREQ < RP_PLL_VCO_MIN_FREQ) || \ + (RP_PLL_SYS_VCO_FREQ > RP_PLL_VCO_MAX_FREQ) +#error "RP_PLL_SYS_VCO_FREQ out of valid range (750-1600 MHz)" +#endif + +#if (RP_PLL_SYS_POSTDIV1 < 1) || (RP_PLL_SYS_POSTDIV1 > 7) +#error "RP_PLL_SYS_POSTDIV1 out of valid range (1-7)" +#endif + +#if (RP_PLL_SYS_POSTDIV2 < 1) || (RP_PLL_SYS_POSTDIV2 > 7) +#error "RP_PLL_SYS_POSTDIV2 out of valid range (1-7)" +#endif + +#if RP_PLL_SYS_POSTDIV1 < RP_PLL_SYS_POSTDIV2 +#error "RP_PLL_SYS_POSTDIV1 must be >= RP_PLL_SYS_POSTDIV2" +#endif + +/* + * PLL_USB configuration checks. + */ +#if (RP_PLL_USB_REFDIV < 1) || (RP_PLL_USB_REFDIV > 63) +#error "RP_PLL_USB_REFDIV out of valid range (1-63)" +#endif + +#if (RP_PLL_USB_VCO_FREQ < RP_PLL_VCO_MIN_FREQ) || \ + (RP_PLL_USB_VCO_FREQ > RP_PLL_VCO_MAX_FREQ) +#error "RP_PLL_USB_VCO_FREQ out of valid range (750-1600 MHz)" +#endif + +#if (RP_PLL_USB_POSTDIV1 < 1) || (RP_PLL_USB_POSTDIV1 > 7) +#error "RP_PLL_USB_POSTDIV1 out of valid range (1-7)" +#endif + +#if (RP_PLL_USB_POSTDIV2 < 1) || (RP_PLL_USB_POSTDIV2 > 7) +#error "RP_PLL_USB_POSTDIV2 out of valid range (1-7)" +#endif + +#if RP_PLL_USB_POSTDIV1 < RP_PLL_USB_POSTDIV2 +#error "RP_PLL_USB_POSTDIV1 must be >= RP_PLL_USB_POSTDIV2" +#endif + +#if RP_PLL_USB_CLK != 48000000 +#error "RP_PLL_USB_CLK must be 48 MHz for USB to work" +#endif + +/** + * @name Various clock points. + * @{ + */ +#define RP_GPOUT0_CLK hal_lld_get_clock_point(RP_CLK_GPOUT0) +#define RP_GPOUT1_CLK hal_lld_get_clock_point(RP_CLK_GPOUT1) +#define RP_GPOUT2_CLK hal_lld_get_clock_point(RP_CLK_GPOUT2) +#define RP_GPOUT3_CLK hal_lld_get_clock_point(RP_CLK_GPOUT3) +#define RP_REF_CLK hal_lld_get_clock_point(RP_CLK_REF) +#define RP_CORE_CLK hal_lld_get_clock_point(RP_CLK_SYS) +#define RP_PERI_CLK hal_lld_get_clock_point(RP_CLK_PERI) +#define RP_HSTX_CLK hal_lld_get_clock_point(RP_CLK_HSTX) +#define RP_USB_CLK hal_lld_get_clock_point(RP_CLK_USB) +#define RP_ADC_CLK hal_lld_get_clock_point(RP_CLK_ADC) +/** @} */ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +#if defined(HAL_LLD_USE_CLOCK_MANAGEMENT) || defined(__DOXYGEN__) +/** + * @brief Type of a clock configuration structure. + */ +typedef struct { + uint32_t dummy; +} halclkcfg_t; +#endif /* defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Safety module counter support + * @note Uses TIMER0 peripheral which counts at 1 us resolution. + * During early clock init, accuracy depends on ROSC variance. + * After clock init completes, timing is precise. + * @{ + */ + +/** + * @brief Counter type for safety timeouts. + */ +typedef uint32_t halcnt_t; + +/** + * @brief Returns the counter frequency in Hz. + * @note Always returns 1 MHz (1 us ticks). + */ +#define HAL_LLD_GET_CNT_FREQUENCY() 1000000U + +/** + * @brief Returns the current counter value. + */ +#define HAL_LLD_GET_CNT_VALUE() ((halcnt_t)TIMER0->TIMERAWL) + +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* Various helpers.*/ +#include "nvic.h" +#include "cache.h" +#include "rp_isr.h" +#include "rp_fifo.h" +#include "rp_dma.h" +#include "rp_pio.h" +#include "rp_bootrom.h" + +#ifdef __cplusplus +extern "C" { +#endif + void hal_lld_init(void); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Driver inline functions. */ +/*===========================================================================*/ + +__STATIC_INLINE void rp_peripheral_reset(uint32_t mask) { + + RESETS->SET.RESET = mask; +} + +__STATIC_INLINE void rp_peripheral_unreset(uint32_t mask) { + + RESETS->CLR.RESET = mask; + while ((RESETS->RESET_DONE & mask) != mask) { + /* Waiting for peripheral to come out of reset */ + } +} + +#if defined(HAL_LLD_USE_CLOCK_MANAGEMENT) || defined(__DOXYGEN__) +/** + * @brief Switches to a different clock configuration + * + * @param[in] ccp pointer to clock a @p halclkcfg_t structure + * @return The clock switch result. + * @retval false if the clock switch succeeded + * @retval true if the clock switch failed + * + * @notapi + */ +__STATIC_INLINE bool hal_lld_clock_switch_mode(const halclkcfg_t *ccp) { + + (void)ccp; + + return false; +} + +/** + * @brief Returns the frequency of a clock point in Hz. + * + * @param[in] clkpt clock point to be returned + * @return The clock point frequency in Hz or zero if the + * frequency is unknown. + * + * @notapi + */ +__STATIC_INLINE halfreq_t hal_lld_get_clock_point(halclkpt_t clkpt) { + + osalDbgAssert(clkpt < RP_CLK_COUNT, "invalid clock point"); + + return rp_clock_get_hz(clkpt); +} +#endif /* defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ + +#endif /* HAL_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/RP/RP2350/platform.mk b/os/hal/ports/RP/RP2350/platform.mk new file mode 100644 index 0000000000..f0b6de539b --- /dev/null +++ b/os/hal/ports/RP/RP2350/platform.mk @@ -0,0 +1,52 @@ +# Required platform files. +PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \ + $(CHIBIOS)/os/hal/ports/RP/rp_bootrom.c \ + $(CHIBIOS)/os/hal/ports/RP/RP2350/rp_clocks.c \ + $(CHIBIOS)/os/hal/ports/RP/RP2350/rp_isr.c \ + $(CHIBIOS)/os/hal/ports/RP/RP2350/rp_pll.c \ + $(CHIBIOS)/os/hal/ports/RP/RP2350/rp_xosc.c \ + $(CHIBIOS)/os/hal/ports/RP/RP2350/hal_lld.c + +# Required include directories. +PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \ + $(CHIBIOS)/os/hal/ports/RP/RP2350 \ + $(CHIBIOS)/os/hal/ports/RP + +# Optional platform files. +ifeq ($(USE_SMART_BUILD),yes) + +# Configuration files directory +ifeq ($(HALCONFDIR),) + ifeq ($(CONFDIR),) + HALCONFDIR = . + else + HALCONFDIR := $(CONFDIR) + endif +endif + +HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define")) + +ifneq ($(findstring HAL_USE_EFL TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/RP/RP2350/hal_efl_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/RP/RP2350/hal_efl_lld.c +endif + +# Drivers compatible with the platform. +include $(CHIBIOS)/os/hal/ports/RP/LLD/EFLv1/driver.mk +include $(CHIBIOS)/os/hal/ports/RP/LLD/DMAv1/driver.mk +include $(CHIBIOS)/os/hal/ports/RP/LLD/PIOv1/driver.mk +include $(CHIBIOS)/os/hal/ports/RP/LLD/GPIOv1/driver.mk +include $(CHIBIOS)/os/hal/ports/RP/LLD/SPIv1/driver.mk +include $(CHIBIOS)/os/hal/ports/RP/LLD/TIMERv1/driver.mk +include $(CHIBIOS)/os/hal/ports/RP/LLD/UARTv1/driver.mk +include $(CHIBIOS)/os/hal/ports/RP/LLD/WDGv1/driver.mk +include $(CHIBIOS)/os/hal/ports/RP/LLD/USBv1/driver.mk +include $(CHIBIOS)/os/hal/ports/RP/LLD/I2Cv1/driver.mk +include $(CHIBIOS)/os/hal/ports/RP/LLD/PWMv1/driver.mk +include $(CHIBIOS)/os/hal/ports/RP/LLD/ADCv1/driver.mk + +# Shared variables +ALLCSRC += $(PLATFORMSRC) +ALLINC += $(PLATFORMINC) diff --git a/os/hal/ports/RP/RP2350/rp_clocks.c b/os/hal/ports/RP/RP2350/rp_clocks.c new file mode 100644 index 0000000000..dadfd381dc --- /dev/null +++ b/os/hal/ports/RP/RP2350/rp_clocks.c @@ -0,0 +1,182 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2350/rp_clocks.c + * @brief RP2350 clock driver source. + * @note See RP2350 Datasheet 8 Clocks + * + * @addtogroup RP_CLOCKS + * @{ + */ + +#include "hal.h" +#include "rp_clocks.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/** + * @brief Estimated ROSC frequency for early timing. + * @note RP2350 ROSC varies 4.6-19.6 MHz, we assume ~6 MHz. + * This gives roughly +/-60% accuracy which is acceptable for + * safety timeouts during early clock initialization. + */ +#define RP_ROSC_ASSUMED_HZ 6000000U + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes all clocks. + * @note Most of this is derived from the RP2350 datasheet which directly + * references suggested code from the Pico SDK which is Copyright + * 2020 Raspberry Pi (Trading) Ltd and licensed under the + * BSD-3-Clause license. We always start with ROSC and then switch + * to XOSC. + * @note See RP2350 Datasheet 8.1.3.1 Clock Instances (Table 541) + */ +void rp_clock_init(void) { + + /* Start early tick generator for safety module timeouts. */ + rp_peripheral_unreset(RESETS_ALLREG_TIMER0); + + /* Configure tick generator for ~1 us ticks. */ + TICKS->TICK[TICKS_TIMER0].CYCLES = RP_ROSC_ASSUMED_HZ / 1000000U;; + TICKS->TICK[TICKS_TIMER0].CTRL = TICKS_CTRL_ENABLE; + + /* Clear clock resus that may be in an unkown state */ + CLOCKS->RESUS.CTRL = 0U; + + rp_xosc_init(); + + /* Switch clk_sys and clk_ref to safe sources */ + CLOCKS->CLR.CLK[RP_CLK_SYS].CTRL = CLOCKS_CLK_SYS_CTRL_SRC_Msk; + while ((CLOCKS->CLK[RP_CLK_SYS].SELECTED & 1U) == 0U) { + /* Wait for clk_sys to switch to clk_ref */ + } + CLOCKS->CLR.CLK[RP_CLK_REF].CTRL = CLOCKS_CLK_REF_CTRL_SRC_Msk; + while ((CLOCKS->CLK[RP_CLK_REF].SELECTED & 1U) == 0U) { + /* Wait for clk_ref to switch to ROSC */ + } + + /* Initialize PLL_SYS: 12 MHz * 125 / 5 / 2 = 150 MHz. */ + rp_pll_init(PLL_SYS, RP_PLL_SYS_REFDIV, RP_PLL_SYS_VCO_FREQ, + RP_PLL_SYS_POSTDIV1, RP_PLL_SYS_POSTDIV2); + + /* Initialize PLL_USB: 12 MHz * 100 / 5 / 5 = 48 MHz. */ + rp_pll_init(PLL_USB, RP_PLL_USB_REFDIV, RP_PLL_USB_VCO_FREQ, + RP_PLL_USB_POSTDIV1, RP_PLL_USB_POSTDIV2); + + /* CLK_REF = XOSC = 12 MHz */ + { + uint32_t src = CLOCKS_CLK_REF_CTRL_SRC_XOSC >> CLOCKS_CLK_REF_CTRL_SRC_Pos; + CLOCKS->CLK[RP_CLK_REF].DIV = 1U << 16; + CLOCKS->XOR.CLK[RP_CLK_REF].CTRL = + (CLOCKS->CLK[RP_CLK_REF].CTRL ^ (src << CLOCKS_CLK_REF_CTRL_SRC_Pos)) & + CLOCKS_CLK_REF_CTRL_SRC_Msk; + while ((CLOCKS->CLK[RP_CLK_REF].SELECTED & (1U << src)) == 0U) { + /* Wait for switch to XOSC */ + } + } + + /* CLK_SYS = PLL_SYS = 150 MHz */ + CLOCKS->CLR.CLK[RP_CLK_SYS].CTRL = CLOCKS_CLK_SYS_CTRL_SRC_Msk; + while ((CLOCKS->CLK[RP_CLK_SYS].SELECTED & 1U) == 0U) { + /* Wait for switch to clk_ref */ + } + CLOCKS->XOR.CLK[RP_CLK_SYS].CTRL = + (CLOCKS->CLK[RP_CLK_SYS].CTRL ^ CLOCKS_CLK_SYS_CTRL_AUXSRC_PLL_SYS) & + CLOCKS_CLK_SYS_CTRL_AUXSRC_Msk; + CLOCKS->SET.CLK[RP_CLK_SYS].CTRL = CLOCKS_CLK_SYS_CTRL_SRC_AUX; + while ((CLOCKS->CLK[RP_CLK_SYS].SELECTED & 2U) == 0U) { + /* Wait for switch to aux */ + } + + /* CLK_USB = PLL_USB = 48 MHz */ + CLOCKS->XOR.CLK[RP_CLK_USB].CTRL = + (CLOCKS->CLK[RP_CLK_USB].CTRL ^ CLOCKS_CLK_USB_CTRL_AUXSRC_PLL_USB) & + CLOCKS_CLK_USB_CTRL_AUXSRC_Msk; + CLOCKS->CLK[RP_CLK_USB].DIV = 1U << 16; + CLOCKS->SET.CLK[RP_CLK_USB].CTRL = CLOCKS_CLK_PERI_CTRL_ENABLE; + + /* CLK_ADC = PLL_USB = 48 MHz */ + CLOCKS->XOR.CLK[RP_CLK_ADC].CTRL = + (CLOCKS->CLK[RP_CLK_ADC].CTRL ^ CLOCKS_CLK_ADC_CTRL_AUXSRC_PLL_USB) & + CLOCKS_CLK_ADC_CTRL_AUXSRC_Msk; + CLOCKS->CLK[RP_CLK_ADC].DIV = 1U << 16; + CLOCKS->SET.CLK[RP_CLK_ADC].CTRL = CLOCKS_CLK_PERI_CTRL_ENABLE; + + /* CLK_PERI = CLK_SYS = 150 MHz */ + CLOCKS->XOR.CLK[RP_CLK_PERI].CTRL = + (CLOCKS->CLK[RP_CLK_PERI].CTRL ^ CLOCKS_CLK_PERI_CTRL_AUXSRC_SYS) & + CLOCKS_CLK_PERI_CTRL_AUXSRC_Msk; + CLOCKS->CLK[RP_CLK_PERI].DIV = 1U << 16; + CLOCKS->SET.CLK[RP_CLK_PERI].CTRL = CLOCKS_CLK_PERI_CTRL_ENABLE; + + /* Calculate cycles for 1us tick based on clk_ref frequency. */ + uint32_t cycles = RP_XOSCCLK / 1000000U; + + /* Start tick generators */ + for (uint32_t i = 0U; i < 6U; i++) { + TICKS->TICK[i].CYCLES = cycles; + TICKS->TICK[i].CTRL = TICKS_CTRL_ENABLE; + } +} + +/** + * @brief Returns the frequency of a clock in Hz. + * @note Uses compile-time constants so this function is safe to call + * before BSS/DATA initialization. + * + * @param[in] clk_index clock index (RP_CLK_xxx) + * @return clock frequency in Hz + */ +uint32_t rp_clock_get_hz(uint32_t clk_index) { + + osalDbgAssert(clk_index < RP_CLK_COUNT, "invalid clock index"); + + switch (clk_index) { + case RP_CLK_REF: + return RP_CLK_REF_FREQ; + case RP_CLK_SYS: + return RP_CLK_SYS_FREQ; + case RP_CLK_PERI: + return RP_CLK_PERI_FREQ; + case RP_CLK_USB: + return RP_CLK_USB_FREQ; + case RP_CLK_ADC: + return RP_CLK_ADC_FREQ; + default: + return 0U; + } +} + +/** @} */ diff --git a/os/hal/ports/RP/RP2350/rp_clocks.h b/os/hal/ports/RP/RP2350/rp_clocks.h new file mode 100644 index 0000000000..5078c340c9 --- /dev/null +++ b/os/hal/ports/RP/RP2350/rp_clocks.h @@ -0,0 +1,155 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2350/rp_clocks.h + * @brief RP2350 clocks header. + * + * @addtogroup RP_CLOCKS + * @{ + */ + +#ifndef RP_CLOCKS_H +#define RP_CLOCKS_H + +#include "rp_xosc.h" +#include "rp_pll.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name PLL_SYS configuration + * @note Default configuration produces 150 MHz system clock + * @{ + */ +#if !defined(RP_PLL_SYS_REFDIV) || defined(__DOXYGEN__) +#define RP_PLL_SYS_REFDIV 1U +#endif +#if !defined(RP_PLL_SYS_VCO_FREQ) || defined(__DOXYGEN__) +#define RP_PLL_SYS_VCO_FREQ 1500000000U /* 1500 MHz VCO */ +#endif +#if !defined(RP_PLL_SYS_POSTDIV1) || defined(__DOXYGEN__) +#define RP_PLL_SYS_POSTDIV1 5U /* 150 MHz output */ +#endif +#if !defined(RP_PLL_SYS_POSTDIV2) || defined(__DOXYGEN__) +#define RP_PLL_SYS_POSTDIV2 2U +#endif +/** @} */ + +/** + * @name PLL_USB configuration + * @{ + */ +#if !defined(RP_PLL_USB_REFDIV) || defined(__DOXYGEN__) +#define RP_PLL_USB_REFDIV 1U +#endif +#if !defined(RP_PLL_USB_VCO_FREQ) || defined(__DOXYGEN__) +#define RP_PLL_USB_VCO_FREQ 1200000000U /* 1200 MHz VCO */ +#endif +#if !defined(RP_PLL_USB_POSTDIV1) || defined(__DOXYGEN__) +#define RP_PLL_USB_POSTDIV1 5U +#endif +#if !defined(RP_PLL_USB_POSTDIV2) || defined(__DOXYGEN__) +#define RP_PLL_USB_POSTDIV2 5U +#endif +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/** + * @name PLL output frequencies + * @{ + */ +/** + * @brief PLL_SYS output frequency in Hz. + */ +#define RP_PLL_SYS_CLK (RP_PLL_SYS_VCO_FREQ / \ + (RP_PLL_SYS_POSTDIV1 * \ + RP_PLL_SYS_POSTDIV2)) + +/** + * @brief PLL_USB output frequency in Hz (must be 48 MHz for USB). + */ +#define RP_PLL_USB_CLK (RP_PLL_USB_VCO_FREQ / \ + (RP_PLL_USB_POSTDIV1 * \ + RP_PLL_USB_POSTDIV2)) +/** @} */ + +/** + * @name Compile-time clock frequencies + * @note These are compile-time constants derived from PLL configuration. + * For runtime clock queries, use the hal_lld_get_clock_point() API. + * @{ + */ +/** + * @brief System core clock frequency in Hz. + */ +#define RP_CLK_SYS_FREQ RP_PLL_SYS_CLK + +/** + * @brief Reference clock frequency in Hz. + */ +#define RP_CLK_REF_FREQ RP_XOSCCLK + +/** + * @brief Peripheral clock frequency in Hz. + * @note CLK_PERI runs at CLK_SYS frequency by default. + */ +#define RP_CLK_PERI_FREQ RP_PLL_SYS_CLK + +/** + * @brief USB clock frequency in Hz (must be 48 MHz). + */ +#define RP_CLK_USB_FREQ RP_PLL_USB_CLK + +/** + * @brief ADC clock frequency in Hz (must be 48 MHz). + */ +#define RP_CLK_ADC_FREQ RP_PLL_USB_CLK +/** @} */ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void rp_clock_init(void); + uint32_t rp_clock_get_hz(uint32_t clk_index); +#ifdef __cplusplus +} +#endif + +#endif /* RP_CLOCKS_H */ + +/** @} */ diff --git a/os/hal/ports/RP/RP2350/rp_fifo.h b/os/hal/ports/RP/RP2350/rp_fifo.h new file mode 100644 index 0000000000..2ed431c3be --- /dev/null +++ b/os/hal/ports/RP/RP2350/rp_fifo.h @@ -0,0 +1,114 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2350/rp_fifo.h + * @brief RP2350 FIFO handler header. + * + * @addtogroup RP2350_FIFO + * @{ + */ + +#ifndef RP_FIFO_H +#define RP_FIFO_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* EInline functions. */ +/*===========================================================================*/ + +__STATIC_INLINE bool fifoIsReadNotEmpty(void) { + + return (bool)((SIO->FIFO_ST & SIO_FIFO_ST_VLD) != 0U); +} + +__STATIC_INLINE bool fifoIsWriteNotFull(void) { + + return (bool)((SIO->FIFO_ST & SIO_FIFO_ST_RDY) != 0U); +} + +__STATIC_INLINE void fifoFlushRead(void) { + + while (fifoIsReadNotEmpty()) { + (void)SIO->FIFO_RD; + } + + /* In case the other core is in WFE.*/ + __SEV(); +} + +__STATIC_INLINE void fifoBlockingWrite(uint32_t data) { + + /* Waiting for space into the FIFO.*/ + while (!fifoIsWriteNotFull()) { + __WFE(); + } + + SIO->FIFO_WR = data; + + /* In case the other core is in WFE, signaling data available.*/ + __SEV(); +} + +__STATIC_INLINE uint32_t fifoBlockingRead(void) { + uint32_t data; + + /* Waiting for data to appear.*/ + while (!fifoIsReadNotEmpty()) { + __WFE(); + } + + data = SIO->FIFO_RD; + + /* In case the other core is in WFE, signaling space available.*/ + __SEV(); + + return data; +} + +#endif /* RP_FIFO_H */ + +/** @} */ diff --git a/os/hal/ports/RP/RP2350/rp_isr.c b/os/hal/ports/RP/RP2350/rp_isr.c new file mode 100644 index 0000000000..ccba44a384 --- /dev/null +++ b/os/hal/ports/RP/RP2350/rp_isr.c @@ -0,0 +1,74 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2350/rp_isr.c + * @brief RP2350 ISR handler code. + * + * @addtogroup RP2350_ISR + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#include "rp_uart0.inc" +#include "rp_uart1.inc" + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief IRQ subsystem initialization. + * @details Puts the IRQ controller in a known clean state before any + * HAL drivers enable their individual interrupts. + * + * @notapi + */ +void irqInit(void) { + +} + +/** + * @brief Disables IRQ sources. + * + * @notapi + */ +void irqDeinit(void) { + +} + +/** @} */ diff --git a/os/hal/ports/RP/RP2350/rp_isr.h b/os/hal/ports/RP/RP2350/rp_isr.h new file mode 100644 index 0000000000..6b4baf9eb1 --- /dev/null +++ b/os/hal/ports/RP/RP2350/rp_isr.h @@ -0,0 +1,213 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2350/rp_isr.h + * @brief RP2350 ISR handler header. + * + * @addtogroup RP2350_ISR + * @{ + */ + +#ifndef RP_ISR_H +#define RP_ISR_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name ISR names and numbers + * @{ + */ + +/* TIMER0 interrupts (4 alarms) */ +#define RP_TIMER0_IRQ0_HANDLER Vector40 +#define RP_TIMER0_IRQ1_HANDLER Vector44 +#define RP_TIMER0_IRQ2_HANDLER Vector48 +#define RP_TIMER0_IRQ3_HANDLER Vector4C + +/* TIMER1 interrupts (4 alarms) */ +#define RP_TIMER1_IRQ0_HANDLER Vector50 +#define RP_TIMER1_IRQ1_HANDLER Vector54 +#define RP_TIMER1_IRQ2_HANDLER Vector58 +#define RP_TIMER1_IRQ3_HANDLER Vector5C + +/* PWM interrupts */ +#define RP_PWM_IRQ_WRAP_0_HANDLER Vector60 +#define RP_PWM_IRQ_WRAP_1_HANDLER Vector64 + +/* DMA interrupts */ +#define RP_DMA_IRQ_0_HANDLER Vector68 +#define RP_DMA_IRQ_1_HANDLER Vector6C +#define RP_DMA_IRQ_2_HANDLER Vector70 +#define RP_DMA_IRQ_3_HANDLER Vector74 + +/* USB interrupt */ +#define RP_USBCTRL_IRQ_HANDLER Vector78 + +/* PIO interrupts */ +#define RP_PIO0_IRQ_0_HANDLER Vector7C +#define RP_PIO0_IRQ_1_HANDLER Vector80 +#define RP_PIO1_IRQ_0_HANDLER Vector84 +#define RP_PIO1_IRQ_1_HANDLER Vector88 +#define RP_PIO2_IRQ_0_HANDLER Vector8C +#define RP_PIO2_IRQ_1_HANDLER Vector90 + +/* IO Bank interrupts */ +#define RP_IO_IRQ_BANK0_HANDLER Vector94 +#define RP_IO_IRQ_BANK0_NS_HANDLER Vector98 +#define RP_IO_IRQ_QSPI_HANDLER Vector9C +#define RP_IO_IRQ_QSPI_NS_HANDLER VectorA0 + +/* SIO interrupts */ +#define RP_SIO_IRQ_FIFO_HANDLER VectorA4 +#define RP_SIO_IRQ_BELL_HANDLER VectorA8 +#define RP_SIO_IRQ_FIFO_NS_HANDLER VectorAC +#define RP_SIO_IRQ_BELL_NS_HANDLER VectorB0 +#define RP_SIO_IRQ_MTIMECMP_HANDLER VectorB4 + +/* Clocks interrupt */ +#define RP_CLOCKS_IRQ_HANDLER VectorB8 + +/* SPI interrupts */ +#define RP_SPI0_IRQ_HANDLER VectorBC +#define RP_SPI1_IRQ_HANDLER VectorC0 + +/* UART interrupts */ +#define RP_UART0_IRQ_HANDLER VectorC4 +#define RP_UART1_IRQ_HANDLER VectorC8 + +/* ADC interrupt */ +#define RP_ADC_IRQ_FIFO_HANDLER VectorCC + +/* I2C interrupts */ +#define RP_I2C0_IRQ_HANDLER VectorD0 +#define RP_I2C1_IRQ_HANDLER VectorD4 + +/* OTP interrupt */ +#define RP_OTP_IRQ_HANDLER VectorD8 + +/* TRNG interrupt */ +#define RP_TRNG_IRQ_HANDLER VectorDC + +/* CTI interrupts */ +#define RP_PROC0_IRQ_CTI_HANDLER VectorE0 +#define RP_PROC1_IRQ_CTI_HANDLER VectorE4 + +/* PLL interrupts */ +#define RP_PLL_SYS_IRQ_HANDLER VectorE8 +#define RP_PLL_USB_IRQ_HANDLER VectorEC + +/* Power manager interrupts */ +#define RP_POWMAN_IRQ_POW_HANDLER VectorF0 +#define RP_POWMAN_IRQ_TIMER_HANDLER VectorF4 + +/* Spare interrupts */ +#define RP_SPARE_IRQ_0_HANDLER VectorF8 +#define RP_SPARE_IRQ_1_HANDLER VectorFC +#define RP_SPARE_IRQ_2_HANDLER Vector100 +#define RP_SPARE_IRQ_3_HANDLER Vector104 +#define RP_SPARE_IRQ_4_HANDLER Vector108 +#define RP_SPARE_IRQ_5_HANDLER Vector10C + +/* IRQ numbers */ +#define RP_TIMER0_IRQ0_NUMBER 0 +#define RP_TIMER0_IRQ1_NUMBER 1 +#define RP_TIMER0_IRQ2_NUMBER 2 +#define RP_TIMER0_IRQ3_NUMBER 3 +#define RP_TIMER1_IRQ0_NUMBER 4 +#define RP_TIMER1_IRQ1_NUMBER 5 +#define RP_TIMER1_IRQ2_NUMBER 6 +#define RP_TIMER1_IRQ3_NUMBER 7 +#define RP_PWM_IRQ_WRAP_0_NUMBER 8 +#define RP_PWM_IRQ_WRAP_1_NUMBER 9 +#define RP_DMA_IRQ_0_NUMBER 10 +#define RP_DMA_IRQ_1_NUMBER 11 +#define RP_DMA_IRQ_2_NUMBER 12 +#define RP_DMA_IRQ_3_NUMBER 13 +#define RP_USBCTRL_IRQ_NUMBER 14 +#define RP_PIO0_IRQ_0_NUMBER 15 +#define RP_PIO0_IRQ_1_NUMBER 16 +#define RP_PIO1_IRQ_0_NUMBER 17 +#define RP_PIO1_IRQ_1_NUMBER 18 +#define RP_PIO2_IRQ_0_NUMBER 19 +#define RP_PIO2_IRQ_1_NUMBER 20 +#define RP_IO_IRQ_BANK0_NUMBER 21 +#define RP_IO_IRQ_BANK0_NS_NUMBER 22 +#define RP_IO_IRQ_QSPI_NUMBER 23 +#define RP_IO_IRQ_QSPI_NS_NUMBER 24 +#define RP_SIO_IRQ_FIFO_NUMBER 25 +#define RP_SIO_IRQ_BELL_NUMBER 26 +#define RP_SIO_IRQ_FIFO_NS_NUMBER 27 +#define RP_SIO_IRQ_BELL_NS_NUMBER 28 +#define RP_SIO_IRQ_MTIMECMP_NUMBER 29 +#define RP_CLOCKS_IRQ_NUMBER 30 +#define RP_SPI0_IRQ_NUMBER 31 +#define RP_SPI1_IRQ_NUMBER 32 +#define RP_UART0_IRQ_NUMBER 33 +#define RP_UART1_IRQ_NUMBER 34 +#define RP_ADC_IRQ_FIFO_NUMBER 35 +#define RP_I2C0_IRQ_NUMBER 36 +#define RP_I2C1_IRQ_NUMBER 37 +#define RP_OTP_IRQ_NUMBER 38 +#define RP_TRNG_IRQ_NUMBER 39 +#define RP_PROC0_IRQ_CTI_NUMBER 40 +#define RP_PROC1_IRQ_CTI_NUMBER 41 +#define RP_PLL_SYS_IRQ_NUMBER 42 +#define RP_PLL_USB_IRQ_NUMBER 43 +#define RP_POWMAN_IRQ_POW_NUMBER 44 +#define RP_POWMAN_IRQ_TIMER_NUMBER 45 +#define RP_SPARE_IRQ_0_NUMBER 46 +#define RP_SPARE_IRQ_1_NUMBER 47 +#define RP_SPARE_IRQ_2_NUMBER 48 +#define RP_SPARE_IRQ_3_NUMBER 49 +#define RP_SPARE_IRQ_4_NUMBER 50 +#define RP_SPARE_IRQ_5_NUMBER 51 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void irqInit(void); + void irqDeinit(void); +#ifdef __cplusplus +} +#endif + +#endif /* RP_ISR_H */ + +/** @} */ diff --git a/os/hal/ports/RP/RP2350/rp_pal_lld.h b/os/hal/ports/RP/RP2350/rp_pal_lld.h new file mode 100644 index 0000000000..058693596b --- /dev/null +++ b/os/hal/ports/RP/RP2350/rp_pal_lld.h @@ -0,0 +1,57 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2350/rp_pal_lld.h + * @brief RP2350-specific PAL low level driver definitions. + */ + +#ifndef RP2350_RP_PAL_LLD_H +#define RP2350_RP_PAL_LLD_H + +/** + * @name RP2350-specific alternate function selectors + * @{ + * @note Selectors above 7 are RP2350-specific and may map to pin-dependent + * signals. Refer to the RP2350 GPIO function tables when using them. + */ +#define PAL_RP_IOCTRL_FUNCSEL_PIO2 PAL_RP_IOCTRL_FUNCSEL(8U) +#define PAL_RP_IOCTRL_FUNCSEL_XIP PAL_RP_IOCTRL_FUNCSEL(9U) +#define PAL_RP_IOCTRL_FUNCSEL_USB PAL_RP_IOCTRL_FUNCSEL(10U) + +#define PAL_MODE_ALTERNATE_PIO2 (PAL_RP_IOCTRL_FUNCSEL_PIO2 | \ + PAL_RP_PAD_IE | \ + PAL_RP_PAD_SCHMITT) +#define PAL_MODE_ALTERNATE_XIP (PAL_RP_IOCTRL_FUNCSEL_XIP | \ + PAL_RP_PAD_IE | \ + PAL_RP_PAD_SCHMITT) +#define PAL_MODE_ALTERNATE_USB (PAL_RP_IOCTRL_FUNCSEL_USB | \ + PAL_RP_PAD_IE | \ + PAL_RP_PAD_SCHMITT) +/** @} */ + +/** + * @brief Access a SIO GPIO register by port. + * @details Given a register name (field of SIO) and port (0, 1), produce a + * reference to the correct GPIO register for the port. On the RP2350 + * every "hi" register immediately follows the "low" register. + * + * @notapi + */ +#define RP_PAL_SIO_REG(reg, port) \ + ((&SIO->reg)[(port)]) + +#endif /* RP2350_RP_PAL_LLD_H */ diff --git a/os/hal/ports/RP/RP2350/rp_pll.c b/os/hal/ports/RP/RP2350/rp_pll.c new file mode 100644 index 0000000000..b77b65faf5 --- /dev/null +++ b/os/hal/ports/RP/RP2350/rp_pll.c @@ -0,0 +1,132 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2350/rp_pll.c + * @brief RP2350 PLL source. + * + * @addtogroup RP_PLL + * @{ + */ + +#include "hal.h" +#include "hal_safety.h" +#include "rp_pll.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/** + * @brief Timeout for PLL lock in microseconds. + * @note PLL lock typically takes <1 ms. We allow up to 10 ms + * to account for ROSC timing variance during early init. + */ +#define RP_PLL_LOCK_TIMEOUT_US 10000U + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes a PLL. + * + * @param[in] pll pointer to PLL registers (PLL_SYS or PLL_USB) + * @param[in] refdiv reference divider (1-63) + * @param[in] vco_freq target VCO frequency in Hz (750-1600 MHz) + * @param[in] postdiv1 post divider 1 (1-7) + * @param[in] postdiv2 post divider 2 (1-7) + * + * @note Output frequency = vco_freq / (postdiv1 * postdiv2) + * @note VCO frequency = (XOSC / refdiv) * fbdiv + * @note See RP2350 Datasheet 8.6 PLL + */ +void rp_pll_init(PLL_TypeDef *pll, uint32_t refdiv, uint32_t vco_freq, + uint32_t postdiv1, uint32_t postdiv2) { + + uint32_t ref_freq = RP_XOSCCLK / refdiv; + uint32_t fbdiv = vco_freq / ref_freq; + uint32_t pdiv = PLL_PRIM_POSTDIV1(postdiv1) | PLL_PRIM_POSTDIV2(postdiv2); + + osalDbgAssert(vco_freq >= RP_PLL_VCO_MIN_FREQ && + vco_freq <= RP_PLL_VCO_MAX_FREQ, + "VCO frequency out of range"); + osalDbgAssert(fbdiv >= 16U && fbdiv <= 320U, "FBDIV out of range"); + osalDbgAssert(postdiv1 >= 1U && postdiv1 <= 7U, "POSTDIV1 out of range"); + osalDbgAssert(postdiv2 >= 1U && postdiv2 <= 7U, "POSTDIV2 out of range"); + osalDbgAssert(ref_freq <= (vco_freq / 16U), "Reference frequency too high"); + + /* Check if PLL is already configured */ + if ((pll->CS & PLL_CS_LOCK) && + (refdiv == (pll->CS & PLL_CS_REFDIV_Msk)) && + (fbdiv == (pll->FBDIV_INT & PLL_FBDIV_INT_Msk)) && + (pdiv == (pll->PRIM & (PLL_PRIM_POSTDIV1_Msk | PLL_PRIM_POSTDIV2_Msk)))) { + return; + } + + /* Reset the PLL */ + if (pll == PLL_SYS) { + rp_peripheral_reset(RESETS_ALLREG_PLL_SYS); + rp_peripheral_unreset(RESETS_ALLREG_PLL_SYS); + } else { + rp_peripheral_reset(RESETS_ALLREG_PLL_USB); + rp_peripheral_unreset(RESETS_ALLREG_PLL_USB); + } + + /* Set VCO divider */ + pll->CS = refdiv; + pll->FBDIV_INT = fbdiv; + + /* Turn on PLL */ + pll->CLR.PWR = PLL_PWR_PD | PLL_PWR_VCOPD; + + /* Wait for PLL lock */ + if (halRegWaitAnySet32X(&pll->CS, PLL_CS_LOCK, + RP_PLL_LOCK_TIMEOUT_US, NULL)) { + halSftFail("PLL lock timeout"); + } + + /* Set post divider */ + pll->PRIM = pdiv; + + /* Turn on post divider */ + pll->CLR.PWR = PLL_PWR_POSTDIVPD; +} + +/** + * @brief Deinitialize a PLL. + * + * @param[in] pll pointer to PLL register + */ +void rp_pll_deinit(PLL_TypeDef *pll) { + + /* Power down the PLL */ + pll->PWR = PLL_PWR_PD | PLL_PWR_VCOPD | PLL_PWR_POSTDIVPD | PLL_PWR_DSMPD; +} + +/** @} */ diff --git a/os/hal/ports/RP/RP2350/rp_pll.h b/os/hal/ports/RP/RP2350/rp_pll.h new file mode 100644 index 0000000000..84a33fe207 --- /dev/null +++ b/os/hal/ports/RP/RP2350/rp_pll.h @@ -0,0 +1,74 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2350/rp_pll.h + * @brief RP2350 PLL header. + * + * @addtogroup RP_PLL + * @{ + */ + +#ifndef RP_PLL_H +#define RP_PLL_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Minimum VCO frequency in Hz. + */ +#define RP_PLL_VCO_MIN_FREQ 750000000U + +/** + * @brief Maximum VCO frequency in Hz. + */ +#define RP_PLL_VCO_MAX_FREQ 1600000000U + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void rp_pll_init(PLL_TypeDef *pll, uint32_t refdiv, uint32_t vco_freq, + uint32_t postdiv1, uint32_t postdiv2); + void rp_pll_deinit(PLL_TypeDef *pll); +#ifdef __cplusplus +} +#endif + +#endif /* RP_PLL_H */ + +/** @} */ diff --git a/os/hal/ports/RP/RP2350/rp_registry.h b/os/hal/ports/RP/RP2350/rp_registry.h new file mode 100644 index 0000000000..59318a9920 --- /dev/null +++ b/os/hal/ports/RP/RP2350/rp_registry.h @@ -0,0 +1,131 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2350/rp_registry.h + * @brief RP2350 capabilities registry. + * + * @addtogroup HAL + * @{ + */ + +#ifndef RP_REGISTRY_H +#define RP_REGISTRY_H + +/*===========================================================================*/ +/* Platform capabilities. */ +/*===========================================================================*/ + +/** + * @name RP2350 capabilities + * @{ + */ + +/*===========================================================================*/ +/* Common. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* RP2350 */ +/*===========================================================================*/ + +/* GPIO attributes.*/ +#define RP_GPIO_NUM_LINES 48 +#define RP_GPIO_INTR_REGS 6 + +/* UART attributes.*/ +#define RP_HAS_UART0 TRUE +#define RP_HAS_UART1 TRUE + +/* PIO attributes.*/ +#define RP_HAS_PIO0 TRUE +#define RP_HAS_PIO1 TRUE +#define RP_HAS_PIO2 TRUE +#define RP_PIO_NUM_BLOCKS 3 + +/* TIMER attributes.*/ +#define RP_HAS_TIMER0 TRUE +#define RP_HAS_TIMER1 TRUE +#define RP_ST_NUM_ALARMS 4 + +/* RP2350 does NOT have an RTC */ +#define RP_HAS_RTC FALSE + +/* SPI attributes.*/ +#define RP_HAS_SPI0 TRUE +#define RP_HAS_SPI1 TRUE + +/* I2C attributes.*/ +#define RP_HAS_I2C0 TRUE +#define RP_HAS_I2C1 TRUE + +/* DMA attributes.*/ +#define RP_HAS_DMA TRUE +#define RP_DMA_NUM_CHANNELS 16 + +/* WDG attributes.*/ +#define RP_HAS_WDG TRUE +#define RP_WDG_STORAGE_SIZE 32U +#define RP_PSM_WDSEL_ALL_BITS 0x1FFFFFFU +#define RP_WDG_HAS_E1_ERRATA FALSE + +/* USB attributes.*/ +#define RP_HAS_USB TRUE +#define USB_ENDPOINTS_NUMBER 15 + +/* Flash attributes.*/ +#define RP_HAS_FLASH TRUE + +#define RP_HAS_HSTX TRUE +#define RP_HAS_TRNG TRUE +#define RP_HAS_SHA256 TRUE +#define RP_HAS_OTP TRUE + +/* PWM attributes.*/ +#define RP_HAS_PWM TRUE +#define RP_PWM_NUM_SLICES 12 +#define RP_HAS_PWM0 TRUE +#define RP_HAS_PWM1 TRUE +#define RP_HAS_PWM2 TRUE +#define RP_HAS_PWM3 TRUE +#define RP_HAS_PWM4 TRUE +#define RP_HAS_PWM5 TRUE +#define RP_HAS_PWM6 TRUE +#define RP_HAS_PWM7 TRUE +#define RP_HAS_PWM8 TRUE +#define RP_HAS_PWM9 TRUE +#define RP_HAS_PWM10 TRUE +#define RP_HAS_PWM11 TRUE + +/* ADC attributes. + Note: RP2350A (QFN-60) has 5 channels (4 external + temp on ch4) + RP2350B (QFN-80) has 9 channels (8 external + temp on ch8) + Default configuration is for RP2350A (Pico 2). */ +#define RP_HAS_ADC TRUE +#define RP_ADC_NUM_CHANNELS 5U +#define RP_ADC_HAS_TEMPERATURE_SENSOR TRUE +#define RP_ADC_TEMPERATURE_CHANNEL 4U +#define RP_ADC_FIFO_DEPTH 8U +#define RP_ADC_BASE_PIN 26U +#define RP_ADC_DREQ 48U +#define RP_ADC_AINSEL_BITS 4U +#define RP_ADC_RROBIN_MASK 0x01FF0000U + +/** @} */ + +#endif /* RP_REGISTRY_H */ + +/** @} */ diff --git a/os/hal/ports/RP/RP2350/rp_xosc.c b/os/hal/ports/RP/RP2350/rp_xosc.c new file mode 100644 index 0000000000..51ae53c625 --- /dev/null +++ b/os/hal/ports/RP/RP2350/rp_xosc.c @@ -0,0 +1,89 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2350/rp_xosc.c + * @brief RP2350 XOSC source. + * + * @addtogroup RP_XOSC + * @{ + */ + +#include "hal.h" +#include "hal_safety.h" +#include "rp_xosc.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/** + * @brief Timeout for XOSC stabilization in microseconds. + * @note Crystal startup typically takes 1-2 ms. We allow up to 100 ms + * to account for slow crystals and ROSC timing variance. + */ +#define RP_XOSC_STABLE_TIMEOUT_US 100000U + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the XOSC + * @note Assumes 1-15 MHz crystal is attached. + * @note See RP2350 Datasheet 8.2 XOSC + */ +void rp_xosc_init(void) { + + /* Set frequency range */ + XOSC->CTRL = XOSC_CTRL_FREQ_RANGE_1_15MHZ; + + /* Set startup delay */ + XOSC->STARTUP = RP_XOSC_STARTUP_DELAY; + + /* Enable the XOSC */ + XOSC->SET.CTRL = XOSC_CTRL_ENABLE_ENABLE; + + /* Wait for XOSC to be stable with timeout protection. */ + if (halRegWaitAnySet32X((volatile uint32_t *)&XOSC->STATUS, XOSC_STATUS_STABLE, + RP_XOSC_STABLE_TIMEOUT_US, NULL)) { + halSftFail("XOSC stable timeout"); + } +} + +/** + * @brief Disable the XOSC + * @pre The XOSC must not be the current source for CLK_REF. + */ +void rp_xosc_disable(void) { + + /* Disable XOSC */ + XOSC->XOR.CTRL = (XOSC->CTRL ^ XOSC_CTRL_ENABLE_DISABLE) & XOSC_CTRL_ENABLE_Msk; +} + +/** @} */ diff --git a/os/hal/ports/RP/RP2350/rp_xosc.h b/os/hal/ports/RP/RP2350/rp_xosc.h new file mode 100644 index 0000000000..d86a2f04f9 --- /dev/null +++ b/os/hal/ports/RP/RP2350/rp_xosc.h @@ -0,0 +1,79 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file RP2350/rp_xosc.h + * @brief RP2350 XOSC header. + * + * @addtogroup RP_XOSC + * @{ + */ + +#ifndef RP_XOSC_H +#define RP_XOSC_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief XOSC startup delay multiplier. + * @note Default value of 1 for 12MHz crystal. + */ +#if !defined(RP_XOSC_STARTUP_DELAY_MULTIPLIER) +#define RP_XOSC_STARTUP_DELAY_MULTIPLIER 1U +#endif + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/** + * @brief XOSC startup delay value. + * @note Delay is in multiples of 256 crystal periods + * For 12MHz, each count is ~21.3us. Default gives 1ms startup. + */ +#define RP_XOSC_STARTUP_DELAY \ + ((((RP_XOSCCLK / 1000U) + 128U) / 256U) * RP_XOSC_STARTUP_DELAY_MULTIPLIER) + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void rp_xosc_init(void); + void rp_xosc_disable(void); +#ifdef __cplusplus +} +#endif + +#endif /* RP_XOSC_H */ + +/** @} */ diff --git a/os/hal/ports/RP/rp_bootrom.c b/os/hal/ports/RP/rp_bootrom.c new file mode 100644 index 0000000000..aefc8dbe4c --- /dev/null +++ b/os/hal/ports/RP/rp_bootrom.c @@ -0,0 +1,267 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file rp_bootrom.c + * @brief RP boot ROM access API implementation. + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" +#include "rp_bootrom.h" + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +#define RP_ROM_BOOTROM_FUNC_TABLE_OFFSET 0x14U + +#if defined(RP2040) +#define RP_ROM_BOOTROM_TABLE_LOOKUP_OFFSET 0x18U +#define RP_ROM_BOOTROM_DATA_TABLE_OFFSET 0x16U +#else +#define RP_ROM_BOOTROM_TABLE_LOOKUP_OFFSET 0x16U +#endif + +static inline void *rp_rom_hword_ptr(uint32_t addr) { + + return (void *)(uintptr_t)(*(uint16_t *)(uintptr_t)(addr)); +} + +typedef void *(*rp_rom_table_lookup_2040_fn_t)(uint16_t *table, uint32_t code); + +#if defined(RP2350) +typedef void *(*rp_rom_table_lookup_2350_fn_t)(uint32_t code, uint32_t mask); +typedef int (*rp_rom_reboot_fn_t)(uint32_t flags, uint32_t delay_ms, + uint32_t p0, uint32_t p1); +#endif + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +#if defined(RP2350) +static uint32_t rp_rom_func_mask_x(void) { + +#if defined(__riscv) + return RP_ROM_RT_FLAG_FUNC_RISCV; +#elif defined(PORT_KERNEL_MODE) && (PORT_KERNEL_MODE == PORT_KERNEL_MODE_GUEST) + return RP_ROM_RT_FLAG_FUNC_ARM_NONSEC; +#else + return RP_ROM_RT_FLAG_FUNC_ARM_SEC; +#endif +} +#endif + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +void *rpRomFuncLookupX(uint32_t code) { + +#if defined(RP2040) + rp_rom_table_lookup_2040_fn_t rom_table_lookup; + uint16_t *func_table; + + rom_table_lookup = + (rp_rom_table_lookup_2040_fn_t)rp_rom_hword_ptr( + RP_ROM_BOOTROM_TABLE_LOOKUP_OFFSET); + func_table = (uint16_t *)rp_rom_hword_ptr(RP_ROM_BOOTROM_FUNC_TABLE_OFFSET); + + return rom_table_lookup(func_table, code); +#else + rp_rom_table_lookup_2350_fn_t rom_table_lookup; + + rom_table_lookup = + (rp_rom_table_lookup_2350_fn_t)rp_rom_hword_ptr( + RP_ROM_BOOTROM_TABLE_LOOKUP_OFFSET); + + return rom_table_lookup(code, rp_rom_func_mask_x()); +#endif +} + +void *rpRomDataLookupX(uint32_t code) { + +#if defined(RP2040) + rp_rom_table_lookup_2040_fn_t rom_table_lookup; + uint16_t *data_table; + + rom_table_lookup = + (rp_rom_table_lookup_2040_fn_t)rp_rom_hword_ptr( + RP_ROM_BOOTROM_TABLE_LOOKUP_OFFSET); + data_table = (uint16_t *)rp_rom_hword_ptr(RP_ROM_BOOTROM_DATA_TABLE_OFFSET); + + return rom_table_lookup(data_table, code); +#else + rp_rom_table_lookup_2350_fn_t rom_table_lookup; + + rom_table_lookup = + (rp_rom_table_lookup_2350_fn_t)rp_rom_hword_ptr( + RP_ROM_BOOTROM_TABLE_LOOKUP_OFFSET); + + return rom_table_lookup(code, RP_ROM_RT_FLAG_DATA); +#endif +} + +/** + * @brief Batch-resolves ROM function codes into function pointers. + * @note The @p table array is modified in place: each entry must be + * initialized with a ROM table code (via @p RP_ROM_TABLE_CODE) + * stored in a @p uintptr_t slot. On return every entry is + * overwritten with the resolved function pointer (or zero on + * lookup failure). + * + * @param[in,out] table array of ROM codes, replaced with pointers + * @param[in] count number of entries in @p table + * @return @p true if every code resolved successfully + */ +bool rpRomFuncsLookupX(uintptr_t *table, unsigned count) { + bool ok = true; + unsigned i; + + osalDbgCheck(table != NULL); + + for (i = 0U; i < count; i++) { + table[i] = (uintptr_t)rpRomFuncLookupX((uint32_t)table[i]); + if (table[i] == 0U) { + ok = false; + } + } + + return ok; +} + +bool rpRomGetFlashApiX(rp_rom_flash_api_t *apip) { + uintptr_t table[] = { + RP_ROM_FUNC_CONNECT_INTERNAL_FLASH, + RP_ROM_FUNC_FLASH_EXIT_XIP, + RP_ROM_FUNC_FLASH_RANGE_ERASE, + RP_ROM_FUNC_FLASH_RANGE_PROGRAM, + RP_ROM_FUNC_FLASH_FLUSH_CACHE, + RP_ROM_FUNC_FLASH_ENTER_CMD_XIP + }; + bool ok; + + osalDbgCheck(apip != NULL); + + *apip = (rp_rom_flash_api_t){0}; + ok = rpRomFuncsLookupX(table, 6U); + + apip->connect_internal_flash = + (rp_rom_connect_internal_flash_fn_t)table[0]; + apip->flash_exit_xip = (rp_rom_flash_exit_xip_fn_t)table[1]; + apip->flash_range_erase = (rp_rom_flash_range_erase_fn_t)table[2]; + apip->flash_range_program = (rp_rom_flash_range_program_fn_t)table[3]; + apip->flash_flush_cache = (rp_rom_flash_flush_cache_fn_t)table[4]; + apip->flash_enter_cmd_xip = (rp_rom_flash_enter_cmd_xip_fn_t)table[5]; + + return ok; +} + +#if defined(RP2350) +int rpRomReboot(uint32_t flags, uint32_t delay_ms, + uint32_t p0, uint32_t p1) { + rp_rom_reboot_fn_t func; + + func = (rp_rom_reboot_fn_t)rpRomFuncLookupX(RP_ROM_FUNC_REBOOT); + osalDbgAssert(func != NULL, "reboot unavailable"); + + return func(flags, delay_ms, p0, p1); +} +#endif + +void __attribute__((noreturn)) rpRomResetUsbBoot( + uint32_t gpio_mask, uint32_t disable_interface_mask) { + + osalDbgAssert((gpio_mask == 0U) || + ((gpio_mask & (gpio_mask - 1U)) == 0U), + "single GPIO bit required"); + +#if defined(RP2040) + rp_rom_reset_usb_boot_fn_t func; + + func = (rp_rom_reset_usb_boot_fn_t)rpRomFuncLookupX( + RP_ROM_FUNC_RESET_USB_BOOT); + osalDbgAssert(func != NULL, "USB boot reset unavailable"); + + func(gpio_mask, disable_interface_mask); +#else + uint32_t flags = disable_interface_mask; + uint32_t gpio = 0U; + + if (gpio_mask != 0U) { + flags |= RP_ROM_BOOTSEL_GPIO_PIN_SPECIFIED; + gpio = (uint32_t)__builtin_ctz(gpio_mask); + } + + (void)rpRomReboot(RP_ROM_REBOOT2_FLAG_REBOOT_TYPE_BOOTSEL | + RP_ROM_REBOOT2_FLAG_NO_RETURN_ON_SUCCESS, + 10U, flags, gpio); +#endif + + osalSysHalt("bootrom return"); + __builtin_unreachable(); +} + +#if defined(RP2040) +bool rpRomGetMemApiX(rp_rom_mem_api_t *apip) { + uintptr_t table[] = { + RP_ROM_FUNC_MEMCPY, + RP_ROM_FUNC_MEMCPY44, + RP_ROM_FUNC_MEMSET, + RP_ROM_FUNC_MEMSET4 + }; + bool ok; + + osalDbgCheck(apip != NULL); + + *apip = (rp_rom_mem_api_t){0}; + ok = rpRomFuncsLookupX(table, 4U); + + apip->memcpy = (rp_rom_memcpy_fn_t)table[0]; + apip->memcpy44 = (rp_rom_memcpy44_fn_t)table[1]; + apip->memset = (rp_rom_memset_fn_t)table[2]; + apip->memset4 = (rp_rom_memset4_fn_t)table[3]; + + return ok; +} + +bool rpRomGetBitApiX(rp_rom_bit_api_t *apip) { + uintptr_t table[] = { + RP_ROM_FUNC_CLZ32, + RP_ROM_FUNC_CTZ32, + RP_ROM_FUNC_POPCOUNT32, + RP_ROM_FUNC_REVERSE32 + }; + bool ok; + + osalDbgCheck(apip != NULL); + + *apip = (rp_rom_bit_api_t){0}; + ok = rpRomFuncsLookupX(table, 4U); + + apip->clz32 = (rp_rom_clz32_fn_t)table[0]; + apip->ctz32 = (rp_rom_ctz32_fn_t)table[1]; + apip->popcount32 = (rp_rom_popcount32_fn_t)table[2]; + apip->reverse32 = (rp_rom_reverse32_fn_t)table[3]; + + return ok; +} +#endif + +/** @} */ diff --git a/os/hal/ports/RP/rp_bootrom.h b/os/hal/ports/RP/rp_bootrom.h new file mode 100644 index 0000000000..fe6436be14 --- /dev/null +++ b/os/hal/ports/RP/rp_bootrom.h @@ -0,0 +1,309 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file rp_bootrom.h + * @brief RP boot ROM access API header. + * + * @addtogroup HAL + * @{ + */ + +#ifndef RP_BOOTROM_H +#define RP_BOOTROM_H + +#include +#include +#include + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/** + * @brief Builds a boot ROM lookup code from two ASCII characters. + */ +#define RP_ROM_TABLE_CODE(c1, c2) \ + ((uint32_t)(c1) | ((uint32_t)(c2) << 8)) + +/** + * @name Boot ROM function codes available on RP2040 and RP2350 + * @{ + */ +#define RP_ROM_FUNC_FLASH_ENTER_CMD_XIP \ + RP_ROM_TABLE_CODE('C', 'X') +#define RP_ROM_FUNC_FLASH_EXIT_XIP \ + RP_ROM_TABLE_CODE('E', 'X') +#define RP_ROM_FUNC_FLASH_FLUSH_CACHE \ + RP_ROM_TABLE_CODE('F', 'C') +#define RP_ROM_FUNC_CONNECT_INTERNAL_FLASH \ + RP_ROM_TABLE_CODE('I', 'F') +#define RP_ROM_FUNC_FLASH_RANGE_ERASE \ + RP_ROM_TABLE_CODE('R', 'E') +#define RP_ROM_FUNC_FLASH_RANGE_PROGRAM \ + RP_ROM_TABLE_CODE('R', 'P') +/** @} */ + +/** + * @name USB BOOTSEL interface flags + * @{ + */ +#define RP_ROM_BOOTSEL_DISABLE_MSD_INTERFACE 0x01U +#define RP_ROM_BOOTSEL_DISABLE_PICOBOOT_INTERFACE 0x02U +/** @} */ + +#if defined(RP2040) || defined(__DOXYGEN__) +/** + * @name RP2040-only boot ROM function codes + * @{ + */ +#define RP_ROM_FUNC_MEMCPY44 RP_ROM_TABLE_CODE('C', '4') +#define RP_ROM_FUNC_CLZ32 RP_ROM_TABLE_CODE('L', '3') +#define RP_ROM_FUNC_MEMCPY RP_ROM_TABLE_CODE('M', 'C') +#define RP_ROM_FUNC_MEMSET RP_ROM_TABLE_CODE('M', 'S') +#define RP_ROM_FUNC_POPCOUNT32 RP_ROM_TABLE_CODE('P', '3') +#define RP_ROM_FUNC_REVERSE32 RP_ROM_TABLE_CODE('R', '3') +#define RP_ROM_FUNC_MEMSET4 RP_ROM_TABLE_CODE('S', '4') +#define RP_ROM_FUNC_CTZ32 RP_ROM_TABLE_CODE('T', '3') +#define RP_ROM_FUNC_RESET_USB_BOOT RP_ROM_TABLE_CODE('U', 'B') +#define RP_ROM_FUNC_WAIT_FOR_VECTOR RP_ROM_TABLE_CODE('W', 'V') +/** @} */ + +/** + * @name RP2040-only boot ROM data table codes + * @{ + */ +#define RP_ROM_DATA_COPYRIGHT_STRING RP_ROM_TABLE_CODE('C', 'R') +#define RP_ROM_DATA_GIT_REVISION RP_ROM_TABLE_CODE('G', 'R') +#define RP_ROM_DATA_SOFT_FLOAT_TABLE RP_ROM_TABLE_CODE('S', 'F') +#define RP_ROM_DATA_SOFT_DOUBLE_TABLE RP_ROM_TABLE_CODE('S', 'D') +#define RP_ROM_DATA_FPLIB_START RP_ROM_TABLE_CODE('F', 'S') +#define RP_ROM_DATA_FPLIB_END RP_ROM_TABLE_CODE('F', 'E') +#define RP_ROM_DATA_FLOAT_TABLE_SIZE RP_ROM_TABLE_CODE('F', 'Z') +/** @} */ +#endif + +#if defined(RP2350) || defined(__DOXYGEN__) +/** + * @name RP2350-only boot ROM function codes + * @{ + */ +#define RP_ROM_FUNC_REBOOT \ + RP_ROM_TABLE_CODE('R', 'B') +#define RP_ROM_FUNC_FLASH_OP \ + RP_ROM_TABLE_CODE('F', 'O') +#define RP_ROM_FUNC_FLASH_RUNTIME_TO_STORAGE_ADDR \ + RP_ROM_TABLE_CODE('F', 'A') +#define RP_ROM_FUNC_FLASH_RESET_ADDRESS_TRANS \ + RP_ROM_TABLE_CODE('R', 'A') +#define RP_ROM_FUNC_FLASH_SELECT_XIP_READ_MODE \ + RP_ROM_TABLE_CODE('X', 'M') +#define RP_ROM_FUNC_GET_SYS_INFO \ + RP_ROM_TABLE_CODE('G', 'S') +#define RP_ROM_FUNC_GET_PARTITION_TABLE_INFO \ + RP_ROM_TABLE_CODE('G', 'P') +#define RP_ROM_FUNC_PICK_AB_PARTITION \ + RP_ROM_TABLE_CODE('A', 'B') +#define RP_ROM_FUNC_GET_B_PARTITION \ + RP_ROM_TABLE_CODE('G', 'B') +#define RP_ROM_FUNC_GET_UF2_TARGET_PARTITION \ + RP_ROM_TABLE_CODE('G', 'U') +#define RP_ROM_FUNC_LOAD_PARTITION_TABLE \ + RP_ROM_TABLE_CODE('L', 'P') +#define RP_ROM_FUNC_OTP_ACCESS \ + RP_ROM_TABLE_CODE('O', 'A') +#define RP_ROM_FUNC_CHAIN_IMAGE \ + RP_ROM_TABLE_CODE('C', 'I') +#define RP_ROM_FUNC_EXPLICIT_BUY \ + RP_ROM_TABLE_CODE('E', 'B') +#define RP_ROM_FUNC_BOOTROM_STATE_RESET \ + RP_ROM_TABLE_CODE('S', 'R') +#define RP_ROM_FUNC_SET_BOOTROM_STACK \ + RP_ROM_TABLE_CODE('S', 'S') +#define RP_ROM_FUNC_SECURE_CALL \ + RP_ROM_TABLE_CODE('S', 'C') +#define RP_ROM_FUNC_SET_NS_API_PERMISSION \ + RP_ROM_TABLE_CODE('S', 'P') +#define RP_ROM_FUNC_SET_ROM_CALLBACK \ + RP_ROM_TABLE_CODE('R', 'C') +#define RP_ROM_FUNC_VALIDATE_NS_BUFFER \ + RP_ROM_TABLE_CODE('V', 'B') +/** @} */ + +/** + * @name RP2350-only boot ROM data table codes + * @{ + */ +#define RP_ROM_DATA_SOFTWARE_GIT_REVISION \ + RP_ROM_TABLE_CODE('G', 'R') +#define RP_ROM_DATA_FLASH_DEVINFO16_PTR \ + RP_ROM_TABLE_CODE('F', 'D') +#define RP_ROM_DATA_PARTITION_TABLE_PTR \ + RP_ROM_TABLE_CODE('P', 'T') +#define RP_ROM_DATA_SAVED_XIP_SETUP_FUNC_PTR \ + RP_ROM_TABLE_CODE('X', 'F') +/** @} */ + +/** + * @name RP2350 ROM table lookup flags + * @{ + */ +#define RP_ROM_RT_FLAG_FUNC_RISCV 0x0001U +#define RP_ROM_RT_FLAG_FUNC_RISCV_FAR 0x0003U +#define RP_ROM_RT_FLAG_FUNC_ARM_SEC 0x0004U +#define RP_ROM_RT_FLAG_FUNC_ARM_NONSEC 0x0010U +#define RP_ROM_RT_FLAG_DATA 0x0040U +/** @} */ + +/** + * @name RP2350 reboot flags + * @{ + */ +#define RP_ROM_REBOOT2_FLAG_REBOOT_TYPE_NORMAL 0x00U +#define RP_ROM_REBOOT2_FLAG_REBOOT_TYPE_BOOTSEL 0x02U +#define RP_ROM_REBOOT2_FLAG_REBOOT_TYPE_RAM_IMAGE 0x03U +#define RP_ROM_REBOOT2_FLAG_REBOOT_TYPE_FLASH_UPDATE 0x04U +#define RP_ROM_REBOOT2_FLAG_REBOOT_TYPE_PC_SP 0x0DU +#define RP_ROM_REBOOT2_FLAG_REBOOT_TO_ARM 0x10U +#define RP_ROM_REBOOT2_FLAG_REBOOT_TO_RISCV 0x20U +#define RP_ROM_REBOOT2_FLAG_NO_RETURN_ON_SUCCESS 0x100U +/** @} */ + +/** + * @name RP2350 BOOTSEL flags + * @{ + */ +#define RP_ROM_BOOTSEL_GPIO_PIN_ACTIVE_LOW 0x10U +#define RP_ROM_BOOTSEL_GPIO_PIN_SPECIFIED 0x20U +/** @} */ + +/** + * @name RP2350 boot ROM error codes + * @{ + */ +#define RP_ROM_OK 0 +#define RP_ROM_ERROR_NOT_PERMITTED (-4) +#define RP_ROM_ERROR_INVALID_ARG (-5) +#define RP_ROM_ERROR_INVALID_ADDRESS (-10) +#define RP_ROM_ERROR_BAD_ALIGNMENT (-11) +#define RP_ROM_ERROR_INVALID_STATE (-12) +#define RP_ROM_ERROR_BUFFER_TOO_SMALL (-13) +#define RP_ROM_ERROR_PRECONDITION_NOT_MET (-14) +#define RP_ROM_ERROR_MODIFIED_DATA (-15) +#define RP_ROM_ERROR_INVALID_DATA (-16) +#define RP_ROM_ERROR_NOT_FOUND (-17) +#define RP_ROM_ERROR_UNSUPPORTED_MODIFICATION (-18) +#define RP_ROM_ERROR_LOCK_REQUIRED (-19) +/** @} */ +#endif + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +#if !defined(__ASSEMBLER__) + +typedef void (*rp_rom_connect_internal_flash_fn_t)(void); +typedef void (*rp_rom_flash_exit_xip_fn_t)(void); +typedef void (*rp_rom_flash_range_erase_fn_t)(uint32_t offset, + size_t count, + uint32_t block_size, + uint8_t block_cmd); +typedef void (*rp_rom_flash_range_program_fn_t)(uint32_t offset, + const uint8_t *data, + size_t count); +typedef void (*rp_rom_flash_flush_cache_fn_t)(void); +typedef void (*rp_rom_flash_enter_cmd_xip_fn_t)(void); +typedef void __attribute__((noreturn)) (*rp_rom_reset_usb_boot_fn_t)( + uint32_t gpio_mask, uint32_t disable_interface_mask); + +/** + * @brief Shared RP flash helper functions exported by the boot ROM. + */ +typedef struct { + rp_rom_connect_internal_flash_fn_t connect_internal_flash; + rp_rom_flash_exit_xip_fn_t flash_exit_xip; + rp_rom_flash_range_erase_fn_t flash_range_erase; + rp_rom_flash_range_program_fn_t flash_range_program; + rp_rom_flash_flush_cache_fn_t flash_flush_cache; + rp_rom_flash_enter_cmd_xip_fn_t flash_enter_cmd_xip; +} rp_rom_flash_api_t; + +#if defined(RP2040) || defined(__DOXYGEN__) +typedef uint32_t (*rp_rom_clz32_fn_t)(uint32_t value); +typedef uint32_t (*rp_rom_ctz32_fn_t)(uint32_t value); +typedef uint32_t (*rp_rom_popcount32_fn_t)(uint32_t value); +typedef uint32_t (*rp_rom_reverse32_fn_t)(uint32_t value); +typedef void *(*rp_rom_memcpy_fn_t)(void *dest, const void *src, size_t n); +typedef uint32_t *(*rp_rom_memcpy44_fn_t)(uint32_t *dest, + const uint32_t *src, + uint32_t n); +typedef void *(*rp_rom_memset_fn_t)(void *dest, int c, size_t n); +typedef uint32_t *(*rp_rom_memset4_fn_t)(uint32_t *dest, + uint8_t value, + uint32_t n); + +/** + * @brief RP2040 memory helper functions exported by the boot ROM. + */ +typedef struct { + rp_rom_memcpy_fn_t memcpy; + rp_rom_memcpy44_fn_t memcpy44; + rp_rom_memset_fn_t memset; + rp_rom_memset4_fn_t memset4; +} rp_rom_mem_api_t; + +/** + * @brief RP2040 bit helper functions exported by the boot ROM. + */ +typedef struct { + rp_rom_clz32_fn_t clz32; + rp_rom_ctz32_fn_t ctz32; + rp_rom_popcount32_fn_t popcount32; + rp_rom_reverse32_fn_t reverse32; +} rp_rom_bit_api_t; +#endif + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void *rpRomFuncLookupX(uint32_t code); + void *rpRomDataLookupX(uint32_t code); + bool rpRomFuncsLookupX(uintptr_t *table, unsigned count); + bool rpRomGetFlashApiX(rp_rom_flash_api_t *apip); + void __attribute__((noreturn)) rpRomResetUsbBoot( + uint32_t gpio_mask, uint32_t disable_interface_mask); +#if defined(RP2350) || defined(__DOXYGEN__) + int rpRomReboot(uint32_t flags, uint32_t delay_ms, + uint32_t p0, uint32_t p1); +#endif +#if defined(RP2040) || defined(__DOXYGEN__) + bool rpRomGetMemApiX(rp_rom_mem_api_t *apip); + bool rpRomGetBitApiX(rp_rom_bit_api_t *apip); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* !__ASSEMBLER__ */ + +#endif /* RP_BOOTROM_H */ + +/** @} */ diff --git a/os/hal/ports/common/ARMCMx/mpu_v8m.h b/os/hal/ports/common/ARMCMx/mpu_v8m.h new file mode 100644 index 0000000000..cc5994fe89 --- /dev/null +++ b/os/hal/ports/common/ARMCMx/mpu_v8m.h @@ -0,0 +1,247 @@ +/* + ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file ARMv8-M/mpu.h + * @brief ARMv8-M MPU support macros and structures. + * + * @addtogroup ARMV8M_MPU + * @{ + */ + +#ifndef MPU_V8M_H +#define MPU_V8M_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name MPU registers definitions + * @{ + */ +#define MPU_TYPE_SEPARATED (1U << 0) +#define MPU_TYPE_DREGION(n) (((n) >> 8) & 255U) + +#define MPU_CTRL_ENABLE (1U << 0) +#define MPU_CTRL_HFNMIENA (1U << 1) +#define MPU_CTRL_PRIVDEFENA (1U << 2) + +#define MPU_RNR_REGION_MASK (255U << 0) +#define MPU_RNR_REGION(n) ((n) << 0) + +#define MPU_RBAR_XN (1U << 0) +#define MPU_RBAR_AP_MASK (3U << 1) +#define MPU_RBAR_AP(n) ((n) << 1) +#define MPU_RBAR_AP_RW_RO MPU_RBAR_AP(0U) +#define MPU_RBAR_AP_RW_RW MPU_RBAR_AP(1U) +#define MPU_RBAR_AP_RO_NA MPU_RBAR_AP(2U) +#define MPU_RBAR_AP_RO_RO MPU_RBAR_AP(3U) +#define MPU_RBAR_SH_MASK (3U << 3) +#define MPU_RBAR_SH(n) ((n) << 3) +#define MPU_RBAR_SH_NO MPU_RBAR_SH(0U) +#define MPU_RBAR_SH_OUTER MPU_RBAR_SH(2U) +#define MPU_RBAR_SH_INNER MPU_RBAR_SH(3U) +#define MPU_RBAR_BASE_MASK 0xFFFFFFE0U +#define MPU_RBAR_BASE(n) ((n) & MPU_RBAR_BASE_MASK) + +#define MPU_RLAR_ENABLE (1U << 0) +#define MPU_RLAR_ATTRINDX_MASK (7U << 1) +#define MPU_RLAR_ATTRINDX(n) ((n) << 1) +#define MPU_RLAR_LIMIT_MASK 0xFFFFFFE0U +#define MPU_RLAR_LIMIT(n) ((n) & MPU_RLAR_LIMIT_MASK) + +#define MPU_MAIR0_ATTR0_MASK ((uint32_t)0xFFU << 0) +#define MPU_MAIR0_ATTR0(n) ((uint32_t)(n) << 0) +#define MPU_MAIR0_ATTR1_MASK ((uint32_t)0xFFU << 8) +#define MPU_MAIR0_ATTR1(n) ((uint32_t)(n) << 8) +#define MPU_MAIR0_ATTR2_MASK ((uint32_t)0xFFU << 16) +#define MPU_MAIR0_ATTR2(n) ((uint32_t)(n) << 16) +#define MPU_MAIR0_ATTR3_MASK ((uint32_t)0xFFU << 24) +#define MPU_MAIR0_ATTR3(n) ((uint32_t)(n) << 24) + +#define MPU_MAIR1_ATTR4_MASK ((uint32_t)0xFFU << 0) +#define MPU_MAIR1_ATTR4(n) ((uint32_t)(n) << 0) +#define MPU_MAIR1_ATTR5_MASK ((uint32_t)0xFFU << 8) +#define MPU_MAIR1_ATTR5(n) ((uint32_t)(n) << 8) +#define MPU_MAIR1_ATTR6_MASK ((uint32_t)0xFFU << 16) +#define MPU_MAIR1_ATTR6(n) ((uint32_t)(n) << 16) +#define MPU_MAIR1_ATTR7_MASK ((uint32_t)0xFFU << 24) +#define MPU_MAIR1_ATTR7(n) ((uint32_t)(n) << 24) +/** @} */ + +/** + * @name Attributes in MAIR registers + * @{ + */ +#define MPU_MAIR_DEVICE_nGnRnE 0x00U +#define MPU_MAIR_DEVICE_nGnRE 0x04U +#define MPU_MAIR_DEVICE_nGRE 0x08U +#define MPU_MAIR_DEVICE_GRE 0x0CU + +#define MPU_MAIR_MEM_OUTER_TRANSIENT 0x00U +#define MPU_MAIR_MEM_OUTER_NON_TRANSIENT 0x80U +#define MPU_MAIR_MEM_OUTER_WRITE_THROUGH 0x00U +#define MPU_MAIR_MEM_OUTER_WRITE_BACK 0x40U +#define MPU_MAIR_MEM_OUTER_R_ALLOCATE 0x20U +#define MPU_MAIR_MEM_OUTER_W_ALLOCATE 0x10U +#define MPU_MAIR_MEM_OUTER_RW_ALLOCATE 0x30U + +#define MPU_MAIR_MEM_INNER_TRANSIENT 0x00U +#define MPU_MAIR_MEM_INNER_NON_TRANSIENT 0x08U +#define MPU_MAIR_MEM_INNER_WRITE_THROUGH 0x00U +#define MPU_MAIR_MEM_INNER_WRITE_BACK 0x04U +#define MPU_MAIR_MEM_INNER_R_ALLOCATE 0x02U +#define MPU_MAIR_MEM_INNER_W_ALLOCATE 0x01U +#define MPU_MAIR_MEM_INNER_RW_ALLOCATE 0x03U + +#define MPU_MAIR_MEM_OUTER_WT_T_WA 0x10U +#define MPU_MAIR_MEM_OUTER_WT_T_RA 0x20U +#define MPU_MAIR_MEM_OUTER_WT_T_RWA 0x30U +#define MPU_MAIR_MEM_OUTER_NC 0x40U +#define MPU_MAIR_MEM_OUTER_WB_T_WA 0x50U +#define MPU_MAIR_MEM_OUTER_WB_T_RA 0x60U +#define MPU_MAIR_MEM_OUTER_WB_T_RWA 0x70U +#define MPU_MAIR_MEM_OUTER_RESVD1 0x80U +#define MPU_MAIR_MEM_OUTER_WT_NT_WA 0x90U +#define MPU_MAIR_MEM_OUTER_WT_NT_RA 0xA0U +#define MPU_MAIR_MEM_OUTER_WT_NT_RWA 0xB0U +#define MPU_MAIR_MEM_OUTER_RESVD2 0xC0U +#define MPU_MAIR_MEM_OUTER_WB_NT_WA 0xD0U +#define MPU_MAIR_MEM_OUTER_WB_NT_RA 0xE0U +#define MPU_MAIR_MEM_OUTER_WB_NT_RWA 0xF0U + +#define MPU_MAIR_MEM_INNER_WT_T_WA 0x01U +#define MPU_MAIR_MEM_INNER_WT_T_RA 0x02U +#define MPU_MAIR_MEM_INNER_WT_T_RWA 0x03U +#define MPU_MAIR_MEM_INNER_NC 0x04U +#define MPU_MAIR_MEM_INNER_WB_T_WA 0x05U +#define MPU_MAIR_MEM_INNER_WB_T_RA 0x06U +#define MPU_MAIR_MEM_INNER_WB_T_RWA 0x07U +#define MPU_MAIR_MEM_INNER_RESVD1 0x08U +#define MPU_MAIR_MEM_INNER_WT_NT_WA 0x09U +#define MPU_MAIR_MEM_INNER_WT_NT_RA 0x0AU +#define MPU_MAIR_MEM_INNER_WT_NT_RWA 0x0BU +#define MPU_MAIR_MEM_INNER_RESVD2 0x0CU +#define MPU_MAIR_MEM_INNER_WB_NT_WA 0x0DU +#define MPU_MAIR_MEM_INNER_WB_NT_RA 0x0EU +#define MPU_MAIR_MEM_INNER_WB_NT_RWA 0x0FU +/** @} */ + +/** + * @name Region identifiers + * @{ + */ +#define MPU_REGION_0 0U +#define MPU_REGION_1 1U +#define MPU_REGION_2 2U +#define MPU_REGION_3 3U +#define MPU_REGION_4 4U +#define MPU_REGION_5 5U +#define MPU_REGION_6 6U +#define MPU_REGION_7 7U +#define MPU_REGION_8 7U +#define MPU_REGION_9 7U +#define MPU_REGION_10 7U +#define MPU_REGION_11 7U +#define MPU_REGION_12 7U +#define MPU_REGION_13 7U +#define MPU_REGION_14 7U +#define MPU_REGION_15 7U +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Enables the MPU. + * @note MEMFAULENA is enabled in SCB_SHCSR. + * + * @param[in] ctrl MPU control modes as defined in @p MPU_CTRL register, + * the enable bit is enforced + * + * @api + */ +#define mpuEnable(ctrl) { \ + MPU->CTRL = ((uint32_t)ctrl) | MPU_CTRL_ENABLE; \ +} + +/** + * @brief Disables the MPU. + * @note MEMFAULENA is disabled in SCB_SHCSR. + * + * @api + */ +#define mpuDisable() { \ + SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; \ +} + +/** + * @brief Configures an MPU region. + * + * @param[in] region the region number + * @param[in] rbar RBAR register initialization value + * @param[in] rlar RAR register initialization value + * + * @api + */ +#define mpuConfigureRegion(region, rbar, rlar) { \ + MPU->RNR = ((uint32_t)region); \ + MPU->RBAR = ((uint32_t)rbar); \ + MPU->RLAR = ((uint32_t)rlar); \ +} + +/** + * @brief Changes an MPU region base address only. + * + * @param[in] region the region number + * @param[in] address new start address of the region + * + * @api + */ +#define mpuSetRegionAddress(region, addr) { \ + MPU->RNR = ((uint32_t)region); \ + MPU->RBAR = (MPU->RBAR & ~MPU_RBAR_BASE_MASK) | \ + ((uint32_t)addr & MPU_RBAR_BASE_MASK); \ +} + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +#endif /* MPU_V8M_H */ + +/** @} */ From 8f666bca44ec002e3824e67ecee06991910472d3 Mon Sep 17 00:00:00 2001 From: David Buzz Date: Tue, 7 Apr 2026 12:50:20 +1000 Subject: [PATCH 02/21] RP: support single-core ARMv8-M-ML-ALT builds --- os/common/ports/ARMv8-M-ML-ALT/smp/rp2/chcoresmp.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/os/common/ports/ARMv8-M-ML-ALT/smp/rp2/chcoresmp.c b/os/common/ports/ARMv8-M-ML-ALT/smp/rp2/chcoresmp.c index 7f0efaa94d..b657303756 100644 --- a/os/common/ports/ARMv8-M-ML-ALT/smp/rp2/chcoresmp.c +++ b/os/common/ports/ARMv8-M-ML-ALT/smp/rp2/chcoresmp.c @@ -25,7 +25,16 @@ */ #include "ch.h" - +#include "chcoresmp_timer.h" + +#if CH_CFG_SMP_MODE == FALSE +#define PORT_FIFO_PANIC_MESSAGE 0xFFFFFFFEU +#define PORT_FIFO_RESCHEDULE_MESSAGE 0xFFFFFFFFU +typedef unsigned core_id_t; +__STATIC_INLINE core_id_t port_get_core_id(void) { return 0U; } +__STATIC_INLINE void port_spinlock_take(void) {} +__STATIC_INLINE void port_spinlock_release(void) {} +#endif /*===========================================================================*/ /* Module local definitions. */ /*===========================================================================*/ From 2dc56b6428f8225af4ba6c088ed0fdf5771eb8c9 Mon Sep 17 00:00:00 2001 From: David Buzz Date: Wed, 8 Apr 2026 04:34:31 +1000 Subject: [PATCH 03/21] RP2350: add QFN-80 ADC channel mapping --- os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.c | 4 +++- os/hal/ports/RP/RP2350/rp_registry.h | 18 +++++++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.c b/os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.c index 556ff20604..ce3c2b5c89 100644 --- a/os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.c +++ b/os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.c @@ -403,7 +403,9 @@ void adcRPDisableTS(ADCDriver *adcp) { * @brief Configures a GPIO pin for ADC input. * @note Disables digital I/O and pulls for proper analog operation. * - * @param[in] gpio GPIO pin number (26-29 RP2040, 26-29/40-47 RP2350) + * @param[in] gpio GPIO pin number (RP2040: 26-29; RP2350A QFN-60: 26-29; + * RP2350B QFN-80: 40-47). Range is validated against + * RP_ADC_BASE_PIN and RP_ADC_NUM_CHANNELS for the build. * * @api */ diff --git a/os/hal/ports/RP/RP2350/rp_registry.h b/os/hal/ports/RP/RP2350/rp_registry.h index 59318a9920..62997f45fa 100644 --- a/os/hal/ports/RP/RP2350/rp_registry.h +++ b/os/hal/ports/RP/RP2350/rp_registry.h @@ -111,15 +111,23 @@ #define RP_HAS_PWM11 TRUE /* ADC attributes. - Note: RP2350A (QFN-60) has 5 channels (4 external + temp on ch4) - RP2350B (QFN-80) has 9 channels (8 external + temp on ch8) - Default configuration is for RP2350A (Pico 2). */ + RP2350A (QFN-60): 4 external inputs on GPIO26-29 (AINSEL 0-3), temp on AINSEL 4. + RP2350B (QFN-80): 8 external inputs on GPIO40-47 (AINSEL 0-7), temp on AINSEL 8. + Select QFN-80 variant by defining RP2350B_QFN80=1 in the board build flags. */ #define RP_HAS_ADC TRUE +#if defined(RP2350B_QFN80) +/* RP2350B QFN-80 (Laurel carrier board): GPIO40-47 = AINSEL 0-7, temp on AINSEL 8. */ +#define RP_ADC_NUM_CHANNELS 9U +#define RP_ADC_TEMPERATURE_CHANNEL 8U +#define RP_ADC_BASE_PIN 40U +#else +/* RP2350A QFN-60 (Pico 2): GPIO26-29 = AINSEL 0-3, temp on AINSEL 4. */ #define RP_ADC_NUM_CHANNELS 5U -#define RP_ADC_HAS_TEMPERATURE_SENSOR TRUE #define RP_ADC_TEMPERATURE_CHANNEL 4U -#define RP_ADC_FIFO_DEPTH 8U #define RP_ADC_BASE_PIN 26U +#endif +#define RP_ADC_HAS_TEMPERATURE_SENSOR TRUE +#define RP_ADC_FIFO_DEPTH 8U #define RP_ADC_DREQ 48U #define RP_ADC_AINSEL_BITS 4U #define RP_ADC_RROBIN_MASK 0x01FF0000U From bfd895e002e92acf5c301c7abe36cfc6354dfa3c Mon Sep 17 00:00:00 2001 From: David Buzz Date: Sun, 12 Apr 2026 17:55:54 +1000 Subject: [PATCH 04/21] RP2350: configure VREG and QMI before PLL switch RP2350: order QMI timing update before XIP access --- os/hal/ports/RP/RP2350/rp_clocks.c | 154 +++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/os/hal/ports/RP/RP2350/rp_clocks.c b/os/hal/ports/RP/RP2350/rp_clocks.c index dadfd381dc..e8b50b99a5 100644 --- a/os/hal/ports/RP/RP2350/rp_clocks.c +++ b/os/hal/ports/RP/RP2350/rp_clocks.c @@ -37,6 +37,23 @@ * safety timeouts during early clock initialization. */ #define RP_ROSC_ASSUMED_HZ 6000000U +#define RP_VREG_TIMEOUT_US 100000U + +#if defined(RP_VREG_VSEL) && (RP_VREG_VSEL > 0x1FU) +#error "RP_VREG_VSEL must fit the POWMAN VREG.VSEL field" +#endif + +#if defined(RP_QMI_CLKDIV) != defined(RP_QMI_RXDELAY) +#error "RP_QMI_CLKDIV and RP_QMI_RXDELAY must be defined together" +#endif + +#if defined(RP_QMI_CLKDIV) && (RP_QMI_CLKDIV > 0xFFU) +#error "RP_QMI_CLKDIV must fit the QMI M0_TIMING.CLKDIV field" +#endif + +#if defined(RP_QMI_RXDELAY) && (RP_QMI_RXDELAY > 0x7U) +#error "RP_QMI_RXDELAY must fit the QMI M0_TIMING.RXDELAY field" +#endif /*===========================================================================*/ /* Driver exported variables. */ @@ -50,6 +67,74 @@ /* Driver local functions. */ /*===========================================================================*/ +#if defined(RP_VREG_VSEL) +/** + * @brief Raises the on-chip VREG output voltage before switching to a + * higher PLL frequency. + * + * The POWMAN voltage regulator (VREG) defaults to 1.1 V. Boards operating + * outside the datasheet-qualified clock range may select a higher voltage, + * which must be applied before the PLL is switched to the target frequency. + * + * This function unlocks the VREG control interface and programs the voltage + * level requested by the RP_VREG_VSEL hwdef.dat define. The sequence mirrors + * the MicroPython reference implementation by MichaelBell (power.py): + * 1. Unlock VREG_CTRL with the POWMAN password (0x5AFE in upper 16 bits). + * 2. Configure BOD (brown-out detector) threshold to "normal". + * 3. Write VSEL field in VREG register to the desired voltage level. + * 4. Wait with a safety timeout for UPDATE_IN_PROGRESS to clear and + * VOUT_OK to assert. + * + * POWMAN base address: 0x40100000 (__POWMAN_BASE). Register offsets: + * +0x04 VREG_CTRL — unlock (bit 13), RST_N (bit 15), HT_TH (bits 6:4) + * +0x08 VREG_STS — VOUT_OK (bit 4) + * +0x0C VREG — VSEL (bits 8:4), UPDATE_IN_PROGRESS (bit 15) + * +0x1C BOD — brown-out detector settings + * + * RP_VREG_VSEL encoding (datasheet Table 481, VREG register): + * 0x0b = 1.10 V (default) + * 0x0c = 1.15 V + * 0x0d = 1.20 V + * 0x0e = 1.25 V + * 0x0f = 1.30 V (voltage-limit cap) + * Voltages above 1.30 V require DISABLE_VOLTAGE_LIMIT in VREG_CTRL first. + * + * All writes to POWMAN addresses <= base+0xAC require the 0x5AFE password + * in the upper 16 bits; reads do NOT return the password (protected). + */ +static void rp2350_vreg_init(void) { + volatile uint32_t *vreg_ctrl = (volatile uint32_t *)(__POWMAN_BASE + 0x04U); + volatile uint32_t *vreg_sts = (volatile uint32_t *)(__POWMAN_BASE + 0x08U); + volatile uint32_t *vreg = (volatile uint32_t *)(__POWMAN_BASE + 0x0CU); + volatile uint32_t *bod = (volatile uint32_t *)(__POWMAN_BASE + 0x1CU); + + /* Unlock VREG control: password | RST_N(bit15) | UNLOCK(bit13) | HT_TH=5/125C(bits6:4). + * Once unlocked the interface cannot be re-locked — one-way operation. */ + *vreg_ctrl = 0x5AFEA050U; + + /* Set brown-out detector to "normal" threshold (appropriate for >= 1.1 V). */ + *bod = 0x5AFE0091U; + + /* Busy-wait ~16 ms at the assumed 6 MHz ROSC for BOD to settle before + * changing the output voltage. No OS timer is available this early. */ + for (volatile uint32_t i = 0U; i < 50000U; i++) { + __asm__ volatile ("nop"); + } + + /* Write VSEL to raise the regulator output. VSEL occupies bits [8:4]. + * The upper 16 bits carry the mandatory 0x5AFE write password. */ + *vreg = 0x5AFE0000U | ((uint32_t)(RP_VREG_VSEL) << 4U); + + /* Bound both waits so a regulator or board-power fault is diagnosable. */ + halSftFailOnError(halRegWaitAllClear32X(vreg, 1U << 15U, + RP_VREG_TIMEOUT_US, NULL), + "RP VREG update timeout"); + halSftFailOnError(halRegWaitAnySet32X(vreg_sts, 1U << 4U, + RP_VREG_TIMEOUT_US, NULL), + "RP VREG regulation timeout"); +} +#endif /* RP_VREG_VSEL */ + /*===========================================================================*/ /* Driver exported functions. */ /*===========================================================================*/ @@ -65,6 +150,44 @@ */ void rp_clock_init(void) { + /* Copy .ramtext (RAMFUNC) section to SRAM before touching the PLL. + * + * CRT0 copies the vector table (INIT_VECTORS) and .data+.ramtext + * (INIT_DATA) AFTER calling __early_init(), which is where this + * function runs. So when rp_clock_init() executes, the RAM fault + * handlers aren't in RAM yet — their VMA addresses are correct but + * the SRAM hasn't been populated. If a fault occurs during the PLL + * switch (e.g. XIP timing glitch at the new higher frequency) the + * CPU jumps to the handler VMA (SRAM) but finds uninitialised memory, + * causing a double-fault lockup at PC=0xEFFFFFFE. + * + * Fix: copy just the .ramtext region now, before XOSC/PLL init, so + * the RAM fault handlers are live before the clock risk window. + * The linker exports __ramfunc_start__ (VMA) and __textramfunc_base__ + * (LMA in flash) and __ramfunc_end__ (VMA end). + */ + { + extern uint32_t __ramfunc_start__; /* VMA: destination in SRAM */ + extern uint32_t __ramfunc_end__; /* VMA: end of ramtext in SRAM */ + /* LMA of ramtext is immediately after the last item in .data in flash. + * The linker puts .ramtext inside the .data output section so its LMA + * follows __textdata_base__ + (size of .data before ramtext). + * We can compute it as: LMA = flash_base_of_.data + offset_of_ramtext. + * The most portable way is to use __textdata_base__ and walk past .data. + * ChibiOS ld exports __textdata_base__ for exactly this purpose. */ + extern uint32_t __textdata_base__; /* LMA: start of .data+ramtext in flash */ + extern uint32_t __data_base__; /* VMA: start of .data in SRAM */ + + /* Compute LMA of ramtext = textdata_base + (ramtext_vma - data_vma). */ + uint32_t *src = &__textdata_base__ + + (&__ramfunc_start__ - &__data_base__); + uint32_t *dst = &__ramfunc_start__; + uint32_t *end = &__ramfunc_end__; + while (dst < end) { + *dst++ = *src++; + } + } + /* Start early tick generator for safety module timeouts. */ rp_peripheral_unreset(RESETS_ALLREG_TIMER0); @@ -87,6 +210,37 @@ void rp_clock_init(void) { /* Wait for clk_ref to switch to ROSC */ } +#if defined(RP_VREG_VSEL) + /* Set the board-selected core voltage before initializing the PLL. The CPU + * is still running on the slow ROSC, so the voltage change precedes any + * increase in system frequency. */ + rp2350_vreg_init(); +#endif + +#if defined(RP_QMI_CLKDIV) + /* Update QMI M0_TIMING before switching PLL_SYS to the target frequency. + * Bootloader timing may not be safe at the selected application clock, so + * the board supplies a characterized CLKDIV and RXDELAY. Apply these values + * before raising sys_clk, then issue a dummy flash access and barriers. + * Only CLKDIV and RXDELAY are replaced; all other fields (MAX_SELECT, + * MIN_DESELECT, etc.) are preserved from the bootloader value. */ + { + volatile uint32_t *m0_timing = (volatile uint32_t *)(0x400D000CU); + uint32_t t = *m0_timing; + t &= ~0x7FFU; /* clear CLKDIV[7:0] and RXDELAY[10:8] */ + t |= ((uint32_t)(RP_QMI_RXDELAY) << 8) | (uint32_t)(RP_QMI_CLKDIV); + *m0_timing = t; + /* DSB ensures the MMIO write reaches the QMI peripheral before the dummy + * flash read triggers a QMI transaction with the new timing. */ + __asm volatile ("dsb sy" ::: "memory"); + __asm volatile ("isb" ::: "memory"); + /* Dummy flash read to flush any in-flight XIP prefetch with old timing. */ + (void)(*(volatile uint32_t *)0x10000000U); + __asm volatile ("dsb sy" ::: "memory"); + __asm volatile ("isb" ::: "memory"); + } +#endif + /* Initialize PLL_SYS: 12 MHz * 125 / 5 / 2 = 150 MHz. */ rp_pll_init(PLL_SYS, RP_PLL_SYS_REFDIV, RP_PLL_SYS_VCO_FREQ, RP_PLL_SYS_POSTDIV1, RP_PLL_SYS_POSTDIV2); From a017114e1bf2404abb1d50a2193cc008ca5194c4 Mon Sep 17 00:00:00 2001 From: David Buzz Date: Sun, 12 Apr 2026 22:00:30 +1000 Subject: [PATCH 05/21] RP PWM: avoid divider overflow at high clocks --- os/hal/ports/RP/LLD/PWMv1/hal_pwm_lld.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/os/hal/ports/RP/LLD/PWMv1/hal_pwm_lld.c b/os/hal/ports/RP/LLD/PWMv1/hal_pwm_lld.c index 595c026c0c..9d84f6f9c3 100644 --- a/os/hal/ports/RP/LLD/PWMv1/hal_pwm_lld.c +++ b/os/hal/ports/RP/LLD/PWMv1/hal_pwm_lld.c @@ -371,7 +371,11 @@ void pwm_lld_start(PWMDriver *pwmp) { p->CH[pwmp->timer_id].CC = 0; } - /* Counter clock divider. */ + /* Counter clock divider. + * CH_DIV register: bits[11:4]=INT(8-bit), bits[3:0]=FRAC(4-bit). + * Minimum achievable frequency = sys_clk / 256 (max INT value). + * The fractional calculation uses <<4 so must be done in 64-bit to avoid + * overflow when sys_clk > 268 MHz (e.g. 375 MHz << 4 = 6 GHz > 4.29 GB). */ halfreq_t sys_clk = halClockGetPointX(RP_CLK_SYS); halfreq_t pwm_freq_min = sys_clk / 256; @@ -382,7 +386,8 @@ void pwm_lld_start(PWMDriver *pwmp) { halfreq_t integer = sys_clk / pwmp->config->frequency; integer = integer == 0 ? 1 : integer; - halfreq_t fraction = (sys_clk << 4) / pwmp->config->frequency; + /* Fractional part: use 64-bit to prevent overflow at high sys_clk values. */ + uint32_t fraction = (uint32_t)(((uint64_t)sys_clk << 4) / pwmp->config->frequency); p->CH[pwmp->timer_id].DIV = (integer << 4 | (fraction & 0xF)); p->CH[pwmp->timer_id].TOP = pwmp->period; From 829bc7d7a4094b62295256d2f720fb846b4708a9 Mon Sep 17 00:00:00 2001 From: David Buzz Date: Thu, 14 May 2026 06:33:42 +1000 Subject: [PATCH 06/21] RP USB: use safe endpoint buffer state handling --- os/hal/ports/RP/LLD/USBv1/hal_usb_lld.c | 36 ++++++++++++------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/os/hal/ports/RP/LLD/USBv1/hal_usb_lld.c b/os/hal/ports/RP/LLD/USBv1/hal_usb_lld.c index 752e125b45..e7e44b90aa 100644 --- a/os/hal/ports/RP/LLD/USBv1/hal_usb_lld.c +++ b/os/hal/ports/RP/LLD/USBv1/hal_usb_lld.c @@ -290,7 +290,6 @@ static uint32_t usb_prepare_in_ep_buffer(USBDriver *usbp, usbep_t ep, uint8_t bu static void usb_prepare_in_ep(USBDriver *usbp, usbep_t ep) { uint32_t buf_ctrl; uint32_t ep_ctrl; - USBInEndpointState *iesp = usbp->epc[ep]->in_state; if (ep == 0) { ep_ctrl = USB->SIECTRL; @@ -298,24 +297,17 @@ static void usb_prepare_in_ep(USBDriver *usbp, usbep_t ep) { ep_ctrl = EP_CTRL(ep).IN; } - /* Fill first buffer */ + /* Fill first buffer only. + * Double-buffered IN mode is not used: on buffer-0 completion the ISR would + * call usb_prepare_in_ep again while buffer-1 is still in-flight, overwriting + * its DPRAM data with the next chunk. The host then receives corrupted bytes + * and MAVLink CRC checks fail. Single-buffered mode (one 64-byte packet per + * interrupt) is correct and sufficient for MAVLink throughput. */ buf_ctrl = usb_prepare_in_ep_buffer(usbp, ep, 0); - /* Second buffer if required */ - /* iesp->txsize - iesp->txlast gives size even not in buffer */ - if (iesp->txsize - iesp->txlast > 0) { - buf_ctrl |= usb_prepare_in_ep_buffer(usbp, ep, 1); - } - - if (buf_ctrl & USB_BUFFER_BUFFER1_AVAILABLE) { - /* Double buffered */ - ep_ctrl &= ~USB_EP_BUFFER_IRQ_EN; - ep_ctrl |= USB_EP_BUFFER_DOUBLE | USB_EP_BUFFER_IRQ_DOUBLE_EN; - } else { - /* Single buffered */ - ep_ctrl &= ~(USB_EP_BUFFER_DOUBLE | USB_EP_BUFFER_IRQ_DOUBLE_EN); - ep_ctrl |= USB_EP_BUFFER_IRQ_EN; - } + /* Single buffered */ + ep_ctrl &= ~(USB_EP_BUFFER_DOUBLE | USB_EP_BUFFER_IRQ_DOUBLE_EN); + ep_ctrl |= USB_EP_BUFFER_IRQ_EN; if (ep == 0) { USB->SIECTRL = ep_ctrl; @@ -746,7 +738,15 @@ usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep) { if (ep == 0U) { return EP_STATUS_ACTIVE; } - if (EP_CTRL(ep).OUT & USB_EP_EN) { + if (!(EP_CTRL(ep).OUT & USB_EP_EN)) { + return EP_STATUS_DISABLED; + } + /* USB_EP_EN stays set permanently after usbInitEndpointI. Use + * BUFFER0_AVAILABLE to detect whether a receive transaction is actually + * armed — it is set by usb_prepare_out_ep and cleared by hardware on + * completion. Without this check sdu_start_receive never calls + * usbStartReceiveI and the OUT endpoint never receives any data. */ + if (BUF_CTRL(ep).OUT & USB_BUFFER_BUFFER0_AVAILABLE) { return EP_STATUS_ACTIVE; } return EP_STATUS_DISABLED; From 37f75992f483fd412b76189aa430306747bdcfcc Mon Sep 17 00:00:00 2001 From: David Buzz Date: Sun, 14 Jun 2026 17:20:35 +1000 Subject: [PATCH 07/21] RP2350: use per-core SRAM idle loops --- os/rt/src/chinstances.c | 27 +++++++++++++++++++++++++++ os/rt/src/rp2350_idle_loops.S | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 os/rt/src/rp2350_idle_loops.S diff --git a/os/rt/src/chinstances.c b/os/rt/src/chinstances.c index 4d21de45eb..c28fa50066 100644 --- a/os/rt/src/chinstances.c +++ b/os/rt/src/chinstances.c @@ -58,6 +58,32 @@ * * @param[in] p the thread parameter, unused in this scenario */ +#if defined(RP2350) && (CH_CFG_SMP_MODE == TRUE) +/* + * RP2350 SMP: route each core to a distinct striped-SRAM bank so their idle + * instruction fetches can proceed in parallel without arbitration stalls. + * + * rp2350_idle_c0/c1 are in rp2350_idle_loops.S (.ramtext), separated by + * .balign 4 so they land in consecutive (different) 4-byte striped-SRAM + * banks. optimize("O0") prevents GCC from analysing the call targets as + * infinite loops and collapsing this function to a single b.n instruction. + */ +extern void rp2350_idle_c0(void); +extern void rp2350_idle_c1(void); + +__attribute__((noinline, optimize("O0"), section(".ramtext"))) +static void __idle_thread(void *p) { + + (void)p; + + if (port_get_core_id() == 0U) { + rp2350_idle_c0(); + } + else { + rp2350_idle_c1(); + } +} +#else static void __idle_thread(void *p) { (void)p; @@ -70,6 +96,7 @@ static void __idle_thread(void *p) { CH_CFG_IDLE_LOOP_HOOK(); } } +#endif /* RP2350 && CH_CFG_SMP_MODE */ #endif /* CH_CFG_NO_IDLE_THREAD == FALSE */ /*===========================================================================*/ diff --git a/os/rt/src/rp2350_idle_loops.S b/os/rt/src/rp2350_idle_loops.S new file mode 100644 index 0000000000..2e0811d36e --- /dev/null +++ b/os/rt/src/rp2350_idle_loops.S @@ -0,0 +1,34 @@ +/* + * rp2350_idle_loops.S — per-core idle loops for RP2350 SMP. + * + * Pure assembly so the C compiler cannot collapse them. Core0 spins at + * rp2350_idle_c0, Core1 spins at rp2350_idle_c1. + * + * .balign 4 before each symbol guarantees they fall in consecutive + * 4-byte-aligned words → consecutive striped-SRAM banks. The RP2350 bus + * fabric can service simultaneous fetches from different banks without + * arbitration stalls. + * + * Both symbols are in .ramtext so they live in SRAM, safe from flash XIP + * blackouts during flash erase/write. + */ + + .thumb + .syntax unified + + .section .ramtext, "ax", %progbits + + .balign 4 + .global rp2350_idle_c0 + .type rp2350_idle_c0, %function +rp2350_idle_c0: + b rp2350_idle_c0 + .size rp2350_idle_c0, . - rp2350_idle_c0 + + .balign 4 /* next 4-byte word = consecutive bank, no conflict */ + .global rp2350_idle_c1 + .type rp2350_idle_c1, %function +rp2350_idle_c1: + nop /* distinct first opcode, also pads to 4 bytes total */ + b rp2350_idle_c1 + .size rp2350_idle_c1, . - rp2350_idle_c1 From 8f70d9884781904b6161d3e70c5175277c057d74 Mon Sep 17 00:00:00 2001 From: David Buzz Date: Mon, 22 Jun 2026 16:47:31 +1000 Subject: [PATCH 08/21] RP SIO: initialize UART FIFO and DMA controls --- os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.c b/os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.c index b80bd8067c..827675b1b5 100644 --- a/os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.c +++ b/os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.c @@ -133,6 +133,8 @@ __STATIC_INLINE void uart_init(SIODriver *siop) { /* Setting up the operation.*/ siop->uart->UARTICR = siop->uart->UARTRIS; + siop->uart->UARTIFLS = siop->config->UARTIFLS; + siop->uart->UARTDMACR = siop->config->UARTDMACR; siop->uart->UARTCR = cr | UART_UARTCR_RXE | UART_UARTCR_TXE | UART_UARTCR_UARTEN; } From f622457d4f5806d1e0ebf07ed535c2c2a5742327 Mon Sep 17 00:00:00 2001 From: David Buzz Date: Fri, 26 Jun 2026 08:52:55 +1000 Subject: [PATCH 09/21] RP DMA: support cross-core channel release --- os/hal/ports/RP/LLD/DMAv1/rp_dma.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/os/hal/ports/RP/LLD/DMAv1/rp_dma.c b/os/hal/ports/RP/LLD/DMAv1/rp_dma.c index 217ecec3ed..480bf0d73f 100644 --- a/os/hal/ports/RP/LLD/DMAv1/rp_dma.c +++ b/os/hal/ports/RP/LLD/DMAv1/rp_dma.c @@ -321,17 +321,22 @@ void dmaChannelFreeI(const rp_dma_channel_t *dmachp) { dmaChannelDisableX(dmachp); dmaChannelSetModeX(dmachp, 0U); - if (SIO->CPUID == 0U) { - /* Channel released by core 0.*/ + /* Remove from whichever core mask owns this channel. + Handles cross-core freeing (e.g. sdcard_init on core0 stopping SPI1 + whose DMA was allocated by the SPI1 bus thread on core1). + NVIC disable: only possible on the current core's own NVIC. + For the other core, dmaChannelDisableInterruptX() above already cleared + INTE0/INTE1 for this channel, so no stray IRQs will fire even if that + core's NVIC vector remains enabled. */ + if (dma.c0_allocated_mask & dmachp->chnmask) { dma.c0_allocated_mask &= ~dmachp->chnmask; - if (dma.c0_allocated_mask == 0U) { + if (dma.c0_allocated_mask == 0U && SIO->CPUID == 0U) { nvicDisableVector(RP_DMA_IRQ_0_NUMBER); } } - else { - /* Channel released by core 1.*/ + if (dma.c1_allocated_mask & dmachp->chnmask) { dma.c1_allocated_mask &= ~dmachp->chnmask; - if (dma.c1_allocated_mask == 0U) { + if (dma.c1_allocated_mask == 0U && SIO->CPUID == 1U) { nvicDisableVector(RP_DMA_IRQ_1_NUMBER); } } From 96d88bd9d5da47c72edefdc3e6ad4383d749c2ba Mon Sep 17 00:00:00 2001 From: David Buzz Date: Fri, 26 Jun 2026 21:33:29 +1000 Subject: [PATCH 10/21] RP2350: keep scheduler and DMA metadata XIP-safe --- .../ports/ARMv8-M-ML-ALT/compilers/GCC/chcoreasm.S | 4 +++- os/hal/ports/RP/LLD/DMAv1/rp_dma.c | 2 +- os/hal/ports/RP/LLD/DMAv1/rp_dma.h | 14 +++++++++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/os/common/ports/ARMv8-M-ML-ALT/compilers/GCC/chcoreasm.S b/os/common/ports/ARMv8-M-ML-ALT/compilers/GCC/chcoreasm.S index 4f39242f2f..274a2d23a3 100644 --- a/os/common/ports/ARMv8-M-ML-ALT/compilers/GCC/chcoreasm.S +++ b/os/common/ports/ARMv8-M-ML-ALT/compilers/GCC/chcoreasm.S @@ -84,7 +84,6 @@ #endif .thumb - .text /*--------------------------------------------------------------------------* * Context switch macros depending on various options. @@ -232,6 +231,7 @@ /*--------------------------------------------------------------------------* * Performs a context switch between two threads using SVC. *--------------------------------------------------------------------------*/ + .section .text.SVC_Handler, "ax", %progbits .thumb_func .globl SVC_Handler SVC_Handler: @@ -313,6 +313,7 @@ SVC_Handler: /*--------------------------------------------------------------------------* * Tail preemption check using PENDSV. *--------------------------------------------------------------------------*/ + .section .text.PendSV_Handler, "ax", %progbits .thumb_func .globl PendSV_Handler PendSV_Handler: @@ -375,6 +376,7 @@ PendSV_Handler: * register R5 contains the thread parameter. The function chThdExit() is * called on thread function return. *--------------------------------------------------------------------------*/ + .section .text.__port_thread_start, "ax", %progbits .thumb_func .globl __port_thread_start __port_thread_start: diff --git a/os/hal/ports/RP/LLD/DMAv1/rp_dma.c b/os/hal/ports/RP/LLD/DMAv1/rp_dma.c index 480bf0d73f..e47e2d7377 100644 --- a/os/hal/ports/RP/LLD/DMAv1/rp_dma.c +++ b/os/hal/ports/RP/LLD/DMAv1/rp_dma.c @@ -43,7 +43,7 @@ /** * @brief DMA channel descriptors. */ -const rp_dma_channel_t __rp_dma_channels[RP_DMA_NUM_CHANNELS] = { +rp_dma_channel_t __rp_dma_channels[RP_DMA_NUM_CHANNELS] = { {DMA, &DMA->CH[0], 0U, 1U << 0}, {DMA, &DMA->CH[1], 1U, 1U << 1}, {DMA, &DMA->CH[2], 2U, 1U << 2}, diff --git a/os/hal/ports/RP/LLD/DMAv1/rp_dma.h b/os/hal/ports/RP/LLD/DMAv1/rp_dma.h index 3582cb1ac5..6284b83461 100644 --- a/os/hal/ports/RP/LLD/DMAv1/rp_dma.h +++ b/os/hal/ports/RP/LLD/DMAv1/rp_dma.h @@ -103,7 +103,7 @@ typedef struct { /*===========================================================================*/ #if !defined(__DOXYGEN__) -extern const rp_dma_channel_t __rp_dma_channels[RP_DMA_NUM_CHANNELS]; +extern rp_dma_channel_t __rp_dma_channels[RP_DMA_NUM_CHANNELS]; #endif #ifdef __cplusplus @@ -157,6 +157,9 @@ __STATIC_INLINE bool dmaChannelIsBusyX(const rp_dma_channel_t *dmachp) { __STATIC_INLINE uint32_t dmaChannelGetAndClearInterrupts(const rp_dma_channel_t *dmachp) { uint32_t ctrl_trig; + if (dmachp == NULL || dmachp->dma != DMA) { + return 0U; + } ctrl_trig = dmachp->channel->CTRL_TRIG; dmachp->channel->CTRL_TRIG = ctrl_trig | DMA_CTRL_TRIG_READ_ERROR | @@ -177,6 +180,9 @@ __STATIC_INLINE uint32_t dmaChannelGetAndClearInterrupts(const rp_dma_channel_t */ __STATIC_INLINE void dmaChannelEnableInterruptX(const rp_dma_channel_t *dmachp) { + if (dmachp == NULL || dmachp->dma != DMA) { + return; + } if (SIO->CPUID == 0U) { dmachp->dma->SET.INTE0 = dmachp->chnmask; } @@ -195,6 +201,9 @@ __STATIC_INLINE void dmaChannelEnableInterruptX(const rp_dma_channel_t *dmachp) */ __STATIC_INLINE void dmaChannelDisableInterruptX(const rp_dma_channel_t *dmachp) { + if (dmachp == NULL || dmachp->dma != DMA) { + return; + } dmachp->dma->CLR.INTE0 = dmachp->chnmask; dmachp->dma->CLR.INTE1 = dmachp->chnmask; } @@ -277,6 +286,9 @@ __STATIC_INLINE void dmaChannelSetModeX(const rp_dma_channel_t *dmachp, */ __STATIC_INLINE void dmaChannelAbortX(const rp_dma_channel_t *dmachp) { + if (dmachp == NULL || dmachp->dma != DMA) { + return; + } /* Clear EN and set CHAIN_TO to self (no chaining) per RP2350-E5. W1C error flags are masked to zero to preserve them. */ dmachp->channel->CTRL_TRIG = (dmachp->channel->CTRL_TRIG & From c1b73334d71eba8edbddaf5ecc8a6aa7b449f840 Mon Sep 17 00:00:00 2001 From: Andy Piper Date: Fri, 3 Jul 2026 23:10:46 +0200 Subject: [PATCH 11/21] RP2350: copy early ramtext without memcpy --- os/hal/ports/RP/RP2350/rp_clocks.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/os/hal/ports/RP/RP2350/rp_clocks.c b/os/hal/ports/RP/RP2350/rp_clocks.c index e8b50b99a5..11a79a5e2a 100644 --- a/os/hal/ports/RP/RP2350/rp_clocks.c +++ b/os/hal/ports/RP/RP2350/rp_clocks.c @@ -179,10 +179,15 @@ void rp_clock_init(void) { extern uint32_t __data_base__; /* VMA: start of .data in SRAM */ /* Compute LMA of ramtext = textdata_base + (ramtext_vma - data_vma). */ - uint32_t *src = &__textdata_base__ + + /* volatile is REQUIRED: without it GCC recognises this word loop as a + * memcpy() idiom and emits a call to memcpy. Once memcpy itself is + * relocated into .ramtext (to keep it out of the XIP cache) that call + * would target uninitialised SRAM - the very region this loop exists to + * populate - and double-fault at boot. volatile forces the explicit copy. */ + volatile uint32_t *src = &__textdata_base__ + (&__ramfunc_start__ - &__data_base__); - uint32_t *dst = &__ramfunc_start__; - uint32_t *end = &__ramfunc_end__; + volatile uint32_t *dst = &__ramfunc_start__; + volatile uint32_t *end = &__ramfunc_end__; while (dst < end) { *dst++ = *src++; } From f4af26d2e272c96ebe876fa944fdb718f6a9767e Mon Sep 17 00:00:00 2001 From: Andy Piper Date: Fri, 7 Aug 2026 18:51:06 +0100 Subject: [PATCH 12/21] hal_mmc: write a block in one full duplex exchange mmcSequentialWrite() framed every block as four separate transfers - prologue, data, dummy CRC, response - and then polled mmc_wait_idle() a byte at a time. On a port where an SPI transfer completes by interrupt each of those is a thread suspend and resume, which costs far more than the bytes are worth: a one byte poll is under a microsecond on the wire wrapped in a reschedule. Stage the whole frame instead and clock it in one exchange, with a busy window after the response slot so the common case of the card finishing promptly needs no polling transfer at all. The exchange is in place, so the staging buffer afterwards holds the card's replies and the response token can be read out of it. Opt-in and backwards compatible: wbuffer is NULL out of mmcObjectInit() and NULL keeps the original path, so drivers that do not supply a buffer are unaffected. hal_mmc: always poll for card idle after a block write The single exchange block write inferred completion from the last byte of the busy window: all ones meant the card had finished programming, so the poll was skipped. That reads the same whether the card has finished or has not yet pulled MISO low, and on the second case the next data token goes into a busy card. The card discards that block and reports nothing, so the write returns success with the data gone. Above this, f_write() reports success and AP_Logger advances its file offset, which is how whole 4 KB writes went missing from the middle of a log while the file kept its full length. Keep the busy window - the card usually does finish inside it, so the poll returns on its first byte and the saving is retained - but confirm it rather than assume it. --- os/hal/include/hal_mmc_spi.h | 27 ++++++++++++++++++++++ os/hal/src/hal_mmc_spi.c | 43 ++++++++++++++++++++++++++++++++---- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/os/hal/include/hal_mmc_spi.h b/os/hal/include/hal_mmc_spi.h index 5358f6e05f..0214d18487 100644 --- a/os/hal/include/hal_mmc_spi.h +++ b/os/hal/include/hal_mmc_spi.h @@ -43,6 +43,26 @@ */ #define MMC_BUFFER_SIZE 16U +/** + * @brief Idle bytes clocked after the data response token. + * @details The card holds DO low while it is busy programming. Clocking extra + * bytes in the same transfer catches it going idle again and saves a + * separate polling transfer per block. + * @note Size this generously. A byte is well under a microsecond on the + * wire and the bus is nearly idle anyway, while every poll avoided in + * @p mmc_wait_idle() is a thread suspend and resume. At 8 bytes the + * card was still busy on about 80% of blocks. + */ +#define MMC_WRITE_BUSY_BYTES 256U + +/** + * @brief Size of the optional single-exchange write frame. + * @details Data prologue, block, dummy CRC, the data response slot and the + * busy window, all clocked in one full duplex transfer. + */ +#define MMC_WRITE_FRAME_SIZE (2U + MMCSD_BLOCK_SIZE + 2U + 1U + \ + MMC_WRITE_BUSY_BYTES) + /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/ @@ -145,6 +165,13 @@ typedef struct { * @brief Pointer to an un-cacheable buffer of size @p MMC_BUFFER_SIZE. */ uint8_t *buffer; + /** + * @brief Optional staging buffer for single-exchange block writes. + * @details When non-NULL it must be at least @p MMC_WRITE_FRAME_SIZE bytes + * and is used in place, so it must be writable. NULL selects the + * portable multi-transaction write path. + */ + uint8_t *wbuffer; } mmc_spi_driver_t; /** diff --git a/os/hal/src/hal_mmc_spi.c b/os/hal/src/hal_mmc_spi.c index 728ce47693..8eedbb0c7a 100644 --- a/os/hal/src/hal_mmc_spi.c +++ b/os/hal/src/hal_mmc_spi.c @@ -42,6 +42,7 @@ #define spiIgnore spiIgnoreHook #define spiSend spiSendHook #define spiReceive spiReceiveHook +#define spiExchange spiExchangeHook #endif #define MMC_READ_WAIT_USEC 250 @@ -567,6 +568,7 @@ void mmcObjectInit(MMCDriver *mmcp, uint8_t *buffer) { mmcp->config = NULL; mmcp->block_addresses = false; mmcp->buffer = buffer; + mmcp->wbuffer = NULL; } /** @@ -993,10 +995,43 @@ bool mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer) { return HAL_FAILED; } - (void) spiSend(mmcp->config->spip, sizeof(start), start); /* Data prologue. */ - (void) spiSend(mmcp->config->spip, MMCSD_BLOCK_SIZE, buffer);/* Data. */ - (void) spiIgnore(mmcp->config->spip, 2); /* CRC ignored. */ - (void) spiReceive(mmcp->config->spip, 1, mmcp->buffer); + if (mmcp->wbuffer != NULL) { + /* Whole frame in one full duplex exchange. The four transfers below are + each a thread suspend and resume on ports where SPI completes by + interrupt, which costs far more than the bytes are worth: a 1 byte poll + is under a microsecond of wire time wrapped in a reschedule. Staging + costs one 512 byte copy per block, which is nothing beside that.*/ + uint8_t *f = mmcp->wbuffer; + unsigned i; + + f[0] = start[0]; + f[1] = start[1]; + memcpy(&f[2], buffer, MMCSD_BLOCK_SIZE); + /* Dummy CRC, the data response slot and the busy window. The card drives + the bus during these, so the content only has to leave MOSI idle.*/ + for (i = 2U + MMCSD_BLOCK_SIZE; i < MMC_WRITE_FRAME_SIZE; i++) { + f[i] = 0xFFU; + } + + /* In place: the transmit side of each byte is consumed before the received + byte replaces it.*/ + (void) spiExchange(mmcp->config->spip, MMC_WRITE_FRAME_SIZE, f, f); + + mmcp->buffer[0] = f[2U + MMCSD_BLOCK_SIZE + 2U]; + /* The busy window still earns its place: the card usually finishes + programming inside it, so the poll below returns on its first byte. + It is not evidence on its own though - a card that has not yet pulled + MISO low reads back all ones, which is indistinguishable from one that + has finished. Treating that as done sends the next data token into a + busy card, which discards the block and reports nothing.*/ + } + else { + (void) spiSend(mmcp->config->spip, sizeof(start), start); /* Data prologue. */ + (void) spiSend(mmcp->config->spip, MMCSD_BLOCK_SIZE, buffer);/* Data. */ + (void) spiIgnore(mmcp->config->spip, 2); /* CRC ignored. */ + (void) spiReceive(mmcp->config->spip, 1, mmcp->buffer); + } + if ((mmcp->buffer[0] & 0x1FU) == 0x05U) { return mmc_wait_idle(mmcp); } From 0e57440848a8b34a00c92c7456c5368a0e417053 Mon Sep 17 00:00:00 2001 From: Andy Piper Date: Fri, 7 Aug 2026 22:49:35 +0100 Subject: [PATCH 13/21] RP SPI: do not continue past a failed DMA allocation spi_lld_start() guarded both dmaChannelAllocI() calls with osalDbgAssert only. With debug assertions disabled, which is how flight builds are compiled, a failed allocation returns NULL and execution falls straight through to dmaChannelSetSourceX() on a null channel, leaving the peripheral in reset while the caller has no way to know it did not start. Release any partial allocation and return instead, so the driver is left with null channels for the caller to test. --- os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.c b/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.c index c0016d6bbb..c24fd031a3 100644 --- a/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.c +++ b/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.c @@ -199,6 +199,23 @@ void spi_lld_start(SPIDriver *spip) { osalDbgAssert(false, "invalid SPI instance"); } + /* The allocations above are only guarded by osalDbgAssert, so with debug + assertions disabled a failure would fall through here, dereference a + NULL channel and leave the peripheral in reset while the caller believes + it started. Bail out cleanly instead, releasing any partial allocation, + so the caller can see that the driver did not come up.*/ + if ((spip->dmarx == NULL) || (spip->dmatx == NULL)) { + if (spip->dmarx != NULL) { + dmaChannelFreeI(spip->dmarx); + spip->dmarx = NULL; + } + if (spip->dmatx != NULL) { + dmaChannelFreeI(spip->dmatx); + spip->dmatx = NULL; + } + return; + } + /* DMA setup for SPI DR.*/ dmaChannelSetSourceX(spip->dmarx, (uint32_t)&spip->spi->SSPDR); dmaChannelSetDestinationX(spip->dmatx, (uint32_t)&spip->spi->SSPDR); From 818fdb901c82ae96710117c7c80c517798c75df6 Mon Sep 17 00:00:00 2001 From: Andy Piper Date: Sat, 8 Aug 2026 21:14:06 +0100 Subject: [PATCH 14/21] RP ADC: drop the analog pads out of isolation RP2350 pads come out of a power-on reset isolated and stay that way until something writes the pad register. The PAL clears ISO as a side effect of writing a whole mode word, but an ADC pad never goes through palSetLineMode, and adcRPGpioInit() read-modify-writes the pad so it preserved the bit. Clear it alongside the pulls and the input buffer, matching the Pico SDK - adc_gpio_init() goes through gpio_set_function(), which ends by clearing ISO. --- os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.c b/os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.c index ce3c2b5c89..b53e73a205 100644 --- a/os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.c +++ b/os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.c @@ -38,6 +38,10 @@ #define PADS_GPIO_OD (1U << 7) #define PADS_GPIO_PUE (1U << 3) #define PADS_GPIO_PDE (1U << 2) +/* RP2350 only. Pads come out of a power-on reset isolated and stay that way + until something writes the pad register; the PAL clears it as a side effect + of writing a whole mode word, but an ADC pad never goes through that path.*/ +#define PADS_GPIO_ISO (1U << 8) /** @} */ /*===========================================================================*/ @@ -420,9 +424,12 @@ void adcRPGpioInit(uint32_t gpio) { /* FUNCSEL = NULL (31): disconnect digital output driver.*/ IO_BANK0->GPIO[gpio].CTRL = 31U; - /* Disable pulls and digital input, enable output disable.*/ + /* Disable pulls and digital input, enable output disable, and drop the pad + out of isolation - the read-modify-write would otherwise preserve it. + This matches what the Pico SDK does: adc_gpio_init() goes through + gpio_set_function(), which ends by clearing ISO.*/ padbits = PADS_BANK0->GPIO[gpio]; - padbits &= ~(PADS_GPIO_PUE | PADS_GPIO_PDE | PADS_GPIO_IE); + padbits &= ~(PADS_GPIO_PUE | PADS_GPIO_PDE | PADS_GPIO_IE | PADS_GPIO_ISO); padbits |= PADS_GPIO_OD; PADS_BANK0->GPIO[gpio] = padbits; } From 957e21347a3e8c1469ee790d177536472c5830fc Mon Sep 17 00:00:00 2001 From: Andy Piper Date: Sun, 9 Aug 2026 18:41:38 +0100 Subject: [PATCH 15/21] hal_mmc: poll for card idle a buffer at a time mmc_wait_idle() read one byte per SPI transfer. Either size is one DMA setup and one thread suspend, so a byte at a time paid that overhead sixteen times over for the same sixteen byte-times on the wire - and it did so on the path the staged block write exists to keep clear. Read MMC_BUFFER_SIZE and scan instead. Overshooting past the moment the card goes idle costs nothing: the extra bytes clock against an idle bus, and a gap before the next token is allowed. Measured over 5932 block writes on RPI_UAVFC at 22.5 MHz: the card finishes inside the in-frame busy window 91.4% of the time. Of the waits that outlast it, 87% complete within 256 us and so are resolved by the two reads that land before the first sleep. The remainder run from 512 us to 10 ms - internal erase, not overhead - so they are slept on rather than polled. The same measurement rules out folding a 4 KB write into one exchange: at an 8.6% per-block overrun rate, half of all eight-block frames would contain a block that ran long, and every one of those would have to be rewritten. --- os/hal/src/hal_mmc_spi.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/os/hal/src/hal_mmc_spi.c b/os/hal/src/hal_mmc_spi.c index 8eedbb0c7a..f6238bfbd2 100644 --- a/os/hal/src/hal_mmc_spi.c +++ b/os/hal/src/hal_mmc_spi.c @@ -299,11 +299,21 @@ static uint8_t mmc_crc7(uint8_t crc, const uint8_t *buffer, size_t len) { * @notapi */ static bool mmc_wait_idle(MMCDriver *mmcp) { - unsigned i; - - for (i = 0U; i < 16U; i++) { - (void) spiReceive(mmcp->config->spip, 1U, mmcp->buffer); - if (mmcp->buffer[0] == 0xFFU) { + unsigned i, j; + + /* Poll a buffer at a time rather than a byte. Either size is one DMA setup + and one thread suspend, so a byte at a time pays that overhead sixteen + times over for the same sixteen byte-times on the wire. Overshooting past + the moment the card goes idle is free - the extra bytes are clocked + against an idle bus, and a gap before the next token is allowed. + + Two reads land before the first sleep, which measurement showed resolves + 87% of the waits that outlast the in-frame busy window. The rest are the + card erasing internally, hundreds of microseconds to ten milliseconds, so + they are waited on rather than polled.*/ + (void) spiReceive(mmcp->config->spip, MMC_BUFFER_SIZE, mmcp->buffer); + for (j = 0U; j < MMC_BUFFER_SIZE; j++) { + if (mmcp->buffer[j] == 0xFFU) { return HAL_SUCCESS; } } @@ -311,9 +321,11 @@ static bool mmc_wait_idle(MMCDriver *mmcp) { /* Looks like it is a long wait.*/ i = 0U; do { - (void) spiReceive(mmcp->config->spip, 1U, mmcp->buffer); - if (mmcp->buffer[0] == 0xFFU) { - return HAL_SUCCESS; + (void) spiReceive(mmcp->config->spip, MMC_BUFFER_SIZE, mmcp->buffer); + for (j = 0U; j < MMC_BUFFER_SIZE; j++) { + if (mmcp->buffer[j] == 0xFFU) { + return HAL_SUCCESS; + } } /* Trying to be nice with the other threads.*/ @@ -1018,12 +1030,12 @@ bool mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer) { (void) spiExchange(mmcp->config->spip, MMC_WRITE_FRAME_SIZE, f, f); mmcp->buffer[0] = f[2U + MMCSD_BLOCK_SIZE + 2U]; - /* The busy window still earns its place: the card usually finishes - programming inside it, so the poll below returns on its first byte. - It is not evidence on its own though - a card that has not yet pulled - MISO low reads back all ones, which is indistinguishable from one that - has finished. Treating that as done sends the next data token into a - busy card, which discards the block and reports nothing.*/ + /* The busy window still earns its place: the card finishes programming + inside it about nine times in ten, so the poll below returns on its + first byte. It is not evidence on its own though - a card that has not + yet pulled MISO low reads back all ones, which is indistinguishable + from one that has finished. Treating that as done sends the next data + token into a busy card, which discards the block and reports nothing.*/ } else { (void) spiSend(mmcp->config->spip, sizeof(start), start); /* Data prologue. */ From ccc41e1330c03c0df0a9bbd1f3f20be5e98136bb Mon Sep 17 00:00:00 2001 From: Andy Piper Date: Mon, 7 Sep 2026 12:19:20 +0100 Subject: [PATCH 16/21] RP: don't store spi dummytx data in flash --- os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.c b/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.c index c24fd031a3..ad5eaacaea 100644 --- a/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.c +++ b/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.c @@ -52,7 +52,7 @@ SPIDriver SPID1; /* Driver local variables and types. */ /*===========================================================================*/ -static const uint16_t dummytx = 0xFFFFU; +static uint16_t dummytx = 0xFFFFU; static uint16_t dummyrx; /*===========================================================================*/ From db33eee7078eca3b6eb819e9318f800dd06376ee Mon Sep 17 00:00:00 2001 From: Andy Piper Date: Mon, 7 Sep 2026 15:50:52 +0100 Subject: [PATCH 17/21] RP SPI: implement spi_lld_abort and detect receive overruns Two silent failure modes on the RP SPIv1 port, both of which corrupt a transfer without reporting anything. spi_lld_abort() was an empty stub gated on SPI_SUPPORTS_CIRCULAR, which this port declares FALSE, so a transfer abandoned on timeout had nothing to tear it down. Its DMA stayed armed and whatever the device had already clocked in stayed in the receive FIFO, where the next transfer's DMA takes those bytes ahead of its own and shifts everything it reads. Implement it for real - stop both channels, drain the receive FIFO, cycle SSE to clear the transmit side - and drop the gate, since aborting a timed out transfer is not specific to circular mode. Upstream ChibiOS master and stable_21.11.x both still carry the stub. Nothing ever read SSPRIS or wrote SSPICR either, so an SSP receive overrun was invisible: the transfer completes, the DMA moves its full count, and the caller gets a buffer shifted down by one from the discarded byte. Check and clear it in the rx service routine and count it per driver. Counters are per SPIDriver so a non-zero value is attributable to a bus. --- os/common/ext/RP/RP2350/rp2350.h | 11 ++++++ os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.c | 52 +++++++++++++++++++++++-- os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.h | 11 ++++-- 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/os/common/ext/RP/RP2350/rp2350.h b/os/common/ext/RP/RP2350/rp2350.h index 72a13d1b96..60e0bab1ac 100644 --- a/os/common/ext/RP/RP2350/rp2350.h +++ b/os/common/ext/RP/RP2350/rp2350.h @@ -1927,6 +1927,17 @@ typedef struct { #define SPI_SSPIMSC_RORIM_Msk (1U << SPI_SSPIMSC_RORIM_Pos) #define SPI_SSPIMSC_RORIM SPI_SSPIMSC_RORIM_Msk +#define SPI_SSPRIS_RORRIS_Pos 0U +#define SPI_SSPRIS_RORRIS_Msk (1U << SPI_SSPRIS_RORRIS_Pos) +#define SPI_SSPRIS_RORRIS SPI_SSPRIS_RORRIS_Msk + +#define SPI_SSPICR_RORIC_Pos 0U +#define SPI_SSPICR_RORIC_Msk (1U << SPI_SSPICR_RORIC_Pos) +#define SPI_SSPICR_RORIC SPI_SSPICR_RORIC_Msk +#define SPI_SSPICR_RTIC_Pos 1U +#define SPI_SSPICR_RTIC_Msk (1U << SPI_SSPICR_RTIC_Pos) +#define SPI_SSPICR_RTIC SPI_SSPICR_RTIC_Msk + #define SPI_SSPDMACR_TXDMAE_Pos 1U #define SPI_SSPDMACR_TXDMAE_Msk (1U << SPI_SSPDMACR_TXDMAE_Pos) #define SPI_SSPDMACR_TXDMAE SPI_SSPDMACR_TXDMAE_Msk diff --git a/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.c b/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.c index ad5eaacaea..c8c5778eea 100644 --- a/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.c +++ b/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.c @@ -67,6 +67,17 @@ static uint16_t dummyrx; */ static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t ct) { + /* Receive overrun. The SSP keeps clocking for as long as the TX FIFO has + data, so a receive FIFO that fills faster than the DMA drains it makes + the SSP discard the arriving byte and set RORRIS. Nothing else reports + it: the transfer completes, the DMA moves its full count, and the caller + sees a buffer whose contents past the discarded byte are shifted down by + one. Count it so that corruption is attributable rather than silent.*/ + if ((spip->spi->SSPRIS & SPI_SSPRIS_RORRIS) != 0U) { + spip->rxoverruns++; + spip->spi->SSPICR = SPI_SSPICR_RORIC; + } + /* DMA errors handling.*/ if ((ct & DMA_CTRL_TRIG_AHB_ERROR) != 0U) { @@ -418,9 +429,16 @@ void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) { dmaChannelEnableX(spip->dmatx); } -#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__) /** * @brief Aborts the ongoing SPI operation, if any. + * @details Stops both DMA channels and leaves the SSP with empty FIFOs, so + * that the next transfer starts from a known state. + * @note Upstream leaves this empty and gates it on SPI_SUPPORTS_CIRCULAR, + * which this port declares FALSE. A transfer abandoned on timeout + * therefore had nothing tear it down: the DMA stayed armed and + * whatever the peripheral had already clocked in stayed in the + * receive FIFO, where the next transfer's DMA would consume it ahead + * of its own data and shift everything it read. * * @param[in] spip pointer to the @p SPIDriver object * @@ -428,9 +446,37 @@ void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) { */ void spi_lld_abort(SPIDriver *spip) { - (void)spip; + spip->aborts++; + + /* DMA first: nothing should be moving while the FIFOs are drained.*/ + if (spip->dmatx != NULL) { + dmaChannelDisableX(spip->dmatx); + } + if (spip->dmarx != NULL) { + dmaChannelDisableX(spip->dmarx); + } + + /* Drain the receive FIFO explicitly rather than relying on the SSE cycle + below to do it. The loop is bounded by the FIFO depth so that a stuck + RNE cannot hang the caller.*/ + { + unsigned i; + + for (i = 0U; i < 8U; i++) { + if ((spip->spi->SSPSR & SPI_SSPSR_RNE) == 0U) { + break; + } + (void) spip->spi->SSPDR; + } + } + + /* Cycle SSE to clear anything left in the transmit FIFO, then drop the + stale error flags. RORRIS in particular is sticky and would otherwise be + attributed to the next transfer.*/ + spip->spi->SSPCR1 &= ~SPI_SSPCR1_SSE; + spip->spi->SSPICR = SPI_SSPICR_RORIC | SPI_SSPICR_RTIC; + spip->spi->SSPCR1 |= SPI_SSPCR1_SSE; } -#endif /* SPI_SUPPORTS_CIRCULAR == TRUE */ /** * @brief Exchanges one frame using a polled wait. diff --git a/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.h b/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.h index 551a129339..c65a9bbe65 100644 --- a/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.h +++ b/os/hal/ports/RP/LLD/SPIv1/hal_spi_lld.h @@ -154,7 +154,11 @@ /* RX DMA mode bit mask.*/ \ uint32_t rxdmamode; \ /* TX DMA mode bit mask.*/ \ - uint32_t txdmamode; + uint32_t txdmamode; \ + /* Transfers that ended with an SSP receive overrun.*/ \ + uint32_t rxoverruns; \ + /* Transfers torn down by spi_lld_abort().*/ \ + uint32_t aborts; /** * @brief Low level fields of the SPI configuration structure. @@ -192,9 +196,10 @@ extern "C" { const void *txbuf, void *rxbuf); void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf); void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf); -#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__) + /* Not gated on SPI_SUPPORTS_CIRCULAR. Upstream only needs an abort to stop + a circular transfer, but a transfer that timed out has to be torn down on + any port, and this one declares circular support FALSE.*/ void spi_lld_abort(SPIDriver *spip); -#endif uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame); #ifdef __cplusplus } From eae870e687b6e5fc3ebb295306a997980ba6f1c4 Mon Sep 17 00:00:00 2001 From: Andy Piper Date: Tue, 8 Sep 2026 17:05:49 +0100 Subject: [PATCH 18/21] RP: run the shared DMA vector at the most urgent priority asked for A core's DMA channels all share one interrupt, so the priority argument to dmaChannelAllocI() cannot be per channel. It was applied only to the first allocation for a core and silently discarded for every later one, which made the result depend on driver init order. On an RP2350 with SPI0 pinned to core1 that put the IMU's transfers at whatever priority the first unrelated driver to take a channel happened to want - 6 rather than the 2 the SPI driver asked for, because an overlay claimed a channel earlier in boot. Core 0 had the same problem, with the ADC's 3 sitting where SPI wanted 2. Track the most urgent request per core and lower the vector to match, so the outcome is the same whoever allocates first. --- os/hal/ports/RP/LLD/DMAv1/rp_dma.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/os/hal/ports/RP/LLD/DMAv1/rp_dma.c b/os/hal/ports/RP/LLD/DMAv1/rp_dma.c index e47e2d7377..d30e35b8d2 100644 --- a/os/hal/ports/RP/LLD/DMAv1/rp_dma.c +++ b/os/hal/ports/RP/LLD/DMAv1/rp_dma.c @@ -81,6 +81,13 @@ static struct { * @brief Mask of the allocated channels for core 1. */ uint32_t c1_allocated_mask; + /** + * @brief Most urgent priority requested by a channel of each core. + * @note All channels of a core share one vector, so it has to run at + * the most urgent priority any of them asked for. + */ + uint32_t c0_priority; + uint32_t c1_priority; /** * @brief DMA IRQ redirectors. */ @@ -247,16 +254,25 @@ const rp_dma_channel_t *dmaChannelAllocI(uint32_t id, rp_peripheral_unreset(RESETS_ALLREG_DMA); } + /* A core's channels all share one vector, so the priority argument + cannot be per channel: the vector runs at the most urgent priority + any of its channels asked for. Enabling it only for the first + allocation silently discarded every later request, which made the + result depend on driver init order - on an RP2350 with SPI0 on core1 + the IMU's transfers ran at whatever the first unrelated driver to + take a channel happened to want.*/ if (SIO->CPUID == 0U) { /* Channel taken by core 0.*/ - if (dma.c0_allocated_mask == 0U) { + if ((dma.c0_allocated_mask == 0U) || (priority < dma.c0_priority)) { + dma.c0_priority = priority; nvicEnableVector(RP_DMA_IRQ_0_NUMBER, priority); } dma.c0_allocated_mask |= dmachp->chnmask; } else { /* Channel taken by core 1.*/ - if (dma.c1_allocated_mask == 0U) { + if ((dma.c1_allocated_mask == 0U) || (priority < dma.c1_priority)) { + dma.c1_priority = priority; nvicEnableVector(RP_DMA_IRQ_1_NUMBER, priority); } dma.c1_allocated_mask |= dmachp->chnmask; From 63cd89e0f6c0493fdd5bac3636dc360f5e395caf Mon Sep 17 00:00:00 2001 From: Andy Piper Date: Tue, 8 Sep 2026 21:44:41 +0100 Subject: [PATCH 19/21] RP: optional write path statistics for the MMC-SPI driver Counters splitting a block into wire time, card busy time and the rest, plus the distribution of blocks per disk_write call. Off by default; MMC_USE_WRITE_STATS TRUE turns them on. They are what found the real cost of the write path on RP2350: the logger was syncing every 4 KB, so four fifths of everything reaching the card was single sector filesystem metadata, and the card's apparent program time was mostly the consequence of being asked for eight times too many program cycles rather than the card being slow. Two traps worth knowing before reading them. A poll is a 16 byte exchange, so mmc_wait_idle can never take zero microseconds at 1 us resolution - an earlier "no wait" counter measured nothing. And the outcome counters catch every caller of mmc_wait_idle, not only the per block one, so their proportions are usable and their absolute counts are not per block. --- os/hal/include/hal_mmc_spi.h | 11 ++++++ os/hal/src/hal_mmc_spi.c | 67 ++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/os/hal/include/hal_mmc_spi.h b/os/hal/include/hal_mmc_spi.h index 0214d18487..45c0181411 100644 --- a/os/hal/include/hal_mmc_spi.h +++ b/os/hal/include/hal_mmc_spi.h @@ -85,6 +85,17 @@ #if !defined(MMC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) #define MMC_USE_MUTUAL_EXCLUSION TRUE #endif + +/** + * @brief Write path statistics, readable by a debugger. + * @details Counters splitting the cost of a block into wire time, card busy + * time and the rest, plus the distribution of blocks per + * @p disk_write call. Investigation only - each block pays four + * reads of the system time. + */ +#if !defined(MMC_USE_WRITE_STATS) || defined(__DOXYGEN__) +#define MMC_USE_WRITE_STATS FALSE +#endif /** @} */ /*===========================================================================*/ diff --git a/os/hal/src/hal_mmc_spi.c b/os/hal/src/hal_mmc_spi.c index f6238bfbd2..e5d823b79b 100644 --- a/os/hal/src/hal_mmc_spi.c +++ b/os/hal/src/hal_mmc_spi.c @@ -209,10 +209,40 @@ static bool mmc_read(void *instance, uint32_t startblk, return err; } +#if MMC_USE_WRITE_STATS == TRUE +/* Write path instrumentation: partitions the cost of a block into wire time, + card busy time and everything else, so the ceiling this hardware can reach + can be told apart from what the scheduling around it is costing. Read with + a debugger; see hwdef/RPI_UAVFC/DEVELOPMENT.md for what the numbers mean. */ +volatile uint32_t mmc_wr_blocks; +volatile uint32_t mmc_wr_calls; +volatile uint32_t mmc_wr_us_exchange; +volatile uint32_t mmc_wr_us_idle; +volatile uint32_t mmc_wr_us_block; +volatile uint32_t mmc_wr_us_call; +volatile uint32_t mmc_wr_us_idle_max; +/* mmc_wait_idle outcome. A poll is a 16 byte exchange, so it can never take + zero microseconds - the earlier "zero wait" counter measured nothing. What + matters is whether the card was ready before the fixed 500 us sleep, since + a sleep that overshoots real readiness is a software cost wearing the + card's clothes. */ +volatile uint32_t mmc_wr_idle_p1; +volatile uint32_t mmc_wr_idle_p2; +volatile uint32_t mmc_wr_idle_slept; +volatile uint32_t mmc_wr_idle_sleeps; +/* blocks per disk_write, to see how much of the 4 KB chunk survives FATFS */ +volatile uint32_t mmc_wr_n_hist[10]; +#endif /* MMC_USE_WRITE_STATS */ + static bool mmc_write(void *instance, uint32_t startblk, const uint8_t *buffer, uint32_t n) { MMCDriver *mmcp = (MMCDriver *)instance; bool err = HAL_FAILED; +#if MMC_USE_WRITE_STATS == TRUE + const systime_t t_c0 = osalOsGetSystemTimeX(); + + mmc_wr_n_hist[(n < 9U) ? n : 9U]++; +#endif #if MMC_USE_MUTUAL_EXCLUSION == TRUE spiAcquireBus(mmcp->config->spip); @@ -242,6 +272,11 @@ static bool mmc_write(void *instance, uint32_t startblk, spiReleaseBus(mmcp->config->spip); #endif +#if MMC_USE_WRITE_STATS == TRUE + mmc_wr_us_call += (uint32_t)(osalOsGetSystemTimeX() - t_c0); + mmc_wr_calls++; +#endif + return err; } @@ -314,6 +349,9 @@ static bool mmc_wait_idle(MMCDriver *mmcp) { (void) spiReceive(mmcp->config->spip, MMC_BUFFER_SIZE, mmcp->buffer); for (j = 0U; j < MMC_BUFFER_SIZE; j++) { if (mmcp->buffer[j] == 0xFFU) { +#if MMC_USE_WRITE_STATS == TRUE + mmc_wr_idle_p1++; +#endif return HAL_SUCCESS; } } @@ -324,12 +362,23 @@ static bool mmc_wait_idle(MMCDriver *mmcp) { (void) spiReceive(mmcp->config->spip, MMC_BUFFER_SIZE, mmcp->buffer); for (j = 0U; j < MMC_BUFFER_SIZE; j++) { if (mmcp->buffer[j] == 0xFFU) { +#if MMC_USE_WRITE_STATS == TRUE + if (i == 0U) { + mmc_wr_idle_p2++; + } + else { + mmc_wr_idle_slept++; + } +#endif return HAL_SUCCESS; } } /* Trying to be nice with the other threads.*/ osalThreadSleepMicroseconds(MMC_WRITE_WAIT_USEC); +#if MMC_USE_WRITE_STATS == TRUE + mmc_wr_idle_sleeps++; +#endif } while (++i < MMC_TIMEOUT_WRITE); return HAL_FAILED; @@ -1027,7 +1076,13 @@ bool mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer) { /* In place: the transmit side of each byte is consumed before the received byte replaces it.*/ +#if MMC_USE_WRITE_STATS == TRUE + const systime_t t_x0 = osalOsGetSystemTimeX(); +#endif (void) spiExchange(mmcp->config->spip, MMC_WRITE_FRAME_SIZE, f, f); +#if MMC_USE_WRITE_STATS == TRUE + mmc_wr_us_exchange += (uint32_t)(osalOsGetSystemTimeX() - t_x0); +#endif mmcp->buffer[0] = f[2U + MMCSD_BLOCK_SIZE + 2U]; /* The busy window still earns its place: the card finishes programming @@ -1045,7 +1100,19 @@ bool mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer) { } if ((mmcp->buffer[0] & 0x1FU) == 0x05U) { +#if MMC_USE_WRITE_STATS == TRUE + const systime_t t_i0 = osalOsGetSystemTimeX(); + const bool res = mmc_wait_idle(mmcp); + const uint32_t dt = (uint32_t)(osalOsGetSystemTimeX() - t_i0); + mmc_wr_us_idle += dt; + if (dt > mmc_wr_us_idle_max) { + mmc_wr_us_idle_max = dt; + } + mmc_wr_blocks++; + return res; +#else return mmc_wait_idle(mmcp); +#endif } /* Error.*/ From af493a7bd5320ed1ffcce83e4202792867fbace7 Mon Sep 17 00:00:00 2001 From: Andy Piper Date: Tue, 15 Sep 2026 14:09:56 +0100 Subject: [PATCH 20/21] RT: re-read the system state while waiting for it chSysWaitSystemState() polls ch_system.state, which another core writes, but the field is not volatile. The compiler loads it once before the loop and then compares the cached value forever, so a core that arrives before chSysInit() has finished on the other core never leaves. On RP2350 core1 calls it from c1_main(). It only worked because core1's CRT0 filled a 16 KB process stack first; with a 1 KB stack core1 won the race and hung with the kernel state already running. --- os/rt/src/chsys.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/os/rt/src/chsys.c b/os/rt/src/chsys.c index 2e32b37ade..8acdde56c3 100644 --- a/os/rt/src/chsys.c +++ b/os/rt/src/chsys.c @@ -140,7 +140,9 @@ const os_instance_config_t ch_core1_cfg = { */ void chSysWaitSystemState(system_state_t state) { - while (ch_system.state != state) { + /* The state is written by another core, reading it through a volatile + pointer stops the compiler sampling it only once before the loop.*/ + while (*(volatile system_state_t *)&ch_system.state != state) { } } From 4723972c44a9a5d26c02d95c4c694ebbb9266b03 Mon Sep 17 00:00:00 2001 From: Andy Piper Date: Fri, 18 Sep 2026 10:17:57 +0100 Subject: [PATCH 21/21] RP: keep an output driven while its pad mode is re-applied rp_pal_pad_set_mode() cleared the pin's output enable before rewriting the mux and pad registers and set it again afterwards, so re-applying the mode of a pin that was already driving left it to the board's pull for the length of the reprogramming - longer if the caller was preempted in between, since nothing masks interrupts there. On RPI_UAVFC the regulator enables for the 5V and video rails are GPIO outputs held off by pull-downs, and ArduPilot's relay library re-applied the output mode on every read, so a read could drop a rail. An output now keeps its driver: the mux and pad are written and OE set, with no release. Inputs still release OE first. --- os/hal/ports/RP/LLD/GPIOv1/hal_pal_lld.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/os/hal/ports/RP/LLD/GPIOv1/hal_pal_lld.c b/os/hal/ports/RP/LLD/GPIOv1/hal_pal_lld.c index 778bd303ee..756635f930 100644 --- a/os/hal/ports/RP/LLD/GPIOv1/hal_pal_lld.c +++ b/os/hal/ports/RP/LLD/GPIOv1/hal_pal_lld.c @@ -82,15 +82,19 @@ static void rp_pal_pad_set_mode(ioportid_t port, return; } - /* Release the output driver while reprogramming mux and pad control. */ - RP_PAL_SIO_REG(GPIO_OE_CLR, port) = bit; - - IO_BANK0->GPIO[abspad].CTRL = ctrlbits; - PADS_BANK0->GPIO[abspad] = padbits; - if (oebits != 0U) { + /* An output keeps its driver: re-applying the mode of a pin that is + already driving must not hand it to the board's pull meanwhile. */ + IO_BANK0->GPIO[abspad].CTRL = ctrlbits; + PADS_BANK0->GPIO[abspad] = padbits; RP_PAL_SIO_REG(GPIO_OE_SET, port) = bit; } + else { + /* Release the output driver while reprogramming mux and pad control. */ + RP_PAL_SIO_REG(GPIO_OE_CLR, port) = bit; + IO_BANK0->GPIO[abspad].CTRL = ctrlbits; + PADS_BANK0->GPIO[abspad] = padbits; + } } /*===========================================================================*/