1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

cpu/rpx0xx: add support for the RP2040 MCU

Co-authored-by: Fabian Hüßler <fabian.huessler@st.ovgu.de>
This commit is contained in:
Marian Buschsieweke 2021-06-01 21:31:30 +02:00
parent c52da5745f
commit ea56dfc3ff
No known key found for this signature in database
GPG Key ID: 61F64C6599B1539F
48 changed files with 35689 additions and 0 deletions

33
cpu/rpx0xx/Kconfig Normal file
View File

@ -0,0 +1,33 @@
# 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.
#
config CPU_FAM_RPX0XX
bool
select CPU_CORE_CORTEX_M0PLUS
select HAS_CPU_RPX0XX
select HAS_PERIPH_GPIO
select HAS_PERIPH_GPIO_IRQ
config CPU_FAM
default "RPX0XX" if CPU_FAM_RPX0XX
config CPU_MODEL_RP2040
bool
select CPU_FAM_RPX0XX
config CPU_MODEL
default "RP2040" if CPU_MODEL_RP2040
config CPU
default "rpx0xx" if CPU_FAM_RPX0XX
config HAS_CPU_RPX0XX
bool
help
Indicates that a RPX0XX CPU (e.g. the RP2040) is used
source "$(RIOTCPU)/cortexm_common/Kconfig"

5
cpu/rpx0xx/Makefile Normal file
View File

@ -0,0 +1,5 @@
MODULE = cpu
DIRS = $(RIOTCPU)/cortexm_common periph
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1 @@
DEFAULT_MODULE += stdio_null

1
cpu/rpx0xx/Makefile.dep Normal file
View File

@ -0,0 +1 @@
include $(RIOTCPU)/cortexm_common/Makefile.dep

View File

@ -0,0 +1,7 @@
CPU_CORE := cortex-m0plus
CPU_FAM := RPX0XX
include $(RIOTCPU)/cortexm_common/Makefile.features
FEATURES_PROVIDED += periph_gpio
FEATURES_PROVIDED += periph_gpio_irq

View File

@ -0,0 +1,21 @@
PICO_DEBUG ?=
ROM_LEN ?= 2097152 # = 2 MiB used in the RPi Pico
ROM_OFFSET := 256 # bootloader size
RAM_LEN := 270336 # = 264 KiB
ROM_START_ADDR := 0x10000000
RAM_START_ADDR := 0x20000000
CFLAGS += -D$(CPU_MODEL)
CFLAGS += -DROM_START_ADDR=$(ROM_START_ADDR)
CFLAGS += -DRAM_START_ADDR=$(RAM_START_ADDR)
INCLUDES += -I$(RIOTCPU)/rpx0xx/include
VECTORS_O ?= $(BINDIR)/cpu/vectors.o
VECTORS_FILE := $(RIOTCPU)/rpx0xx/vectors.c
PROGRAMMERS_SUPPORTED := uf2conv openocd jlink
PROGRAMMER ?= openocd
OPENOCD_DEBUG_ADAPTER ?= dap
include $(RIOTMAKE)/arch/cortexm.inc.mk

View File

@ -0,0 +1,23 @@
// Padded and checksummed version of: boot2_w25q080.bin
.cpu cortex-m0plus
.thumb
.section .boot2, "ax"
.byte 0x00, 0xb5, 0x32, 0x4b, 0x21, 0x20, 0x58, 0x60, 0x98, 0x68, 0x02, 0x21, 0x88, 0x43, 0x98, 0x60
.byte 0xd8, 0x60, 0x18, 0x61, 0x58, 0x61, 0x2e, 0x4b, 0x00, 0x21, 0x99, 0x60, 0x02, 0x21, 0x59, 0x61
.byte 0x01, 0x21, 0xf0, 0x22, 0x99, 0x50, 0x2b, 0x49, 0x19, 0x60, 0x01, 0x21, 0x99, 0x60, 0x35, 0x20
.byte 0x00, 0xf0, 0x44, 0xf8, 0x02, 0x22, 0x90, 0x42, 0x14, 0xd0, 0x06, 0x21, 0x19, 0x66, 0x00, 0xf0
.byte 0x34, 0xf8, 0x19, 0x6e, 0x01, 0x21, 0x19, 0x66, 0x00, 0x20, 0x18, 0x66, 0x1a, 0x66, 0x00, 0xf0
.byte 0x2c, 0xf8, 0x19, 0x6e, 0x19, 0x6e, 0x19, 0x6e, 0x05, 0x20, 0x00, 0xf0, 0x2f, 0xf8, 0x01, 0x21
.byte 0x08, 0x42, 0xf9, 0xd1, 0x00, 0x21, 0x99, 0x60, 0x1b, 0x49, 0x19, 0x60, 0x00, 0x21, 0x59, 0x60
.byte 0x1a, 0x49, 0x1b, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0xeb, 0x21, 0x19, 0x66, 0xa0, 0x21
.byte 0x19, 0x66, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0x21, 0x99, 0x60, 0x16, 0x49, 0x14, 0x48, 0x01, 0x60
.byte 0x01, 0x21, 0x99, 0x60, 0x01, 0xbc, 0x00, 0x28, 0x00, 0xd0, 0x00, 0x47, 0x12, 0x48, 0x13, 0x49
.byte 0x08, 0x60, 0x03, 0xc8, 0x80, 0xf3, 0x08, 0x88, 0x08, 0x47, 0x03, 0xb5, 0x99, 0x6a, 0x04, 0x20
.byte 0x01, 0x42, 0xfb, 0xd0, 0x01, 0x20, 0x01, 0x42, 0xf8, 0xd1, 0x03, 0xbd, 0x02, 0xb5, 0x18, 0x66
.byte 0x18, 0x66, 0xff, 0xf7, 0xf2, 0xff, 0x18, 0x6e, 0x18, 0x6e, 0x02, 0xbd, 0x00, 0x00, 0x02, 0x40
.byte 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x5f, 0x00, 0x21, 0x22, 0x00, 0x00
.byte 0xf4, 0x00, 0x00, 0x18, 0x22, 0x20, 0x00, 0xa0, 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0xb2, 0x4e, 0x7a

179
cpu/rpx0xx/clock.c Normal file
View File

@ -0,0 +1,179 @@
/*
* 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.
*/
/**
* @ingroup cpu_rpx0xx
* @{
*
* @file
* @brief Implementation of the CPU clock configuration
*
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
*
* @}
*/
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include "vendor/RP2040.h"
#include "vendor/system_RP2040.h"
#include "io_reg.h"
#include "periph_cpu.h"
static void _clk_sys_set_source(CLOCKS_CLK_SYS_CTRL_SRC_Enum source)
{
io_reg_write_dont_corrupt(&CLOCKS->CLK_SYS_CTRL.reg, source << CLOCKS_CLK_SYS_CTRL_SRC_Pos,
CLOCKS_CLK_SYS_CTRL_SRC_Msk);
}
static void _clk_sys_set_aux_source(CLOCKS_CLK_SYS_CTRL_AUXSRC_Enum source)
{
io_reg_write_dont_corrupt(&CLOCKS->CLK_SYS_CTRL.reg, source << CLOCKS_CLK_SYS_CTRL_AUXSRC_Pos,
CLOCKS_CLK_SYS_CTRL_AUXSRC_Msk);
}
static void _clk_ref_set_source(CLOCKS_CLK_REF_CTRL_SRC_Enum source)
{
io_reg_write_dont_corrupt(&CLOCKS->CLK_REF_CTRL.reg, source << CLOCKS_CLK_REF_CTRL_SRC_Pos,
CLOCKS_CLK_REF_CTRL_SRC_Msk);
}
static void _clk_ref_set_aux_source(CLOCKS_CLK_REF_CTRL_AUXSRC_Enum source)
{
io_reg_write_dont_corrupt(&CLOCKS->CLK_REF_CTRL.reg, source << CLOCKS_CLK_REF_CTRL_AUXSRC_Pos,
CLOCKS_CLK_REF_CTRL_AUXSRC_Msk);
}
static void _gpout_set_aux_source(volatile uint32_t *reg, uint32_t value)
{
io_reg_write_dont_corrupt(reg,
value << CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_Pos,
CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_Msk);
}
void clock_sys_configure_source(uint32_t f_in, uint32_t f_out, CLOCKS_CLK_SYS_CTRL_SRC_Enum source)
{
assert(f_out <= f_in);
assert(source != CLOCKS_CLK_SYS_CTRL_SRC_clksrc_clk_sys_aux);
uint32_t div = (((uint64_t)f_in) << CLOCKS_CLK_SYS_DIV_INT_Pos) / f_out;
/* switch the glitchless mux to clk_ref */
_clk_sys_set_source(source);
/* apply divider */
CLOCKS->CLK_SYS_DIV.reg = div;
/* poll SELECTED until the switch is completed */
while (!(CLOCKS->CLK_SYS_SELECTED & (1U << source))) { }
}
void clock_sys_configure_aux_source(uint32_t f_in, uint32_t f_out,
CLOCKS_CLK_SYS_CTRL_AUXSRC_Enum aux)
{
assert(f_out <= f_in);
uint32_t div = (((uint64_t)f_in) << CLOCKS_CLK_SYS_DIV_INT_Pos) / f_out;
/* switch the glitchless mux to a source that is not the aux mux */
_clk_sys_set_source(CLOCKS_CLK_SYS_CTRL_SRC_clk_ref);
/* poll SELECTED until the switch is completed */
while (!(CLOCKS->CLK_SYS_SELECTED & (1U << CLOCKS_CLK_SYS_CTRL_SRC_clk_ref))) { }
/* change the auxiliary mux */
_clk_sys_set_aux_source(aux);
/* apply divider */
CLOCKS->CLK_SYS_DIV.reg = div;
/* switch the glitchless mux to clk_sys_aux */
_clk_sys_set_source(CLOCKS_CLK_SYS_CTRL_SRC_clksrc_clk_sys_aux);
/* poll SELECTED until the switch is completed */
while (!(CLOCKS->CLK_SYS_SELECTED & (1U << CLOCKS_CLK_SYS_CTRL_SRC_clksrc_clk_sys_aux))) { }
}
void clock_ref_configure_source(uint32_t f_in, uint32_t f_out, CLOCKS_CLK_REF_CTRL_SRC_Enum source)
{
assert(f_out <= f_in);
assert(source != CLOCKS_CLK_REF_CTRL_SRC_clksrc_clk_ref_aux);
uint32_t div = (((uint64_t)f_in) << CLOCKS_CLK_REF_DIV_INT_Pos) / f_out;
/* switch the glitchless mux to clock source */
_clk_ref_set_source(source);
/* apply divider */
CLOCKS->CLK_REF_DIV.reg = div & CLOCKS_CLK_REF_DIV_INT_Msk;
/* poll SELECTED until the switch is completed */
while (!(CLOCKS->CLK_REF_SELECTED & (1U << source))) { }
}
void clock_ref_configure_aux_source(uint32_t f_in, uint32_t f_out,
CLOCKS_CLK_REF_CTRL_AUXSRC_Enum aux)
{
assert(f_out <= f_in);
uint32_t div = (((uint64_t)f_in) << CLOCKS_CLK_REF_DIV_INT_Pos) / f_out;
/* switch the glitchless mux to a source that is not the aux mux */
_clk_ref_set_source(CLOCKS_CLK_REF_CTRL_SRC_rosc_clksrc_ph);
/* poll SELECTED until the switch is completed */
while (!(CLOCKS->CLK_REF_SELECTED & (1U << CLOCKS_CLK_REF_CTRL_SRC_rosc_clksrc_ph))) { }
/* change the auxiliary mux */
_clk_ref_set_aux_source(aux);
/* apply divider */
CLOCKS->CLK_REF_DIV.reg = div & CLOCKS_CLK_REF_DIV_INT_Msk;
/* switch the glitchless mux to clk_ref_aux */
_clk_ref_set_source(CLOCKS_CLK_REF_CTRL_SRC_clksrc_clk_ref_aux);
/* poll SELECTED until the switch is completed */
while (!(CLOCKS->CLK_REF_SELECTED & (1U << CLOCKS_CLK_REF_CTRL_SRC_clksrc_clk_ref_aux))) { }
}
void clock_periph_configure(CLOCKS_CLK_PERI_CTRL_AUXSRC_Enum aux)
{
io_reg_atomic_clear(&CLOCKS->CLK_PERI_CTRL.reg, (1u << CLOCKS_CLK_PERI_CTRL_ENABLE_Pos));
io_reg_write_dont_corrupt(&CLOCKS->CLK_PERI_CTRL.reg, aux << CLOCKS_CLK_PERI_CTRL_AUXSRC_Pos,
CLOCKS_CLK_PERI_CTRL_AUXSRC_Msk);
io_reg_atomic_set(&CLOCKS->CLK_PERI_CTRL.reg, (1u << CLOCKS_CLK_PERI_CTRL_ENABLE_Pos));
}
void clock_gpout0_configure(uint32_t f_in, uint32_t f_out, CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_Enum aux)
{
assert(f_out <= f_in);
uint32_t div = (((uint64_t)f_in) << CLOCKS_CLK_REF_DIV_INT_Pos) / f_out;
io_reg_atomic_clear(&CLOCKS->CLK_GPOUT0_CTRL.reg, 1U << CLOCKS_CLK_GPOUT0_CTRL_ENABLE_Pos);
_gpout_set_aux_source(&CLOCKS->CLK_GPOUT0_CTRL.reg, aux);
CLOCKS->CLK_GPOUT0_DIV.reg = div;
io_reg_atomic_set(&CLOCKS->CLK_GPOUT0_CTRL.reg, 1U << CLOCKS_CLK_GPOUT0_CTRL_ENABLE_Pos);
io_reg_atomic_set(&PADS_BANK0->GPIO21.reg, 1U << PADS_BANK0_GPIO21_IE_Pos);
gpio_set_function_select(21, FUNCTION_SELECT_CLOCK);
}
void clock_gpout1_configure(uint32_t f_in, uint32_t f_out, CLOCKS_CLK_GPOUT1_CTRL_AUXSRC_Enum aux)
{
assert(f_out <= f_in);
uint32_t div = (((uint64_t)f_in) << CLOCKS_CLK_REF_DIV_INT_Pos) / f_out;
io_reg_atomic_clear(&CLOCKS->CLK_GPOUT1_CTRL.reg, 1U << CLOCKS_CLK_GPOUT1_CTRL_ENABLE_Pos);
_gpout_set_aux_source(&CLOCKS->CLK_GPOUT1_CTRL.reg, aux);
CLOCKS->CLK_GPOUT1_DIV.reg = div;
io_reg_atomic_set(&CLOCKS->CLK_GPOUT1_CTRL.reg, 1U << CLOCKS_CLK_GPOUT1_CTRL_ENABLE_Pos);
io_reg_atomic_set(&PADS_BANK0->GPIO23.reg, 1U << PADS_BANK0_GPIO23_IE_Pos);
gpio_set_function_select(23, FUNCTION_SELECT_CLOCK);
}
void clock_gpout2_configure(uint32_t f_in, uint32_t f_out, CLOCKS_CLK_GPOUT2_CTRL_AUXSRC_Enum aux)
{
assert(f_out <= f_in);
uint32_t div = (((uint64_t)f_in) << CLOCKS_CLK_REF_DIV_INT_Pos) / f_out;
io_reg_atomic_clear(&CLOCKS->CLK_GPOUT2_CTRL.reg, 1U << CLOCKS_CLK_GPOUT2_CTRL_ENABLE_Pos);
_gpout_set_aux_source(&CLOCKS->CLK_GPOUT2_CTRL.reg, aux);
CLOCKS->CLK_GPOUT2_DIV.reg = div;
io_reg_atomic_set(&CLOCKS->CLK_GPOUT2_CTRL.reg, 1U << CLOCKS_CLK_GPOUT2_CTRL_ENABLE_Pos);
io_reg_atomic_set(&PADS_BANK0->GPIO24.reg, 1U << PADS_BANK0_GPIO24_IE_Pos);
gpio_set_function_select(24, FUNCTION_SELECT_CLOCK);
}
void clock_gpout3_configure(uint32_t f_in, uint32_t f_out, CLOCKS_CLK_GPOUT3_CTRL_AUXSRC_Enum aux)
{
assert(f_out <= f_in);
uint32_t div = (((uint64_t)f_in) << CLOCKS_CLK_REF_DIV_INT_Pos) / f_out;
io_reg_atomic_clear(&CLOCKS->CLK_GPOUT3_CTRL.reg, 1U << CLOCKS_CLK_GPOUT3_CTRL_ENABLE_Pos);
_gpout_set_aux_source(&CLOCKS->CLK_GPOUT3_CTRL.reg, aux);
CLOCKS->CLK_GPOUT3_DIV.reg = div;
io_reg_atomic_set(&CLOCKS->CLK_GPOUT3_CTRL.reg, 1U << CLOCKS_CLK_GPOUT3_CTRL_ENABLE_Pos);
io_reg_atomic_set(&PADS_BANK0->GPIO25.reg, 1U << PADS_BANK0_GPIO25_IE_Pos);
gpio_set_function_select(25, FUNCTION_SELECT_CLOCK);
}

96
cpu/rpx0xx/cpu.c Normal file
View File

@ -0,0 +1,96 @@
/*
* 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.
*/
/**
* @ingroup cpu_rpx0xx
* @{
*
* @file
* @brief Implementation of the CPU initialization
*
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
*
* @}
*/
#include "cpu.h"
#include "macros/units.h"
#include "periph/init.h"
#include "periph_cpu.h"
#include "io_reg.h"
#include "stdio_base.h"
#include "vendor/RP2040.h"
#define ENABLE_DEBUG 0
#include "debug.h"
static void _cpu_reset(void)
{
/* 2.14 subsystem resets */
uint32_t rst;
/* Reset hardware components except for critical ones */
rst = RESETS_RESET_MASK
& ~(RESETS_RESET_usbctrl_Msk
| RESETS_RESET_syscfg_Msk
| RESETS_RESET_pll_usb_Msk
| RESETS_RESET_pll_sys_Msk
| RESETS_RESET_pads_qspi_Msk
| RESETS_RESET_io_qspi_Msk);
periph_reset(rst);
/* Assert that reset has completed except for those components which
are not clocked by clk_ref or clk_sys */
rst = RESETS_RESET_MASK
& ~(RESETS_RESET_usbctrl_Msk
| RESETS_RESET_uart1_Msk
| RESETS_RESET_uart0_Msk
| RESETS_RESET_spi1_Msk
| RESETS_RESET_spi0_Msk
| RESETS_RESET_rtc_Msk
| RESETS_RESET_adc_Msk);
periph_reset_done(rst);
/* power the reference clock from its default source: the ROSC */
clock_ref_configure_source(MHZ(12), MHZ(12), CLOCKS_CLK_REF_CTRL_SRC_rosc_clksrc_ph);
/* power the system clock from its default source: the reference clock */
clock_sys_configure_source(MHZ(12), MHZ(12), CLOCKS_CLK_SYS_CTRL_SRC_clk_ref);
/* start XOSC, typically running at 12 MHz */
xosc_start(CLOCK_XOSC);
/* reset system PLL */
pll_reset_sys();
/* start the system PLL (typically takes the 12 MHz XOSC to generate 125 MHz) */
pll_start_sys(PLL_SYS_REF_DIV, PLL_SYS_VCO_FEEDBACK_SCALE, PLL_SYS_POSTDIV1, PLL_SYS_POSTDIV2);
/* configure reference clock to run from XOSC (typically 12 MHz) */
clock_ref_configure_source(CLOCK_XOSC, CLOCK_XOSC,
CLOCKS_CLK_REF_CTRL_SRC_xosc_clksrc);
/* configure system clock output */
clock_sys_configure_aux_source(CLOCK_CORECLOCK, CLOCK_CORECLOCK,
CLOCKS_CLK_SYS_CTRL_AUXSRC_clksrc_pll_sys);
/* configure the peripheral clock to run from the system clock */
clock_periph_configure(CLOCK_PERIPH_SOURCE);
if (IS_USED(ENABLE_DEBUG)) {
/* check clk_ref with logic analyzer */
clock_gpout0_configure(CLOCK_XOSC, CLOCK_XOSC,
CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_clk_ref);
}
}
void cpu_init(void)
{
/* initialize the Cortex-M core */
cortexm_init();
_cpu_reset();
/* initialize stdio prior to periph_init() to allow use of DEBUG() there */
stdio_init();
DEBUG_PUTS("[rpx0xx] GPOUT0 (GPIO pin 21) is clocked from XOSC (typically 12 MHz)");
/* trigger static peripheral initialization */
periph_init();
}

9
cpu/rpx0xx/doc.txt Normal file
View File

@ -0,0 +1,9 @@
/**
@defgroup cpu_rpx0xx RPx0xx MCUs
@ingroup cpu
@brief RPx0xx MCU code and definitions
This module contains the code and definitions for MCUs of the RPx0xx family, of which only the
RP2040 is currently released.
*/

1
cpu/rpx0xx/include/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
irqs/

View File

@ -0,0 +1,47 @@
/*
* 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.
*/
/**
* @ingroup cpu_rpx0xx
* @{
*
* @file
* @brief Implementation specific CPU configuration options
*
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
*/
#ifndef CPU_CONF_H
#define CPU_CONF_H
#include <stdint.h>
#include "macros/units.h"
#include "cpu_conf_common.h"
#include "vendor/RP2040.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief ARM Cortex-M specific CPU configuration
* @{
*/
#define CPU_DEFAULT_IRQ_PRIO (1U)
#define CPU_FLASH_BASE ROM_START_ADDR
#define CPU_IRQ_NUMOF (32U)
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* CPU_CONF_H */
/** @} */

138
cpu/rpx0xx/include/io_reg.h Normal file
View File

@ -0,0 +1,138 @@
/*
* 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.
*/
/**
* @ingroup cpu_rpx0xx
* @{
*
* @file
* @brief RP2040 atomic register access macros
* @details This allows individual fields of a control register to be
* modified without performing a read-modify-write sequence.
* See section "2.1.2. Atomic Register Access" in
* https://datasheets.raspberrypi.org/rpx0xx/rpx0xx-datasheet.pdf
*
* @warning The Single-cycle IO block (SIO), which contains the GPIO, does not support
* atomic access using these aliases.
*
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
*/
#ifndef IO_REG_H
#define IO_REG_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Bit to be set if an atomic XOR operation shall be done
*/
#define REG_ATOMIC_XOR_BIT (0x1000U)
/**
* @brief Bit to be set if an atomic set operation shall be done
*/
#define REG_ATOMIC_SET_BIT (0x2000U)
/**
* @brief Bits to be set if an atomic clear operation shall be done
*/
#define REG_ATOMIC_CLEAR_BIT (0x3000U)
/**
* @brief The operation to be performed to the register at address @p reg
* will be an atomic XOR of the bits of the right-hand-side operand
*/
#define REG_ATOMIC_XOR(reg) ((volatile uint32_t *)(((uintptr_t)(reg)) | REG_ATOMIC_XOR_BIT))
/**
* @brief The operation to be performed to the register at address @p reg
* will be an atomic set of the bits of the right-hand-side operand
*/
#define REG_ATOMIC_SET(reg) ((volatile uint32_t *)(((uintptr_t)(reg)) | REG_ATOMIC_SET_BIT))
/**
* @brief The operation to be performed to the register at address @p reg
* will be an atomic clear of the bits of the right-hand-side operand
*/
#define REG_ATOMIC_CLEAR(reg) ((volatile uint32_t *)(((uintptr_t)(reg)) | REG_ATOMIC_CLEAR_BIT))
/**
* @brief Performed an atomic XOR of the set bits in @p op
* with the bits in the register at address @p reg
*
* @param reg Register address
* @param mask Mask of bits to be XORed
*/
static inline void io_reg_atomic_xor(volatile uint32_t *reg, uint32_t mask)
{
*REG_ATOMIC_XOR(reg) = mask;
}
/**
* @brief Set the bits in the register at address @p reg as given by
* the set bits in operand @p op
*
* @param reg Register address
* @param mask Mask of bits to be set
*/
static inline void io_reg_atomic_set(volatile uint32_t *reg, uint32_t mask)
{
*REG_ATOMIC_SET(reg) = mask;
}
/**
* @brief Clear the bits in the register at address @p reg as given by
* the set bits in operand @p op
*
* @param reg Register address
* @param mask Mask of bits to be cleared
*/
static inline void io_reg_atomic_clear(volatile uint32_t *reg, uint32_t mask)
{
*REG_ATOMIC_CLEAR(reg) = mask;
}
/**
* @brief Updates part of an I/O register without corrupting its contents
*
* @param reg Register address
* @param value bits to set in the register (e.g. the new value shifted to the right position)
* @param mask bits to clear in the register (e.g. bitmask indicating the part to update with
* one bits, and everything else with zero bits)
*
* @details The RP2040 only correctly implements 32 bit writes to I/O register. When
* updating parts of an I/O register using the structs in the CMSIS header, the
* C compiler might implement those updates e.g. using 8-bit writes, especially
* when the part to update is 8-bit in size and byte-aligned. The RP2040 will then
* sneakily corrupt the I/O register, rather than triggering a hard fault. This
* hard to debug silent corruption issue is *NOT* a bug, but an intentional
* feature, obviously.
* @pre `value & (~mask) == 0`
*
* Example use:
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
* io_reg_write_dont_corrupt(&CLOCKS->CLK_SYS_CTRL.reg, source << CLOCKS_CLK_SYS_CTRL_SRC_Pos,
* CLOCKS_CLK_SYS_CTRL_SRC_Msk);
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
static inline void io_reg_write_dont_corrupt(volatile uint32_t *reg, uint32_t value, uint32_t mask)
{
*reg = (*reg & (~mask)) | value;
}
#ifdef __cplusplus
}
#endif
#endif /* IO_REG_H */
/** @} */

View File

@ -0,0 +1,689 @@
/*
* 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.
*/
/**
* @ingroup cpu_rpx0xx
* @{
*
* @file
* @brief RP2040 specific definitions for handling peripherals
*
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
*/
#ifndef PERIPH_CPU_H
#define PERIPH_CPU_H
#include "cpu.h"
#include "vendor/RP2040.h"
#include "io_reg.h"
#include "macros/units.h"
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(PLL_SYS_REF_DIV) || defined(DOXYGEN)
/**
* @brief For generating the system clock via PLL, the XOSC reference clock can be divided. The
* datasheet says for the supported frequency range of the crystal, only a divider of 1 is
* reasonable.
*/
#define PLL_SYS_REF_DIV 1
#endif
#if !defined(PLL_USB_REF_DIV) || defined(DOXYGEN)
/**
* @brief Same as @ref PLL_SYS_REF_DIV but for the PLL generating the USB clock
*/
#define PLL_USB_REF_DIV 1
#endif
#if !defined(PLL_SYS_VCO_FEEDBACK_SCALE) || defined(DOXYGEN)
/**
* @brief VCO feedback scale used for system clock
*
* @note The result of `PLL_SYS_VCO_FEEDBACK_SCALE * CLOCK_XOSC` must be in the range of
* 400 MHz to 1600 MHz
*/
#define PLL_SYS_VCO_FEEDBACK_SCALE 125
#endif
#if !defined(PLL_SYS_POSTDIV1) || defined(DOXYGEN)
/**
* @brief First post-PLL clock divider for system clock
*
* @note Must be in rage 1..7
*/
#define PLL_SYS_POSTDIV1 6
#endif
#if !defined(PLL_SYS_POSTDIV2) || defined(DOXYGEN)
/**
* @brief Second post-PLL clock divider for system clock
*
* @note Must be in rage 1..7
*/
#define PLL_SYS_POSTDIV2 2
#endif
#if !defined(PLL_USB_VCO_FEEDBACK_SCALE) || defined(DOXYGEN)
/**
* @brief VCO feedback scale used for USB clock
*
* @note The result of `PLL_USB_VCO_FEEDBACK_SCALE * CLOCK_XOSC` must be in the range of
* 400 MHz to 1600 MHz
*/
#define PLL_USB_VCO_FEEDBACK_SCALE 40
#endif
#if !defined(PLL_USB_POSTDIV1) || defined(DOXYGEN)
/**
* @brief First post-PLL clock divider for USB clock
*
* @note Must be in rage 1..7
*/
#define PLL_USB_POSTDIV1 5
#endif
#if !defined(PLL_USB_POSTDIV2) || defined(DOXYGEN)
/**
* @brief Second post-PLL clock divider for USB clock
*
* @note Must be in rage 1..7
*/
#define PLL_USB_POSTDIV2 2
#endif
#if !defined(CLOCK_XOSC) || defined(DOXYGEN)
/**
* @brief The RP2040 reference design attaches a 12 MHz crystal to the MCU, so we take this
* value as default
*/
#define CLOCK_XOSC MHZ(12)
#endif
/**
* @brief Calculate the resulting PLL clock frequency for the given parameters
*/
#define PLL_CLOCK(vco_feedback, postdiv1, postdiv2) \
(CLOCK_XOSC * (vco_feedback) / (postdiv1) / (postdiv2))
/**
* @brief System core clock speed, 125 MHz unless board changes parameters
*/
#define CLOCK_CORECLOCK \
PLL_CLOCK(PLL_SYS_VCO_FEEDBACK_SCALE, PLL_SYS_POSTDIV1, PLL_SYS_POSTDIV2)
/**
* @brief USB clock speed
*/
#define CLOCK_USB \
PLL_CLOCK(PLL_USB_VCO_FEEDBACK_SCALE, PLL_USB_POSTDIV1, PLL_USB_POSTDIV2)
/**
* @name Ranges for clock frequencies and clock settings
* @{
*/
#define CLOCK_XOSC_MAX MHZ(15) /**< Maximum crystal frequency */
#define CLOCK_XOSC_MIN MHZ(5) /**< Minimum 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 */
/** @} */
#if CLOCK_USB != MHZ(48)
#error "USB clock != 48 MHz, check PLL_USB_VCO_FEEDBACK_SCALE, PLL_USB_POSTDIV1, PLL_SYS_POSTDIV2"
#endif
#if (CLOCK_XOSC > CLOCK_XOSC_MAX) || (CLOCK_XOSC < CLOCK_XOSC_MIN)
#error "Value for CLOCK_XOSC out of range, check config"
#endif
#if (PLL_SYS_REF_DIV < PLL_REF_DIV_MIN) || (PLL_SYS_REF_DIV > PLL_REF_DIV_MAX)
#error "Value for PLL_SYS_REF_DIV out of range, check config"
#endif
#if (PLL_USB_REF_DIV < PLL_REF_DIV_MIN) || (PLL_USB_REF_DIV > PLL_REF_DIV_MAX)
#error "Value for PLL_USB_REF_DIV out of range, check config"
#endif
#if (PLL_SYS_VCO_FEEDBACK_SCALE < PLL_VCO_FEEDBACK_SCALE_MIN) \
|| (PLL_SYS_VCO_FEEDBACK_SCALE > PLL_VCO_FEEDBACK_SCALE_MAX)
#error "Value for PLL_SYS_VCO_FEEDBACK_SCALE out of range, check config"
#endif
#if (PLL_USB_VCO_FEEDBACK_SCALE < PLL_VCO_FEEDBACK_SCALE_MIN) \
|| (PLL_USB_VCO_FEEDBACK_SCALE > PLL_VCO_FEEDBACK_SCALE_MAX)
#error "Value for PLL_USB_VCO_FEEDBACK_SCALE out of range, check config"
#endif
#if (PLL_SYS_POSTDIV1 < PLL_POSTDIV_MIN) || (PLL_SYS_POSTDIV1 > PLL_POSTDIV_MAX)
#error "Value for PLL_SYS_POSTDIV1 out of range, check config"
#endif
#if (PLL_SYS_POSTDIV2 < PLL_POSTDIV_MIN) || (PLL_SYS_POSTDIV2 > PLL_POSTDIV_MAX)
#error "Value for PLL_SYS_POSTDIV2 out of range, check config"
#endif
#if (PLL_USB_POSTDIV1 < PLL_POSTDIV_MIN) || (PLL_USB_POSTDIV1 > PLL_POSTDIV_MAX)
#error "Value for PLL_USB_POSTDIV1 out of range, check config"
#endif
#if (PLL_USB_POSTDIV2 < PLL_POSTDIV_MIN) || (PLL_USB_POSTDIV2 > PLL_POSTDIV_MAX)
#error "Value for PLL_USB_POSTDIV2 out of range, check config"
#endif
#if !defined(CLOCK_PERIPH_SOURCE) || defined(DOXYGEN)
/**
* @brief How to source the peripheral clock (default: 125 MHz system clock)
*/
#define CLOCK_PERIPH_SOURCE CLOCKS_CLK_PERI_CTRL_AUXSRC_clk_sys
#endif
#if !defined(CLOCK_PERIPH) || defined(DOXYGEN)
/**
* @brief Peripheral clock (by default source from system clock)
*/
#define CLOCK_PERIPH CLOCK_CORECLOCK
#endif
/**
* @brief Periphery blocks that can be reset
*/
#define RESETS_RESET_MASK \
(RESETS_RESET_usbctrl_Msk | \
RESETS_RESET_uart1_Msk | \
RESETS_RESET_uart0_Msk | \
RESETS_RESET_timer_Msk | \
RESETS_RESET_tbman_Msk | \
RESETS_RESET_sysinfo_Msk | \
RESETS_RESET_syscfg_Msk | \
RESETS_RESET_spi1_Msk | \
RESETS_RESET_spi0_Msk | \
RESETS_RESET_rtc_Msk | \
RESETS_RESET_pwm_Msk | \
RESETS_RESET_pll_usb_Msk | \
RESETS_RESET_pll_sys_Msk | \
RESETS_RESET_pio1_Msk | \
RESETS_RESET_pio0_Msk | \
RESETS_RESET_pads_qspi_Msk | \
RESETS_RESET_pads_bank0_Msk | \
RESETS_RESET_jtag_Msk | \
RESETS_RESET_io_qspi_Msk | \
RESETS_RESET_io_bank0_Msk | \
RESETS_RESET_i2c1_Msk | \
RESETS_RESET_i2c0_Msk | \
RESETS_RESET_dma_Msk | \
RESETS_RESET_busctrl_Msk | \
RESETS_RESET_adc_Msk)
/**
* @brief Convert (port, pin) tuple to a @ref gpio_t value
*
* @note The RPX0XX MCU family only has a single GPIO port. Still the API requires a
* port parameter, which is currently ignored.
*/
#define GPIO_PIN(port, pin) (pin)
/**
* @brief Overwrite the default gpio_t type definition
* @{
*/
#define HAVE_GPIO_T
typedef uint32_t gpio_t;
/** @} */
/**
* @brief Definition of a fitting UNDEF value
*/
#define GPIO_UNDEF UINT32_MAX
/**
* @brief Override GPIO active flank values
* @{
*/
#define HAVE_GPIO_FLANK_T
typedef enum {
GPIO_LEVEL_LOW = 0x1, /**< emit interrupt level-triggered on low input */
GPIO_LEVEL_HIGH = 0x2, /**< emit interrupt level-triggered on low input */
GPIO_FALLING = 0x4, /**< emit interrupt on falling flank */
GPIO_RISING = 0x8, /**< emit interrupt on rising flank */
GPIO_BOTH = 0xc /**< emit interrupt on both flanks */
} gpio_flank_t;
/** @} */
/**
* @name GPIO pad configuration register defines and types
* @{
*/
/**
* @brief Reset value of the GPIO pad configuration register
*/
#define GPIO_PAD_REGISTER_RESET_VALUE (0x00000056)
/**
* @brief Possible drive strength values for @ref gpio_pad_ctrl_t::drive_strength
*/
enum {
DRIVE_STRENGTH_2MA, /**< set driver strength to 2 mA */
DRIVE_STRENGTH_4MA, /**< set driver strength to 4 mA */
DRIVE_STRENGTH_8MA, /**< set driver strength to 8 mA */
DRIVE_STRENGTH_12MA, /**< set driver strength to 12 mA */
DRIVE_STRENGTH_NUMOF /**< number of different drive strength options */
};
/**
* @brief Memory layout of GPIO control register in pads bank 0
*/
typedef struct {
uint32_t slew_rate_fast : 1; /**< set slew rate control to fast */
uint32_t schmitt_trig_enable : 1; /**< enable Schmitt trigger */
uint32_t pull_down_enable : 1; /**< enable pull down resistor */
uint32_t pull_up_enable : 1; /**< enable pull up resistor */
uint32_t drive_strength : 2; /**< GPIO driver strength */
uint32_t input_enable : 1; /**< enable as input */
uint32_t output_disable : 1; /**< disable output, overwrite output enable from
* peripherals */
uint32_t : 24; /**< 24 bits reserved for future use */
} gpio_pad_ctrl_t;
/** @} */
/**
* @name GPIO I/O configuration register defines and types
* @{
*/
/**
* @brief Reset value of the GPIO I/O configuration register
*/
#define GPIO_IO_REGISTER_RESET_VALUE (0x0000001f)
/**
* @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 */
} gpio_function_select_t;
/**
* @brief Possible function values for @ref gpio_io_ctrl_t::output_override
*/
enum {
OUTPUT_OVERRIDE_NORMAL, /**< drive pin from connected peripheral */
OUTPUT_OVERRIDE_INVERT, /**< drive pin from connected peripheral, but invert output */
OUTPUT_OVERRIDE_LOW, /**< drive pin low, overriding peripheral signal */
OUTPUT_OVERRIDE_HIGH, /**< drive pin high, overriding peripheral signal */
OUTPUT_OVERRIDE_NUMOF /**< number of possible output override settings */
};
/**
* @brief Possible function values for @ref gpio_io_ctrl_t::output_enable_override
*/
enum {
OUTPUT_ENABLE_OVERRIDE_NOMARL, /**< enable output as specified by connected peripheral */
OUTPUT_ENABLE_OVERRIDE_INVERT, /**< invert output enable setting of peripheral */
OUTPUT_ENABLE_OVERRIDE_DISABLE, /**< disable output, overriding peripheral signal */
OUTPUT_ENABLE_OVERRIDE_ENABLE, /**< enable output, overriding peripheral signal */
OUTPUT_ENABLE_OVERRIDE_NUMOF /**< number of possible output enable override settings */
};
/**
* @brief Possible function values for @ref gpio_io_ctrl_t::input_override
*/
enum {
INPUT_OVERRIDE_NOMARL, /**< don't mess with peripheral input signal */
INPUT_OVERRIDE_INVERT, /**< invert signal to connected peripheral */
INPUT_OVERRIDE_LOW, /**< signal low to connected peripheral */
INPUT_OVERRIDE_HIGH, /**< signal high to connected peripheral */
INPUT_OVERRIDE_NUMOF /**< number of possible input override settings */
};
/**
* @brief Possible function values for @ref gpio_io_ctrl_t::irq_override
*/
enum {
IRQ_OVERRIDE_NORMAL, /**< don't mess with IRQ signal */
IRQ_OVERRIDE_INVERT, /**< invert IRQ signal */
IRQ_OVERRIDE_LOW, /**< set IRQ signal to low */
IRQ_OVERRIDE_HIGH, /**< set IRQ signal to high */
IRQ_OVERRIDE_NUMOF /**< number of possible IRQ override settings */
};
/**
* @brief Memory layout of GPIO control register in IO bank 0
*/
typedef struct {
uint32_t function_select : 5; /**< select GPIO function */
uint32_t : 3; /**< 3 bits reserved for future use */
uint32_t output_override : 2; /**< output value override */
uint32_t : 2; /**< 2 bits reserved for future use */
uint32_t output_enable_override : 2; /**< output enable override */
uint32_t : 2; /**< 2 bits reserved for future use */
uint32_t input_override : 2; /**< input value override */
uint32_t : 10; /**< 10 bits reserved for future use */
uint32_t irq_override : 2; /**< interrupt inversion override */
uint32_t : 2; /**< 2 bits reserved for future use */
} gpio_io_ctrl_t;
/** @} */
/**
* @brief Get the PAD control register for the given GPIO pin as word
*
* Note: Only perform 32-bit writes to I/O registers.
*/
static inline volatile uint32_t * gpio_pad_register(uint8_t pin)
{
return (uint32_t *)(PADS_BANK0_BASE + 4 + (pin << 2));
}
/**
* @brief Convenience function to set the pad configuration of the given pin
* using the bit-field convenience type
*/
static inline void gpio_set_pad_config(uint8_t pin, gpio_pad_ctrl_t config)
{
*(volatile gpio_pad_ctrl_t*)gpio_pad_register(pin) = config;
}
/**
* @brief Get the IO control register for the given GPIO pin as word
*/
static inline volatile uint32_t * gpio_io_register(uint8_t pin)
{
return (uint32_t *)(IO_BANK0_BASE + 4 + (pin << 3));
}
/**
* @brief Convenience function to set the I/O configuration of the given pin
* using the bit-field convenience type
*/
static inline void gpio_set_io_config(uint8_t pin, gpio_io_ctrl_t config)
{
*(volatile gpio_io_ctrl_t*)gpio_io_register(pin) = config;
}
/**
* @brief Set the function select subregister for the given pin to the given value
*/
static inline void gpio_set_function_select(uint8_t pin, gpio_function_select_t funcsel)
{
io_reg_write_dont_corrupt(gpio_io_register(pin), funcsel << IO_BANK0_GPIO0_CTRL_FUNCSEL_Pos,
IO_BANK0_GPIO0_CTRL_FUNCSEL_Msk);
}
/**
* @brief Restore the default I/O and PAD configuration of the given GPIO pin
*/
static inline void gpio_reset_all_config(uint8_t pin)
{
*gpio_io_register(pin) = GPIO_IO_REGISTER_RESET_VALUE;
*gpio_pad_register(pin) = GPIO_PAD_REGISTER_RESET_VALUE;
}
/**
* @brief Reset hardware components
*
* @param components bitmask of components to be reset,
* @see RESETS_RESET_MASK
*/
static inline void periph_reset(uint32_t components)
{
io_reg_atomic_set(&RESETS->RESET.reg, components);
}
/**
* @brief Waits until hardware components have been reset
*
* @param components bitmask of components that must have reset,
* @see RESETS_RESET_MASK
*/
static inline void periph_reset_done(uint32_t components)
{
io_reg_atomic_clear(&RESETS->RESET.reg, components);
while ((~RESETS->RESET_DONE.reg) & components) { }
}
/**
* @name RP2040 clock configuration
* @{
*/
/**
* @brief Configure the system clock to run from the reference clock,
* which is the default on boot
*
* @param f_in Input frequency of the reference clock
* @param f_out Output frequency of the system clock
* @param source Clock source
*/
void clock_sys_configure_source(uint32_t f_in, uint32_t f_out,
CLOCKS_CLK_SYS_CTRL_SRC_Enum source);
/**
* @brief Configure the system clock to run from an auxiliary clock source,
* like PLL
*
* @note The auxiliary must have been configured beforehand
*
* @param f_in Input frequency of the auxiliary clock source
* @param f_out Output frequency of the system clock
* @param aux Which auxiliary clock source to use
*/
void clock_sys_configure_aux_source(uint32_t f_in, uint32_t f_out,
CLOCKS_CLK_SYS_CTRL_AUXSRC_Enum aux);
/**
* @brief Configure the reference clock to run from a clock source,
* which is either the ROSC or the XOSC
*
* @note Make sure that ROSC or XOSC are properly set up
*
* @param f_in Input frequency of the reference clock
* @param f_out Output frequency of the system clock
* @param source Clock source
*/
void clock_ref_configure_source(uint32_t f_in, uint32_t f_out,
CLOCKS_CLK_REF_CTRL_SRC_Enum source);
/**
* @brief Configure the reference clock to run from an auxiliary clock source,
* like PLL
*
* @note The auxiliary must have been configured beforehand
*
* @param f_in Input frequency of the auxiliary clock source
* @param f_out Output frequency of the reference clock
* @param aux Which auxiliary clock source to use
*/
void clock_ref_configure_aux_source(uint32_t f_in, uint32_t f_out,
CLOCKS_CLK_REF_CTRL_AUXSRC_Enum aux);
/**
* @brief Configure the peripheral clock to run from a dedicated auxiliary
* clock source
*
* @param aux Auxiliary clock source
*/
void clock_periph_configure(CLOCKS_CLK_PERI_CTRL_AUXSRC_Enum aux);
/**
* @brief Configure gpio21 as clock output pin
*
* @details Can be used as an external clock source for another circuit or
* to check the expected signal with a logic analyzer
*
* @param f_in Input frequency
* @param f_out Output frequency
* @param aux Auxiliary clock source
*/
void clock_gpout0_configure(uint32_t f_in, uint32_t f_out, CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_Enum aux);
/**
* @brief Configure gpio23 as clock output pin
*
* @details Can be used as an external clock source for another circuit or
* to check the expected signal with a logic analyzer
*
* @param f_in Input frequency
* @param f_out Output frequency
* @param aux Auxiliary clock source
*/
void clock_gpout1_configure(uint32_t f_in, uint32_t f_out, CLOCKS_CLK_GPOUT1_CTRL_AUXSRC_Enum aux);
/**
* @brief Configure gpio24 as clock output pin
*
* @details Can be used as an external clock source for another circuit or
* to check the expected signal with a logic analyzer
*
* @param f_in Input frequency
* @param f_out Output frequency
* @param aux Auxiliary clock source
*/
void clock_gpout2_configure(uint32_t f_in, uint32_t f_out, CLOCKS_CLK_GPOUT2_CTRL_AUXSRC_Enum aux);
/**
* @brief Configure gpio25 as clock output pin
*
* @details Can be used as an external clock source for another circuit or
* to check the expected signal with a logic analyzer
*
* @param f_in Input frequency
* @param f_out Output frequency
* @param aux Auxiliary clock source
*/
void clock_gpout3_configure(uint32_t f_in, uint32_t f_out, CLOCKS_CLK_GPOUT3_CTRL_AUXSRC_Enum aux);
/** @} */
/**
* @name RP2040 PLL configuration
* @{
*/
/**
* @brief Start the PLL for the system clock
* output[MHz] = f_ref / @p ref_div * @p vco_feedback_scale / @p post_div_1 / @p post_div_2
*
* @note Usual setting should be (12 MHz, 1, 125, 6, 2) to get a 125 MHz system clock signal
*
* @param ref_div Input clock divisor
* @param vco_feedback_scale VCO feedback scales
* @param post_div_1 Output post divider factor 1
* @param post_div_2 Output post divider factor 2
*/
void pll_start_sys(uint8_t ref_div,
uint16_t vco_feedback_scale,
uint8_t post_div_1, uint8_t post_div_2);
/**
* @brief Start the PLL for the system clock
* output[MHz] = f_ref / @p ref_div * @p vco_feedback_scale / @p post_div_1 / @p post_div_2
*
* @note Usual setting should be (12 MHz, 1, 40, 5, 2) to get a 48 MHz USB clock signal
*
* @param ref_div Input clock divisor
* @param vco_feedback_scale VCO feedback scales
* @param post_div_1 Output post divider factor 1
* @param post_div_2 Output post divider factor 2
*/
void pll_start_usb(uint8_t ref_div,
uint16_t vco_feedback_scale,
uint8_t post_div_1, uint8_t post_div_2);
/**
* @brief Stop the PLL of the system clock
*/
void pll_stop_sys(void);
/**
* @brief Stop the PLL of the USB clock
*/
void pll_stop_usb(void);
/**
* @brief Reset the PLL of the system clock
*/
void pll_reset_sys(void);
/**
* @brief Reset the PLL of the USB clock
*/
void pll_reset_usb(void);
/** @} */
/**
* @name RP2040 XOSC configuration
* @{
*/
/**
* @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.
*/
void xosc_start(uint32_t f_ref);
/**
* @brief Stop the crystal.
*/
void xosc_stop(void);
/** @} */
/**
* @name RP2040 ROSC configuration
* @{
*/
/**
* @brief Start the ring oscillator in default mode.
*
* The ROSC is running at boot time but may be turned off to save power when switching to the
* accurate XOSC. The default ROSC provides an instable frequency of 1.8 MHz to 12 MHz.
*/
void rosc_start(void);
/**
* @brief Turn off the ROSC to save power.
* The system clock must be switched to to another lock source
* before the ROSC is stopped, other wise the chip will be lock up.
*/
void rosc_stop(void);
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* PERIPH_CPU_H */
/** @} */

29410
cpu/rpx0xx/include/vendor/RP2040.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,67 @@
/*************************************************************************//**
* @file system_RP2040.h
* @brief CMSIS-Core(M) Device Peripheral Access Layer Header File for
* Device RP2040
* @version V1.0.0
* @date 5. May 2021
*****************************************************************************/
/*
* Copyright (c) 2009-2021 Arm Limited. All rights reserved.
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _CMSIS_SYSTEM_RP2040_H
#define _CMSIS_SYSTEM_RP2040_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
/**
\brief Exception / Interrupt Handler Function Prototype
*/
typedef void(*VECTOR_TABLE_Type)(void);
/**
\brief System Clock Frequency (Core Clock)
*/
extern uint32_t SystemCoreClock;
/**
\brief Setup the microcontroller system.
Initialize the System and update the SystemCoreClock variable.
*/
extern void SystemInit (void);
/**
\brief Update SystemCoreClock variable.
Updates the SystemCoreClock with current core Clock retrieved from cpu registers.
*/
extern void SystemCoreClockUpdate (void);
#ifdef __cplusplus
}
#endif
#endif /* _CMSIS_SYSTEM_RP2040_H */

View File

@ -0,0 +1,46 @@
/*
* 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.
*/
/**
* @ingroup cpu_rp2040
* @{
*
* @file
* @brief Memory definitions for the RP2040 MCU
*
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
*
* @}
*/
INCLUDE cortexm.ld
MEMORY
{
boot_loader (rx) : ORIGIN = 0x10000000, LENGTH = 0x100
}
SECTIONS {
.boot_loader :
{
__boot_loader_start__ = .;
KEEP(*(.boot2));
__boot_loader_end__ = .;
KEEP(*(.boot2));
} > boot_loader
ASSERT(__boot_loader_end__ - __boot_loader_start__ == 256,
"ERROR: RP2040 second stage bootloader must be 256 bytes in size")
/* Reserve 16 KiB of RAM for virtual CMSIS-DAP on-chip debugging adapter
* running on the second core */
.pico-debug 0x2003C000:
{
. = . + 16K;
} > ram
}

View File

@ -0,0 +1 @@
include $(RIOTMAKE)/periph.mk

235
cpu/rpx0xx/periph/gpio.c Normal file
View File

@ -0,0 +1,235 @@
/*
* 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.
*/
/**
* @ingroup cpu_rpx0xx
* @ingroup drivers_periph_gpio
* @{
*
* @file
* @brief GPIO driver implementation for the RP2040
*
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
*
* @}
*/
#include <errno.h>
#include "bitarithm.h"
#include "board.h"
#include "irq.h"
#include "periph/gpio.h"
#include "periph_conf.h"
#include "periph_cpu.h"
#include "io_reg.h"
#define ENABLE_DEBUG 0
#include "debug.h"
#define GPIO_PIN_NUMOF 30U
#ifdef MODULE_PERIPH_GPIO_IRQ
static gpio_cb_t _cbs[GPIO_PIN_NUMOF];
static void *_args[GPIO_PIN_NUMOF];
#endif /* MODULE_PERIPH_GPIO_IRQ */
int gpio_init(gpio_t pin, gpio_mode_t mode)
{
assert(pin < GPIO_PIN_NUMOF);
SIO->GPIO_OE_CLR.reg = 1LU << pin;
SIO->GPIO_OUT_CLR.reg = 1LU << pin;
switch (mode) {
case GPIO_IN:
{
gpio_pad_ctrl_t pad_config = {
.input_enable = 1,
.schmitt_trig_enable = 1
};
gpio_io_ctrl_t io_config = {
.function_select = FUNCTION_SELECT_SIO,
};
gpio_set_pad_config(pin, pad_config);
gpio_set_io_config(pin, io_config);
}
break;
case GPIO_IN_PD:
{
gpio_pad_ctrl_t pad_config = {
.pull_down_enable = 1,
.input_enable = 1,
.schmitt_trig_enable = 1
};
gpio_io_ctrl_t io_config = {
.function_select = FUNCTION_SELECT_SIO,
};
gpio_set_pad_config(pin, pad_config);
gpio_set_io_config(pin, io_config);
}
break;
case GPIO_IN_PU:
{
gpio_pad_ctrl_t pad_config = {
.pull_up_enable = 1,
.input_enable = 1,
.schmitt_trig_enable = 1
};
gpio_io_ctrl_t io_config = {
.function_select = FUNCTION_SELECT_SIO,
};
gpio_set_pad_config(pin, pad_config);
gpio_set_io_config(pin, io_config);
}
break;
case GPIO_OUT:
{
gpio_pad_ctrl_t pad_config = {
.drive_strength = DRIVE_STRENGTH_12MA,
};
gpio_io_ctrl_t io_config = {
.function_select = FUNCTION_SELECT_SIO,
};
gpio_set_pad_config(pin, pad_config);
gpio_set_io_config(pin, io_config);
}
SIO->GPIO_OE_SET.reg = 1LU << pin;
break;
default:
return -ENOTSUP;
}
return 0;
}
int gpio_read(gpio_t pin)
{
if (SIO->GPIO_OE.reg & (1LU << pin)) {
/* pin is output: */
return SIO->GPIO_OUT.reg & (1LU << pin);
}
/* pin is input: */
return SIO->GPIO_IN.reg & (1LU << pin);
}
void gpio_set(gpio_t pin)
{
SIO->GPIO_OUT_SET.reg = 1LU << pin;
}
void gpio_clear(gpio_t pin)
{
SIO->GPIO_OUT_CLR.reg = 1LU << pin;
}
void gpio_toggle(gpio_t pin)
{
SIO->GPIO_OUT_XOR.reg = 1LU << pin;
}
void gpio_write(gpio_t pin, int value)
{
if (value) {
gpio_set(pin);
}
else {
gpio_clear(pin);
}
}
#ifdef MODULE_PERIPH_GPIO_IRQ
static void _irq_enable(gpio_t pin, unsigned flank)
{
volatile uint32_t *irq_enable_regs = &IO_BANK0->PROC0_INTE0.reg;
volatile uint32_t *irq_ack_regs = &IO_BANK0->INTR0.reg;
/* There are 4 bits to control IRQs per pin, hence the configuration is split across multiple
* I/O registers. The following calculates the position the four bits matching the given pin,
* where idx refers to the I/O register and shift_amount to the position in the I/O register.
*/
unsigned shift_amount = (pin & 0x7) << 2;
unsigned idx = pin >> 3;
/* make access atomic by disabling IRQs */
unsigned irq_state = irq_disable();
uint32_t value = irq_enable_regs[idx];
/* clear any stray IRQs */
io_reg_atomic_clear(&irq_ack_regs[idx], 0xFLU << shift_amount);
/* first, clear previous setting */
value &= ~(0xFLU << shift_amount);
/* then, apply new setting */
value |= flank << shift_amount;
irq_enable_regs[idx] = value;
irq_restore(irq_state);
NVIC_EnableIRQ(IO_IRQ_BANK0_IRQn);
}
void gpio_irq_enable(gpio_t pin)
{
io_reg_atomic_clear(gpio_io_register(pin), IO_BANK0_GPIO1_CTRL_IRQOVER_Msk);
}
void gpio_irq_disable(gpio_t pin)
{
/* Beware: The two-bit IRQOVER value needs to be set to 0b10 == IRQ_OVERRIDE_LOW. This
* implementation will set IRQOVER only to either 0b00 == IRQ_OVERRIDE_NORMAL or
* 0b10 == IRQ_OVERRIDE_LOW. If we just set the most significant bit, this will result in
* IRQOVER set to IRQ_OVERRIDE_LOW.
*
* IRQOVER must not be set by user code for this to work, though.
*/
io_reg_atomic_set(gpio_io_register(pin), IRQ_OVERRIDE_LOW << IO_BANK0_GPIO1_CTRL_IRQOVER_Pos);
}
int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, gpio_cb_t cb, void *arg)
{
assert(pin < GPIO_PIN_NUMOF);
int retval = gpio_init(pin, mode);
if (retval) {
return retval;
}
_cbs[pin] = cb;
_args[pin] = arg;
_irq_enable(pin, flank);
return 0;
}
void isr_io_bank0(void)
{
unsigned offset = 0;
volatile uint32_t *irq_status_regs = &IO_BANK0->PROC0_INTS0.reg;
volatile uint32_t *irq_ack_regs = &IO_BANK0->INTR0.reg;
DEBUG("[rp0x00] GPIO IRQ mask: %08x, %08x, %08x, %08x\n",
(unsigned)IO_BANK0->PROC0_INTE0.reg, (unsigned)IO_BANK0->PROC0_INTE1.reg,
(unsigned)IO_BANK0->PROC0_INTE2.reg, (unsigned)IO_BANK0->PROC0_INTE3.reg);
DEBUG("[rp0x00] GPIO IRQ status: %08x, %08x, %08x, %08x\n",
(unsigned)IO_BANK0->PROC0_INTS0.reg, (unsigned)IO_BANK0->PROC0_INTS1.reg,
(unsigned)IO_BANK0->PROC0_INTS2.reg, (unsigned)IO_BANK0->PROC0_INTS3.reg);
/* There are four IRQ status bits per pin, so there is info for 8 pins per I/O register.
* We will iterate over all IRQ status I/O registers in the outer loop, and over all 8 pins
* per register in the inner loop */
for (unsigned i = 0; i < (GPIO_PIN_NUMOF + 7) / 8; i++, offset += 8) {
unsigned status = irq_status_regs[i];
irq_ack_regs[i] = status;
for (unsigned pin = 0; pin < 8; pin++) {
/* Note: Not use bitarithm_test_and_clear() here, since two bits for a single pin could
* be set. This happens if both rising and falling flank (1 bit used to track each) have
* occurred until the ISR started to handle the first IRQ.
*/
if (status & (0xFLU << (pin << 2))) {
if (_cbs[pin + offset]) {
_cbs[pin + offset](_args[pin + offset]);
}
}
}
}
cortexm_isr_end();
}
#endif /* MODULE_PERIPH_GPIO_IRQ */

118
cpu/rpx0xx/pll.c Normal file
View File

@ -0,0 +1,118 @@
/*
* 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.
*/
/**
* @ingroup cpu_rpx0xx
* @{
*
* @file
* @brief Implementation of the phase locked loop (PLL)
* to drive the ROSC or XOSC to a higher frequency
*
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
*
* @}
*/
#include <assert.h>
#include "macros/units.h"
#include "periph_cpu.h"
#include "vendor/RP2040.h"
#include "io_reg.h"
/**
* @brief Start the PLL for the system clock (@p pll = PLL_SYS) or
* the USB clock (@p pll = PLL_USB)
*/
static void _pll_start(PLL_SYS_Type *pll, uint8_t ref_div,
uint16_t vco_feedback_scale,
uint8_t post_div_1, uint8_t post_div_2)
{
assert(PLL_REF_DIV_MIN <= ref_div);
assert(ref_div <= PLL_REF_DIV_MAX);
assert(PLL_VCO_FEEDBACK_SCALE_MIN <= vco_feedback_scale);
assert(vco_feedback_scale <= PLL_VCO_FEEDBACK_SCALE_MAX);
assert(PLL_POSTDIV_MIN <= post_div_1);
assert(post_div_1 <= PLL_POSTDIV_MAX);
assert(PLL_POSTDIV_MIN <= post_div_2);
assert(post_div_2 <= PLL_POSTDIV_MAX);
/* program reference clock divider */
io_reg_write_dont_corrupt(&pll->CS.reg, ref_div << PLL_SYS_CS_REFDIV_Pos,
PLL_SYS_CS_REFDIV_Msk);
/* program feedback divider */
io_reg_write_dont_corrupt(&pll->FBDIV_INT.reg,
vco_feedback_scale << PLL_SYS_FBDIV_INT_FBDIV_INT_Pos,
PLL_SYS_FBDIV_INT_FBDIV_INT_Msk);
/* turn on the main power */
io_reg_atomic_clear(&pll->PWR.reg, (1U << PLL_SYS_PWR_VCOPD_Pos)
| (1U << PLL_SYS_PWR_DSMPD_Pos)
| (1U << PLL_SYS_PWR_PD_Pos));
/* wait for VCO to lock (i.e. keep its output stable) */
while (!pll->CS.bit.LOCK) { }
/* set up post divisors and turn them on */
pll->PRIM.reg = (post_div_1 << PLL_SYS_PRIM_POSTDIV1_Pos)
| (post_div_2 << PLL_SYS_PRIM_POSTDIV2_Pos);
io_reg_atomic_clear(&pll->PWR.reg, 1U << PLL_SYS_PWR_POSTDIVPD_Pos);
}
/**
* @brief Stop the PLL for the system clock (@p pll = PLL_SYS) or
* the USB clock (@p pll = PLL_USB)
*/
static void _pll_stop(PLL_SYS_Type *pll)
{
uint32_t reg = (1U << PLL_SYS_PWR_VCOPD_Pos)
| (1U << PLL_SYS_PWR_POSTDIVPD_Pos)
| (1U << PLL_SYS_PWR_DSMPD_Pos)
| (1U << PLL_SYS_PWR_PD_Pos);
io_reg_atomic_set(&pll->PWR.reg, reg);
}
void pll_start_sys(uint8_t ref_div,
uint16_t vco_feedback_scale,
uint8_t post_div_1, uint8_t post_div_2)
{
_pll_start(PLL_SYS, ref_div, vco_feedback_scale, post_div_1, post_div_2);
}
void pll_start_usb(uint8_t ref_div,
uint16_t vco_feedback_scale,
uint8_t post_div_1, uint8_t post_div_2)
{
_pll_start(PLL_USB, ref_div, vco_feedback_scale, post_div_1, post_div_2);
}
void pll_stop_sys(void)
{
_pll_stop(PLL_SYS);
}
void pll_stop_usb(void)
{
_pll_stop(PLL_USB);
}
/**
* @brief Reset the PLL of the system clock
*/
void pll_reset_sys(void)
{
periph_reset(1U << RESETS_RESET_pll_sys_Pos);
periph_reset_done(1U << RESETS_RESET_pll_sys_Pos);
}
/**
* @brief Reset the PLL of the USB clock
*/
void pll_reset_usb(void)
{
periph_reset(1U << RESETS_RESET_pll_usb_Pos);
periph_reset_done(1U << RESETS_RESET_pll_usb_Pos);
}

57
cpu/rpx0xx/rosc.c Normal file
View File

@ -0,0 +1,57 @@
/*
* 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.
*/
/**
* @ingroup cpu_rpx0xx
* @{
*
* @file
* @brief Implementation of the ring oscillator (ROSC)
*
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
*
* @}
*/
#include "vendor/RP2040.h"
#include "io_reg.h"
/**
* @brief Start the ring oscillator in default mode.
* The ROSC is running at boot time but may be turned off
* to save power when switching to the accurate XOSC.
* The default ROSC provides an instable frequency of 1.8 MHz to 12 MHz.
*/
void rosc_start(void)
{
/* set drive strengths to default 0 */
io_reg_atomic_clear(&ROSC->FREQA.reg, ROSC_FREQA_PASSWD_Msk);
io_reg_atomic_clear(&ROSC->FREQB.reg, ROSC_FREQB_PASSWD_Msk);
/* apply settings with magic value 0x9696 */
const uint32_t magic = 0x9696U;
io_reg_write_dont_corrupt(&ROSC->FREQA.reg, magic << ROSC_FREQA_PASSWD_Pos,
ROSC_FREQA_PASSWD_Msk);
io_reg_write_dont_corrupt(&ROSC->FREQB.reg, magic << ROSC_FREQB_PASSWD_Pos,
ROSC_FREQB_PASSWD_Msk);
/* default divider is 16 */
io_reg_write_dont_corrupt(&ROSC->DIV.reg, 16 << ROSC_DIV_DIV_Pos, ROSC_DIV_DIV_Msk);
io_reg_atomic_set(&ROSC->CTRL.reg, ROSC_CTRL_ENABLE_ENABLE << ROSC_CTRL_ENABLE_Pos);
while (!ROSC->STATUS.bit.STABLE) { }
}
/**
* @brief Turn off the ROSC to save power.
* The system clock must be switched to to another lock source
* before the ROSC is stopped, other wise the chip will be lock up.
*/
void rosc_stop(void)
{
io_reg_atomic_set(&ROSC->CTRL.reg, ROSC_CTRL_ENABLE_DISABLE << ROSC_CTRL_ENABLE_Pos);
}

95
cpu/rpx0xx/vectors.c Normal file
View File

@ -0,0 +1,95 @@
/*
* 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.
*/
/**
* @ingroup cpu_rpx0xx
* @{
*
* @file
* @brief rpx0xx interrupt vector definitions
*
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
*
* @}
*/
#include <stdint.h>
#include "vectors_cortexm.h"
void dummy_handler(void) {
dummy_handler_default();
}
WEAK_DEFAULT void isr_timer0(void);
WEAK_DEFAULT void isr_timer1(void);
WEAK_DEFAULT void isr_timer2(void);
WEAK_DEFAULT void isr_timer3(void);
WEAK_DEFAULT void isr_pwm_wrap(void);
WEAK_DEFAULT void isr_usbctrl(void);
WEAK_DEFAULT void isr_xip(void);
WEAK_DEFAULT void isr_pio00(void);
WEAK_DEFAULT void isr_pio01(void);
WEAK_DEFAULT void isr_pio10(void);
WEAK_DEFAULT void isr_pio11(void);
WEAK_DEFAULT void isr_dma0(void);
WEAK_DEFAULT void isr_dma1(void);
WEAK_DEFAULT void isr_io_bank0(void);
WEAK_DEFAULT void isr_io_qspi(void);
WEAK_DEFAULT void isr_sio_proc0(void);
WEAK_DEFAULT void isr_sio_proc1(void);
WEAK_DEFAULT void isr_clocks(void);
WEAK_DEFAULT void isr_spi0(void);
WEAK_DEFAULT void isr_spi1(void);
WEAK_DEFAULT void isr_uart0(void);
WEAK_DEFAULT void isr_uart1(void);
WEAK_DEFAULT void isr_adc_fifo(void);
WEAK_DEFAULT void isr_i2c0(void);
WEAK_DEFAULT void isr_i2c1(void);
WEAK_DEFAULT void isr_rtc0(void);
WEAK_DEFAULT void isr_swi0(void);
WEAK_DEFAULT void isr_swi1(void);
WEAK_DEFAULT void isr_swi2(void);
WEAK_DEFAULT void isr_swi3(void);
WEAK_DEFAULT void isr_swi4(void);
WEAK_DEFAULT void isr_swi5(void);
ISR_VECTOR(1) const isr_t vector_cpu[CPU_IRQ_NUMOF] = {
isr_timer0,
isr_timer1,
isr_timer2,
isr_timer3,
isr_pwm_wrap,
isr_usbctrl,
isr_xip,
isr_pio00,
isr_pio01,
isr_pio10,
isr_pio11,
isr_dma0,
isr_dma1,
isr_io_bank0,
isr_io_qspi,
isr_sio_proc0,
isr_sio_proc1,
isr_clocks,
isr_spi0,
isr_spi1,
isr_uart0,
isr_uart1,
isr_adc_fifo,
isr_i2c0,
isr_i2c1,
isr_rtc0,
isr_swi0,
isr_swi1,
isr_swi2,
isr_swi3,
isr_swi4,
isr_swi5,
};

View File

@ -0,0 +1 @@
/*padded_checksummed.S

33
cpu/rpx0xx/vendor/boot_stage2/Makefile vendored Normal file
View File

@ -0,0 +1,33 @@
CC := arm-none-eabi-gcc
OBJCOPY := arm-none-eabi-objcopy
CFLAGS := -mcpu=cortex-m0plus -mthumb -O3 -DNDEBUG -I$(abspath include)
LDFLAGS := -Wl,--build-id=none --specs=nosys.specs -nostartfiles -Wl,--script=boot_stage2.ld
PAD_CHECKSUM := ./pad_checksum
CHECKSUM_SEED := 0xffffffff
.PHONY: clean all
all: \
boot2_at25sf128a_padded_checksummed.S \
boot2_generic_03h_padded_checksummed.S \
boot2_is25lp080_padded_checksummed.S \
boot2_usb_blinky_padded_checksummed.S \
boot2_w25q080_padded_checksummed.S \
boot2_w25x10cl_padded_checksummed.S \
#
clean:
rm -f *_padded_checksummed.S *.o *.bin *.elf
%.o: %.S
$(CC) $(CFLAGS) -c -o $@ $<
%.elf: %.o
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
%.bin: %.elf
$(OBJCOPY) -Obinary $< $@
%_padded_checksummed.S: %.bin
$(PAD_CHECKSUM) -s $(CHECKSUM_SEED) $< $@

View File

@ -0,0 +1,5 @@
How to Generate
===============
Run `make` create the bootloader. The source is taken from the pico-sdk. Ideally, the
boot loader needs to never be touched.

View File

@ -0,0 +1,285 @@
// ----------------------------------------------------------------------------
// Second stage boot code
// Copyright (c) 2019-2021 Raspberry Pi (Trading) Ltd.
// SPDX-License-Identifier: BSD-3-Clause
//
// Device: Adesto AT25SF128A
// Based on W25Q080 code: main difference is the QE bit is being set
// via command 0x31
//
// Description: Configures AT25SF128A to run in Quad I/O continuous read XIP mode
//
// Details: * Check status register 2 to determine if QSPI mode is enabled,
// and perform an SR2 programming cycle if necessary.
// * Use SSI to perform a dummy 0xEB read command, with the mode
// continuation bits set, so that the flash will not require
// 0xEB instruction prefix on subsequent reads.
// * Configure SSI to write address, mode bits, but no instruction.
// SSI + flash are now jointly in a state where continuous reads
// can take place.
// * Jump to exit pointer passed in via lr. Bootrom passes null,
// in which case this code uses a default 256 byte flash offset
//
// Building: * This code must be position-independent, and use stack only
// * The code will be padded to a size of 256 bytes, including a
// 4-byte checksum. Therefore code size cannot exceed 252 bytes.
// ----------------------------------------------------------------------------
#include "pico/asm_helper.S"
#include "hardware/regs/addressmap.h"
#include "hardware/regs/ssi.h"
#include "hardware/regs/pads_qspi.h"
// ----------------------------------------------------------------------------
// Config section
// ----------------------------------------------------------------------------
// It should be possible to support most flash devices by modifying this section
// The serial flash interface will run at clk_sys/PICO_FLASH_SPI_CLKDIV.
// This must be a positive, even integer.
// The bootrom is very conservative with SPI frequency, but here we should be
// as aggressive as possible.
#ifndef PICO_FLASH_SPI_CLKDIV
#define PICO_FLASH_SPI_CLKDIV 4
#endif
#if PICO_FLASH_SPI_CLKDIV & 1
#error PICO_FLASH_SPI_CLKDIV must be even
#endif
// Define interface width: single/dual/quad IO
#define FRAME_FORMAT SSI_CTRLR0_SPI_FRF_VALUE_QUAD
// For W25Q080 this is the "Read data fast quad IO" instruction:
#define CMD_READ 0xeb
// "Mode bits" are 8 special bits sent immediately after
// the address bits in a "Read Data Fast Quad I/O" command sequence.
// On W25Q080, the four LSBs are don't care, and if MSBs == 0xa, the
// next read does not require the 0xeb instruction prefix.
#define MODE_CONTINUOUS_READ 0x20
// The number of address + mode bits, divided by 4 (always 4, not function of
// interface width).
#define ADDR_L 8
// How many clocks of Hi-Z following the mode bits. For W25Q080, 4 dummy cycles
// are required.
#define WAIT_CYCLES 4
// If defined, we will read status reg, compare to SREG_DATA, and overwrite
// with our value if the SR doesn't match.
// We do a two-byte write to SR1 (01h cmd) rather than a one-byte write to
// SR2 (31h cmd) as the latter command isn't supported by WX25Q080.
// This isn't great because it will remove block protections.
// A better solution is to use a volatile SR write if your device supports it.
#define PROGRAM_STATUS_REG
#define CMD_WRITE_ENABLE 0x06
#define CMD_READ_STATUS 0x05
#define CMD_READ_STATUS2 0x35
#define CMD_WRITE_STATUS 0x01
#define CMD_WRITE_STATUS2 0x31
#define SREG_DATA 0x02 // Enable quad-SPI mode
// ----------------------------------------------------------------------------
// Start of 2nd Stage Boot Code
// ----------------------------------------------------------------------------
.syntax unified
.cpu cortex-m0plus
.thumb
.section .text
// The exit point is passed in lr. If entered from bootrom, this will be the
// flash address immediately following this second stage (0x10000100).
// Otherwise it will be a return address -- second stage being called as a
// function by user code, after copying out of XIP region. r3 holds SSI base,
// r0...2 used as temporaries. Other GPRs not used.
.global _stage2_boot
.type _stage2_boot,%function
.thumb_func
_stage2_boot:
push {lr}
// Set pad configuration:
// - SCLK 8mA drive, no slew limiting
// - SDx disable input Schmitt to reduce delay
ldr r3, =PADS_QSPI_BASE
movs r0, #(2 << PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_LSB | PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_BITS)
str r0, [r3, #PADS_QSPI_GPIO_QSPI_SCLK_OFFSET]
ldr r0, [r3, #PADS_QSPI_GPIO_QSPI_SD0_OFFSET]
movs r1, #PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_BITS
bics r0, r1
str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD0_OFFSET]
str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD1_OFFSET]
str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD2_OFFSET]
str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD3_OFFSET]
ldr r3, =XIP_SSI_BASE
// Disable SSI to allow further config
movs r1, #0
str r1, [r3, #SSI_SSIENR_OFFSET]
// Set baud rate
movs r1, #PICO_FLASH_SPI_CLKDIV
str r1, [r3, #SSI_BAUDR_OFFSET]
// Set 1-cycle sample delay. If PICO_FLASH_SPI_CLKDIV == 2 then this means,
// if the flash launches data on SCLK posedge, we capture it at the time that
// the next SCLK posedge is launched. This is shortly before that posedge
// arrives at the flash, so data hold time should be ok. For
// PICO_FLASH_SPI_CLKDIV > 2 this pretty much has no effect.
movs r1, #1
movs r2, #SSI_RX_SAMPLE_DLY_OFFSET // == 0xf0 so need 8 bits of offset significance
str r1, [r3, r2]
// On QSPI parts we usually need a 01h SR-write command to enable QSPI mode
// (i.e. turn WPn and HOLDn into IO2/IO3)
#ifdef PROGRAM_STATUS_REG
program_sregs:
#define CTRL0_SPI_TXRX \
(7 << SSI_CTRLR0_DFS_32_LSB) | /* 8 bits per data frame */ \
(SSI_CTRLR0_TMOD_VALUE_TX_AND_RX << SSI_CTRLR0_TMOD_LSB)
ldr r1, =(CTRL0_SPI_TXRX)
str r1, [r3, #SSI_CTRLR0_OFFSET]
// Enable SSI and select slave 0
movs r1, #1
str r1, [r3, #SSI_SSIENR_OFFSET]
// Check whether SR needs updating
movs r0, #CMD_READ_STATUS2
bl read_flash_sreg
movs r2, #SREG_DATA
cmp r0, r2
beq skip_sreg_programming
// Send write enable command
movs r1, #CMD_WRITE_ENABLE
str r1, [r3, #SSI_DR0_OFFSET]
// Poll for completion and discard RX
bl wait_ssi_ready
ldr r1, [r3, #SSI_DR0_OFFSET]
// Send status write command followed by data bytes
movs r1, #CMD_WRITE_STATUS2
str r1, [r3, #SSI_DR0_OFFSET]
str r2, [r3, #SSI_DR0_OFFSET]
bl wait_ssi_ready
ldr r1, [r3, #SSI_DR0_OFFSET]
ldr r1, [r3, #SSI_DR0_OFFSET]
ldr r1, [r3, #SSI_DR0_OFFSET]
// Poll status register for write completion
1:
movs r0, #CMD_READ_STATUS
bl read_flash_sreg
movs r1, #1
tst r0, r1
bne 1b
skip_sreg_programming:
// Disable SSI again so that it can be reconfigured
movs r1, #0
str r1, [r3, #SSI_SSIENR_OFFSET]
#endif
// Currently the flash expects an 8 bit serial command prefix on every
// transfer, which is a waste of cycles. Perform a dummy Fast Read Quad I/O
// command, with mode bits set such that the flash will not expect a serial
// command prefix on *subsequent* transfers. We don't care about the results
// of the read, the important part is the mode bits.
dummy_read:
#define CTRLR0_ENTER_XIP \
(FRAME_FORMAT /* Quad I/O mode */ \
<< SSI_CTRLR0_SPI_FRF_LSB) | \
(31 << SSI_CTRLR0_DFS_32_LSB) | /* 32 data bits */ \
(SSI_CTRLR0_TMOD_VALUE_EEPROM_READ /* Send INST/ADDR, Receive Data */ \
<< SSI_CTRLR0_TMOD_LSB)
ldr r1, =(CTRLR0_ENTER_XIP)
str r1, [r3, #SSI_CTRLR0_OFFSET]
movs r1, #0x0 // NDF=0 (single 32b read)
str r1, [r3, #SSI_CTRLR1_OFFSET]
#define SPI_CTRLR0_ENTER_XIP \
(ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Address + mode bits */ \
(WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \
(SSI_SPI_CTRLR0_INST_L_VALUE_8B \
<< SSI_SPI_CTRLR0_INST_L_LSB) | /* 8-bit instruction */ \
(SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C2A /* Send Command in serial mode then address in Quad I/O mode */ \
<< SSI_SPI_CTRLR0_TRANS_TYPE_LSB)
ldr r1, =(SPI_CTRLR0_ENTER_XIP)
ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) // SPI_CTRL0 Register
str r1, [r0]
movs r1, #1 // Re-enable SSI
str r1, [r3, #SSI_SSIENR_OFFSET]
movs r1, #CMD_READ
str r1, [r3, #SSI_DR0_OFFSET] // Push SPI command into TX FIFO
movs r1, #MODE_CONTINUOUS_READ // 32-bit: 24 address bits (we don't care, so 0) and M[7:4]=1010
str r1, [r3, #SSI_DR0_OFFSET] // Push Address into TX FIFO - this will trigger the transaction
// Poll for completion
bl wait_ssi_ready
// The flash is in a state where we can blast addresses in parallel, and get
// parallel data back. Now configure the SSI to translate XIP bus accesses
// into QSPI transfers of this form.
movs r1, #0
str r1, [r3, #SSI_SSIENR_OFFSET] // Disable SSI (and clear FIFO) to allow further config
// Note that the INST_L field is used to select what XIP data gets pushed into
// the TX FIFO:
// INST_L_0_BITS {ADDR[23:0],XIP_CMD[7:0]} Load "mode bits" into XIP_CMD
// Anything else {XIP_CMD[7:0],ADDR[23:0]} Load SPI command into XIP_CMD
configure_ssi:
#define SPI_CTRLR0_XIP \
(MODE_CONTINUOUS_READ /* Mode bits to keep flash in continuous read mode */ \
<< SSI_SPI_CTRLR0_XIP_CMD_LSB) | \
(ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Total number of address + mode bits */ \
(WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \
(SSI_SPI_CTRLR0_INST_L_VALUE_NONE /* Do not send a command, instead send XIP_CMD as mode bits after address */ \
<< SSI_SPI_CTRLR0_INST_L_LSB) | \
(SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_2C2A /* Send Address in Quad I/O mode (and Command but that is zero bits long) */ \
<< SSI_SPI_CTRLR0_TRANS_TYPE_LSB)
ldr r1, =(SPI_CTRLR0_XIP)
ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET)
str r1, [r0]
movs r1, #1
str r1, [r3, #SSI_SSIENR_OFFSET] // Re-enable SSI
// Bus accesses to the XIP window will now be transparently serviced by the
// external flash on cache miss. We are ready to run code from flash.
// Pull in standard exit routine
#include "boot2_helpers/exit_from_boot2.S"
// Common functions
#include "boot2_helpers/wait_ssi_ready.S"
#ifdef PROGRAM_STATUS_REG
#include "boot2_helpers/read_flash_sreg.S"
#endif
.global literals
literals:
.ltorg
.end

View File

@ -0,0 +1,103 @@
// ----------------------------------------------------------------------------
// Second stage boot code
// Copyright (c) 2019-2021 Raspberry Pi (Trading) Ltd.
// SPDX-License-Identifier: BSD-3-Clause
//
// Device: Anything which responds to 03h serial read command
//
// Details: * Configure SSI to translate each APB read into a 03h command
// * 8 command clocks, 24 address clocks and 32 data clocks
// * This enables you to boot from almost anything: you can pretty
// much solder a potato to your PCB, or a piece of cheese
// * The tradeoff is performance around 3x worse than QSPI XIP
//
// Building: * This code must be position-independent, and use stack only
// * The code will be padded to a size of 256 bytes, including a
// 4-byte checksum. Therefore code size cannot exceed 252 bytes.
// ----------------------------------------------------------------------------
#include "pico/asm_helper.S"
#include "hardware/regs/addressmap.h"
#include "hardware/regs/ssi.h"
// ----------------------------------------------------------------------------
// Config section
// ----------------------------------------------------------------------------
// It should be possible to support most flash devices by modifying this section
// The serial flash interface will run at clk_sys/PICO_FLASH_SPI_CLKDIV.
// This must be a positive, even integer.
// The bootrom is very conservative with SPI frequency, but here we should be
// as aggressive as possible.
#ifndef PICO_FLASH_SPI_CLKDIV
#define PICO_FLASH_SPI_CLKDIV 4
#endif
#define CMD_READ 0x03
// Value is number of address bits divided by 4
#define ADDR_L 6
#define CTRLR0_XIP \
(SSI_CTRLR0_SPI_FRF_VALUE_STD << SSI_CTRLR0_SPI_FRF_LSB) | /* Standard 1-bit SPI serial frames */ \
(31 << SSI_CTRLR0_DFS_32_LSB) | /* 32 clocks per data frame */ \
(SSI_CTRLR0_TMOD_VALUE_EEPROM_READ << SSI_CTRLR0_TMOD_LSB) /* Send instr + addr, receive data */
#define SPI_CTRLR0_XIP \
(CMD_READ << SSI_SPI_CTRLR0_XIP_CMD_LSB) | /* Value of instruction prefix */ \
(ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Total number of address + mode bits */ \
(2 << SSI_SPI_CTRLR0_INST_L_LSB) | /* 8 bit command prefix (field value is bits divided by 4) */ \
(SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C1A << SSI_SPI_CTRLR0_TRANS_TYPE_LSB) /* command and address both in serial format */
// ----------------------------------------------------------------------------
// Start of 2nd Stage Boot Code
// ----------------------------------------------------------------------------
.cpu cortex-m0
.thumb
.section .text
.global _stage2_boot
.type _stage2_boot,%function
.thumb_func
_stage2_boot:
push {lr}
ldr r3, =XIP_SSI_BASE // Use as base address where possible
// Disable SSI to allow further config
mov r1, #0
str r1, [r3, #SSI_SSIENR_OFFSET]
// Set baud rate
mov r1, #PICO_FLASH_SPI_CLKDIV
str r1, [r3, #SSI_BAUDR_OFFSET]
ldr r1, =(CTRLR0_XIP)
str r1, [r3, #SSI_CTRLR0_OFFSET]
ldr r1, =(SPI_CTRLR0_XIP)
ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET)
str r1, [r0]
// NDF=0 (single 32b read)
mov r1, #0x0
str r1, [r3, #SSI_CTRLR1_OFFSET]
// Re-enable SSI
mov r1, #1
str r1, [r3, #SSI_SSIENR_OFFSET]
// We are now in XIP mode. Any bus accesses to the XIP address window will be
// translated by the SSI into 03h read commands to the external flash (if cache is missed),
// and the data will be returned to the bus.
// Pull in standard exit routine
#include "boot2_helpers/exit_from_boot2.S"
.global literals
literals:
.ltorg
.end

View File

@ -0,0 +1,262 @@
// ----------------------------------------------------------------------------
// Copyright (c) 2019-2021 Raspberry Pi (Trading) Ltd.
// SPDX-License-Identifier: BSD-3-Clause
//
// Device: ISSI IS25LP080D
// Based on W25Q080 code: main difference is the QE bit being in
// SR1 instead of SR2.
//
// Description: Configures IS25LP080D to run in Quad I/O continuous read XIP mode
//
// Details: * Check status register to determine if QSPI mode is enabled,
// and perform an SR programming cycle if necessary.
// * Use SSI to perform a dummy 0xEB read command, with the mode
// continuation bits set, so that the flash will not require
// 0xEB instruction prefix on subsequent reads.
// * Configure SSI to write address, mode bits, but no instruction.
// SSI + flash are now jointly in a state where continuous reads
// can take place.
// * Set VTOR = 0x10000100 (user vector table immediately after
// this boot2 image).
// * Read stack pointer (MSP) and reset vector from the flash
// vector table; set SP and jump, as though the processor had
// booted directly from flash.
//
// Building: * This code must be linked to run at 0x20027f00
// * The code will be padded to a size of 256 bytes, including a
// 4-byte checksum. Therefore code size cannot exceed 252 bytes.
// ----------------------------------------------------------------------------
#include "pico/asm_helper.S"
#include "hardware/regs/addressmap.h"
#include "hardware/regs/ssi.h"
// ----------------------------------------------------------------------------
// Config section
// ----------------------------------------------------------------------------
// It should be possible to support most flash devices by modifying this section
// The serial flash interface will run at clk_sys/PICO_FLASH_SPI_CLKDIV.
// This must be a positive, even integer.
// The bootrom is very conservative with SPI frequency, but here we should be
// as aggressive as possible.
#ifndef PICO_FLASH_SPI_CLKDIV
#define PICO_FLASH_SPI_CLKDIV 4
#endif
// Define interface width: single/dual/quad IO
#define FRAME_FORMAT SSI_CTRLR0_SPI_FRF_VALUE_QUAD
// For W25Q080 this is the "Read data fast quad IO" instruction:
#define CMD_READ 0xeb
// "Mode bits" are 8 special bits sent immediately after
// the address bits in a "Read Data Fast Quad I/O" command sequence.
// On W25Q080, the four LSBs are don't care, and if MSBs == 0xa, the
// next read does not require the 0xeb instruction prefix.
#define MODE_CONTINUOUS_READ 0xa0
// The number of address + mode bits, divided by 4 (always 4, not function of
// interface width).
#define ADDR_L 8
// How many clocks of Hi-Z following the mode bits. For W25Q080, 4 dummy cycles
// are required.
#define WAIT_CYCLES 4
// If defined, we will read status reg, compare to SREG_DATA, and overwrite
// with our value if the SR doesn't match.
// This isn't great because it will remove block protections.
// A better solution is to use a volatile SR write if your device supports it.
#define PROGRAM_STATUS_REG
#define CMD_WRITE_ENABLE 0x06
#define CMD_READ_STATUS 0x05
#define CMD_WRITE_STATUS 0x01
#define SREG_DATA 0x40 // Enable quad-SPI mode
// ----------------------------------------------------------------------------
// Start of 2nd Stage Boot Code
// ----------------------------------------------------------------------------
.cpu cortex-m0
.thumb
.section .text
.global _stage2_boot
.type _stage2_boot,%function
.thumb_func
_stage2_boot:
push {lr}
ldr r3, =XIP_SSI_BASE // Use as base address where possible
// Disable SSI to allow further config
mov r1, #0
str r1, [r3, #SSI_SSIENR_OFFSET]
// Set baud rate
mov r1, #PICO_FLASH_SPI_CLKDIV
str r1, [r3, #SSI_BAUDR_OFFSET]
// On QSPI parts we usually need a 01h SR-write command to enable QSPI mode
// (i.e. turn WPn and HOLDn into IO2/IO3)
#ifdef PROGRAM_STATUS_REG
program_sregs:
#define CTRL0_SPI_TXRX \
(7 << SSI_CTRLR0_DFS_32_LSB) | /* 8 bits per data frame */ \
(SSI_CTRLR0_TMOD_VALUE_TX_AND_RX << SSI_CTRLR0_TMOD_LSB)
ldr r1, =(CTRL0_SPI_TXRX)
str r1, [r3, #SSI_CTRLR0_OFFSET]
// Enable SSI and select slave 0
mov r1, #1
str r1, [r3, #SSI_SSIENR_OFFSET]
// Check whether SR needs updating
ldr r0, =CMD_READ_STATUS
bl read_flash_sreg
ldr r2, =SREG_DATA
cmp r0, r2
beq skip_sreg_programming
// Send write enable command
mov r1, #CMD_WRITE_ENABLE
str r1, [r3, #SSI_DR0_OFFSET]
// Poll for completion and discard RX
bl wait_ssi_ready
ldr r1, [r3, #SSI_DR0_OFFSET]
// Send status write command followed by data bytes
mov r1, #CMD_WRITE_STATUS
str r1, [r3, #SSI_DR0_OFFSET]
mov r0, #0
str r2, [r3, #SSI_DR0_OFFSET]
bl wait_ssi_ready
ldr r1, [r3, #SSI_DR0_OFFSET]
ldr r1, [r3, #SSI_DR0_OFFSET]
// Poll status register for write completion
1:
ldr r0, =CMD_READ_STATUS
bl read_flash_sreg
mov r1, #1
tst r0, r1
bne 1b
skip_sreg_programming:
// Send a 0xA3 high-performance-mode instruction
// ldr r1, =0xa3
// str r1, [r3, #SSI_DR0_OFFSET]
// bl wait_ssi_ready
// Disable SSI again so that it can be reconfigured
mov r1, #0
str r1, [r3, #SSI_SSIENR_OFFSET]
#endif
// First we need to send the initial command to get us in to Fast Read Quad I/O
// mode. As this transaction requires a command, we can't send it in XIP mode.
// To enter Continuous Read mode as well we need to append 4'b0010 to the address
// bits and then add a further 4 don't care bits. We will construct this by
// specifying a 28-bit address, with the least significant bits being 4'b0010.
// This is just a dummy transaction so we'll perform a read from address zero
// and then discard what comes back. All we really care about is that at the
// end of the transaction, the flash device is in Continuous Read mode
// and from then on will only expect to receive addresses.
dummy_read:
#define CTRLR0_ENTER_XIP \
(FRAME_FORMAT /* Quad I/O mode */ \
<< SSI_CTRLR0_SPI_FRF_LSB) | \
(31 << SSI_CTRLR0_DFS_32_LSB) | /* 32 data bits */ \
(SSI_CTRLR0_TMOD_VALUE_EEPROM_READ /* Send INST/ADDR, Receive Data */ \
<< SSI_CTRLR0_TMOD_LSB)
ldr r1, =(CTRLR0_ENTER_XIP)
str r1, [r3, #SSI_CTRLR0_OFFSET]
mov r1, #0x0 // NDF=0 (single 32b read)
str r1, [r3, #SSI_CTRLR1_OFFSET]
#define SPI_CTRLR0_ENTER_XIP \
(ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Address + mode bits */ \
(WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \
(SSI_SPI_CTRLR0_INST_L_VALUE_8B \
<< SSI_SPI_CTRLR0_INST_L_LSB) | /* 8-bit instruction */ \
(SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C2A /* Send Command in serial mode then address in Quad I/O mode */ \
<< SSI_SPI_CTRLR0_TRANS_TYPE_LSB)
ldr r1, =(SPI_CTRLR0_ENTER_XIP)
ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) // SPI_CTRL0 Register
str r1, [r0]
mov r1, #1 // Re-enable SSI
str r1, [r3, #SSI_SSIENR_OFFSET]
mov r1, #CMD_READ
str r1, [r3, #SSI_DR0_OFFSET] // Push SPI command into TX FIFO
mov r1, #MODE_CONTINUOUS_READ // 32-bit: 24 address bits (we don't care, so 0) and M[7:4]=1010
str r1, [r3, #SSI_DR0_OFFSET] // Push Address into TX FIFO - this will trigger the transaction
// Poll for completion
bl wait_ssi_ready
// At this point CN# will be deasserted and the SPI clock will not be running.
// The Winbond WX25X10CL device will be in continuous read, dual I/O mode and
// only expecting address bits after the next CN# assertion. So long as we
// send 4'b0010 (and 4 more dummy HiZ bits) after every subsequent 24b address
// then the Winbond device will remain in continuous read mode. This is the
// ideal mode for Execute-In-Place.
// (If we want to exit continuous read mode then we will need to switch back
// to APM mode and generate a 28-bit address phase with the extra nibble set
// to 4'b0000).
mov r1, #0
str r1, [r3, #SSI_SSIENR_OFFSET] // Disable SSI (and clear FIFO) to allow further config
// Note that the INST_L field is used to select what XIP data gets pushed into
// the TX FIFO:
// INST_L_0_BITS {ADDR[23:0],XIP_CMD[7:0]} Load "mode bits" into XIP_CMD
// Anything else {XIP_CMD[7:0],ADDR[23:0]} Load SPI command into XIP_CMD
configure_ssi:
#define SPI_CTRLR0_XIP \
(MODE_CONTINUOUS_READ /* Mode bits to keep flash in continuous read mode */ \
<< SSI_SPI_CTRLR0_XIP_CMD_LSB) | \
(ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Total number of address + mode bits */ \
(WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \
(SSI_SPI_CTRLR0_INST_L_VALUE_NONE /* Do not send a command, instead send XIP_CMD as mode bits after address */ \
<< SSI_SPI_CTRLR0_INST_L_LSB) | \
(SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_2C2A /* Send Address in Quad I/O mode (and Command but that is zero bits long) */ \
<< SSI_SPI_CTRLR0_TRANS_TYPE_LSB)
ldr r1, =(SPI_CTRLR0_XIP)
ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET)
str r1, [r0]
mov r1, #1
str r1, [r3, #SSI_SSIENR_OFFSET] // Re-enable SSI
// We are now in XIP mode, with all transactions using Dual I/O and only
// needing to send 24-bit addresses (plus mode bits) for each read transaction.
// Pull in standard exit routine
#include "boot2_helpers/exit_from_boot2.S"
// Common functions
#include "boot2_helpers/wait_ssi_ready.S"
#ifdef PROGRAM_STATUS_REG
#include "boot2_helpers/read_flash_sreg.S"
#endif
.global literals
literals:
.ltorg
.end

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
// Stub second stage which calls into USB bootcode, with parameters.
// USB boot takes two parameters:
// - A GPIO mask for activity LED -- if mask is 0, don't touch GPIOs at all
// - A mask of interfaces to disable. Bit 0 disables MSC, bit 1 disables PICOBoot
// The bootrom passes 0 for both of these parameters, but user code (or this
// second stage) can pass anything.
#define USB_BOOT_MSD_AND_PICOBOOT 0x0
#define USB_BOOT_MSD_ONLY 0x2
#define USB_BOOT_PICOBOOT_ONLY 0x1
// Config
#define ACTIVITY_LED 0
#define BOOT_MODE USB_BOOT_MSD_AND_PICOBOOT
.cpu cortex-m0
.thumb
.section .text
.global _stage2_boot
.type _stage2_boot,%function
.thumb_func
_stage2_boot:
mov r7, #0x14 // Pointer to _well_known pointer table in ROM
ldrh r0, [r7, #0] // Offset 0 is 16 bit pointer to function table
ldrh r7, [r7, #4] // Offset 4 is 16 bit pointer to table lookup routine
ldr r1, =('U' | ('B' << 8)) // Symbol for USB Boot
blx r7
cmp r0, #0
beq dead
mov r7, r0
ldr r0, =(1u << ACTIVITY_LED) // Mask of which GPIO (or GPIOs) to use
mov r1, #BOOT_MODE
blx r7
dead:
wfi
b dead
.global literals
literals:
.ltorg
.end

View File

@ -0,0 +1,287 @@
// ----------------------------------------------------------------------------
// Second stage boot code
// Copyright (c) 2019-2021 Raspberry Pi (Trading) Ltd.
// SPDX-License-Identifier: BSD-3-Clause
//
// Device: Winbond W25Q080
// Also supports W25Q16JV (which has some different SR instructions)
// Also supports AT25SF081
// Also supports S25FL132K0
//
// Description: Configures W25Q080 to run in Quad I/O continuous read XIP mode
//
// Details: * Check status register 2 to determine if QSPI mode is enabled,
// and perform an SR2 programming cycle if necessary.
// * Use SSI to perform a dummy 0xEB read command, with the mode
// continuation bits set, so that the flash will not require
// 0xEB instruction prefix on subsequent reads.
// * Configure SSI to write address, mode bits, but no instruction.
// SSI + flash are now jointly in a state where continuous reads
// can take place.
// * Jump to exit pointer passed in via lr. Bootrom passes null,
// in which case this code uses a default 256 byte flash offset
//
// Building: * This code must be position-independent, and use stack only
// * The code will be padded to a size of 256 bytes, including a
// 4-byte checksum. Therefore code size cannot exceed 252 bytes.
// ----------------------------------------------------------------------------
#include "pico/asm_helper.S"
#include "hardware/regs/addressmap.h"
#include "hardware/regs/ssi.h"
#include "hardware/regs/pads_qspi.h"
// ----------------------------------------------------------------------------
// Config section
// ----------------------------------------------------------------------------
// It should be possible to support most flash devices by modifying this section
// The serial flash interface will run at clk_sys/PICO_FLASH_SPI_CLKDIV.
// This must be a positive, even integer.
// The bootrom is very conservative with SPI frequency, but here we should be
// as aggressive as possible.
#ifndef PICO_FLASH_SPI_CLKDIV
#define PICO_FLASH_SPI_CLKDIV 4
#endif
#if PICO_FLASH_SPI_CLKDIV & 1
#error PICO_FLASH_SPI_CLKDIV must be even
#endif
// Define interface width: single/dual/quad IO
#define FRAME_FORMAT SSI_CTRLR0_SPI_FRF_VALUE_QUAD
// For W25Q080 this is the "Read data fast quad IO" instruction:
#define CMD_READ 0xeb
// "Mode bits" are 8 special bits sent immediately after
// the address bits in a "Read Data Fast Quad I/O" command sequence.
// On W25Q080, the four LSBs are don't care, and if MSBs == 0xa, the
// next read does not require the 0xeb instruction prefix.
#define MODE_CONTINUOUS_READ 0xa0
// The number of address + mode bits, divided by 4 (always 4, not function of
// interface width).
#define ADDR_L 8
// How many clocks of Hi-Z following the mode bits. For W25Q080, 4 dummy cycles
// are required.
#define WAIT_CYCLES 4
// If defined, we will read status reg, compare to SREG_DATA, and overwrite
// with our value if the SR doesn't match.
// We do a two-byte write to SR1 (01h cmd) rather than a one-byte write to
// SR2 (31h cmd) as the latter command isn't supported by WX25Q080.
// This isn't great because it will remove block protections.
// A better solution is to use a volatile SR write if your device supports it.
#define PROGRAM_STATUS_REG
#define CMD_WRITE_ENABLE 0x06
#define CMD_READ_STATUS 0x05
#define CMD_READ_STATUS2 0x35
#define CMD_WRITE_STATUS 0x01
#define SREG_DATA 0x02 // Enable quad-SPI mode
// ----------------------------------------------------------------------------
// Start of 2nd Stage Boot Code
// ----------------------------------------------------------------------------
.syntax unified
.cpu cortex-m0plus
.thumb
.section .text
// The exit point is passed in lr. If entered from bootrom, this will be the
// flash address immediately following this second stage (0x10000100).
// Otherwise it will be a return address -- second stage being called as a
// function by user code, after copying out of XIP region. r3 holds SSI base,
// r0...2 used as temporaries. Other GPRs not used.
.global _stage2_boot
.type _stage2_boot,%function
.thumb_func
_stage2_boot:
push {lr}
// Set pad configuration:
// - SCLK 8mA drive, no slew limiting
// - SDx disable input Schmitt to reduce delay
ldr r3, =PADS_QSPI_BASE
movs r0, #(2 << PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_LSB | PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_BITS)
str r0, [r3, #PADS_QSPI_GPIO_QSPI_SCLK_OFFSET]
ldr r0, [r3, #PADS_QSPI_GPIO_QSPI_SD0_OFFSET]
movs r1, #PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_BITS
bics r0, r1
str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD0_OFFSET]
str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD1_OFFSET]
str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD2_OFFSET]
str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD3_OFFSET]
ldr r3, =XIP_SSI_BASE
// Disable SSI to allow further config
movs r1, #0
str r1, [r3, #SSI_SSIENR_OFFSET]
// Set baud rate
movs r1, #PICO_FLASH_SPI_CLKDIV
str r1, [r3, #SSI_BAUDR_OFFSET]
// Set 1-cycle sample delay. If PICO_FLASH_SPI_CLKDIV == 2 then this means,
// if the flash launches data on SCLK posedge, we capture it at the time that
// the next SCLK posedge is launched. This is shortly before that posedge
// arrives at the flash, so data hold time should be ok. For
// PICO_FLASH_SPI_CLKDIV > 2 this pretty much has no effect.
movs r1, #1
movs r2, #SSI_RX_SAMPLE_DLY_OFFSET // == 0xf0 so need 8 bits of offset significance
str r1, [r3, r2]
// On QSPI parts we usually need a 01h SR-write command to enable QSPI mode
// (i.e. turn WPn and HOLDn into IO2/IO3)
#ifdef PROGRAM_STATUS_REG
program_sregs:
#define CTRL0_SPI_TXRX \
(7 << SSI_CTRLR0_DFS_32_LSB) | /* 8 bits per data frame */ \
(SSI_CTRLR0_TMOD_VALUE_TX_AND_RX << SSI_CTRLR0_TMOD_LSB)
ldr r1, =(CTRL0_SPI_TXRX)
str r1, [r3, #SSI_CTRLR0_OFFSET]
// Enable SSI and select slave 0
movs r1, #1
str r1, [r3, #SSI_SSIENR_OFFSET]
// Check whether SR needs updating
movs r0, #CMD_READ_STATUS2
bl read_flash_sreg
movs r2, #SREG_DATA
cmp r0, r2
beq skip_sreg_programming
// Send write enable command
movs r1, #CMD_WRITE_ENABLE
str r1, [r3, #SSI_DR0_OFFSET]
// Poll for completion and discard RX
bl wait_ssi_ready
ldr r1, [r3, #SSI_DR0_OFFSET]
// Send status write command followed by data bytes
movs r1, #CMD_WRITE_STATUS
str r1, [r3, #SSI_DR0_OFFSET]
movs r0, #0
str r0, [r3, #SSI_DR0_OFFSET]
str r2, [r3, #SSI_DR0_OFFSET]
bl wait_ssi_ready
ldr r1, [r3, #SSI_DR0_OFFSET]
ldr r1, [r3, #SSI_DR0_OFFSET]
ldr r1, [r3, #SSI_DR0_OFFSET]
// Poll status register for write completion
1:
movs r0, #CMD_READ_STATUS
bl read_flash_sreg
movs r1, #1
tst r0, r1
bne 1b
skip_sreg_programming:
// Disable SSI again so that it can be reconfigured
movs r1, #0
str r1, [r3, #SSI_SSIENR_OFFSET]
#endif
// Currently the flash expects an 8 bit serial command prefix on every
// transfer, which is a waste of cycles. Perform a dummy Fast Read Quad I/O
// command, with mode bits set such that the flash will not expect a serial
// command prefix on *subsequent* transfers. We don't care about the results
// of the read, the important part is the mode bits.
dummy_read:
#define CTRLR0_ENTER_XIP \
(FRAME_FORMAT /* Quad I/O mode */ \
<< SSI_CTRLR0_SPI_FRF_LSB) | \
(31 << SSI_CTRLR0_DFS_32_LSB) | /* 32 data bits */ \
(SSI_CTRLR0_TMOD_VALUE_EEPROM_READ /* Send INST/ADDR, Receive Data */ \
<< SSI_CTRLR0_TMOD_LSB)
ldr r1, =(CTRLR0_ENTER_XIP)
str r1, [r3, #SSI_CTRLR0_OFFSET]
movs r1, #0x0 // NDF=0 (single 32b read)
str r1, [r3, #SSI_CTRLR1_OFFSET]
#define SPI_CTRLR0_ENTER_XIP \
(ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Address + mode bits */ \
(WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \
(SSI_SPI_CTRLR0_INST_L_VALUE_8B \
<< SSI_SPI_CTRLR0_INST_L_LSB) | /* 8-bit instruction */ \
(SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C2A /* Send Command in serial mode then address in Quad I/O mode */ \
<< SSI_SPI_CTRLR0_TRANS_TYPE_LSB)
ldr r1, =(SPI_CTRLR0_ENTER_XIP)
ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) // SPI_CTRL0 Register
str r1, [r0]
movs r1, #1 // Re-enable SSI
str r1, [r3, #SSI_SSIENR_OFFSET]
movs r1, #CMD_READ
str r1, [r3, #SSI_DR0_OFFSET] // Push SPI command into TX FIFO
movs r1, #MODE_CONTINUOUS_READ // 32-bit: 24 address bits (we don't care, so 0) and M[7:4]=1010
str r1, [r3, #SSI_DR0_OFFSET] // Push Address into TX FIFO - this will trigger the transaction
// Poll for completion
bl wait_ssi_ready
// The flash is in a state where we can blast addresses in parallel, and get
// parallel data back. Now configure the SSI to translate XIP bus accesses
// into QSPI transfers of this form.
movs r1, #0
str r1, [r3, #SSI_SSIENR_OFFSET] // Disable SSI (and clear FIFO) to allow further config
// Note that the INST_L field is used to select what XIP data gets pushed into
// the TX FIFO:
// INST_L_0_BITS {ADDR[23:0],XIP_CMD[7:0]} Load "mode bits" into XIP_CMD
// Anything else {XIP_CMD[7:0],ADDR[23:0]} Load SPI command into XIP_CMD
configure_ssi:
#define SPI_CTRLR0_XIP \
(MODE_CONTINUOUS_READ /* Mode bits to keep flash in continuous read mode */ \
<< SSI_SPI_CTRLR0_XIP_CMD_LSB) | \
(ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Total number of address + mode bits */ \
(WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \
(SSI_SPI_CTRLR0_INST_L_VALUE_NONE /* Do not send a command, instead send XIP_CMD as mode bits after address */ \
<< SSI_SPI_CTRLR0_INST_L_LSB) | \
(SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_2C2A /* Send Address in Quad I/O mode (and Command but that is zero bits long) */ \
<< SSI_SPI_CTRLR0_TRANS_TYPE_LSB)
ldr r1, =(SPI_CTRLR0_XIP)
ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET)
str r1, [r0]
movs r1, #1
str r1, [r3, #SSI_SSIENR_OFFSET] // Re-enable SSI
// Bus accesses to the XIP window will now be transparently serviced by the
// external flash on cache miss. We are ready to run code from flash.
// Pull in standard exit routine
#include "boot2_helpers/exit_from_boot2.S"
// Common functions
#include "boot2_helpers/wait_ssi_ready.S"
#ifdef PROGRAM_STATUS_REG
#include "boot2_helpers/read_flash_sreg.S"
#endif
.global literals
literals:
.ltorg
.end

View File

@ -0,0 +1,196 @@
// ----------------------------------------------------------------------------
// Second stage boot code
// Copyright (c) 2019-2021 Raspberry Pi (Trading) Ltd.
// SPDX-License-Identifier: BSD-3-Clause
//
// Device: Winbond W25X10CL
//
// Description: Configures W25X10CL to run in Dual I/O continuous read XIP mode
//
// Details: * Disable SSI
// * Configure SSI to generate 8b command + 28b address + 2 wait,
// with address and data using dual SPI mode
// * Enable SSI
// * Generate dummy read with command = 0xBB, top 24b of address
// of 0x000000 followed by M[7:0]=0010zzzz (with the HiZ being
// generated by 2 wait cycles). This leaves the W25X10CL in
// continuous read mode
// * Disable SSI
// * Configure SSI to generate 0b command + 28b address + 2 wait,
// with the extra 4 bits of address LSB being 0x2 to keep the
// W25X10CL in continuous read mode forever
// * Enable SSI
// * Set VTOR = 0x10000100
// * Read MSP reset vector from 0x10000100 and write to MSP (this
// will also enable XIP mode in the SSI wrapper)
// * Read PC reset vector from 0x10000104 and jump to it
//
// Building: * This code must be linked to run at 0x20000000
// * The code will be padded to a size of 256 bytes, including a
// 4-byte checksum. Therefore code size cannot exceed 252 bytes.
// ----------------------------------------------------------------------------
#include "pico/asm_helper.S"
#include "hardware/regs/addressmap.h"
#include "hardware/regs/ssi.h"
// The serial flash interface will run at clk_sys/PICO_FLASH_SPI_CLKDIV.
// This must be an even number.
#ifndef PICO_FLASH_SPI_CLKDIV
#define PICO_FLASH_SPI_CLKDIV 4
#endif
// ----------------------------------------------------------------------------
// The "System Control Block" is a set of internal Cortex-M0+ control registers
// that are memory mapped and accessed like any other H/W register. They have
// fixed addresses in the address map of every Cortex-M0+ system.
// ----------------------------------------------------------------------------
.equ SCB_VTOR, 0xE000ED08 // RW Vector Table Offset Register
// ----------------------------------------------------------------------------
// Winbond W25X10CL Supported Commands
// Taken from "w25x10cl_reg_021714.pdf"
// ----------------------------------------------------------------------------
.equ W25X10CL_CMD_READ_DATA_FAST_DUAL_IO, 0xbb
// ----------------------------------------------------------------------------
// Winbond W25X10CL "Mode bits" are 8 special bits sent immediately after
// the address bits in a "Read Data Fast Dual I/O" command sequence.
// Of M[7:4], they say M[7:6] are reserved (set to zero), and bits M[3:0]
// are don't care (we HiZ). Only M[5:4] are used, and they must be set
// to M[5:4] = 2'b10 to enable continuous read mode.
// ----------------------------------------------------------------------------
.equ W25X10CL_MODE_CONTINUOUS_READ, 0x20
// ----------------------------------------------------------------------------
// Start of 2nd Stage Boot Code
// ----------------------------------------------------------------------------
.cpu cortex-m0
.thumb
.org 0
.section .text
// This code will get copied to 0x20000000 and then executed
.global _stage2_boot
.type _stage2_boot,%function
.thumb_func
_stage2_boot:
push {lr}
ldr r3, =XIP_SSI_BASE // Use as base address where possible
// We are primarily interested in setting up Flash for DSPI XIP w/ continuous read
mov r1, #0
str r1, [r3, #SSI_SSIENR_OFFSET] // Disable SSI to allow further config
// The Boot ROM sets a very conservative SPI clock frequency to be sure it can
// read the initial 256 bytes from any device. Here we can be more aggressive.
mov r1, #PICO_FLASH_SPI_CLKDIV
str r1, [r3, #SSI_BAUDR_OFFSET] // Set SSI Clock
// First we need to send the initial command to get us in to Fast Read Dual I/O
// mode. As this transaction requires a command, we can't send it in XIP mode.
// To enter Continuous Read mode as well we need to append 4'b0010 to the address
// bits and then add a further 4 don't care bits. We will construct this by
// specifying a 28-bit address, with the least significant bits being 4'b0010.
// This is just a dummy transaction so we'll perform a read from address zero
// and then discard what comes back. All we really care about is that at the
// end of the transaction, the Winbond W25X10CL device is in Continuous Read mode
// and from then on will only expect to receive addresses.
#define CTRLR0_ENTER_XIP \
(SSI_CTRLR0_SPI_FRF_VALUE_DUAL /* Dual I/O mode */ \
<< SSI_CTRLR0_SPI_FRF_LSB) | \
(31 << SSI_CTRLR0_DFS_32_LSB) | /* 32 data bits */ \
(SSI_CTRLR0_TMOD_VALUE_EEPROM_READ /* Send INST/ADDR, Receive Data */ \
<< SSI_CTRLR0_TMOD_LSB)
ldr r1, =(CTRLR0_ENTER_XIP)
str r1, [r3, #SSI_CTRLR0_OFFSET]
mov r1, #0x0 // NDF=0 (single 32b read)
str r1, [r3, #SSI_CTRLR1_OFFSET]
#define SPI_CTRLR0_ENTER_XIP \
(7 << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Send 28 bits (24 address + 4 mode) */ \
(2 << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z the other 4 mode bits (2 cycles @ dual I/O = 4 bits) */ \
(SSI_SPI_CTRLR0_INST_L_VALUE_8B \
<< SSI_SPI_CTRLR0_INST_L_LSB) | /* 8-bit instruction */ \
(SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C2A /* Send Command in serial mode then address in Dual I/O mode */ \
<< SSI_SPI_CTRLR0_TRANS_TYPE_LSB)
ldr r1, =(SPI_CTRLR0_ENTER_XIP)
ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) // SPI_CTRL0 Register
str r1, [r0]
mov r1, #1 // Re-enable SSI
str r1, [r3, #SSI_SSIENR_OFFSET]
mov r1, #W25X10CL_CMD_READ_DATA_FAST_DUAL_IO // 8b command = 0xBB
str r1, [r3, #SSI_DR0_OFFSET] // Push SPI command into TX FIFO
mov r1, #0x0000002 // 28-bit Address for dummy read = 0x000000 + 0x2 Mode bits to set M[5:4]=10
str r1, [r3, #SSI_DR0_OFFSET] // Push Address into TX FIFO - this will trigger the transaction
// Now we wait for the read transaction to complete by monitoring the SSI
// status register and checking for the "RX FIFO Not Empty" flag to assert.
mov r1, #SSI_SR_RFNE_BITS
00:
ldr r0, [r3, #SSI_SR_OFFSET] // Read status register
tst r0, r1 // RFNE status flag set?
beq 00b // If not then wait
// At this point CN# will be deasserted and the SPI clock will not be running.
// The Winbond WX25X10CL device will be in continuous read, dual I/O mode and
// only expecting address bits after the next CN# assertion. So long as we
// send 4'b0010 (and 4 more dummy HiZ bits) after every subsequent 24b address
// then the Winbond device will remain in continuous read mode. This is the
// ideal mode for Execute-In-Place.
// (If we want to exit continuous read mode then we will need to switch back
// to APM mode and generate a 28-bit address phase with the extra nibble set
// to 4'b0000).
mov r1, #0
str r1, [r3, #SSI_SSIENR_OFFSET] // Disable SSI (and clear FIFO) to allow further config
// Note that the INST_L field is used to select what XIP data gets pushed into
// the TX FIFO:
// INST_L_0_BITS {ADDR[23:0],XIP_CMD[7:0]} Load "mode bits" into XIP_CMD
// Anything else {XIP_CMD[7:0],ADDR[23:0]} Load SPI command into XIP_CMD
#define SPI_CTRLR0_XIP \
(W25X10CL_MODE_CONTINUOUS_READ /* Mode bits to keep Winbond in continuous read mode */ \
<< SSI_SPI_CTRLR0_XIP_CMD_LSB) | \
(7 << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Send 28 bits (24 address + 4 mode) */ \
(2 << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z the other 4 mode bits (2 cycles @ dual I/O = 4 bits) */ \
(SSI_SPI_CTRLR0_INST_L_VALUE_NONE /* Do not send a command, instead send XIP_CMD as mode bits after address */ \
<< SSI_SPI_CTRLR0_INST_L_LSB) | \
(SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_2C2A /* Send Address in Dual I/O mode (and Command but that is zero bits long) */ \
<< SSI_SPI_CTRLR0_TRANS_TYPE_LSB)
ldr r1, =(SPI_CTRLR0_XIP)
ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET)
str r1, [r0]
mov r1, #1
str r1, [r3, #SSI_SSIENR_OFFSET] // Re-enable SSI
// We are now in XIP mode, with all transactions using Dual I/O and only
// needing to send 24-bit addresses (plus mode bits) for each read transaction.
// Pull in standard exit routine
#include "boot2_helpers/exit_from_boot2.S"
.global literals
literals:
.ltorg
.end

View File

@ -0,0 +1,13 @@
MEMORY {
/* We are loaded to the top 256 bytes of SRAM, which is above the bootrom
stack. Note 4 bytes occupied by checksum. */
SRAM(rx) : ORIGIN = 0x20041f00, LENGTH = 252
}
SECTIONS {
. = ORIGIN(SRAM);
.text : {
*(.entry)
*(.text)
} >SRAM
}

View File

@ -0,0 +1,19 @@
// ----------------------------------------------------------------------------
// Second stage boot code
// Copyright (c) 2019-2021 Raspberry Pi (Trading) Ltd.
// SPDX-License-Identifier: BSD-3-Clause
// ----------------------------------------------------------------------------
//
// This implementation uses the PICO_BOOT_STAGE2_CHOOSE_ preprocessor defines to pick
// amongst a menu of known boot stage 2 implementations, allowing the board
// configuration header to be able to specify the boot stage 2
#include "boot_stage2/config.h"
#ifdef PICO_BUILD_BOOT_STAGE2_NAME
// boot stage 2 is configured by cmake, so use the name specified there
#error PICO_BUILD_BOOT_STAGE2_NAME should not be defined for compile_time_choice builds
#else
// boot stage 2 is selected by board config header, and PICO_BOOT_STAGE2_ASM is set in boot_stage2/config.h
#include PICO_BOOT_STAGE2_ASM
#endif

92
cpu/rpx0xx/vendor/boot_stage2/config.h vendored Normal file
View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _BOOT_STAGE2_CONFIG_H_
#define _BOOT_STAGE2_CONFIG_H_
// NOTE THIS HEADER IS INCLUDED FROM ASSEMBLY
// PICO_CONFIG: PICO_BUILD_BOOT_STAGE2_NAME, The name of the boot stage 2 if selected by the build, group=boot_stage2
#ifdef PICO_BUILD_BOOT_STAGE2_NAME
#define _BOOT_STAGE2_SELECTED
#else
// check that multiple boot stage 2 options haven't been set...
// PICO_CONFIG: PICO_BOOT_STAGE2_CHOOSE_IS25LP080, Select boot2_is25lp080 as the boot stage 2 when no boot stage 2 selection is made by the CMake build, type=bool, default=0, group=boot_stage2
#ifndef PICO_BOOT_STAGE2_CHOOSE_IS25LP080
#define PICO_BOOT_STAGE2_CHOOSE_IS25LP080 0
#elif PICO_BOOT_STAGE2_CHOOSE_IS25LP080
#ifdef _BOOT_STAGE2_SELECTED
#error multiple boot stage 2 options chosen
#endif
#define _BOOT_STAGE2_SELECTED
#endif
// PICO_CONFIG: PICO_BOOT_STAGE2_CHOOSE_W25Q080, Select boot2_w25q080 as the boot stage 2 when no boot stage 2 selection is made by the CMake build, type=bool, default=0, group=boot_stage2
#ifndef PICO_BOOT_STAGE2_CHOOSE_W25Q080
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 0
#elif PICO_BOOT_STAGE2_CHOOSE_W25Q080
#ifdef _BOOT_STAGE2_SELECTED
#error multiple boot stage 2 options chosen
#endif
#define _BOOT_STAGE2_SELECTED
#endif
// PICO_CONFIG: PICO_BOOT_STAGE2_CHOOSE_W25X10CL, Select boot2_w25x10cl as the boot stage 2 when no boot stage 2 selection is made by the CMake build, type=bool, default=0, group=boot_stage2
#ifndef PICO_BOOT_STAGE2_CHOOSE_W25X10CL
#define PICO_BOOT_STAGE2_CHOOSE_W25X10CL 0
#elif PICO_BOOT_STAGE2_CHOOSE_W25X10CL
#ifdef _BOOT_STAGE2_SELECTED
#error multiple boot stage 2 options chosen
#endif
#define _BOOT_STAGE2_SELECTED
#endif
// PICO_CONFIG: PICO_BOOT_STAGE2_CHOOSE_AT25SF128A, Select boot2_at25sf128a as the boot stage 2 when no boot stage 2 selection is made by the CMake build, type=bool, default=0, group=boot_stage2
#ifndef PICO_BOOT_STAGE2_CHOOSE_AT25SF128A
#define PICO_BOOT_STAGE2_CHOOSE_AT25SF128A 0
#elif PICO_BOOT_STAGE2_CHOOSE_AT25SF128A
#ifdef _BOOT_STAGE2_SELECTED
#error multiple boot stage 2 options chosen
#endif
#define _BOOT_STAGE2_SELECTED
#endif
// PICO_CONFIG: PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H, Select boot2_generic_03h as the boot stage 2 when no boot stage 2 selection is made by the CMake build, type=bool, default=1, group=boot_stage2
#if defined(PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H) && PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H
#ifdef _BOOT_STAGE2_SELECTED
#error multiple boot stage 2 options chosen
#endif
#define _BOOT_STAGE2_SELECTED
#endif
#endif // PICO_BUILD_BOOT_STAGE2_NAME
#ifdef PICO_BUILD_BOOT_STAGE2_NAME
// boot stage 2 is configured by cmake, so use the name specified there
#define PICO_BOOT_STAGE2_NAME PICO_BUILD_BOOT_STAGE2_NAME
#else
// boot stage 2 is selected by board config header, so we have to do some work
#if PICO_BOOT_STAGE2_CHOOSE_IS25LP080
#define _BOOT_STAGE2 boot2_is25lp080
#elif PICO_BOOT_STAGE2_CHOOSE_W25Q080
#define _BOOT_STAGE2 boot2_w25q080
#elif PICO_BOOT_STAGE2_CHOOSE_W25X10CL
#define _BOOT_STAGE2 boot2_w25x10cl
#elif PICO_BOOT_STAGE2_CHOOSE_AT25SF128A
#define _BOOT_STAGE2 boot2_at25sf128a
#elif !defined(PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H) || PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H
#undef PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H
#define PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H 1
#define _BOOT_STAGE2 boot2_generic_03h
#else
#error no boot stage 2 is defined by PICO_BOOT_STAGE2_CHOOSE_ macro
#endif
// we can't include cdefs in assembly, so define our own, but avoid conflict with real ones for c inclusion
#define _PICO__STRING(x) #x
#define _PICO__XSTRING(x) _PICO__STRING(x)
#define _PICO__CONCAT1(x, y) x ## y
#define PICO_BOOT_STAGE2_NAME _PICO__XSTRING(_BOOT_STAGE2)
#define PICO_BOOT_STAGE2_ASM _PICO__XSTRING(_PICO__CONCAT1(_BOOT_STAGE2,.S))
#endif
#endif

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _BOOT2_HELPER_EXIT_FROM_BOOT2
#define _BOOT2_HELPER_EXIT_FROM_BOOT2
#include "hardware/regs/m0plus.h"
// If entered from the bootrom, lr (which we earlier pushed) will be 0,
// and we vector through the table at the start of the main flash image.
// Any regular function call will have a nonzero value for lr.
check_return:
pop {r0}
cmp r0, #0
beq vector_into_flash
bx r0
vector_into_flash:
ldr r0, =(XIP_BASE + 0x100)
ldr r1, =(PPB_BASE + M0PLUS_VTOR_OFFSET)
str r0, [r1]
ldmia r0, {r0, r1}
msr msp, r0
bx r1
#endif

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _BOOT2_HELPER_READ_FLASH_SREG
#define _BOOT2_HELPER_READ_FLASH_SREG
#include "boot2_helpers/wait_ssi_ready.S"
// Pass status read cmd into r0.
// Returns status value in r0.
.global read_flash_sreg
.type read_flash_sreg,%function
.thumb_func
read_flash_sreg:
push {r1, lr}
str r0, [r3, #SSI_DR0_OFFSET]
// Dummy byte:
str r0, [r3, #SSI_DR0_OFFSET]
bl wait_ssi_ready
// Discard first byte and combine the next two
ldr r0, [r3, #SSI_DR0_OFFSET]
ldr r0, [r3, #SSI_DR0_OFFSET]
pop {r1, pc}
#endif

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _BOOT2_HELPER_WAIT_SSI_READY
#define _BOOT2_HELPER_WAIT_SSI_READY
wait_ssi_ready:
push {r0, r1, lr}
// Command is complete when there is nothing left to send
// (TX FIFO empty) and SSI is no longer busy (CSn deasserted)
1:
ldr r1, [r3, #SSI_SR_OFFSET]
movs r0, #SSI_SR_TFE_BITS
tst r1, r0
beq 1b
movs r0, #SSI_SR_BUSY_BITS
tst r1, r0
bne 1b
pop {r0, r1, pc}
#endif

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _HARDWARE_PLATFORM_DEFS_H
#define _HARDWARE_PLATFORM_DEFS_H
// This header is included from C and assembler - only define macros
#ifndef _u
#ifdef __ASSEMBLER__
#define _u(x) x
#else
#define _u(x) x ## u
#endif
#endif
#define NUM_CORES _u(2)
#define NUM_DMA_CHANNELS _u(12)
#define NUM_IRQS _u(32)
#define NUM_PIOS _u(2)
#define NUM_PIO_STATE_MACHINES _u(4)
#define NUM_PWM_SLICES _u(8)
#define NUM_SPIN_LOCKS _u(32)
#define NUM_UARTS _u(2)
#define NUM_I2CS _u(2)
#define NUM_SPIS _u(2)
#define NUM_ADC_CHANNELS _u(5)
#define NUM_BANK0_GPIOS _u(30)
#define PIO_INSTRUCTION_COUNT _u(32)
#define XOSC_MHZ _u(12)
// PICO_CONFIG: PICO_STACK_SIZE, Stack Size, min=0x100, default=0x800, advanced=true, group=pico_standard_link
#ifndef PICO_STACK_SIZE
#define PICO_STACK_SIZE _u(0x800)
#endif
// PICO_CONFIG: PICO_HEAP_SIZE, Heap size to reserve, min=0x100, default=0x800, advanced=true, group=pico_standard_link
#ifndef PICO_HEAP_SIZE
#define PICO_HEAP_SIZE _u(0x800)
#endif
// PICO_CONFIG: PICO_NO_RAM_VECTOR_TABLE, Enable/disable the RAM vector table, type=bool, default=0, advanced=true, group=pico_runtime
#ifndef PICO_NO_RAM_VECTOR_TABLE
#define PICO_NO_RAM_VECTOR_TABLE 0
#endif
#endif

View File

@ -0,0 +1,74 @@
/**
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _ADDRESSMAP_H_
#define _ADDRESSMAP_H_
#include "hardware/platform_defs.h"
// Register address offsets for atomic RMW aliases
#define REG_ALIAS_RW_BITS (0x0u << 12u)
#define REG_ALIAS_XOR_BITS (0x1u << 12u)
#define REG_ALIAS_SET_BITS (0x2u << 12u)
#define REG_ALIAS_CLR_BITS (0x3u << 12u)
#define ROM_BASE _u(0x00000000)
#define XIP_BASE _u(0x10000000)
#define XIP_MAIN_BASE _u(0x10000000)
#define XIP_NOALLOC_BASE _u(0x11000000)
#define XIP_NOCACHE_BASE _u(0x12000000)
#define XIP_NOCACHE_NOALLOC_BASE _u(0x13000000)
#define XIP_CTRL_BASE _u(0x14000000)
#define XIP_SRAM_BASE _u(0x15000000)
#define XIP_SRAM_END _u(0x15004000)
#define XIP_SSI_BASE _u(0x18000000)
#define SRAM_BASE _u(0x20000000)
#define SRAM_STRIPED_BASE _u(0x20000000)
#define SRAM_STRIPED_END _u(0x20040000)
#define SRAM4_BASE _u(0x20040000)
#define SRAM5_BASE _u(0x20041000)
#define SRAM_END _u(0x20042000)
#define SRAM0_BASE _u(0x21000000)
#define SRAM1_BASE _u(0x21010000)
#define SRAM2_BASE _u(0x21020000)
#define SRAM3_BASE _u(0x21030000)
#define SYSINFO_BASE _u(0x40000000)
#define SYSCFG_BASE _u(0x40004000)
#define CLOCKS_BASE _u(0x40008000)
#define RESETS_BASE _u(0x4000c000)
#define PSM_BASE _u(0x40010000)
#define IO_BANK0_BASE _u(0x40014000)
#define IO_QSPI_BASE _u(0x40018000)
#define PADS_BANK0_BASE _u(0x4001c000)
#define PADS_QSPI_BASE _u(0x40020000)
#define XOSC_BASE _u(0x40024000)
#define PLL_SYS_BASE _u(0x40028000)
#define PLL_USB_BASE _u(0x4002c000)
#define BUSCTRL_BASE _u(0x40030000)
#define UART0_BASE _u(0x40034000)
#define UART1_BASE _u(0x40038000)
#define SPI0_BASE _u(0x4003c000)
#define SPI1_BASE _u(0x40040000)
#define I2C0_BASE _u(0x40044000)
#define I2C1_BASE _u(0x40048000)
#define ADC_BASE _u(0x4004c000)
#define PWM_BASE _u(0x40050000)
#define TIMER_BASE _u(0x40054000)
#define WATCHDOG_BASE _u(0x40058000)
#define RTC_BASE _u(0x4005c000)
#define ROSC_BASE _u(0x40060000)
#define VREG_AND_CHIP_RESET_BASE _u(0x40064000)
#define TBMAN_BASE _u(0x4006c000)
#define DMA_BASE _u(0x50000000)
#define USBCTRL_DPRAM_BASE _u(0x50100000)
#define USBCTRL_BASE _u(0x50100000)
#define USBCTRL_REGS_BASE _u(0x50110000)
#define PIO0_BASE _u(0x50200000)
#define PIO1_BASE _u(0x50300000)
#define XIP_AUX_BASE _u(0x50400000)
#define SIO_BASE _u(0xd0000000)
#define PPB_BASE _u(0xe0000000)
#endif // _ADDRESSMAP_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,454 @@
/**
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
// =============================================================================
// Register block : PADS_QSPI
// Version : 1
// Bus type : apb
// Description : None
// =============================================================================
#ifndef HARDWARE_REGS_PADS_QSPI_DEFINED
#define HARDWARE_REGS_PADS_QSPI_DEFINED
// =============================================================================
// Register : PADS_QSPI_VOLTAGE_SELECT
// Description : Voltage select. Per bank control
// 0x0 -> Set voltage to 3.3V (DVDD >= 2V5)
// 0x1 -> Set voltage to 1.8V (DVDD <= 1V8)
#define PADS_QSPI_VOLTAGE_SELECT_OFFSET _u(0x00000000)
#define PADS_QSPI_VOLTAGE_SELECT_BITS _u(0x00000001)
#define PADS_QSPI_VOLTAGE_SELECT_RESET _u(0x00000000)
#define PADS_QSPI_VOLTAGE_SELECT_MSB _u(0)
#define PADS_QSPI_VOLTAGE_SELECT_LSB _u(0)
#define PADS_QSPI_VOLTAGE_SELECT_ACCESS "RW"
#define PADS_QSPI_VOLTAGE_SELECT_VALUE_3V3 _u(0x0)
#define PADS_QSPI_VOLTAGE_SELECT_VALUE_1V8 _u(0x1)
// =============================================================================
// Register : PADS_QSPI_GPIO_QSPI_SCLK
// Description : Pad control register
#define PADS_QSPI_GPIO_QSPI_SCLK_OFFSET _u(0x00000004)
#define PADS_QSPI_GPIO_QSPI_SCLK_BITS _u(0x000000ff)
#define PADS_QSPI_GPIO_QSPI_SCLK_RESET _u(0x00000056)
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SCLK_OD
// Description : Output disable. Has priority over output enable from
// peripherals
#define PADS_QSPI_GPIO_QSPI_SCLK_OD_RESET _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SCLK_OD_BITS _u(0x00000080)
#define PADS_QSPI_GPIO_QSPI_SCLK_OD_MSB _u(7)
#define PADS_QSPI_GPIO_QSPI_SCLK_OD_LSB _u(7)
#define PADS_QSPI_GPIO_QSPI_SCLK_OD_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SCLK_IE
// Description : Input enable
#define PADS_QSPI_GPIO_QSPI_SCLK_IE_RESET _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SCLK_IE_BITS _u(0x00000040)
#define PADS_QSPI_GPIO_QSPI_SCLK_IE_MSB _u(6)
#define PADS_QSPI_GPIO_QSPI_SCLK_IE_LSB _u(6)
#define PADS_QSPI_GPIO_QSPI_SCLK_IE_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SCLK_DRIVE
// Description : Drive strength.
// 0x0 -> 2mA
// 0x1 -> 4mA
// 0x2 -> 8mA
// 0x3 -> 12mA
#define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_RESET _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_BITS _u(0x00000030)
#define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_MSB _u(5)
#define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_LSB _u(4)
#define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_ACCESS "RW"
#define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_VALUE_2MA _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_VALUE_4MA _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_VALUE_8MA _u(0x2)
#define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_VALUE_12MA _u(0x3)
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SCLK_PUE
// Description : Pull up enable
#define PADS_QSPI_GPIO_QSPI_SCLK_PUE_RESET _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SCLK_PUE_BITS _u(0x00000008)
#define PADS_QSPI_GPIO_QSPI_SCLK_PUE_MSB _u(3)
#define PADS_QSPI_GPIO_QSPI_SCLK_PUE_LSB _u(3)
#define PADS_QSPI_GPIO_QSPI_SCLK_PUE_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SCLK_PDE
// Description : Pull down enable
#define PADS_QSPI_GPIO_QSPI_SCLK_PDE_RESET _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SCLK_PDE_BITS _u(0x00000004)
#define PADS_QSPI_GPIO_QSPI_SCLK_PDE_MSB _u(2)
#define PADS_QSPI_GPIO_QSPI_SCLK_PDE_LSB _u(2)
#define PADS_QSPI_GPIO_QSPI_SCLK_PDE_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SCLK_SCHMITT
// Description : Enable schmitt trigger
#define PADS_QSPI_GPIO_QSPI_SCLK_SCHMITT_RESET _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SCLK_SCHMITT_BITS _u(0x00000002)
#define PADS_QSPI_GPIO_QSPI_SCLK_SCHMITT_MSB _u(1)
#define PADS_QSPI_GPIO_QSPI_SCLK_SCHMITT_LSB _u(1)
#define PADS_QSPI_GPIO_QSPI_SCLK_SCHMITT_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST
// Description : Slew rate control. 1 = Fast, 0 = Slow
#define PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_RESET _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_BITS _u(0x00000001)
#define PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_MSB _u(0)
#define PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_LSB _u(0)
#define PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_ACCESS "RW"
// =============================================================================
// Register : PADS_QSPI_GPIO_QSPI_SD0
// Description : Pad control register
#define PADS_QSPI_GPIO_QSPI_SD0_OFFSET _u(0x00000008)
#define PADS_QSPI_GPIO_QSPI_SD0_BITS _u(0x000000ff)
#define PADS_QSPI_GPIO_QSPI_SD0_RESET _u(0x00000052)
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD0_OD
// Description : Output disable. Has priority over output enable from
// peripherals
#define PADS_QSPI_GPIO_QSPI_SD0_OD_RESET _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SD0_OD_BITS _u(0x00000080)
#define PADS_QSPI_GPIO_QSPI_SD0_OD_MSB _u(7)
#define PADS_QSPI_GPIO_QSPI_SD0_OD_LSB _u(7)
#define PADS_QSPI_GPIO_QSPI_SD0_OD_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD0_IE
// Description : Input enable
#define PADS_QSPI_GPIO_QSPI_SD0_IE_RESET _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SD0_IE_BITS _u(0x00000040)
#define PADS_QSPI_GPIO_QSPI_SD0_IE_MSB _u(6)
#define PADS_QSPI_GPIO_QSPI_SD0_IE_LSB _u(6)
#define PADS_QSPI_GPIO_QSPI_SD0_IE_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD0_DRIVE
// Description : Drive strength.
// 0x0 -> 2mA
// 0x1 -> 4mA
// 0x2 -> 8mA
// 0x3 -> 12mA
#define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_RESET _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_BITS _u(0x00000030)
#define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_MSB _u(5)
#define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_LSB _u(4)
#define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_ACCESS "RW"
#define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_VALUE_2MA _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_VALUE_4MA _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_VALUE_8MA _u(0x2)
#define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_VALUE_12MA _u(0x3)
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD0_PUE
// Description : Pull up enable
#define PADS_QSPI_GPIO_QSPI_SD0_PUE_RESET _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SD0_PUE_BITS _u(0x00000008)
#define PADS_QSPI_GPIO_QSPI_SD0_PUE_MSB _u(3)
#define PADS_QSPI_GPIO_QSPI_SD0_PUE_LSB _u(3)
#define PADS_QSPI_GPIO_QSPI_SD0_PUE_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD0_PDE
// Description : Pull down enable
#define PADS_QSPI_GPIO_QSPI_SD0_PDE_RESET _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SD0_PDE_BITS _u(0x00000004)
#define PADS_QSPI_GPIO_QSPI_SD0_PDE_MSB _u(2)
#define PADS_QSPI_GPIO_QSPI_SD0_PDE_LSB _u(2)
#define PADS_QSPI_GPIO_QSPI_SD0_PDE_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD0_SCHMITT
// Description : Enable schmitt trigger
#define PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_RESET _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_BITS _u(0x00000002)
#define PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_MSB _u(1)
#define PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_LSB _u(1)
#define PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD0_SLEWFAST
// Description : Slew rate control. 1 = Fast, 0 = Slow
#define PADS_QSPI_GPIO_QSPI_SD0_SLEWFAST_RESET _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SD0_SLEWFAST_BITS _u(0x00000001)
#define PADS_QSPI_GPIO_QSPI_SD0_SLEWFAST_MSB _u(0)
#define PADS_QSPI_GPIO_QSPI_SD0_SLEWFAST_LSB _u(0)
#define PADS_QSPI_GPIO_QSPI_SD0_SLEWFAST_ACCESS "RW"
// =============================================================================
// Register : PADS_QSPI_GPIO_QSPI_SD1
// Description : Pad control register
#define PADS_QSPI_GPIO_QSPI_SD1_OFFSET _u(0x0000000c)
#define PADS_QSPI_GPIO_QSPI_SD1_BITS _u(0x000000ff)
#define PADS_QSPI_GPIO_QSPI_SD1_RESET _u(0x00000052)
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD1_OD
// Description : Output disable. Has priority over output enable from
// peripherals
#define PADS_QSPI_GPIO_QSPI_SD1_OD_RESET _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SD1_OD_BITS _u(0x00000080)
#define PADS_QSPI_GPIO_QSPI_SD1_OD_MSB _u(7)
#define PADS_QSPI_GPIO_QSPI_SD1_OD_LSB _u(7)
#define PADS_QSPI_GPIO_QSPI_SD1_OD_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD1_IE
// Description : Input enable
#define PADS_QSPI_GPIO_QSPI_SD1_IE_RESET _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SD1_IE_BITS _u(0x00000040)
#define PADS_QSPI_GPIO_QSPI_SD1_IE_MSB _u(6)
#define PADS_QSPI_GPIO_QSPI_SD1_IE_LSB _u(6)
#define PADS_QSPI_GPIO_QSPI_SD1_IE_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD1_DRIVE
// Description : Drive strength.
// 0x0 -> 2mA
// 0x1 -> 4mA
// 0x2 -> 8mA
// 0x3 -> 12mA
#define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_RESET _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_BITS _u(0x00000030)
#define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_MSB _u(5)
#define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_LSB _u(4)
#define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_ACCESS "RW"
#define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_VALUE_2MA _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_VALUE_4MA _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_VALUE_8MA _u(0x2)
#define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_VALUE_12MA _u(0x3)
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD1_PUE
// Description : Pull up enable
#define PADS_QSPI_GPIO_QSPI_SD1_PUE_RESET _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SD1_PUE_BITS _u(0x00000008)
#define PADS_QSPI_GPIO_QSPI_SD1_PUE_MSB _u(3)
#define PADS_QSPI_GPIO_QSPI_SD1_PUE_LSB _u(3)
#define PADS_QSPI_GPIO_QSPI_SD1_PUE_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD1_PDE
// Description : Pull down enable
#define PADS_QSPI_GPIO_QSPI_SD1_PDE_RESET _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SD1_PDE_BITS _u(0x00000004)
#define PADS_QSPI_GPIO_QSPI_SD1_PDE_MSB _u(2)
#define PADS_QSPI_GPIO_QSPI_SD1_PDE_LSB _u(2)
#define PADS_QSPI_GPIO_QSPI_SD1_PDE_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD1_SCHMITT
// Description : Enable schmitt trigger
#define PADS_QSPI_GPIO_QSPI_SD1_SCHMITT_RESET _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SD1_SCHMITT_BITS _u(0x00000002)
#define PADS_QSPI_GPIO_QSPI_SD1_SCHMITT_MSB _u(1)
#define PADS_QSPI_GPIO_QSPI_SD1_SCHMITT_LSB _u(1)
#define PADS_QSPI_GPIO_QSPI_SD1_SCHMITT_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD1_SLEWFAST
// Description : Slew rate control. 1 = Fast, 0 = Slow
#define PADS_QSPI_GPIO_QSPI_SD1_SLEWFAST_RESET _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SD1_SLEWFAST_BITS _u(0x00000001)
#define PADS_QSPI_GPIO_QSPI_SD1_SLEWFAST_MSB _u(0)
#define PADS_QSPI_GPIO_QSPI_SD1_SLEWFAST_LSB _u(0)
#define PADS_QSPI_GPIO_QSPI_SD1_SLEWFAST_ACCESS "RW"
// =============================================================================
// Register : PADS_QSPI_GPIO_QSPI_SD2
// Description : Pad control register
#define PADS_QSPI_GPIO_QSPI_SD2_OFFSET _u(0x00000010)
#define PADS_QSPI_GPIO_QSPI_SD2_BITS _u(0x000000ff)
#define PADS_QSPI_GPIO_QSPI_SD2_RESET _u(0x00000052)
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD2_OD
// Description : Output disable. Has priority over output enable from
// peripherals
#define PADS_QSPI_GPIO_QSPI_SD2_OD_RESET _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SD2_OD_BITS _u(0x00000080)
#define PADS_QSPI_GPIO_QSPI_SD2_OD_MSB _u(7)
#define PADS_QSPI_GPIO_QSPI_SD2_OD_LSB _u(7)
#define PADS_QSPI_GPIO_QSPI_SD2_OD_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD2_IE
// Description : Input enable
#define PADS_QSPI_GPIO_QSPI_SD2_IE_RESET _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SD2_IE_BITS _u(0x00000040)
#define PADS_QSPI_GPIO_QSPI_SD2_IE_MSB _u(6)
#define PADS_QSPI_GPIO_QSPI_SD2_IE_LSB _u(6)
#define PADS_QSPI_GPIO_QSPI_SD2_IE_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD2_DRIVE
// Description : Drive strength.
// 0x0 -> 2mA
// 0x1 -> 4mA
// 0x2 -> 8mA
// 0x3 -> 12mA
#define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_RESET _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_BITS _u(0x00000030)
#define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_MSB _u(5)
#define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_LSB _u(4)
#define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_ACCESS "RW"
#define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_VALUE_2MA _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_VALUE_4MA _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_VALUE_8MA _u(0x2)
#define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_VALUE_12MA _u(0x3)
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD2_PUE
// Description : Pull up enable
#define PADS_QSPI_GPIO_QSPI_SD2_PUE_RESET _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SD2_PUE_BITS _u(0x00000008)
#define PADS_QSPI_GPIO_QSPI_SD2_PUE_MSB _u(3)
#define PADS_QSPI_GPIO_QSPI_SD2_PUE_LSB _u(3)
#define PADS_QSPI_GPIO_QSPI_SD2_PUE_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD2_PDE
// Description : Pull down enable
#define PADS_QSPI_GPIO_QSPI_SD2_PDE_RESET _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SD2_PDE_BITS _u(0x00000004)
#define PADS_QSPI_GPIO_QSPI_SD2_PDE_MSB _u(2)
#define PADS_QSPI_GPIO_QSPI_SD2_PDE_LSB _u(2)
#define PADS_QSPI_GPIO_QSPI_SD2_PDE_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD2_SCHMITT
// Description : Enable schmitt trigger
#define PADS_QSPI_GPIO_QSPI_SD2_SCHMITT_RESET _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SD2_SCHMITT_BITS _u(0x00000002)
#define PADS_QSPI_GPIO_QSPI_SD2_SCHMITT_MSB _u(1)
#define PADS_QSPI_GPIO_QSPI_SD2_SCHMITT_LSB _u(1)
#define PADS_QSPI_GPIO_QSPI_SD2_SCHMITT_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD2_SLEWFAST
// Description : Slew rate control. 1 = Fast, 0 = Slow
#define PADS_QSPI_GPIO_QSPI_SD2_SLEWFAST_RESET _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SD2_SLEWFAST_BITS _u(0x00000001)
#define PADS_QSPI_GPIO_QSPI_SD2_SLEWFAST_MSB _u(0)
#define PADS_QSPI_GPIO_QSPI_SD2_SLEWFAST_LSB _u(0)
#define PADS_QSPI_GPIO_QSPI_SD2_SLEWFAST_ACCESS "RW"
// =============================================================================
// Register : PADS_QSPI_GPIO_QSPI_SD3
// Description : Pad control register
#define PADS_QSPI_GPIO_QSPI_SD3_OFFSET _u(0x00000014)
#define PADS_QSPI_GPIO_QSPI_SD3_BITS _u(0x000000ff)
#define PADS_QSPI_GPIO_QSPI_SD3_RESET _u(0x00000052)
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD3_OD
// Description : Output disable. Has priority over output enable from
// peripherals
#define PADS_QSPI_GPIO_QSPI_SD3_OD_RESET _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SD3_OD_BITS _u(0x00000080)
#define PADS_QSPI_GPIO_QSPI_SD3_OD_MSB _u(7)
#define PADS_QSPI_GPIO_QSPI_SD3_OD_LSB _u(7)
#define PADS_QSPI_GPIO_QSPI_SD3_OD_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD3_IE
// Description : Input enable
#define PADS_QSPI_GPIO_QSPI_SD3_IE_RESET _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SD3_IE_BITS _u(0x00000040)
#define PADS_QSPI_GPIO_QSPI_SD3_IE_MSB _u(6)
#define PADS_QSPI_GPIO_QSPI_SD3_IE_LSB _u(6)
#define PADS_QSPI_GPIO_QSPI_SD3_IE_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD3_DRIVE
// Description : Drive strength.
// 0x0 -> 2mA
// 0x1 -> 4mA
// 0x2 -> 8mA
// 0x3 -> 12mA
#define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_RESET _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_BITS _u(0x00000030)
#define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_MSB _u(5)
#define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_LSB _u(4)
#define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_ACCESS "RW"
#define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_VALUE_2MA _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_VALUE_4MA _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_VALUE_8MA _u(0x2)
#define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_VALUE_12MA _u(0x3)
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD3_PUE
// Description : Pull up enable
#define PADS_QSPI_GPIO_QSPI_SD3_PUE_RESET _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SD3_PUE_BITS _u(0x00000008)
#define PADS_QSPI_GPIO_QSPI_SD3_PUE_MSB _u(3)
#define PADS_QSPI_GPIO_QSPI_SD3_PUE_LSB _u(3)
#define PADS_QSPI_GPIO_QSPI_SD3_PUE_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD3_PDE
// Description : Pull down enable
#define PADS_QSPI_GPIO_QSPI_SD3_PDE_RESET _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SD3_PDE_BITS _u(0x00000004)
#define PADS_QSPI_GPIO_QSPI_SD3_PDE_MSB _u(2)
#define PADS_QSPI_GPIO_QSPI_SD3_PDE_LSB _u(2)
#define PADS_QSPI_GPIO_QSPI_SD3_PDE_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD3_SCHMITT
// Description : Enable schmitt trigger
#define PADS_QSPI_GPIO_QSPI_SD3_SCHMITT_RESET _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SD3_SCHMITT_BITS _u(0x00000002)
#define PADS_QSPI_GPIO_QSPI_SD3_SCHMITT_MSB _u(1)
#define PADS_QSPI_GPIO_QSPI_SD3_SCHMITT_LSB _u(1)
#define PADS_QSPI_GPIO_QSPI_SD3_SCHMITT_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SD3_SLEWFAST
// Description : Slew rate control. 1 = Fast, 0 = Slow
#define PADS_QSPI_GPIO_QSPI_SD3_SLEWFAST_RESET _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SD3_SLEWFAST_BITS _u(0x00000001)
#define PADS_QSPI_GPIO_QSPI_SD3_SLEWFAST_MSB _u(0)
#define PADS_QSPI_GPIO_QSPI_SD3_SLEWFAST_LSB _u(0)
#define PADS_QSPI_GPIO_QSPI_SD3_SLEWFAST_ACCESS "RW"
// =============================================================================
// Register : PADS_QSPI_GPIO_QSPI_SS
// Description : Pad control register
#define PADS_QSPI_GPIO_QSPI_SS_OFFSET _u(0x00000018)
#define PADS_QSPI_GPIO_QSPI_SS_BITS _u(0x000000ff)
#define PADS_QSPI_GPIO_QSPI_SS_RESET _u(0x0000005a)
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SS_OD
// Description : Output disable. Has priority over output enable from
// peripherals
#define PADS_QSPI_GPIO_QSPI_SS_OD_RESET _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SS_OD_BITS _u(0x00000080)
#define PADS_QSPI_GPIO_QSPI_SS_OD_MSB _u(7)
#define PADS_QSPI_GPIO_QSPI_SS_OD_LSB _u(7)
#define PADS_QSPI_GPIO_QSPI_SS_OD_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SS_IE
// Description : Input enable
#define PADS_QSPI_GPIO_QSPI_SS_IE_RESET _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SS_IE_BITS _u(0x00000040)
#define PADS_QSPI_GPIO_QSPI_SS_IE_MSB _u(6)
#define PADS_QSPI_GPIO_QSPI_SS_IE_LSB _u(6)
#define PADS_QSPI_GPIO_QSPI_SS_IE_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SS_DRIVE
// Description : Drive strength.
// 0x0 -> 2mA
// 0x1 -> 4mA
// 0x2 -> 8mA
// 0x3 -> 12mA
#define PADS_QSPI_GPIO_QSPI_SS_DRIVE_RESET _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SS_DRIVE_BITS _u(0x00000030)
#define PADS_QSPI_GPIO_QSPI_SS_DRIVE_MSB _u(5)
#define PADS_QSPI_GPIO_QSPI_SS_DRIVE_LSB _u(4)
#define PADS_QSPI_GPIO_QSPI_SS_DRIVE_ACCESS "RW"
#define PADS_QSPI_GPIO_QSPI_SS_DRIVE_VALUE_2MA _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SS_DRIVE_VALUE_4MA _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SS_DRIVE_VALUE_8MA _u(0x2)
#define PADS_QSPI_GPIO_QSPI_SS_DRIVE_VALUE_12MA _u(0x3)
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SS_PUE
// Description : Pull up enable
#define PADS_QSPI_GPIO_QSPI_SS_PUE_RESET _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SS_PUE_BITS _u(0x00000008)
#define PADS_QSPI_GPIO_QSPI_SS_PUE_MSB _u(3)
#define PADS_QSPI_GPIO_QSPI_SS_PUE_LSB _u(3)
#define PADS_QSPI_GPIO_QSPI_SS_PUE_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SS_PDE
// Description : Pull down enable
#define PADS_QSPI_GPIO_QSPI_SS_PDE_RESET _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SS_PDE_BITS _u(0x00000004)
#define PADS_QSPI_GPIO_QSPI_SS_PDE_MSB _u(2)
#define PADS_QSPI_GPIO_QSPI_SS_PDE_LSB _u(2)
#define PADS_QSPI_GPIO_QSPI_SS_PDE_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SS_SCHMITT
// Description : Enable schmitt trigger
#define PADS_QSPI_GPIO_QSPI_SS_SCHMITT_RESET _u(0x1)
#define PADS_QSPI_GPIO_QSPI_SS_SCHMITT_BITS _u(0x00000002)
#define PADS_QSPI_GPIO_QSPI_SS_SCHMITT_MSB _u(1)
#define PADS_QSPI_GPIO_QSPI_SS_SCHMITT_LSB _u(1)
#define PADS_QSPI_GPIO_QSPI_SS_SCHMITT_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : PADS_QSPI_GPIO_QSPI_SS_SLEWFAST
// Description : Slew rate control. 1 = Fast, 0 = Slow
#define PADS_QSPI_GPIO_QSPI_SS_SLEWFAST_RESET _u(0x0)
#define PADS_QSPI_GPIO_QSPI_SS_SLEWFAST_BITS _u(0x00000001)
#define PADS_QSPI_GPIO_QSPI_SS_SLEWFAST_MSB _u(0)
#define PADS_QSPI_GPIO_QSPI_SS_SLEWFAST_LSB _u(0)
#define PADS_QSPI_GPIO_QSPI_SS_SLEWFAST_ACCESS "RW"
// =============================================================================
#endif // HARDWARE_REGS_PADS_QSPI_DEFINED

View File

@ -0,0 +1,809 @@
/**
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
// =============================================================================
// Register block : SSI
// Version : 1
// Bus type : apb
// Description : DW_apb_ssi has the following features:
// * APB interface Allows for easy integration into a
// DesignWare Synthesizable Components for AMBA 2
// implementation.
// * APB3 and APB4 protocol support.
// * Scalable APB data bus width Supports APB data bus widths
// of 8, 16, and 32 bits.
// * Serial-master or serial-slave operation Enables serial
// communication with serial-master or serial-slave peripheral
// devices.
// * Programmable Dual/Quad/Octal SPI support in Master Mode.
// * Dual Data Rate (DDR) and Read Data Strobe (RDS) Support -
// Enables the DW_apb_ssi master to perform operations with the
// device in DDR and RDS modes when working in Dual/Quad/Octal
// mode of operation.
// * Data Mask Support - Enables the DW_apb_ssi to selectively
// update the bytes in the device. This feature is applicable
// only in enhanced SPI modes.
// * eXecute-In-Place (XIP) support - Enables the DW_apb_ssi
// master to behave as a memory mapped I/O and fetches the data
// from the device based on the APB read request. This feature
// is applicable only in enhanced SPI modes.
// * DMA Controller Interface Enables the DW_apb_ssi to
// interface to a DMA controller over the bus using a
// handshaking interface for transfer requests.
// * Independent masking of interrupts Master collision,
// transmit FIFO overflow, transmit FIFO empty, receive FIFO
// full, receive FIFO underflow, and receive FIFO overflow
// interrupts can all be masked independently.
// * Multi-master contention detection Informs the processor
// of multiple serial-master accesses on the serial bus.
// * Bypass of meta-stability flip-flops for synchronous clocks
// When the APB clock (pclk) and the DW_apb_ssi serial clock
// (ssi_clk) are synchronous, meta-stable flip-flops are not
// used when transferring control signals across these clock
// domains.
// * Programmable delay on the sample time of the received
// serial data bit (rxd); enables programmable control of
// routing delays resulting in higher serial data-bit rates.
// * Programmable features:
// - Serial interface operation Choice of Motorola SPI, Texas
// Instruments Synchronous Serial Protocol or National
// Semiconductor Microwire.
// - Clock bit-rate Dynamic control of the serial bit rate of
// the data transfer; used in only serial-master mode of
// operation.
// - Data Item size (4 to 32 bits) Item size of each data
// transfer under the control of the programmer.
// * Configured features:
// - FIFO depth 16 words deep. The FIFO width is fixed at 32
// bits.
// - 1 slave select output.
// - Hardware slave-select Dedicated hardware slave-select
// line.
// - Combined interrupt line - one combined interrupt line from
// the DW_apb_ssi to the interrupt controller.
// - Interrupt polarity active high interrupt lines.
// - Serial clock polarity low serial-clock polarity directly
// after reset.
// - Serial clock phase capture on first edge of serial-clock
// directly after reset.
// =============================================================================
#ifndef HARDWARE_REGS_SSI_DEFINED
#define HARDWARE_REGS_SSI_DEFINED
// =============================================================================
// Register : SSI_CTRLR0
// Description : Control register 0
#define SSI_CTRLR0_OFFSET _u(0x00000000)
#define SSI_CTRLR0_BITS _u(0x017fffff)
#define SSI_CTRLR0_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : SSI_CTRLR0_SSTE
// Description : Slave select toggle enable
#define SSI_CTRLR0_SSTE_RESET _u(0x0)
#define SSI_CTRLR0_SSTE_BITS _u(0x01000000)
#define SSI_CTRLR0_SSTE_MSB _u(24)
#define SSI_CTRLR0_SSTE_LSB _u(24)
#define SSI_CTRLR0_SSTE_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : SSI_CTRLR0_SPI_FRF
// Description : SPI frame format
// 0x0 -> Standard 1-bit SPI frame format; 1 bit per SCK,
// full-duplex
// 0x1 -> Dual-SPI frame format; two bits per SCK, half-duplex
// 0x2 -> Quad-SPI frame format; four bits per SCK, half-duplex
#define SSI_CTRLR0_SPI_FRF_RESET _u(0x0)
#define SSI_CTRLR0_SPI_FRF_BITS _u(0x00600000)
#define SSI_CTRLR0_SPI_FRF_MSB _u(22)
#define SSI_CTRLR0_SPI_FRF_LSB _u(21)
#define SSI_CTRLR0_SPI_FRF_ACCESS "RW"
#define SSI_CTRLR0_SPI_FRF_VALUE_STD _u(0x0)
#define SSI_CTRLR0_SPI_FRF_VALUE_DUAL _u(0x1)
#define SSI_CTRLR0_SPI_FRF_VALUE_QUAD _u(0x2)
// -----------------------------------------------------------------------------
// Field : SSI_CTRLR0_DFS_32
// Description : Data frame size in 32b transfer mode
// Value of n -> n+1 clocks per frame.
#define SSI_CTRLR0_DFS_32_RESET _u(0x00)
#define SSI_CTRLR0_DFS_32_BITS _u(0x001f0000)
#define SSI_CTRLR0_DFS_32_MSB _u(20)
#define SSI_CTRLR0_DFS_32_LSB _u(16)
#define SSI_CTRLR0_DFS_32_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : SSI_CTRLR0_CFS
// Description : Control frame size
// Value of n -> n+1 clocks per frame.
#define SSI_CTRLR0_CFS_RESET _u(0x0)
#define SSI_CTRLR0_CFS_BITS _u(0x0000f000)
#define SSI_CTRLR0_CFS_MSB _u(15)
#define SSI_CTRLR0_CFS_LSB _u(12)
#define SSI_CTRLR0_CFS_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : SSI_CTRLR0_SRL
// Description : Shift register loop (test mode)
#define SSI_CTRLR0_SRL_RESET _u(0x0)
#define SSI_CTRLR0_SRL_BITS _u(0x00000800)
#define SSI_CTRLR0_SRL_MSB _u(11)
#define SSI_CTRLR0_SRL_LSB _u(11)
#define SSI_CTRLR0_SRL_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : SSI_CTRLR0_SLV_OE
// Description : Slave output enable
#define SSI_CTRLR0_SLV_OE_RESET _u(0x0)
#define SSI_CTRLR0_SLV_OE_BITS _u(0x00000400)
#define SSI_CTRLR0_SLV_OE_MSB _u(10)
#define SSI_CTRLR0_SLV_OE_LSB _u(10)
#define SSI_CTRLR0_SLV_OE_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : SSI_CTRLR0_TMOD
// Description : Transfer mode
// 0x0 -> Both transmit and receive
// 0x1 -> Transmit only (not for FRF == 0, standard SPI mode)
// 0x2 -> Receive only (not for FRF == 0, standard SPI mode)
// 0x3 -> EEPROM read mode (TX then RX; RX starts after control
// data TX'd)
#define SSI_CTRLR0_TMOD_RESET _u(0x0)
#define SSI_CTRLR0_TMOD_BITS _u(0x00000300)
#define SSI_CTRLR0_TMOD_MSB _u(9)
#define SSI_CTRLR0_TMOD_LSB _u(8)
#define SSI_CTRLR0_TMOD_ACCESS "RW"
#define SSI_CTRLR0_TMOD_VALUE_TX_AND_RX _u(0x0)
#define SSI_CTRLR0_TMOD_VALUE_TX_ONLY _u(0x1)
#define SSI_CTRLR0_TMOD_VALUE_RX_ONLY _u(0x2)
#define SSI_CTRLR0_TMOD_VALUE_EEPROM_READ _u(0x3)
// -----------------------------------------------------------------------------
// Field : SSI_CTRLR0_SCPOL
// Description : Serial clock polarity
#define SSI_CTRLR0_SCPOL_RESET _u(0x0)
#define SSI_CTRLR0_SCPOL_BITS _u(0x00000080)
#define SSI_CTRLR0_SCPOL_MSB _u(7)
#define SSI_CTRLR0_SCPOL_LSB _u(7)
#define SSI_CTRLR0_SCPOL_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : SSI_CTRLR0_SCPH
// Description : Serial clock phase
#define SSI_CTRLR0_SCPH_RESET _u(0x0)
#define SSI_CTRLR0_SCPH_BITS _u(0x00000040)
#define SSI_CTRLR0_SCPH_MSB _u(6)
#define SSI_CTRLR0_SCPH_LSB _u(6)
#define SSI_CTRLR0_SCPH_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : SSI_CTRLR0_FRF
// Description : Frame format
#define SSI_CTRLR0_FRF_RESET _u(0x0)
#define SSI_CTRLR0_FRF_BITS _u(0x00000030)
#define SSI_CTRLR0_FRF_MSB _u(5)
#define SSI_CTRLR0_FRF_LSB _u(4)
#define SSI_CTRLR0_FRF_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : SSI_CTRLR0_DFS
// Description : Data frame size
#define SSI_CTRLR0_DFS_RESET _u(0x0)
#define SSI_CTRLR0_DFS_BITS _u(0x0000000f)
#define SSI_CTRLR0_DFS_MSB _u(3)
#define SSI_CTRLR0_DFS_LSB _u(0)
#define SSI_CTRLR0_DFS_ACCESS "RW"
// =============================================================================
// Register : SSI_CTRLR1
// Description : Master Control register 1
#define SSI_CTRLR1_OFFSET _u(0x00000004)
#define SSI_CTRLR1_BITS _u(0x0000ffff)
#define SSI_CTRLR1_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : SSI_CTRLR1_NDF
// Description : Number of data frames
#define SSI_CTRLR1_NDF_RESET _u(0x0000)
#define SSI_CTRLR1_NDF_BITS _u(0x0000ffff)
#define SSI_CTRLR1_NDF_MSB _u(15)
#define SSI_CTRLR1_NDF_LSB _u(0)
#define SSI_CTRLR1_NDF_ACCESS "RW"
// =============================================================================
// Register : SSI_SSIENR
// Description : SSI Enable
#define SSI_SSIENR_OFFSET _u(0x00000008)
#define SSI_SSIENR_BITS _u(0x00000001)
#define SSI_SSIENR_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : SSI_SSIENR_SSI_EN
// Description : SSI enable
#define SSI_SSIENR_SSI_EN_RESET _u(0x0)
#define SSI_SSIENR_SSI_EN_BITS _u(0x00000001)
#define SSI_SSIENR_SSI_EN_MSB _u(0)
#define SSI_SSIENR_SSI_EN_LSB _u(0)
#define SSI_SSIENR_SSI_EN_ACCESS "RW"
// =============================================================================
// Register : SSI_MWCR
// Description : Microwire Control
#define SSI_MWCR_OFFSET _u(0x0000000c)
#define SSI_MWCR_BITS _u(0x00000007)
#define SSI_MWCR_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : SSI_MWCR_MHS
// Description : Microwire handshaking
#define SSI_MWCR_MHS_RESET _u(0x0)
#define SSI_MWCR_MHS_BITS _u(0x00000004)
#define SSI_MWCR_MHS_MSB _u(2)
#define SSI_MWCR_MHS_LSB _u(2)
#define SSI_MWCR_MHS_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : SSI_MWCR_MDD
// Description : Microwire control
#define SSI_MWCR_MDD_RESET _u(0x0)
#define SSI_MWCR_MDD_BITS _u(0x00000002)
#define SSI_MWCR_MDD_MSB _u(1)
#define SSI_MWCR_MDD_LSB _u(1)
#define SSI_MWCR_MDD_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : SSI_MWCR_MWMOD
// Description : Microwire transfer mode
#define SSI_MWCR_MWMOD_RESET _u(0x0)
#define SSI_MWCR_MWMOD_BITS _u(0x00000001)
#define SSI_MWCR_MWMOD_MSB _u(0)
#define SSI_MWCR_MWMOD_LSB _u(0)
#define SSI_MWCR_MWMOD_ACCESS "RW"
// =============================================================================
// Register : SSI_SER
// Description : Slave enable
// For each bit:
// 0 -> slave not selected
// 1 -> slave selected
#define SSI_SER_OFFSET _u(0x00000010)
#define SSI_SER_BITS _u(0x00000001)
#define SSI_SER_RESET _u(0x00000000)
#define SSI_SER_MSB _u(0)
#define SSI_SER_LSB _u(0)
#define SSI_SER_ACCESS "RW"
// =============================================================================
// Register : SSI_BAUDR
// Description : Baud rate
#define SSI_BAUDR_OFFSET _u(0x00000014)
#define SSI_BAUDR_BITS _u(0x0000ffff)
#define SSI_BAUDR_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : SSI_BAUDR_SCKDV
// Description : SSI clock divider
#define SSI_BAUDR_SCKDV_RESET _u(0x0000)
#define SSI_BAUDR_SCKDV_BITS _u(0x0000ffff)
#define SSI_BAUDR_SCKDV_MSB _u(15)
#define SSI_BAUDR_SCKDV_LSB _u(0)
#define SSI_BAUDR_SCKDV_ACCESS "RW"
// =============================================================================
// Register : SSI_TXFTLR
// Description : TX FIFO threshold level
#define SSI_TXFTLR_OFFSET _u(0x00000018)
#define SSI_TXFTLR_BITS _u(0x000000ff)
#define SSI_TXFTLR_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : SSI_TXFTLR_TFT
// Description : Transmit FIFO threshold
#define SSI_TXFTLR_TFT_RESET _u(0x00)
#define SSI_TXFTLR_TFT_BITS _u(0x000000ff)
#define SSI_TXFTLR_TFT_MSB _u(7)
#define SSI_TXFTLR_TFT_LSB _u(0)
#define SSI_TXFTLR_TFT_ACCESS "RW"
// =============================================================================
// Register : SSI_RXFTLR
// Description : RX FIFO threshold level
#define SSI_RXFTLR_OFFSET _u(0x0000001c)
#define SSI_RXFTLR_BITS _u(0x000000ff)
#define SSI_RXFTLR_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : SSI_RXFTLR_RFT
// Description : Receive FIFO threshold
#define SSI_RXFTLR_RFT_RESET _u(0x00)
#define SSI_RXFTLR_RFT_BITS _u(0x000000ff)
#define SSI_RXFTLR_RFT_MSB _u(7)
#define SSI_RXFTLR_RFT_LSB _u(0)
#define SSI_RXFTLR_RFT_ACCESS "RW"
// =============================================================================
// Register : SSI_TXFLR
// Description : TX FIFO level
#define SSI_TXFLR_OFFSET _u(0x00000020)
#define SSI_TXFLR_BITS _u(0x000000ff)
#define SSI_TXFLR_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : SSI_TXFLR_TFTFL
// Description : Transmit FIFO level
#define SSI_TXFLR_TFTFL_RESET _u(0x00)
#define SSI_TXFLR_TFTFL_BITS _u(0x000000ff)
#define SSI_TXFLR_TFTFL_MSB _u(7)
#define SSI_TXFLR_TFTFL_LSB _u(0)
#define SSI_TXFLR_TFTFL_ACCESS "RO"
// =============================================================================
// Register : SSI_RXFLR
// Description : RX FIFO level
#define SSI_RXFLR_OFFSET _u(0x00000024)
#define SSI_RXFLR_BITS _u(0x000000ff)
#define SSI_RXFLR_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : SSI_RXFLR_RXTFL
// Description : Receive FIFO level
#define SSI_RXFLR_RXTFL_RESET _u(0x00)
#define SSI_RXFLR_RXTFL_BITS _u(0x000000ff)
#define SSI_RXFLR_RXTFL_MSB _u(7)
#define SSI_RXFLR_RXTFL_LSB _u(0)
#define SSI_RXFLR_RXTFL_ACCESS "RO"
// =============================================================================
// Register : SSI_SR
// Description : Status register
#define SSI_SR_OFFSET _u(0x00000028)
#define SSI_SR_BITS _u(0x0000007f)
#define SSI_SR_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : SSI_SR_DCOL
// Description : Data collision error
#define SSI_SR_DCOL_RESET _u(0x0)
#define SSI_SR_DCOL_BITS _u(0x00000040)
#define SSI_SR_DCOL_MSB _u(6)
#define SSI_SR_DCOL_LSB _u(6)
#define SSI_SR_DCOL_ACCESS "RO"
// -----------------------------------------------------------------------------
// Field : SSI_SR_TXE
// Description : Transmission error
#define SSI_SR_TXE_RESET _u(0x0)
#define SSI_SR_TXE_BITS _u(0x00000020)
#define SSI_SR_TXE_MSB _u(5)
#define SSI_SR_TXE_LSB _u(5)
#define SSI_SR_TXE_ACCESS "RO"
// -----------------------------------------------------------------------------
// Field : SSI_SR_RFF
// Description : Receive FIFO full
#define SSI_SR_RFF_RESET _u(0x0)
#define SSI_SR_RFF_BITS _u(0x00000010)
#define SSI_SR_RFF_MSB _u(4)
#define SSI_SR_RFF_LSB _u(4)
#define SSI_SR_RFF_ACCESS "RO"
// -----------------------------------------------------------------------------
// Field : SSI_SR_RFNE
// Description : Receive FIFO not empty
#define SSI_SR_RFNE_RESET _u(0x0)
#define SSI_SR_RFNE_BITS _u(0x00000008)
#define SSI_SR_RFNE_MSB _u(3)
#define SSI_SR_RFNE_LSB _u(3)
#define SSI_SR_RFNE_ACCESS "RO"
// -----------------------------------------------------------------------------
// Field : SSI_SR_TFE
// Description : Transmit FIFO empty
#define SSI_SR_TFE_RESET _u(0x0)
#define SSI_SR_TFE_BITS _u(0x00000004)
#define SSI_SR_TFE_MSB _u(2)
#define SSI_SR_TFE_LSB _u(2)
#define SSI_SR_TFE_ACCESS "RO"
// -----------------------------------------------------------------------------
// Field : SSI_SR_TFNF
// Description : Transmit FIFO not full
#define SSI_SR_TFNF_RESET _u(0x0)
#define SSI_SR_TFNF_BITS _u(0x00000002)
#define SSI_SR_TFNF_MSB _u(1)
#define SSI_SR_TFNF_LSB _u(1)
#define SSI_SR_TFNF_ACCESS "RO"
// -----------------------------------------------------------------------------
// Field : SSI_SR_BUSY
// Description : SSI busy flag
#define SSI_SR_BUSY_RESET _u(0x0)
#define SSI_SR_BUSY_BITS _u(0x00000001)
#define SSI_SR_BUSY_MSB _u(0)
#define SSI_SR_BUSY_LSB _u(0)
#define SSI_SR_BUSY_ACCESS "RO"
// =============================================================================
// Register : SSI_IMR
// Description : Interrupt mask
#define SSI_IMR_OFFSET _u(0x0000002c)
#define SSI_IMR_BITS _u(0x0000003f)
#define SSI_IMR_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : SSI_IMR_MSTIM
// Description : Multi-master contention interrupt mask
#define SSI_IMR_MSTIM_RESET _u(0x0)
#define SSI_IMR_MSTIM_BITS _u(0x00000020)
#define SSI_IMR_MSTIM_MSB _u(5)
#define SSI_IMR_MSTIM_LSB _u(5)
#define SSI_IMR_MSTIM_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : SSI_IMR_RXFIM
// Description : Receive FIFO full interrupt mask
#define SSI_IMR_RXFIM_RESET _u(0x0)
#define SSI_IMR_RXFIM_BITS _u(0x00000010)
#define SSI_IMR_RXFIM_MSB _u(4)
#define SSI_IMR_RXFIM_LSB _u(4)
#define SSI_IMR_RXFIM_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : SSI_IMR_RXOIM
// Description : Receive FIFO overflow interrupt mask
#define SSI_IMR_RXOIM_RESET _u(0x0)
#define SSI_IMR_RXOIM_BITS _u(0x00000008)
#define SSI_IMR_RXOIM_MSB _u(3)
#define SSI_IMR_RXOIM_LSB _u(3)
#define SSI_IMR_RXOIM_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : SSI_IMR_RXUIM
// Description : Receive FIFO underflow interrupt mask
#define SSI_IMR_RXUIM_RESET _u(0x0)
#define SSI_IMR_RXUIM_BITS _u(0x00000004)
#define SSI_IMR_RXUIM_MSB _u(2)
#define SSI_IMR_RXUIM_LSB _u(2)
#define SSI_IMR_RXUIM_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : SSI_IMR_TXOIM
// Description : Transmit FIFO overflow interrupt mask
#define SSI_IMR_TXOIM_RESET _u(0x0)
#define SSI_IMR_TXOIM_BITS _u(0x00000002)
#define SSI_IMR_TXOIM_MSB _u(1)
#define SSI_IMR_TXOIM_LSB _u(1)
#define SSI_IMR_TXOIM_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : SSI_IMR_TXEIM
// Description : Transmit FIFO empty interrupt mask
#define SSI_IMR_TXEIM_RESET _u(0x0)
#define SSI_IMR_TXEIM_BITS _u(0x00000001)
#define SSI_IMR_TXEIM_MSB _u(0)
#define SSI_IMR_TXEIM_LSB _u(0)
#define SSI_IMR_TXEIM_ACCESS "RW"
// =============================================================================
// Register : SSI_ISR
// Description : Interrupt status
#define SSI_ISR_OFFSET _u(0x00000030)
#define SSI_ISR_BITS _u(0x0000003f)
#define SSI_ISR_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : SSI_ISR_MSTIS
// Description : Multi-master contention interrupt status
#define SSI_ISR_MSTIS_RESET _u(0x0)
#define SSI_ISR_MSTIS_BITS _u(0x00000020)
#define SSI_ISR_MSTIS_MSB _u(5)
#define SSI_ISR_MSTIS_LSB _u(5)
#define SSI_ISR_MSTIS_ACCESS "RO"
// -----------------------------------------------------------------------------
// Field : SSI_ISR_RXFIS
// Description : Receive FIFO full interrupt status
#define SSI_ISR_RXFIS_RESET _u(0x0)
#define SSI_ISR_RXFIS_BITS _u(0x00000010)
#define SSI_ISR_RXFIS_MSB _u(4)
#define SSI_ISR_RXFIS_LSB _u(4)
#define SSI_ISR_RXFIS_ACCESS "RO"
// -----------------------------------------------------------------------------
// Field : SSI_ISR_RXOIS
// Description : Receive FIFO overflow interrupt status
#define SSI_ISR_RXOIS_RESET _u(0x0)
#define SSI_ISR_RXOIS_BITS _u(0x00000008)
#define SSI_ISR_RXOIS_MSB _u(3)
#define SSI_ISR_RXOIS_LSB _u(3)
#define SSI_ISR_RXOIS_ACCESS "RO"
// -----------------------------------------------------------------------------
// Field : SSI_ISR_RXUIS
// Description : Receive FIFO underflow interrupt status
#define SSI_ISR_RXUIS_RESET _u(0x0)
#define SSI_ISR_RXUIS_BITS _u(0x00000004)
#define SSI_ISR_RXUIS_MSB _u(2)
#define SSI_ISR_RXUIS_LSB _u(2)
#define SSI_ISR_RXUIS_ACCESS "RO"
// -----------------------------------------------------------------------------
// Field : SSI_ISR_TXOIS
// Description : Transmit FIFO overflow interrupt status
#define SSI_ISR_TXOIS_RESET _u(0x0)
#define SSI_ISR_TXOIS_BITS _u(0x00000002)
#define SSI_ISR_TXOIS_MSB _u(1)
#define SSI_ISR_TXOIS_LSB _u(1)
#define SSI_ISR_TXOIS_ACCESS "RO"
// -----------------------------------------------------------------------------
// Field : SSI_ISR_TXEIS
// Description : Transmit FIFO empty interrupt status
#define SSI_ISR_TXEIS_RESET _u(0x0)
#define SSI_ISR_TXEIS_BITS _u(0x00000001)
#define SSI_ISR_TXEIS_MSB _u(0)
#define SSI_ISR_TXEIS_LSB _u(0)
#define SSI_ISR_TXEIS_ACCESS "RO"
// =============================================================================
// Register : SSI_RISR
// Description : Raw interrupt status
#define SSI_RISR_OFFSET _u(0x00000034)
#define SSI_RISR_BITS _u(0x0000003f)
#define SSI_RISR_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : SSI_RISR_MSTIR
// Description : Multi-master contention raw interrupt status
#define SSI_RISR_MSTIR_RESET _u(0x0)
#define SSI_RISR_MSTIR_BITS _u(0x00000020)
#define SSI_RISR_MSTIR_MSB _u(5)
#define SSI_RISR_MSTIR_LSB _u(5)
#define SSI_RISR_MSTIR_ACCESS "RO"
// -----------------------------------------------------------------------------
// Field : SSI_RISR_RXFIR
// Description : Receive FIFO full raw interrupt status
#define SSI_RISR_RXFIR_RESET _u(0x0)
#define SSI_RISR_RXFIR_BITS _u(0x00000010)
#define SSI_RISR_RXFIR_MSB _u(4)
#define SSI_RISR_RXFIR_LSB _u(4)
#define SSI_RISR_RXFIR_ACCESS "RO"
// -----------------------------------------------------------------------------
// Field : SSI_RISR_RXOIR
// Description : Receive FIFO overflow raw interrupt status
#define SSI_RISR_RXOIR_RESET _u(0x0)
#define SSI_RISR_RXOIR_BITS _u(0x00000008)
#define SSI_RISR_RXOIR_MSB _u(3)
#define SSI_RISR_RXOIR_LSB _u(3)
#define SSI_RISR_RXOIR_ACCESS "RO"
// -----------------------------------------------------------------------------
// Field : SSI_RISR_RXUIR
// Description : Receive FIFO underflow raw interrupt status
#define SSI_RISR_RXUIR_RESET _u(0x0)
#define SSI_RISR_RXUIR_BITS _u(0x00000004)
#define SSI_RISR_RXUIR_MSB _u(2)
#define SSI_RISR_RXUIR_LSB _u(2)
#define SSI_RISR_RXUIR_ACCESS "RO"
// -----------------------------------------------------------------------------
// Field : SSI_RISR_TXOIR
// Description : Transmit FIFO overflow raw interrupt status
#define SSI_RISR_TXOIR_RESET _u(0x0)
#define SSI_RISR_TXOIR_BITS _u(0x00000002)
#define SSI_RISR_TXOIR_MSB _u(1)
#define SSI_RISR_TXOIR_LSB _u(1)
#define SSI_RISR_TXOIR_ACCESS "RO"
// -----------------------------------------------------------------------------
// Field : SSI_RISR_TXEIR
// Description : Transmit FIFO empty raw interrupt status
#define SSI_RISR_TXEIR_RESET _u(0x0)
#define SSI_RISR_TXEIR_BITS _u(0x00000001)
#define SSI_RISR_TXEIR_MSB _u(0)
#define SSI_RISR_TXEIR_LSB _u(0)
#define SSI_RISR_TXEIR_ACCESS "RO"
// =============================================================================
// Register : SSI_TXOICR
// Description : TX FIFO overflow interrupt clear
// Clear-on-read transmit FIFO overflow interrupt
#define SSI_TXOICR_OFFSET _u(0x00000038)
#define SSI_TXOICR_BITS _u(0x00000001)
#define SSI_TXOICR_RESET _u(0x00000000)
#define SSI_TXOICR_MSB _u(0)
#define SSI_TXOICR_LSB _u(0)
#define SSI_TXOICR_ACCESS "RO"
// =============================================================================
// Register : SSI_RXOICR
// Description : RX FIFO overflow interrupt clear
// Clear-on-read receive FIFO overflow interrupt
#define SSI_RXOICR_OFFSET _u(0x0000003c)
#define SSI_RXOICR_BITS _u(0x00000001)
#define SSI_RXOICR_RESET _u(0x00000000)
#define SSI_RXOICR_MSB _u(0)
#define SSI_RXOICR_LSB _u(0)
#define SSI_RXOICR_ACCESS "RO"
// =============================================================================
// Register : SSI_RXUICR
// Description : RX FIFO underflow interrupt clear
// Clear-on-read receive FIFO underflow interrupt
#define SSI_RXUICR_OFFSET _u(0x00000040)
#define SSI_RXUICR_BITS _u(0x00000001)
#define SSI_RXUICR_RESET _u(0x00000000)
#define SSI_RXUICR_MSB _u(0)
#define SSI_RXUICR_LSB _u(0)
#define SSI_RXUICR_ACCESS "RO"
// =============================================================================
// Register : SSI_MSTICR
// Description : Multi-master interrupt clear
// Clear-on-read multi-master contention interrupt
#define SSI_MSTICR_OFFSET _u(0x00000044)
#define SSI_MSTICR_BITS _u(0x00000001)
#define SSI_MSTICR_RESET _u(0x00000000)
#define SSI_MSTICR_MSB _u(0)
#define SSI_MSTICR_LSB _u(0)
#define SSI_MSTICR_ACCESS "RO"
// =============================================================================
// Register : SSI_ICR
// Description : Interrupt clear
// Clear-on-read all active interrupts
#define SSI_ICR_OFFSET _u(0x00000048)
#define SSI_ICR_BITS _u(0x00000001)
#define SSI_ICR_RESET _u(0x00000000)
#define SSI_ICR_MSB _u(0)
#define SSI_ICR_LSB _u(0)
#define SSI_ICR_ACCESS "RO"
// =============================================================================
// Register : SSI_DMACR
// Description : DMA control
#define SSI_DMACR_OFFSET _u(0x0000004c)
#define SSI_DMACR_BITS _u(0x00000003)
#define SSI_DMACR_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : SSI_DMACR_TDMAE
// Description : Transmit DMA enable
#define SSI_DMACR_TDMAE_RESET _u(0x0)
#define SSI_DMACR_TDMAE_BITS _u(0x00000002)
#define SSI_DMACR_TDMAE_MSB _u(1)
#define SSI_DMACR_TDMAE_LSB _u(1)
#define SSI_DMACR_TDMAE_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : SSI_DMACR_RDMAE
// Description : Receive DMA enable
#define SSI_DMACR_RDMAE_RESET _u(0x0)
#define SSI_DMACR_RDMAE_BITS _u(0x00000001)
#define SSI_DMACR_RDMAE_MSB _u(0)
#define SSI_DMACR_RDMAE_LSB _u(0)
#define SSI_DMACR_RDMAE_ACCESS "RW"
// =============================================================================
// Register : SSI_DMATDLR
// Description : DMA TX data level
#define SSI_DMATDLR_OFFSET _u(0x00000050)
#define SSI_DMATDLR_BITS _u(0x000000ff)
#define SSI_DMATDLR_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : SSI_DMATDLR_DMATDL
// Description : Transmit data watermark level
#define SSI_DMATDLR_DMATDL_RESET _u(0x00)
#define SSI_DMATDLR_DMATDL_BITS _u(0x000000ff)
#define SSI_DMATDLR_DMATDL_MSB _u(7)
#define SSI_DMATDLR_DMATDL_LSB _u(0)
#define SSI_DMATDLR_DMATDL_ACCESS "RW"
// =============================================================================
// Register : SSI_DMARDLR
// Description : DMA RX data level
#define SSI_DMARDLR_OFFSET _u(0x00000054)
#define SSI_DMARDLR_BITS _u(0x000000ff)
#define SSI_DMARDLR_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : SSI_DMARDLR_DMARDL
// Description : Receive data watermark level (DMARDLR+1)
#define SSI_DMARDLR_DMARDL_RESET _u(0x00)
#define SSI_DMARDLR_DMARDL_BITS _u(0x000000ff)
#define SSI_DMARDLR_DMARDL_MSB _u(7)
#define SSI_DMARDLR_DMARDL_LSB _u(0)
#define SSI_DMARDLR_DMARDL_ACCESS "RW"
// =============================================================================
// Register : SSI_IDR
// Description : Identification register
#define SSI_IDR_OFFSET _u(0x00000058)
#define SSI_IDR_BITS _u(0xffffffff)
#define SSI_IDR_RESET _u(0x51535049)
// -----------------------------------------------------------------------------
// Field : SSI_IDR_IDCODE
// Description : Peripheral dentification code
#define SSI_IDR_IDCODE_RESET _u(0x51535049)
#define SSI_IDR_IDCODE_BITS _u(0xffffffff)
#define SSI_IDR_IDCODE_MSB _u(31)
#define SSI_IDR_IDCODE_LSB _u(0)
#define SSI_IDR_IDCODE_ACCESS "RO"
// =============================================================================
// Register : SSI_SSI_VERSION_ID
// Description : Version ID
#define SSI_SSI_VERSION_ID_OFFSET _u(0x0000005c)
#define SSI_SSI_VERSION_ID_BITS _u(0xffffffff)
#define SSI_SSI_VERSION_ID_RESET _u(0x3430312a)
// -----------------------------------------------------------------------------
// Field : SSI_SSI_VERSION_ID_SSI_COMP_VERSION
// Description : SNPS component version (format X.YY)
#define SSI_SSI_VERSION_ID_SSI_COMP_VERSION_RESET _u(0x3430312a)
#define SSI_SSI_VERSION_ID_SSI_COMP_VERSION_BITS _u(0xffffffff)
#define SSI_SSI_VERSION_ID_SSI_COMP_VERSION_MSB _u(31)
#define SSI_SSI_VERSION_ID_SSI_COMP_VERSION_LSB _u(0)
#define SSI_SSI_VERSION_ID_SSI_COMP_VERSION_ACCESS "RO"
// =============================================================================
// Register : SSI_DR0
// Description : Data Register 0 (of 36)
#define SSI_DR0_OFFSET _u(0x00000060)
#define SSI_DR0_BITS _u(0xffffffff)
#define SSI_DR0_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : SSI_DR0_DR
// Description : First data register of 36
#define SSI_DR0_DR_RESET _u(0x00000000)
#define SSI_DR0_DR_BITS _u(0xffffffff)
#define SSI_DR0_DR_MSB _u(31)
#define SSI_DR0_DR_LSB _u(0)
#define SSI_DR0_DR_ACCESS "RW"
// =============================================================================
// Register : SSI_RX_SAMPLE_DLY
// Description : RX sample delay
#define SSI_RX_SAMPLE_DLY_OFFSET _u(0x000000f0)
#define SSI_RX_SAMPLE_DLY_BITS _u(0x000000ff)
#define SSI_RX_SAMPLE_DLY_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : SSI_RX_SAMPLE_DLY_RSD
// Description : RXD sample delay (in SCLK cycles)
#define SSI_RX_SAMPLE_DLY_RSD_RESET _u(0x00)
#define SSI_RX_SAMPLE_DLY_RSD_BITS _u(0x000000ff)
#define SSI_RX_SAMPLE_DLY_RSD_MSB _u(7)
#define SSI_RX_SAMPLE_DLY_RSD_LSB _u(0)
#define SSI_RX_SAMPLE_DLY_RSD_ACCESS "RW"
// =============================================================================
// Register : SSI_SPI_CTRLR0
// Description : SPI control
#define SSI_SPI_CTRLR0_OFFSET _u(0x000000f4)
#define SSI_SPI_CTRLR0_BITS _u(0xff07fb3f)
#define SSI_SPI_CTRLR0_RESET _u(0x03000000)
// -----------------------------------------------------------------------------
// Field : SSI_SPI_CTRLR0_XIP_CMD
// Description : SPI Command to send in XIP mode (INST_L = 8-bit) or to append
// to Address (INST_L = 0-bit)
#define SSI_SPI_CTRLR0_XIP_CMD_RESET _u(0x03)
#define SSI_SPI_CTRLR0_XIP_CMD_BITS _u(0xff000000)
#define SSI_SPI_CTRLR0_XIP_CMD_MSB _u(31)
#define SSI_SPI_CTRLR0_XIP_CMD_LSB _u(24)
#define SSI_SPI_CTRLR0_XIP_CMD_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : SSI_SPI_CTRLR0_SPI_RXDS_EN
// Description : Read data strobe enable
#define SSI_SPI_CTRLR0_SPI_RXDS_EN_RESET _u(0x0)
#define SSI_SPI_CTRLR0_SPI_RXDS_EN_BITS _u(0x00040000)
#define SSI_SPI_CTRLR0_SPI_RXDS_EN_MSB _u(18)
#define SSI_SPI_CTRLR0_SPI_RXDS_EN_LSB _u(18)
#define SSI_SPI_CTRLR0_SPI_RXDS_EN_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : SSI_SPI_CTRLR0_INST_DDR_EN
// Description : Instruction DDR transfer enable
#define SSI_SPI_CTRLR0_INST_DDR_EN_RESET _u(0x0)
#define SSI_SPI_CTRLR0_INST_DDR_EN_BITS _u(0x00020000)
#define SSI_SPI_CTRLR0_INST_DDR_EN_MSB _u(17)
#define SSI_SPI_CTRLR0_INST_DDR_EN_LSB _u(17)
#define SSI_SPI_CTRLR0_INST_DDR_EN_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : SSI_SPI_CTRLR0_SPI_DDR_EN
// Description : SPI DDR transfer enable
#define SSI_SPI_CTRLR0_SPI_DDR_EN_RESET _u(0x0)
#define SSI_SPI_CTRLR0_SPI_DDR_EN_BITS _u(0x00010000)
#define SSI_SPI_CTRLR0_SPI_DDR_EN_MSB _u(16)
#define SSI_SPI_CTRLR0_SPI_DDR_EN_LSB _u(16)
#define SSI_SPI_CTRLR0_SPI_DDR_EN_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : SSI_SPI_CTRLR0_WAIT_CYCLES
// Description : Wait cycles between control frame transmit and data reception
// (in SCLK cycles)
#define SSI_SPI_CTRLR0_WAIT_CYCLES_RESET _u(0x00)
#define SSI_SPI_CTRLR0_WAIT_CYCLES_BITS _u(0x0000f800)
#define SSI_SPI_CTRLR0_WAIT_CYCLES_MSB _u(15)
#define SSI_SPI_CTRLR0_WAIT_CYCLES_LSB _u(11)
#define SSI_SPI_CTRLR0_WAIT_CYCLES_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : SSI_SPI_CTRLR0_INST_L
// Description : Instruction length (0/4/8/16b)
// 0x0 -> No instruction
// 0x1 -> 4-bit instruction
// 0x2 -> 8-bit instruction
// 0x3 -> 16-bit instruction
#define SSI_SPI_CTRLR0_INST_L_RESET _u(0x0)
#define SSI_SPI_CTRLR0_INST_L_BITS _u(0x00000300)
#define SSI_SPI_CTRLR0_INST_L_MSB _u(9)
#define SSI_SPI_CTRLR0_INST_L_LSB _u(8)
#define SSI_SPI_CTRLR0_INST_L_ACCESS "RW"
#define SSI_SPI_CTRLR0_INST_L_VALUE_NONE _u(0x0)
#define SSI_SPI_CTRLR0_INST_L_VALUE_4B _u(0x1)
#define SSI_SPI_CTRLR0_INST_L_VALUE_8B _u(0x2)
#define SSI_SPI_CTRLR0_INST_L_VALUE_16B _u(0x3)
// -----------------------------------------------------------------------------
// Field : SSI_SPI_CTRLR0_ADDR_L
// Description : Address length (0b-60b in 4b increments)
#define SSI_SPI_CTRLR0_ADDR_L_RESET _u(0x0)
#define SSI_SPI_CTRLR0_ADDR_L_BITS _u(0x0000003c)
#define SSI_SPI_CTRLR0_ADDR_L_MSB _u(5)
#define SSI_SPI_CTRLR0_ADDR_L_LSB _u(2)
#define SSI_SPI_CTRLR0_ADDR_L_ACCESS "RW"
// -----------------------------------------------------------------------------
// Field : SSI_SPI_CTRLR0_TRANS_TYPE
// Description : Address and instruction transfer format
// 0x0 -> Command and address both in standard SPI frame format
// 0x1 -> Command in standard SPI format, address in format
// specified by FRF
// 0x2 -> Command and address both in format specified by FRF
// (e.g. Dual-SPI)
#define SSI_SPI_CTRLR0_TRANS_TYPE_RESET _u(0x0)
#define SSI_SPI_CTRLR0_TRANS_TYPE_BITS _u(0x00000003)
#define SSI_SPI_CTRLR0_TRANS_TYPE_MSB _u(1)
#define SSI_SPI_CTRLR0_TRANS_TYPE_LSB _u(0)
#define SSI_SPI_CTRLR0_TRANS_TYPE_ACCESS "RW"
#define SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C1A _u(0x0)
#define SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C2A _u(0x1)
#define SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_2C2A _u(0x2)
// =============================================================================
// Register : SSI_TXD_DRIVE_EDGE
// Description : TX drive edge
#define SSI_TXD_DRIVE_EDGE_OFFSET _u(0x000000f8)
#define SSI_TXD_DRIVE_EDGE_BITS _u(0x000000ff)
#define SSI_TXD_DRIVE_EDGE_RESET _u(0x00000000)
// -----------------------------------------------------------------------------
// Field : SSI_TXD_DRIVE_EDGE_TDE
// Description : TXD drive edge
#define SSI_TXD_DRIVE_EDGE_TDE_RESET _u(0x00)
#define SSI_TXD_DRIVE_EDGE_TDE_BITS _u(0x000000ff)
#define SSI_TXD_DRIVE_EDGE_TDE_MSB _u(7)
#define SSI_TXD_DRIVE_EDGE_TDE_LSB _u(0)
#define SSI_TXD_DRIVE_EDGE_TDE_ACCESS "RW"
// =============================================================================
#endif // HARDWARE_REGS_SSI_DEFINED

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "hardware/platform_defs.h"
#include "pico/config.h"
#define WRAPPER_FUNC_NAME(x) __wrap_##x
#define SECTION_NAME(x) .text.##x
#define RAM_SECTION_NAME(x) .time_critical.##x
#define rom_table_code(c1, c2) ((c1) | ((c2) << 8))
// do not put align in here as it is used mid function sometimes
.macro regular_func x
.global \x
.type \x,%function
.thumb_func
\x:
.endm
.macro regular_func_with_section x
.section .text.\x
regular_func \x
.endm
// do not put align in here as it is used mid function sometimes
.macro wrapper_func x
regular_func WRAPPER_FUNC_NAME(\x)
.endm
.macro __pre_init func, priority_string
.section .preinit_array.\priority_string
.align 2
.word \func
.endm

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
// -----------------------------------------------------
// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
// -----------------------------------------------------
// This header may be included by other board headers as "boards/pico.h"
#ifndef _BOARDS_PICO_H
#define _BOARDS_PICO_H
// --- UART ---
#ifndef PICO_DEFAULT_UART
#define PICO_DEFAULT_UART 0
#endif
#ifndef PICO_DEFAULT_UART_TX_PIN
#define PICO_DEFAULT_UART_TX_PIN 0
#endif
#ifndef PICO_DEFAULT_UART_RX_PIN
#define PICO_DEFAULT_UART_RX_PIN 1
#endif
// --- LED ---
#ifndef PICO_DEFAULT_LED_PIN
#define PICO_DEFAULT_LED_PIN 25
#endif
// no PICO_DEFAULT_WS2812_PIN
// --- I2C ---
#ifndef PICO_DEFAULT_I2C
#define PICO_DEFAULT_I2C 0
#endif
#ifndef PICO_DEFAULT_I2C_SDA_PIN
#define PICO_DEFAULT_I2C_SDA_PIN 4
#endif
#ifndef PICO_DEFAULT_I2C_SCL_PIN
#define PICO_DEFAULT_I2C_SCL_PIN 5
#endif
// --- SPI ---
#ifndef PICO_DEFAULT_SPI
#define PICO_DEFAULT_SPI 0
#endif
#ifndef PICO_DEFAULT_SPI_SCK_PIN
#define PICO_DEFAULT_SPI_SCK_PIN 18
#endif
#ifndef PICO_DEFAULT_SPI_TX_PIN
#define PICO_DEFAULT_SPI_TX_PIN 19
#endif
#ifndef PICO_DEFAULT_SPI_RX_PIN
#define PICO_DEFAULT_SPI_RX_PIN 16
#endif
#ifndef PICO_DEFAULT_SPI_CSN_PIN
#define PICO_DEFAULT_SPI_CSN_PIN 17
#endif
// --- FLASH ---
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
#ifndef PICO_FLASH_SPI_CLKDIV
#define PICO_FLASH_SPI_CLKDIV 2
#endif
#ifndef PICO_FLASH_SIZE_BYTES
#define PICO_FLASH_SIZE_BYTES (2 * 1024 * 1024)
#endif
// Drive high to force power supply into PWM mode (lower ripple on 3V3 at light loads)
#define PICO_SMPS_MODE_PIN 23
#ifndef PICO_FLOAT_SUPPORT_ROM_V1
#define PICO_FLOAT_SUPPORT_ROM_V1 1
#endif
#ifndef PICO_DOUBLE_SUPPORT_ROM_V1
#define PICO_DOUBLE_SUPPORT_ROM_V1 1
#endif
#endif

View File

@ -0,0 +1,180 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_PLATFORM_H_
#define _PICO_PLATFORM_H_
#include <sys/cdefs.h>
#include "pico/types.h"
#include "hardware/platform_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
/** \file platform.h
* \defgroup pico_platform pico_platform
* Compiler definitions for the selected PICO_PLATFORM
*/
#define __isr
// Section naming macros
#define __after_data(group) __attribute__((section(".after_data." group)))
#define __not_in_flash(group) __attribute__((section(".time_critical." group)))
#define __scratch_x(group) __attribute__((section(".scratch_x." group)))
#define __scratch_y(group) __attribute__((section(".scratch_y." group)))
#define __uninitialized_ram(group) __attribute__((section(".uninitialized_ram." #group))) group
// For use with PICO_COPY_TO_RAM:
#define __in_flash(group) __attribute__((section(".flashdata" group)))
/**
* Decorates a function name, such that the function will execute from RAM (assuming it is not inlined
* into a flash function by the compiler)
*/
#define __not_in_flash_func(func_name) __not_in_flash(__STRING(func_name)) func_name
/**
* Historical synonym for __not_in_flash_func()
*/
#define __time_critical_func(func_name) __not_in_flash_func(func_name)
/**
* Decorates a function name, such that the function will execute from RAM, explicitly marking it as
* noinline to prevent it being inlined into a flash function by the compiler
*/
#define __no_inline_not_in_flash_func(func_name) __noinline __not_in_flash_func(func_name)
#define __packed_aligned __packed __aligned(4)
#if defined(__GNUC__) && __GNUC__ < 7
#define __force_inline inline __always_inline
#else
#define __force_inline __always_inline
#endif
#ifndef count_of
#define count_of(a) (sizeof(a)/sizeof((a)[0]))
#endif
#ifndef MAX
#define MAX(a, b) ((a)>(b)?(a):(b))
#endif
#ifndef MIN
#define MIN(a, b) ((b)>(a)?(a):(b))
#endif
/**
* Execute a breakpoint instruction
*/
static inline void __breakpoint(void) {
__asm__("bkpt #0");
}
/**
* Ensure that the compiler does not move memory access across this method call
*/
__force_inline static void __compiler_memory_barrier(void) {
__asm__ volatile ("" : : : "memory");
}
// return a 32 bit handle for a raw ptr; DMA chaining for example embeds pointers in 32 bit values
// which of course does not work if we're running the code natively on a 64 bit platforms. Therefore
// we provide this macro which allows that code to provide a 64->32 bit mapping in host mode
#define host_safe_hw_ptr(x) ((uintptr_t)(x))
/**
* Panic (see panic()) with the message "Unsupported".
*/
void __attribute__((noreturn)) panic_unsupported(void);
/**
* Panic with a message. An attempt is made to output the message to all registered STDOUT drivers
* after which this method executes a BKPT instruction.
*
* @param fmt format string (printf-like)
* @param ... printf-like arguments
*/
void __attribute__((noreturn)) panic(const char *fmt, ...);
// PICO_CONFIG: PICO_NO_FPGA_CHECK, Remove the FPGA platform check for small code size reduction, type=bool, default=0, advanced=true, group=pico_runtime
#ifndef PICO_NO_FPGA_CHECK
#define PICO_NO_FPGA_CHECK 0
#endif
#if PICO_NO_FPGA_CHECK
static inline bool running_on_fpga(void) {return false;}
#else
bool running_on_fpga(void);
#endif
/**
* @return the RP2040 chip revision number
*/
uint8_t rp2040_chip_version(void);
/**
* @return the RP2040 rom version number
*/
static inline uint8_t rp2040_rom_version(void) {
return *(uint8_t*)0x13;
}
/**
* Empty function intended to be called by any tight hardware polling loop. using this ubiquitously
* makes it much easier to find tight loops, but also in the future \#ifdef-ed support for lockup
* debugging might be added
*/
static inline void tight_loop_contents(void) {}
/**
* Helper macro for making chain DMA code portable to PICO_PLATFORM=host. The problem here is
* that embedded pointers in the data are only 32 bit, which is a problem if the host
* system is 64 bit. This macro is zero cost on the actual device, but in host mode
* it provides a 64->32 bit mapping
*/
#define native_safe_hw_ptr(x) ((uintptr_t)(x))
/**
* Multiplies a by b using multiply instruction using the ARM mul instruction regardless of values;
* i.e. this is a 1 cycle operation.
*
* \param a the first operand
* \param b the second operand
* \return a * b
*/
__force_inline static int32_t __mul_instruction(int32_t a, int32_t b) {
asm ("mul %0, %1" : "+l" (a) : "l" (b) : );
return a;
}
/**
* Efficiently Multiplies value a by possibly constant value b.
* If b is known to be constant and not zero or a power of 2, then a mul instruction is used rather than gcc's default
* which is often a slow combination of shifts and adds
*
* \param a the first operand
* \param b the second operand
* \return a * b
*/
#define __fast_mul(a, b) __builtin_choose_expr(__builtin_constant_p(b) && !__builtin_constant_p(a), \
(__builtin_popcount(b) >= 2 ? __mul_instruction(a,b) : (a)*(b)), \
(a)*(b))
#define WRAPPER_FUNC(x) __wrap_ ## x
#define REAL_FUNC(x) __real_ ## x
#define __check_type_compatible(type_a, type_b) static_assert(__builtin_types_compatible_p(type_a, type_b), __STRING(type_a) " is not compatible with " __STRING(type_b));
/**
* Get the current exception level on this core
* \return the exception number if the CPU is handling an exception, or 0 otherwise
*/
uint __get_current_exception(void);
#ifdef __cplusplus
}
#endif
#endif

55
cpu/rpx0xx/vendor/boot_stage2/pad_checksum vendored Executable file
View File

@ -0,0 +1,55 @@
#!/usr/bin/env python3
import argparse
import binascii
import struct
import sys
def any_int(x):
try:
return int(x, 0)
except:
raise argparse.ArgumentTypeError("expected an integer, not '{!r}'".format(x))
def bitrev(x, width):
return int("{:0{w}b}".format(x, w=width)[::-1], 2)
parser = argparse.ArgumentParser()
parser.add_argument("ifile", help="Input file (binary)")
parser.add_argument("ofile", help="Output file (assembly)")
parser.add_argument("-p", "--pad", help="Padded size (bytes), including 4-byte checksum, default 256",
type=any_int, default=256)
parser.add_argument("-s", "--seed", help="Checksum seed value, default 0",
type=any_int, default=0)
args = parser.parse_args()
try:
idata = open(args.ifile, "rb").read()
except:
sys.exit("Could not open input file '{}'".format(args.ifile))
if len(idata) >= args.pad - 4:
sys.exit("Input file size ({} bytes) too large for final size ({} bytes)".format(len(idata), args.pad))
idata_padded = idata + bytes(args.pad - 4 - len(idata))
# Our bootrom CRC32 is slightly bass-ackward but it's best to work around for now (FIXME)
# 100% worth it to save two Thumb instructions
checksum = bitrev(
(binascii.crc32(bytes(bitrev(b, 8) for b in idata_padded), args.seed ^ 0xffffffff) ^ 0xffffffff) & 0xffffffff, 32)
odata = idata_padded + struct.pack("<L", checksum)
try:
with open(args.ofile, "w") as ofile:
ofile.write("// Padded and checksummed version of: {}\n\n".format(args.ifile))
ofile.write(".cpu cortex-m0plus\n")
ofile.write(".thumb\n\n")
ofile.write(".section .boot2, \"ax\"\n\n")
for offs in range(0, len(odata), 16):
chunk = odata[offs:min(offs + 16, len(odata))]
ofile.write(".byte {}\n".format(", ".join("0x{:02x}".format(b) for b in chunk)))
except:
sys.exit("Could not open output file '{}'".format(args.ofile))

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _BOOT2_HELPER_READ_FLASH_SREG
#define _BOOT2_HELPER_READ_FLASH_SREG
#include "boot2_helpers/wait_ssi_ready.S"
// Pass status read cmd into r0.
// Returns status value in r0.
.global read_flash_sreg
.type read_flash_sreg,%function
.thumb_func
read_flash_sreg:
push {r1, lr}
str r0, [r3, #SSI_DR0_OFFSET]
// Dummy byte:
str r0, [r3, #SSI_DR0_OFFSET]
bl wait_ssi_ready
// Discard first byte and combine the next two
ldr r0, [r3, #SSI_DR0_OFFSET]
ldr r0, [r3, #SSI_DR0_OFFSET]
pop {r1, pc}
#endif

48
cpu/rpx0xx/xosc.c Normal file
View File

@ -0,0 +1,48 @@
/*
* 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.
*/
/**
* @ingroup cpu_rpx0xx
* @{
*
* @file
* @brief Implementation of the crystal oscillator (XOSC)
*
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
*
* @}
*/
#include <assert.h>
#include "macros/units.h"
#include "vendor/RP2040.h"
#include "io_reg.h"
static inline uint32_t _xosc_conf_sartup_delay(uint32_t f_crystal_mhz, uint32_t t_stable_ms)
{
return (((f_crystal_mhz / 1000) * t_stable_ms) + 128) / 256;
}
void xosc_start(uint32_t f_ref)
{
assert(f_ref == MHZ(12));
uint32_t delay = _xosc_conf_sartup_delay(f_ref, 1);
io_reg_write_dont_corrupt(&XOSC->STARTUP.reg, delay << XOSC_STARTUP_DELAY_Pos,
XOSC_STARTUP_DELAY_Msk);
io_reg_write_dont_corrupt(&XOSC->CTRL.reg, XOSC_CTRL_ENABLE_ENABLE << XOSC_CTRL_ENABLE_Pos,
XOSC_CTRL_ENABLE_Msk);
while (!XOSC->STATUS.bit.STABLE) { }
}
void xosc_stop(void)
{
io_reg_write_dont_corrupt(&XOSC->CTRL.reg, XOSC_CTRL_ENABLE_DISABLE << XOSC_CTRL_ENABLE_Pos,
XOSC_CTRL_ENABLE_Msk);
}