mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-16 18:13:49 +01:00
boards: Raspberry Pi Pico 2 support
This commit is contained in:
parent
014b17250b
commit
359d3a9efd
11
boards/rpi-pico-2/Kconfig
Normal file
11
boards/rpi-pico-2/Kconfig
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2025 Tom Hert <git@annsann.eu>
|
||||||
|
# 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
|
||||||
3
boards/rpi-pico-2/Makefile
Normal file
3
boards/rpi-pico-2/Makefile
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
MODULE = board
|
||||||
|
|
||||||
|
include $(RIOTBASE)/Makefile.base
|
||||||
1
boards/rpi-pico-2/Makefile.features
Normal file
1
boards/rpi-pico-2/Makefile.features
Normal file
@ -0,0 +1 @@
|
|||||||
|
CPU := rp2350
|
||||||
7
boards/rpi-pico-2/Makefile.include
Normal file
7
boards/rpi-pico-2/Makefile.include
Normal file
@ -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
|
||||||
15
boards/rpi-pico-2/board.c
Normal file
15
boards/rpi-pico-2/board.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Tom Hert <git@annsann.eu>
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
7
boards/rpi-pico-2/dist/openocd.cfg
vendored
Normal file
7
boards/rpi-pico-2/dist/openocd.cfg
vendored
Normal file
@ -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
|
||||||
116
boards/rpi-pico-2/doc.md
Normal file
116
boards/rpi-pico-2/doc.md
Normal file
@ -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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 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.
|
||||||
43
boards/rpi-pico-2/include/board.h
Normal file
43
boards/rpi-pico-2/include/board.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Tom Hert <git@annsann.eu>
|
||||||
|
* 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 <git@annsann.eu>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
/** @} */
|
||||||
18
boards/rpi-pico-2/include/gpio_params.h
Normal file
18
boards/rpi-pico-2/include/gpio_params.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Tom Hert <git@annsann.eu>
|
||||||
|
* 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
|
||||||
20
boards/rpi-pico-2/include/periph_conf.h
Normal file
20
boards/rpi-pico-2/include/periph_conf.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Tom Hert <git@annsann.eu>
|
||||||
|
* SPDX-FileCopyrightText: 2025 HAW Hamburg
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "RP2350.h"
|
||||||
|
#include "periph_cpu.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@ -1,9 +1,6 @@
|
|||||||
# Copyright (C) 2021 Otto-von-Guericke-Universität Magdeburg
|
# SPDX-FileCopyrightText: 2025 Tom Hert <git@annsann.eu>
|
||||||
#
|
# SPDX-FileCopyrightText: 2025 HAW Hamburg
|
||||||
# This file is subject to the terms and conditions of the GNU Lesser
|
# SPDX-License-Identifier: LGPL-2.1-only
|
||||||
# General Public License v2.1. See the file LICENSE in the top level
|
|
||||||
# directory for more details.
|
|
||||||
#
|
|
||||||
|
|
||||||
config CPU_FAM_RP2350
|
config CPU_FAM_RP2350
|
||||||
bool
|
bool
|
||||||
|
|||||||
@ -1,13 +1,6 @@
|
|||||||
MODULE = cpu
|
MODULE = cpu
|
||||||
|
|
||||||
USEPKG += picosdk
|
DIRS += $(RIOTCPU)/cortexm_common
|
||||||
|
DIRS += periph
|
||||||
DIRS = $(RIOTCPU)/cortexm_common periph
|
|
||||||
|
|
||||||
include $(RIOTBASE)/Makefile.base
|
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
|
|
||||||
|
|||||||
@ -1,2 +1,3 @@
|
|||||||
|
USEPKG += picosdk
|
||||||
|
|
||||||
include $(RIOTCPU)/cortexm_common/Makefile.dep
|
include $(RIOTCPU)/cortexm_common/Makefile.dep
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
CPU_CORE := cortex-m33
|
CPU_CORE := cortex-m33
|
||||||
CPU_FAM := RP2350
|
CPU_FAM := RP2350
|
||||||
|
CPU_ARCH = armv8m
|
||||||
|
CPU_MODEL = rp2350
|
||||||
|
|
||||||
include $(RIOTCPU)/cortexm_common/Makefile.features
|
include $(RIOTCPU)/cortexm_common/Makefile.features
|
||||||
|
|
||||||
|
|||||||
@ -1,22 +1,19 @@
|
|||||||
ROM_LEN ?= 2097152 # = 2 MiB used in the RPi Pico
|
ROM_LEN ?= 2097152 # = 2 MiB used in the RPi Pico
|
||||||
ROM_OFFSET := 0 # bootloader size
|
ROM_OFFSET := 0 # bootloader size
|
||||||
RAM_LEN := 0x82000 # 520kB = 532479 used in the RPi Pico 2350
|
RAM_LEN := 0x82000 # 520kB = 532479 used in the RPi Pico 2350
|
||||||
ROM_START_ADDR := 0x10000000 # XIP Non-Secure address for rp2350
|
ROM_START_ADDR := 0x10000000 # XIP Non-Secure address for rp2350
|
||||||
RAM_START_ADDR := 0x20000000 # Non-Secure RAM 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
|
# CPU and architecture specific flags
|
||||||
CFLAGS += -D$(CPU_MODEL)
|
CFLAGS += -D$(CPU_MODEL)
|
||||||
CFLAGS += -DROM_START_ADDR=$(ROM_START_ADDR)
|
CFLAGS += -DROM_START_ADDR=$(ROM_START_ADDR)
|
||||||
CFLAGS += -DRAM_START_ADDR=$(RAM_START_ADDR)
|
CFLAGS += -DRAM_START_ADDR=$(RAM_START_ADDR)
|
||||||
CFLAGS += -Wno-error
|
CFLAGS += -Wno-error
|
||||||
|
|
||||||
# Include paths
|
# Include paths
|
||||||
INCLUDES += -I$(RIOTCPU)/rp2350/include
|
INCLUDES += -I$(RIOTCPU)/rp2350/include
|
||||||
INCLUDES += -isystem$(RIOTBASE)/dist/tools/picosdk/picosdk/src/rp2_common/cmsis/stub/CMSIS/Core/Include
|
INCLUDES += -isystem$(RIOTBASE)/build/pkg/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/Device/RP2350/Include
|
||||||
|
|
||||||
# Linker flags
|
# Linker flags
|
||||||
LINKFLAGS += -mcpu=$(CPU_ARCH) -mthumb
|
LINKFLAGS += -mcpu=$(CPU_ARCH) -mthumb
|
||||||
@ -29,7 +26,7 @@ VECTORS_FILE := $(RIOTCPU)/rp2350/vectors.c
|
|||||||
|
|
||||||
# Supported programmers and debuggers
|
# Supported programmers and debuggers
|
||||||
PROGRAMMERS_SUPPORTED := picotool openocd jlink
|
PROGRAMMERS_SUPPORTED := picotool openocd jlink
|
||||||
PROGRAMMER ?= openocd
|
PROGRAMMER ?= picotool
|
||||||
OPENOCD_DEBUG_ADAPTER ?= dap
|
OPENOCD_DEBUG_ADAPTER ?= dap
|
||||||
|
|
||||||
# Include the base Cortex-M makefile
|
# Include the base Cortex-M makefile
|
||||||
|
|||||||
@ -1,51 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Tom Hert <git@annsann.eu>
|
||||||
|
* 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 <git@annsann.eu>
|
||||||
|
*/
|
||||||
|
|
||||||
#include "periph_cpu.h"
|
#include "periph_cpu.h"
|
||||||
|
|
||||||
void clock_reset(void) {
|
void clock_reset(void) {
|
||||||
// Reset the clock system
|
/* Reset the clock system */
|
||||||
reset_component(RESET_PLL_SYS, RESET_PLL_SYS);
|
reset_component(RESET_PLL_SYS, RESET_PLL_SYS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Configures the XOSC and then sets CLK_SYS, PLL_SYS and CLK_PERI to it
|
* @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
|
* @warning Make sure to call clock_reset() before this function to reset the
|
||||||
* @note RP2350 Docs Chapter 8, mostly 8.2 for more details
|
* clock system
|
||||||
*/
|
* @see RP2350 Docs Chapter 8, mostly 8.2 for more details
|
||||||
|
*/
|
||||||
void cpu_clock_init(void) {
|
void cpu_clock_init(void) {
|
||||||
// Enable the XOSC
|
/* Enable the XOSC */
|
||||||
xosc_start();
|
xosc_start();
|
||||||
|
|
||||||
/**
|
/* Setup the PLL using the XOSC as the reference clock. */
|
||||||
* Setup the PLL using the XOSC as the reference clock.
|
PLL_SYS->FBDIV_INT =
|
||||||
*/
|
PLL_FEEDBACK_DIVIDER_VALUE; /* Set the feedback divider */
|
||||||
//PLL_SYS->CS = REF_DIV; // Set the reference divider
|
|
||||||
PLL_SYS->FBDIV_INT = 125; // Set the feedback divider
|
|
||||||
|
|
||||||
/**
|
/* Set the post-dividers for the PLL output.*/
|
||||||
* Set the post-dividers for the PLL output.
|
|
||||||
*/
|
|
||||||
PLL_SYS->PRIM = PDIV;
|
PLL_SYS->PRIM = PDIV;
|
||||||
// Turn on PLL
|
/* Turn on PLL */
|
||||||
atomic_clear(&PLL_SYS->PWR, PLL_PWR_PD_BITS | PLL_PWR_VCOPD_BITS | PLL_PWR_POSTDIVPD_BITS);
|
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);
|
xosc_sleep(10);
|
||||||
|
|
||||||
// // Wait for lock
|
/* Based on the description in chapter 8 this is something that should be done
|
||||||
// while (!(PLL_SYS->CS & PLL_CS_LOCK_BITS)) {
|
* However, it appears to cause issues and is not done by other examples on the
|
||||||
// // Wait for the PLL to lock
|
* internet. This needs to be investigated further. */
|
||||||
// }
|
|
||||||
|
|
||||||
// AUXSRC = 0x0 7:5 && SRC == 0x0 0
|
/* Wait for lock */
|
||||||
// CLOCKS: CLK_SYS_CTRL CLK_PERI_CTRL_ENABLE_BIT
|
/* while (!(PLL_SYS->CS & PLL_CS_LOCK_BITS)) { */
|
||||||
CLOCKS->CLK_SYS_CTRL = 1;
|
/* Wait for the PLL to lock */
|
||||||
|
/* } */
|
||||||
|
|
||||||
// This register contains one decoded bit for each of the clock sources enumerated in the CTRL SRC field.
|
/* AUXSRC = 0x0 7:5 && SRC == 0x0 0 */
|
||||||
// The bit does not directly correlate with the value of the SRC field
|
CLOCKS->CLK_SYS_CTRL = CLK_SYS_PERI_CTRL_ENABLE_BIT;
|
||||||
// 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) {}
|
|
||||||
|
|
||||||
// src: CLOCKS: CLK_PERI_CTRL
|
/* This register contains one decoded bit for each of the clock sources
|
||||||
// AUXSRC = 0x0 -> CLK_SYS Indirectly through lower line
|
* 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;
|
CLOCKS->CLK_PERI_CTRL = CLK_PERI_CTRL_ENABLE_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|||||||
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Tom Hert <git@annsann.eu>
|
||||||
|
* 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 <git@annsann.eu>
|
||||||
|
*/
|
||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
|
||||||
#include "RP2350.h"
|
#include "RP2350.h"
|
||||||
@ -12,22 +28,32 @@
|
|||||||
#define DEBUG_WITH_OSC
|
#define DEBUG_WITH_OSC
|
||||||
|
|
||||||
void gpio_reset(void) {
|
void gpio_reset(void) {
|
||||||
reset_component(RESET_PADS_BANK0, RESET_PADS_BANK0);
|
reset_component(RESET_PADS_BANK0, RESET_PADS_BANK0);
|
||||||
reset_component(RESET_IO_BANK0, RESET_IO_BANK0);
|
reset_component(RESET_IO_BANK0, RESET_IO_BANK0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpu_init(void) {
|
void cpu_init(void) {
|
||||||
/* initialize the Cortex-M core */
|
/* initialize the Cortex-M core, once UART support is moved
|
||||||
//cortexm_init();
|
* to shared driver as currently this will cause unhandled interrupts */
|
||||||
gpio_reset();
|
/* cortexm_init(); */
|
||||||
//_cpu_reset();
|
|
||||||
|
|
||||||
/* initialize stdio prior to periph_init() to allow use of DEBUG() there */
|
/* Reset GPIO state */
|
||||||
early_init();
|
gpio_reset();
|
||||||
|
|
||||||
clock_reset();
|
/* Reset clock to default state */
|
||||||
cpu_clock_init();
|
clock_reset();
|
||||||
|
|
||||||
/* trigger static peripheral initialization */
|
/* initialize the CPU clock */
|
||||||
periph_init();
|
cpu_clock_init();
|
||||||
|
|
||||||
|
/* initialize the early peripherals */
|
||||||
|
early_init();
|
||||||
|
|
||||||
|
/* trigger static peripheral initialization */
|
||||||
|
periph_init();
|
||||||
|
|
||||||
|
/* initialize the board */
|
||||||
|
board_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|||||||
5
cpu/rp2350/doc.md
Normal file
5
cpu/rp2350/doc.md
Normal file
@ -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.
|
||||||
@ -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
|
|
||||||
|
|
||||||
*/
|
|
||||||
@ -1,69 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Tom Hert <git@annsann.eu>
|
||||||
|
* SPDX-FileCopyrightText: 2025 HAW Hamburg
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-only
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup cpu_rp2350
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Clock configuration for the RP2350
|
||||||
|
*
|
||||||
|
* @author Tom Hert <git@annsann.eu>
|
||||||
|
*/
|
||||||
|
|
||||||
#include "RP2350.h"
|
#include "RP2350.h"
|
||||||
|
#include "macros/units.h"
|
||||||
|
|
||||||
// Based on hardware/regs/xosc.h and 8.2.8
|
/** 1-15 MHz range
|
||||||
#define XOSC_CTRL_FREQ_RANGE_VALUE_1_15MHZ 0xaa0u
|
* @see hardware/regs/xosc.h and chapter 8.2.8
|
||||||
#define XOSC_CTRL_FREQ_RANGE_VALUE_10_30MHZ 0xaa1u
|
*/
|
||||||
#define XOSC_CTRL_FREQ_RANGE_VALUE_25_60MHZ 0xaa2u
|
#define XOSC_CTRL_FREQ_RANGE_VALUE_1_15MHZ 0xaa0u
|
||||||
#define XOSC_CTRL_FREQ_RANGE_VALUE_40_100MHZ 0xaa3u
|
/** 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
|
#define XOSC_CTRL_ENABLE_VALUE_DISABLE 0xd1eu
|
||||||
|
/** Enable the XOSC */
|
||||||
#define XOSC_CTRL_ENABLE_VALUE_ENABLE 0xfabu
|
#define XOSC_CTRL_ENABLE_VALUE_ENABLE 0xfabu
|
||||||
#define XOSC_CTRL_ENABLE_LSB 12u
|
/** LSB of the enable bit */
|
||||||
#define XOSC_STATUS_STABLE_BITS 0x80000000u
|
#define XOSC_CTRL_ENABLE_LSB 12u
|
||||||
#define XOSC_HZ MHZ(12)
|
/** Stable bit in the XOSC status register */
|
||||||
#define REF_DIV 2
|
#define XOSC_STATUS_STABLE_BITS 0x80000000u
|
||||||
#define VCO_FREQ 750000000u
|
/** Default crystal frequency is 12 MHz */
|
||||||
#define PD1 6
|
#define XOSC_HZ MHZ(12u)
|
||||||
#define PD2 2
|
/** 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
|
#define PLL_PWR_PD_BITS 0x00000001u
|
||||||
|
/** VCO power down bits for the PLL */
|
||||||
#define PLL_PWR_VCOPD_BITS 0x00000020u
|
#define PLL_PWR_VCOPD_BITS 0x00000020u
|
||||||
|
/** Lock bit in the PLL control status register */
|
||||||
#define PLL_CS_LOCK_BITS 0x80000000u
|
#define PLL_CS_LOCK_BITS 0x80000000u
|
||||||
|
/** LSB of the post divider 1 in the PLL primary register */
|
||||||
#define PLL_PRIM_POSTDIV1_LSB 16u
|
#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_PRIM_POSTDIV2_LSB 12u
|
||||||
#define PLL_PWR_POSTDIVPD_BITS 0x00000008u
|
/** Post divider power down bits for the PLL */
|
||||||
#define CLK_PERI_CTRL_ENABLE_BIT 1 << 11
|
#define PLL_PWR_POSTDIVPD_BITS 0x00000008u
|
||||||
#define XOSC_FREQ 12000000
|
/** Enable bit for the peripheral clock control register */
|
||||||
#define POSTDIV1 6
|
#define CLK_PERI_CTRL_ENABLE_BIT (1u << 11u)
|
||||||
#define POSTDIV2 2
|
/** Default CPU frequency in Hz, set to 125 MHz as per hardware manual */
|
||||||
#define CPUFREQ 125000000
|
#define CPUFREQ 125000000u
|
||||||
#define CLOCK_XOSC_MAX MHZ(15) /**< Maximum crystal frequency */
|
/** Maximum crystal frequency */
|
||||||
#define CLOCK_XOSC_MIN MHZ(5) /**< Minimum crystal frequency */
|
#define CLOCK_XOSC_MAX MHZ(15u)
|
||||||
#define CLOCK_XOSC (XOSC_HZ) /**< Crystal frequency */
|
/** Minimum crystal frequency */
|
||||||
#define PLL_POSTDIV_MIN (1U) /**< Minimum value of the post PLL clock divers */
|
#define CLOCK_XOSC_MIN MHZ(5u)
|
||||||
#define PLL_POSTDIV_MAX (7U) /**< Maximum value of the post PLL clock divers */
|
/** Crystal frequency */
|
||||||
#define PLL_VCO_FEEDBACK_SCALE_MIN (16U) /**< Minimum value of the PLL VCO feedback scaler */
|
#define CLOCK_XOSC (XOSC_HZ)
|
||||||
#define PLL_VCO_FEEDBACK_SCALE_MAX (320U) /**< Maximum value of the PLL VCO feedback scaler */
|
/** Minimum value of the post PLL clock divers */
|
||||||
#define PLL_REF_DIV_MIN (1U) /**< Minimum value of the clock divider applied before
|
#define PLL_POSTDIV_MIN 1u
|
||||||
* feeding in the reference clock into the PLL */
|
/** Maximum value of the post PLL clock divers */
|
||||||
#define PLL_REF_DIV_MAX (1U) /**< Minimum value of the clock divider applied before
|
#define PLL_POSTDIV_MAX 7u
|
||||||
* feeding in the reference clock into the PLL */
|
/** 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)
|
#if (PLL_VCO_FEEDBACK_SCALE_MIN < PLL_VCO_FEEDBACK_SCALE_MIN) || \
|
||||||
#error "Value for PLL_VCO_FEEDBACK_SCALE out of range, check config"
|
(PLL_VCO_FEEDBACK_SCALE_MAX > PLL_VCO_FEEDBACK_SCALE_MAX)
|
||||||
|
# error "Value for PLL_VCO_FEEDBACK_SCALE out of range, check config"
|
||||||
#endif
|
#endif
|
||||||
#if (PLL_REF_DIV_MIN < PLL_REF_DIV_MIN) || (PLL_REF_DIV_MAX > PLL_REF_DIV_MAX)
|
#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
|
#endif
|
||||||
#if (PLL_POSTDIV_MIN < PLL_POSTDIV_MIN) || (PLL_POSTDIV_MAX > PLL_POSTDIV_MAX)
|
#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
|
#endif
|
||||||
#if ((CLOCK_XOSC > CLOCK_XOSC_MAX) || (CLOCK_XOSC < CLOCK_XOSC_MIN))
|
#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
|
#endif
|
||||||
|
|
||||||
#define PDIV ((PD1 << PLL_PRIM_POSTDIV1_LSB) | (PD2 << PLL_PRIM_POSTDIV2_LSB))
|
/** Post divider for the PLL, calculated based on the post divider values */
|
||||||
#define FBDIV ((VCO_FREQ / XOSC_HZ) / REF_DIV)
|
#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.
|
* @brief Configures the Crystal to run.
|
||||||
*
|
* @note The reference hardware manual suggests to use a 12 MHz crystal, which we
|
||||||
* @param f_ref Desired frequency in Hz
|
* use by default.
|
||||||
*
|
|
||||||
* @pre 1 MHz <= @p f_ref <= 15 MHz.
|
|
||||||
*
|
|
||||||
* The reference hardware manual suggests to use a 12 MHz crystal.
|
|
||||||
*/
|
*/
|
||||||
void xosc_start(void);
|
void xosc_start(void);
|
||||||
|
|
||||||
@ -73,9 +131,10 @@ void xosc_start(void);
|
|||||||
void xosc_stop(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.
|
* @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
|
* @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
|
* @pre Make sure to call clock_reset() before this function to reset the
|
||||||
* @note RP2350 Docs Chapter 8, mostly 8.2 for more details
|
* clock system
|
||||||
*/
|
* @see RP2350 Docs Chapter 8, mostly 8.2 for more details
|
||||||
|
*/
|
||||||
void cpu_clock_init(void);
|
void cpu_clock_init(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|||||||
@ -1,13 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Tom Hert <git@annsann.eu>
|
||||||
|
* SPDX-FileCopyrightText: 2025 HAW Hamburg
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-only
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "cpu_conf_common.h"
|
/**
|
||||||
|
* @ingroup cpu_rp2350
|
||||||
|
* @{
|
||||||
|
* @file
|
||||||
|
* @brief CPU configuration for the RP2350
|
||||||
|
*
|
||||||
|
* @author Tom Hert <git@annsann.eu>
|
||||||
|
*/
|
||||||
|
|
||||||
#include "RP2350.h"
|
#include "RP2350.h"
|
||||||
#include "core_cm33.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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -16,3 +29,5 @@ extern "C" {
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|||||||
@ -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
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup cpu_rp2350
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief GPIO configuration for the RP2350
|
||||||
|
*
|
||||||
|
* @author Tom Hert <git@annsann.eu>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** 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
|
* @brief Possible function values for @ref gpio_io_ctrl_t::function_select
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FUNCTION_SELECT_SPI = 1, /**< connect pin to the SPI peripheral
|
/** connect pin to the SPI peripheral (MISO/MOSI/SCK depends on pin) */
|
||||||
* (MISO/MOSI/SCK depends on pin) */
|
FUNCTION_SELECT_SPI = 1,
|
||||||
FUNCTION_SELECT_UART = 2, /**< connect pin to the UART peripheral
|
|
||||||
* (TXD/RXD depends on pin) */
|
/** connect pin to the UART peripheral (TXD/RXD depends on pin) */
|
||||||
FUNCTION_SELECT_I2C = 3, /**< connect pin to the I2C peripheral
|
FUNCTION_SELECT_UART = 2,
|
||||||
* (SCL/SDA depends on pin) */
|
|
||||||
FUNCTION_SELECT_PWM = 4, /**< connect pin to the timer for PWM
|
/** connect pin to the I2C peripheral (SCL/SDA depends on pin) */
|
||||||
* (channel depends on pin) */
|
FUNCTION_SELECT_I2C = 3,
|
||||||
FUNCTION_SELECT_SIO = 5, /**< use pin as vanilla GPIO */
|
|
||||||
FUNCTION_SELECT_PIO0 = 6, /**< connect pin to the first PIO peripheral */
|
/** connect pin to the timer for PWM (channel depends on pin) */
|
||||||
FUNCTION_SELECT_PIO1 = 7, /**< connect pin to the second PIO peripheral */
|
FUNCTION_SELECT_PWM = 4,
|
||||||
FUNCTION_SELECT_CLOCK = 8, /**< connect pin to the timer (depending on pin: external clock,
|
|
||||||
* clock output, or not supported) */
|
/** use pin as vanilla GPIO */
|
||||||
FUNCTION_SELECT_USB = 9, /**< connect pin to the USB peripheral
|
FUNCTION_SELECT_SIO = 5,
|
||||||
* (function depends on pin) */
|
|
||||||
FUNCTION_SELECT_NONE = 31, /**< Reset value, pin unconnected */
|
/** 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;
|
} gpio_function_select_t;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|||||||
@ -1,48 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Tom Hert <git@annsann.eu>
|
||||||
|
* SPDX-FileCopyrightText: 2025 HAW Hamburg
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-only
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "RP2350.h"
|
#include "RP2350.h"
|
||||||
|
|
||||||
#define ATOMIC_XOR_WRITE 0x1000
|
/**
|
||||||
#define ATOMIC_BITMASK_SET_WRITE 0x2000
|
* @ingroup cpu_rp2350
|
||||||
#define ATOMIC_BITMASK_CLEAR_WRITE 0x3000
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Helper functions for atomic register operations
|
||||||
|
*
|
||||||
|
* @author Tom Hert <git@annsann.eu>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** 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
|
* @brief Perform an atomic XOR write to a register
|
||||||
*
|
*
|
||||||
* @param[in] reg Pointer to the target register
|
* @param[in,out] reg Pointer to the target register
|
||||||
* @param[in] val Value to be XORed with the 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;
|
*(volatile uint32_t *)((uintptr_t)reg | ATOMIC_XOR_WRITE) = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set bits in a register atomically
|
* @brief Set bits in a register atomically
|
||||||
*
|
*
|
||||||
* @param[in] reg Pointer to the target register
|
* @param[in,out] reg Pointer to the target register
|
||||||
* @param[in] val Bit mask of bits to set
|
* @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;
|
*(volatile uint32_t *)((uintptr_t)reg | ATOMIC_BITMASK_SET_WRITE) = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Clear bits in a register atomically
|
* @brief Clear bits in a register atomically
|
||||||
*
|
*
|
||||||
* @param[in] reg Pointer to the target register
|
* @param[in,out] reg Pointer to the target register
|
||||||
* @param[in] val Bit mask of bits to clear
|
* @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;
|
*(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);
|
atomic_clear(&RESETS->RESET, reset_value);
|
||||||
while(~RESETS->RESET_DONE & reset_done_value) {
|
while (~RESETS->RESET_DONE & reset_done_value) {
|
||||||
// Wait for the reset to complete
|
/* Wait for the reset to complete */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|||||||
@ -1,52 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Tom Hert <git@annsann.eu>
|
||||||
|
* SPDX-FileCopyrightText: 2025 HAW Hamburg
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-only
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup cpu_rp2350
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Peripheral CPU definitions for the RP2350
|
||||||
|
*
|
||||||
|
* @author Tom Hert <git@annsann.eu>
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "cpu.h"
|
|
||||||
#include "RP2350.h"
|
#include "RP2350.h"
|
||||||
|
|
||||||
#include "uart_conf.h"
|
|
||||||
#include "clock_conf.h"
|
#include "clock_conf.h"
|
||||||
|
#include "cpu.h"
|
||||||
#include "gpio_conf.h"
|
#include "gpio_conf.h"
|
||||||
#include "helpers.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
|
#define HAVE_GPIO_T
|
||||||
typedef uint32_t gpio_t;
|
typedef uint32_t gpio_t;
|
||||||
|
|
||||||
#define LED0_PIN_ID 25
|
#include "periph/gpio.h"
|
||||||
#define OSC_DEBUG_PIN_ID 15
|
|
||||||
|
|
||||||
#define RESET_PLL_SYS 1 << 14
|
/** GPIO Pin ID for oscillator debugging */
|
||||||
#define RESET_PADS_BANK0 1 << 9
|
#define OSC_DEBUG_PIN_ID 15u
|
||||||
#define RESET_UART0 1 << 26
|
|
||||||
#define RESET_UART1 1 << 27
|
|
||||||
#define RESET_IO_BANK0 1 << 6
|
|
||||||
|
|
||||||
#define PADS_BANK0_GPIO0_IE_BITS 1<<6
|
/** Reset bit for the system PLL */
|
||||||
#define PADS_BANK0_ISO_BITS 1<<8
|
#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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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
|
* @brief Calculate the address of the GPIO pad register for a given pin
|
||||||
// by adding 4 bytes for each pin, starting at the base address of PADS_BANK0
|
* @param pin The GPIO pin number
|
||||||
// and adding 4 bytes to skip VOLTAGE_SELECT
|
* @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);
|
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;
|
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),
|
* @brief Calculate the address of the GPIO IO control register for a given
|
||||||
// so we can calculate the address by adding 8 bytes for each pin,
|
* pin
|
||||||
// starting at the base address of IO_BANK0
|
* @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;
|
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
|
#endif
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|||||||
@ -1,24 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Tom Hert <git@annsann.eu>
|
||||||
|
* SPDX-FileCopyrightText: 2025 HAW Hamburg
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-only
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "periph_cpu.h"
|
/**
|
||||||
#include "macros/units.h"
|
* @ingroup cpu_rp2350
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief UART configuration for the RP2350
|
||||||
|
*
|
||||||
|
* @author Tom Hert <git@annsann.eu>
|
||||||
|
*/
|
||||||
|
|
||||||
#include "RP2350.h"
|
#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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|||||||
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Tom Hert <git@annsann.eu>
|
||||||
|
* 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 <git@annsann.eu>
|
||||||
|
*/
|
||||||
|
|
||||||
#include "periph/gpio.h"
|
#include "periph/gpio.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -10,56 +26,71 @@
|
|||||||
#define ENABLE_DEBUG 0
|
#define ENABLE_DEBUG 0
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
#define GPIO_PIN_NUMOF 30U
|
|
||||||
|
|
||||||
|
|
||||||
int gpio_init(gpio_t pin, gpio_mode_t mode) {
|
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);
|
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_OE_CLR = 1LU << pin;
|
||||||
SIO->GPIO_OUT_CLR = 1LU << pin;
|
SIO->GPIO_OUT_CLR = 1LU << pin;
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case GPIO_OUT:
|
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 clear all bits except the drive strength bit
|
||||||
// We set that to the highest one possible (12mA)
|
* We set that to the highest one possible (12mA)
|
||||||
// to mimic the behavior of the pico1 GPIO driver
|
* to mimic the behavior of the pico1 GPIO driver
|
||||||
// (Not too sure why we do this, but it seems to be the standard)
|
* (Not too sure why we do this, but it seems to be the standard) */
|
||||||
*pad_reg = 0x3 << 4;
|
*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:
|
default:
|
||||||
// Unsupported mode
|
/* Unsupported mode */
|
||||||
return -ENOTSUP;
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
if (value) {
|
||||||
gpio_set(pin); // Set the pin to HIGH
|
gpio_set(pin); /* Set the pin to HIGH */
|
||||||
} else {
|
} else {
|
||||||
gpio_clear(pin); // Set the pin to LOW
|
gpio_clear(pin); /* Set the pin to LOW */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|||||||
@ -1,52 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Tom Hert <git@annsann.eu>
|
||||||
|
* 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 <git@annsann.eu>
|
||||||
|
*/
|
||||||
|
|
||||||
#include "periph/uart.h"
|
#include "periph/uart.h"
|
||||||
|
|
||||||
#include "periph_cpu.h"
|
#include "periph_cpu.h"
|
||||||
|
|
||||||
int uart_init(uart_t uart, uint32_t baud, uart_rx_cb_t rx_cb, void *arg) {
|
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
|
(void)uart;
|
||||||
IO_BANK0->GPIO0_CTRL = FUNCTION_SELECT_UART;
|
(void)baud;
|
||||||
IO_BANK0->GPIO1_CTRL = FUNCTION_SELECT_UART;
|
(void)rx_cb;
|
||||||
// Clear the ISO bits
|
(void)arg;
|
||||||
atomic_clear(&PADS_BANK0->GPIO0, PADS_BANK0_ISO_BITS);
|
/* Set the UART pins to the correct function */
|
||||||
atomic_clear(&PADS_BANK0->GPIO1, PADS_BANK0_ISO_BITS);
|
IO_BANK0->GPIO0_CTRL = FUNCTION_SELECT_UART;
|
||||||
// Set IE bit for gpio1
|
IO_BANK0->GPIO1_CTRL = FUNCTION_SELECT_UART;
|
||||||
PADS_BANK0->GPIO1 = PADS_BANK0->GPIO1 | PADS_BANK0_GPIO0_IE_BITS;
|
/* 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
|
/* We reset UART0 here, so we can be sure it is in a known state */
|
||||||
reset_component(RESET_UART0, RESET_UART0);
|
reset_component(RESET_UART0, RESET_UART0);
|
||||||
|
|
||||||
UART0->UARTIBRD = IBRD;
|
UART0->UARTIBRD = IBRD;
|
||||||
UART0->UARTFBRD = FBRD;
|
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,
|
int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t parity,
|
||||||
uart_stop_bits_t stop_bits) {
|
uart_stop_bits_t stop_bits) {
|
||||||
atomic_clear(&UART0->UARTCR, UART_UARTCR_UARTEN_BITS | UART_UARTCR_RXE_BITS |
|
(void)uart;
|
||||||
UART_UARTCR_TXE_BITS);
|
(void)data_bits;
|
||||||
// Set the data bits, parity, and stop bits
|
(void)stop_bits;
|
||||||
UART0->UARTLCR_H = (uint32_t)data_bits << 5;
|
atomic_clear(&UART0->UARTCR, UART_UARTCR_UARTEN_BITS | UART_UARTCR_RXE_BITS |
|
||||||
|
UART_UARTCR_TXE_BITS);
|
||||||
|
|
||||||
switch (parity) {
|
/* Set the data bits, parity, and stop bits
|
||||||
case UART_PARITY_NONE:
|
* Set to 8 bits (0b11) based on Table 1035 page 976
|
||||||
break;
|
*/
|
||||||
default:
|
UART0->UARTLCR_H = 0b11 << 5;
|
||||||
// @todo: Implement other parity modes lel
|
|
||||||
return UART_NOMODE;
|
|
||||||
}
|
|
||||||
|
|
||||||
UART0->UARTCR =
|
switch (parity) {
|
||||||
UART_UARTCR_RXE_BITS | UART_UARTCR_TXE_BITS | UART_UARTCR_UARTEN_BITS;
|
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) {
|
void uart_write(uart_t uart, const uint8_t *data, size_t len) {
|
||||||
for (size_t i = 0; i < len; i++) {
|
(void)uart;
|
||||||
UART0->UARTDR = data[i];
|
for (size_t i = 0; i < len; i++) {
|
||||||
// Wait until the TX FIFO is empty before sending the next byte
|
UART0->UARTDR = data[i];
|
||||||
while (!(UART0->UARTFR & UART_UARTFR_TXFE_BITS));
|
/* 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_poweron(uart_t uart) {
|
||||||
void uart_poweroff(uart_t uart) {}
|
(void)uart;
|
||||||
|
}
|
||||||
|
void uart_poweroff(uart_t uart) {
|
||||||
|
(void)uart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|||||||
@ -1,28 +1,34 @@
|
|||||||
// Picobin block required for the binary
|
/*
|
||||||
// This defines the minimum viable image metadata to be recognized by the RP2350 bootloader
|
* SPDX-FileCopyrightText: 2025 Tom Hert <git@annsann.eu>
|
||||||
// based on RP2350 Chapter 5.9.1
|
* 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
|
.word 0xffffded3
|
||||||
// ITEM 0 START based on 5.9.3.1
|
/* ITEM 0 START based on 5.9.3.1 */
|
||||||
.byte 0x42 // (size_flag == 0, item_type == PICOBIN_BLOCK_ITEM_1BS_IMAGE_TYPE)
|
.byte 0x42 /* (size_flag == 0, item_type == PICOBIN_BLOCK_ITEM_1BS_IMAGE_TYPE) */
|
||||||
.byte 0x1 // Block Size in words
|
.byte 0x1 /* Block Size in words */
|
||||||
// image_type_flags (2 bytes) [See 5.9.3.1 / p419]
|
/* image_type_flags (2 bytes) [See 5.9.3.1 / p419] */
|
||||||
// 15 -> 0 (1 for "Try before you buy" image [Wacky]
|
/* 15 -> 0 (1 for "Try before you buy" image [Wacky] */
|
||||||
// 12-14 -> 001 (RP2350 = 1)
|
/* 12-14 -> 001 (RP2350 = 1) */
|
||||||
// 11 -> 0 (Reserved)
|
/* 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)
|
/* 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)
|
/* 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
|
/* 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
|
/* 0-3 // 0001 IMAGE_TYPE_EXE */
|
||||||
.hword 0b0001000000100001
|
.hword 0b0001000000100001
|
||||||
// ITEM 0 END see 5.1.5.1 for explanation and 5.9.5.1 for the value / structure
|
/* 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
|
.byte 0xff /* PICOBIN_BLOCK_ITEM_2BS_LAST */
|
||||||
.hword 0x0001 // Size of the item in words (predefined value)
|
.hword 0x0001 /* Size of the item in words (predefined value) */
|
||||||
.byte 0x00 // Padding
|
.byte 0x00 /* Padding */
|
||||||
// Next Block Pointer
|
/* Next Block Pointer */
|
||||||
.word 0x00000000 // Next block pointer (0 means no more blocks)
|
.word 0x00000000 /* Next block pointer (0 means no more blocks) */
|
||||||
// PICOBIN_BLOCK_MARKER_END
|
/* PICOBIN_BLOCK_MARKER_END */
|
||||||
.word 0xab123579 // Marker for the end of the picobin block
|
.word 0xab123579 /* Marker for the end of the picobin block */
|
||||||
|
|||||||
@ -1,33 +1,26 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2021 Ishraq Ibne Ashraf
|
* SPDX-FileCopyrightText: 2025 Tom Hert <git@annsann.eu>
|
||||||
*
|
* SPDX-FileCopyrightText: 2025 HAW Hamburg
|
||||||
*
|
* SPDX-License-Identifier: LGPL-2.1-only
|
||||||
* This file is subject to the terms and conditions of the GNU Lesser
|
|
||||||
* General Public License v2.1. See the file LICENSE in the top level
|
|
||||||
* directory for more details.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup cpu_ro2040
|
* @ingroup cpu_rp2350
|
||||||
* @{
|
* @{
|
||||||
*
|
*
|
||||||
* @file vectors.c
|
* @file
|
||||||
* @brief Startup code and interrupt vector definition
|
* @brief Interrupt vector table for the RP2350
|
||||||
*
|
*
|
||||||
* @author Ishraq Ibne Ashraf <ishraq.i.ashraf@gmail.com>
|
* @author Tom Hert <git@annsann.eu>
|
||||||
*
|
|
||||||
* @}
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "RP2350.h"
|
||||||
#include "cpu_conf.h"
|
#include "cpu_conf.h"
|
||||||
#include "vectors_cortexm.h"
|
#include "vectors_cortexm.h"
|
||||||
#include "RP2350.h"
|
|
||||||
|
|
||||||
/* define a local dummy handler as it needs to be in the same compilation unit
|
/* define a local dummy handler as it needs to be in the same compilation unit
|
||||||
* as the alias definition */
|
* as the alias definition */
|
||||||
void dummy_handler(void) {
|
void dummy_handler(void) { dummy_handler_default(); }
|
||||||
dummy_handler_default();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* rp2350 specific interrupt vector */
|
/* rp2350 specific interrupt vector */
|
||||||
WEAK_DEFAULT void isr_timer0_0(void);
|
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);
|
WEAK_DEFAULT void isr_spareirq_5(void);
|
||||||
|
|
||||||
/* CPU specific interrupt vector table */
|
/* CPU specific interrupt vector table */
|
||||||
ISR_VECTOR(1) const isr_t vector_cpu[CPU_IRQ_NUMOF] = {
|
ISR_VECTOR(1)
|
||||||
(void*) isr_timer0_0, /* 0 TIMER0_IRQ_0 */
|
const isr_t vector_cpu[CPU_IRQ_NUMOF] = {
|
||||||
(void*) isr_timer0_1, /* 1 TIMER0_IRQ_1 */
|
(void*)isr_timer0_0, /* 0 TIMER0_IRQ_0 */
|
||||||
(void*) isr_timer0_2, /* 2 TIMER0_IRQ_2 */
|
(void*)isr_timer0_1, /* 1 TIMER0_IRQ_1 */
|
||||||
(void*) isr_timer0_3, /* 3 TIMER0_IRQ_3 */
|
(void*)isr_timer0_2, /* 2 TIMER0_IRQ_2 */
|
||||||
(void*) isr_timer1_0, /* 4 TIMER1_IRQ_0 */
|
(void*)isr_timer0_3, /* 3 TIMER0_IRQ_3 */
|
||||||
(void*) isr_timer1_1, /* 5 TIMER1_IRQ_1 */
|
(void*)isr_timer1_0, /* 4 TIMER1_IRQ_0 */
|
||||||
(void*) isr_timer1_2, /* 6 TIMER1_IRQ_2 */
|
(void*)isr_timer1_1, /* 5 TIMER1_IRQ_1 */
|
||||||
(void*) isr_timer1_3, /* 7 TIMER1_IRQ_3 */
|
(void*)isr_timer1_2, /* 6 TIMER1_IRQ_2 */
|
||||||
(void*) isr_pwm_wrap_0, /* 8 PWM_IRQ_WRAP_0 */
|
(void*)isr_timer1_3, /* 7 TIMER1_IRQ_3 */
|
||||||
(void*) isr_pwm_wrap_1, /* 9 PWM_IRQ_WRAP_1 */
|
(void*)isr_pwm_wrap_0, /* 8 PWM_IRQ_WRAP_0 */
|
||||||
(void*) isr_dma_0, /* 10 DMA_IRQ_0 */
|
(void*)isr_pwm_wrap_1, /* 9 PWM_IRQ_WRAP_1 */
|
||||||
(void*) isr_dma_1, /* 11 DMA_IRQ_1 */
|
(void*)isr_dma_0, /* 10 DMA_IRQ_0 */
|
||||||
(void*) isr_dma_2, /* 12 DMA_IRQ_2 */
|
(void*)isr_dma_1, /* 11 DMA_IRQ_1 */
|
||||||
(void*) isr_dma_3, /* 13 DMA_IRQ_3 */
|
(void*)isr_dma_2, /* 12 DMA_IRQ_2 */
|
||||||
(void*) isr_usbctrl, /* 14 USBCTRL_IRQ */
|
(void*)isr_dma_3, /* 13 DMA_IRQ_3 */
|
||||||
(void*) isr_pio0_0, /* 15 PIO0_IRQ_0 */
|
(void*)isr_usbctrl, /* 14 USBCTRL_IRQ */
|
||||||
(void*) isr_pio0_1, /* 16 PIO0_IRQ_1 */
|
(void*)isr_pio0_0, /* 15 PIO0_IRQ_0 */
|
||||||
(void*) isr_pio1_0, /* 17 PIO1_IRQ_0 */
|
(void*)isr_pio0_1, /* 16 PIO0_IRQ_1 */
|
||||||
(void*) isr_pio1_1, /* 18 PIO1_IRQ_1 */
|
(void*)isr_pio1_0, /* 17 PIO1_IRQ_0 */
|
||||||
(void*) isr_pio2_0, /* 19 PIO2_IRQ_0 */
|
(void*)isr_pio1_1, /* 18 PIO1_IRQ_1 */
|
||||||
(void*) isr_pio2_1, /* 20 PIO2_IRQ_1 */
|
(void*)isr_pio2_0, /* 19 PIO2_IRQ_0 */
|
||||||
(void*) isr_io_bank0, /* 21 IO_IRQ_BANK0 */
|
(void*)isr_pio2_1, /* 20 PIO2_IRQ_1 */
|
||||||
(void*) isr_io_bank0_ns, /* 22 IO_IRQ_BANK0_NS */
|
(void*)isr_io_bank0, /* 21 IO_IRQ_BANK0 */
|
||||||
(void*) isr_io_qspi, /* 23 IO_IRQ_QSPI */
|
(void*)isr_io_bank0_ns, /* 22 IO_IRQ_BANK0_NS */
|
||||||
(void*) isr_io_qspi_ns, /* 24 IO_IRQ_QSPI_NS */
|
(void*)isr_io_qspi, /* 23 IO_IRQ_QSPI */
|
||||||
(void*) isr_sio_fifo, /* 25 SIO_IRQ_FIFO */
|
(void*)isr_io_qspi_ns, /* 24 IO_IRQ_QSPI_NS */
|
||||||
(void*) isr_sio_bell, /* 26 SIO_IRQ_BELL */
|
(void*)isr_sio_fifo, /* 25 SIO_IRQ_FIFO */
|
||||||
(void*) isr_sio_fifo_ns, /* 27 SIO_IRQ_FIFO_NS */
|
(void*)isr_sio_bell, /* 26 SIO_IRQ_BELL */
|
||||||
(void*) isr_sio_bell_ns, /* 28 SIO_IRQ_BELL_NS */
|
(void*)isr_sio_fifo_ns, /* 27 SIO_IRQ_FIFO_NS */
|
||||||
(void*) isr_sio_mtimecmp, /* 29 SIO_IRQ_MTIMECMP */
|
(void*)isr_sio_bell_ns, /* 28 SIO_IRQ_BELL_NS */
|
||||||
(void*) isr_clocks, /* 30 CLOCKS_IRQ */
|
(void*)isr_sio_mtimecmp, /* 29 SIO_IRQ_MTIMECMP */
|
||||||
(void*) isr_spi0, /* 31 SPI0_IRQ */
|
(void*)isr_clocks, /* 30 CLOCKS_IRQ */
|
||||||
(void*) isr_spi1, /* 32 SPI1_IRQ */
|
(void*)isr_spi0, /* 31 SPI0_IRQ */
|
||||||
(void*) isr_uart0, /* 33 UART0_IRQ */
|
(void*)isr_spi1, /* 32 SPI1_IRQ */
|
||||||
(void*) isr_uart1, /* 34 UART1_IRQ */
|
(void*)isr_uart0, /* 33 UART0_IRQ */
|
||||||
(void*) isr_adc_fifo, /* 35 ADC_IRQ_FIFO */
|
(void*)isr_uart1, /* 34 UART1_IRQ */
|
||||||
(void*) isr_i2c0, /* 36 I2C0_IRQ */
|
(void*)isr_adc_fifo, /* 35 ADC_IRQ_FIFO */
|
||||||
(void*) isr_i2c1, /* 37 I2C1_IRQ */
|
(void*)isr_i2c0, /* 36 I2C0_IRQ */
|
||||||
(void*) isr_otp, /* 38 OTP_IRQ */
|
(void*)isr_i2c1, /* 37 I2C1_IRQ */
|
||||||
(void*) isr_trng, /* 39 TRNG_IRQ */
|
(void*)isr_otp, /* 38 OTP_IRQ */
|
||||||
(void*) isr_proc0_cti, /* 40 PROC0_IRQ_CTI */
|
(void*)isr_trng, /* 39 TRNG_IRQ */
|
||||||
(void*) isr_proc1_cti, /* 41 PROC1_IRQ_CTI */
|
(void*)isr_proc0_cti, /* 40 PROC0_IRQ_CTI */
|
||||||
(void*) isr_pll_sys, /* 42 PLL_SYS_IRQ */
|
(void*)isr_proc1_cti, /* 41 PROC1_IRQ_CTI */
|
||||||
(void*) isr_pll_usb, /* 43 PLL_USB_IRQ */
|
(void*)isr_pll_sys, /* 42 PLL_SYS_IRQ */
|
||||||
(void*) isr_powman_pow, /* 44 POWMAN_IRQ_POW */
|
(void*)isr_pll_usb, /* 43 PLL_USB_IRQ */
|
||||||
(void*) isr_powman_timer, /* 45 POWMAN_IRQ_TIMER */
|
(void*)isr_powman_pow, /* 44 POWMAN_IRQ_POW */
|
||||||
(void*) isr_spareirq_0, /* 46 SPAREIRQ_IRQ_0 */
|
(void*)isr_powman_timer, /* 45 POWMAN_IRQ_TIMER */
|
||||||
(void*) isr_spareirq_1, /* 47 SPAREIRQ_IRQ_1 */
|
(void*)isr_spareirq_0, /* 46 SPAREIRQ_IRQ_0 */
|
||||||
(void*) isr_spareirq_2, /* 48 SPAREIRQ_IRQ_2 */
|
(void*)isr_spareirq_1, /* 47 SPAREIRQ_IRQ_1 */
|
||||||
(void*) isr_spareirq_3, /* 49 SPAREIRQ_IRQ_3 */
|
(void*)isr_spareirq_2, /* 48 SPAREIRQ_IRQ_2 */
|
||||||
(void*) isr_spareirq_4, /* 50 SPAREIRQ_IRQ_4 */
|
(void*)isr_spareirq_3, /* 49 SPAREIRQ_IRQ_3 */
|
||||||
(void*) isr_spareirq_5, /* 51 SPAREIRQ_IRQ_5 */
|
(void*)isr_spareirq_4, /* 50 SPAREIRQ_IRQ_4 */
|
||||||
|
(void*)isr_spareirq_5, /* 51 SPAREIRQ_IRQ_5 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|||||||
@ -1,22 +1,17 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2021 Otto-von-Guericke Universität Magdeburg
|
* SPDX-FileCopyrightText: 2025 Tom Hert <git@annsann.eu>
|
||||||
*
|
* SPDX-FileCopyrightText: 2025 HAW Hamburg
|
||||||
* This file is subject to the terms and conditions of the GNU Lesser
|
* SPDX-License-Identifier: LGPL-2.1-only
|
||||||
* General Public License v2.1. See the file LICENSE in the top level
|
|
||||||
* directory for more details.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup cpu_rpx0xx
|
* @ingroup cpu_rp2350
|
||||||
* @{
|
* @{
|
||||||
*
|
*
|
||||||
* @file
|
* @file
|
||||||
* @brief Implementation of the crystal oscillator (XOSC)
|
* @brief XOSC implementation for the RP2350
|
||||||
*
|
*
|
||||||
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
|
* @author Tom Hert <git@annsann.eu>
|
||||||
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
|
|
||||||
*
|
|
||||||
* @}
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@ -26,33 +21,35 @@
|
|||||||
#include "macros/units.h"
|
#include "macros/units.h"
|
||||||
#include "periph_cpu.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 STARTUP_DELAY 47
|
||||||
#define MAX_XOSC_COUNTER_SIZE 0xFFFF
|
#define MAX_XOSC_COUNTER_SIZE 0xFFFF
|
||||||
#define Sleep100HzSpeed 60000
|
#define SLEEP_100HZ_SPEED 12000000UL
|
||||||
#define CYCLES_PER_MS (Sleep100HzSpeed / 1000)
|
#define CYCLES_PER_MS (SLEEP_100HZ_SPEED / 1000)
|
||||||
|
|
||||||
void xosc_start(void) {
|
void xosc_start(void) {
|
||||||
// Set the FREQ_RANGE
|
/* Set the FREQ_RANGE */
|
||||||
XOSC->CTRL = XOSC_CTRL_FREQ_RANGE_VALUE_1_15MHZ;
|
XOSC->CTRL = XOSC_CTRL_FREQ_RANGE_VALUE_1_15MHZ;
|
||||||
// Set the startup delay (default 1ms)
|
/* Set the startup delay (default 1ms) */
|
||||||
XOSC->STARTUP = STARTUP_DELAY;
|
XOSC->STARTUP = STARTUP_DELAY;
|
||||||
// set enable bit
|
/* set enable bit */
|
||||||
atomic_set(&XOSC->CTRL, XOSC_CTRL_ENABLE_VALUE_ENABLE << XOSC_CTRL_ENABLE_LSB);
|
atomic_set(&XOSC->CTRL,
|
||||||
|
XOSC_CTRL_ENABLE_VALUE_ENABLE << XOSC_CTRL_ENABLE_LSB);
|
||||||
|
|
||||||
while (!(XOSC->STATUS & XOSC_STATUS_STABLE_BITS)) {
|
while (!(XOSC->STATUS & XOSC_STATUS_STABLE_BITS)) {
|
||||||
// Wait for the crystal to stabilize
|
/* Wait for the crystal to stabilize */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void xosc_sleep(int32_t milliseconds) {
|
void xosc_sleep(uint32_t milliseconds) {
|
||||||
for (int32_t i = 0; i < milliseconds; i++) {
|
for (uint32_t i = milliseconds; i > 0; i--) {
|
||||||
XOSC->COUNT = CYCLES_PER_MS* milliseconds;
|
XOSC->COUNT = CYCLES_PER_MS;
|
||||||
while (XOSC->COUNT != 0) {
|
while (XOSC->COUNT != 0) {};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void xosc_stop(void) {
|
void xosc_stop(void) {
|
||||||
// @TODO
|
/* @TODO */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|||||||
@ -85,8 +85,8 @@ FEATURES_EXISTING := \
|
|||||||
cpu_nrf53 \
|
cpu_nrf53 \
|
||||||
cpu_nrf9160 \
|
cpu_nrf9160 \
|
||||||
cpu_qn908x \
|
cpu_qn908x \
|
||||||
cpu_rpx0xx \
|
|
||||||
cpu_rp2350 \
|
cpu_rp2350 \
|
||||||
|
cpu_rpx0xx \
|
||||||
cpu_sam3 \
|
cpu_sam3 \
|
||||||
cpu_sam4s \
|
cpu_sam4s \
|
||||||
cpu_samd21 \
|
cpu_samd21 \
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user