Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Now builds on stable. #18

Merged
merged 3 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .cargo/config
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
[unstable]
build-std = ["core"]
build-std-features = ["panic_immediate_abort"]

[target.'cfg(all(target_arch = "arm", target_os = "none"))']

rustflags = [
"-C", "link-arg=--nmagic",
"-C", "link-arg=-Tlink.x",

# Code-size optimizations.
"-Z", "trap-unreachable=no",
"-C", "inline-threshold=5",
"-C", "no-vectorize-loops",
"-C", "force-frame-pointers=no",
Expand Down
5 changes: 0 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,12 @@ env:

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- name: Install Dependencies
run: |
sudo apt update
rustup component add rust-src
cargo install cargo-binutils
rustup component add llvm-tools-preview
- name: Build
run: |
./build.sh
Expand Down
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,27 @@ It implements the CMSIS-Pack ABI, so it's compatible with any tools that use it,

## Dependencies

Run the following requirements:
Run the following to install the requirements:

```bash
cargo install cargo-binutils && rustup component add llvm-tools-preview rust-src
cargo install cargo-binutils
```
## Building

Building requires nightly Rust.
The `rust-toolchain` file will get you the targets and components you need.

## Building

Just run `build.sh`. It spits out the flash algo in the probe-rs YAML format:

flash-algo$ ./build.sh
```console
flash-algo$ ./build.sh
instructions: sLUUIACIGUoBRguI...wRwAgcEc=
pc_init: 0x00000000
pc_uninit: 0x0000007c
pc_program_page: 0x00000088
pc_erase_sector: 0x00000084
pc_erase_all: 0x00000080
```

## Hacking

Expand All @@ -30,7 +34,7 @@ the glue functions for a given struct implementing it. This is generic for all c

`main.rs` has the actual implementation for RP2040.

# License
## License

This thingy is licensed under either of

Expand Down
6 changes: 5 additions & 1 deletion rust-toolchain
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
nightly
[toolchain]
channel = "stable"
components = [ "llvm-tools" ]
profile = "minimal"
targets = ["thumbv6m-none-eabi"]
41 changes: 31 additions & 10 deletions src/algo.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#![macro_use]


use core::arch::asm;
use core::num::NonZeroU32;

Expand All @@ -12,10 +11,6 @@ fn panic(_info: &core::panic::PanicInfo) -> ! {
}
}

pub const FUNCTION_ERASE: u32 = 1;
pub const FUNCTION_PROGRAM: u32 = 2;
pub const FUNCTION_VERIFY: u32 = 3;

pub type ErrorCode = NonZeroU32;

pub trait FlashAlgo: Sized + 'static {
Expand All @@ -38,6 +33,12 @@ macro_rules! algo {
static mut _IS_INIT: bool = false;
static mut _ALGO_INSTANCE: MaybeUninit<$type> = MaybeUninit::uninit();

/// Initialise the Flash Algorithm
///
/// # Safety
///
/// Will disable execution from Flash. Ensure you are running from SRAM
/// and do not call any flash-based based functions.
#[no_mangle]
#[link_section = ".entry"]
pub unsafe extern "C" fn Init(addr: u32, clock: u32, function: u32) -> u32 {
Expand All @@ -53,16 +54,25 @@ macro_rules! algo {
Err(e) => e.get(),
}
}
/// Uninitialise the Flash Algorithm
#[no_mangle]
#[link_section = ".entry"]
pub unsafe extern "C" fn UnInit() -> u32 {
if !_IS_INIT {
return 1;
pub extern "C" fn UnInit() -> u32 {
unsafe {
if !_IS_INIT {
return 1;
}
_ALGO_INSTANCE.as_mut_ptr().drop_in_place();
_IS_INIT = false;
}
_ALGO_INSTANCE.as_mut_ptr().drop_in_place();
_IS_INIT = false;
0
}
/// Erase the flash chip.
///
/// # Safety
///
/// Will erase the flash chip. Ensure you really want to erase the
/// flash chip.
#[no_mangle]
#[link_section = ".entry"]
pub unsafe extern "C" fn EraseChip() -> u32 {
Expand All @@ -75,6 +85,11 @@ macro_rules! algo {
Err(e) => e.get(),
}
}
/// Erase the a sector on the flash chip.
///
/// # Safety
///
/// Will erase the given sector. Pass a valid sector address.
#[no_mangle]
#[link_section = ".entry"]
pub unsafe extern "C" fn EraseSector(addr: u32) -> u32 {
Expand All @@ -87,6 +102,12 @@ macro_rules! algo {
Err(e) => e.get(),
}
}
/// Write to a page on the flash chip.
///
/// # Safety
///
/// Will program the given page. Pass a valid page address, and a
/// valid pointer to at least `size` bytes of data.
#[no_mangle]
#[link_section = ".entry"]
pub unsafe extern "C" fn ProgramPage(addr: u32, size: u32, data: *const u8) -> u32 {
Expand Down
55 changes: 27 additions & 28 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,27 @@

mod algo;

use core::mem;
use core::mem::MaybeUninit;

use self::algo::*;

fn find_func<T>(tag: [u8; 2]) -> T {
let tag = u16::from_le_bytes(tag);

fn find_func<T>(tag: [u8; 2]) -> Option<T> {
let tag = u16::from_le_bytes(tag) as u32;
type RomTableLookupFn = unsafe extern "C" fn(table: *const u16, code: u32) -> usize;
/// This location in flash holds a 16-bit truncated pointer for the ROM lookup function
const ROM_TABLE_LOOKUP_PTR: *const u16 = 0x0000_0018 as _;
/// This location in flash holds a 16-bit truncated pointer for the ROM function table
/// (there's also a ROM data table which we don't need)
const FUNC_TABLE: *const u16 = 0x0000_0014 as _;
unsafe {
let mut entry = *(0x00000014 as *const u16) as *const u16;
loop {
let entry_tag = entry.read();
if entry_tag == 0 {
panic!("Func not found");
}
entry = entry.add(1);
let entry_addr = entry.read();
entry = entry.add(1);
if entry_tag == tag {
return mem::transmute_copy(&(entry_addr as u32));
}
let lookup_func = ROM_TABLE_LOOKUP_PTR.read() as usize;
let lookup_func: RomTableLookupFn = core::mem::transmute(lookup_func);
let table = FUNC_TABLE.read() as usize;
let result = lookup_func(table as *const u16, tag);
if result == 0 {
return None;
}
Some(core::mem::transmute_copy(&result))
}
}

Expand All @@ -38,15 +37,15 @@ struct ROMFuncs {
}

impl ROMFuncs {
fn load() -> Self {
ROMFuncs {
connect_internal_flash: find_func(*b"IF"),
flash_exit_xip: find_func(*b"EX"),
flash_range_erase: find_func(*b"RE"),
flash_range_program: find_func(*b"RP"),
flash_flush_cache: find_func(*b"FC"),
flash_enter_cmd_xip: find_func(*b"CX"),
}
fn load() -> Option<Self> {
Some(ROMFuncs {
connect_internal_flash: find_func(*b"IF")?,
flash_exit_xip: find_func(*b"EX")?,
flash_range_erase: find_func(*b"RE")?,
flash_range_program: find_func(*b"RP")?,
flash_flush_cache: find_func(*b"FC")?,
flash_enter_cmd_xip: find_func(*b"CX")?,
})
}
}

Expand All @@ -58,14 +57,14 @@ algo!(RP2040Algo);

const BLOCK_SIZE: u32 = 65536;
const SECTOR_SIZE: u32 = 4096;
const PAGE_SIZE: u32 = 256;
const BLOCK_ERASE_CMD: u8 = 0xd8;
const FLASH_BASE: u32 = 0x1000_0000;

impl FlashAlgo for RP2040Algo {
fn new(_address: u32, _clock: u32, _function: u32) -> Result<Self, ErrorCode> {
let funcs = ROMFuncs::load();

let Some(funcs) = ROMFuncs::load() else {
return Err(ErrorCode::new(1).unwrap());
};
(funcs.connect_internal_flash)();
(funcs.flash_exit_xip)();
Ok(Self { funcs })
Expand Down
Loading