From 359d3a9efdba0ce5648f1186d0f5c5cba363e240 Mon Sep 17 00:00:00 2001 From: AnnsAnn Date: Tue, 10 Jun 2025 12:02:30 +0200 Subject: [PATCH] boards: Raspberry Pi Pico 2 support --- boards/rpi-pico-2/Kconfig | 11 ++ boards/rpi-pico-2/Makefile | 3 + boards/rpi-pico-2/Makefile.features | 1 + boards/rpi-pico-2/Makefile.include | 7 ++ boards/rpi-pico-2/board.c | 15 +++ boards/rpi-pico-2/dist/openocd.cfg | 7 ++ boards/rpi-pico-2/doc.md | 116 +++++++++++++++++ boards/rpi-pico-2/include/board.h | 43 +++++++ boards/rpi-pico-2/include/gpio_params.h | 18 +++ boards/rpi-pico-2/include/periph_conf.h | 20 +++ cpu/rp2350/Kconfig | 9 +- cpu/rp2350/Makefile | 11 +- cpu/rp2350/Makefile.dep | 1 + cpu/rp2350/Makefile.features | 2 + cpu/rp2350/Makefile.include | 17 ++- cpu/rp2350/clock.c | 84 ++++++++----- cpu/rp2350/cpu.c | 50 ++++++-- cpu/rp2350/doc.md | 5 + cpu/rp2350/doc.txt | 8 -- cpu/rp2350/include/clock_conf.h | 160 +++++++++++++++++------- cpu/rp2350/include/cpu_conf.h | 25 +++- cpu/rp2350/include/gpio_conf.h | 75 ++++++++--- cpu/rp2350/include/helpers.h | 70 ++++++++--- cpu/rp2350/include/periph_cpu.h | 92 ++++++++++---- cpu/rp2350/include/uart_conf.h | 57 +++++++-- cpu/rp2350/periph/gpio.c | 75 +++++++---- cpu/rp2350/periph/uart.c | 102 ++++++++++----- cpu/rp2350/picobin_block.s | 54 ++++---- cpu/rp2350/vectors.c | 134 ++++++++++---------- cpu/rp2350/xosc.c | 55 ++++---- makefiles/features_existing.inc.mk | 2 +- 31 files changed, 950 insertions(+), 379 deletions(-) create mode 100644 boards/rpi-pico-2/Kconfig create mode 100644 boards/rpi-pico-2/Makefile create mode 100644 boards/rpi-pico-2/Makefile.features create mode 100644 boards/rpi-pico-2/Makefile.include create mode 100644 boards/rpi-pico-2/board.c create mode 100644 boards/rpi-pico-2/dist/openocd.cfg create mode 100644 boards/rpi-pico-2/doc.md create mode 100644 boards/rpi-pico-2/include/board.h create mode 100644 boards/rpi-pico-2/include/gpio_params.h create mode 100644 boards/rpi-pico-2/include/periph_conf.h create mode 100644 cpu/rp2350/doc.md delete mode 100644 cpu/rp2350/doc.txt diff --git a/boards/rpi-pico-2/Kconfig b/boards/rpi-pico-2/Kconfig new file mode 100644 index 0000000000..d0ac0bb574 --- /dev/null +++ b/boards/rpi-pico-2/Kconfig @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2025 Tom Hert +# SPDX-FileCopyrightText: 2025 HAW Hamburg +# SPDX-License-Identifier: LGPL-2.1-only + +config BOARD + default "rpi-pico-2" if BOARD_RPI_PICO_2 + +config BOARD_RPI_PICO_2 + bool + default y + select CPU_MODEL_RP2350 diff --git a/boards/rpi-pico-2/Makefile b/boards/rpi-pico-2/Makefile new file mode 100644 index 0000000000..f8fcbb53a0 --- /dev/null +++ b/boards/rpi-pico-2/Makefile @@ -0,0 +1,3 @@ +MODULE = board + +include $(RIOTBASE)/Makefile.base diff --git a/boards/rpi-pico-2/Makefile.features b/boards/rpi-pico-2/Makefile.features new file mode 100644 index 0000000000..b19f996d14 --- /dev/null +++ b/boards/rpi-pico-2/Makefile.features @@ -0,0 +1 @@ +CPU := rp2350 diff --git a/boards/rpi-pico-2/Makefile.include b/boards/rpi-pico-2/Makefile.include new file mode 100644 index 0000000000..b80aa5b4da --- /dev/null +++ b/boards/rpi-pico-2/Makefile.include @@ -0,0 +1,7 @@ +CPU_MODEL := RP2350 +PORT_LINUX ?= /dev/ttyACM0 + +# JLink isnt tested yet on RP2350 +# ifeq ($(PROGRAMMER),jlink) +# JLINK_DEVICE = RP2350_M33_0 +# endif diff --git a/boards/rpi-pico-2/board.c b/boards/rpi-pico-2/board.c new file mode 100644 index 0000000000..49f7740789 --- /dev/null +++ b/boards/rpi-pico-2/board.c @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: 2025 Tom Hert + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only + */ + +#include "board.h" + +void board_init(void) { + /* Re-enable the LED0 pin + * Otherwise the LED will not work after a reset + * This is needed, esp. when the LED is used via + * the define macros */ + gpio_init(LED0_PIN_ID, GPIO_OUT); +} diff --git a/boards/rpi-pico-2/dist/openocd.cfg b/boards/rpi-pico-2/dist/openocd.cfg new file mode 100644 index 0000000000..69faf2c879 --- /dev/null +++ b/boards/rpi-pico-2/dist/openocd.cfg @@ -0,0 +1,7 @@ +echo "Make sure to use the Raspberry Pi OpenOCD version!" +source [find target/rp2350.cfg] +set USE_CORE 0 +set RESCUE 1 +$_TARGETNAME_0 configure -rtos auto +adapter speed 5000 +rp2350.dap.core1 cortex_m reset_config sysresetreq diff --git a/boards/rpi-pico-2/doc.md b/boards/rpi-pico-2/doc.md new file mode 100644 index 0000000000..f441304714 --- /dev/null +++ b/boards/rpi-pico-2/doc.md @@ -0,0 +1,116 @@ +@defgroup boards_rpi_pico_2 Raspberry Pi Pico 2 +@ingroup boards +@brief Support for the RP2350 based Raspberry Pi Pico board + +@warning The support for the Raspberry Pi Pico 2 is still in a very early stage! +See [Known Issues](#rpi_pico_2_known_issues). + +## Overview + +The Raspberry Pi Pico 2 is a microcontroller board based on the RP2350 chip, +featuring dual-core Arm Cortex-M0+ processors and RISC-V Hazard secondary +architecture. It is designed for a wide range of applications, +from hobbyist projects to professional embedded systems +for a fairly affordable price. + +![The Raspberry Pi Pico 2 Board](https://www.raspberrypi.com/documentation/microcontrollers/images/pico-2.png) + +## Hardware + +| MCU | RP2350 | +|:-----------|:------------------------------------------------------------| +| Family | Dual Cortex-M33 or Hazard3 (RISC-V) | +| Vendor | Raspberry Pi | +| RAM | 520 kB on-chip SRAM (10 independent banks) | +| Flash | Up to 16 MB external QSPI flash (Pico 2 has 4 MB by default)| +| Frequency | up to 150 MHz (Set to 125 MHz in RIOT) | +| Security | Boot signing, key storage, SHA-256 accelerator | +| PIOs | 12 state machines | +| UARTs | 2 | +| SPIs | 2 | +| I2Cs | 2 | +| PWM | 24 channels | +| USB | USB 1.1 controller with host and device support | +| Power | On-chip switched-mode power supply with LDO sleep mode | +| OTP | 8 kB of one-time-programmable storage | +| Datasheet | [RP2350 Datasheet](https://datasheets.raspberrypi.com/rp2350/rp2350-datasheet.pdf) | + +## User Interfaces + +| Interface | Description | +|:-----------|:-------------------------------------------------------------| +| LED0 | User LED (GPIO 0 at Pin 25) | +| SW0 | Button used in flash process, can be accessed using registers but difficult | + +## Pinout + +![Pinout Diagram](https://www.raspberrypi.com/documentation/microcontrollers/images/pico-2-r4-pinout.svg) + +## Flashing the Board + +The Raspberry Pi Pico 2 has a built-in bootloader that allows flashing via USB. +However, you can also use OpenOCD for flashing the board. +If you are using picotool, you need to hold the bootselect button +(the only button on the board) while connecting the board to +your computer via USB. This will put the board into bootloader mode, +allowing you to flash it. + +### Flashing using OpenOCD + +If you have two Raspberry Pi Pico boards, +you can utilize one as a programmer to program the other board. + +Please refer to the +[Debugprobe documentation](https://www.raspberrypi.com/documentation/microcontrollers/debug-probe.html#getting-started) +for more details. + +Note that Raspberry Pi actually uses their own OpenOCD fork, which is available +in the [RP2040 OpenOCD repository](https://github.com/raspberrypi/openocd). +While technically you can use the standard OpenOCD, +it is recommended to use the Raspberry Pi fork for better compatibility with the +RP2350, as its still fairly "new" and under development, +which is why even their own Pico SDK Extension +uses the Raspberry Pi fork of OpenOCD, instead of the standard one. + +To do this, you need to connect the board to your computer +and use the following command: + +```bash +PROGRAMMER=openocd BOARD=rpi-pico-2 make flash +``` + +You can then debug your application using GDB with the following command: + +```bash +PROGRAMMER=openocd BOARD=rpi-pico-2 make debug +``` + +### Flashing using Picotool + +Simply connect the board to your computer via USB and use the following command: + +```bash +BOARD=rpi-pico-2 make flash +``` + +This is the default method for flashing the Raspberry Pi Pico 2. +However, it does not allow for debugging using GDB. + +@note When programming the board with the Picotool for the first time, +RIOT will download and install the Picotool locally in the RIOT folder. +This process will take some minutes to complete. + +## Known Issues {#rpi_pico_2_known_issues} + +Currently RP2350 support is rather minimal, +as such peripheral support is extremely limited. +The following peripherals are supported: + +- GPIO +- Non-configurable write-only UART (UART0 using Pin 0 and 1) + - The UART Baudrate is set to 115200. + - UART does not work via USB, you need to connect it directly to the GPIO pins. + +More peripherals will be added in the future. +It should also be noted that we currently only support the Cortex M33 cores, +not the RISC-V Hazard cores. diff --git a/boards/rpi-pico-2/include/board.h b/boards/rpi-pico-2/include/board.h new file mode 100644 index 0000000000..0cdbc0d51f --- /dev/null +++ b/boards/rpi-pico-2/include/board.h @@ -0,0 +1,43 @@ +/* + * SPDX-FileCopyrightText: 2025 Tom Hert + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only + */ + +#pragma once + +/** + * @ingroup boards_rpi_pico_2 + * @{ + * + * @file + * @brief Board specific definitions for the Raspberry Pi Pico 2 + * + * @author Tom Hert + */ + +#include "RP2350.h" +#include "cpu.h" +#include "cpu_conf.h" +#include "periph_conf.h" +#include "periph_cpu.h" + +/** GPIO Pin ID for the onboard LED */ +#define LED0_PIN_ID 25u +#define LED0_ON gpio_set(LED0_PIN_ID) +#define LED0_OFF gpio_clear(LED0_PIN_ID) +#define LED0_TOGGLE gpio_toggle(LED0_PIN_ID) +#define LED0_NAME "LED(Green)" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Initialize the board, called from the cpu startup code */ +void board_init(void); + +#ifdef __cplusplus +} +#endif + +/** @} */ diff --git a/boards/rpi-pico-2/include/gpio_params.h b/boards/rpi-pico-2/include/gpio_params.h new file mode 100644 index 0000000000..1998b8afaa --- /dev/null +++ b/boards/rpi-pico-2/include/gpio_params.h @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2025 Tom Hert + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only + */ + +#pragma once + +#include "board.h" +#include "saul/periph.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif diff --git a/boards/rpi-pico-2/include/periph_conf.h b/boards/rpi-pico-2/include/periph_conf.h new file mode 100644 index 0000000000..ed237d2c3b --- /dev/null +++ b/boards/rpi-pico-2/include/periph_conf.h @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: 2025 Tom Hert + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only + */ + +#pragma once + +#include + +#include "RP2350.h" +#include "periph_cpu.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif diff --git a/cpu/rp2350/Kconfig b/cpu/rp2350/Kconfig index 9433c08895..867bcf84f9 100644 --- a/cpu/rp2350/Kconfig +++ b/cpu/rp2350/Kconfig @@ -1,9 +1,6 @@ -# Copyright (C) 2021 Otto-von-Guericke-Universität Magdeburg -# -# This file is subject to the terms and conditions of the GNU Lesser -# General Public License v2.1. See the file LICENSE in the top level -# directory for more details. -# +# SPDX-FileCopyrightText: 2025 Tom Hert +# SPDX-FileCopyrightText: 2025 HAW Hamburg +# SPDX-License-Identifier: LGPL-2.1-only config CPU_FAM_RP2350 bool diff --git a/cpu/rp2350/Makefile b/cpu/rp2350/Makefile index 295f535853..33d57306d1 100644 --- a/cpu/rp2350/Makefile +++ b/cpu/rp2350/Makefile @@ -1,13 +1,6 @@ MODULE = cpu -USEPKG += picosdk - -DIRS = $(RIOTCPU)/cortexm_common periph +DIRS += $(RIOTCPU)/cortexm_common +DIRS += periph include $(RIOTBASE)/Makefile.base - -# Check if picosdk directory exists, otherwise build it -ifeq (,$(wildcard $(RIOTBASE)/dist/tools/picosdk/picosdk)) - $(info Building picosdk...) - $(shell $(MAKE) -C $(RIOTBASE)/dist/tools/picosdk) -endif diff --git a/cpu/rp2350/Makefile.dep b/cpu/rp2350/Makefile.dep index 1059dae00c..75b95e8112 100644 --- a/cpu/rp2350/Makefile.dep +++ b/cpu/rp2350/Makefile.dep @@ -1,2 +1,3 @@ +USEPKG += picosdk include $(RIOTCPU)/cortexm_common/Makefile.dep diff --git a/cpu/rp2350/Makefile.features b/cpu/rp2350/Makefile.features index 699c874028..5fc956bd1b 100644 --- a/cpu/rp2350/Makefile.features +++ b/cpu/rp2350/Makefile.features @@ -1,5 +1,7 @@ CPU_CORE := cortex-m33 CPU_FAM := RP2350 +CPU_ARCH = armv8m +CPU_MODEL = rp2350 include $(RIOTCPU)/cortexm_common/Makefile.features diff --git a/cpu/rp2350/Makefile.include b/cpu/rp2350/Makefile.include index 2ab2cde574..67a1064010 100644 --- a/cpu/rp2350/Makefile.include +++ b/cpu/rp2350/Makefile.include @@ -1,22 +1,19 @@ -ROM_LEN ?= 2097152 # = 2 MiB used in the RPi Pico -ROM_OFFSET := 0 # bootloader size -RAM_LEN := 0x82000 # 520kB = 532479 used in the RPi Pico 2350 +ROM_LEN ?= 2097152 # = 2 MiB used in the RPi Pico +ROM_OFFSET := 0 # bootloader size +RAM_LEN := 0x82000 # 520kB = 532479 used in the RPi Pico 2350 ROM_START_ADDR := 0x10000000 # XIP Non-Secure address for rp2350 RAM_START_ADDR := 0x20000000 # Non-Secure RAM address for rp2350 -# Specify CPU and FPU options -CPU_ARCH = armv8m -CPU_MODEL ?= rp2350 - # CPU and architecture specific flags CFLAGS += -D$(CPU_MODEL) CFLAGS += -DROM_START_ADDR=$(ROM_START_ADDR) CFLAGS += -DRAM_START_ADDR=$(RAM_START_ADDR) CFLAGS += -Wno-error + # Include paths INCLUDES += -I$(RIOTCPU)/rp2350/include -INCLUDES += -isystem$(RIOTBASE)/dist/tools/picosdk/picosdk/src/rp2_common/cmsis/stub/CMSIS/Core/Include -INCLUDES += -isystem$(RIOTBASE)/dist/tools/picosdk/picosdk/src/rp2_common/cmsis/stub/CMSIS/Device/RP2350/Include +INCLUDES += -isystem$(RIOTBASE)/build/pkg/picosdk/src/rp2_common/cmsis/stub/CMSIS/Core/Include +INCLUDES += -isystem$(RIOTBASE)/build/pkg/picosdk/src/rp2_common/cmsis/stub/CMSIS/Device/RP2350/Include # Linker flags LINKFLAGS += -mcpu=$(CPU_ARCH) -mthumb @@ -29,7 +26,7 @@ VECTORS_FILE := $(RIOTCPU)/rp2350/vectors.c # Supported programmers and debuggers PROGRAMMERS_SUPPORTED := picotool openocd jlink -PROGRAMMER ?= openocd +PROGRAMMER ?= picotool OPENOCD_DEBUG_ADAPTER ?= dap # Include the base Cortex-M makefile diff --git a/cpu/rp2350/clock.c b/cpu/rp2350/clock.c index 19b127a243..243b644511 100644 --- a/cpu/rp2350/clock.c +++ b/cpu/rp2350/clock.c @@ -1,51 +1,71 @@ +/* + * SPDX-FileCopyrightText: 2025 Tom Hert + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only + */ + +/** + * @ingroup cpu_rp2350 + * @{ + * + * @file + * @brief Clock configuration implementation for the RP2350 + * + * @author Tom Hert + */ + #include "periph_cpu.h" void clock_reset(void) { - // Reset the clock system + /* Reset the clock system */ reset_component(RESET_PLL_SYS, RESET_PLL_SYS); } /** * @brief Configures the XOSC and then sets CLK_SYS, PLL_SYS and CLK_PERI to it - * @warning Make sure to call clock_reset() before this function to reset the clock system - * @note RP2350 Docs Chapter 8, mostly 8.2 for more details -*/ -void cpu_clock_init(void) { - // Enable the XOSC - xosc_start(); + * @warning Make sure to call clock_reset() before this function to reset the + * clock system + * @see RP2350 Docs Chapter 8, mostly 8.2 for more details + */ +void cpu_clock_init(void) { + /* Enable the XOSC */ + xosc_start(); - /** - * Setup the PLL using the XOSC as the reference clock. - */ - //PLL_SYS->CS = REF_DIV; // Set the reference divider - PLL_SYS->FBDIV_INT = 125; // Set the feedback divider + /* Setup the PLL using the XOSC as the reference clock. */ + PLL_SYS->FBDIV_INT = + PLL_FEEDBACK_DIVIDER_VALUE; /* Set the feedback divider */ - /** - * Set the post-dividers for the PLL output. - */ + /* Set the post-dividers for the PLL output.*/ PLL_SYS->PRIM = PDIV; - // Turn on PLL - atomic_clear(&PLL_SYS->PWR, PLL_PWR_PD_BITS | PLL_PWR_VCOPD_BITS | PLL_PWR_POSTDIVPD_BITS); + /* Turn on PLL */ + atomic_clear(&PLL_SYS->PWR, + PLL_PWR_PD_BITS | PLL_PWR_VCOPD_BITS | PLL_PWR_POSTDIVPD_BITS); - // sleep 10ms to allow the PLL to stabilize + /* sleep 10ms to allow the PLL to stabilize */ xosc_sleep(10); - // // Wait for lock - // while (!(PLL_SYS->CS & PLL_CS_LOCK_BITS)) { - // // Wait for the PLL to lock - // } + /* Based on the description in chapter 8 this is something that should be done + * However, it appears to cause issues and is not done by other examples on the + * internet. This needs to be investigated further. */ - // AUXSRC = 0x0 7:5 && SRC == 0x0 0 - // CLOCKS: CLK_SYS_CTRL CLK_PERI_CTRL_ENABLE_BIT - CLOCKS->CLK_SYS_CTRL = 1; + /* Wait for lock */ + /* while (!(PLL_SYS->CS & PLL_CS_LOCK_BITS)) { */ + /* Wait for the PLL to lock */ + /* } */ - // This register contains one decoded bit for each of the clock sources enumerated in the CTRL SRC field. - // The bit does not directly correlate with the value of the SRC field - // For example 0x0 is the first bit while 0x1 is the second bit - // In some way this makes sense, in some way I lost too much time on this - while (CLOCKS->CLK_SYS_SELECTED != 2) {} + /* AUXSRC = 0x0 7:5 && SRC == 0x0 0 */ + CLOCKS->CLK_SYS_CTRL = CLK_SYS_PERI_CTRL_ENABLE_BIT; - // src: CLOCKS: CLK_PERI_CTRL - // AUXSRC = 0x0 -> CLK_SYS Indirectly through lower line + /* This register contains one decoded bit for each of the clock sources + * enumerated in the CTRL SRC field. The bit does not directly correlate with + * the value of the SRC field For example 0x0 is the first bit while 0x1 is + * the second bit. In some way this makes sense, in some way I lost too much + * time on this. */ + while (CLOCKS->CLK_SYS_SELECTED != CLK_SYS_SELECTED_PERI_FIELD_VALUE) { + } + + /* AUXSRC = 0x0 -> CLK_SYS Indirectly through lower line */ CLOCKS->CLK_PERI_CTRL = CLK_PERI_CTRL_ENABLE_BIT; } + +/** @} */ diff --git a/cpu/rp2350/cpu.c b/cpu/rp2350/cpu.c index 64ce534df8..f4ff0006d8 100644 --- a/cpu/rp2350/cpu.c +++ b/cpu/rp2350/cpu.c @@ -1,3 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2025 Tom Hert + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only + */ + +/** + * @ingroup cpu_rp2350 + * @{ + * + * @file + * @brief CPU initialization implementation for the RP2350 + * + * @author Tom Hert + */ + #include "cpu.h" #include "RP2350.h" @@ -12,22 +28,32 @@ #define DEBUG_WITH_OSC void gpio_reset(void) { - reset_component(RESET_PADS_BANK0, RESET_PADS_BANK0); - reset_component(RESET_IO_BANK0, RESET_IO_BANK0); + reset_component(RESET_PADS_BANK0, RESET_PADS_BANK0); + reset_component(RESET_IO_BANK0, RESET_IO_BANK0); } void cpu_init(void) { - /* initialize the Cortex-M core */ - //cortexm_init(); - gpio_reset(); - //_cpu_reset(); + /* initialize the Cortex-M core, once UART support is moved + * to shared driver as currently this will cause unhandled interrupts */ + /* cortexm_init(); */ - /* initialize stdio prior to periph_init() to allow use of DEBUG() there */ - early_init(); + /* Reset GPIO state */ + gpio_reset(); - clock_reset(); - cpu_clock_init(); + /* Reset clock to default state */ + clock_reset(); - /* trigger static peripheral initialization */ - periph_init(); + /* initialize the CPU clock */ + cpu_clock_init(); + + /* initialize the early peripherals */ + early_init(); + + /* trigger static peripheral initialization */ + periph_init(); + + /* initialize the board */ + board_init(); } + +/** @} */ diff --git a/cpu/rp2350/doc.md b/cpu/rp2350/doc.md new file mode 100644 index 0000000000..cc2f01362e --- /dev/null +++ b/cpu/rp2350/doc.md @@ -0,0 +1,5 @@ +@defgroup cpu_rp2350 RP2350 MCUs +@ingroup cpu +@brief RP2350 MCU code and definitions + +This module contains the code and definitions for MCUs of the RP2350 family used by the Pi Pico 2. diff --git a/cpu/rp2350/doc.txt b/cpu/rp2350/doc.txt deleted file mode 100644 index 8a8d0e1ddf..0000000000 --- a/cpu/rp2350/doc.txt +++ /dev/null @@ -1,8 +0,0 @@ -/** -@defgroup cpu_rp23xx RP23xx MCUs -@ingroup cpu -@brief RP23xx MCU code and definitions - -This module contains the code and definitions for MCUs of the RP23xx family used by the Pi Pico 2 - - */ diff --git a/cpu/rp2350/include/clock_conf.h b/cpu/rp2350/include/clock_conf.h index 53cf59915f..f5137e4c57 100644 --- a/cpu/rp2350/include/clock_conf.h +++ b/cpu/rp2350/include/clock_conf.h @@ -1,69 +1,127 @@ +/* + * SPDX-FileCopyrightText: 2025 Tom Hert + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only + */ + #pragma once +/** + * @ingroup cpu_rp2350 + * @{ + * + * @file + * @brief Clock configuration for the RP2350 + * + * @author Tom Hert + */ + #include "RP2350.h" +#include "macros/units.h" -// Based on hardware/regs/xosc.h and 8.2.8 -#define XOSC_CTRL_FREQ_RANGE_VALUE_1_15MHZ 0xaa0u -#define XOSC_CTRL_FREQ_RANGE_VALUE_10_30MHZ 0xaa1u -#define XOSC_CTRL_FREQ_RANGE_VALUE_25_60MHZ 0xaa2u -#define XOSC_CTRL_FREQ_RANGE_VALUE_40_100MHZ 0xaa3u +/** 1-15 MHz range + * @see hardware/regs/xosc.h and chapter 8.2.8 + */ +#define XOSC_CTRL_FREQ_RANGE_VALUE_1_15MHZ 0xaa0u +/** 10-30 MHz range */ +#define XOSC_CTRL_FREQ_RANGE_VALUE_10_30MHZ 0xaa1u +/** 25-60 MHz range */ +#define XOSC_CTRL_FREQ_RANGE_VALUE_25_60MHZ 0xaa2u +/** 40-100 MHz range */ +#define XOSC_CTRL_FREQ_RANGE_VALUE_40_100MHZ 0xaa3u +/** Disable the XOSC */ #define XOSC_CTRL_ENABLE_VALUE_DISABLE 0xd1eu +/** Enable the XOSC */ #define XOSC_CTRL_ENABLE_VALUE_ENABLE 0xfabu -#define XOSC_CTRL_ENABLE_LSB 12u -#define XOSC_STATUS_STABLE_BITS 0x80000000u -#define XOSC_HZ MHZ(12) -#define REF_DIV 2 -#define VCO_FREQ 750000000u -#define PD1 6 -#define PD2 2 +/** LSB of the enable bit */ +#define XOSC_CTRL_ENABLE_LSB 12u +/** Stable bit in the XOSC status register */ +#define XOSC_STATUS_STABLE_BITS 0x80000000u +/** Default crystal frequency is 12 MHz */ +#define XOSC_HZ MHZ(12u) +/** Reference divider for the PLL, set to 2 as per hardware manual */ +#define PLL_REF_DIV 2u +/** VCO frequency for the PLL, set to 750 MHz as per hardware manual */ +#define PLL_VCO_FREQ 750000000u +/** Post divider 1 for the PLL, set to 6 as per hardware manual */ +#define PLL_PD1 6u +/** Post divider 2 for the PLL, set to 2 as per hardware manual */ +#define PLL_PD2 2u +/** Power down bits for the PLL */ #define PLL_PWR_PD_BITS 0x00000001u +/** VCO power down bits for the PLL */ #define PLL_PWR_VCOPD_BITS 0x00000020u +/** Lock bit in the PLL control status register */ #define PLL_CS_LOCK_BITS 0x80000000u +/** LSB of the post divider 1 in the PLL primary register */ #define PLL_PRIM_POSTDIV1_LSB 16u +/** LSB of the post divider 2 in the PLL primary register */ #define PLL_PRIM_POSTDIV2_LSB 12u -#define PLL_PWR_POSTDIVPD_BITS 0x00000008u -#define CLK_PERI_CTRL_ENABLE_BIT 1 << 11 -#define XOSC_FREQ 12000000 -#define POSTDIV1 6 -#define POSTDIV2 2 -#define CPUFREQ 125000000 -#define CLOCK_XOSC_MAX MHZ(15) /**< Maximum crystal frequency */ -#define CLOCK_XOSC_MIN MHZ(5) /**< Minimum crystal frequency */ -#define CLOCK_XOSC (XOSC_HZ) /**< Crystal frequency */ -#define PLL_POSTDIV_MIN (1U) /**< Minimum value of the post PLL clock divers */ -#define PLL_POSTDIV_MAX (7U) /**< Maximum value of the post PLL clock divers */ -#define PLL_VCO_FEEDBACK_SCALE_MIN (16U) /**< Minimum value of the PLL VCO feedback scaler */ -#define PLL_VCO_FEEDBACK_SCALE_MAX (320U) /**< Maximum value of the PLL VCO feedback scaler */ -#define PLL_REF_DIV_MIN (1U) /**< Minimum value of the clock divider applied before - * feeding in the reference clock into the PLL */ -#define PLL_REF_DIV_MAX (1U) /**< Minimum value of the clock divider applied before - * feeding in the reference clock into the PLL */ +/** Post divider power down bits for the PLL */ +#define PLL_PWR_POSTDIVPD_BITS 0x00000008u +/** Enable bit for the peripheral clock control register */ +#define CLK_PERI_CTRL_ENABLE_BIT (1u << 11u) +/** Default CPU frequency in Hz, set to 125 MHz as per hardware manual */ +#define CPUFREQ 125000000u +/** Maximum crystal frequency */ +#define CLOCK_XOSC_MAX MHZ(15u) +/** Minimum crystal frequency */ +#define CLOCK_XOSC_MIN MHZ(5u) +/** Crystal frequency */ +#define CLOCK_XOSC (XOSC_HZ) +/** Minimum value of the post PLL clock divers */ +#define PLL_POSTDIV_MIN 1u +/** Maximum value of the post PLL clock divers */ +#define PLL_POSTDIV_MAX 7u +/** Minimum value of the PLL VCO feedback scaler */ +#define PLL_VCO_FEEDBACK_SCALE_MIN 16u +/** Maximum value of the PLL VCO feedback scaler */ +#define PLL_VCO_FEEDBACK_SCALE_MAX 320u +/** Minimum value of the clock divider applied before + * feeding in the reference clock into the PLL */ +#define PLL_REF_DIV_MIN 1u +/** Minimum value of the clock divider applied before feeding in + * the reference clock into the PLL */ +#define PLL_REF_DIV_MAX 1u +/** PLL feedback divider value, set to 125 as per hardware manual */ +#define PLL_FEEDBACK_DIVIDER_VALUE 125u +/** Enable bit for the system clock control register to select the peripheral + * clock */ +#define CLK_SYS_PERI_CTRL_ENABLE_BIT (1u << 0u) +/** Selected field value for the system clock control register +* to select the peripheral clock */ +#define CLK_SYS_SELECTED_PERI_FIELD_VALUE 2u +/** RIOT core clock frequency defined as the CPU frequency */ +#define CLOCK_CORECLOCK MHZ(12u) -#if (PLL_VCO_FEEDBACK_SCALE_MIN < PLL_VCO_FEEDBACK_SCALE_MIN) || (PLL_VCO_FEEDBACK_SCALE_MAX > PLL_VCO_FEEDBACK_SCALE_MAX) -#error "Value for PLL_VCO_FEEDBACK_SCALE out of range, check config" +#if (PLL_VCO_FEEDBACK_SCALE_MIN < PLL_VCO_FEEDBACK_SCALE_MIN) || \ +(PLL_VCO_FEEDBACK_SCALE_MAX > PLL_VCO_FEEDBACK_SCALE_MAX) +# error "Value for PLL_VCO_FEEDBACK_SCALE out of range, check config" #endif #if (PLL_REF_DIV_MIN < PLL_REF_DIV_MIN) || (PLL_REF_DIV_MAX > PLL_REF_DIV_MAX) -#error "Value for PLLxosc_sleep_REF_DIV out of range, check config" +# error "Value for PLLxosc_sleep_REF_DIV out of range, check config" #endif #if (PLL_POSTDIV_MIN < PLL_POSTDIV_MIN) || (PLL_POSTDIV_MAX > PLL_POSTDIV_MAX) -#error "Value for PLL_POSTDIV out of range, check config" +# error "Value for PLL_POSTDIV out of range, check config" #endif #if ((CLOCK_XOSC > CLOCK_XOSC_MAX) || (CLOCK_XOSC < CLOCK_XOSC_MIN)) -#error "Value for CLOCK_XOSC out of range, check config" +# error "Value for CLOCK_XOSC out of range, check config" #endif -#define PDIV ((PD1 << PLL_PRIM_POSTDIV1_LSB) | (PD2 << PLL_PRIM_POSTDIV2_LSB)) -#define FBDIV ((VCO_FREQ / XOSC_HZ) / REF_DIV) +/** Post divider for the PLL, calculated based on the post divider values */ +#define PDIV ((PLL_PD1 << PLL_PRIM_POSTDIV1_LSB) | (PLL_PD2 << PLL_PRIM_POSTDIV2_LSB)) +/** Feedback divider for the PLL, calculated based on the VCO frequency and +* reference clock frequency */ +#define FBDIV ((PLL_VCO_FREQ / XOSC_HZ) / PLL_REF_DIV) +#ifdef __cplusplus +extern "C" { +#endif /** * @brief Configures the Crystal to run. - * - * @param f_ref Desired frequency in Hz - * - * @pre 1 MHz <= @p f_ref <= 15 MHz. - * - * The reference hardware manual suggests to use a 12 MHz crystal. + * @note The reference hardware manual suggests to use a 12 MHz crystal, which we + * use by default. */ void xosc_start(void); @@ -73,9 +131,10 @@ void xosc_start(void); void xosc_stop(void); /** - * @brief Sleep for a given number of cycles. + * @brief Sleep for a given time in milliseconds. + * @param milliseconds The time to sleep in milliseconds. */ -void xosc_sleep(int32_t cycles); +void xosc_sleep(uint32_t milliseconds); /** * @brief Reset the clock system. @@ -87,7 +146,14 @@ void clock_reset(void); /** * @brief Configures the XOSC and then sets CLK_SYS, PLL_SYS and CLK_PERI to it - * @warning Make sure to call clock_reset() before this function to reset the clock system - * @note RP2350 Docs Chapter 8, mostly 8.2 for more details -*/ + * @pre Make sure to call clock_reset() before this function to reset the + * clock system + * @see RP2350 Docs Chapter 8, mostly 8.2 for more details + */ void cpu_clock_init(void); + +#ifdef __cplusplus +} +#endif + +/** @} */ diff --git a/cpu/rp2350/include/cpu_conf.h b/cpu/rp2350/include/cpu_conf.h index 89913a1fbf..652be6fe27 100644 --- a/cpu/rp2350/include/cpu_conf.h +++ b/cpu/rp2350/include/cpu_conf.h @@ -1,13 +1,26 @@ +/* + * SPDX-FileCopyrightText: 2025 Tom Hert + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only + */ + #pragma once -#include "cpu_conf_common.h" +/** + * @ingroup cpu_rp2350 + * @{ + * @file + * @brief CPU configuration for the RP2350 + * + * @author Tom Hert + */ + #include "RP2350.h" #include "core_cm33.h" +#include "cpu_conf_common.h" -#define __CHECK_DEVICE_DEFINES - -#define CPU_DEFAULT_IRQ_PRIO (1U) -#define CPU_IRQ_NUMOF (52U) +#define CPU_DEFAULT_IRQ_PRIO 1u +#define CPU_IRQ_NUMOF 52u #ifdef __cplusplus extern "C" { @@ -16,3 +29,5 @@ extern "C" { #ifdef __cplusplus } #endif + +/** @} */ diff --git a/cpu/rp2350/include/gpio_conf.h b/cpu/rp2350/include/gpio_conf.h index 49f3d158a3..3991542d43 100644 --- a/cpu/rp2350/include/gpio_conf.h +++ b/cpu/rp2350/include/gpio_conf.h @@ -1,23 +1,66 @@ +/* + * SPDX-FileCopyrightText: 2025 Tom Hert git@annsann.eu> + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only + */ + #pragma once +/** + * @ingroup cpu_rp2350 + * @{ + * + * @file + * @brief GPIO configuration for the RP2350 + * + * @author Tom Hert + */ + +/** The number of GPIO pins available on the RP2350 */ +#define GPIO_PIN_NUMOF 30u + +#ifdef __cplusplus +extern "C" { +#endif + /** * @brief Possible function values for @ref gpio_io_ctrl_t::function_select */ typedef enum { - FUNCTION_SELECT_SPI = 1, /**< connect pin to the SPI peripheral - * (MISO/MOSI/SCK depends on pin) */ - FUNCTION_SELECT_UART = 2, /**< connect pin to the UART peripheral - * (TXD/RXD depends on pin) */ - FUNCTION_SELECT_I2C = 3, /**< connect pin to the I2C peripheral - * (SCL/SDA depends on pin) */ - FUNCTION_SELECT_PWM = 4, /**< connect pin to the timer for PWM - * (channel depends on pin) */ - FUNCTION_SELECT_SIO = 5, /**< use pin as vanilla GPIO */ - FUNCTION_SELECT_PIO0 = 6, /**< connect pin to the first PIO peripheral */ - FUNCTION_SELECT_PIO1 = 7, /**< connect pin to the second PIO peripheral */ - FUNCTION_SELECT_CLOCK = 8, /**< connect pin to the timer (depending on pin: external clock, - * clock output, or not supported) */ - FUNCTION_SELECT_USB = 9, /**< connect pin to the USB peripheral - * (function depends on pin) */ - FUNCTION_SELECT_NONE = 31, /**< Reset value, pin unconnected */ + /** connect pin to the SPI peripheral (MISO/MOSI/SCK depends on pin) */ + FUNCTION_SELECT_SPI = 1, + + /** connect pin to the UART peripheral (TXD/RXD depends on pin) */ + FUNCTION_SELECT_UART = 2, + + /** connect pin to the I2C peripheral (SCL/SDA depends on pin) */ + FUNCTION_SELECT_I2C = 3, + + /** connect pin to the timer for PWM (channel depends on pin) */ + FUNCTION_SELECT_PWM = 4, + + /** use pin as vanilla GPIO */ + FUNCTION_SELECT_SIO = 5, + + /** connect pin to the first PIO peripheral */ + FUNCTION_SELECT_PIO0 = 6, + + /** connect pin to the second PIO peripheral */ + FUNCTION_SELECT_PIO1 = 7, + + /** connect pin to the timer (depending on pin: external clock, + * clock output, or not supported) */ + FUNCTION_SELECT_CLOCK = 8, + + /** connect pin to the USB peripheral (function depends on pin) */ + FUNCTION_SELECT_USB = 9, + + /** Reset value, pin unconnected */ + FUNCTION_SELECT_NONE = 31, } gpio_function_select_t; + +#ifdef __cplusplus +} +#endif + +/** @} */ diff --git a/cpu/rp2350/include/helpers.h b/cpu/rp2350/include/helpers.h index 069fae757b..5560882017 100644 --- a/cpu/rp2350/include/helpers.h +++ b/cpu/rp2350/include/helpers.h @@ -1,48 +1,80 @@ +/* + * SPDX-FileCopyrightText: 2025 Tom Hert + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only + */ + #pragma once #include "RP2350.h" -#define ATOMIC_XOR_WRITE 0x1000 -#define ATOMIC_BITMASK_SET_WRITE 0x2000 -#define ATOMIC_BITMASK_CLEAR_WRITE 0x3000 +/** + * @ingroup cpu_rp2350 + * @{ + * + * @file + * @brief Helper functions for atomic register operations + * + * @author Tom Hert + */ + +/** Bit to be set for an atomic XOR operation */ +#define ATOMIC_XOR_WRITE 0x1000u +/** Bit to be set for an atomic set operation */ +#define ATOMIC_BITMASK_SET_WRITE 0x2000u +/** Bits to be set for an atomic clear operation */ +#define ATOMIC_BITMASK_CLEAR_WRITE 0x3000u + +#ifdef __cplusplus +extern "C" { +#endif /** * @brief Perform an atomic XOR write to a register * - * @param[in] reg Pointer to the target register - * @param[in] val Value to be XORed with the register + * @param[in,out] reg Pointer to the target register + * @param[in] val Value to be XORed with the register */ -static inline void atomic_xor(volatile uint32_t *reg, uint32_t val) -{ +static inline void atomic_xor(volatile uint32_t *reg, uint32_t val) { *(volatile uint32_t *)((uintptr_t)reg | ATOMIC_XOR_WRITE) = val; } /** * @brief Set bits in a register atomically * - * @param[in] reg Pointer to the target register - * @param[in] val Bit mask of bits to set + * @param[in,out] reg Pointer to the target register + * @param[in] val Bit mask of bits to set */ -static inline void atomic_set(volatile uint32_t *reg, uint32_t val) -{ +static inline void atomic_set(volatile uint32_t *reg, uint32_t val) { *(volatile uint32_t *)((uintptr_t)reg | ATOMIC_BITMASK_SET_WRITE) = val; } /** * @brief Clear bits in a register atomically * - * @param[in] reg Pointer to the target register - * @param[in] val Bit mask of bits to clear + * @param[in,out] reg Pointer to the target register + * @param[in] val Bit mask of bits to clear */ -static inline void atomic_clear(volatile uint32_t *reg, uint32_t val) -{ +static inline void atomic_clear(volatile uint32_t *reg, uint32_t val) { *(volatile uint32_t *)((uintptr_t)reg | ATOMIC_BITMASK_CLEAR_WRITE) = val; } -static inline void reset_component(uint32_t reset_value, uint32_t reset_done_value) -{ +/** + * @brief Reset a component by clearing its reset bits and waiting for the reset to complete + * + * @param reset_value Bit mask of the reset bits to clear + * @param reset_done_value Bit mask of the reset done bits to wait for + */ +static inline void reset_component(uint32_t reset_value, + uint32_t reset_done_value) { atomic_clear(&RESETS->RESET, reset_value); - while(~RESETS->RESET_DONE & reset_done_value) { - // Wait for the reset to complete + while (~RESETS->RESET_DONE & reset_done_value) { + /* Wait for the reset to complete */ } } + +#ifdef __cplusplus +} +#endif + +/** @} */ diff --git a/cpu/rp2350/include/periph_cpu.h b/cpu/rp2350/include/periph_cpu.h index 98c8f96c08..0eb149a4a0 100644 --- a/cpu/rp2350/include/periph_cpu.h +++ b/cpu/rp2350/include/periph_cpu.h @@ -1,52 +1,97 @@ +/* + * SPDX-FileCopyrightText: 2025 Tom Hert + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only + */ + #pragma once +/** + * @ingroup cpu_rp2350 + * @{ + * + * @file + * @brief Peripheral CPU definitions for the RP2350 + * + * @author Tom Hert + */ + #include #include -#include "cpu.h" #include "RP2350.h" - -#include "uart_conf.h" #include "clock_conf.h" +#include "cpu.h" #include "gpio_conf.h" #include "helpers.h" +#include "uart_conf.h" -// Overwrite the default GPIO type to use uint32_t +/** Overwrite the default GPIO type to use uint32_t */ #define HAVE_GPIO_T typedef uint32_t gpio_t; -#define LED0_PIN_ID 25 -#define OSC_DEBUG_PIN_ID 15 +#include "periph/gpio.h" -#define RESET_PLL_SYS 1 << 14 -#define RESET_PADS_BANK0 1 << 9 -#define RESET_UART0 1 << 26 -#define RESET_UART1 1 << 27 -#define RESET_IO_BANK0 1 << 6 +/** GPIO Pin ID for oscillator debugging */ +#define OSC_DEBUG_PIN_ID 15u -#define PADS_BANK0_GPIO0_IE_BITS 1<<6 -#define PADS_BANK0_ISO_BITS 1<<8 +/** Reset bit for the system PLL */ +#define RESET_PLL_SYS (1u << 14u) + +/** Reset bit for the pads bank 0 */ +#define RESET_PADS_BANK0 (1u << 9u) + +/** Reset bit for UART0 peripheral */ +#define RESET_UART0 (1u << 26u) + +/** Reset bit for UART1 peripheral */ +#define RESET_UART1 (1u << 27u) + +/** Reset bit for the IO bank 0 */ +#define RESET_IO_BANK0 (1u << 6u) + +/** Input enable bit for GPIO0 in PADS_BANK0 */ +#define PADS_BANK0_GPIO0_IE_BITS (1u << 6u) + +/** Isolation bits for PADS_BANK0 */ +#define PADS_BANK0_ISO_BITS (1u << 8u) #ifdef __cplusplus extern "C" { #endif -static inline volatile uint32_t calculate_gpio_pad_register_addr(gpio_t pin) { - // Each pin has a 4 byte register, so we can calculate the address - // by adding 4 bytes for each pin, starting at the base address of PADS_BANK0 - // and adding 4 bytes to skip VOLTAGE_SELECT +/** + * @brief Calculate the address of the GPIO pad register for a given pin + * @param pin The GPIO pin number + * @return The address of the GPIO pad register for the given pin + */ +static inline uint32_t calculate_gpio_pad_register_addr(gpio_t pin) { + /* Each pin has a 4 byte register, so we can calculate the address + * by adding 4 bytes for each pin, starting at the base address of PADS_BANK0 + * and adding 4 bytes to skip VOLTAGE_SELECT */ return PADS_BANK0_BASE + 4 * (pin + 1); } -static volatile uint32_t calculate_gpio_io_status_register_addr(gpio_t pin) { - // Each status register is followed by a ctrl register, +/** + * @brief Calculate the address of the GPIO IO status register for a given pin + * @param pin The GPIO pin number + * @return The address of the GPIO IO status register for the given pin + */ +static uint32_t calculate_gpio_io_status_register_addr(gpio_t pin) { + /* Each status register is followed by a ctrl register, */ return IO_BANK0_BASE + 8 * pin; } -static inline volatile uint32_t calculate_gpio_io_ctrl_register_addr(gpio_t pin) { - // Each pin has a 8 byte register (4 Bytes of Status, 4 Bytes of CTRL), - // so we can calculate the address by adding 8 bytes for each pin, - // starting at the base address of IO_BANK0 +/** + * @brief Calculate the address of the GPIO IO control register for a given + * pin + * @param pin The GPIO pin number + * @return The address of the GPIO IO control register for the given pin + */ +static inline uint32_t calculate_gpio_io_ctrl_register_addr(gpio_t pin) { + /* Each pin has a 8 byte register (4 Bytes of Status, 4 Bytes of CTRL), + * so we can calculate the address by adding 8 bytes for each pin, + * starting at the base address of IO_BANK0 */ return calculate_gpio_io_status_register_addr(pin) + 4; } @@ -54,3 +99,4 @@ static inline volatile uint32_t calculate_gpio_io_ctrl_register_addr(gpio_t pin) } #endif +/** @} */ diff --git a/cpu/rp2350/include/uart_conf.h b/cpu/rp2350/include/uart_conf.h index 64c9c6b27d..ed25e9f6ea 100644 --- a/cpu/rp2350/include/uart_conf.h +++ b/cpu/rp2350/include/uart_conf.h @@ -1,24 +1,55 @@ +/* + * SPDX-FileCopyrightText: 2025 Tom Hert + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only + */ + #pragma once -#include "periph_cpu.h" -#include "macros/units.h" +/** + * @ingroup cpu_rp2350 + * @{ + * + * @file + * @brief UART configuration for the RP2350 + * + * @author Tom Hert + */ + #include "RP2350.h" +#include "macros/units.h" +#include "periph_cpu.h" + +/** UART baud rate in bits per second */ +#define BAUDRATE 115200u + +/** Integer baud rate divisor */ +#define IBRD ((((8u * CPUFREQ) + BAUDRATE) / (2u * BAUDRATE)) / 64u) + +/** Fractional baud rate divisor */ +#define FBRD ((((8u * CPUFREQ) + BAUDRATE) / (2u * BAUDRATE)) % 64u) + +/** UART enable bit in control register */ +#define UART_UARTCR_UARTEN_BITS (1u << 0u) + +/** UART receive enable bit in control register */ +#define UART_UARTCR_RXE_BITS (1u << 9u) + +/** UART transmit enable bit in control register */ +#define UART_UARTCR_TXE_BITS (1u << 8u) + +/** UART receive FIFO full flag bit in flag register */ +#define UART_UARTFR_RXFF_BITS (1u << 6u) + +/** UART transmit FIFO empty flag bit in flag register */ +#define UART_UARTFR_TXFE_BITS (1u << 7u) #ifdef __cplusplus extern "C" { #endif -#define BAUDRATE 115200 -#define IBRD ((8*CPUFREQ + BAUDRATE)/(2*BAUDRATE))/64 -#define FBRD ((8*CPUFREQ + BAUDRATE)/(2*BAUDRATE))%64 - - -#define UART_UARTCR_UARTEN_BITS 1<<0 -#define UART_UARTCR_RXE_BITS 1<<9 -#define UART_UARTCR_TXE_BITS 1<<8 -#define UART_UARTFR_RXFF_BITS 1<<6 -#define UART_UARTFR_TXFE_BITS 1<<7 - #ifdef __cplusplus } #endif + +/** @} */ diff --git a/cpu/rp2350/periph/gpio.c b/cpu/rp2350/periph/gpio.c index d0d31d7e2b..e949b34445 100644 --- a/cpu/rp2350/periph/gpio.c +++ b/cpu/rp2350/periph/gpio.c @@ -1,3 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2025 Tom Hert + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only + */ + +/** + * @ingroup cpu_rp2350 + * @{ + * + * @file + * @brief GPIO implementation for the RP2350 + * + * @author Tom Hert + */ + #include "periph/gpio.h" #include @@ -10,56 +26,71 @@ #define ENABLE_DEBUG 0 #include "debug.h" -#define GPIO_PIN_NUMOF 30U - - int gpio_init(gpio_t pin, gpio_mode_t mode) { - // Check if we exceed the maximum number of GPIO pins + /* Check if we exceed the maximum number of GPIO pins */ assert(pin < GPIO_PIN_NUMOF); - // Clear the pin's output enable and output state + /* Clear the pin's output enable and output state */ SIO->GPIO_OE_CLR = 1LU << pin; SIO->GPIO_OUT_CLR = 1LU << pin; switch (mode) { case GPIO_OUT: - *(uint32_t*)calculate_gpio_io_ctrl_register_addr(pin) = FUNCTION_SELECT_SIO; + *(uint32_t*)calculate_gpio_io_ctrl_register_addr(pin) = + FUNCTION_SELECT_SIO; - volatile uint32_t* pad_reg = (uint32_t*)calculate_gpio_pad_register_addr(pin); + volatile uint32_t* pad_reg = + (uint32_t*)calculate_gpio_pad_register_addr(pin); - // We clear all bits except the drive strength bit - // We set that to the highest one possible (12mA) - // to mimic the behavior of the pico1 GPIO driver - // (Not too sure why we do this, but it seems to be the standard) - *pad_reg = 0x3 << 4; + /* We clear all bits except the drive strength bit + * We set that to the highest one possible (12mA) + * to mimic the behavior of the pico1 GPIO driver + * (Not too sure why we do this, but it seems to be the standard) */ + *pad_reg = 0x3 << 4; - SIO->GPIO_OE_SET = 1 << pin; // Set the pin as output + SIO->GPIO_OE_SET = 1 << pin; /* Set the pin as output */ - break; + break; default: - // Unsupported mode - return -ENOTSUP; + /* Unsupported mode */ + return -ENOTSUP; } + return 0; } -bool gpio_read(gpio_t pin) {} +bool gpio_read(gpio_t pin) { + /* Check if we exceed the maximum number of GPIO pins */ + assert(pin < GPIO_PIN_NUMOF); + /* Read the pin state */ + return (SIO->GPIO_IN & (1 << pin)) != 0; /* Return true if the pin is HIGH */ +} void gpio_set(gpio_t pin) { - SIO->GPIO_OUT_SET = 1 << pin; // Set the pin to HIGH + /* Check if we exceed the maximum number of GPIO pins */ + assert(pin < GPIO_PIN_NUMOF); + SIO->GPIO_OUT_SET = 1 << pin; /* Set the pin to HIGH */ } void gpio_clear(gpio_t pin) { - SIO->GPIO_OUT_CLR = 1 << pin; // Set the pin to LOW + /* Check if we exceed the maximum number of GPIO pins */ + assert(pin < GPIO_PIN_NUMOF); + SIO->GPIO_OUT_CLR = 1 << pin; /* Set the pin to LOW */ } void gpio_toggle(gpio_t pin) { - SIO->GPIO_OUT_XOR = 1 << pin; // Toggle the pin state (XOR) + /* Check if we exceed the maximum number of GPIO pins */ + assert(pin < GPIO_PIN_NUMOF); + SIO->GPIO_OUT_XOR = 1 << pin; /* Toggle the pin state (XOR) */ } void gpio_write(gpio_t pin, bool value) { + /* Check if we exceed the maximum number of GPIO pins */ + assert(pin < GPIO_PIN_NUMOF); if (value) { - gpio_set(pin); // Set the pin to HIGH + gpio_set(pin); /* Set the pin to HIGH */ } else { - gpio_clear(pin); // Set the pin to LOW + gpio_clear(pin); /* Set the pin to LOW */ } } + +/** @} */ diff --git a/cpu/rp2350/periph/uart.c b/cpu/rp2350/periph/uart.c index 5a66cf5499..4b6c21677e 100644 --- a/cpu/rp2350/periph/uart.c +++ b/cpu/rp2350/periph/uart.c @@ -1,52 +1,86 @@ +/* + * SPDX-FileCopyrightText: 2025 Tom Hert + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only + */ + +/** + * @ingroup cpu_rp2350 + * @{ + * + * @file + * @brief UART implementation for the RP2350 + * + * @author Tom Hert + */ + #include "periph/uart.h" #include "periph_cpu.h" int uart_init(uart_t uart, uint32_t baud, uart_rx_cb_t rx_cb, void *arg) { - // Set the UART pins to the correct function - IO_BANK0->GPIO0_CTRL = FUNCTION_SELECT_UART; - IO_BANK0->GPIO1_CTRL = FUNCTION_SELECT_UART; - // Clear the ISO bits - atomic_clear(&PADS_BANK0->GPIO0, PADS_BANK0_ISO_BITS); - atomic_clear(&PADS_BANK0->GPIO1, PADS_BANK0_ISO_BITS); - // Set IE bit for gpio1 - PADS_BANK0->GPIO1 = PADS_BANK0->GPIO1 | PADS_BANK0_GPIO0_IE_BITS; + (void)uart; + (void)baud; + (void)rx_cb; + (void)arg; + /* Set the UART pins to the correct function */ + IO_BANK0->GPIO0_CTRL = FUNCTION_SELECT_UART; + IO_BANK0->GPIO1_CTRL = FUNCTION_SELECT_UART; + /* Clear the ISO bits */ + atomic_clear(&PADS_BANK0->GPIO0, PADS_BANK0_ISO_BITS); + atomic_clear(&PADS_BANK0->GPIO1, PADS_BANK0_ISO_BITS); + /* Set IE bit for gpio1 */ + PADS_BANK0->GPIO1 = PADS_BANK0->GPIO1 | PADS_BANK0_GPIO0_IE_BITS; - // We reset UART0 here, so we can be sure it is in a known state - reset_component(RESET_UART0, RESET_UART0); + /* We reset UART0 here, so we can be sure it is in a known state */ + reset_component(RESET_UART0, RESET_UART0); - UART0->UARTIBRD = IBRD; - UART0->UARTFBRD = FBRD; + UART0->UARTIBRD = IBRD; + UART0->UARTFBRD = FBRD; + uart_mode(0, 8, UART_PARITY_NONE, 1); + return 0; } int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t parity, - uart_stop_bits_t stop_bits) { - atomic_clear(&UART0->UARTCR, UART_UARTCR_UARTEN_BITS | UART_UARTCR_RXE_BITS | - UART_UARTCR_TXE_BITS); - // Set the data bits, parity, and stop bits - UART0->UARTLCR_H = (uint32_t)data_bits << 5; + uart_stop_bits_t stop_bits) { + (void)uart; + (void)data_bits; + (void)stop_bits; + atomic_clear(&UART0->UARTCR, UART_UARTCR_UARTEN_BITS | UART_UARTCR_RXE_BITS | + UART_UARTCR_TXE_BITS); - switch (parity) { - case UART_PARITY_NONE: - break; - default: - // @todo: Implement other parity modes lel - return UART_NOMODE; - } + /* Set the data bits, parity, and stop bits + * Set to 8 bits (0b11) based on Table 1035 page 976 + */ + UART0->UARTLCR_H = 0b11 << 5; - UART0->UARTCR = - UART_UARTCR_RXE_BITS | UART_UARTCR_TXE_BITS | UART_UARTCR_UARTEN_BITS; + switch (parity) { + case UART_PARITY_NONE: + break; + default: + return UART_NOMODE; + } - return UART_OK; + UART0->UARTCR = UART_UARTCR_TXE_BITS | UART_UARTCR_UARTEN_BITS; + + return UART_OK; } void uart_write(uart_t uart, const uint8_t *data, size_t len) { - for (size_t i = 0; i < len; i++) { - UART0->UARTDR = data[i]; - // Wait until the TX FIFO is empty before sending the next byte - while (!(UART0->UARTFR & UART_UARTFR_TXFE_BITS)); - } + (void)uart; + for (size_t i = 0; i < len; i++) { + UART0->UARTDR = data[i]; + /* Wait until the TX FIFO is empty before sending the next byte */ + while (!(UART0->UARTFR & UART_UARTFR_TXFE_BITS)) { + } + } } -void uart_poweron(uart_t uart) {} -void uart_poweroff(uart_t uart) {} +void uart_poweron(uart_t uart) { + (void)uart; +} +void uart_poweroff(uart_t uart) { + (void)uart; +} + +/** @} */ diff --git a/cpu/rp2350/picobin_block.s b/cpu/rp2350/picobin_block.s index 93924af69c..468d465d4c 100644 --- a/cpu/rp2350/picobin_block.s +++ b/cpu/rp2350/picobin_block.s @@ -1,28 +1,34 @@ -// Picobin block required for the binary -// This defines the minimum viable image metadata to be recognized by the RP2350 bootloader -// based on RP2350 Chapter 5.9.1 +/* + * SPDX-FileCopyrightText: 2025 Tom Hert + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only + */ -.section .picobin_block, "a" // "a" means "allocatable" (can be moved by the linker) +/* Picobin block required for the binary */ +/* This defines the minimum viable image metadata to be recognized by the RP2350 bootloader */ +/* based on RP2350 Chapter 5.9.1 */ -// PICOBIN_BLOCK_MARKER_START +.section .picobin_block, "a" /* "a" means "allocatable" (can be moved by the linker) */ + +/* PICOBIN_BLOCK_MARKER_START */ .word 0xffffded3 - // ITEM 0 START based on 5.9.3.1 - .byte 0x42 // (size_flag == 0, item_type == PICOBIN_BLOCK_ITEM_1BS_IMAGE_TYPE) - .byte 0x1 // Block Size in words - // image_type_flags (2 bytes) [See 5.9.3.1 / p419] - // 15 -> 0 (1 for "Try before you buy" image [Wacky] - // 12-14 -> 001 (RP2350 = 1) - // 11 -> 0 (Reserved) - // 8-10 -> 000 (EXE_CPU_ARM = 0), **WARNING** if I ever want to support RISC-V this needs to be 001 (EXE_CPU_RISCV) - // 6-7 -> 00 (Reserved) - // 4-5 -> 10 (2) EXE Security (As far as I understand we cant run in EXE_SECURITY_NS on the RP2350 [Appears to be correct]) thus EXE_SECURITY_S = 2 - // 0-3 // 0001 IMAGE_TYPE_EXE + /* ITEM 0 START based on 5.9.3.1 */ + .byte 0x42 /* (size_flag == 0, item_type == PICOBIN_BLOCK_ITEM_1BS_IMAGE_TYPE) */ + .byte 0x1 /* Block Size in words */ + /* image_type_flags (2 bytes) [See 5.9.3.1 / p419] */ + /* 15 -> 0 (1 for "Try before you buy" image [Wacky] */ + /* 12-14 -> 001 (RP2350 = 1) */ + /* 11 -> 0 (Reserved) */ + /* 8-10 -> 000 (EXE_CPU_ARM = 0), **WARNING** if I ever want to support RISC-V this needs to be 001 (EXE_CPU_RISCV) */ + /* 6-7 -> 00 (Reserved) */ + /* 4-5 -> 10 (2) EXE Security (As far as I understand we cant run in EXE_SECURITY_NS on the RP2350 [Appears to be correct]) thus EXE_SECURITY_S = 2 */ + /* 0-3 // 0001 IMAGE_TYPE_EXE */ .hword 0b0001000000100001 - // ITEM 0 END see 5.1.5.1 for explanation and 5.9.5.1 for the value / structure - .byte 0xff // PICOBIN_BLOCK_ITEM_2BS_LAST - .hword 0x0001 // Size of the item in words (predefined value) - .byte 0x00 // Padding - // Next Block Pointer - .word 0x00000000 // Next block pointer (0 means no more blocks) -// PICOBIN_BLOCK_MARKER_END -.word 0xab123579 // Marker for the end of the picobin block + /* ITEM 0 END see 5.1.5.1 for explanation and 5.9.5.1 for the value / structure */ + .byte 0xff /* PICOBIN_BLOCK_ITEM_2BS_LAST */ + .hword 0x0001 /* Size of the item in words (predefined value) */ + .byte 0x00 /* Padding */ + /* Next Block Pointer */ + .word 0x00000000 /* Next block pointer (0 means no more blocks) */ +/* PICOBIN_BLOCK_MARKER_END */ +.word 0xab123579 /* Marker for the end of the picobin block */ diff --git a/cpu/rp2350/vectors.c b/cpu/rp2350/vectors.c index fc7a0bd9a2..36d0079f4c 100644 --- a/cpu/rp2350/vectors.c +++ b/cpu/rp2350/vectors.c @@ -1,33 +1,26 @@ /* - * Copyright (C) 2021 Ishraq Ibne Ashraf - * - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. + * SPDX-FileCopyrightText: 2025 Tom Hert + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only */ /** - * @ingroup cpu_ro2040 + * @ingroup cpu_rp2350 * @{ * - * @file vectors.c - * @brief Startup code and interrupt vector definition + * @file + * @brief Interrupt vector table for the RP2350 * - * @author Ishraq Ibne Ashraf - * - * @} + * @author Tom Hert */ +#include "RP2350.h" #include "cpu_conf.h" #include "vectors_cortexm.h" -#include "RP2350.h" /* define a local dummy handler as it needs to be in the same compilation unit * as the alias definition */ -void dummy_handler(void) { - dummy_handler_default(); -} +void dummy_handler(void) { dummy_handler_default(); } /* rp2350 specific interrupt vector */ WEAK_DEFAULT void isr_timer0_0(void); @@ -84,57 +77,60 @@ WEAK_DEFAULT void isr_spareirq_4(void); WEAK_DEFAULT void isr_spareirq_5(void); /* CPU specific interrupt vector table */ -ISR_VECTOR(1) const isr_t vector_cpu[CPU_IRQ_NUMOF] = { - (void*) isr_timer0_0, /* 0 TIMER0_IRQ_0 */ - (void*) isr_timer0_1, /* 1 TIMER0_IRQ_1 */ - (void*) isr_timer0_2, /* 2 TIMER0_IRQ_2 */ - (void*) isr_timer0_3, /* 3 TIMER0_IRQ_3 */ - (void*) isr_timer1_0, /* 4 TIMER1_IRQ_0 */ - (void*) isr_timer1_1, /* 5 TIMER1_IRQ_1 */ - (void*) isr_timer1_2, /* 6 TIMER1_IRQ_2 */ - (void*) isr_timer1_3, /* 7 TIMER1_IRQ_3 */ - (void*) isr_pwm_wrap_0, /* 8 PWM_IRQ_WRAP_0 */ - (void*) isr_pwm_wrap_1, /* 9 PWM_IRQ_WRAP_1 */ - (void*) isr_dma_0, /* 10 DMA_IRQ_0 */ - (void*) isr_dma_1, /* 11 DMA_IRQ_1 */ - (void*) isr_dma_2, /* 12 DMA_IRQ_2 */ - (void*) isr_dma_3, /* 13 DMA_IRQ_3 */ - (void*) isr_usbctrl, /* 14 USBCTRL_IRQ */ - (void*) isr_pio0_0, /* 15 PIO0_IRQ_0 */ - (void*) isr_pio0_1, /* 16 PIO0_IRQ_1 */ - (void*) isr_pio1_0, /* 17 PIO1_IRQ_0 */ - (void*) isr_pio1_1, /* 18 PIO1_IRQ_1 */ - (void*) isr_pio2_0, /* 19 PIO2_IRQ_0 */ - (void*) isr_pio2_1, /* 20 PIO2_IRQ_1 */ - (void*) isr_io_bank0, /* 21 IO_IRQ_BANK0 */ - (void*) isr_io_bank0_ns, /* 22 IO_IRQ_BANK0_NS */ - (void*) isr_io_qspi, /* 23 IO_IRQ_QSPI */ - (void*) isr_io_qspi_ns, /* 24 IO_IRQ_QSPI_NS */ - (void*) isr_sio_fifo, /* 25 SIO_IRQ_FIFO */ - (void*) isr_sio_bell, /* 26 SIO_IRQ_BELL */ - (void*) isr_sio_fifo_ns, /* 27 SIO_IRQ_FIFO_NS */ - (void*) isr_sio_bell_ns, /* 28 SIO_IRQ_BELL_NS */ - (void*) isr_sio_mtimecmp, /* 29 SIO_IRQ_MTIMECMP */ - (void*) isr_clocks, /* 30 CLOCKS_IRQ */ - (void*) isr_spi0, /* 31 SPI0_IRQ */ - (void*) isr_spi1, /* 32 SPI1_IRQ */ - (void*) isr_uart0, /* 33 UART0_IRQ */ - (void*) isr_uart1, /* 34 UART1_IRQ */ - (void*) isr_adc_fifo, /* 35 ADC_IRQ_FIFO */ - (void*) isr_i2c0, /* 36 I2C0_IRQ */ - (void*) isr_i2c1, /* 37 I2C1_IRQ */ - (void*) isr_otp, /* 38 OTP_IRQ */ - (void*) isr_trng, /* 39 TRNG_IRQ */ - (void*) isr_proc0_cti, /* 40 PROC0_IRQ_CTI */ - (void*) isr_proc1_cti, /* 41 PROC1_IRQ_CTI */ - (void*) isr_pll_sys, /* 42 PLL_SYS_IRQ */ - (void*) isr_pll_usb, /* 43 PLL_USB_IRQ */ - (void*) isr_powman_pow, /* 44 POWMAN_IRQ_POW */ - (void*) isr_powman_timer, /* 45 POWMAN_IRQ_TIMER */ - (void*) isr_spareirq_0, /* 46 SPAREIRQ_IRQ_0 */ - (void*) isr_spareirq_1, /* 47 SPAREIRQ_IRQ_1 */ - (void*) isr_spareirq_2, /* 48 SPAREIRQ_IRQ_2 */ - (void*) isr_spareirq_3, /* 49 SPAREIRQ_IRQ_3 */ - (void*) isr_spareirq_4, /* 50 SPAREIRQ_IRQ_4 */ - (void*) isr_spareirq_5, /* 51 SPAREIRQ_IRQ_5 */ +ISR_VECTOR(1) +const isr_t vector_cpu[CPU_IRQ_NUMOF] = { + (void*)isr_timer0_0, /* 0 TIMER0_IRQ_0 */ + (void*)isr_timer0_1, /* 1 TIMER0_IRQ_1 */ + (void*)isr_timer0_2, /* 2 TIMER0_IRQ_2 */ + (void*)isr_timer0_3, /* 3 TIMER0_IRQ_3 */ + (void*)isr_timer1_0, /* 4 TIMER1_IRQ_0 */ + (void*)isr_timer1_1, /* 5 TIMER1_IRQ_1 */ + (void*)isr_timer1_2, /* 6 TIMER1_IRQ_2 */ + (void*)isr_timer1_3, /* 7 TIMER1_IRQ_3 */ + (void*)isr_pwm_wrap_0, /* 8 PWM_IRQ_WRAP_0 */ + (void*)isr_pwm_wrap_1, /* 9 PWM_IRQ_WRAP_1 */ + (void*)isr_dma_0, /* 10 DMA_IRQ_0 */ + (void*)isr_dma_1, /* 11 DMA_IRQ_1 */ + (void*)isr_dma_2, /* 12 DMA_IRQ_2 */ + (void*)isr_dma_3, /* 13 DMA_IRQ_3 */ + (void*)isr_usbctrl, /* 14 USBCTRL_IRQ */ + (void*)isr_pio0_0, /* 15 PIO0_IRQ_0 */ + (void*)isr_pio0_1, /* 16 PIO0_IRQ_1 */ + (void*)isr_pio1_0, /* 17 PIO1_IRQ_0 */ + (void*)isr_pio1_1, /* 18 PIO1_IRQ_1 */ + (void*)isr_pio2_0, /* 19 PIO2_IRQ_0 */ + (void*)isr_pio2_1, /* 20 PIO2_IRQ_1 */ + (void*)isr_io_bank0, /* 21 IO_IRQ_BANK0 */ + (void*)isr_io_bank0_ns, /* 22 IO_IRQ_BANK0_NS */ + (void*)isr_io_qspi, /* 23 IO_IRQ_QSPI */ + (void*)isr_io_qspi_ns, /* 24 IO_IRQ_QSPI_NS */ + (void*)isr_sio_fifo, /* 25 SIO_IRQ_FIFO */ + (void*)isr_sio_bell, /* 26 SIO_IRQ_BELL */ + (void*)isr_sio_fifo_ns, /* 27 SIO_IRQ_FIFO_NS */ + (void*)isr_sio_bell_ns, /* 28 SIO_IRQ_BELL_NS */ + (void*)isr_sio_mtimecmp, /* 29 SIO_IRQ_MTIMECMP */ + (void*)isr_clocks, /* 30 CLOCKS_IRQ */ + (void*)isr_spi0, /* 31 SPI0_IRQ */ + (void*)isr_spi1, /* 32 SPI1_IRQ */ + (void*)isr_uart0, /* 33 UART0_IRQ */ + (void*)isr_uart1, /* 34 UART1_IRQ */ + (void*)isr_adc_fifo, /* 35 ADC_IRQ_FIFO */ + (void*)isr_i2c0, /* 36 I2C0_IRQ */ + (void*)isr_i2c1, /* 37 I2C1_IRQ */ + (void*)isr_otp, /* 38 OTP_IRQ */ + (void*)isr_trng, /* 39 TRNG_IRQ */ + (void*)isr_proc0_cti, /* 40 PROC0_IRQ_CTI */ + (void*)isr_proc1_cti, /* 41 PROC1_IRQ_CTI */ + (void*)isr_pll_sys, /* 42 PLL_SYS_IRQ */ + (void*)isr_pll_usb, /* 43 PLL_USB_IRQ */ + (void*)isr_powman_pow, /* 44 POWMAN_IRQ_POW */ + (void*)isr_powman_timer, /* 45 POWMAN_IRQ_TIMER */ + (void*)isr_spareirq_0, /* 46 SPAREIRQ_IRQ_0 */ + (void*)isr_spareirq_1, /* 47 SPAREIRQ_IRQ_1 */ + (void*)isr_spareirq_2, /* 48 SPAREIRQ_IRQ_2 */ + (void*)isr_spareirq_3, /* 49 SPAREIRQ_IRQ_3 */ + (void*)isr_spareirq_4, /* 50 SPAREIRQ_IRQ_4 */ + (void*)isr_spareirq_5, /* 51 SPAREIRQ_IRQ_5 */ }; + +/** @} */ diff --git a/cpu/rp2350/xosc.c b/cpu/rp2350/xosc.c index 5f31580ebe..c398e28ec9 100644 --- a/cpu/rp2350/xosc.c +++ b/cpu/rp2350/xosc.c @@ -1,22 +1,17 @@ /* - * Copyright (C) 2021 Otto-von-Guericke Universität Magdeburg - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. + * SPDX-FileCopyrightText: 2025 Tom Hert + * SPDX-FileCopyrightText: 2025 HAW Hamburg + * SPDX-License-Identifier: LGPL-2.1-only */ /** - * @ingroup cpu_rpx0xx + * @ingroup cpu_rp2350 * @{ * * @file - * @brief Implementation of the crystal oscillator (XOSC) + * @brief XOSC implementation for the RP2350 * - * @author Marian Buschsieweke - * @author Fabian Hüßler - * - * @} + * @author Tom Hert */ #include @@ -26,33 +21,35 @@ #include "macros/units.h" #include "periph_cpu.h" -// Based on datasheet 8.2.4 (1ms wait time) +/* Based on datasheet 8.2.4 (1ms wait time) */ #define STARTUP_DELAY 47 #define MAX_XOSC_COUNTER_SIZE 0xFFFF -#define Sleep100HzSpeed 60000 -#define CYCLES_PER_MS (Sleep100HzSpeed / 1000) +#define SLEEP_100HZ_SPEED 12000000UL +#define CYCLES_PER_MS (SLEEP_100HZ_SPEED / 1000) void xosc_start(void) { - // Set the FREQ_RANGE - XOSC->CTRL = XOSC_CTRL_FREQ_RANGE_VALUE_1_15MHZ; - // Set the startup delay (default 1ms) - XOSC->STARTUP = STARTUP_DELAY; - // set enable bit - atomic_set(&XOSC->CTRL, XOSC_CTRL_ENABLE_VALUE_ENABLE << XOSC_CTRL_ENABLE_LSB); + /* Set the FREQ_RANGE */ + XOSC->CTRL = XOSC_CTRL_FREQ_RANGE_VALUE_1_15MHZ; + /* Set the startup delay (default 1ms) */ + XOSC->STARTUP = STARTUP_DELAY; + /* set enable bit */ + atomic_set(&XOSC->CTRL, + XOSC_CTRL_ENABLE_VALUE_ENABLE << XOSC_CTRL_ENABLE_LSB); - while (!(XOSC->STATUS & XOSC_STATUS_STABLE_BITS)) { - // Wait for the crystal to stabilize - } + while (!(XOSC->STATUS & XOSC_STATUS_STABLE_BITS)) { + /* Wait for the crystal to stabilize */ + } } -void xosc_sleep(int32_t milliseconds) { - for (int32_t i = 0; i < milliseconds; i++) { - XOSC->COUNT = CYCLES_PER_MS* milliseconds; - while (XOSC->COUNT != 0) { +void xosc_sleep(uint32_t milliseconds) { + for (uint32_t i = milliseconds; i > 0; i--) { + XOSC->COUNT = CYCLES_PER_MS; + while (XOSC->COUNT != 0) {}; } - } } void xosc_stop(void) { - // @TODO + /* @TODO */ } + +/** @} */ diff --git a/makefiles/features_existing.inc.mk b/makefiles/features_existing.inc.mk index a76197bf8b..de51f5cd76 100644 --- a/makefiles/features_existing.inc.mk +++ b/makefiles/features_existing.inc.mk @@ -85,8 +85,8 @@ FEATURES_EXISTING := \ cpu_nrf53 \ cpu_nrf9160 \ cpu_qn908x \ - cpu_rpx0xx \ cpu_rp2350 \ + cpu_rpx0xx \ cpu_sam3 \ cpu_sam4s \ cpu_samd21 \