From e830a7a87005876861836b4eb6c27a2b62ff529b Mon Sep 17 00:00:00 2001 From: Anton Glukhov Date: Sun, 22 Dec 2024 22:52:33 +0100 Subject: [PATCH 1/6] add missing ReadFlash(optional) function Signed-off-by: Anton Glukhov --- Cargo.toml | 1 + src/lib.rs | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index cecf914..a3968b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,4 +14,5 @@ description = "A crate to write CMSIS-DAP flash algorithms for flashing embedded default = ["erase-chip", "panic-handler"] erase-chip = [] panic-handler = [] +read-flash = [] verify = [] diff --git a/src/lib.rs b/src/lib.rs index a414479..0e0e421 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -75,6 +75,15 @@ pub trait FlashAlgorithm: Sized + 'static { /// * `data` - The data to compare with. #[cfg(feature = "verify")] fn verify(&mut self, address: u32, size: u32, data: Option<&[u8]>) -> Result<(), ErrorCode>; + + /// Read flash. + /// + /// # Arguments + /// + /// * `address` - The start address of the flash to read. + /// * `data` - The data. + #[cfg(feature = "read-flash")] + fn read_flash(&mut self, address: u32, data: &mut [u8]) -> Result<(), ErrorCode>; } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -167,6 +176,7 @@ macro_rules! algorithm { } } $crate::erase_chip!($type); + $crate::read_flash!($type); $crate::verify!($type); #[allow(non_upper_case_globals)] @@ -270,6 +280,33 @@ macro_rules! erase_chip { }; } +#[doc(hidden)] +#[macro_export] +#[cfg(not(feature = "read-flash"))] +macro_rules! read_flash { + ($type:ty) => {}; +} +#[doc(hidden)] +#[macro_export] +#[cfg(feature = "read-flash")] +macro_rules! read_flash { + ($type:ty) => { + #[no_mangle] + #[link_section = ".entry"] + pub unsafe extern "C" fn ReadFlash(addr: u32, size: u32, data: *mut u8) -> u32 { + if !_IS_INIT { + return 1; + } + let this = &mut *_ALGO_INSTANCE.as_mut_ptr(); + let data_slice: &mut [u8] = unsafe { core::slice::from_raw_parts_mut(data, size as usize) }; + match <$type as $crate::FlashAlgorithm>::read_flash(this, addr, data_slice) { + Ok(()) => 0, + Err(e) => e.get(), + } + } + }; +} + #[doc(hidden)] #[macro_export] #[cfg(not(feature = "verify"))] From 947a6b72fb3f7e2e85c1232e846e536f4385911f Mon Sep 17 00:00:00 2001 From: Anton Glukhov Date: Mon, 23 Dec 2024 15:21:25 +0100 Subject: [PATCH 2/6] Bump version Signed-off-by: Anton Glukhov --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index a3968b2..ca22b36 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "flash-algorithm" -version = "0.5.0" +version = "0.6.0" edition = "2021" readme = "README.md" keywords = ["no-std", "embedded", "flashing"] From a915acb7e326eac9e0650ebfdf8f482f779bb5d0 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Wed, 7 May 2025 12:33:03 +0800 Subject: [PATCH 3/6] memory: support ti section naming TI names their sections with a `:`. For example, `.text:Fapi_issueAsyncCommand`. Add this as a recognized section prefix when placing symbols into the text section. Signed-off-by: Sean Cross --- memory.x | 2 ++ 1 file changed, 2 insertions(+) diff --git a/memory.x b/memory.x index fb7233b..472c1fe 100644 --- a/memory.x +++ b/memory.x @@ -16,6 +16,8 @@ SECTIONS { *(.text) *(.text.*) + /* TI naming convention */ + *(.text:*) *(.rodata) *(.rodata.*) From b0c8c1d5aa2a8aafaac4835f2b0fefd16cc1c92b Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Wed, 7 May 2025 12:36:22 +0800 Subject: [PATCH 4/6] lib: support big endian devices With big endian devices, the symbols are stored in big endian order. This is fine if the header is getting loaded onto the target, however the header is only for use with the host system, which is almost alays little endian. Ensure each field of the header is correctly swapped by adding `.to_le()` to each field. Additionally, ensure all fields are primitive integer types, as byte swapping is undefined for Rust types. Signed-off-by: Sean Cross --- src/lib.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 0e0e421..948c4da 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -185,35 +185,35 @@ macro_rules! algorithm { #[link_section = "DeviceData"] pub static FlashDevice: FlashDeviceDescription = FlashDeviceDescription { // The version is never read by probe-rs and can be fixed. - vers: 0x1, + vers: 0x1u16.to_le(), // The device name here can be customized but it really has no real use // appart from identifying the device the ELF is intended for which we have // in our YAML. dev_name: $crate::arrayify_string($device_name), // The specification does not specify the values that can go here, // but this value means internal flash device. - dev_type: $device_type, - dev_addr: $flash_address, - device_size: $flash_size, - page_size: $page_size, + dev_type: ($device_type as u16).to_le(), + dev_addr: ($flash_address as u32).to_le(), + device_size: ($flash_size as u32).to_le(), + page_size: ($page_size as u32).to_le(), _reserved: 0, // The empty state of a byte in flash. - empty: $empty_value, + empty: ($empty_value as u8).to_le(), // This value can be used to estimate the amount of time the flashing procedure takes worst case. - program_time_out: $program_time_out, + program_time_out: ($program_time_out as u32).to_le(), // This value can be used to estimate the amount of time the erasing procedure takes worst case. - erase_time_out: $erase_time_out, + erase_time_out: ($erase_time_out as u32).to_le(), flash_sectors: [ $( FlashSector { - size: $size, - address: $address, + size: ($size as u32).to_le(), + address: ($address as u32).to_le(), } ),+, // This marks the end of the flash sector list. FlashSector { - size: 0xffff_ffff, - address: 0xffff_ffff, + size: 0xffff_ffffu32.to_le(), + address: 0xffff_ffffu32.to_le(), } ], }; @@ -222,7 +222,7 @@ macro_rules! algorithm { pub struct FlashDeviceDescription { vers: u16, dev_name: [u8; 128], - dev_type: DeviceType, + dev_type: u16, dev_addr: u32, device_size: u32, page_size: u32, From eb629a3d78b070e74226164461140b6cec0f1478 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Sun, 18 May 2025 22:38:05 +0800 Subject: [PATCH 5/6] add blank_check command Add a command to perform a blank check on a device. This is an alternate method for devices that have ECC, where a blank device doesn't necessarily have a predetermined or homogenous bit pattern. Signed-off-by: Sean Cross --- Cargo.toml | 1 + src/lib.rs | 119 +++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 89 insertions(+), 31 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ca22b36..3436fb9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ description = "A crate to write CMSIS-DAP flash algorithms for flashing embedded [features] default = ["erase-chip", "panic-handler"] +blank-check = [] erase-chip = [] panic-handler = [] read-flash = [] diff --git a/src/lib.rs b/src/lib.rs index 948c4da..0394625 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,6 +30,7 @@ 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 const FUNCTION_BLANKCHECK: u32 = 4; pub type ErrorCode = core::num::NonZeroU32; @@ -84,6 +85,15 @@ pub trait FlashAlgorithm: Sized + 'static { /// * `data` - The data. #[cfg(feature = "read-flash")] fn read_flash(&mut self, address: u32, data: &mut [u8]) -> Result<(), ErrorCode>; + + /// Verify that flash is blank. + /// + /// # Arguments + /// + /// * `address` - The start address of the flash to check. + /// * `size` - The length of the area to check. + #[cfg(feature = "blank-check")] + fn blank_check(&mut self, address: u32, size: u32) -> Result<(), ErrorCode>; } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -91,6 +101,7 @@ pub enum Function { Erase = 1, Program = 2, Verify = 3, + BlankCheck = 4, } /// A macro to define a new flash algoritm. @@ -121,20 +132,23 @@ macro_rules! algorithm { #[no_mangle] #[link_section = ".entry"] pub unsafe extern "C" fn Init(addr: u32, clock: u32, function: u32) -> u32 { - if _IS_INIT { - UnInit(); + unsafe { + if _IS_INIT { + UnInit(); + } + _IS_INIT = true; } - _IS_INIT = true; let function = match function { 1 => $crate::Function::Erase, 2 => $crate::Function::Program, 3 => $crate::Function::Verify, + 4 => $crate::Function::BlankCheck, _ => core::panic!("This branch can only be reached if the host library sent an unknown function code.") }; match <$type as $crate::FlashAlgorithm>::new(addr, clock, function) { Ok(inst) => { - _ALGO_INSTANCE.as_mut_ptr().write(inst); - _IS_INIT = true; + unsafe { _ALGO_INSTANCE.as_mut_ptr().write(inst) }; + unsafe { _IS_INIT = true }; 0 } Err(e) => e.get(), @@ -143,20 +157,24 @@ macro_rules! algorithm { #[no_mangle] #[link_section = ".entry"] pub unsafe extern "C" fn UnInit() -> u32 { - if !_IS_INIT { - return 1; + 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 } #[no_mangle] #[link_section = ".entry"] pub unsafe extern "C" fn EraseSector(addr: u32) -> u32 { - if !_IS_INIT { - return 1; - } - let this = &mut *_ALGO_INSTANCE.as_mut_ptr(); + let this = unsafe { + if !unsafe { _IS_INIT } { + return 1; + } + &mut *_ALGO_INSTANCE.as_mut_ptr() + }; match <$type as $crate::FlashAlgorithm>::erase_sector(this, addr) { Ok(()) => 0, Err(e) => e.get(), @@ -165,11 +183,14 @@ macro_rules! algorithm { #[no_mangle] #[link_section = ".entry"] pub unsafe extern "C" fn ProgramPage(addr: u32, size: u32, data: *const u8) -> u32 { - if !_IS_INIT { - return 1; - } - let this = &mut *_ALGO_INSTANCE.as_mut_ptr(); - let data_slice: &[u8] = unsafe { core::slice::from_raw_parts(data, size as usize) }; + let (this, data_slice) = unsafe { + if !_IS_INIT { + return 1; + } + let this = &mut *_ALGO_INSTANCE.as_mut_ptr(); + let data_slice: &[u8] = core::slice::from_raw_parts(data, size as usize); + (this, data_slice) + }; match <$type as $crate::FlashAlgorithm>::program_page(this, addr, data_slice) { Ok(()) => 0, Err(e) => e.get(), @@ -178,6 +199,7 @@ macro_rules! algorithm { $crate::erase_chip!($type); $crate::read_flash!($type); $crate::verify!($type); + $crate::blank_check!($type); #[allow(non_upper_case_globals)] #[no_mangle] @@ -268,10 +290,12 @@ macro_rules! erase_chip { #[no_mangle] #[link_section = ".entry"] pub unsafe extern "C" fn EraseChip() -> u32 { - if !_IS_INIT { - return 1; - } - let this = &mut *_ALGO_INSTANCE.as_mut_ptr(); + let this = unsafe { + if !_IS_INIT { + return 1; + } + &mut *_ALGO_INSTANCE.as_mut_ptr() + }; match <$type as $crate::FlashAlgorithm>::erase_all(this) { Ok(()) => 0, Err(e) => e.get(), @@ -294,11 +318,14 @@ macro_rules! read_flash { #[no_mangle] #[link_section = ".entry"] pub unsafe extern "C" fn ReadFlash(addr: u32, size: u32, data: *mut u8) -> u32 { - if !_IS_INIT { - return 1; - } - let this = &mut *_ALGO_INSTANCE.as_mut_ptr(); - let data_slice: &mut [u8] = unsafe { core::slice::from_raw_parts_mut(data, size as usize) }; + let (this, data_slice) = unsafe { + if !_IS_INIT { + return 1; + } + let this = &mut *_ALGO_INSTANCE.as_mut_ptr(); + let data_slice: &mut [u8] = core::slice::from_raw_parts_mut(data, size as usize); + (this, data_slice) + }; match <$type as $crate::FlashAlgorithm>::read_flash(this, addr, data_slice) { Ok(()) => 0, Err(e) => e.get(), @@ -321,10 +348,12 @@ macro_rules! verify { #[no_mangle] #[link_section = ".entry"] pub unsafe extern "C" fn Verify(addr: u32, size: u32, data: *const u8) -> u32 { - if !_IS_INIT { - return 1; - } - let this = &mut *_ALGO_INSTANCE.as_mut_ptr(); + let this = unsafe { + if !_IS_INIT { + return 1; + } + &mut *_ALGO_INSTANCE.as_mut_ptr() + }; if data.is_null() { match <$type as $crate::FlashAlgorithm>::verify(this, addr, size, None) { @@ -343,6 +372,34 @@ macro_rules! verify { }; } +#[doc(hidden)] +#[macro_export] +#[cfg(not(feature = "blank-check"))] +macro_rules! blank_check { + ($type:ty) => {}; +} +#[doc(hidden)] +#[macro_export] +#[cfg(feature = "blank-check")] +macro_rules! blank_check { + ($type:ty) => { + #[no_mangle] + #[link_section = ".entry"] + pub unsafe extern "C" fn BlankCheck(addr: u32, size: u32) -> u32 { + let this = unsafe { + if !_IS_INIT { + return 1; + } + &mut *_ALGO_INSTANCE.as_mut_ptr() + }; + match <$type as $crate::FlashAlgorithm>::blank_check(this, addr, size) { + Ok(()) => 0, + Err(e) => e.get(), + } + } + }; +} + #[doc(hidden)] #[macro_export] macro_rules! count { From 32361889e1241498194eea4b6c3e1c8610fee956 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Mon, 19 May 2025 21:54:26 +0800 Subject: [PATCH 6/6] blank_check: add `pattern` argument based on cmsis-dap CMSIS-DAP has a `BlankCheck` function available that is very close to the `blank_check` function already. Add a `u8` argument that describes a `pattern` in order to bring them up to parity. Signed-off-by: Sean Cross --- src/lib.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 0394625..8e71b21 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -92,8 +92,9 @@ pub trait FlashAlgorithm: Sized + 'static { /// /// * `address` - The start address of the flash to check. /// * `size` - The length of the area to check. + /// * `pattern` - A pattern to be checked. The algorithm may choose ignore this value. #[cfg(feature = "blank-check")] - fn blank_check(&mut self, address: u32, size: u32) -> Result<(), ErrorCode>; + fn blank_check(&mut self, address: u32, size: u32, pattern: u8) -> Result<(), ErrorCode>; } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -385,14 +386,14 @@ macro_rules! blank_check { ($type:ty) => { #[no_mangle] #[link_section = ".entry"] - pub unsafe extern "C" fn BlankCheck(addr: u32, size: u32) -> u32 { + pub unsafe extern "C" fn BlankCheck(addr: u32, size: u32, pattern: u8) -> u32 { let this = unsafe { if !_IS_INIT { return 1; } &mut *_ALGO_INSTANCE.as_mut_ptr() }; - match <$type as $crate::FlashAlgorithm>::blank_check(this, addr, size) { + match <$type as $crate::FlashAlgorithm>::blank_check(this, addr, size, pattern) { Ok(()) => 0, Err(e) => e.get(), } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy