├── .cargo └── config.toml ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── Cargo.toml ├── README.md ├── bin ├── boot2_at25sf128a.padded.bin ├── boot2_gd25q64cs.padded.bin ├── boot2_generic_03h.padded.bin ├── boot2_is25lp080.padded.bin ├── boot2_ram_memcpy.padded.bin ├── boot2_w25q080.padded.bin └── boot2_w25x10cl.padded.bin ├── build.rs ├── check-blobs.sh └── src ├── boot2_at25sf128a.S ├── boot2_gd25q64cs.S ├── boot2_generic_03h.S ├── boot2_is25lp080.S ├── boot2_ram_memcpy.S ├── boot2_w25q080.S ├── boot2_w25x10cl.S ├── include ├── boot2_helpers │ ├── exit_from_boot2.S │ ├── read_flash_sreg.S │ └── wait_ssi_ready.S ├── hardware │ ├── platform_defs.h │ └── regs │ │ ├── addressmap.h │ │ ├── m0plus.h │ │ ├── pads_qspi.h │ │ ├── sio.h │ │ └── ssi.h ├── pico.h └── pico │ ├── asm_helper.S │ ├── config.h │ ├── error.h │ ├── platform.h │ ├── types.h │ └── version.h └── lib.rs /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "thumbv6m-none-eabi" 3 | 4 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | on: [push, pull_request] 2 | 3 | name: Continuous integration 4 | 5 | jobs: 6 | ci-linux: 7 | runs-on: ubuntu-24.04 8 | steps: 9 | - uses: actions/checkout@v3 10 | - uses: dtolnay/rust-toolchain@stable 11 | with: 12 | target: thumbv6m-none-eabi 13 | - name: Install gcc 14 | run: sudo apt-get update && sudo apt-get install gcc-arm-none-eabi 15 | - name: Run CI script for thumbv6m-none-eabi 16 | run: bash ./check-blobs.sh 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | bin/*.before 4 | bin/*.after 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Unreleased Changes 4 | 5 | ## v0.3.0 6 | 7 | * Set PICO_FLASH_SPI_CLKDIV=2 when building boot2 8 | 9 | This doubles the flash access speed to the value used by the C SDK by 10 | default. So it should usually be safe. However, if you are overclocking 11 | the RP2040, you might need to lower the flash speed accordingly. 12 | 13 | ## v0.2.1 14 | 15 | * Update boot2 code from SDK version 1.4.0 16 | (No changes to resulting binaries, but include structure is different) 17 | * Add more boot2 versions: 18 | * BOOT_LOADER_W25X10CL 19 | * BOOT_LOADER_GENERIC_03H 20 | * BOOT_LOADER_IS25LP080 21 | 22 | ## v0.2.0 23 | 24 | * Added AT25SF128A support 25 | * Ensured all bootloaders are built on a `cargo build` 26 | * Enable building without GCC by providing precompiled binaries. Use `--feature=assemble` to opt out. 27 | * Added CI using `--feature=assemble` to verify latest boot2 source matches bootloader binary blobs 28 | 29 | ## v0.1.2 30 | 31 | Added description to `Cargo.toml` that prevented publishing. 32 | 33 | ## v0.1.1 34 | 35 | Fixed typo in `Cargo.toml` that prevented publishing. 36 | 37 | ## v0.1.0 38 | 39 | Based on v1.0.0 pico boot2, but hacked to boot to a vector table, not a function, at 0x100. 40 | 41 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | Contribution to these projects is organized under the terms of the [Rust Code of Conduct](https://www.rust-lang.org/policies/code-of-conduct) 2 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rp2040-boot2" 3 | version = "0.3.0" 4 | authors = ["The rp-rs Team"] 5 | edition = "2018" 6 | license = "BSD-3-Clause" 7 | repository = "https://github.com/rp-rs/rp2040-boot2-rs" 8 | description = "Raspberry Pi RP2040 SoC second stage bootloader." 9 | 10 | [dependencies] 11 | 12 | [build-dependencies] 13 | crc-any = "2.3" 14 | 15 | [features] 16 | # Assemble the boot2 files. Requires GCC 17 | assemble = [] 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Raspberry Pi RP2040 Second-Stage Bootloader 2 | 3 | This is a second stage bootloader for the Raspberry Pi RP2040 SoC. 4 | 5 | You can use this crate to include a second-stage bootloader in your application. Simply ensure that your linker script 6 | puts the array exported by this crate at the start of your flash image (0x000 to 0x100). 7 | 8 | ## Instructions 9 | 10 | Add to your application's `Cargo.toml`: 11 | 12 | ```toml 13 | rp2040_boot2 = { version = "0.3" } 14 | ``` 15 | 16 | Add to your `main.rs`: 17 | 18 | ```rust 19 | #[link_section = ".boot_loader"] 20 | #[used] 21 | pub static BOOT_LOADER: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080; 22 | ``` 23 | 24 | This will include support for the W25Q080 flash part on the Raspberry Pi Pico. If you have a board that uses the AT25SF128A (like the Arduino Nano Connect), you can instead use: 25 | 26 | ```rust 27 | #[link_section = ".boot_loader"] 28 | #[used] 29 | pub static BOOT_LOADER: [u8; 256] = rp2040_boot2::BOOT_LOADER_AT25SF128A; 30 | ``` 31 | 32 | Finally, add to your application's `memory.x`: 33 | 34 | ``` 35 | MEMORY 36 | { 37 | /* NOTE 1 K = 1 KiBi = 1024 bytes */ 38 | /* To suit Raspberry Pi RP2040 SoC */ 39 | BOOT_LOADER : ORIGIN = 0x10000000, LENGTH = 0x100 40 | /* Adjust this to suit the size of your specific flash chip */ 41 | FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100 42 | RAM : ORIGIN = 0x20000000, LENGTH = 264K 43 | } 44 | 45 | SECTIONS { 46 | 47 | /* ### Boot loader */ 48 | .boot_loader ORIGIN(BOOT_LOADER) : 49 | { 50 | KEEP(*(.boot_loader*)); 51 | } > BOOT_LOADER 52 | 53 | } INSERT BEFORE .text; 54 | ``` 55 | 56 | ## Booting from RAM 57 | 58 | If you want the bootloader to copy your application from flash to RAM before booting, you can use the boot loader `BOOT_LOADER_RAM_MEMCPY`, this will move all the contents from flash to RAM (up to RAM length). Using this strategy allows for faster execution and flash availability for persistent storage. 59 | 60 | Additionally, you need to change your linker script in order to specify the VMAs & LMAs for all the RAM sections, as in this example 61 | 62 | ``` 63 | .text : { 64 | ... 65 | } > RAM AT > FLASH 66 | ``` 67 | 68 | ## Adding or changing an existing bootloader 69 | 70 | In order to remove the need for GCC for users of this crate, we link against prebuilt versions of each of the bootloaders by default. 71 | 72 | If you wish to add or change an existing bootloader you should install GCC and build with the feature `assemble` 73 | 74 | ``` 75 | UPDATE_PRECOMPILED_BINARIES=true cargo build --features=assemble 76 | ``` 77 | 78 | To add a new bootloader to the build you need to add it to `SOURCE_FILES` in `build.rs` and add an entry for it in `lib.rs` 79 | 80 | Once you are done testing, add the padded binary file in the `bin` folder (example: `bin/boot2_w25q080.padded.bin`) to git 81 | 82 | You can run `check-blobs.sh` to verify that you have built your latest sources before making a Pull Request. 83 | 84 | ## Licence 85 | 86 | Some of the assembly source files are Copyright Raspberry Pi Trading and licensed under a BSD 3-clause licence. See source files for details. 87 | 88 | The remaining files in this crate are licensed as CC0. 89 | 90 | -------------------------------------------------------------------------------- /bin/boot2_at25sf128a.padded.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rp-rs/rp2040-boot2/06402359ca3ec2ef8ce3b8dbade7dc126f95781c/bin/boot2_at25sf128a.padded.bin -------------------------------------------------------------------------------- /bin/boot2_gd25q64cs.padded.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rp-rs/rp2040-boot2/06402359ca3ec2ef8ce3b8dbade7dc126f95781c/bin/boot2_gd25q64cs.padded.bin -------------------------------------------------------------------------------- /bin/boot2_generic_03h.padded.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rp-rs/rp2040-boot2/06402359ca3ec2ef8ce3b8dbade7dc126f95781c/bin/boot2_generic_03h.padded.bin -------------------------------------------------------------------------------- /bin/boot2_is25lp080.padded.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rp-rs/rp2040-boot2/06402359ca3ec2ef8ce3b8dbade7dc126f95781c/bin/boot2_is25lp080.padded.bin -------------------------------------------------------------------------------- /bin/boot2_ram_memcpy.padded.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rp-rs/rp2040-boot2/06402359ca3ec2ef8ce3b8dbade7dc126f95781c/bin/boot2_ram_memcpy.padded.bin -------------------------------------------------------------------------------- /bin/boot2_w25q080.padded.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rp-rs/rp2040-boot2/06402359ca3ec2ef8ce3b8dbade7dc126f95781c/bin/boot2_w25q080.padded.bin -------------------------------------------------------------------------------- /bin/boot2_w25x10cl.padded.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rp-rs/rp2040-boot2/06402359ca3ec2ef8ce3b8dbade7dc126f95781c/bin/boot2_w25x10cl.padded.bin -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | //! Compiles boot2 bootloader from assembler source 2 | //! Compiles the bootloader from assembly language source, and creates a binary file. 3 | 4 | use std::env; 5 | use std::fs; 6 | #[cfg(feature = "assemble")] 7 | use std::io::{self, Write}; 8 | use std::path::Path; 9 | #[cfg(feature = "assemble")] 10 | use std::path::PathBuf; 11 | #[cfg(feature = "assemble")] 12 | use std::process::Command; 13 | 14 | #[cfg(feature = "assemble")] 15 | static SOURCE_FILES: &[&'static str] = &[ 16 | "src/boot2_at25sf128a.S", 17 | "src/boot2_ram_memcpy.S", 18 | "src/boot2_w25q080.S", 19 | "src/boot2_gd25q64cs.S", 20 | "src/boot2_w25x10cl.S", 21 | "src/boot2_generic_03h.S", 22 | "src/boot2_is25lp080.S", 23 | ]; 24 | 25 | #[cfg(feature = "assemble")] 26 | fn make_elf, Q: AsRef>(input_path: P, out_dir: Q) -> PathBuf { 27 | let input_path: &Path = input_path.as_ref(); 28 | let mut result_file = PathBuf::from(input_path.file_name().unwrap()); 29 | result_file.set_extension("elf"); 30 | let result_path = out_dir.as_ref().join(result_file); 31 | let output = Command::new("arm-none-eabi-gcc") 32 | .arg("-nostartfiles") 33 | .arg("-fPIC") 34 | .arg("--specs=nosys.specs") 35 | .arg("-Isrc/include") 36 | .arg("-DPICO_FLASH_SPI_CLKDIV=2") 37 | .arg(input_path) 38 | .arg("-o") 39 | .arg(&result_path) 40 | .output() 41 | .expect("executing arm-none-eabi-gcc"); 42 | io::stderr().write_all(&output.stderr).unwrap(); 43 | if !output.status.success() { 44 | panic!("asm compile failed: {:?}", output); 45 | } 46 | 47 | result_path 48 | } 49 | 50 | #[cfg(feature = "assemble")] 51 | fn make_bin, Q: AsRef>(input_path: P, out_dir: Q) -> PathBuf { 52 | let input_path: &Path = input_path.as_ref(); 53 | let mut result_file = PathBuf::from(input_path.file_name().unwrap()); 54 | result_file.set_extension("bin"); 55 | let result_path = out_dir.as_ref().join(result_file); 56 | let output = Command::new("arm-none-eabi-objcopy") 57 | .arg("-O") 58 | .arg("binary") 59 | .arg(input_path) 60 | .arg(&result_path) 61 | .output() 62 | .expect("executing arm-none-eabi-objcopy"); 63 | io::stderr().write_all(&output.stderr).unwrap(); 64 | if !output.status.success() { 65 | panic!("asm compile failed: {:?}", output); 66 | } 67 | 68 | result_path 69 | } 70 | 71 | #[cfg(feature = "assemble")] 72 | fn make_padded_bin, Q: AsRef>(input_path: P, out_dir: Q) -> PathBuf { 73 | const BOOT2_OUTPUT_LEN: usize = 256; 74 | const MAX_BOOT2_INPUT_LEN: usize = BOOT2_OUTPUT_LEN - 4; 75 | let input_path: &Path = input_path.as_ref(); 76 | let mut blob = fs::read(input_path).expect("reading compiled blob for padding"); 77 | if blob.len() >= MAX_BOOT2_INPUT_LEN { 78 | panic!("boot2 blob is too long!") 79 | } 80 | let num_padding_bytes = MAX_BOOT2_INPUT_LEN - blob.len(); 81 | if num_padding_bytes > 0 { 82 | let padding = vec![0u8; num_padding_bytes]; 83 | blob.extend(padding); 84 | } 85 | let crc_word = calc_crc(&blob); 86 | blob.extend(&crc_word.to_le_bytes()); 87 | 88 | let mut result_file = PathBuf::from(input_path.file_name().unwrap()); 89 | result_file.set_extension("padded.bin"); 90 | let result_path = out_dir.as_ref().join(result_file); 91 | fs::write(&result_path, blob).expect("writing padded output file"); 92 | result_path 93 | } 94 | 95 | #[cfg(feature = "assemble")] 96 | fn calc_crc(data: &[u8]) -> u32 { 97 | let mut engine = crc_any::CRCu32::crc32mpeg2(); 98 | engine.digest(data); 99 | engine.get_crc() 100 | } 101 | 102 | #[cfg(feature = "assemble")] 103 | fn update_precompiled_bin>(input_path: P) { 104 | let input_path: &Path = input_path.as_ref(); 105 | // Abort if this crate is being built as a dependency. 106 | // This check is crude, but CARGO_PRIMARY_PACKAGE is not 107 | // available in build scripts. 108 | if !env::var("OUT_DIR") 109 | .unwrap() 110 | .starts_with(&env::var("CARGO_MANIFEST_DIR").unwrap()) 111 | { 112 | panic!( 113 | "UPDATE_PRECOMPILED_BINARIES must only be used when compiling this package directly" 114 | ); 115 | } 116 | let precompiled_bin_dir = env::var("CARGO_MANIFEST_DIR").unwrap() + "/bin/"; 117 | std::fs::copy( 118 | &input_path, 119 | Path::new(&precompiled_bin_dir).join(input_path.file_name().unwrap()), 120 | ) 121 | .unwrap(); 122 | } 123 | 124 | #[cfg(feature = "assemble")] 125 | fn main() -> Result<(), String> { 126 | let out_dir = env::var("OUT_DIR").unwrap(); 127 | for asm_file in SOURCE_FILES.iter() { 128 | let elf = make_elf(asm_file, &out_dir); 129 | let bin = make_bin(elf, &out_dir); 130 | let padded_bin = make_padded_bin(bin, &out_dir); 131 | if env::var("UPDATE_PRECOMPILED_BINARIES").is_ok() { 132 | update_precompiled_bin(padded_bin); 133 | } 134 | println!("cargo:rerun-if-changed={}", asm_file); 135 | } 136 | println!("cargo:rerun-if-changed=./build.rs"); 137 | println!("cargo:rerun-if-env-changed=UPDATE_PRECOMPILED_BINARIES"); 138 | 139 | Ok(()) 140 | } 141 | 142 | #[cfg(not(feature = "assemble"))] 143 | fn main() -> Result<(), String> { 144 | let in_dir = env::var("CARGO_MANIFEST_DIR").unwrap() + "/bin/"; 145 | let out_dir = env::var("OUT_DIR").unwrap(); 146 | 147 | let paths: Vec<_> = fs::read_dir(in_dir) 148 | .unwrap() 149 | .map(|entry| entry.unwrap().path()) 150 | .collect(); 151 | for path in paths { 152 | if path 153 | .file_name() 154 | .unwrap() 155 | .to_string_lossy() 156 | .ends_with(".padded.bin") 157 | { 158 | std::fs::copy(&path, Path::new(&out_dir).join(path.file_name().unwrap())).unwrap(); 159 | } 160 | } 161 | println!("cargo:warning=Using prebuilt boot2 files. use feature `assemble` to rebuild instead (requires GNU toolchain)"); 162 | Ok(()) 163 | } 164 | -------------------------------------------------------------------------------- /check-blobs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Checks that the blobs are up to date with the committed assembly files 4 | 5 | set -euxo pipefail 6 | 7 | # We could just do `git diff --exit-code bin` but then all the feedback we get is 8 | # Binary files a/bin/boot2_gd25q64cs.padded.bin and b/bin/boot2_gd25q64cs.padded.bin differ 9 | # so lets dissassemble with objdump to get better feedback 10 | 11 | git checkout bin 12 | git clean -f bin 13 | 14 | cargo clean 15 | 16 | for lib in bin/*.bin; do 17 | filename=$(basename "$lib") 18 | arm-none-eabi-objdump -b binary -m armv6-m -M force-thumb -D "$lib" > "bin/${filename%.bin}.before" 19 | done 20 | 21 | UPDATE_PRECOMPILED_BINARIES=true cargo build --features=assemble 22 | 23 | for lib in bin/*.bin; do 24 | filename=$(basename "$lib") 25 | arm-none-eabi-objdump -b binary -m armv6-m -M force-thumb -D "$lib" > "bin/${filename%.bin}.after" 26 | done 27 | 28 | for disassembly in bin/*.after; do 29 | diff -u "$disassembly" "${disassembly%.after}.before" 30 | done 31 | -------------------------------------------------------------------------------- /src/boot2_at25sf128a.S: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // Second stage boot code 3 | // Copyright (c) 2019-2021 Raspberry Pi (Trading) Ltd. 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | // 6 | // Device: Adesto AT25SF128A 7 | // Based on W25Q080 code: main difference is the QE bit is being set 8 | // via command 0x31 9 | // 10 | // Description: Configures AT25SF128A to run in Quad I/O continuous read XIP mode 11 | // 12 | // Details: * Check status register 2 to determine if QSPI mode is enabled, 13 | // and perform an SR2 programming cycle if necessary. 14 | // * Use SSI to perform a dummy 0xEB read command, with the mode 15 | // continuation bits set, so that the flash will not require 16 | // 0xEB instruction prefix on subsequent reads. 17 | // * Configure SSI to write address, mode bits, but no instruction. 18 | // SSI + flash are now jointly in a state where continuous reads 19 | // can take place. 20 | // * Jump to exit pointer passed in via lr. Bootrom passes null, 21 | // in which case this code uses a default 256 byte flash offset 22 | // 23 | // Building: * This code must be position-independent, and use stack only 24 | // * The code will be padded to a size of 256 bytes, including a 25 | // 4-byte checksum. Therefore code size cannot exceed 252 bytes. 26 | // ---------------------------------------------------------------------------- 27 | 28 | #include "pico/asm_helper.S" 29 | #include "hardware/regs/addressmap.h" 30 | #include "hardware/regs/ssi.h" 31 | #include "hardware/regs/pads_qspi.h" 32 | 33 | // ---------------------------------------------------------------------------- 34 | // Config section 35 | // ---------------------------------------------------------------------------- 36 | // It should be possible to support most flash devices by modifying this section 37 | 38 | // The serial flash interface will run at clk_sys/PICO_FLASH_SPI_CLKDIV. 39 | // This must be a positive, even integer. 40 | // The bootrom is very conservative with SPI frequency, but here we should be 41 | // as aggressive as possible. 42 | 43 | #ifndef PICO_FLASH_SPI_CLKDIV 44 | #define PICO_FLASH_SPI_CLKDIV 4 45 | #endif 46 | #if PICO_FLASH_SPI_CLKDIV & 1 47 | #error PICO_FLASH_SPI_CLKDIV must be even 48 | #endif 49 | 50 | // Define interface width: single/dual/quad IO 51 | #define FRAME_FORMAT SSI_CTRLR0_SPI_FRF_VALUE_QUAD 52 | 53 | // For W25Q080 this is the "Read data fast quad IO" instruction: 54 | #define CMD_READ 0xeb 55 | 56 | // "Mode bits" are 8 special bits sent immediately after 57 | // the address bits in a "Read Data Fast Quad I/O" command sequence. 58 | // On W25Q080, the four LSBs are don't care, and if MSBs == 0xa, the 59 | // next read does not require the 0xeb instruction prefix. 60 | #define MODE_CONTINUOUS_READ 0x20 61 | 62 | // The number of address + mode bits, divided by 4 (always 4, not function of 63 | // interface width). 64 | #define ADDR_L 8 65 | 66 | // How many clocks of Hi-Z following the mode bits. For W25Q080, 4 dummy cycles 67 | // are required. 68 | #define WAIT_CYCLES 4 69 | 70 | // If defined, we will read status reg, compare to SREG_DATA, and overwrite 71 | // with our value if the SR doesn't match. 72 | // We do a two-byte write to SR1 (01h cmd) rather than a one-byte write to 73 | // SR2 (31h cmd) as the latter command isn't supported by WX25Q080. 74 | // This isn't great because it will remove block protections. 75 | // A better solution is to use a volatile SR write if your device supports it. 76 | #define PROGRAM_STATUS_REG 77 | 78 | #define CMD_WRITE_ENABLE 0x06 79 | #define CMD_READ_STATUS 0x05 80 | #define CMD_READ_STATUS2 0x35 81 | #define CMD_WRITE_STATUS 0x01 82 | #define CMD_WRITE_STATUS2 0x31 83 | #define SREG_DATA 0x02 // Enable quad-SPI mode 84 | 85 | // ---------------------------------------------------------------------------- 86 | // Start of 2nd Stage Boot Code 87 | // ---------------------------------------------------------------------------- 88 | 89 | .syntax unified 90 | .cpu cortex-m0plus 91 | .thumb 92 | 93 | .section .text 94 | 95 | // The exit point is passed in lr. If entered from bootrom, this will be the 96 | // flash address immediately following this second stage (0x10000100). 97 | // Otherwise it will be a return address -- second stage being called as a 98 | // function by user code, after copying out of XIP region. r3 holds SSI base, 99 | // r0...2 used as temporaries. Other GPRs not used. 100 | .global _stage2_boot 101 | .type _stage2_boot,%function 102 | .thumb_func 103 | _stage2_boot: 104 | push {lr} 105 | 106 | // Set pad configuration: 107 | // - SCLK 8mA drive, no slew limiting 108 | // - SDx disable input Schmitt to reduce delay 109 | 110 | ldr r3, =PADS_QSPI_BASE 111 | movs r0, #(2 << PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_LSB | PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_BITS) 112 | str r0, [r3, #PADS_QSPI_GPIO_QSPI_SCLK_OFFSET] 113 | ldr r0, [r3, #PADS_QSPI_GPIO_QSPI_SD0_OFFSET] 114 | movs r1, #PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_BITS 115 | bics r0, r1 116 | str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD0_OFFSET] 117 | str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD1_OFFSET] 118 | str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD2_OFFSET] 119 | str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD3_OFFSET] 120 | 121 | ldr r3, =XIP_SSI_BASE 122 | 123 | // Disable SSI to allow further config 124 | movs r1, #0 125 | str r1, [r3, #SSI_SSIENR_OFFSET] 126 | 127 | // Set baud rate 128 | movs r1, #PICO_FLASH_SPI_CLKDIV 129 | str r1, [r3, #SSI_BAUDR_OFFSET] 130 | 131 | // Set 1-cycle sample delay. If PICO_FLASH_SPI_CLKDIV == 2 then this means, 132 | // if the flash launches data on SCLK posedge, we capture it at the time that 133 | // the next SCLK posedge is launched. This is shortly before that posedge 134 | // arrives at the flash, so data hold time should be ok. For 135 | // PICO_FLASH_SPI_CLKDIV > 2 this pretty much has no effect. 136 | 137 | movs r1, #1 138 | movs r2, #SSI_RX_SAMPLE_DLY_OFFSET // == 0xf0 so need 8 bits of offset significance 139 | str r1, [r3, r2] 140 | 141 | 142 | // On QSPI parts we usually need a 01h SR-write command to enable QSPI mode 143 | // (i.e. turn WPn and HOLDn into IO2/IO3) 144 | #ifdef PROGRAM_STATUS_REG 145 | program_sregs: 146 | #define CTRL0_SPI_TXRX \ 147 | (7 << SSI_CTRLR0_DFS_32_LSB) | /* 8 bits per data frame */ \ 148 | (SSI_CTRLR0_TMOD_VALUE_TX_AND_RX << SSI_CTRLR0_TMOD_LSB) 149 | 150 | ldr r1, =(CTRL0_SPI_TXRX) 151 | str r1, [r3, #SSI_CTRLR0_OFFSET] 152 | 153 | // Enable SSI and select slave 0 154 | movs r1, #1 155 | str r1, [r3, #SSI_SSIENR_OFFSET] 156 | 157 | // Check whether SR needs updating 158 | movs r0, #CMD_READ_STATUS2 159 | bl read_flash_sreg 160 | movs r2, #SREG_DATA 161 | cmp r0, r2 162 | beq skip_sreg_programming 163 | 164 | // Send write enable command 165 | movs r1, #CMD_WRITE_ENABLE 166 | str r1, [r3, #SSI_DR0_OFFSET] 167 | 168 | // Poll for completion and discard RX 169 | bl wait_ssi_ready 170 | ldr r1, [r3, #SSI_DR0_OFFSET] 171 | 172 | // Send status write command followed by data bytes 173 | movs r1, #CMD_WRITE_STATUS2 174 | str r1, [r3, #SSI_DR0_OFFSET] 175 | str r2, [r3, #SSI_DR0_OFFSET] 176 | 177 | bl wait_ssi_ready 178 | ldr r1, [r3, #SSI_DR0_OFFSET] 179 | ldr r1, [r3, #SSI_DR0_OFFSET] 180 | ldr r1, [r3, #SSI_DR0_OFFSET] 181 | 182 | // Poll status register for write completion 183 | 1: 184 | movs r0, #CMD_READ_STATUS 185 | bl read_flash_sreg 186 | movs r1, #1 187 | tst r0, r1 188 | bne 1b 189 | 190 | skip_sreg_programming: 191 | 192 | // Disable SSI again so that it can be reconfigured 193 | movs r1, #0 194 | str r1, [r3, #SSI_SSIENR_OFFSET] 195 | #endif 196 | 197 | // Currently the flash expects an 8 bit serial command prefix on every 198 | // transfer, which is a waste of cycles. Perform a dummy Fast Read Quad I/O 199 | // command, with mode bits set such that the flash will not expect a serial 200 | // command prefix on *subsequent* transfers. We don't care about the results 201 | // of the read, the important part is the mode bits. 202 | 203 | dummy_read: 204 | #define CTRLR0_ENTER_XIP \ 205 | (FRAME_FORMAT /* Quad I/O mode */ \ 206 | << SSI_CTRLR0_SPI_FRF_LSB) | \ 207 | (31 << SSI_CTRLR0_DFS_32_LSB) | /* 32 data bits */ \ 208 | (SSI_CTRLR0_TMOD_VALUE_EEPROM_READ /* Send INST/ADDR, Receive Data */ \ 209 | << SSI_CTRLR0_TMOD_LSB) 210 | 211 | ldr r1, =(CTRLR0_ENTER_XIP) 212 | str r1, [r3, #SSI_CTRLR0_OFFSET] 213 | 214 | movs r1, #0x0 // NDF=0 (single 32b read) 215 | str r1, [r3, #SSI_CTRLR1_OFFSET] 216 | 217 | #define SPI_CTRLR0_ENTER_XIP \ 218 | (ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Address + mode bits */ \ 219 | (WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \ 220 | (SSI_SPI_CTRLR0_INST_L_VALUE_8B \ 221 | << SSI_SPI_CTRLR0_INST_L_LSB) | /* 8-bit instruction */ \ 222 | (SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C2A /* Send Command in serial mode then address in Quad I/O mode */ \ 223 | << SSI_SPI_CTRLR0_TRANS_TYPE_LSB) 224 | 225 | ldr r1, =(SPI_CTRLR0_ENTER_XIP) 226 | ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) // SPI_CTRL0 Register 227 | str r1, [r0] 228 | 229 | movs r1, #1 // Re-enable SSI 230 | str r1, [r3, #SSI_SSIENR_OFFSET] 231 | 232 | movs r1, #CMD_READ 233 | str r1, [r3, #SSI_DR0_OFFSET] // Push SPI command into TX FIFO 234 | movs r1, #MODE_CONTINUOUS_READ // 32-bit: 24 address bits (we don't care, so 0) and M[7:4]=1010 235 | str r1, [r3, #SSI_DR0_OFFSET] // Push Address into TX FIFO - this will trigger the transaction 236 | 237 | // Poll for completion 238 | bl wait_ssi_ready 239 | 240 | // The flash is in a state where we can blast addresses in parallel, and get 241 | // parallel data back. Now configure the SSI to translate XIP bus accesses 242 | // into QSPI transfers of this form. 243 | 244 | movs r1, #0 245 | str r1, [r3, #SSI_SSIENR_OFFSET] // Disable SSI (and clear FIFO) to allow further config 246 | 247 | // Note that the INST_L field is used to select what XIP data gets pushed into 248 | // the TX FIFO: 249 | // INST_L_0_BITS {ADDR[23:0],XIP_CMD[7:0]} Load "mode bits" into XIP_CMD 250 | // Anything else {XIP_CMD[7:0],ADDR[23:0]} Load SPI command into XIP_CMD 251 | configure_ssi: 252 | #define SPI_CTRLR0_XIP \ 253 | (MODE_CONTINUOUS_READ /* Mode bits to keep flash in continuous read mode */ \ 254 | << SSI_SPI_CTRLR0_XIP_CMD_LSB) | \ 255 | (ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Total number of address + mode bits */ \ 256 | (WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \ 257 | (SSI_SPI_CTRLR0_INST_L_VALUE_NONE /* Do not send a command, instead send XIP_CMD as mode bits after address */ \ 258 | << SSI_SPI_CTRLR0_INST_L_LSB) | \ 259 | (SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_2C2A /* Send Address in Quad I/O mode (and Command but that is zero bits long) */ \ 260 | << SSI_SPI_CTRLR0_TRANS_TYPE_LSB) 261 | 262 | ldr r1, =(SPI_CTRLR0_XIP) 263 | ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) 264 | str r1, [r0] 265 | 266 | movs r1, #1 267 | str r1, [r3, #SSI_SSIENR_OFFSET] // Re-enable SSI 268 | 269 | // Bus accesses to the XIP window will now be transparently serviced by the 270 | // external flash on cache miss. We are ready to run code from flash. 271 | 272 | // Pull in standard exit routine 273 | #include "boot2_helpers/exit_from_boot2.S" 274 | 275 | // Common functions 276 | #include "boot2_helpers/wait_ssi_ready.S" 277 | #ifdef PROGRAM_STATUS_REG 278 | #include "boot2_helpers/read_flash_sreg.S" 279 | #endif 280 | 281 | .global literals 282 | literals: 283 | .ltorg 284 | 285 | .end 286 | -------------------------------------------------------------------------------- /src/boot2_gd25q64cs.S: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // Second stage boot code 3 | // Copyright (c) 2019-2021 Raspberry Pi (Trading) Ltd. 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | // 6 | // Device: GigaDevice Semiconductor GD25Q64CSIG 7 | // 8 | // 9 | // Description: Configures GD25Q64CSIG to run in Quad I/O continuous read XIP mode 10 | // 11 | // Details: * Check status register 2 to determine if QSPI mode is enabled, 12 | // and perform an SR2 programming cycle if necessary. 13 | // * Use SSI to perform a dummy 0xEB read command, with the mode 14 | // continuation bits set, so that the flash will not require 15 | // 0xEB instruction prefix on subsequent reads. 16 | // * Configure SSI to write address, mode bits, but no instruction. 17 | // SSI + flash are now jointly in a state where continuous reads 18 | // can take place. 19 | // * Jump to exit pointer passed in via lr. Bootrom passes null, 20 | // in which case this code uses a default 256 byte flash offset 21 | // 22 | // Building: * This code must be position-independent, and use stack only 23 | // * The code will be padded to a size of 256 bytes, including a 24 | // 4-byte checksum. Therefore code size cannot exceed 252 bytes. 25 | // ---------------------------------------------------------------------------- 26 | 27 | #include "pico/asm_helper.S" 28 | #include "hardware/regs/addressmap.h" 29 | #include "hardware/regs/ssi.h" 30 | #include "hardware/regs/pads_qspi.h" 31 | 32 | // ---------------------------------------------------------------------------- 33 | // Config section 34 | // ---------------------------------------------------------------------------- 35 | // It should be possible to support most flash devices by modifying this section 36 | 37 | // The serial flash interface will run at clk_sys/PICO_FLASH_SPI_CLKDIV. 38 | // This must be a positive, even integer. 39 | // The bootrom is very conservative with SPI frequency, but here we should be 40 | // as aggressive as possible. 41 | 42 | #ifndef PICO_FLASH_SPI_CLKDIV 43 | #define PICO_FLASH_SPI_CLKDIV 4 44 | #endif 45 | #if PICO_FLASH_SPI_CLKDIV & 1 46 | #error PICO_FLASH_SPI_CLKDIV must be even 47 | #endif 48 | 49 | // Define interface width: single/dual/quad IO 50 | #define FRAME_FORMAT SSI_CTRLR0_SPI_FRF_VALUE_QUAD 51 | 52 | // For GD25Q64CSIG this is the "Read data fast quad IO" instruction: 53 | #define CMD_READ 0xe7 54 | 55 | // "Mode bits" are 8 special bits sent immediately after 56 | // the address bits in a "Read Data Fast Quad I/O" command sequence. 57 | // On GD25Q64CSIG, the four LSBs are don't care, and if MSBs == 0xa0, the 58 | // next read does not require the 0xeb instruction prefix. 59 | #define MODE_CONTINUOUS_READ 0xa0 60 | 61 | // The number of address + mode bits, divided by 4 (always 4, not function of 62 | // interface width). 63 | #define ADDR_L 8 64 | 65 | // How many clocks of Hi-Z following the mode bits. For GD25Q64CSIG, 2 dummy cycles 66 | // are required. 67 | #define WAIT_CYCLES 2 68 | 69 | // If defined, we will read status reg, compare to SREG_DATA, and overwrite 70 | // with our value if the SR doesn't match. 71 | // We do a two-byte write to SR1 (01h cmd) rather than a one-byte write to 72 | // SR2 (31h cmd) as the latter command isn't supported by WX25Q080. 73 | // This isn't great because it will remove block protections. 74 | // A better solution is to use a volatile SR write if your device supports it. 75 | #define PROGRAM_STATUS_REG 76 | 77 | #define CMD_WRITE_ENABLE 0x06 78 | #define CMD_READ_STATUS 0x05 79 | #define CMD_READ_STATUS2 0x35 80 | #define CMD_WRITE_STATUS 0x01 81 | #define CMD_WRITE_STATUS2 0x31 82 | #define SREG_DATA 0x02 // Enable quad-SPI mode 83 | 84 | // ---------------------------------------------------------------------------- 85 | // Start of 2nd Stage Boot Code 86 | // ---------------------------------------------------------------------------- 87 | 88 | .syntax unified 89 | .cpu cortex-m0plus 90 | .thumb 91 | 92 | .section .text 93 | 94 | // The exit point is passed in lr. If entered from bootrom, this will be the 95 | // flash address immediately following this second stage (0x10000100). 96 | // Otherwise it will be a return address -- second stage being called as a 97 | // function by user code, after copying out of XIP region. r3 holds SSI base, 98 | // r0...2 used as temporaries. Other GPRs not used. 99 | .global _stage2_boot 100 | .type _stage2_boot,%function 101 | .thumb_func 102 | _stage2_boot: 103 | push {lr} 104 | 105 | // Set pad configuration: 106 | // - SCLK 8mA drive, no slew limiting 107 | // - SDx disable input Schmitt to reduce delay 108 | 109 | ldr r3, =PADS_QSPI_BASE 110 | movs r0, #(2 << PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_LSB | PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_BITS) 111 | str r0, [r3, #PADS_QSPI_GPIO_QSPI_SCLK_OFFSET] 112 | ldr r0, [r3, #PADS_QSPI_GPIO_QSPI_SD0_OFFSET] 113 | movs r1, #PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_BITS 114 | bics r0, r1 115 | str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD0_OFFSET] 116 | str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD1_OFFSET] 117 | str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD2_OFFSET] 118 | str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD3_OFFSET] 119 | 120 | ldr r3, =XIP_SSI_BASE 121 | 122 | // Disable SSI to allow further config 123 | movs r1, #0 124 | str r1, [r3, #SSI_SSIENR_OFFSET] 125 | 126 | // Set baud rate 127 | movs r1, #PICO_FLASH_SPI_CLKDIV 128 | str r1, [r3, #SSI_BAUDR_OFFSET] 129 | 130 | // Set 1-cycle sample delay. If PICO_FLASH_SPI_CLKDIV == 2 then this means, 131 | // if the flash launches data on SCLK posedge, we capture it at the time that 132 | // the next SCLK posedge is launched. This is shortly before that posedge 133 | // arrives at the flash, so data hold time should be ok. For 134 | // PICO_FLASH_SPI_CLKDIV > 2 this pretty much has no effect. 135 | 136 | movs r1, #1 137 | movs r2, #SSI_RX_SAMPLE_DLY_OFFSET // == 0xf0 so need 8 bits of offset significance 138 | str r1, [r3, r2] 139 | 140 | 141 | // On QSPI parts we usually need a 01h SR-write command to enable QSPI mode 142 | // (i.e. turn WPn and HOLDn into IO2/IO3) 143 | #ifdef PROGRAM_STATUS_REG 144 | program_sregs: 145 | #define CTRL0_SPI_TXRX \ 146 | (7 << SSI_CTRLR0_DFS_32_LSB) | /* 8 bits per data frame */ \ 147 | (SSI_CTRLR0_TMOD_VALUE_TX_AND_RX << SSI_CTRLR0_TMOD_LSB) 148 | 149 | ldr r1, =(CTRL0_SPI_TXRX) 150 | str r1, [r3, #SSI_CTRLR0_OFFSET] 151 | 152 | // Enable SSI and select slave 0 153 | movs r1, #1 154 | str r1, [r3, #SSI_SSIENR_OFFSET] 155 | 156 | // Check whether SR needs updating 157 | movs r0, #CMD_READ_STATUS2 158 | bl read_flash_sreg 159 | movs r2, #SREG_DATA 160 | cmp r0, r2 161 | beq skip_sreg_programming 162 | 163 | // Send write enable command 164 | movs r1, #CMD_WRITE_ENABLE 165 | str r1, [r3, #SSI_DR0_OFFSET] 166 | 167 | // Poll for completion and discard RX 168 | bl wait_ssi_ready 169 | ldr r1, [r3, #SSI_DR0_OFFSET] 170 | 171 | // Send status write command followed by data bytes 172 | movs r1, #CMD_WRITE_STATUS2 173 | str r1, [r3, #SSI_DR0_OFFSET] 174 | str r2, [r3, #SSI_DR0_OFFSET] 175 | 176 | bl wait_ssi_ready 177 | ldr r1, [r3, #SSI_DR0_OFFSET] 178 | ldr r1, [r3, #SSI_DR0_OFFSET] 179 | ldr r1, [r3, #SSI_DR0_OFFSET] 180 | 181 | // Poll status register for write completion 182 | 1: 183 | movs r0, #CMD_READ_STATUS 184 | bl read_flash_sreg 185 | movs r1, #1 186 | tst r0, r1 187 | bne 1b 188 | 189 | skip_sreg_programming: 190 | 191 | // Disable SSI again so that it can be reconfigured 192 | movs r1, #0 193 | str r1, [r3, #SSI_SSIENR_OFFSET] 194 | #endif 195 | 196 | // Currently the flash expects an 8 bit serial command prefix on every 197 | // transfer, which is a waste of cycles. Perform a dummy Fast Read Quad I/O 198 | // command, with mode bits set such that the flash will not expect a serial 199 | // command prefix on *subsequent* transfers. We don't care about the results 200 | // of the read, the important part is the mode bits. 201 | 202 | dummy_read: 203 | #define CTRLR0_ENTER_XIP \ 204 | (FRAME_FORMAT /* Quad I/O mode */ \ 205 | << SSI_CTRLR0_SPI_FRF_LSB) | \ 206 | (31 << SSI_CTRLR0_DFS_32_LSB) | /* 32 data bits */ \ 207 | (SSI_CTRLR0_TMOD_VALUE_EEPROM_READ /* Send INST/ADDR, Receive Data */ \ 208 | << SSI_CTRLR0_TMOD_LSB) 209 | 210 | ldr r1, =(CTRLR0_ENTER_XIP) 211 | str r1, [r3, #SSI_CTRLR0_OFFSET] 212 | 213 | movs r1, #0x0 // NDF=0 (single 32b read) 214 | str r1, [r3, #SSI_CTRLR1_OFFSET] 215 | 216 | #define SPI_CTRLR0_ENTER_XIP \ 217 | (ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Address + mode bits */ \ 218 | (WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \ 219 | (SSI_SPI_CTRLR0_INST_L_VALUE_8B \ 220 | << SSI_SPI_CTRLR0_INST_L_LSB) | /* 8-bit instruction */ \ 221 | (SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C2A /* Send Command in serial mode then address in Quad I/O mode */ \ 222 | << SSI_SPI_CTRLR0_TRANS_TYPE_LSB) 223 | 224 | ldr r1, =(SPI_CTRLR0_ENTER_XIP) 225 | ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) // SPI_CTRL0 Register 226 | str r1, [r0] 227 | 228 | movs r1, #1 // Re-enable SSI 229 | str r1, [r3, #SSI_SSIENR_OFFSET] 230 | 231 | movs r1, #CMD_READ 232 | str r1, [r3, #SSI_DR0_OFFSET] // Push SPI command into TX FIFO 233 | movs r1, #MODE_CONTINUOUS_READ // 32-bit: 24 address bits (we don't care, so 0) and M[7:4]=1010 234 | str r1, [r3, #SSI_DR0_OFFSET] // Push Address into TX FIFO - this will trigger the transaction 235 | 236 | // Poll for completion 237 | bl wait_ssi_ready 238 | 239 | // The flash is in a state where we can blast addresses in parallel, and get 240 | // parallel data back. Now configure the SSI to translate XIP bus accesses 241 | // into QSPI transfers of this form. 242 | 243 | movs r1, #0 244 | str r1, [r3, #SSI_SSIENR_OFFSET] // Disable SSI (and clear FIFO) to allow further config 245 | 246 | // Note that the INST_L field is used to select what XIP data gets pushed into 247 | // the TX FIFO: 248 | // INST_L_0_BITS {ADDR[23:0],XIP_CMD[7:0]} Load "mode bits" into XIP_CMD 249 | // Anything else {XIP_CMD[7:0],ADDR[23:0]} Load SPI command into XIP_CMD 250 | configure_ssi: 251 | #define SPI_CTRLR0_XIP \ 252 | (MODE_CONTINUOUS_READ /* Mode bits to keep flash in continuous read mode */ \ 253 | << SSI_SPI_CTRLR0_XIP_CMD_LSB) | \ 254 | (ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Total number of address + mode bits */ \ 255 | (WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \ 256 | (SSI_SPI_CTRLR0_INST_L_VALUE_NONE /* Do not send a command, instead send XIP_CMD as mode bits after address */ \ 257 | << SSI_SPI_CTRLR0_INST_L_LSB) | \ 258 | (SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_2C2A /* Send Address in Quad I/O mode (and Command but that is zero bits long) */ \ 259 | << SSI_SPI_CTRLR0_TRANS_TYPE_LSB) 260 | 261 | ldr r1, =(SPI_CTRLR0_XIP) 262 | ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) 263 | str r1, [r0] 264 | 265 | movs r1, #1 266 | str r1, [r3, #SSI_SSIENR_OFFSET] // Re-enable SSI 267 | 268 | // Bus accesses to the XIP window will now be transparently serviced by the 269 | // external flash on cache miss. We are ready to run code from flash. 270 | 271 | 272 | // Bus accesses to the XIP window will now be transparently serviced by the 273 | // external flash on cache miss. We are ready to run code from flash. 274 | 275 | check_return: 276 | pop {r0} 277 | cmp r0, #0 278 | beq vector_into_flash 279 | bx r0 280 | vector_into_flash: 281 | ldr r0, =(XIP_BASE + 0x100) 282 | ldr r1, =(PPB_BASE + M0PLUS_VTOR_OFFSET) 283 | str r0, [r1] 284 | ldmia r0, {r0, r1} 285 | msr msp, r0 286 | bx r1 287 | 288 | // Common functions 289 | 290 | wait_ssi_ready: 291 | push {r0, r1, lr} 292 | 293 | // Command is complete when there is nothing left to send 294 | // (TX FIFO empty) and SSI is no longer busy (CSn deasserted) 295 | 1: 296 | ldr r1, [r3, #SSI_SR_OFFSET] 297 | movs r0, #SSI_SR_TFE_BITS 298 | tst r1, r0 299 | beq 1b 300 | movs r0, #SSI_SR_BUSY_BITS 301 | tst r1, r0 302 | bne 1b 303 | 304 | pop {r0, r1, pc} 305 | 306 | #ifdef PROGRAM_STATUS_REG 307 | // Pass status read cmd into r0. 308 | // Returns status value in r0. 309 | .global read_flash_sreg 310 | .type read_flash_sreg,%function 311 | .thumb_func 312 | read_flash_sreg: 313 | push {r1, lr} 314 | str r0, [r3, #SSI_DR0_OFFSET] 315 | // Dummy byte: 316 | str r0, [r3, #SSI_DR0_OFFSET] 317 | 318 | bl wait_ssi_ready 319 | // Discard first byte and combine the next two 320 | ldr r0, [r3, #SSI_DR0_OFFSET] 321 | ldr r0, [r3, #SSI_DR0_OFFSET] 322 | 323 | pop {r1, pc} 324 | #endif 325 | 326 | 327 | .global literals 328 | literals: 329 | .ltorg 330 | 331 | .end 332 | -------------------------------------------------------------------------------- /src/boot2_generic_03h.S: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // Second stage boot code 3 | // Copyright (c) 2019-2021 Raspberry Pi (Trading) Ltd. 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | // 6 | // Device: Anything which responds to 03h serial read command 7 | // 8 | // Details: * Configure SSI to translate each APB read into a 03h command 9 | // * 8 command clocks, 24 address clocks and 32 data clocks 10 | // * This enables you to boot from almost anything: you can pretty 11 | // much solder a potato to your PCB, or a piece of cheese 12 | // * The tradeoff is performance around 3x worse than QSPI XIP 13 | // 14 | // Building: * This code must be position-independent, and use stack only 15 | // * The code will be padded to a size of 256 bytes, including a 16 | // 4-byte checksum. Therefore code size cannot exceed 252 bytes. 17 | // ---------------------------------------------------------------------------- 18 | 19 | #include "pico/asm_helper.S" 20 | #include "hardware/regs/addressmap.h" 21 | #include "hardware/regs/ssi.h" 22 | 23 | // ---------------------------------------------------------------------------- 24 | // Config section 25 | // ---------------------------------------------------------------------------- 26 | // It should be possible to support most flash devices by modifying this section 27 | 28 | // The serial flash interface will run at clk_sys/PICO_FLASH_SPI_CLKDIV. 29 | // This must be a positive, even integer. 30 | // The bootrom is very conservative with SPI frequency, but here we should be 31 | // as aggressive as possible. 32 | #ifndef PICO_FLASH_SPI_CLKDIV 33 | #define PICO_FLASH_SPI_CLKDIV 4 34 | #endif 35 | 36 | #define CMD_READ 0x03 37 | 38 | // Value is number of address bits divided by 4 39 | #define ADDR_L 6 40 | 41 | #define CTRLR0_XIP \ 42 | (SSI_CTRLR0_SPI_FRF_VALUE_STD << SSI_CTRLR0_SPI_FRF_LSB) | /* Standard 1-bit SPI serial frames */ \ 43 | (31 << SSI_CTRLR0_DFS_32_LSB) | /* 32 clocks per data frame */ \ 44 | (SSI_CTRLR0_TMOD_VALUE_EEPROM_READ << SSI_CTRLR0_TMOD_LSB) /* Send instr + addr, receive data */ 45 | 46 | #define SPI_CTRLR0_XIP \ 47 | (CMD_READ << SSI_SPI_CTRLR0_XIP_CMD_LSB) | /* Value of instruction prefix */ \ 48 | (ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Total number of address + mode bits */ \ 49 | (2 << SSI_SPI_CTRLR0_INST_L_LSB) | /* 8 bit command prefix (field value is bits divided by 4) */ \ 50 | (SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C1A << SSI_SPI_CTRLR0_TRANS_TYPE_LSB) /* command and address both in serial format */ 51 | 52 | // ---------------------------------------------------------------------------- 53 | // Start of 2nd Stage Boot Code 54 | // ---------------------------------------------------------------------------- 55 | 56 | .cpu cortex-m0 57 | .thumb 58 | 59 | .section .text 60 | 61 | .global _stage2_boot 62 | .type _stage2_boot,%function 63 | .thumb_func 64 | _stage2_boot: 65 | push {lr} 66 | 67 | ldr r3, =XIP_SSI_BASE // Use as base address where possible 68 | 69 | // Disable SSI to allow further config 70 | mov r1, #0 71 | str r1, [r3, #SSI_SSIENR_OFFSET] 72 | 73 | // Set baud rate 74 | mov r1, #PICO_FLASH_SPI_CLKDIV 75 | str r1, [r3, #SSI_BAUDR_OFFSET] 76 | 77 | ldr r1, =(CTRLR0_XIP) 78 | str r1, [r3, #SSI_CTRLR0_OFFSET] 79 | 80 | ldr r1, =(SPI_CTRLR0_XIP) 81 | ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) 82 | str r1, [r0] 83 | 84 | // NDF=0 (single 32b read) 85 | mov r1, #0x0 86 | str r1, [r3, #SSI_CTRLR1_OFFSET] 87 | 88 | // Re-enable SSI 89 | mov r1, #1 90 | str r1, [r3, #SSI_SSIENR_OFFSET] 91 | 92 | // We are now in XIP mode. Any bus accesses to the XIP address window will be 93 | // translated by the SSI into 03h read commands to the external flash (if cache is missed), 94 | // and the data will be returned to the bus. 95 | 96 | // Pull in standard exit routine 97 | #include "boot2_helpers/exit_from_boot2.S" 98 | 99 | .global literals 100 | literals: 101 | .ltorg 102 | 103 | .end 104 | -------------------------------------------------------------------------------- /src/boot2_is25lp080.S: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // Copyright (c) 2019-2021 Raspberry Pi (Trading) Ltd. 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | // 5 | // Device: ISSI IS25LP080D 6 | // Based on W25Q080 code: main difference is the QE bit being in 7 | // SR1 instead of SR2. 8 | // 9 | // Description: Configures IS25LP080D to run in Quad I/O continuous read XIP mode 10 | // 11 | // Details: * Check status register to determine if QSPI mode is enabled, 12 | // and perform an SR programming cycle if necessary. 13 | // * Use SSI to perform a dummy 0xEB read command, with the mode 14 | // continuation bits set, so that the flash will not require 15 | // 0xEB instruction prefix on subsequent reads. 16 | // * Configure SSI to write address, mode bits, but no instruction. 17 | // SSI + flash are now jointly in a state where continuous reads 18 | // can take place. 19 | // * Set VTOR = 0x10000100 (user vector table immediately after 20 | // this boot2 image). 21 | // * Read stack pointer (MSP) and reset vector from the flash 22 | // vector table; set SP and jump, as though the processor had 23 | // booted directly from flash. 24 | // 25 | // Building: * This code must be linked to run at 0x20027f00 26 | // * The code will be padded to a size of 256 bytes, including a 27 | // 4-byte checksum. Therefore code size cannot exceed 252 bytes. 28 | // ---------------------------------------------------------------------------- 29 | 30 | #include "pico/asm_helper.S" 31 | #include "hardware/regs/addressmap.h" 32 | #include "hardware/regs/ssi.h" 33 | 34 | // ---------------------------------------------------------------------------- 35 | // Config section 36 | // ---------------------------------------------------------------------------- 37 | // It should be possible to support most flash devices by modifying this section 38 | 39 | // The serial flash interface will run at clk_sys/PICO_FLASH_SPI_CLKDIV. 40 | // This must be a positive, even integer. 41 | // The bootrom is very conservative with SPI frequency, but here we should be 42 | // as aggressive as possible. 43 | #ifndef PICO_FLASH_SPI_CLKDIV 44 | #define PICO_FLASH_SPI_CLKDIV 4 45 | #endif 46 | 47 | 48 | // Define interface width: single/dual/quad IO 49 | #define FRAME_FORMAT SSI_CTRLR0_SPI_FRF_VALUE_QUAD 50 | 51 | // For W25Q080 this is the "Read data fast quad IO" instruction: 52 | #define CMD_READ 0xeb 53 | 54 | // "Mode bits" are 8 special bits sent immediately after 55 | // the address bits in a "Read Data Fast Quad I/O" command sequence. 56 | // On W25Q080, the four LSBs are don't care, and if MSBs == 0xa, the 57 | // next read does not require the 0xeb instruction prefix. 58 | #define MODE_CONTINUOUS_READ 0xa0 59 | 60 | // The number of address + mode bits, divided by 4 (always 4, not function of 61 | // interface width). 62 | #define ADDR_L 8 63 | 64 | // How many clocks of Hi-Z following the mode bits. For W25Q080, 4 dummy cycles 65 | // are required. 66 | #define WAIT_CYCLES 4 67 | 68 | // If defined, we will read status reg, compare to SREG_DATA, and overwrite 69 | // with our value if the SR doesn't match. 70 | // This isn't great because it will remove block protections. 71 | // A better solution is to use a volatile SR write if your device supports it. 72 | #define PROGRAM_STATUS_REG 73 | 74 | #define CMD_WRITE_ENABLE 0x06 75 | #define CMD_READ_STATUS 0x05 76 | #define CMD_WRITE_STATUS 0x01 77 | #define SREG_DATA 0x40 // Enable quad-SPI mode 78 | 79 | // ---------------------------------------------------------------------------- 80 | // Start of 2nd Stage Boot Code 81 | // ---------------------------------------------------------------------------- 82 | 83 | .cpu cortex-m0 84 | .thumb 85 | 86 | .section .text 87 | 88 | .global _stage2_boot 89 | .type _stage2_boot,%function 90 | .thumb_func 91 | _stage2_boot: 92 | push {lr} 93 | 94 | ldr r3, =XIP_SSI_BASE // Use as base address where possible 95 | 96 | // Disable SSI to allow further config 97 | mov r1, #0 98 | str r1, [r3, #SSI_SSIENR_OFFSET] 99 | 100 | // Set baud rate 101 | mov r1, #PICO_FLASH_SPI_CLKDIV 102 | str r1, [r3, #SSI_BAUDR_OFFSET] 103 | 104 | // On QSPI parts we usually need a 01h SR-write command to enable QSPI mode 105 | // (i.e. turn WPn and HOLDn into IO2/IO3) 106 | #ifdef PROGRAM_STATUS_REG 107 | program_sregs: 108 | #define CTRL0_SPI_TXRX \ 109 | (7 << SSI_CTRLR0_DFS_32_LSB) | /* 8 bits per data frame */ \ 110 | (SSI_CTRLR0_TMOD_VALUE_TX_AND_RX << SSI_CTRLR0_TMOD_LSB) 111 | 112 | ldr r1, =(CTRL0_SPI_TXRX) 113 | str r1, [r3, #SSI_CTRLR0_OFFSET] 114 | 115 | // Enable SSI and select slave 0 116 | mov r1, #1 117 | str r1, [r3, #SSI_SSIENR_OFFSET] 118 | 119 | // Check whether SR needs updating 120 | ldr r0, =CMD_READ_STATUS 121 | bl read_flash_sreg 122 | ldr r2, =SREG_DATA 123 | cmp r0, r2 124 | beq skip_sreg_programming 125 | 126 | // Send write enable command 127 | mov r1, #CMD_WRITE_ENABLE 128 | str r1, [r3, #SSI_DR0_OFFSET] 129 | 130 | // Poll for completion and discard RX 131 | bl wait_ssi_ready 132 | ldr r1, [r3, #SSI_DR0_OFFSET] 133 | 134 | // Send status write command followed by data bytes 135 | mov r1, #CMD_WRITE_STATUS 136 | str r1, [r3, #SSI_DR0_OFFSET] 137 | mov r0, #0 138 | str r2, [r3, #SSI_DR0_OFFSET] 139 | 140 | bl wait_ssi_ready 141 | ldr r1, [r3, #SSI_DR0_OFFSET] 142 | ldr r1, [r3, #SSI_DR0_OFFSET] 143 | 144 | // Poll status register for write completion 145 | 1: 146 | ldr r0, =CMD_READ_STATUS 147 | bl read_flash_sreg 148 | mov r1, #1 149 | tst r0, r1 150 | bne 1b 151 | 152 | skip_sreg_programming: 153 | 154 | // Send a 0xA3 high-performance-mode instruction 155 | // ldr r1, =0xa3 156 | // str r1, [r3, #SSI_DR0_OFFSET] 157 | // bl wait_ssi_ready 158 | 159 | // Disable SSI again so that it can be reconfigured 160 | mov r1, #0 161 | str r1, [r3, #SSI_SSIENR_OFFSET] 162 | #endif 163 | 164 | 165 | // First we need to send the initial command to get us in to Fast Read Quad I/O 166 | // mode. As this transaction requires a command, we can't send it in XIP mode. 167 | // To enter Continuous Read mode as well we need to append 4'b0010 to the address 168 | // bits and then add a further 4 don't care bits. We will construct this by 169 | // specifying a 28-bit address, with the least significant bits being 4'b0010. 170 | // This is just a dummy transaction so we'll perform a read from address zero 171 | // and then discard what comes back. All we really care about is that at the 172 | // end of the transaction, the flash device is in Continuous Read mode 173 | // and from then on will only expect to receive addresses. 174 | dummy_read: 175 | #define CTRLR0_ENTER_XIP \ 176 | (FRAME_FORMAT /* Quad I/O mode */ \ 177 | << SSI_CTRLR0_SPI_FRF_LSB) | \ 178 | (31 << SSI_CTRLR0_DFS_32_LSB) | /* 32 data bits */ \ 179 | (SSI_CTRLR0_TMOD_VALUE_EEPROM_READ /* Send INST/ADDR, Receive Data */ \ 180 | << SSI_CTRLR0_TMOD_LSB) 181 | 182 | ldr r1, =(CTRLR0_ENTER_XIP) 183 | str r1, [r3, #SSI_CTRLR0_OFFSET] 184 | 185 | mov r1, #0x0 // NDF=0 (single 32b read) 186 | str r1, [r3, #SSI_CTRLR1_OFFSET] 187 | 188 | #define SPI_CTRLR0_ENTER_XIP \ 189 | (ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Address + mode bits */ \ 190 | (WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \ 191 | (SSI_SPI_CTRLR0_INST_L_VALUE_8B \ 192 | << SSI_SPI_CTRLR0_INST_L_LSB) | /* 8-bit instruction */ \ 193 | (SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C2A /* Send Command in serial mode then address in Quad I/O mode */ \ 194 | << SSI_SPI_CTRLR0_TRANS_TYPE_LSB) 195 | 196 | ldr r1, =(SPI_CTRLR0_ENTER_XIP) 197 | ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) // SPI_CTRL0 Register 198 | str r1, [r0] 199 | 200 | mov r1, #1 // Re-enable SSI 201 | str r1, [r3, #SSI_SSIENR_OFFSET] 202 | 203 | mov r1, #CMD_READ 204 | str r1, [r3, #SSI_DR0_OFFSET] // Push SPI command into TX FIFO 205 | mov r1, #MODE_CONTINUOUS_READ // 32-bit: 24 address bits (we don't care, so 0) and M[7:4]=1010 206 | str r1, [r3, #SSI_DR0_OFFSET] // Push Address into TX FIFO - this will trigger the transaction 207 | 208 | // Poll for completion 209 | bl wait_ssi_ready 210 | 211 | // At this point CN# will be deasserted and the SPI clock will not be running. 212 | // The Winbond WX25X10CL device will be in continuous read, dual I/O mode and 213 | // only expecting address bits after the next CN# assertion. So long as we 214 | // send 4'b0010 (and 4 more dummy HiZ bits) after every subsequent 24b address 215 | // then the Winbond device will remain in continuous read mode. This is the 216 | // ideal mode for Execute-In-Place. 217 | // (If we want to exit continuous read mode then we will need to switch back 218 | // to APM mode and generate a 28-bit address phase with the extra nibble set 219 | // to 4'b0000). 220 | 221 | mov r1, #0 222 | str r1, [r3, #SSI_SSIENR_OFFSET] // Disable SSI (and clear FIFO) to allow further config 223 | 224 | // Note that the INST_L field is used to select what XIP data gets pushed into 225 | // the TX FIFO: 226 | // INST_L_0_BITS {ADDR[23:0],XIP_CMD[7:0]} Load "mode bits" into XIP_CMD 227 | // Anything else {XIP_CMD[7:0],ADDR[23:0]} Load SPI command into XIP_CMD 228 | configure_ssi: 229 | #define SPI_CTRLR0_XIP \ 230 | (MODE_CONTINUOUS_READ /* Mode bits to keep flash in continuous read mode */ \ 231 | << SSI_SPI_CTRLR0_XIP_CMD_LSB) | \ 232 | (ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Total number of address + mode bits */ \ 233 | (WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \ 234 | (SSI_SPI_CTRLR0_INST_L_VALUE_NONE /* Do not send a command, instead send XIP_CMD as mode bits after address */ \ 235 | << SSI_SPI_CTRLR0_INST_L_LSB) | \ 236 | (SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_2C2A /* Send Address in Quad I/O mode (and Command but that is zero bits long) */ \ 237 | << SSI_SPI_CTRLR0_TRANS_TYPE_LSB) 238 | 239 | ldr r1, =(SPI_CTRLR0_XIP) 240 | ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) 241 | str r1, [r0] 242 | 243 | mov r1, #1 244 | str r1, [r3, #SSI_SSIENR_OFFSET] // Re-enable SSI 245 | 246 | // We are now in XIP mode, with all transactions using Dual I/O and only 247 | // needing to send 24-bit addresses (plus mode bits) for each read transaction. 248 | 249 | // Pull in standard exit routine 250 | #include "boot2_helpers/exit_from_boot2.S" 251 | 252 | // Common functions 253 | #include "boot2_helpers/wait_ssi_ready.S" 254 | #ifdef PROGRAM_STATUS_REG 255 | #include "boot2_helpers/read_flash_sreg.S" 256 | #endif 257 | 258 | .global literals 259 | literals: 260 | .ltorg 261 | 262 | .end 263 | -------------------------------------------------------------------------------- /src/boot2_ram_memcpy.S: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // Start of 2nd Stage Boot Code 3 | // ---------------------------------------------------------------------------- 4 | #define ROM_FN_TABLE 0x00000014 5 | #define ROM_DATA_TABLE 0x00000016 6 | #define ROM_TABLE_LOOKUP 0x00000018 7 | 8 | #define SRAM_BASE 0x20000000 9 | #define SRAM_END 0x20040000 // 256KB 10 | #define SRAM_STACK0_BASE 0x20040000 11 | #define SRAM_STACK0_END 0x20041000 // 4KB 12 | #define SRAM_STACK1_BASE 0x20041000 13 | #define SRAM_STACK1_END 0x20042000 // 4KB 14 | 15 | #define XIP_BASE 0x10000000 16 | #define XIP_SSI_BASE 0x18000000 17 | #define SSI_CTRLR0_OFFSET 0x00000000 18 | #define SSI_CTRLR1_OFFSET 0x00000004 19 | #define SSI_SSIENR_OFFSET 0x00000008 20 | #define SSI_BAUDR_OFFSET 0x00000014 21 | #define SSI_SPI_CTRLR0_OFFSET 0x000000f4 22 | #define PPB_BASE 0xe0000000 23 | #define M0PLUS_VTOR_OFFSET 0x0000ed08 24 | 25 | #define PICO_FLASH_SPI_CLKDIV 4 26 | #define CMD_READ 0x03 27 | #define ADDR_L 6 28 | #define CTRLR0_XIP \ 29 | (0x0 << 21) | /* Standard 1-bit SPI serial frames */ \ 30 | (31 << 16) | /* 32 clocks per data frame */ \ 31 | (0x3 << 8) /* Send instr + addr, receive data */ 32 | #define SPI_CTRLR0_XIP \ 33 | (CMD_READ << 24) | /* Value of instruction prefix */ \ 34 | (2 << 8) | /* 8 bit command prefix (field value is bits divided by 4) */ \ 35 | (ADDR_L << 2) | /* Total number of address + mode bits */ \ 36 | (0x0 << 0) /* command and address both in serial format */ 37 | 38 | 39 | .cpu cortex-m0plus 40 | .thumb 41 | 42 | .section .text 43 | 44 | // The exit point is passed in lr. If entered from bootrom, this will be the 45 | // flash address immediately following this second stage (0x10000100). 46 | // Otherwise it will be a return address -- second stage being called as a 47 | // function by user code, after copying out of XIP region. r3 holds SSI base, 48 | // r0...2 used as temporaries. Other GPRs not used. 49 | .global _stage2_boot 50 | .type _stage2_boot,%function 51 | .thumb_func 52 | _stage2_boot: 53 | //b . // Wait for the debugger 54 | push {lr} 55 | bl _enable_xip 56 | bl _do_memcpy44 57 | bl _disable_xip 58 | 59 | // If entered from the bootrom, lr (which we earlier pushed) will be 0, 60 | // and we vector through the table at the start of the main flash image. 61 | // Any regular function call will have a nonzero value for lr. 62 | check_return: 63 | pop {r0} 64 | cmp r0, #0 65 | beq vector_into_flash 66 | bx r0 67 | vector_into_flash: 68 | ldr r0, =SRAM_BASE 69 | ldr r1, =(PPB_BASE + M0PLUS_VTOR_OFFSET) 70 | str r0, [r1] 71 | ldmia r0, {r0, r1} 72 | msr msp, r0 73 | bx r1 74 | 75 | .global _enable_xip 76 | .type _enable_xip,%function 77 | .thumb_func 78 | _enable_xip: 79 | push {lr} 80 | 81 | ldr r3, =XIP_SSI_BASE // Use as base address where possible 82 | 83 | // Disable SSI to allow further config 84 | mov r1, #0 85 | str r1, [r3, #SSI_SSIENR_OFFSET] 86 | 87 | // Set baud rate 88 | mov r1, #PICO_FLASH_SPI_CLKDIV 89 | str r1, [r3, #SSI_BAUDR_OFFSET] 90 | 91 | ldr r1, =(CTRLR0_XIP) 92 | str r1, [r3, #SSI_CTRLR0_OFFSET] 93 | 94 | ldr r1, =(SPI_CTRLR0_XIP) 95 | ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) 96 | str r1, [r0] 97 | 98 | // NDF=0 (single 32b read) 99 | mov r1, #0x0 100 | str r1, [r3, #SSI_CTRLR1_OFFSET] 101 | 102 | // Re-enable SSI 103 | mov r1, #1 104 | str r1, [r3, #SSI_SSIENR_OFFSET] 105 | 106 | pop {pc} 107 | 108 | .global _do_memcpy44 109 | .type _do_memcpy44,%function 110 | .thumb_func 111 | _do_memcpy44: 112 | push {lr} 113 | 114 | ldr r0, =ROM_FN_TABLE 115 | ldrh r0, [r0] 116 | ldr r2, =ROM_TABLE_LOOKUP 117 | ldrh r2, [r2] 118 | 119 | // Query the bootrom function pointer 120 | ldr r1, =0x3443 // 'C','4' for _memcpy44 121 | blx r2 122 | 123 | //uint8_t *_memcpy44(uint32_t *dest, uint32_t *src, uint32_t n) 124 | mov r3, r0 125 | ldr r0, =SRAM_BASE 126 | ldr r1, =XIP_BASE+0x100 // Skip this boot2 region 127 | ldr r2, =SRAM_END-SRAM_BASE 128 | blx r3 129 | 130 | pop {pc} 131 | 132 | 133 | .global _disable_xip 134 | .type _disable_xip,%function 135 | .thumb_func 136 | _disable_xip: 137 | push {lr} 138 | 139 | ldr r3, =XIP_SSI_BASE // Use as base address where possible 140 | 141 | // Disable SSI to allow further config 142 | mov r1, #0 143 | str r1, [r3, #SSI_SSIENR_OFFSET] 144 | 145 | pop {pc} 146 | 147 | 148 | .global literals 149 | literals: 150 | .ltorg 151 | 152 | .end 153 | -------------------------------------------------------------------------------- /src/boot2_w25q080.S: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // Second stage boot code 3 | // Copyright (c) 2019-2021 Raspberry Pi (Trading) Ltd. 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | // 6 | // Device: Winbond W25Q080 7 | // Also supports W25Q16JV (which has some different SR instructions) 8 | // Also supports AT25SF081 9 | // Also supports S25FL132K0 10 | // 11 | // Description: Configures W25Q080 to run in Quad I/O continuous read XIP mode 12 | // 13 | // Details: * Check status register 2 to determine if QSPI mode is enabled, 14 | // and perform an SR2 programming cycle if necessary. 15 | // * Use SSI to perform a dummy 0xEB read command, with the mode 16 | // continuation bits set, so that the flash will not require 17 | // 0xEB instruction prefix on subsequent reads. 18 | // * Configure SSI to write address, mode bits, but no instruction. 19 | // SSI + flash are now jointly in a state where continuous reads 20 | // can take place. 21 | // * Jump to exit pointer passed in via lr. Bootrom passes null, 22 | // in which case this code uses a default 256 byte flash offset 23 | // 24 | // Building: * This code must be position-independent, and use stack only 25 | // * The code will be padded to a size of 256 bytes, including a 26 | // 4-byte checksum. Therefore code size cannot exceed 252 bytes. 27 | // ---------------------------------------------------------------------------- 28 | 29 | #include "pico/asm_helper.S" 30 | #include "hardware/regs/addressmap.h" 31 | #include "hardware/regs/ssi.h" 32 | #include "hardware/regs/pads_qspi.h" 33 | 34 | // ---------------------------------------------------------------------------- 35 | // Config section 36 | // ---------------------------------------------------------------------------- 37 | // It should be possible to support most flash devices by modifying this section 38 | 39 | // The serial flash interface will run at clk_sys/PICO_FLASH_SPI_CLKDIV. 40 | // This must be a positive, even integer. 41 | // The bootrom is very conservative with SPI frequency, but here we should be 42 | // as aggressive as possible. 43 | 44 | #ifndef PICO_FLASH_SPI_CLKDIV 45 | #define PICO_FLASH_SPI_CLKDIV 4 46 | #endif 47 | #if PICO_FLASH_SPI_CLKDIV & 1 48 | #error PICO_FLASH_SPI_CLKDIV must be even 49 | #endif 50 | 51 | // Define interface width: single/dual/quad IO 52 | #define FRAME_FORMAT SSI_CTRLR0_SPI_FRF_VALUE_QUAD 53 | 54 | // For W25Q080 this is the "Read data fast quad IO" instruction: 55 | #define CMD_READ 0xeb 56 | 57 | // "Mode bits" are 8 special bits sent immediately after 58 | // the address bits in a "Read Data Fast Quad I/O" command sequence. 59 | // On W25Q080, the four LSBs are don't care, and if MSBs == 0xa, the 60 | // next read does not require the 0xeb instruction prefix. 61 | #define MODE_CONTINUOUS_READ 0xa0 62 | 63 | // The number of address + mode bits, divided by 4 (always 4, not function of 64 | // interface width). 65 | #define ADDR_L 8 66 | 67 | // How many clocks of Hi-Z following the mode bits. For W25Q080, 4 dummy cycles 68 | // are required. 69 | #define WAIT_CYCLES 4 70 | 71 | // If defined, we will read status reg, compare to SREG_DATA, and overwrite 72 | // with our value if the SR doesn't match. 73 | // We do a two-byte write to SR1 (01h cmd) rather than a one-byte write to 74 | // SR2 (31h cmd) as the latter command isn't supported by WX25Q080. 75 | // This isn't great because it will remove block protections. 76 | // A better solution is to use a volatile SR write if your device supports it. 77 | #define PROGRAM_STATUS_REG 78 | 79 | #define CMD_WRITE_ENABLE 0x06 80 | #define CMD_READ_STATUS 0x05 81 | #define CMD_READ_STATUS2 0x35 82 | #define CMD_WRITE_STATUS 0x01 83 | #define SREG_DATA 0x02 // Enable quad-SPI mode 84 | 85 | // ---------------------------------------------------------------------------- 86 | // Start of 2nd Stage Boot Code 87 | // ---------------------------------------------------------------------------- 88 | 89 | .syntax unified 90 | .cpu cortex-m0plus 91 | .thumb 92 | 93 | .section .text 94 | 95 | // The exit point is passed in lr. If entered from bootrom, this will be the 96 | // flash address immediately following this second stage (0x10000100). 97 | // Otherwise it will be a return address -- second stage being called as a 98 | // function by user code, after copying out of XIP region. r3 holds SSI base, 99 | // r0...2 used as temporaries. Other GPRs not used. 100 | .global _stage2_boot 101 | .type _stage2_boot,%function 102 | .thumb_func 103 | _stage2_boot: 104 | push {lr} 105 | 106 | // Set pad configuration: 107 | // - SCLK 8mA drive, no slew limiting 108 | // - SDx disable input Schmitt to reduce delay 109 | 110 | ldr r3, =PADS_QSPI_BASE 111 | movs r0, #(2 << PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_LSB | PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_BITS) 112 | str r0, [r3, #PADS_QSPI_GPIO_QSPI_SCLK_OFFSET] 113 | ldr r0, [r3, #PADS_QSPI_GPIO_QSPI_SD0_OFFSET] 114 | movs r1, #PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_BITS 115 | bics r0, r1 116 | str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD0_OFFSET] 117 | str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD1_OFFSET] 118 | str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD2_OFFSET] 119 | str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD3_OFFSET] 120 | 121 | ldr r3, =XIP_SSI_BASE 122 | 123 | // Disable SSI to allow further config 124 | movs r1, #0 125 | str r1, [r3, #SSI_SSIENR_OFFSET] 126 | 127 | // Set baud rate 128 | movs r1, #PICO_FLASH_SPI_CLKDIV 129 | str r1, [r3, #SSI_BAUDR_OFFSET] 130 | 131 | // Set 1-cycle sample delay. If PICO_FLASH_SPI_CLKDIV == 2 then this means, 132 | // if the flash launches data on SCLK posedge, we capture it at the time that 133 | // the next SCLK posedge is launched. This is shortly before that posedge 134 | // arrives at the flash, so data hold time should be ok. For 135 | // PICO_FLASH_SPI_CLKDIV > 2 this pretty much has no effect. 136 | 137 | movs r1, #1 138 | movs r2, #SSI_RX_SAMPLE_DLY_OFFSET // == 0xf0 so need 8 bits of offset significance 139 | str r1, [r3, r2] 140 | 141 | 142 | // On QSPI parts we usually need a 01h SR-write command to enable QSPI mode 143 | // (i.e. turn WPn and HOLDn into IO2/IO3) 144 | #ifdef PROGRAM_STATUS_REG 145 | program_sregs: 146 | #define CTRL0_SPI_TXRX \ 147 | (7 << SSI_CTRLR0_DFS_32_LSB) | /* 8 bits per data frame */ \ 148 | (SSI_CTRLR0_TMOD_VALUE_TX_AND_RX << SSI_CTRLR0_TMOD_LSB) 149 | 150 | ldr r1, =(CTRL0_SPI_TXRX) 151 | str r1, [r3, #SSI_CTRLR0_OFFSET] 152 | 153 | // Enable SSI and select slave 0 154 | movs r1, #1 155 | str r1, [r3, #SSI_SSIENR_OFFSET] 156 | 157 | // Check whether SR needs updating 158 | movs r0, #CMD_READ_STATUS2 159 | bl read_flash_sreg 160 | movs r2, #SREG_DATA 161 | cmp r0, r2 162 | beq skip_sreg_programming 163 | 164 | // Send write enable command 165 | movs r1, #CMD_WRITE_ENABLE 166 | str r1, [r3, #SSI_DR0_OFFSET] 167 | 168 | // Poll for completion and discard RX 169 | bl wait_ssi_ready 170 | ldr r1, [r3, #SSI_DR0_OFFSET] 171 | 172 | // Send status write command followed by data bytes 173 | movs r1, #CMD_WRITE_STATUS 174 | str r1, [r3, #SSI_DR0_OFFSET] 175 | movs r0, #0 176 | str r0, [r3, #SSI_DR0_OFFSET] 177 | str r2, [r3, #SSI_DR0_OFFSET] 178 | 179 | bl wait_ssi_ready 180 | ldr r1, [r3, #SSI_DR0_OFFSET] 181 | ldr r1, [r3, #SSI_DR0_OFFSET] 182 | ldr r1, [r3, #SSI_DR0_OFFSET] 183 | 184 | // Poll status register for write completion 185 | 1: 186 | movs r0, #CMD_READ_STATUS 187 | bl read_flash_sreg 188 | movs r1, #1 189 | tst r0, r1 190 | bne 1b 191 | 192 | skip_sreg_programming: 193 | 194 | // Disable SSI again so that it can be reconfigured 195 | movs r1, #0 196 | str r1, [r3, #SSI_SSIENR_OFFSET] 197 | #endif 198 | 199 | // Currently the flash expects an 8 bit serial command prefix on every 200 | // transfer, which is a waste of cycles. Perform a dummy Fast Read Quad I/O 201 | // command, with mode bits set such that the flash will not expect a serial 202 | // command prefix on *subsequent* transfers. We don't care about the results 203 | // of the read, the important part is the mode bits. 204 | 205 | dummy_read: 206 | #define CTRLR0_ENTER_XIP \ 207 | (FRAME_FORMAT /* Quad I/O mode */ \ 208 | << SSI_CTRLR0_SPI_FRF_LSB) | \ 209 | (31 << SSI_CTRLR0_DFS_32_LSB) | /* 32 data bits */ \ 210 | (SSI_CTRLR0_TMOD_VALUE_EEPROM_READ /* Send INST/ADDR, Receive Data */ \ 211 | << SSI_CTRLR0_TMOD_LSB) 212 | 213 | ldr r1, =(CTRLR0_ENTER_XIP) 214 | str r1, [r3, #SSI_CTRLR0_OFFSET] 215 | 216 | movs r1, #0x0 // NDF=0 (single 32b read) 217 | str r1, [r3, #SSI_CTRLR1_OFFSET] 218 | 219 | #define SPI_CTRLR0_ENTER_XIP \ 220 | (ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Address + mode bits */ \ 221 | (WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \ 222 | (SSI_SPI_CTRLR0_INST_L_VALUE_8B \ 223 | << SSI_SPI_CTRLR0_INST_L_LSB) | /* 8-bit instruction */ \ 224 | (SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C2A /* Send Command in serial mode then address in Quad I/O mode */ \ 225 | << SSI_SPI_CTRLR0_TRANS_TYPE_LSB) 226 | 227 | ldr r1, =(SPI_CTRLR0_ENTER_XIP) 228 | ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) // SPI_CTRL0 Register 229 | str r1, [r0] 230 | 231 | movs r1, #1 // Re-enable SSI 232 | str r1, [r3, #SSI_SSIENR_OFFSET] 233 | 234 | movs r1, #CMD_READ 235 | str r1, [r3, #SSI_DR0_OFFSET] // Push SPI command into TX FIFO 236 | movs r1, #MODE_CONTINUOUS_READ // 32-bit: 24 address bits (we don't care, so 0) and M[7:4]=1010 237 | str r1, [r3, #SSI_DR0_OFFSET] // Push Address into TX FIFO - this will trigger the transaction 238 | 239 | // Poll for completion 240 | bl wait_ssi_ready 241 | 242 | // The flash is in a state where we can blast addresses in parallel, and get 243 | // parallel data back. Now configure the SSI to translate XIP bus accesses 244 | // into QSPI transfers of this form. 245 | 246 | movs r1, #0 247 | str r1, [r3, #SSI_SSIENR_OFFSET] // Disable SSI (and clear FIFO) to allow further config 248 | 249 | // Note that the INST_L field is used to select what XIP data gets pushed into 250 | // the TX FIFO: 251 | // INST_L_0_BITS {ADDR[23:0],XIP_CMD[7:0]} Load "mode bits" into XIP_CMD 252 | // Anything else {XIP_CMD[7:0],ADDR[23:0]} Load SPI command into XIP_CMD 253 | configure_ssi: 254 | #define SPI_CTRLR0_XIP \ 255 | (MODE_CONTINUOUS_READ /* Mode bits to keep flash in continuous read mode */ \ 256 | << SSI_SPI_CTRLR0_XIP_CMD_LSB) | \ 257 | (ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Total number of address + mode bits */ \ 258 | (WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \ 259 | (SSI_SPI_CTRLR0_INST_L_VALUE_NONE /* Do not send a command, instead send XIP_CMD as mode bits after address */ \ 260 | << SSI_SPI_CTRLR0_INST_L_LSB) | \ 261 | (SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_2C2A /* Send Address in Quad I/O mode (and Command but that is zero bits long) */ \ 262 | << SSI_SPI_CTRLR0_TRANS_TYPE_LSB) 263 | 264 | ldr r1, =(SPI_CTRLR0_XIP) 265 | ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) 266 | str r1, [r0] 267 | 268 | movs r1, #1 269 | str r1, [r3, #SSI_SSIENR_OFFSET] // Re-enable SSI 270 | 271 | // Bus accesses to the XIP window will now be transparently serviced by the 272 | // external flash on cache miss. We are ready to run code from flash. 273 | 274 | // Pull in standard exit routine 275 | #include "boot2_helpers/exit_from_boot2.S" 276 | 277 | // Common functions 278 | #include "boot2_helpers/wait_ssi_ready.S" 279 | #ifdef PROGRAM_STATUS_REG 280 | #include "boot2_helpers/read_flash_sreg.S" 281 | #endif 282 | 283 | .global literals 284 | literals: 285 | .ltorg 286 | 287 | .end 288 | -------------------------------------------------------------------------------- /src/boot2_w25x10cl.S: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // Second stage boot code 3 | // Copyright (c) 2019-2021 Raspberry Pi (Trading) Ltd. 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | // 6 | // Device: Winbond W25X10CL 7 | // 8 | // Description: Configures W25X10CL to run in Dual I/O continuous read XIP mode 9 | // 10 | // Details: * Disable SSI 11 | // * Configure SSI to generate 8b command + 28b address + 2 wait, 12 | // with address and data using dual SPI mode 13 | // * Enable SSI 14 | // * Generate dummy read with command = 0xBB, top 24b of address 15 | // of 0x000000 followed by M[7:0]=0010zzzz (with the HiZ being 16 | // generated by 2 wait cycles). This leaves the W25X10CL in 17 | // continuous read mode 18 | // * Disable SSI 19 | // * Configure SSI to generate 0b command + 28b address + 2 wait, 20 | // with the extra 4 bits of address LSB being 0x2 to keep the 21 | // W25X10CL in continuous read mode forever 22 | // * Enable SSI 23 | // * Set VTOR = 0x10000100 24 | // * Read MSP reset vector from 0x10000100 and write to MSP (this 25 | // will also enable XIP mode in the SSI wrapper) 26 | // * Read PC reset vector from 0x10000104 and jump to it 27 | // 28 | // Building: * This code must be linked to run at 0x20000000 29 | // * The code will be padded to a size of 256 bytes, including a 30 | // 4-byte checksum. Therefore code size cannot exceed 252 bytes. 31 | // ---------------------------------------------------------------------------- 32 | 33 | #include "pico/asm_helper.S" 34 | #include "hardware/regs/addressmap.h" 35 | #include "hardware/regs/ssi.h" 36 | 37 | // The serial flash interface will run at clk_sys/PICO_FLASH_SPI_CLKDIV. 38 | // This must be an even number. 39 | #ifndef PICO_FLASH_SPI_CLKDIV 40 | #define PICO_FLASH_SPI_CLKDIV 4 41 | #endif 42 | 43 | // ---------------------------------------------------------------------------- 44 | // The "System Control Block" is a set of internal Cortex-M0+ control registers 45 | // that are memory mapped and accessed like any other H/W register. They have 46 | // fixed addresses in the address map of every Cortex-M0+ system. 47 | // ---------------------------------------------------------------------------- 48 | 49 | .equ SCB_VTOR, 0xE000ED08 // RW Vector Table Offset Register 50 | 51 | // ---------------------------------------------------------------------------- 52 | // Winbond W25X10CL Supported Commands 53 | // Taken from "w25x10cl_reg_021714.pdf" 54 | // ---------------------------------------------------------------------------- 55 | 56 | .equ W25X10CL_CMD_READ_DATA_FAST_DUAL_IO, 0xbb 57 | 58 | // ---------------------------------------------------------------------------- 59 | // Winbond W25X10CL "Mode bits" are 8 special bits sent immediately after 60 | // the address bits in a "Read Data Fast Dual I/O" command sequence. 61 | // Of M[7:4], they say M[7:6] are reserved (set to zero), and bits M[3:0] 62 | // are don't care (we HiZ). Only M[5:4] are used, and they must be set 63 | // to M[5:4] = 2'b10 to enable continuous read mode. 64 | // ---------------------------------------------------------------------------- 65 | 66 | .equ W25X10CL_MODE_CONTINUOUS_READ, 0x20 67 | 68 | // ---------------------------------------------------------------------------- 69 | // Start of 2nd Stage Boot Code 70 | // ---------------------------------------------------------------------------- 71 | 72 | .cpu cortex-m0 73 | .thumb 74 | 75 | .org 0 76 | 77 | .section .text 78 | 79 | // This code will get copied to 0x20000000 and then executed 80 | 81 | .global _stage2_boot 82 | .type _stage2_boot,%function 83 | .thumb_func 84 | _stage2_boot: 85 | push {lr} 86 | ldr r3, =XIP_SSI_BASE // Use as base address where possible 87 | 88 | // We are primarily interested in setting up Flash for DSPI XIP w/ continuous read 89 | 90 | mov r1, #0 91 | str r1, [r3, #SSI_SSIENR_OFFSET] // Disable SSI to allow further config 92 | 93 | // The Boot ROM sets a very conservative SPI clock frequency to be sure it can 94 | // read the initial 256 bytes from any device. Here we can be more aggressive. 95 | 96 | mov r1, #PICO_FLASH_SPI_CLKDIV 97 | str r1, [r3, #SSI_BAUDR_OFFSET] // Set SSI Clock 98 | 99 | // First we need to send the initial command to get us in to Fast Read Dual I/O 100 | // mode. As this transaction requires a command, we can't send it in XIP mode. 101 | // To enter Continuous Read mode as well we need to append 4'b0010 to the address 102 | // bits and then add a further 4 don't care bits. We will construct this by 103 | // specifying a 28-bit address, with the least significant bits being 4'b0010. 104 | // This is just a dummy transaction so we'll perform a read from address zero 105 | // and then discard what comes back. All we really care about is that at the 106 | // end of the transaction, the Winbond W25X10CL device is in Continuous Read mode 107 | // and from then on will only expect to receive addresses. 108 | 109 | #define CTRLR0_ENTER_XIP \ 110 | (SSI_CTRLR0_SPI_FRF_VALUE_DUAL /* Dual I/O mode */ \ 111 | << SSI_CTRLR0_SPI_FRF_LSB) | \ 112 | (31 << SSI_CTRLR0_DFS_32_LSB) | /* 32 data bits */ \ 113 | (SSI_CTRLR0_TMOD_VALUE_EEPROM_READ /* Send INST/ADDR, Receive Data */ \ 114 | << SSI_CTRLR0_TMOD_LSB) 115 | 116 | ldr r1, =(CTRLR0_ENTER_XIP) 117 | str r1, [r3, #SSI_CTRLR0_OFFSET] 118 | 119 | mov r1, #0x0 // NDF=0 (single 32b read) 120 | str r1, [r3, #SSI_CTRLR1_OFFSET] 121 | 122 | #define SPI_CTRLR0_ENTER_XIP \ 123 | (7 << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Send 28 bits (24 address + 4 mode) */ \ 124 | (2 << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z the other 4 mode bits (2 cycles @ dual I/O = 4 bits) */ \ 125 | (SSI_SPI_CTRLR0_INST_L_VALUE_8B \ 126 | << SSI_SPI_CTRLR0_INST_L_LSB) | /* 8-bit instruction */ \ 127 | (SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C2A /* Send Command in serial mode then address in Dual I/O mode */ \ 128 | << SSI_SPI_CTRLR0_TRANS_TYPE_LSB) 129 | 130 | ldr r1, =(SPI_CTRLR0_ENTER_XIP) 131 | ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) // SPI_CTRL0 Register 132 | str r1, [r0] 133 | 134 | mov r1, #1 // Re-enable SSI 135 | str r1, [r3, #SSI_SSIENR_OFFSET] 136 | 137 | mov r1, #W25X10CL_CMD_READ_DATA_FAST_DUAL_IO // 8b command = 0xBB 138 | str r1, [r3, #SSI_DR0_OFFSET] // Push SPI command into TX FIFO 139 | mov r1, #0x0000002 // 28-bit Address for dummy read = 0x000000 + 0x2 Mode bits to set M[5:4]=10 140 | str r1, [r3, #SSI_DR0_OFFSET] // Push Address into TX FIFO - this will trigger the transaction 141 | 142 | // Now we wait for the read transaction to complete by monitoring the SSI 143 | // status register and checking for the "RX FIFO Not Empty" flag to assert. 144 | 145 | mov r1, #SSI_SR_RFNE_BITS 146 | 00: 147 | ldr r0, [r3, #SSI_SR_OFFSET] // Read status register 148 | tst r0, r1 // RFNE status flag set? 149 | beq 00b // If not then wait 150 | 151 | // At this point CN# will be deasserted and the SPI clock will not be running. 152 | // The Winbond WX25X10CL device will be in continuous read, dual I/O mode and 153 | // only expecting address bits after the next CN# assertion. So long as we 154 | // send 4'b0010 (and 4 more dummy HiZ bits) after every subsequent 24b address 155 | // then the Winbond device will remain in continuous read mode. This is the 156 | // ideal mode for Execute-In-Place. 157 | // (If we want to exit continuous read mode then we will need to switch back 158 | // to APM mode and generate a 28-bit address phase with the extra nibble set 159 | // to 4'b0000). 160 | 161 | mov r1, #0 162 | str r1, [r3, #SSI_SSIENR_OFFSET] // Disable SSI (and clear FIFO) to allow further config 163 | 164 | // Note that the INST_L field is used to select what XIP data gets pushed into 165 | // the TX FIFO: 166 | // INST_L_0_BITS {ADDR[23:0],XIP_CMD[7:0]} Load "mode bits" into XIP_CMD 167 | // Anything else {XIP_CMD[7:0],ADDR[23:0]} Load SPI command into XIP_CMD 168 | 169 | #define SPI_CTRLR0_XIP \ 170 | (W25X10CL_MODE_CONTINUOUS_READ /* Mode bits to keep Winbond in continuous read mode */ \ 171 | << SSI_SPI_CTRLR0_XIP_CMD_LSB) | \ 172 | (7 << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Send 28 bits (24 address + 4 mode) */ \ 173 | (2 << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z the other 4 mode bits (2 cycles @ dual I/O = 4 bits) */ \ 174 | (SSI_SPI_CTRLR0_INST_L_VALUE_NONE /* Do not send a command, instead send XIP_CMD as mode bits after address */ \ 175 | << SSI_SPI_CTRLR0_INST_L_LSB) | \ 176 | (SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_2C2A /* Send Address in Dual I/O mode (and Command but that is zero bits long) */ \ 177 | << SSI_SPI_CTRLR0_TRANS_TYPE_LSB) 178 | 179 | ldr r1, =(SPI_CTRLR0_XIP) 180 | ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) 181 | str r1, [r0] 182 | 183 | mov r1, #1 184 | str r1, [r3, #SSI_SSIENR_OFFSET] // Re-enable SSI 185 | 186 | // We are now in XIP mode, with all transactions using Dual I/O and only 187 | // needing to send 24-bit addresses (plus mode bits) for each read transaction. 188 | 189 | // Pull in standard exit routine 190 | #include "boot2_helpers/exit_from_boot2.S" 191 | 192 | .global literals 193 | literals: 194 | .ltorg 195 | 196 | .end 197 | -------------------------------------------------------------------------------- /src/include/boot2_helpers/exit_from_boot2.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | #ifndef _BOOT2_HELPER_EXIT_FROM_BOOT2 8 | #define _BOOT2_HELPER_EXIT_FROM_BOOT2 9 | 10 | #include "hardware/regs/m0plus.h" 11 | 12 | // If entered from the bootrom, lr (which we earlier pushed) will be 0, 13 | // and we vector through the table at the start of the main flash image. 14 | // Any regular function call will have a nonzero value for lr. 15 | check_return: 16 | pop {r0} 17 | cmp r0, #0 18 | beq vector_into_flash 19 | bx r0 20 | vector_into_flash: 21 | ldr r0, =(XIP_BASE + 0x100) 22 | ldr r1, =(PPB_BASE + M0PLUS_VTOR_OFFSET) 23 | str r0, [r1] 24 | ldmia r0, {r0, r1} 25 | msr msp, r0 26 | bx r1 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/include/boot2_helpers/read_flash_sreg.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | #ifndef _BOOT2_HELPER_READ_FLASH_SREG 8 | #define _BOOT2_HELPER_READ_FLASH_SREG 9 | 10 | #include "boot2_helpers/wait_ssi_ready.S" 11 | 12 | // Pass status read cmd into r0. 13 | // Returns status value in r0. 14 | .global read_flash_sreg 15 | .type read_flash_sreg,%function 16 | .thumb_func 17 | read_flash_sreg: 18 | push {r1, lr} 19 | str r0, [r3, #SSI_DR0_OFFSET] 20 | // Dummy byte: 21 | str r0, [r3, #SSI_DR0_OFFSET] 22 | 23 | bl wait_ssi_ready 24 | // Discard first byte and combine the next two 25 | ldr r0, [r3, #SSI_DR0_OFFSET] 26 | ldr r0, [r3, #SSI_DR0_OFFSET] 27 | 28 | pop {r1, pc} 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/include/boot2_helpers/wait_ssi_ready.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | #ifndef _BOOT2_HELPER_WAIT_SSI_READY 8 | #define _BOOT2_HELPER_WAIT_SSI_READY 9 | 10 | wait_ssi_ready: 11 | push {r0, r1, lr} 12 | 13 | // Command is complete when there is nothing left to send 14 | // (TX FIFO empty) and SSI is no longer busy (CSn deasserted) 15 | 1: 16 | ldr r1, [r3, #SSI_SR_OFFSET] 17 | movs r0, #SSI_SR_TFE_BITS 18 | tst r1, r0 19 | beq 1b 20 | movs r0, #SSI_SR_BUSY_BITS 21 | tst r1, r0 22 | bne 1b 23 | 24 | pop {r0, r1, pc} 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/include/hardware/platform_defs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | #ifndef _HARDWARE_PLATFORM_DEFS_H 8 | #define _HARDWARE_PLATFORM_DEFS_H 9 | 10 | // This header is included from C and assembler - intended mostly for #defines; guard other stuff with #ifdef __ASSEMBLER__ 11 | 12 | #ifndef _u 13 | #ifdef __ASSEMBLER__ 14 | #define _u(x) x 15 | #else 16 | #define _u(x) x ## u 17 | #endif 18 | #endif 19 | 20 | #define NUM_CORES _u(2) 21 | #define NUM_DMA_CHANNELS _u(12) 22 | #define NUM_DMA_TIMERS _u(4) 23 | #define NUM_IRQS _u(32) 24 | #define NUM_USER_IRQS _u(6) 25 | #define NUM_PIOS _u(2) 26 | #define NUM_PIO_STATE_MACHINES _u(4) 27 | #define NUM_PWM_SLICES _u(8) 28 | #define NUM_SPIN_LOCKS _u(32) 29 | #define NUM_UARTS _u(2) 30 | #define NUM_I2CS _u(2) 31 | #define NUM_SPIS _u(2) 32 | #define NUM_TIMERS _u(4) 33 | #define NUM_ADC_CHANNELS _u(5) 34 | 35 | #define NUM_BANK0_GPIOS _u(30) 36 | #define NUM_QSPI_GPIOS _u(6) 37 | 38 | #define PIO_INSTRUCTION_COUNT _u(32) 39 | 40 | // PICO_CONFIG: XOSC_MHZ, The crystal oscillator frequency in Mhz, type=int, default=12, advanced=true, group=hardware_base 41 | #ifndef XOSC_MHZ 42 | #define XOSC_MHZ _u(12) 43 | #endif 44 | 45 | #endif 46 | 47 | -------------------------------------------------------------------------------- /src/include/hardware/regs/addressmap.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | #ifndef _ADDRESSMAP_H_ 7 | #define _ADDRESSMAP_H_ 8 | 9 | // Register address offsets for atomic RMW aliases 10 | #define REG_ALIAS_RW_BITS (0x0u << 12u) 11 | #define REG_ALIAS_XOR_BITS (0x1u << 12u) 12 | #define REG_ALIAS_SET_BITS (0x2u << 12u) 13 | #define REG_ALIAS_CLR_BITS (0x3u << 12u) 14 | 15 | #define ROM_BASE 0x00000000 16 | #define XIP_BASE 0x10000000 17 | #define XIP_MAIN_BASE 0x10000000 18 | #define XIP_NOALLOC_BASE 0x11000000 19 | #define XIP_NOCACHE_BASE 0x12000000 20 | #define XIP_NOCACHE_NOALLOC_BASE 0x13000000 21 | #define XIP_CTRL_BASE 0x14000000 22 | #define XIP_SRAM_BASE 0x15000000 23 | #define XIP_SRAM_END 0x15004000 24 | #define XIP_SSI_BASE 0x18000000 25 | #define SRAM_BASE 0x20000000 26 | #define SRAM_STRIPED_BASE 0x20000000 27 | #define SRAM_STRIPED_END 0x20040000 28 | #define SRAM4_BASE 0x20040000 29 | #define SRAM5_BASE 0x20041000 30 | #define SRAM_END 0x20042000 31 | #define SRAM0_BASE 0x21000000 32 | #define SRAM1_BASE 0x21010000 33 | #define SRAM2_BASE 0x21020000 34 | #define SRAM3_BASE 0x21030000 35 | #define SYSINFO_BASE 0x40000000 36 | #define SYSCFG_BASE 0x40004000 37 | #define CLOCKS_BASE 0x40008000 38 | #define RESETS_BASE 0x4000c000 39 | #define PSM_BASE 0x40010000 40 | #define IO_BANK0_BASE 0x40014000 41 | #define IO_QSPI_BASE 0x40018000 42 | #define PADS_BANK0_BASE 0x4001c000 43 | #define PADS_QSPI_BASE 0x40020000 44 | #define XOSC_BASE 0x40024000 45 | #define PLL_SYS_BASE 0x40028000 46 | #define PLL_USB_BASE 0x4002c000 47 | #define BUSCTRL_BASE 0x40030000 48 | #define UART0_BASE 0x40034000 49 | #define UART1_BASE 0x40038000 50 | #define SPI0_BASE 0x4003c000 51 | #define SPI1_BASE 0x40040000 52 | #define I2C0_BASE 0x40044000 53 | #define I2C1_BASE 0x40048000 54 | #define ADC_BASE 0x4004c000 55 | #define PWM_BASE 0x40050000 56 | #define TIMER_BASE 0x40054000 57 | #define WATCHDOG_BASE 0x40058000 58 | #define RTC_BASE 0x4005c000 59 | #define ROSC_BASE 0x40060000 60 | #define VREG_AND_CHIP_RESET_BASE 0x40064000 61 | #define TBMAN_BASE 0x4006c000 62 | #define DMA_BASE 0x50000000 63 | #define USBCTRL_DPRAM_BASE 0x50100000 64 | #define USBCTRL_BASE 0x50100000 65 | #define USBCTRL_REGS_BASE 0x50110000 66 | #define PIO0_BASE 0x50200000 67 | #define PIO1_BASE 0x50300000 68 | #define XIP_AUX_BASE 0x50400000 69 | #define SIO_BASE 0xd0000000 70 | #define PPB_BASE 0xe0000000 71 | 72 | #define M0PLUS_CPUID_OFFSET 0x0000ed00 73 | #define M0PLUS_VTOR_OFFSET 0x0000ed08 74 | 75 | #endif // _ADDRESSMAP_H_ 76 | -------------------------------------------------------------------------------- /src/include/hardware/regs/pads_qspi.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | // ============================================================================= 7 | // Register block : PADS_QSPI 8 | // Version : 1 9 | // Bus type : apb 10 | // Description : None 11 | // ============================================================================= 12 | #ifndef HARDWARE_REGS_PADS_QSPI_DEFINED 13 | #define HARDWARE_REGS_PADS_QSPI_DEFINED 14 | // ============================================================================= 15 | // Register : PADS_QSPI_VOLTAGE_SELECT 16 | // Description : Voltage select. Per bank control 17 | // 0x0 -> Set voltage to 3.3V (DVDD >= 2V5) 18 | // 0x1 -> Set voltage to 1.8V (DVDD <= 1V8) 19 | #define PADS_QSPI_VOLTAGE_SELECT_OFFSET 0x00000000 20 | #define PADS_QSPI_VOLTAGE_SELECT_BITS 0x00000001 21 | #define PADS_QSPI_VOLTAGE_SELECT_RESET 0x00000000 22 | #define PADS_QSPI_VOLTAGE_SELECT_MSB 0 23 | #define PADS_QSPI_VOLTAGE_SELECT_LSB 0 24 | #define PADS_QSPI_VOLTAGE_SELECT_ACCESS "RW" 25 | #define PADS_QSPI_VOLTAGE_SELECT_VALUE_3V3 0x0 26 | #define PADS_QSPI_VOLTAGE_SELECT_VALUE_1V8 0x1 27 | // ============================================================================= 28 | // Register : PADS_QSPI_GPIO_QSPI_SCLK 29 | // Description : Pad control register 30 | #define PADS_QSPI_GPIO_QSPI_SCLK_OFFSET 0x00000004 31 | #define PADS_QSPI_GPIO_QSPI_SCLK_BITS 0x000000ff 32 | #define PADS_QSPI_GPIO_QSPI_SCLK_RESET 0x00000056 33 | // ----------------------------------------------------------------------------- 34 | // Field : PADS_QSPI_GPIO_QSPI_SCLK_OD 35 | // Description : Output disable. Has priority over output enable from 36 | // peripherals 37 | #define PADS_QSPI_GPIO_QSPI_SCLK_OD_RESET 0x0 38 | #define PADS_QSPI_GPIO_QSPI_SCLK_OD_BITS 0x00000080 39 | #define PADS_QSPI_GPIO_QSPI_SCLK_OD_MSB 7 40 | #define PADS_QSPI_GPIO_QSPI_SCLK_OD_LSB 7 41 | #define PADS_QSPI_GPIO_QSPI_SCLK_OD_ACCESS "RW" 42 | // ----------------------------------------------------------------------------- 43 | // Field : PADS_QSPI_GPIO_QSPI_SCLK_IE 44 | // Description : Input enable 45 | #define PADS_QSPI_GPIO_QSPI_SCLK_IE_RESET 0x1 46 | #define PADS_QSPI_GPIO_QSPI_SCLK_IE_BITS 0x00000040 47 | #define PADS_QSPI_GPIO_QSPI_SCLK_IE_MSB 6 48 | #define PADS_QSPI_GPIO_QSPI_SCLK_IE_LSB 6 49 | #define PADS_QSPI_GPIO_QSPI_SCLK_IE_ACCESS "RW" 50 | // ----------------------------------------------------------------------------- 51 | // Field : PADS_QSPI_GPIO_QSPI_SCLK_DRIVE 52 | // Description : Drive strength. 53 | // 0x0 -> 2mA 54 | // 0x1 -> 4mA 55 | // 0x2 -> 8mA 56 | // 0x3 -> 12mA 57 | #define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_RESET 0x1 58 | #define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_BITS 0x00000030 59 | #define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_MSB 5 60 | #define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_LSB 4 61 | #define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_ACCESS "RW" 62 | #define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_VALUE_2MA 0x0 63 | #define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_VALUE_4MA 0x1 64 | #define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_VALUE_8MA 0x2 65 | #define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_VALUE_12MA 0x3 66 | // ----------------------------------------------------------------------------- 67 | // Field : PADS_QSPI_GPIO_QSPI_SCLK_PUE 68 | // Description : Pull up enable 69 | #define PADS_QSPI_GPIO_QSPI_SCLK_PUE_RESET 0x0 70 | #define PADS_QSPI_GPIO_QSPI_SCLK_PUE_BITS 0x00000008 71 | #define PADS_QSPI_GPIO_QSPI_SCLK_PUE_MSB 3 72 | #define PADS_QSPI_GPIO_QSPI_SCLK_PUE_LSB 3 73 | #define PADS_QSPI_GPIO_QSPI_SCLK_PUE_ACCESS "RW" 74 | // ----------------------------------------------------------------------------- 75 | // Field : PADS_QSPI_GPIO_QSPI_SCLK_PDE 76 | // Description : Pull down enable 77 | #define PADS_QSPI_GPIO_QSPI_SCLK_PDE_RESET 0x1 78 | #define PADS_QSPI_GPIO_QSPI_SCLK_PDE_BITS 0x00000004 79 | #define PADS_QSPI_GPIO_QSPI_SCLK_PDE_MSB 2 80 | #define PADS_QSPI_GPIO_QSPI_SCLK_PDE_LSB 2 81 | #define PADS_QSPI_GPIO_QSPI_SCLK_PDE_ACCESS "RW" 82 | // ----------------------------------------------------------------------------- 83 | // Field : PADS_QSPI_GPIO_QSPI_SCLK_SCHMITT 84 | // Description : Enable schmitt trigger 85 | #define PADS_QSPI_GPIO_QSPI_SCLK_SCHMITT_RESET 0x1 86 | #define PADS_QSPI_GPIO_QSPI_SCLK_SCHMITT_BITS 0x00000002 87 | #define PADS_QSPI_GPIO_QSPI_SCLK_SCHMITT_MSB 1 88 | #define PADS_QSPI_GPIO_QSPI_SCLK_SCHMITT_LSB 1 89 | #define PADS_QSPI_GPIO_QSPI_SCLK_SCHMITT_ACCESS "RW" 90 | // ----------------------------------------------------------------------------- 91 | // Field : PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST 92 | // Description : Slew rate control. 1 = Fast, 0 = Slow 93 | #define PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_RESET 0x0 94 | #define PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_BITS 0x00000001 95 | #define PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_MSB 0 96 | #define PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_LSB 0 97 | #define PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_ACCESS "RW" 98 | // ============================================================================= 99 | // Register : PADS_QSPI_GPIO_QSPI_SD0 100 | // Description : Pad control register 101 | #define PADS_QSPI_GPIO_QSPI_SD0_OFFSET 0x00000008 102 | #define PADS_QSPI_GPIO_QSPI_SD0_BITS 0x000000ff 103 | #define PADS_QSPI_GPIO_QSPI_SD0_RESET 0x00000052 104 | // ----------------------------------------------------------------------------- 105 | // Field : PADS_QSPI_GPIO_QSPI_SD0_OD 106 | // Description : Output disable. Has priority over output enable from 107 | // peripherals 108 | #define PADS_QSPI_GPIO_QSPI_SD0_OD_RESET 0x0 109 | #define PADS_QSPI_GPIO_QSPI_SD0_OD_BITS 0x00000080 110 | #define PADS_QSPI_GPIO_QSPI_SD0_OD_MSB 7 111 | #define PADS_QSPI_GPIO_QSPI_SD0_OD_LSB 7 112 | #define PADS_QSPI_GPIO_QSPI_SD0_OD_ACCESS "RW" 113 | // ----------------------------------------------------------------------------- 114 | // Field : PADS_QSPI_GPIO_QSPI_SD0_IE 115 | // Description : Input enable 116 | #define PADS_QSPI_GPIO_QSPI_SD0_IE_RESET 0x1 117 | #define PADS_QSPI_GPIO_QSPI_SD0_IE_BITS 0x00000040 118 | #define PADS_QSPI_GPIO_QSPI_SD0_IE_MSB 6 119 | #define PADS_QSPI_GPIO_QSPI_SD0_IE_LSB 6 120 | #define PADS_QSPI_GPIO_QSPI_SD0_IE_ACCESS "RW" 121 | // ----------------------------------------------------------------------------- 122 | // Field : PADS_QSPI_GPIO_QSPI_SD0_DRIVE 123 | // Description : Drive strength. 124 | // 0x0 -> 2mA 125 | // 0x1 -> 4mA 126 | // 0x2 -> 8mA 127 | // 0x3 -> 12mA 128 | #define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_RESET 0x1 129 | #define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_BITS 0x00000030 130 | #define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_MSB 5 131 | #define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_LSB 4 132 | #define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_ACCESS "RW" 133 | #define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_VALUE_2MA 0x0 134 | #define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_VALUE_4MA 0x1 135 | #define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_VALUE_8MA 0x2 136 | #define PADS_QSPI_GPIO_QSPI_SD0_DRIVE_VALUE_12MA 0x3 137 | // ----------------------------------------------------------------------------- 138 | // Field : PADS_QSPI_GPIO_QSPI_SD0_PUE 139 | // Description : Pull up enable 140 | #define PADS_QSPI_GPIO_QSPI_SD0_PUE_RESET 0x0 141 | #define PADS_QSPI_GPIO_QSPI_SD0_PUE_BITS 0x00000008 142 | #define PADS_QSPI_GPIO_QSPI_SD0_PUE_MSB 3 143 | #define PADS_QSPI_GPIO_QSPI_SD0_PUE_LSB 3 144 | #define PADS_QSPI_GPIO_QSPI_SD0_PUE_ACCESS "RW" 145 | // ----------------------------------------------------------------------------- 146 | // Field : PADS_QSPI_GPIO_QSPI_SD0_PDE 147 | // Description : Pull down enable 148 | #define PADS_QSPI_GPIO_QSPI_SD0_PDE_RESET 0x0 149 | #define PADS_QSPI_GPIO_QSPI_SD0_PDE_BITS 0x00000004 150 | #define PADS_QSPI_GPIO_QSPI_SD0_PDE_MSB 2 151 | #define PADS_QSPI_GPIO_QSPI_SD0_PDE_LSB 2 152 | #define PADS_QSPI_GPIO_QSPI_SD0_PDE_ACCESS "RW" 153 | // ----------------------------------------------------------------------------- 154 | // Field : PADS_QSPI_GPIO_QSPI_SD0_SCHMITT 155 | // Description : Enable schmitt trigger 156 | #define PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_RESET 0x1 157 | #define PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_BITS 0x00000002 158 | #define PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_MSB 1 159 | #define PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_LSB 1 160 | #define PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_ACCESS "RW" 161 | // ----------------------------------------------------------------------------- 162 | // Field : PADS_QSPI_GPIO_QSPI_SD0_SLEWFAST 163 | // Description : Slew rate control. 1 = Fast, 0 = Slow 164 | #define PADS_QSPI_GPIO_QSPI_SD0_SLEWFAST_RESET 0x0 165 | #define PADS_QSPI_GPIO_QSPI_SD0_SLEWFAST_BITS 0x00000001 166 | #define PADS_QSPI_GPIO_QSPI_SD0_SLEWFAST_MSB 0 167 | #define PADS_QSPI_GPIO_QSPI_SD0_SLEWFAST_LSB 0 168 | #define PADS_QSPI_GPIO_QSPI_SD0_SLEWFAST_ACCESS "RW" 169 | // ============================================================================= 170 | // Register : PADS_QSPI_GPIO_QSPI_SD1 171 | // Description : Pad control register 172 | #define PADS_QSPI_GPIO_QSPI_SD1_OFFSET 0x0000000c 173 | #define PADS_QSPI_GPIO_QSPI_SD1_BITS 0x000000ff 174 | #define PADS_QSPI_GPIO_QSPI_SD1_RESET 0x00000052 175 | // ----------------------------------------------------------------------------- 176 | // Field : PADS_QSPI_GPIO_QSPI_SD1_OD 177 | // Description : Output disable. Has priority over output enable from 178 | // peripherals 179 | #define PADS_QSPI_GPIO_QSPI_SD1_OD_RESET 0x0 180 | #define PADS_QSPI_GPIO_QSPI_SD1_OD_BITS 0x00000080 181 | #define PADS_QSPI_GPIO_QSPI_SD1_OD_MSB 7 182 | #define PADS_QSPI_GPIO_QSPI_SD1_OD_LSB 7 183 | #define PADS_QSPI_GPIO_QSPI_SD1_OD_ACCESS "RW" 184 | // ----------------------------------------------------------------------------- 185 | // Field : PADS_QSPI_GPIO_QSPI_SD1_IE 186 | // Description : Input enable 187 | #define PADS_QSPI_GPIO_QSPI_SD1_IE_RESET 0x1 188 | #define PADS_QSPI_GPIO_QSPI_SD1_IE_BITS 0x00000040 189 | #define PADS_QSPI_GPIO_QSPI_SD1_IE_MSB 6 190 | #define PADS_QSPI_GPIO_QSPI_SD1_IE_LSB 6 191 | #define PADS_QSPI_GPIO_QSPI_SD1_IE_ACCESS "RW" 192 | // ----------------------------------------------------------------------------- 193 | // Field : PADS_QSPI_GPIO_QSPI_SD1_DRIVE 194 | // Description : Drive strength. 195 | // 0x0 -> 2mA 196 | // 0x1 -> 4mA 197 | // 0x2 -> 8mA 198 | // 0x3 -> 12mA 199 | #define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_RESET 0x1 200 | #define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_BITS 0x00000030 201 | #define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_MSB 5 202 | #define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_LSB 4 203 | #define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_ACCESS "RW" 204 | #define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_VALUE_2MA 0x0 205 | #define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_VALUE_4MA 0x1 206 | #define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_VALUE_8MA 0x2 207 | #define PADS_QSPI_GPIO_QSPI_SD1_DRIVE_VALUE_12MA 0x3 208 | // ----------------------------------------------------------------------------- 209 | // Field : PADS_QSPI_GPIO_QSPI_SD1_PUE 210 | // Description : Pull up enable 211 | #define PADS_QSPI_GPIO_QSPI_SD1_PUE_RESET 0x0 212 | #define PADS_QSPI_GPIO_QSPI_SD1_PUE_BITS 0x00000008 213 | #define PADS_QSPI_GPIO_QSPI_SD1_PUE_MSB 3 214 | #define PADS_QSPI_GPIO_QSPI_SD1_PUE_LSB 3 215 | #define PADS_QSPI_GPIO_QSPI_SD1_PUE_ACCESS "RW" 216 | // ----------------------------------------------------------------------------- 217 | // Field : PADS_QSPI_GPIO_QSPI_SD1_PDE 218 | // Description : Pull down enable 219 | #define PADS_QSPI_GPIO_QSPI_SD1_PDE_RESET 0x0 220 | #define PADS_QSPI_GPIO_QSPI_SD1_PDE_BITS 0x00000004 221 | #define PADS_QSPI_GPIO_QSPI_SD1_PDE_MSB 2 222 | #define PADS_QSPI_GPIO_QSPI_SD1_PDE_LSB 2 223 | #define PADS_QSPI_GPIO_QSPI_SD1_PDE_ACCESS "RW" 224 | // ----------------------------------------------------------------------------- 225 | // Field : PADS_QSPI_GPIO_QSPI_SD1_SCHMITT 226 | // Description : Enable schmitt trigger 227 | #define PADS_QSPI_GPIO_QSPI_SD1_SCHMITT_RESET 0x1 228 | #define PADS_QSPI_GPIO_QSPI_SD1_SCHMITT_BITS 0x00000002 229 | #define PADS_QSPI_GPIO_QSPI_SD1_SCHMITT_MSB 1 230 | #define PADS_QSPI_GPIO_QSPI_SD1_SCHMITT_LSB 1 231 | #define PADS_QSPI_GPIO_QSPI_SD1_SCHMITT_ACCESS "RW" 232 | // ----------------------------------------------------------------------------- 233 | // Field : PADS_QSPI_GPIO_QSPI_SD1_SLEWFAST 234 | // Description : Slew rate control. 1 = Fast, 0 = Slow 235 | #define PADS_QSPI_GPIO_QSPI_SD1_SLEWFAST_RESET 0x0 236 | #define PADS_QSPI_GPIO_QSPI_SD1_SLEWFAST_BITS 0x00000001 237 | #define PADS_QSPI_GPIO_QSPI_SD1_SLEWFAST_MSB 0 238 | #define PADS_QSPI_GPIO_QSPI_SD1_SLEWFAST_LSB 0 239 | #define PADS_QSPI_GPIO_QSPI_SD1_SLEWFAST_ACCESS "RW" 240 | // ============================================================================= 241 | // Register : PADS_QSPI_GPIO_QSPI_SD2 242 | // Description : Pad control register 243 | #define PADS_QSPI_GPIO_QSPI_SD2_OFFSET 0x00000010 244 | #define PADS_QSPI_GPIO_QSPI_SD2_BITS 0x000000ff 245 | #define PADS_QSPI_GPIO_QSPI_SD2_RESET 0x00000052 246 | // ----------------------------------------------------------------------------- 247 | // Field : PADS_QSPI_GPIO_QSPI_SD2_OD 248 | // Description : Output disable. Has priority over output enable from 249 | // peripherals 250 | #define PADS_QSPI_GPIO_QSPI_SD2_OD_RESET 0x0 251 | #define PADS_QSPI_GPIO_QSPI_SD2_OD_BITS 0x00000080 252 | #define PADS_QSPI_GPIO_QSPI_SD2_OD_MSB 7 253 | #define PADS_QSPI_GPIO_QSPI_SD2_OD_LSB 7 254 | #define PADS_QSPI_GPIO_QSPI_SD2_OD_ACCESS "RW" 255 | // ----------------------------------------------------------------------------- 256 | // Field : PADS_QSPI_GPIO_QSPI_SD2_IE 257 | // Description : Input enable 258 | #define PADS_QSPI_GPIO_QSPI_SD2_IE_RESET 0x1 259 | #define PADS_QSPI_GPIO_QSPI_SD2_IE_BITS 0x00000040 260 | #define PADS_QSPI_GPIO_QSPI_SD2_IE_MSB 6 261 | #define PADS_QSPI_GPIO_QSPI_SD2_IE_LSB 6 262 | #define PADS_QSPI_GPIO_QSPI_SD2_IE_ACCESS "RW" 263 | // ----------------------------------------------------------------------------- 264 | // Field : PADS_QSPI_GPIO_QSPI_SD2_DRIVE 265 | // Description : Drive strength. 266 | // 0x0 -> 2mA 267 | // 0x1 -> 4mA 268 | // 0x2 -> 8mA 269 | // 0x3 -> 12mA 270 | #define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_RESET 0x1 271 | #define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_BITS 0x00000030 272 | #define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_MSB 5 273 | #define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_LSB 4 274 | #define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_ACCESS "RW" 275 | #define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_VALUE_2MA 0x0 276 | #define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_VALUE_4MA 0x1 277 | #define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_VALUE_8MA 0x2 278 | #define PADS_QSPI_GPIO_QSPI_SD2_DRIVE_VALUE_12MA 0x3 279 | // ----------------------------------------------------------------------------- 280 | // Field : PADS_QSPI_GPIO_QSPI_SD2_PUE 281 | // Description : Pull up enable 282 | #define PADS_QSPI_GPIO_QSPI_SD2_PUE_RESET 0x0 283 | #define PADS_QSPI_GPIO_QSPI_SD2_PUE_BITS 0x00000008 284 | #define PADS_QSPI_GPIO_QSPI_SD2_PUE_MSB 3 285 | #define PADS_QSPI_GPIO_QSPI_SD2_PUE_LSB 3 286 | #define PADS_QSPI_GPIO_QSPI_SD2_PUE_ACCESS "RW" 287 | // ----------------------------------------------------------------------------- 288 | // Field : PADS_QSPI_GPIO_QSPI_SD2_PDE 289 | // Description : Pull down enable 290 | #define PADS_QSPI_GPIO_QSPI_SD2_PDE_RESET 0x0 291 | #define PADS_QSPI_GPIO_QSPI_SD2_PDE_BITS 0x00000004 292 | #define PADS_QSPI_GPIO_QSPI_SD2_PDE_MSB 2 293 | #define PADS_QSPI_GPIO_QSPI_SD2_PDE_LSB 2 294 | #define PADS_QSPI_GPIO_QSPI_SD2_PDE_ACCESS "RW" 295 | // ----------------------------------------------------------------------------- 296 | // Field : PADS_QSPI_GPIO_QSPI_SD2_SCHMITT 297 | // Description : Enable schmitt trigger 298 | #define PADS_QSPI_GPIO_QSPI_SD2_SCHMITT_RESET 0x1 299 | #define PADS_QSPI_GPIO_QSPI_SD2_SCHMITT_BITS 0x00000002 300 | #define PADS_QSPI_GPIO_QSPI_SD2_SCHMITT_MSB 1 301 | #define PADS_QSPI_GPIO_QSPI_SD2_SCHMITT_LSB 1 302 | #define PADS_QSPI_GPIO_QSPI_SD2_SCHMITT_ACCESS "RW" 303 | // ----------------------------------------------------------------------------- 304 | // Field : PADS_QSPI_GPIO_QSPI_SD2_SLEWFAST 305 | // Description : Slew rate control. 1 = Fast, 0 = Slow 306 | #define PADS_QSPI_GPIO_QSPI_SD2_SLEWFAST_RESET 0x0 307 | #define PADS_QSPI_GPIO_QSPI_SD2_SLEWFAST_BITS 0x00000001 308 | #define PADS_QSPI_GPIO_QSPI_SD2_SLEWFAST_MSB 0 309 | #define PADS_QSPI_GPIO_QSPI_SD2_SLEWFAST_LSB 0 310 | #define PADS_QSPI_GPIO_QSPI_SD2_SLEWFAST_ACCESS "RW" 311 | // ============================================================================= 312 | // Register : PADS_QSPI_GPIO_QSPI_SD3 313 | // Description : Pad control register 314 | #define PADS_QSPI_GPIO_QSPI_SD3_OFFSET 0x00000014 315 | #define PADS_QSPI_GPIO_QSPI_SD3_BITS 0x000000ff 316 | #define PADS_QSPI_GPIO_QSPI_SD3_RESET 0x00000052 317 | // ----------------------------------------------------------------------------- 318 | // Field : PADS_QSPI_GPIO_QSPI_SD3_OD 319 | // Description : Output disable. Has priority over output enable from 320 | // peripherals 321 | #define PADS_QSPI_GPIO_QSPI_SD3_OD_RESET 0x0 322 | #define PADS_QSPI_GPIO_QSPI_SD3_OD_BITS 0x00000080 323 | #define PADS_QSPI_GPIO_QSPI_SD3_OD_MSB 7 324 | #define PADS_QSPI_GPIO_QSPI_SD3_OD_LSB 7 325 | #define PADS_QSPI_GPIO_QSPI_SD3_OD_ACCESS "RW" 326 | // ----------------------------------------------------------------------------- 327 | // Field : PADS_QSPI_GPIO_QSPI_SD3_IE 328 | // Description : Input enable 329 | #define PADS_QSPI_GPIO_QSPI_SD3_IE_RESET 0x1 330 | #define PADS_QSPI_GPIO_QSPI_SD3_IE_BITS 0x00000040 331 | #define PADS_QSPI_GPIO_QSPI_SD3_IE_MSB 6 332 | #define PADS_QSPI_GPIO_QSPI_SD3_IE_LSB 6 333 | #define PADS_QSPI_GPIO_QSPI_SD3_IE_ACCESS "RW" 334 | // ----------------------------------------------------------------------------- 335 | // Field : PADS_QSPI_GPIO_QSPI_SD3_DRIVE 336 | // Description : Drive strength. 337 | // 0x0 -> 2mA 338 | // 0x1 -> 4mA 339 | // 0x2 -> 8mA 340 | // 0x3 -> 12mA 341 | #define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_RESET 0x1 342 | #define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_BITS 0x00000030 343 | #define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_MSB 5 344 | #define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_LSB 4 345 | #define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_ACCESS "RW" 346 | #define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_VALUE_2MA 0x0 347 | #define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_VALUE_4MA 0x1 348 | #define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_VALUE_8MA 0x2 349 | #define PADS_QSPI_GPIO_QSPI_SD3_DRIVE_VALUE_12MA 0x3 350 | // ----------------------------------------------------------------------------- 351 | // Field : PADS_QSPI_GPIO_QSPI_SD3_PUE 352 | // Description : Pull up enable 353 | #define PADS_QSPI_GPIO_QSPI_SD3_PUE_RESET 0x0 354 | #define PADS_QSPI_GPIO_QSPI_SD3_PUE_BITS 0x00000008 355 | #define PADS_QSPI_GPIO_QSPI_SD3_PUE_MSB 3 356 | #define PADS_QSPI_GPIO_QSPI_SD3_PUE_LSB 3 357 | #define PADS_QSPI_GPIO_QSPI_SD3_PUE_ACCESS "RW" 358 | // ----------------------------------------------------------------------------- 359 | // Field : PADS_QSPI_GPIO_QSPI_SD3_PDE 360 | // Description : Pull down enable 361 | #define PADS_QSPI_GPIO_QSPI_SD3_PDE_RESET 0x0 362 | #define PADS_QSPI_GPIO_QSPI_SD3_PDE_BITS 0x00000004 363 | #define PADS_QSPI_GPIO_QSPI_SD3_PDE_MSB 2 364 | #define PADS_QSPI_GPIO_QSPI_SD3_PDE_LSB 2 365 | #define PADS_QSPI_GPIO_QSPI_SD3_PDE_ACCESS "RW" 366 | // ----------------------------------------------------------------------------- 367 | // Field : PADS_QSPI_GPIO_QSPI_SD3_SCHMITT 368 | // Description : Enable schmitt trigger 369 | #define PADS_QSPI_GPIO_QSPI_SD3_SCHMITT_RESET 0x1 370 | #define PADS_QSPI_GPIO_QSPI_SD3_SCHMITT_BITS 0x00000002 371 | #define PADS_QSPI_GPIO_QSPI_SD3_SCHMITT_MSB 1 372 | #define PADS_QSPI_GPIO_QSPI_SD3_SCHMITT_LSB 1 373 | #define PADS_QSPI_GPIO_QSPI_SD3_SCHMITT_ACCESS "RW" 374 | // ----------------------------------------------------------------------------- 375 | // Field : PADS_QSPI_GPIO_QSPI_SD3_SLEWFAST 376 | // Description : Slew rate control. 1 = Fast, 0 = Slow 377 | #define PADS_QSPI_GPIO_QSPI_SD3_SLEWFAST_RESET 0x0 378 | #define PADS_QSPI_GPIO_QSPI_SD3_SLEWFAST_BITS 0x00000001 379 | #define PADS_QSPI_GPIO_QSPI_SD3_SLEWFAST_MSB 0 380 | #define PADS_QSPI_GPIO_QSPI_SD3_SLEWFAST_LSB 0 381 | #define PADS_QSPI_GPIO_QSPI_SD3_SLEWFAST_ACCESS "RW" 382 | // ============================================================================= 383 | // Register : PADS_QSPI_GPIO_QSPI_SS 384 | // Description : Pad control register 385 | #define PADS_QSPI_GPIO_QSPI_SS_OFFSET 0x00000018 386 | #define PADS_QSPI_GPIO_QSPI_SS_BITS 0x000000ff 387 | #define PADS_QSPI_GPIO_QSPI_SS_RESET 0x0000005a 388 | // ----------------------------------------------------------------------------- 389 | // Field : PADS_QSPI_GPIO_QSPI_SS_OD 390 | // Description : Output disable. Has priority over output enable from 391 | // peripherals 392 | #define PADS_QSPI_GPIO_QSPI_SS_OD_RESET 0x0 393 | #define PADS_QSPI_GPIO_QSPI_SS_OD_BITS 0x00000080 394 | #define PADS_QSPI_GPIO_QSPI_SS_OD_MSB 7 395 | #define PADS_QSPI_GPIO_QSPI_SS_OD_LSB 7 396 | #define PADS_QSPI_GPIO_QSPI_SS_OD_ACCESS "RW" 397 | // ----------------------------------------------------------------------------- 398 | // Field : PADS_QSPI_GPIO_QSPI_SS_IE 399 | // Description : Input enable 400 | #define PADS_QSPI_GPIO_QSPI_SS_IE_RESET 0x1 401 | #define PADS_QSPI_GPIO_QSPI_SS_IE_BITS 0x00000040 402 | #define PADS_QSPI_GPIO_QSPI_SS_IE_MSB 6 403 | #define PADS_QSPI_GPIO_QSPI_SS_IE_LSB 6 404 | #define PADS_QSPI_GPIO_QSPI_SS_IE_ACCESS "RW" 405 | // ----------------------------------------------------------------------------- 406 | // Field : PADS_QSPI_GPIO_QSPI_SS_DRIVE 407 | // Description : Drive strength. 408 | // 0x0 -> 2mA 409 | // 0x1 -> 4mA 410 | // 0x2 -> 8mA 411 | // 0x3 -> 12mA 412 | #define PADS_QSPI_GPIO_QSPI_SS_DRIVE_RESET 0x1 413 | #define PADS_QSPI_GPIO_QSPI_SS_DRIVE_BITS 0x00000030 414 | #define PADS_QSPI_GPIO_QSPI_SS_DRIVE_MSB 5 415 | #define PADS_QSPI_GPIO_QSPI_SS_DRIVE_LSB 4 416 | #define PADS_QSPI_GPIO_QSPI_SS_DRIVE_ACCESS "RW" 417 | #define PADS_QSPI_GPIO_QSPI_SS_DRIVE_VALUE_2MA 0x0 418 | #define PADS_QSPI_GPIO_QSPI_SS_DRIVE_VALUE_4MA 0x1 419 | #define PADS_QSPI_GPIO_QSPI_SS_DRIVE_VALUE_8MA 0x2 420 | #define PADS_QSPI_GPIO_QSPI_SS_DRIVE_VALUE_12MA 0x3 421 | // ----------------------------------------------------------------------------- 422 | // Field : PADS_QSPI_GPIO_QSPI_SS_PUE 423 | // Description : Pull up enable 424 | #define PADS_QSPI_GPIO_QSPI_SS_PUE_RESET 0x1 425 | #define PADS_QSPI_GPIO_QSPI_SS_PUE_BITS 0x00000008 426 | #define PADS_QSPI_GPIO_QSPI_SS_PUE_MSB 3 427 | #define PADS_QSPI_GPIO_QSPI_SS_PUE_LSB 3 428 | #define PADS_QSPI_GPIO_QSPI_SS_PUE_ACCESS "RW" 429 | // ----------------------------------------------------------------------------- 430 | // Field : PADS_QSPI_GPIO_QSPI_SS_PDE 431 | // Description : Pull down enable 432 | #define PADS_QSPI_GPIO_QSPI_SS_PDE_RESET 0x0 433 | #define PADS_QSPI_GPIO_QSPI_SS_PDE_BITS 0x00000004 434 | #define PADS_QSPI_GPIO_QSPI_SS_PDE_MSB 2 435 | #define PADS_QSPI_GPIO_QSPI_SS_PDE_LSB 2 436 | #define PADS_QSPI_GPIO_QSPI_SS_PDE_ACCESS "RW" 437 | // ----------------------------------------------------------------------------- 438 | // Field : PADS_QSPI_GPIO_QSPI_SS_SCHMITT 439 | // Description : Enable schmitt trigger 440 | #define PADS_QSPI_GPIO_QSPI_SS_SCHMITT_RESET 0x1 441 | #define PADS_QSPI_GPIO_QSPI_SS_SCHMITT_BITS 0x00000002 442 | #define PADS_QSPI_GPIO_QSPI_SS_SCHMITT_MSB 1 443 | #define PADS_QSPI_GPIO_QSPI_SS_SCHMITT_LSB 1 444 | #define PADS_QSPI_GPIO_QSPI_SS_SCHMITT_ACCESS "RW" 445 | // ----------------------------------------------------------------------------- 446 | // Field : PADS_QSPI_GPIO_QSPI_SS_SLEWFAST 447 | // Description : Slew rate control. 1 = Fast, 0 = Slow 448 | #define PADS_QSPI_GPIO_QSPI_SS_SLEWFAST_RESET 0x0 449 | #define PADS_QSPI_GPIO_QSPI_SS_SLEWFAST_BITS 0x00000001 450 | #define PADS_QSPI_GPIO_QSPI_SS_SLEWFAST_MSB 0 451 | #define PADS_QSPI_GPIO_QSPI_SS_SLEWFAST_LSB 0 452 | #define PADS_QSPI_GPIO_QSPI_SS_SLEWFAST_ACCESS "RW" 453 | // ============================================================================= 454 | #endif // HARDWARE_REGS_PADS_QSPI_DEFINED 455 | -------------------------------------------------------------------------------- /src/include/hardware/regs/ssi.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | // ============================================================================= 7 | // Register block : SSI 8 | // Version : 1 9 | // Bus type : apb 10 | // Description : DW_apb_ssi has the following features: 11 | // * APB interface – Allows for easy integration into a 12 | // DesignWare Synthesizable Components for AMBA 2 13 | // implementation. 14 | // * APB3 and APB4 protocol support. 15 | // * Scalable APB data bus width – Supports APB data bus widths 16 | // of 8, 16, and 32 bits. 17 | // * Serial-master or serial-slave operation – Enables serial 18 | // communication with serial-master or serial-slave peripheral 19 | // devices. 20 | // * Programmable Dual/Quad/Octal SPI support in Master Mode. 21 | // * Dual Data Rate (DDR) and Read Data Strobe (RDS) Support - 22 | // Enables the DW_apb_ssi master to perform operations with the 23 | // device in DDR and RDS modes when working in Dual/Quad/Octal 24 | // mode of operation. 25 | // * Data Mask Support - Enables the DW_apb_ssi to selectively 26 | // update the bytes in the device. This feature is applicable 27 | // only in enhanced SPI modes. 28 | // * eXecute-In-Place (XIP) support - Enables the DW_apb_ssi 29 | // master to behave as a memory mapped I/O and fetches the data 30 | // from the device based on the APB read request. This feature 31 | // is applicable only in enhanced SPI modes. 32 | // * DMA Controller Interface – Enables the DW_apb_ssi to 33 | // interface to a DMA controller over the bus using a 34 | // handshaking interface for transfer requests. 35 | // * Independent masking of interrupts – Master collision, 36 | // transmit FIFO overflow, transmit FIFO empty, receive FIFO 37 | // full, receive FIFO underflow, and receive FIFO overflow 38 | // interrupts can all be masked independently. 39 | // * Multi-master contention detection – Informs the processor 40 | // of multiple serial-master accesses on the serial bus. 41 | // * Bypass of meta-stability flip-flops for synchronous clocks 42 | // – When the APB clock (pclk) and the DW_apb_ssi serial clock 43 | // (ssi_clk) are synchronous, meta-stable flip-flops are not 44 | // used when transferring control signals across these clock 45 | // domains. 46 | // * Programmable delay on the sample time of the received 47 | // serial data bit (rxd); enables programmable control of 48 | // routing delays resulting in higher serial data-bit rates. 49 | // * Programmable features: 50 | // - Serial interface operation – Choice of Motorola SPI, Texas 51 | // Instruments Synchronous Serial Protocol or National 52 | // Semiconductor Microwire. 53 | // - Clock bit-rate – Dynamic control of the serial bit rate of 54 | // the data transfer; used in only serial-master mode of 55 | // operation. 56 | // - Data Item size (4 to 32 bits) – Item size of each data 57 | // transfer under the control of the programmer. 58 | // * Configured features: 59 | // - FIFO depth – 16 words deep. The FIFO width is fixed at 32 60 | // bits. 61 | // - 1 slave select output. 62 | // - Hardware slave-select – Dedicated hardware slave-select 63 | // line. 64 | // - Combined interrupt line - one combined interrupt line from 65 | // the DW_apb_ssi to the interrupt controller. 66 | // - Interrupt polarity – active high interrupt lines. 67 | // - Serial clock polarity – low serial-clock polarity directly 68 | // after reset. 69 | // - Serial clock phase – capture on first edge of serial-clock 70 | // directly after reset. 71 | // ============================================================================= 72 | #ifndef HARDWARE_REGS_SSI_DEFINED 73 | #define HARDWARE_REGS_SSI_DEFINED 74 | // ============================================================================= 75 | // Register : SSI_CTRLR0 76 | // Description : Control register 0 77 | #define SSI_CTRLR0_OFFSET 0x00000000 78 | #define SSI_CTRLR0_BITS 0x017fffff 79 | #define SSI_CTRLR0_RESET 0x00000000 80 | // ----------------------------------------------------------------------------- 81 | // Field : SSI_CTRLR0_SSTE 82 | // Description : Slave select toggle enable 83 | #define SSI_CTRLR0_SSTE_RESET 0x0 84 | #define SSI_CTRLR0_SSTE_BITS 0x01000000 85 | #define SSI_CTRLR0_SSTE_MSB 24 86 | #define SSI_CTRLR0_SSTE_LSB 24 87 | #define SSI_CTRLR0_SSTE_ACCESS "RW" 88 | // ----------------------------------------------------------------------------- 89 | // Field : SSI_CTRLR0_SPI_FRF 90 | // Description : SPI frame format 91 | // 0x0 -> Standard 1-bit SPI frame format; 1 bit per SCK, 92 | // full-duplex 93 | // 0x1 -> Dual-SPI frame format; two bits per SCK, half-duplex 94 | // 0x2 -> Quad-SPI frame format; four bits per SCK, half-duplex 95 | #define SSI_CTRLR0_SPI_FRF_RESET 0x0 96 | #define SSI_CTRLR0_SPI_FRF_BITS 0x00600000 97 | #define SSI_CTRLR0_SPI_FRF_MSB 22 98 | #define SSI_CTRLR0_SPI_FRF_LSB 21 99 | #define SSI_CTRLR0_SPI_FRF_ACCESS "RW" 100 | #define SSI_CTRLR0_SPI_FRF_VALUE_STD 0x0 101 | #define SSI_CTRLR0_SPI_FRF_VALUE_DUAL 0x1 102 | #define SSI_CTRLR0_SPI_FRF_VALUE_QUAD 0x2 103 | // ----------------------------------------------------------------------------- 104 | // Field : SSI_CTRLR0_DFS_32 105 | // Description : Data frame size in 32b transfer mode 106 | // Value of n -> n+1 clocks per frame. 107 | #define SSI_CTRLR0_DFS_32_RESET 0x00 108 | #define SSI_CTRLR0_DFS_32_BITS 0x001f0000 109 | #define SSI_CTRLR0_DFS_32_MSB 20 110 | #define SSI_CTRLR0_DFS_32_LSB 16 111 | #define SSI_CTRLR0_DFS_32_ACCESS "RW" 112 | // ----------------------------------------------------------------------------- 113 | // Field : SSI_CTRLR0_CFS 114 | // Description : Control frame size 115 | // Value of n -> n+1 clocks per frame. 116 | #define SSI_CTRLR0_CFS_RESET 0x0 117 | #define SSI_CTRLR0_CFS_BITS 0x0000f000 118 | #define SSI_CTRLR0_CFS_MSB 15 119 | #define SSI_CTRLR0_CFS_LSB 12 120 | #define SSI_CTRLR0_CFS_ACCESS "RW" 121 | // ----------------------------------------------------------------------------- 122 | // Field : SSI_CTRLR0_SRL 123 | // Description : Shift register loop (test mode) 124 | #define SSI_CTRLR0_SRL_RESET 0x0 125 | #define SSI_CTRLR0_SRL_BITS 0x00000800 126 | #define SSI_CTRLR0_SRL_MSB 11 127 | #define SSI_CTRLR0_SRL_LSB 11 128 | #define SSI_CTRLR0_SRL_ACCESS "RW" 129 | // ----------------------------------------------------------------------------- 130 | // Field : SSI_CTRLR0_SLV_OE 131 | // Description : Slave output enable 132 | #define SSI_CTRLR0_SLV_OE_RESET 0x0 133 | #define SSI_CTRLR0_SLV_OE_BITS 0x00000400 134 | #define SSI_CTRLR0_SLV_OE_MSB 10 135 | #define SSI_CTRLR0_SLV_OE_LSB 10 136 | #define SSI_CTRLR0_SLV_OE_ACCESS "RW" 137 | // ----------------------------------------------------------------------------- 138 | // Field : SSI_CTRLR0_TMOD 139 | // Description : Transfer mode 140 | // 0x0 -> Both transmit and receive 141 | // 0x1 -> Transmit only (not for FRF == 0, standard SPI mode) 142 | // 0x2 -> Receive only (not for FRF == 0, standard SPI mode) 143 | // 0x3 -> EEPROM read mode (TX then RX; RX starts after control 144 | // data TX'd) 145 | #define SSI_CTRLR0_TMOD_RESET 0x0 146 | #define SSI_CTRLR0_TMOD_BITS 0x00000300 147 | #define SSI_CTRLR0_TMOD_MSB 9 148 | #define SSI_CTRLR0_TMOD_LSB 8 149 | #define SSI_CTRLR0_TMOD_ACCESS "RW" 150 | #define SSI_CTRLR0_TMOD_VALUE_TX_AND_RX 0x0 151 | #define SSI_CTRLR0_TMOD_VALUE_TX_ONLY 0x1 152 | #define SSI_CTRLR0_TMOD_VALUE_RX_ONLY 0x2 153 | #define SSI_CTRLR0_TMOD_VALUE_EEPROM_READ 0x3 154 | // ----------------------------------------------------------------------------- 155 | // Field : SSI_CTRLR0_SCPOL 156 | // Description : Serial clock polarity 157 | #define SSI_CTRLR0_SCPOL_RESET 0x0 158 | #define SSI_CTRLR0_SCPOL_BITS 0x00000080 159 | #define SSI_CTRLR0_SCPOL_MSB 7 160 | #define SSI_CTRLR0_SCPOL_LSB 7 161 | #define SSI_CTRLR0_SCPOL_ACCESS "RW" 162 | // ----------------------------------------------------------------------------- 163 | // Field : SSI_CTRLR0_SCPH 164 | // Description : Serial clock phase 165 | #define SSI_CTRLR0_SCPH_RESET 0x0 166 | #define SSI_CTRLR0_SCPH_BITS 0x00000040 167 | #define SSI_CTRLR0_SCPH_MSB 6 168 | #define SSI_CTRLR0_SCPH_LSB 6 169 | #define SSI_CTRLR0_SCPH_ACCESS "RW" 170 | // ----------------------------------------------------------------------------- 171 | // Field : SSI_CTRLR0_FRF 172 | // Description : Frame format 173 | #define SSI_CTRLR0_FRF_RESET 0x0 174 | #define SSI_CTRLR0_FRF_BITS 0x00000030 175 | #define SSI_CTRLR0_FRF_MSB 5 176 | #define SSI_CTRLR0_FRF_LSB 4 177 | #define SSI_CTRLR0_FRF_ACCESS "RW" 178 | // ----------------------------------------------------------------------------- 179 | // Field : SSI_CTRLR0_DFS 180 | // Description : Data frame size 181 | #define SSI_CTRLR0_DFS_RESET 0x0 182 | #define SSI_CTRLR0_DFS_BITS 0x0000000f 183 | #define SSI_CTRLR0_DFS_MSB 3 184 | #define SSI_CTRLR0_DFS_LSB 0 185 | #define SSI_CTRLR0_DFS_ACCESS "RW" 186 | // ============================================================================= 187 | // Register : SSI_CTRLR1 188 | // Description : Master Control register 1 189 | #define SSI_CTRLR1_OFFSET 0x00000004 190 | #define SSI_CTRLR1_BITS 0x0000ffff 191 | #define SSI_CTRLR1_RESET 0x00000000 192 | // ----------------------------------------------------------------------------- 193 | // Field : SSI_CTRLR1_NDF 194 | // Description : Number of data frames 195 | #define SSI_CTRLR1_NDF_RESET 0x0000 196 | #define SSI_CTRLR1_NDF_BITS 0x0000ffff 197 | #define SSI_CTRLR1_NDF_MSB 15 198 | #define SSI_CTRLR1_NDF_LSB 0 199 | #define SSI_CTRLR1_NDF_ACCESS "RW" 200 | // ============================================================================= 201 | // Register : SSI_SSIENR 202 | // Description : SSI Enable 203 | #define SSI_SSIENR_OFFSET 0x00000008 204 | #define SSI_SSIENR_BITS 0x00000001 205 | #define SSI_SSIENR_RESET 0x00000000 206 | // ----------------------------------------------------------------------------- 207 | // Field : SSI_SSIENR_SSI_EN 208 | // Description : SSI enable 209 | #define SSI_SSIENR_SSI_EN_RESET 0x0 210 | #define SSI_SSIENR_SSI_EN_BITS 0x00000001 211 | #define SSI_SSIENR_SSI_EN_MSB 0 212 | #define SSI_SSIENR_SSI_EN_LSB 0 213 | #define SSI_SSIENR_SSI_EN_ACCESS "RW" 214 | // ============================================================================= 215 | // Register : SSI_MWCR 216 | // Description : Microwire Control 217 | #define SSI_MWCR_OFFSET 0x0000000c 218 | #define SSI_MWCR_BITS 0x00000007 219 | #define SSI_MWCR_RESET 0x00000000 220 | // ----------------------------------------------------------------------------- 221 | // Field : SSI_MWCR_MHS 222 | // Description : Microwire handshaking 223 | #define SSI_MWCR_MHS_RESET 0x0 224 | #define SSI_MWCR_MHS_BITS 0x00000004 225 | #define SSI_MWCR_MHS_MSB 2 226 | #define SSI_MWCR_MHS_LSB 2 227 | #define SSI_MWCR_MHS_ACCESS "RW" 228 | // ----------------------------------------------------------------------------- 229 | // Field : SSI_MWCR_MDD 230 | // Description : Microwire control 231 | #define SSI_MWCR_MDD_RESET 0x0 232 | #define SSI_MWCR_MDD_BITS 0x00000002 233 | #define SSI_MWCR_MDD_MSB 1 234 | #define SSI_MWCR_MDD_LSB 1 235 | #define SSI_MWCR_MDD_ACCESS "RW" 236 | // ----------------------------------------------------------------------------- 237 | // Field : SSI_MWCR_MWMOD 238 | // Description : Microwire transfer mode 239 | #define SSI_MWCR_MWMOD_RESET 0x0 240 | #define SSI_MWCR_MWMOD_BITS 0x00000001 241 | #define SSI_MWCR_MWMOD_MSB 0 242 | #define SSI_MWCR_MWMOD_LSB 0 243 | #define SSI_MWCR_MWMOD_ACCESS "RW" 244 | // ============================================================================= 245 | // Register : SSI_SER 246 | // Description : Slave enable 247 | // For each bit: 248 | // 0 -> slave not selected 249 | // 1 -> slave selected 250 | #define SSI_SER_OFFSET 0x00000010 251 | #define SSI_SER_BITS 0x00000001 252 | #define SSI_SER_RESET 0x00000000 253 | #define SSI_SER_MSB 0 254 | #define SSI_SER_LSB 0 255 | #define SSI_SER_ACCESS "RW" 256 | // ============================================================================= 257 | // Register : SSI_BAUDR 258 | // Description : Baud rate 259 | #define SSI_BAUDR_OFFSET 0x00000014 260 | #define SSI_BAUDR_BITS 0x0000ffff 261 | #define SSI_BAUDR_RESET 0x00000000 262 | // ----------------------------------------------------------------------------- 263 | // Field : SSI_BAUDR_SCKDV 264 | // Description : SSI clock divider 265 | #define SSI_BAUDR_SCKDV_RESET 0x0000 266 | #define SSI_BAUDR_SCKDV_BITS 0x0000ffff 267 | #define SSI_BAUDR_SCKDV_MSB 15 268 | #define SSI_BAUDR_SCKDV_LSB 0 269 | #define SSI_BAUDR_SCKDV_ACCESS "RW" 270 | // ============================================================================= 271 | // Register : SSI_TXFTLR 272 | // Description : TX FIFO threshold level 273 | #define SSI_TXFTLR_OFFSET 0x00000018 274 | #define SSI_TXFTLR_BITS 0x000000ff 275 | #define SSI_TXFTLR_RESET 0x00000000 276 | // ----------------------------------------------------------------------------- 277 | // Field : SSI_TXFTLR_TFT 278 | // Description : Transmit FIFO threshold 279 | #define SSI_TXFTLR_TFT_RESET 0x00 280 | #define SSI_TXFTLR_TFT_BITS 0x000000ff 281 | #define SSI_TXFTLR_TFT_MSB 7 282 | #define SSI_TXFTLR_TFT_LSB 0 283 | #define SSI_TXFTLR_TFT_ACCESS "RW" 284 | // ============================================================================= 285 | // Register : SSI_RXFTLR 286 | // Description : RX FIFO threshold level 287 | #define SSI_RXFTLR_OFFSET 0x0000001c 288 | #define SSI_RXFTLR_BITS 0x000000ff 289 | #define SSI_RXFTLR_RESET 0x00000000 290 | // ----------------------------------------------------------------------------- 291 | // Field : SSI_RXFTLR_RFT 292 | // Description : Receive FIFO threshold 293 | #define SSI_RXFTLR_RFT_RESET 0x00 294 | #define SSI_RXFTLR_RFT_BITS 0x000000ff 295 | #define SSI_RXFTLR_RFT_MSB 7 296 | #define SSI_RXFTLR_RFT_LSB 0 297 | #define SSI_RXFTLR_RFT_ACCESS "RW" 298 | // ============================================================================= 299 | // Register : SSI_TXFLR 300 | // Description : TX FIFO level 301 | #define SSI_TXFLR_OFFSET 0x00000020 302 | #define SSI_TXFLR_BITS 0x000000ff 303 | #define SSI_TXFLR_RESET 0x00000000 304 | // ----------------------------------------------------------------------------- 305 | // Field : SSI_TXFLR_TFTFL 306 | // Description : Transmit FIFO level 307 | #define SSI_TXFLR_TFTFL_RESET 0x00 308 | #define SSI_TXFLR_TFTFL_BITS 0x000000ff 309 | #define SSI_TXFLR_TFTFL_MSB 7 310 | #define SSI_TXFLR_TFTFL_LSB 0 311 | #define SSI_TXFLR_TFTFL_ACCESS "RO" 312 | // ============================================================================= 313 | // Register : SSI_RXFLR 314 | // Description : RX FIFO level 315 | #define SSI_RXFLR_OFFSET 0x00000024 316 | #define SSI_RXFLR_BITS 0x000000ff 317 | #define SSI_RXFLR_RESET 0x00000000 318 | // ----------------------------------------------------------------------------- 319 | // Field : SSI_RXFLR_RXTFL 320 | // Description : Receive FIFO level 321 | #define SSI_RXFLR_RXTFL_RESET 0x00 322 | #define SSI_RXFLR_RXTFL_BITS 0x000000ff 323 | #define SSI_RXFLR_RXTFL_MSB 7 324 | #define SSI_RXFLR_RXTFL_LSB 0 325 | #define SSI_RXFLR_RXTFL_ACCESS "RO" 326 | // ============================================================================= 327 | // Register : SSI_SR 328 | // Description : Status register 329 | #define SSI_SR_OFFSET 0x00000028 330 | #define SSI_SR_BITS 0x0000007f 331 | #define SSI_SR_RESET 0x00000000 332 | // ----------------------------------------------------------------------------- 333 | // Field : SSI_SR_DCOL 334 | // Description : Data collision error 335 | #define SSI_SR_DCOL_RESET 0x0 336 | #define SSI_SR_DCOL_BITS 0x00000040 337 | #define SSI_SR_DCOL_MSB 6 338 | #define SSI_SR_DCOL_LSB 6 339 | #define SSI_SR_DCOL_ACCESS "RO" 340 | // ----------------------------------------------------------------------------- 341 | // Field : SSI_SR_TXE 342 | // Description : Transmission error 343 | #define SSI_SR_TXE_RESET 0x0 344 | #define SSI_SR_TXE_BITS 0x00000020 345 | #define SSI_SR_TXE_MSB 5 346 | #define SSI_SR_TXE_LSB 5 347 | #define SSI_SR_TXE_ACCESS "RO" 348 | // ----------------------------------------------------------------------------- 349 | // Field : SSI_SR_RFF 350 | // Description : Receive FIFO full 351 | #define SSI_SR_RFF_RESET 0x0 352 | #define SSI_SR_RFF_BITS 0x00000010 353 | #define SSI_SR_RFF_MSB 4 354 | #define SSI_SR_RFF_LSB 4 355 | #define SSI_SR_RFF_ACCESS "RO" 356 | // ----------------------------------------------------------------------------- 357 | // Field : SSI_SR_RFNE 358 | // Description : Receive FIFO not empty 359 | #define SSI_SR_RFNE_RESET 0x0 360 | #define SSI_SR_RFNE_BITS 0x00000008 361 | #define SSI_SR_RFNE_MSB 3 362 | #define SSI_SR_RFNE_LSB 3 363 | #define SSI_SR_RFNE_ACCESS "RO" 364 | // ----------------------------------------------------------------------------- 365 | // Field : SSI_SR_TFE 366 | // Description : Transmit FIFO empty 367 | #define SSI_SR_TFE_RESET 0x0 368 | #define SSI_SR_TFE_BITS 0x00000004 369 | #define SSI_SR_TFE_MSB 2 370 | #define SSI_SR_TFE_LSB 2 371 | #define SSI_SR_TFE_ACCESS "RO" 372 | // ----------------------------------------------------------------------------- 373 | // Field : SSI_SR_TFNF 374 | // Description : Transmit FIFO not full 375 | #define SSI_SR_TFNF_RESET 0x0 376 | #define SSI_SR_TFNF_BITS 0x00000002 377 | #define SSI_SR_TFNF_MSB 1 378 | #define SSI_SR_TFNF_LSB 1 379 | #define SSI_SR_TFNF_ACCESS "RO" 380 | // ----------------------------------------------------------------------------- 381 | // Field : SSI_SR_BUSY 382 | // Description : SSI busy flag 383 | #define SSI_SR_BUSY_RESET 0x0 384 | #define SSI_SR_BUSY_BITS 0x00000001 385 | #define SSI_SR_BUSY_MSB 0 386 | #define SSI_SR_BUSY_LSB 0 387 | #define SSI_SR_BUSY_ACCESS "RO" 388 | // ============================================================================= 389 | // Register : SSI_IMR 390 | // Description : Interrupt mask 391 | #define SSI_IMR_OFFSET 0x0000002c 392 | #define SSI_IMR_BITS 0x0000003f 393 | #define SSI_IMR_RESET 0x00000000 394 | // ----------------------------------------------------------------------------- 395 | // Field : SSI_IMR_MSTIM 396 | // Description : Multi-master contention interrupt mask 397 | #define SSI_IMR_MSTIM_RESET 0x0 398 | #define SSI_IMR_MSTIM_BITS 0x00000020 399 | #define SSI_IMR_MSTIM_MSB 5 400 | #define SSI_IMR_MSTIM_LSB 5 401 | #define SSI_IMR_MSTIM_ACCESS "RW" 402 | // ----------------------------------------------------------------------------- 403 | // Field : SSI_IMR_RXFIM 404 | // Description : Receive FIFO full interrupt mask 405 | #define SSI_IMR_RXFIM_RESET 0x0 406 | #define SSI_IMR_RXFIM_BITS 0x00000010 407 | #define SSI_IMR_RXFIM_MSB 4 408 | #define SSI_IMR_RXFIM_LSB 4 409 | #define SSI_IMR_RXFIM_ACCESS "RW" 410 | // ----------------------------------------------------------------------------- 411 | // Field : SSI_IMR_RXOIM 412 | // Description : Receive FIFO overflow interrupt mask 413 | #define SSI_IMR_RXOIM_RESET 0x0 414 | #define SSI_IMR_RXOIM_BITS 0x00000008 415 | #define SSI_IMR_RXOIM_MSB 3 416 | #define SSI_IMR_RXOIM_LSB 3 417 | #define SSI_IMR_RXOIM_ACCESS "RW" 418 | // ----------------------------------------------------------------------------- 419 | // Field : SSI_IMR_RXUIM 420 | // Description : Receive FIFO underflow interrupt mask 421 | #define SSI_IMR_RXUIM_RESET 0x0 422 | #define SSI_IMR_RXUIM_BITS 0x00000004 423 | #define SSI_IMR_RXUIM_MSB 2 424 | #define SSI_IMR_RXUIM_LSB 2 425 | #define SSI_IMR_RXUIM_ACCESS "RW" 426 | // ----------------------------------------------------------------------------- 427 | // Field : SSI_IMR_TXOIM 428 | // Description : Transmit FIFO overflow interrupt mask 429 | #define SSI_IMR_TXOIM_RESET 0x0 430 | #define SSI_IMR_TXOIM_BITS 0x00000002 431 | #define SSI_IMR_TXOIM_MSB 1 432 | #define SSI_IMR_TXOIM_LSB 1 433 | #define SSI_IMR_TXOIM_ACCESS "RW" 434 | // ----------------------------------------------------------------------------- 435 | // Field : SSI_IMR_TXEIM 436 | // Description : Transmit FIFO empty interrupt mask 437 | #define SSI_IMR_TXEIM_RESET 0x0 438 | #define SSI_IMR_TXEIM_BITS 0x00000001 439 | #define SSI_IMR_TXEIM_MSB 0 440 | #define SSI_IMR_TXEIM_LSB 0 441 | #define SSI_IMR_TXEIM_ACCESS "RW" 442 | // ============================================================================= 443 | // Register : SSI_ISR 444 | // Description : Interrupt status 445 | #define SSI_ISR_OFFSET 0x00000030 446 | #define SSI_ISR_BITS 0x0000003f 447 | #define SSI_ISR_RESET 0x00000000 448 | // ----------------------------------------------------------------------------- 449 | // Field : SSI_ISR_MSTIS 450 | // Description : Multi-master contention interrupt status 451 | #define SSI_ISR_MSTIS_RESET 0x0 452 | #define SSI_ISR_MSTIS_BITS 0x00000020 453 | #define SSI_ISR_MSTIS_MSB 5 454 | #define SSI_ISR_MSTIS_LSB 5 455 | #define SSI_ISR_MSTIS_ACCESS "RO" 456 | // ----------------------------------------------------------------------------- 457 | // Field : SSI_ISR_RXFIS 458 | // Description : Receive FIFO full interrupt status 459 | #define SSI_ISR_RXFIS_RESET 0x0 460 | #define SSI_ISR_RXFIS_BITS 0x00000010 461 | #define SSI_ISR_RXFIS_MSB 4 462 | #define SSI_ISR_RXFIS_LSB 4 463 | #define SSI_ISR_RXFIS_ACCESS "RO" 464 | // ----------------------------------------------------------------------------- 465 | // Field : SSI_ISR_RXOIS 466 | // Description : Receive FIFO overflow interrupt status 467 | #define SSI_ISR_RXOIS_RESET 0x0 468 | #define SSI_ISR_RXOIS_BITS 0x00000008 469 | #define SSI_ISR_RXOIS_MSB 3 470 | #define SSI_ISR_RXOIS_LSB 3 471 | #define SSI_ISR_RXOIS_ACCESS "RO" 472 | // ----------------------------------------------------------------------------- 473 | // Field : SSI_ISR_RXUIS 474 | // Description : Receive FIFO underflow interrupt status 475 | #define SSI_ISR_RXUIS_RESET 0x0 476 | #define SSI_ISR_RXUIS_BITS 0x00000004 477 | #define SSI_ISR_RXUIS_MSB 2 478 | #define SSI_ISR_RXUIS_LSB 2 479 | #define SSI_ISR_RXUIS_ACCESS "RO" 480 | // ----------------------------------------------------------------------------- 481 | // Field : SSI_ISR_TXOIS 482 | // Description : Transmit FIFO overflow interrupt status 483 | #define SSI_ISR_TXOIS_RESET 0x0 484 | #define SSI_ISR_TXOIS_BITS 0x00000002 485 | #define SSI_ISR_TXOIS_MSB 1 486 | #define SSI_ISR_TXOIS_LSB 1 487 | #define SSI_ISR_TXOIS_ACCESS "RO" 488 | // ----------------------------------------------------------------------------- 489 | // Field : SSI_ISR_TXEIS 490 | // Description : Transmit FIFO empty interrupt status 491 | #define SSI_ISR_TXEIS_RESET 0x0 492 | #define SSI_ISR_TXEIS_BITS 0x00000001 493 | #define SSI_ISR_TXEIS_MSB 0 494 | #define SSI_ISR_TXEIS_LSB 0 495 | #define SSI_ISR_TXEIS_ACCESS "RO" 496 | // ============================================================================= 497 | // Register : SSI_RISR 498 | // Description : Raw interrupt status 499 | #define SSI_RISR_OFFSET 0x00000034 500 | #define SSI_RISR_BITS 0x0000003f 501 | #define SSI_RISR_RESET 0x00000000 502 | // ----------------------------------------------------------------------------- 503 | // Field : SSI_RISR_MSTIR 504 | // Description : Multi-master contention raw interrupt status 505 | #define SSI_RISR_MSTIR_RESET 0x0 506 | #define SSI_RISR_MSTIR_BITS 0x00000020 507 | #define SSI_RISR_MSTIR_MSB 5 508 | #define SSI_RISR_MSTIR_LSB 5 509 | #define SSI_RISR_MSTIR_ACCESS "RO" 510 | // ----------------------------------------------------------------------------- 511 | // Field : SSI_RISR_RXFIR 512 | // Description : Receive FIFO full raw interrupt status 513 | #define SSI_RISR_RXFIR_RESET 0x0 514 | #define SSI_RISR_RXFIR_BITS 0x00000010 515 | #define SSI_RISR_RXFIR_MSB 4 516 | #define SSI_RISR_RXFIR_LSB 4 517 | #define SSI_RISR_RXFIR_ACCESS "RO" 518 | // ----------------------------------------------------------------------------- 519 | // Field : SSI_RISR_RXOIR 520 | // Description : Receive FIFO overflow raw interrupt status 521 | #define SSI_RISR_RXOIR_RESET 0x0 522 | #define SSI_RISR_RXOIR_BITS 0x00000008 523 | #define SSI_RISR_RXOIR_MSB 3 524 | #define SSI_RISR_RXOIR_LSB 3 525 | #define SSI_RISR_RXOIR_ACCESS "RO" 526 | // ----------------------------------------------------------------------------- 527 | // Field : SSI_RISR_RXUIR 528 | // Description : Receive FIFO underflow raw interrupt status 529 | #define SSI_RISR_RXUIR_RESET 0x0 530 | #define SSI_RISR_RXUIR_BITS 0x00000004 531 | #define SSI_RISR_RXUIR_MSB 2 532 | #define SSI_RISR_RXUIR_LSB 2 533 | #define SSI_RISR_RXUIR_ACCESS "RO" 534 | // ----------------------------------------------------------------------------- 535 | // Field : SSI_RISR_TXOIR 536 | // Description : Transmit FIFO overflow raw interrupt status 537 | #define SSI_RISR_TXOIR_RESET 0x0 538 | #define SSI_RISR_TXOIR_BITS 0x00000002 539 | #define SSI_RISR_TXOIR_MSB 1 540 | #define SSI_RISR_TXOIR_LSB 1 541 | #define SSI_RISR_TXOIR_ACCESS "RO" 542 | // ----------------------------------------------------------------------------- 543 | // Field : SSI_RISR_TXEIR 544 | // Description : Transmit FIFO empty raw interrupt status 545 | #define SSI_RISR_TXEIR_RESET 0x0 546 | #define SSI_RISR_TXEIR_BITS 0x00000001 547 | #define SSI_RISR_TXEIR_MSB 0 548 | #define SSI_RISR_TXEIR_LSB 0 549 | #define SSI_RISR_TXEIR_ACCESS "RO" 550 | // ============================================================================= 551 | // Register : SSI_TXOICR 552 | // Description : TX FIFO overflow interrupt clear 553 | // Clear-on-read transmit FIFO overflow interrupt 554 | #define SSI_TXOICR_OFFSET 0x00000038 555 | #define SSI_TXOICR_BITS 0x00000001 556 | #define SSI_TXOICR_RESET 0x00000000 557 | #define SSI_TXOICR_MSB 0 558 | #define SSI_TXOICR_LSB 0 559 | #define SSI_TXOICR_ACCESS "RO" 560 | // ============================================================================= 561 | // Register : SSI_RXOICR 562 | // Description : RX FIFO overflow interrupt clear 563 | // Clear-on-read receive FIFO overflow interrupt 564 | #define SSI_RXOICR_OFFSET 0x0000003c 565 | #define SSI_RXOICR_BITS 0x00000001 566 | #define SSI_RXOICR_RESET 0x00000000 567 | #define SSI_RXOICR_MSB 0 568 | #define SSI_RXOICR_LSB 0 569 | #define SSI_RXOICR_ACCESS "RO" 570 | // ============================================================================= 571 | // Register : SSI_RXUICR 572 | // Description : RX FIFO underflow interrupt clear 573 | // Clear-on-read receive FIFO underflow interrupt 574 | #define SSI_RXUICR_OFFSET 0x00000040 575 | #define SSI_RXUICR_BITS 0x00000001 576 | #define SSI_RXUICR_RESET 0x00000000 577 | #define SSI_RXUICR_MSB 0 578 | #define SSI_RXUICR_LSB 0 579 | #define SSI_RXUICR_ACCESS "RO" 580 | // ============================================================================= 581 | // Register : SSI_MSTICR 582 | // Description : Multi-master interrupt clear 583 | // Clear-on-read multi-master contention interrupt 584 | #define SSI_MSTICR_OFFSET 0x00000044 585 | #define SSI_MSTICR_BITS 0x00000001 586 | #define SSI_MSTICR_RESET 0x00000000 587 | #define SSI_MSTICR_MSB 0 588 | #define SSI_MSTICR_LSB 0 589 | #define SSI_MSTICR_ACCESS "RO" 590 | // ============================================================================= 591 | // Register : SSI_ICR 592 | // Description : Interrupt clear 593 | // Clear-on-read all active interrupts 594 | #define SSI_ICR_OFFSET 0x00000048 595 | #define SSI_ICR_BITS 0x00000001 596 | #define SSI_ICR_RESET 0x00000000 597 | #define SSI_ICR_MSB 0 598 | #define SSI_ICR_LSB 0 599 | #define SSI_ICR_ACCESS "RO" 600 | // ============================================================================= 601 | // Register : SSI_DMACR 602 | // Description : DMA control 603 | #define SSI_DMACR_OFFSET 0x0000004c 604 | #define SSI_DMACR_BITS 0x00000003 605 | #define SSI_DMACR_RESET 0x00000000 606 | // ----------------------------------------------------------------------------- 607 | // Field : SSI_DMACR_TDMAE 608 | // Description : Transmit DMA enable 609 | #define SSI_DMACR_TDMAE_RESET 0x0 610 | #define SSI_DMACR_TDMAE_BITS 0x00000002 611 | #define SSI_DMACR_TDMAE_MSB 1 612 | #define SSI_DMACR_TDMAE_LSB 1 613 | #define SSI_DMACR_TDMAE_ACCESS "RW" 614 | // ----------------------------------------------------------------------------- 615 | // Field : SSI_DMACR_RDMAE 616 | // Description : Receive DMA enable 617 | #define SSI_DMACR_RDMAE_RESET 0x0 618 | #define SSI_DMACR_RDMAE_BITS 0x00000001 619 | #define SSI_DMACR_RDMAE_MSB 0 620 | #define SSI_DMACR_RDMAE_LSB 0 621 | #define SSI_DMACR_RDMAE_ACCESS "RW" 622 | // ============================================================================= 623 | // Register : SSI_DMATDLR 624 | // Description : DMA TX data level 625 | #define SSI_DMATDLR_OFFSET 0x00000050 626 | #define SSI_DMATDLR_BITS 0x000000ff 627 | #define SSI_DMATDLR_RESET 0x00000000 628 | // ----------------------------------------------------------------------------- 629 | // Field : SSI_DMATDLR_DMATDL 630 | // Description : Transmit data watermark level 631 | #define SSI_DMATDLR_DMATDL_RESET 0x00 632 | #define SSI_DMATDLR_DMATDL_BITS 0x000000ff 633 | #define SSI_DMATDLR_DMATDL_MSB 7 634 | #define SSI_DMATDLR_DMATDL_LSB 0 635 | #define SSI_DMATDLR_DMATDL_ACCESS "RW" 636 | // ============================================================================= 637 | // Register : SSI_DMARDLR 638 | // Description : DMA RX data level 639 | #define SSI_DMARDLR_OFFSET 0x00000054 640 | #define SSI_DMARDLR_BITS 0x000000ff 641 | #define SSI_DMARDLR_RESET 0x00000000 642 | // ----------------------------------------------------------------------------- 643 | // Field : SSI_DMARDLR_DMARDL 644 | // Description : Receive data watermark level (DMARDLR+1) 645 | #define SSI_DMARDLR_DMARDL_RESET 0x00 646 | #define SSI_DMARDLR_DMARDL_BITS 0x000000ff 647 | #define SSI_DMARDLR_DMARDL_MSB 7 648 | #define SSI_DMARDLR_DMARDL_LSB 0 649 | #define SSI_DMARDLR_DMARDL_ACCESS "RW" 650 | // ============================================================================= 651 | // Register : SSI_IDR 652 | // Description : Identification register 653 | #define SSI_IDR_OFFSET 0x00000058 654 | #define SSI_IDR_BITS 0xffffffff 655 | #define SSI_IDR_RESET 0x51535049 656 | // ----------------------------------------------------------------------------- 657 | // Field : SSI_IDR_IDCODE 658 | // Description : Peripheral dentification code 659 | #define SSI_IDR_IDCODE_RESET 0x51535049 660 | #define SSI_IDR_IDCODE_BITS 0xffffffff 661 | #define SSI_IDR_IDCODE_MSB 31 662 | #define SSI_IDR_IDCODE_LSB 0 663 | #define SSI_IDR_IDCODE_ACCESS "RO" 664 | // ============================================================================= 665 | // Register : SSI_SSI_VERSION_ID 666 | // Description : Version ID 667 | #define SSI_SSI_VERSION_ID_OFFSET 0x0000005c 668 | #define SSI_SSI_VERSION_ID_BITS 0xffffffff 669 | #define SSI_SSI_VERSION_ID_RESET 0x3430312a 670 | // ----------------------------------------------------------------------------- 671 | // Field : SSI_SSI_VERSION_ID_SSI_COMP_VERSION 672 | // Description : SNPS component version (format X.YY) 673 | #define SSI_SSI_VERSION_ID_SSI_COMP_VERSION_RESET 0x3430312a 674 | #define SSI_SSI_VERSION_ID_SSI_COMP_VERSION_BITS 0xffffffff 675 | #define SSI_SSI_VERSION_ID_SSI_COMP_VERSION_MSB 31 676 | #define SSI_SSI_VERSION_ID_SSI_COMP_VERSION_LSB 0 677 | #define SSI_SSI_VERSION_ID_SSI_COMP_VERSION_ACCESS "RO" 678 | // ============================================================================= 679 | // Register : SSI_DR0 680 | // Description : Data Register 0 (of 36) 681 | #define SSI_DR0_OFFSET 0x00000060 682 | #define SSI_DR0_BITS 0xffffffff 683 | #define SSI_DR0_RESET 0x00000000 684 | // ----------------------------------------------------------------------------- 685 | // Field : SSI_DR0_DR 686 | // Description : First data register of 36 687 | #define SSI_DR0_DR_RESET 0x00000000 688 | #define SSI_DR0_DR_BITS 0xffffffff 689 | #define SSI_DR0_DR_MSB 31 690 | #define SSI_DR0_DR_LSB 0 691 | #define SSI_DR0_DR_ACCESS "RW" 692 | // ============================================================================= 693 | // Register : SSI_RX_SAMPLE_DLY 694 | // Description : RX sample delay 695 | #define SSI_RX_SAMPLE_DLY_OFFSET 0x000000f0 696 | #define SSI_RX_SAMPLE_DLY_BITS 0x000000ff 697 | #define SSI_RX_SAMPLE_DLY_RESET 0x00000000 698 | // ----------------------------------------------------------------------------- 699 | // Field : SSI_RX_SAMPLE_DLY_RSD 700 | // Description : RXD sample delay (in SCLK cycles) 701 | #define SSI_RX_SAMPLE_DLY_RSD_RESET 0x00 702 | #define SSI_RX_SAMPLE_DLY_RSD_BITS 0x000000ff 703 | #define SSI_RX_SAMPLE_DLY_RSD_MSB 7 704 | #define SSI_RX_SAMPLE_DLY_RSD_LSB 0 705 | #define SSI_RX_SAMPLE_DLY_RSD_ACCESS "RW" 706 | // ============================================================================= 707 | // Register : SSI_SPI_CTRLR0 708 | // Description : SPI control 709 | #define SSI_SPI_CTRLR0_OFFSET 0x000000f4 710 | #define SSI_SPI_CTRLR0_BITS 0xff07fb3f 711 | #define SSI_SPI_CTRLR0_RESET 0x03000000 712 | // ----------------------------------------------------------------------------- 713 | // Field : SSI_SPI_CTRLR0_XIP_CMD 714 | // Description : SPI Command to send in XIP mode (INST_L = 8-bit) or to append 715 | // to Address (INST_L = 0-bit) 716 | #define SSI_SPI_CTRLR0_XIP_CMD_RESET 0x03 717 | #define SSI_SPI_CTRLR0_XIP_CMD_BITS 0xff000000 718 | #define SSI_SPI_CTRLR0_XIP_CMD_MSB 31 719 | #define SSI_SPI_CTRLR0_XIP_CMD_LSB 24 720 | #define SSI_SPI_CTRLR0_XIP_CMD_ACCESS "RW" 721 | // ----------------------------------------------------------------------------- 722 | // Field : SSI_SPI_CTRLR0_SPI_RXDS_EN 723 | // Description : Read data strobe enable 724 | #define SSI_SPI_CTRLR0_SPI_RXDS_EN_RESET 0x0 725 | #define SSI_SPI_CTRLR0_SPI_RXDS_EN_BITS 0x00040000 726 | #define SSI_SPI_CTRLR0_SPI_RXDS_EN_MSB 18 727 | #define SSI_SPI_CTRLR0_SPI_RXDS_EN_LSB 18 728 | #define SSI_SPI_CTRLR0_SPI_RXDS_EN_ACCESS "RW" 729 | // ----------------------------------------------------------------------------- 730 | // Field : SSI_SPI_CTRLR0_INST_DDR_EN 731 | // Description : Instruction DDR transfer enable 732 | #define SSI_SPI_CTRLR0_INST_DDR_EN_RESET 0x0 733 | #define SSI_SPI_CTRLR0_INST_DDR_EN_BITS 0x00020000 734 | #define SSI_SPI_CTRLR0_INST_DDR_EN_MSB 17 735 | #define SSI_SPI_CTRLR0_INST_DDR_EN_LSB 17 736 | #define SSI_SPI_CTRLR0_INST_DDR_EN_ACCESS "RW" 737 | // ----------------------------------------------------------------------------- 738 | // Field : SSI_SPI_CTRLR0_SPI_DDR_EN 739 | // Description : SPI DDR transfer enable 740 | #define SSI_SPI_CTRLR0_SPI_DDR_EN_RESET 0x0 741 | #define SSI_SPI_CTRLR0_SPI_DDR_EN_BITS 0x00010000 742 | #define SSI_SPI_CTRLR0_SPI_DDR_EN_MSB 16 743 | #define SSI_SPI_CTRLR0_SPI_DDR_EN_LSB 16 744 | #define SSI_SPI_CTRLR0_SPI_DDR_EN_ACCESS "RW" 745 | // ----------------------------------------------------------------------------- 746 | // Field : SSI_SPI_CTRLR0_WAIT_CYCLES 747 | // Description : Wait cycles between control frame transmit and data reception 748 | // (in SCLK cycles) 749 | #define SSI_SPI_CTRLR0_WAIT_CYCLES_RESET 0x00 750 | #define SSI_SPI_CTRLR0_WAIT_CYCLES_BITS 0x0000f800 751 | #define SSI_SPI_CTRLR0_WAIT_CYCLES_MSB 15 752 | #define SSI_SPI_CTRLR0_WAIT_CYCLES_LSB 11 753 | #define SSI_SPI_CTRLR0_WAIT_CYCLES_ACCESS "RW" 754 | // ----------------------------------------------------------------------------- 755 | // Field : SSI_SPI_CTRLR0_INST_L 756 | // Description : Instruction length (0/4/8/16b) 757 | // 0x0 -> No instruction 758 | // 0x1 -> 4-bit instruction 759 | // 0x2 -> 8-bit instruction 760 | // 0x3 -> 16-bit instruction 761 | #define SSI_SPI_CTRLR0_INST_L_RESET 0x0 762 | #define SSI_SPI_CTRLR0_INST_L_BITS 0x00000300 763 | #define SSI_SPI_CTRLR0_INST_L_MSB 9 764 | #define SSI_SPI_CTRLR0_INST_L_LSB 8 765 | #define SSI_SPI_CTRLR0_INST_L_ACCESS "RW" 766 | #define SSI_SPI_CTRLR0_INST_L_VALUE_NONE 0x0 767 | #define SSI_SPI_CTRLR0_INST_L_VALUE_4B 0x1 768 | #define SSI_SPI_CTRLR0_INST_L_VALUE_8B 0x2 769 | #define SSI_SPI_CTRLR0_INST_L_VALUE_16B 0x3 770 | // ----------------------------------------------------------------------------- 771 | // Field : SSI_SPI_CTRLR0_ADDR_L 772 | // Description : Address length (0b-60b in 4b increments) 773 | #define SSI_SPI_CTRLR0_ADDR_L_RESET 0x0 774 | #define SSI_SPI_CTRLR0_ADDR_L_BITS 0x0000003c 775 | #define SSI_SPI_CTRLR0_ADDR_L_MSB 5 776 | #define SSI_SPI_CTRLR0_ADDR_L_LSB 2 777 | #define SSI_SPI_CTRLR0_ADDR_L_ACCESS "RW" 778 | // ----------------------------------------------------------------------------- 779 | // Field : SSI_SPI_CTRLR0_TRANS_TYPE 780 | // Description : Address and instruction transfer format 781 | // 0x0 -> Command and address both in standard SPI frame format 782 | // 0x1 -> Command in standard SPI format, address in format 783 | // specified by FRF 784 | // 0x2 -> Command and address both in format specified by FRF 785 | // (e.g. Dual-SPI) 786 | #define SSI_SPI_CTRLR0_TRANS_TYPE_RESET 0x0 787 | #define SSI_SPI_CTRLR0_TRANS_TYPE_BITS 0x00000003 788 | #define SSI_SPI_CTRLR0_TRANS_TYPE_MSB 1 789 | #define SSI_SPI_CTRLR0_TRANS_TYPE_LSB 0 790 | #define SSI_SPI_CTRLR0_TRANS_TYPE_ACCESS "RW" 791 | #define SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C1A 0x0 792 | #define SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C2A 0x1 793 | #define SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_2C2A 0x2 794 | // ============================================================================= 795 | // Register : SSI_TXD_DRIVE_EDGE 796 | // Description : TX drive edge 797 | #define SSI_TXD_DRIVE_EDGE_OFFSET 0x000000f8 798 | #define SSI_TXD_DRIVE_EDGE_BITS 0x000000ff 799 | #define SSI_TXD_DRIVE_EDGE_RESET 0x00000000 800 | // ----------------------------------------------------------------------------- 801 | // Field : SSI_TXD_DRIVE_EDGE_TDE 802 | // Description : TXD drive edge 803 | #define SSI_TXD_DRIVE_EDGE_TDE_RESET 0x00 804 | #define SSI_TXD_DRIVE_EDGE_TDE_BITS 0x000000ff 805 | #define SSI_TXD_DRIVE_EDGE_TDE_MSB 7 806 | #define SSI_TXD_DRIVE_EDGE_TDE_LSB 0 807 | #define SSI_TXD_DRIVE_EDGE_TDE_ACCESS "RW" 808 | // ============================================================================= 809 | #endif // HARDWARE_REGS_SSI_DEFINED 810 | -------------------------------------------------------------------------------- /src/include/pico.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | #ifndef PICO_H_ 8 | #define PICO_H_ 9 | 10 | /** \file pico.h 11 | * \defgroup pico_base pico_base 12 | * 13 | * Core types and macros for the Raspberry Pi Pico SDK. This header is intended to be included by all source code 14 | * as it includes configuration headers and overrides in the correct order 15 | * 16 | * This header may be included by assembly code 17 | */ 18 | 19 | #define __PICO_STRING(x) #x 20 | #define __PICO_XSTRING(x) __PICO_STRING(x) 21 | 22 | #include "pico/types.h" 23 | #include "pico/version.h" 24 | 25 | // PICO_CONFIG: PICO_CONFIG_HEADER, unquoted path to header include in place of the default pico/config.h which may be desirable for build systems which can't easily generate the config_autogen header, group=pico_base 26 | #ifdef PICO_CONFIG_HEADER 27 | #include __PICO_XSTRING(PICO_CONFIG_HEADER) 28 | #else 29 | #include "pico/config.h" 30 | #endif 31 | #include "pico/platform.h" 32 | #include "pico/error.h" 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/include/pico/asm_helper.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | #include "pico.h" 8 | 9 | // do not put align in here as it is used mid function sometimes 10 | .macro regular_func x 11 | .global \x 12 | .type \x,%function 13 | .thumb_func 14 | \x: 15 | .endm 16 | 17 | .macro regular_func_with_section x 18 | .section .text.\x 19 | regular_func \x 20 | .endm 21 | 22 | // do not put align in here as it is used mid function sometimes 23 | .macro wrapper_func x 24 | regular_func WRAPPER_FUNC_NAME(\x) 25 | .endm 26 | 27 | .macro __pre_init func, priority_string 28 | .section .preinit_array.\priority_string 29 | .align 2 30 | .word \func 31 | .endm 32 | 33 | -------------------------------------------------------------------------------- /src/include/pico/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | #ifndef PICO_CONFIG_H_ 8 | #define PICO_CONFIG_H_ 9 | 10 | // ----------------------------------------------------- 11 | // NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO 12 | // SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES 13 | // OR USE #ifndef __ASSEMBLER__ guards 14 | // ------------- 15 | 16 | // PICO_CONFIG_HEADER_FILES and then PICO_SDK__CONFIG_INCLUDE_FILES 17 | // entries are dumped in order at build time into this generated header 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/include/pico/error.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | #ifndef _PICO_ERROR_H 8 | #define _PICO_ERROR_H 9 | 10 | #ifndef __ASSEMBLER__ 11 | 12 | /*! 13 | * \brief Common return codes from pico_sdk methods that return a status 14 | * \ingroup pico_base 15 | */ 16 | enum pico_error_codes { 17 | PICO_OK = 0, 18 | PICO_ERROR_NONE = 0, 19 | PICO_ERROR_TIMEOUT = -1, 20 | PICO_ERROR_GENERIC = -2, 21 | PICO_ERROR_NO_DATA = -3, 22 | PICO_ERROR_NOT_PERMITTED = -4, 23 | PICO_ERROR_INVALID_ARG = -5, 24 | PICO_ERROR_IO = -6, 25 | }; 26 | 27 | #endif // !__ASSEMBLER__ 28 | 29 | #endif -------------------------------------------------------------------------------- /src/include/pico/platform.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | #ifndef _PICO_PLATFORM_H_ 8 | #define _PICO_PLATFORM_H_ 9 | 10 | /** \file platform.h 11 | * \defgroup pico_platform pico_platform 12 | * 13 | * Macros and definitions (and functions when included by non assembly code) for the RP2 family device / architecture 14 | * to provide a common abstraction over low level compiler / platform specifics. 15 | * 16 | * This header may be included by assembly code 17 | */ 18 | 19 | #include "hardware/platform_defs.h" 20 | #include "hardware/regs/addressmap.h" 21 | #include "hardware/regs/sio.h" 22 | 23 | // Marker for builds targeting the RP2040 24 | #define PICO_RP2040 1 25 | 26 | // PICO_CONFIG: PICO_STACK_SIZE, Stack Size, min=0x100, default=0x800, advanced=true, group=pico_platform 27 | #ifndef PICO_STACK_SIZE 28 | #define PICO_STACK_SIZE _u(0x800) 29 | #endif 30 | 31 | // PICO_CONFIG: PICO_HEAP_SIZE, Heap size to reserve, min=0x100, default=0x800, advanced=true, group=pico_platform 32 | #ifndef PICO_HEAP_SIZE 33 | #define PICO_HEAP_SIZE _u(0x800) 34 | #endif 35 | 36 | // PICO_CONFIG: PICO_NO_RAM_VECTOR_TABLE, Enable/disable the RAM vector table, type=bool, default=0, advanced=true, group=pico_platform 37 | #ifndef PICO_NO_RAM_VECTOR_TABLE 38 | #define PICO_NO_RAM_VECTOR_TABLE 0 39 | #endif 40 | 41 | // PICO_CONFIG: PICO_RP2040_B0_SUPPORTED, Whether to include any specific software support for RP2040 B0 revision, type=bool, default=1, advanced=true, group=pico_platform 42 | #ifndef PICO_RP2040_B0_SUPPORTED 43 | #define PICO_RP2040_B0_SUPPORTED 1 44 | #endif 45 | 46 | // PICO_CONFIG: PICO_FLOAT_SUPPORT_ROM_V1, Include float support code for RP2040 B0 when that chip revision is supported , type=bool, default=1, advanced=true, group=pico_platform 47 | #ifndef PICO_FLOAT_SUPPORT_ROM_V1 48 | #define PICO_FLOAT_SUPPORT_ROM_V1 1 49 | #endif 50 | 51 | // PICO_CONFIG: PICO_DOUBLE_SUPPORT_ROM_V1, Include double support code for RP2040 B0 when that chip revision is supported , type=bool, default=1, advanced=true, group=pico_platform 52 | #ifndef PICO_DOUBLE_SUPPORT_ROM_V1 53 | #define PICO_DOUBLE_SUPPORT_ROM_V1 1 54 | #endif 55 | 56 | 57 | // PICO_CONFIG: PICO_RP2040_B1_SUPPORTED, Whether to include any specific software support for RP2040 B1 revision, type=bool, default=1, advanced=true, group=pico_platform 58 | #ifndef PICO_RP2040_B1_SUPPORTED 59 | #define PICO_RP2040_B1_SUPPORTED 1 60 | #endif 61 | 62 | // PICO_CONFIG: PICO_RP2040_B2_SUPPORTED, Whether to include any specific software support for RP2040 B2 revision, type=bool, default=1, advanced=true, group=pico_platform 63 | #ifndef PICO_RP2040_B2_SUPPORTED 64 | #define PICO_RP2040_B2_SUPPORTED 1 65 | #endif 66 | 67 | // --- remainder of file is not included by assembly code --- 68 | 69 | #ifndef __ASSEMBLER__ 70 | 71 | #include 72 | #include "pico/types.h" 73 | 74 | #ifdef __cplusplus 75 | extern "C" { 76 | #endif 77 | 78 | /*! \brief Marker for an interrupt handler 79 | * \ingroup pico_platform 80 | * For example an IRQ handler function called my_interrupt_handler: 81 | * 82 | * void __isr my_interrupt_handler(void) { 83 | */ 84 | #define __isr 85 | 86 | /*! \brief Section attribute macro for placement in RAM after the `.data` section 87 | * \ingroup pico_platform 88 | * 89 | * For example a 400 element `uint32_t` array placed after the .data section 90 | * 91 | * uint32_t __after_data("my_group_name") a_big_array[400]; 92 | * 93 | * The section attribute is `.after_data.` 94 | * 95 | * \param group a string suffix to use in the section name to distinguish groups that can be linker 96 | * garbage-collected independently 97 | */ 98 | #define __after_data(group) __attribute__((section(".after_data." group))) 99 | 100 | /*! \brief Section attribute macro for placement not in flash (i.e in RAM) 101 | * \ingroup pico_platform 102 | * 103 | * For example a 3 element `uint32_t` array placed in RAM (even though it is `static const`) 104 | * 105 | * static const uint32_t __not_in_flash("my_group_name") an_array[3]; 106 | * 107 | * The section attribute is `.time_critical.` 108 | * 109 | * \param group a string suffix to use in the section name to distinguish groups that can be linker 110 | * garbage-collected independently 111 | */ 112 | #define __not_in_flash(group) __attribute__((section(".time_critical." group))) 113 | 114 | /*! \brief Section attribute macro for placement in the SRAM bank 4 (known as "scratch X") 115 | * \ingroup pico_platform 116 | * 117 | * Scratch X is commonly used for critical data and functions accessed only by one core (when only 118 | * one core is accessing the RAM bank, there is no opportunity for stalls) 119 | * 120 | * For example a `uint32_t` variable placed in "scratch X" 121 | * 122 | * uint32_t __scratch_x("my_group_name") foo = 23; 123 | * 124 | * The section attribute is `.scratch_x.` 125 | * 126 | * \param group a string suffix to use in the section name to distinguish groups that can be linker 127 | * garbage-collected independently 128 | */ 129 | #define __scratch_x(group) __attribute__((section(".scratch_x." group))) 130 | 131 | /*! \brief Section attribute macro for placement in the SRAM bank 5 (known as "scratch Y") 132 | * \ingroup pico_platform 133 | * 134 | * Scratch Y is commonly used for critical data and functions accessed only by one core (when only 135 | * one core is accessing the RAM bank, there is no opportunity for stalls) 136 | * 137 | * For example a `uint32_t` variable placed in "scratch Y" 138 | * 139 | * uint32_t __scratch_y("my_group_name") foo = 23; 140 | * 141 | * The section attribute is `.scratch_y.` 142 | * 143 | * \param group a string suffix to use in the section name to distinguish groups that can be linker 144 | * garbage-collected independently 145 | */ 146 | #define __scratch_y(group) __attribute__((section(".scratch_y." group))) 147 | 148 | /*! \brief Section attribute macro for data that is to be left uninitialized 149 | * \ingroup pico_platform 150 | * 151 | * Data marked this way will retain its value across a reset (normally uninitialized data - in the .bss 152 | * section) is initialized to zero during runtime initialization 153 | * 154 | * For example a `uint32_t` foo that will retain its value if the program is restarted by reset. 155 | * 156 | * uint32_t __uninitialized_ram("my_group_name") foo; 157 | * 158 | * The section attribute is `.uninitialized_ram.` 159 | * 160 | * \param group a string suffix to use in the section name to distinguish groups that can be linker 161 | * garbage-collected independently 162 | */ 163 | #define __uninitialized_ram(group) __attribute__((section(".uninitialized_ram." #group))) group 164 | 165 | /*! \brief Section attribute macro for placement in flash even in a COPY_TO_RAM binary 166 | * \ingroup pico_platform 167 | * 168 | * For example a `uint32_t` variable explicitly placed in flash (it will hard fault if you attempt to write it!) 169 | * 170 | * uint32_t __in_flash("my_group_name") foo = 23; 171 | * 172 | * The section attribute is `.flashdata.` 173 | * 174 | * \param group a string suffix to use in the section name to distinguish groups that can be linker 175 | * garbage-collected independently 176 | */ 177 | #define __in_flash(group) __attribute__((section(".flashdata" group))) 178 | 179 | /*! \brief Indicates a function should not be stored in flash 180 | * \ingroup pico_platform 181 | * 182 | * Decorates a function name, such that the function will execute from RAM (assuming it is not inlined 183 | * into a flash function by the compiler) 184 | * 185 | * For example a function called my_func taking an int parameter: 186 | * 187 | * void __not_in_flash_func(my_func)(int some_arg) { 188 | * 189 | * The function is placed in the `.time_critical.` linker section 190 | * 191 | * \see __no_inline_not_in_flash_func 192 | */ 193 | #define __not_in_flash_func(func_name) __not_in_flash(__STRING(func_name)) func_name 194 | 195 | /*! \brief Indicates a function is time/latency critical and should not run from flash 196 | * \ingroup pico_platform 197 | * 198 | * Decorates a function name, such that the function will execute from RAM (assuming it is not inlined 199 | * into a flash function by the compiler) to avoid possible flash latency. Currently this macro is identical 200 | * in implementation to `__not_in_flash_func`, however the semantics are distinct and a `__time_critical_func` 201 | * may in the future be treated more specially to reduce the overhead when calling such function from a flash 202 | * function. 203 | * 204 | * For example a function called my_func taking an int parameter: 205 | * 206 | * void __time_critical(my_func)(int some_arg) { 207 | * 208 | * The function is placed in the `.time_critical.` linker section 209 | * 210 | * \see __not_in_flash_func 211 | */ 212 | #define __time_critical_func(func_name) __not_in_flash_func(func_name) 213 | 214 | /*! \brief Indicate a function should not be stored in flash and should not be inlined 215 | * \ingroup pico_platform 216 | * 217 | * Decorates a function name, such that the function will execute from RAM, explicitly marking it as 218 | * noinline to prevent it being inlined into a flash function by the compiler 219 | * 220 | * For example a function called my_func taking an int parameter: 221 | * 222 | * void __no_inline_not_in_flash_func(my_func)(int some_arg) { 223 | * 224 | * The function is placed in the `.time_critical.` linker section 225 | */ 226 | #define __no_inline_not_in_flash_func(func_name) __noinline __not_in_flash_func(func_name) 227 | 228 | #define __packed_aligned __packed __aligned(4) 229 | 230 | /*! \brief Attribute to force inlining of a function regardless of optimization level 231 | * \ingroup pico_platform 232 | * 233 | * For example my_function here will always be inlined: 234 | * 235 | * int __force_inline my_function(int x) { 236 | * 237 | */ 238 | #if defined(__GNUC__) && (__GNUC__ <= 6 || (__GNUC__ == 7 && (__GNUC_MINOR__ < 3 || !defined(__cplusplus)))) 239 | #define __force_inline inline __always_inline 240 | #else 241 | #define __force_inline __always_inline 242 | #endif 243 | 244 | /*! \brief Macro to determine the number of elements in an array 245 | * \ingroup pico_platform 246 | */ 247 | #ifndef count_of 248 | #define count_of(a) (sizeof(a)/sizeof((a)[0])) 249 | #endif 250 | 251 | /*! \brief Macro to return the maximum of two comparable values 252 | * \ingroup pico_platform 253 | */ 254 | #ifndef MAX 255 | #define MAX(a, b) ((a)>(b)?(a):(b)) 256 | #endif 257 | 258 | /*! \brief Macro to return the minimum of two comparable values 259 | * \ingroup pico_platform 260 | */ 261 | #ifndef MIN 262 | #define MIN(a, b) ((b)>(a)?(a):(b)) 263 | #endif 264 | 265 | /*! \brief Execute a breakpoint instruction 266 | * \ingroup pico_platform 267 | */ 268 | static inline void __breakpoint(void) { 269 | __asm__("bkpt #0"); 270 | } 271 | 272 | /*! \brief Ensure that the compiler does not move memory access across this method call 273 | * \ingroup pico_platform 274 | * 275 | * For example in the following code: 276 | * 277 | * *some_memory_location = var_a; 278 | * __compiler_memory_barrier(); 279 | * uint32_t var_b = *some_other_memory_location 280 | * 281 | * The compiler will not move the load from `some_other_memory_location` above the memory barrier (which it otherwise 282 | * might - even above the memory store!) 283 | */ 284 | __force_inline static void __compiler_memory_barrier(void) { 285 | __asm__ volatile ("" : : : "memory"); 286 | } 287 | 288 | /*! \brief Macro for converting memory addresses to 32 bit addresses suitable for DMA 289 | * \ingroup pico_platform 290 | * 291 | * This is just a cast to `uintptr_t` on the RP2040, however you may want to use this when developing code 292 | * that also runs in "host" mode. If the host mode is 64 bit and you are embedding data pointers 293 | * in other data (e.g. DMA chaining), then there is a need in "host" mode to convert a 64 bit native 294 | * pointer to a 32 bit value for storage, which can be done using this macro. 295 | */ 296 | #define host_safe_hw_ptr(x) ((uintptr_t)(x)) 297 | #define native_safe_hw_ptr(x) host_safe_hw_ptr(x) 298 | 299 | 300 | /*! \brief Panics with the message "Unsupported" 301 | * \ingroup pico_platform 302 | * \see panic 303 | */ 304 | void __attribute__((noreturn)) panic_unsupported(void); 305 | 306 | /*! \brief Displays a panic message and halts execution 307 | * \ingroup pico_platform 308 | * 309 | * An attempt is made to output the message to all registered STDOUT drivers 310 | * after which this method executes a BKPT instruction. 311 | * 312 | * @param fmt format string (printf-like) 313 | * @param ... printf-like arguments 314 | */ 315 | void __attribute__((noreturn)) panic(const char *fmt, ...); 316 | 317 | // 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 318 | #ifndef PICO_NO_FPGA_CHECK 319 | #define PICO_NO_FPGA_CHECK 0 320 | #endif 321 | 322 | #if PICO_NO_FPGA_CHECK 323 | static inline bool running_on_fpga(void) {return false;} 324 | #else 325 | bool running_on_fpga(void); 326 | #endif 327 | 328 | /*! \brief Returns the RP2040 chip revision number 329 | * \ingroup pico_platform 330 | * @return the RP2040 chip revision number (1 for B0/B1, 2 for B2) 331 | */ 332 | uint8_t rp2040_chip_version(void); 333 | 334 | /*! \brief Returns the RP2040 rom version number 335 | * \ingroup pico_platform 336 | * @return the RP2040 rom version number (1 for RP2040-B0, 2 for RP2040-B1, 3 for RP2040-B2) 337 | */ 338 | static inline uint8_t rp2040_rom_version(void) { 339 | #pragma GCC diagnostic push 340 | #pragma GCC diagnostic ignored "-Warray-bounds" 341 | return *(uint8_t*)0x13; 342 | #pragma GCC diagnostic pop 343 | } 344 | 345 | /*! \brief No-op function for the body of tight loops 346 | * \ingroup pico_platform 347 | * 348 | * No-op function intended to be called by any tight hardware polling loop. Using this ubiquitously 349 | * makes it much easier to find tight loops, but also in the future \#ifdef-ed support for lockup 350 | * debugging might be added 351 | */ 352 | static __force_inline void tight_loop_contents(void) {} 353 | 354 | /*! \brief Multiply two integers using an assembly `MUL` instruction 355 | * \ingroup pico_platform 356 | * 357 | * This multiplies a by b using multiply instruction using the ARM mul instruction regardless of values (the compiler 358 | * might otherwise choose to perform shifts/adds), i.e. this is a 1 cycle operation. 359 | * 360 | * \param a the first operand 361 | * \param b the second operand 362 | * \return a * b 363 | */ 364 | __force_inline static int32_t __mul_instruction(int32_t a, int32_t b) { 365 | asm ("mul %0, %1" : "+l" (a) : "l" (b) : ); 366 | return a; 367 | } 368 | 369 | /*! \brief multiply two integer values using the fastest method possible 370 | * \ingroup pico_platform 371 | * 372 | * Efficiently multiplies value a by possibly constant value b. 373 | * 374 | * 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 375 | * which is often a slow combination of shifts and adds. If b is a power of 2 then a single shift is of course preferable 376 | * and will be used 377 | * 378 | * \param a the first operand 379 | * \param b the second operand 380 | * \return a * b 381 | */ 382 | #define __fast_mul(a, b) __builtin_choose_expr(__builtin_constant_p(b) && !__builtin_constant_p(a), \ 383 | (__builtin_popcount(b) >= 2 ? __mul_instruction(a,b) : (a)*(b)), \ 384 | (a)*(b)) 385 | 386 | /*! \brief Utility macro to assert two types are equivalent. 387 | * \ingroup pico_platform 388 | * 389 | * This macro can be useful in other macros along with `typeof` to assert that two parameters are of equivalent type 390 | * (or that a single parameter is of an expected type) 391 | */ 392 | #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)); 393 | 394 | /*! \brief Get the current exception level on this core 395 | * \ingroup pico_platform 396 | * 397 | * \return the exception number if the CPU is handling an exception, or 0 otherwise 398 | */ 399 | uint __get_current_exception(void); 400 | 401 | #define WRAPPER_FUNC(x) __wrap_ ## x 402 | #define REAL_FUNC(x) __real_ ## x 403 | 404 | #ifdef __cplusplus 405 | } 406 | #endif 407 | 408 | /*! \brief Helper method to busy-wait for at least the given number of cycles 409 | * \ingroup pico_platform 410 | * 411 | * This method is useful for introducing very short delays. 412 | * 413 | * This method busy-waits in a tight loop for the given number of system clock cycles. The total wait time is only accurate to within 2 cycles, 414 | * and this method uses a loop counter rather than a hardware timer, so the method will always take longer than expected if an 415 | * interrupt is handled on the calling core during the busy-wait; you can of course disable interrupts to prevent this. 416 | * 417 | * You can use \ref clock_get_hz(clk_sys) to determine the number of clock cycles per second if you want to convert an actual 418 | * time duration to a number of cycles. 419 | * 420 | * \param minimum_cycles the minimum number of system clock cycles to delay for 421 | */ 422 | static inline void busy_wait_at_least_cycles(uint32_t minimum_cycles) { 423 | __asm volatile ( 424 | ".syntax unified\n" 425 | "1: subs %0, #3\n" 426 | "bcs 1b\n" 427 | : "+r" (minimum_cycles) : : "memory" 428 | ); 429 | } 430 | 431 | /*! \brief Get the current core number 432 | * \ingroup pico_platform 433 | * 434 | * \return The core number the call was made from 435 | */ 436 | __force_inline static uint get_core_num(void) { 437 | return (*(uint32_t *) (SIO_BASE + SIO_CPUID_OFFSET)); 438 | } 439 | 440 | #else // __ASSEMBLER__ 441 | 442 | #define WRAPPER_FUNC_NAME(x) __wrap_##x 443 | #define SECTION_NAME(x) .text.##x 444 | #define RAM_SECTION_NAME(x) .time_critical.##x 445 | 446 | #endif // !__ASSEMBLER__ 447 | 448 | #endif 449 | -------------------------------------------------------------------------------- /src/include/pico/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | #ifndef _PICO_TYPES_H 8 | #define _PICO_TYPES_H 9 | 10 | #ifndef __ASSEMBLER__ 11 | 12 | #include "pico/assert.h" 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | typedef unsigned int uint; 19 | 20 | /*! \typedef absolute_time_t 21 | \brief An opaque 64 bit timestamp in microseconds 22 | 23 | The type is used instead of a raw uint64_t to prevent accidentally passing relative times or times in the wrong 24 | time units where an absolute time is required. It is equivalent to uint64_t in release builds. 25 | 26 | \see to_us_since_boot() 27 | \see update_us_since_boot() 28 | \ingroup timestamp 29 | */ 30 | #ifdef NDEBUG 31 | typedef uint64_t absolute_time_t; 32 | #else 33 | typedef struct { 34 | uint64_t _private_us_since_boot; 35 | } absolute_time_t; 36 | #endif 37 | 38 | /*! fn to_us_since_boot 39 | * \brief convert an absolute_time_t into a number of microseconds since boot. 40 | * \param t the absolute time to convert 41 | * \return a number of microseconds since boot, equivalent to t 42 | * \ingroup timestamp 43 | */ 44 | static inline uint64_t to_us_since_boot(absolute_time_t t) { 45 | #ifdef NDEBUG 46 | return t; 47 | #else 48 | return t._private_us_since_boot; 49 | #endif 50 | } 51 | 52 | /*! fn update_us_since_boot 53 | * \brief update an absolute_time_t value to represent a given number of microseconds since boot 54 | * \param t the absolute time value to update 55 | * \param us_since_boot the number of microseconds since boot to represent. Note this should be representable 56 | * as a signed 64 bit integer 57 | * \ingroup timestamp 58 | */ 59 | static inline void update_us_since_boot(absolute_time_t *t, uint64_t us_since_boot) { 60 | #ifdef NDEBUG 61 | *t = us_since_boot; 62 | #else 63 | assert(us_since_boot <= INT64_MAX); 64 | t->_private_us_since_boot = us_since_boot; 65 | #endif 66 | } 67 | 68 | #ifdef NDEBUG 69 | #define ABSOLUTE_TIME_INITIALIZED_VAR(name, value) name = value 70 | #else 71 | #define ABSOLUTE_TIME_INITIALIZED_VAR(name, value) name = {value} 72 | #endif 73 | 74 | /** \struct datetime_t 75 | * \ingroup util_datetime 76 | * \brief Structure containing date and time information 77 | * 78 | * When setting an RTC alarm, set a field to -1 tells 79 | * the RTC to not match on this field 80 | */ 81 | typedef struct { 82 | int16_t year; ///< 0..4095 83 | int8_t month; ///< 1..12, 1 is January 84 | int8_t day; ///< 1..28,29,30,31 depending on month 85 | int8_t dotw; ///< 0..6, 0 is Sunday 86 | int8_t hour; ///< 0..23 87 | int8_t min; ///< 0..59 88 | int8_t sec; ///< 0..59 89 | } datetime_t; 90 | 91 | #define bool_to_bit(x) ((uint)!!(x)) 92 | 93 | #endif 94 | #endif 95 | -------------------------------------------------------------------------------- /src/include/pico/version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | // --------------------------------------- 8 | // THIS FILE IS AUTOGENERATED; DO NOT EDIT 9 | // --------------------------------------- 10 | 11 | #ifndef _PICO_VERSION_H 12 | #define _PICO_VERSION_H 13 | 14 | #define PICO_SDK_VERSION_MAJOR 1 15 | #define PICO_SDK_VERSION_MINOR 4 16 | #define PICO_SDK_VERSION_REVISION 0 17 | #define PICO_SDK_VERSION_STRING "1.4.0" 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | 3 | /// The bootloader to use if you have a W25Q080 flash device 4 | pub static BOOT_LOADER_W25Q080: [u8; 256] = 5 | *include_bytes!(concat!(env!("OUT_DIR"), "/boot2_w25q080.padded.bin")); 6 | 7 | /// The bootloader to use if you want to copy code to RAM and then boot from RAM 8 | pub static BOOT_LOADER_RAM_MEMCPY: [u8; 256] = 9 | *include_bytes!(concat!(env!("OUT_DIR"), "/boot2_ram_memcpy.padded.bin")); 10 | 11 | /// The bootloader to use if you want to boot from an AT25SF128A flash device 12 | pub static BOOT_LOADER_AT25SF128A: [u8; 256] = 13 | *include_bytes!(concat!(env!("OUT_DIR"), "/boot2_at25sf128a.padded.bin")); 14 | 15 | /// The bootloader to use if you want to boot from an GD25Q64CS flash device 16 | pub static BOOT_LOADER_GD25Q64CS: [u8; 256] = 17 | *include_bytes!(concat!(env!("OUT_DIR"), "/boot2_gd25q64cs.padded.bin")); 18 | 19 | /// The bootloader to use if you want to boot from an W25X10CL flash device 20 | pub static BOOT_LOADER_W25X10CL: [u8; 256] = 21 | *include_bytes!(concat!(env!("OUT_DIR"), "/boot2_w25x10cl.padded.bin")); 22 | 23 | /// The bootloader to use if you want to boot from a generic flash device 24 | pub static BOOT_LOADER_GENERIC_03H: [u8; 256] = 25 | *include_bytes!(concat!(env!("OUT_DIR"), "/boot2_generic_03h.padded.bin")); 26 | 27 | /// The bootloader to use if you want to boot from an IS25LP080 flash device 28 | pub static BOOT_LOADER_IS25LP080: [u8; 256] = 29 | *include_bytes!(concat!(env!("OUT_DIR"), "/boot2_is25lp080.padded.bin")); 30 | --------------------------------------------------------------------------------