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..60e0bab1ac --- /dev/null +++ b/os/common/ext/RP/RP2350/rp2350.h @@ -0,0 +1,3055 @@ +/* + 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_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 +#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..274a2d23a3 --- /dev/null +++ b/os/common/ports/ARMv8-M-ML-ALT/compilers/GCC/chcoreasm.S @@ -0,0 +1,408 @@ +/* + 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 + +/*--------------------------------------------------------------------------* + * 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. + *--------------------------------------------------------------------------*/ + .section .text.SVC_Handler, "ax", %progbits + .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. + *--------------------------------------------------------------------------*/ + .section .text.PendSV_Handler, "ax", %progbits + .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. + *--------------------------------------------------------------------------*/ + .section .text.__port_thread_start, "ax", %progbits + .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..b657303756 --- /dev/null +++ b/os/common/ports/ARMv8-M-ML-ALT/smp/rp2/chcoresmp.c @@ -0,0 +1,152 @@ +/* + 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" +#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. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* 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_mmc_spi.h b/os/hal/include/hal_mmc_spi.h index 5358f6e05f..45c0181411 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. */ /*===========================================================================*/ @@ -65,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 /** @} */ /*===========================================================================*/ @@ -145,6 +176,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/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..b53e73a205 --- /dev/null +++ b/os/hal/ports/RP/LLD/ADCv1/hal_adc_lld.c @@ -0,0 +1,439 @@ +/* + 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) +/* 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) +/** @} */ + +/*===========================================================================*/ +/* 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 (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 + */ +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, 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 | PADS_GPIO_ISO); + 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..d30e35b8d2 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] = { +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 }; /*===========================================================================*/ @@ -74,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. */ @@ -86,7 +100,7 @@ static struct { * @brief DMA callback parameter. */ void *param; - } channels[RP_DMA_CHANNELS]; + } channels[RP_DMA_NUM_CHANNELS]; } dma; /*===========================================================================*/ @@ -184,7 +198,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,26 +249,35 @@ 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); + } + + /* 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; } - /* Releasing DMA reset if it is the 1st channel taken.*/ - if (prevmask == 0U) { - hal_lld_peripheral_unreset(RESETS_ALLREG_DMA); - } - return dmachp; } } @@ -314,17 +337,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); } } @@ -335,7 +363,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..6284b83461 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 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 @@ -160,11 +157,17 @@ __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 | DMA_CTRL_TRIG_WRITE_ERROR; + dmachp->dma->INTS0 = dmachp->chnmask; + dmachp->dma->INTS1 = dmachp->chnmask; + return ctrl_trig; } @@ -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; } @@ -268,6 +277,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 +286,17 @@ __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 & + ~(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..756635f930 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,55 @@ 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; + } + + 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; + } +} + /*===========================================================================*/ /* 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 +111,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 +123,8 @@ OSAL_IRQ_HANDLER(RP_IO_IRQ_BANK0_HANDLER) { } ints >>= 4; ++line; - }; - }; + } + } OSAL_IRQ_EPILOGUE(); } @@ -91,15 +139,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 +158,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 +240,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 +262,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 +279,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..9d84f6f9c3 --- /dev/null +++ b/os/hal/ports/RP/LLD/PWMv1/hal_pwm_lld.c @@ -0,0 +1,560 @@ +/* + 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. + * 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; + + 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; + + /* 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; + + 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..c8c5778eea 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; /*===========================================================================*/ @@ -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) { @@ -175,7 +186,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,13 +203,30 @@ 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 { 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); @@ -251,12 +279,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 { @@ -401,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 * @@ -411,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. @@ -431,10 +494,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..c65a9bbe65 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) @@ -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 } 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..827675b1b5 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,17 @@ __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->UARTIFLS = siop->config->UARTIFLS; + siop->uart->UARTDMACR = siop->config->UARTDMACR; + siop->uart->UARTCR = cr | UART_UARTCR_RXE | UART_UARTCR_TXE | UART_UARTCR_UARTEN; } /*===========================================================================*/ @@ -154,12 +157,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 +189,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 +228,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 +544,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..e7e44b90aa --- /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; + + if (ep == 0) { + ep_ctrl = USB->SIECTRL; + } else { + ep_ctrl = EP_CTRL(ep).IN; + } + + /* 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); + + /* 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_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; +} + +/** + * @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..11a79a5e2a --- /dev/null +++ b/os/hal/ports/RP/RP2350/rp_clocks.c @@ -0,0 +1,341 @@ +/* + 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 +#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. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* 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. */ +/*===========================================================================*/ + +/** + * @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) { + + /* 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). */ + /* 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__); + volatile uint32_t *dst = &__ramfunc_start__; + volatile uint32_t *end = &__ramfunc_end__; + while (dst < end) { + *dst++ = *src++; + } + } + + /* 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 */ + } + +#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); + + /* 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..62997f45fa --- /dev/null +++ b/os/hal/ports/RP/RP2350/rp_registry.h @@ -0,0 +1,139 @@ +/* + 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. + 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_TEMPERATURE_CHANNEL 4U +#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 + +/** @} */ + +#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 */ + +/** @} */ diff --git a/os/hal/src/hal_mmc_spi.c b/os/hal/src/hal_mmc_spi.c index 728ce47693..e5d823b79b 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 @@ -208,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); @@ -241,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; } @@ -298,11 +334,24 @@ 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) { +#if MMC_USE_WRITE_STATS == TRUE + mmc_wr_idle_p1++; +#endif return HAL_SUCCESS; } } @@ -310,13 +359,26 @@ 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) { +#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; @@ -567,6 +629,7 @@ void mmcObjectInit(MMCDriver *mmcp, uint8_t *buffer) { mmcp->config = NULL; mmcp->block_addresses = false; mmcp->buffer = buffer; + mmcp->wbuffer = NULL; } /** @@ -993,12 +1056,63 @@ 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.*/ +#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 + 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. */ + (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) { +#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.*/ 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/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) { } } 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