From 0cd442df6ca0aff89348d1f7c7de8498f5d2bca5 Mon Sep 17 00:00:00 2001 From: agrc Date: Fri, 17 May 2024 19:37:12 +0200 Subject: [PATCH 01/12] feat: Add coprocessor access --- cortex-m/src/coprocessor.rs | 94 +++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 cortex-m/src/coprocessor.rs diff --git a/cortex-m/src/coprocessor.rs b/cortex-m/src/coprocessor.rs new file mode 100644 index 00000000..29f07bac --- /dev/null +++ b/cortex-m/src/coprocessor.rs @@ -0,0 +1,94 @@ +//! Coprocessor access assembly instructions. + + + +/// Internal function to create an inlined MCR instruction. +/// This instruction moves one Register to a Coprocessor Register. +/// For this function to compile to a single instruction, compile to opt-level > 2. +#[inline(always)] +pub(crate) fn mcr(value: u32) { + unsafe { + core::arch::asm!( + "MCR p{cp}, #{op1}, {0}, c{crn}, c{crm}, #{op2}", + in(reg) value, + cp = const CP, + op1 = const OP1, + crn = const CRN, + crm = const CRM, + op2 = const OP2, + options(nostack, nomem) + ) + } +} + + + +/// Internal function to create an inlined MRC instruction. +/// This instruction moves one Coprocessor Register to a Register. +/// For this function to compile to a single instruction, compile to opt-level > 2. +#[inline(always)] +pub(crate) fn mrc() -> u32 { + // Preallocate the value. + let a: u32; + + unsafe { + core::arch::asm!( + "MRC p{cp}, #{op1}, {0}, c{crn}, c{crm}, #{op2}", + out(reg) a, + cp = const CP, + op1 = const OP1, + crn = const CRN, + crm = const CRM, + op2 = const OP2, + options(nostack, nomem) + ) + } + + a +} + + + +/// Internal function to create an inlined MCRR instruction. +/// This instruction moves two Registers to Coprocessor Registers. +/// For this function to compile to a single instruction, compile to opt-level > 2. +#[inline(always)] +pub(crate) fn mcrr(a: u32, b: u32) { + unsafe { + core::arch::asm!( + "MCRR p{cp}, #{op1}, {0}, {1}, c{crm}", + in(reg) a, + in(reg) b, + cp = const CP, + op1 = const OP1, + crm = const CRM, + options(nostack, nomem) + ) + } +} + + + +/// Internal function to create an inlined MRRC instruction. +/// This instruction moves two Coprocessor Registers to Registers. +/// For this function to compile to a single instruction, compile to opt-level > 2. +#[inline(always)] +pub(crate) fn mrrc() -> (u32, u32) { + // Preallocate the values. + let a: u32; + let b: u32; + + unsafe { + core::arch::asm!( + "MRRC p{cp}, #{opc}, {0}, {1}, c{crm}", + out(reg) a, + out(reg) b, + cp = const CP, + opc = const OPC, + crm = const CRM, + options(nostack, nomem) + ) + } + + (a, b) +} From defd5cf5fd8284fb35d87402568440fdddc87948 Mon Sep 17 00:00:00 2001 From: agrc Date: Fri, 17 May 2024 19:37:26 +0200 Subject: [PATCH 02/12] feat: Add feature gate to coprocessor access --- cortex-m/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/cortex-m/Cargo.toml b/cortex-m/Cargo.toml index 27228d5f..b7668a83 100644 --- a/cortex-m/Cargo.toml +++ b/cortex-m/Cargo.toml @@ -34,6 +34,7 @@ cm7-r0p1 = ["cm7"] linker-plugin-lto = [] std = [] critical-section-single-core = ["critical-section/restore-state-bool"] +coprocessor = [] [package.metadata.docs.rs] targets = [ From f04b8b66e9376e442b637a13f6bdce9b937bb8d2 Mon Sep 17 00:00:00 2001 From: agrc Date: Fri, 17 May 2024 19:37:53 +0200 Subject: [PATCH 03/12] feat: Add coprocessor access to all cortex-m excep ARMV6 --- cortex-m/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cortex-m/src/lib.rs b/cortex-m/src/lib.rs index f74fcbf7..1aef82e0 100644 --- a/cortex-m/src/lib.rs +++ b/cortex-m/src/lib.rs @@ -59,6 +59,8 @@ mod macros; pub mod asm; #[cfg(armv8m)] pub mod cmse; +#[cfg(all(not(armv6m), feature = "coprocessor"))] +pub mod coprocessor; pub mod delay; pub mod interrupt; #[cfg(all(not(armv6m), not(armv8m_base)))] From 7b3bc97ce68b382ed886e4604df40a5ecc343dc4 Mon Sep 17 00:00:00 2001 From: agrc Date: Fri, 17 May 2024 21:03:32 +0200 Subject: [PATCH 04/12] fix: Change pub(crate) to pub --- cortex-m/src/coprocessor.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cortex-m/src/coprocessor.rs b/cortex-m/src/coprocessor.rs index 29f07bac..14f2c83b 100644 --- a/cortex-m/src/coprocessor.rs +++ b/cortex-m/src/coprocessor.rs @@ -6,7 +6,7 @@ /// This instruction moves one Register to a Coprocessor Register. /// For this function to compile to a single instruction, compile to opt-level > 2. #[inline(always)] -pub(crate) fn mcr(value: u32) { +pub fn mcr(value: u32) { unsafe { core::arch::asm!( "MCR p{cp}, #{op1}, {0}, c{crn}, c{crm}, #{op2}", @@ -27,7 +27,7 @@ pub(crate) fn mcr 2. #[inline(always)] -pub(crate) fn mrc() -> u32 { +pub fn mrc() -> u32 { // Preallocate the value. let a: u32; @@ -53,7 +53,7 @@ pub(crate) fn mrc 2. #[inline(always)] -pub(crate) fn mcrr(a: u32, b: u32) { +pub fn mcrr(a: u32, b: u32) { unsafe { core::arch::asm!( "MCRR p{cp}, #{op1}, {0}, {1}, c{crm}", @@ -73,7 +73,7 @@ pub(crate) fn mcrr(a: u32, b: u32 /// This instruction moves two Coprocessor Registers to Registers. /// For this function to compile to a single instruction, compile to opt-level > 2. #[inline(always)] -pub(crate) fn mrrc() -> (u32, u32) { +pub fn mrrc() -> (u32, u32) { // Preallocate the values. let a: u32; let b: u32; From df5e0b5dd192585c1d120fe6fb03c329411fb7e5 Mon Sep 17 00:00:00 2001 From: agrc Date: Fri, 17 May 2024 21:05:42 +0200 Subject: [PATCH 05/12] doc: Remove compilation gaurantee --- cortex-m/src/coprocessor.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cortex-m/src/coprocessor.rs b/cortex-m/src/coprocessor.rs index 14f2c83b..1f606d59 100644 --- a/cortex-m/src/coprocessor.rs +++ b/cortex-m/src/coprocessor.rs @@ -4,7 +4,6 @@ /// Internal function to create an inlined MCR instruction. /// This instruction moves one Register to a Coprocessor Register. -/// For this function to compile to a single instruction, compile to opt-level > 2. #[inline(always)] pub fn mcr(value: u32) { unsafe { @@ -25,7 +24,6 @@ pub fn mcr 2. #[inline(always)] pub fn mrc() -> u32 { // Preallocate the value. @@ -51,7 +49,6 @@ pub fn mrc 2. #[inline(always)] pub fn mcrr(a: u32, b: u32) { unsafe { @@ -71,7 +68,6 @@ pub fn mcrr(a: u32, b: u32) { /// Internal function to create an inlined MRRC instruction. /// This instruction moves two Coprocessor Registers to Registers. -/// For this function to compile to a single instruction, compile to opt-level > 2. #[inline(always)] pub fn mrrc() -> (u32, u32) { // Preallocate the values. From 3139b375969a085024154f83fda6887de661f1a0 Mon Sep 17 00:00:00 2001 From: agrc Date: Fri, 17 May 2024 21:07:02 +0200 Subject: [PATCH 06/12] fix: Remove feature gate --- cortex-m/Cargo.toml | 1 - cortex-m/src/lib.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/cortex-m/Cargo.toml b/cortex-m/Cargo.toml index b7668a83..27228d5f 100644 --- a/cortex-m/Cargo.toml +++ b/cortex-m/Cargo.toml @@ -34,7 +34,6 @@ cm7-r0p1 = ["cm7"] linker-plugin-lto = [] std = [] critical-section-single-core = ["critical-section/restore-state-bool"] -coprocessor = [] [package.metadata.docs.rs] targets = [ diff --git a/cortex-m/src/lib.rs b/cortex-m/src/lib.rs index 1aef82e0..70ef61dd 100644 --- a/cortex-m/src/lib.rs +++ b/cortex-m/src/lib.rs @@ -59,7 +59,7 @@ mod macros; pub mod asm; #[cfg(armv8m)] pub mod cmse; -#[cfg(all(not(armv6m), feature = "coprocessor"))] +#[cfg(not(armv6m))] pub mod coprocessor; pub mod delay; pub mod interrupt; From 3de32502d28b54e8a07049333c0af3e8ee103dcb Mon Sep 17 00:00:00 2001 From: Andres Date: Tue, 3 Feb 2026 11:33:29 +0100 Subject: [PATCH 07/12] feat: Update documentation, formatting --- cortex-m/src/coprocessor.rs | 49 ++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/cortex-m/src/coprocessor.rs b/cortex-m/src/coprocessor.rs index 1f606d59..b8b23423 100644 --- a/cortex-m/src/coprocessor.rs +++ b/cortex-m/src/coprocessor.rs @@ -1,11 +1,19 @@ //! Coprocessor access assembly instructions. - - -/// Internal function to create an inlined MCR instruction. /// This instruction moves one Register to a Coprocessor Register. +/// This function generates inline assembly and needs the instruction configuration +/// during compilation time (i.e. as `const`). +/// The values of the constants required by this function should be defined by +/// the coprocessor's reference manual. +/// - CP: The coprocessor's index. +/// - OP1: First optional operation for the coprocessor. +/// - CRN: Coprocessor register N. +/// - CRM: Coprocessor register M. +/// - OP2: Second optional operation for the coprocessor. #[inline(always)] -pub fn mcr(value: u32) { +pub fn mcr( + value: u32, +) { unsafe { core::arch::asm!( "MCR p{cp}, #{op1}, {0}, c{crn}, c{crm}, #{op2}", @@ -20,13 +28,18 @@ pub fn mcr() -> u32 { - // Preallocate the value. let a: u32; unsafe { @@ -45,10 +58,14 @@ pub fn mrc(a: u32, b: u32) { unsafe { @@ -64,10 +81,14 @@ pub fn mcrr(a: u32, b: u32) { } } - - -/// Internal function to create an inlined MRRC instruction. /// This instruction moves two Coprocessor Registers to Registers. +/// This function generates inline assembly and needs the instruction configuration +/// during compilation time (i.e. as `const`). +/// The values of the constants required by this function should be defined by +/// the coprocessor's reference manual. +/// - CP: The coprocessor's index. +/// - OP1: First optional operation for the coprocessor. +/// - CRM: Coprocessor register M. #[inline(always)] pub fn mrrc() -> (u32, u32) { // Preallocate the values. From 41b3882f1a756a5fc565e6f7d2ada10a82dc9208 Mon Sep 17 00:00:00 2001 From: Andres Date: Thu, 5 Feb 2026 13:21:11 +0100 Subject: [PATCH 08/12] fix: Unsafe at function level, refmt --- cortex-m/src/coprocessor.rs | 93 +++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 50 deletions(-) diff --git a/cortex-m/src/coprocessor.rs b/cortex-m/src/coprocessor.rs index b8b23423..2e286f9f 100644 --- a/cortex-m/src/coprocessor.rs +++ b/cortex-m/src/coprocessor.rs @@ -11,21 +11,19 @@ /// - CRM: Coprocessor register M. /// - OP2: Second optional operation for the coprocessor. #[inline(always)] -pub fn mcr( +pub unsafe fn mcr( value: u32, ) { - unsafe { - core::arch::asm!( - "MCR p{cp}, #{op1}, {0}, c{crn}, c{crm}, #{op2}", - in(reg) value, - cp = const CP, - op1 = const OP1, - crn = const CRN, - crm = const CRM, - op2 = const OP2, - options(nostack, nomem) - ) - } + core::arch::asm!( + "MCR p{cp}, #{op1}, {0}, c{crn}, c{crm}, #{op2}", + in(reg) value, + cp = const CP, + op1 = const OP1, + crn = const CRN, + crm = const CRM, + op2 = const OP2, + options(nostack, nomem) + ); } /// This instruction moves one Coprocessor Register to a Register. @@ -39,21 +37,20 @@ pub fn mcr() -> u32 { +pub unsafe fn mrc( +) -> u32 { let a: u32; - unsafe { - core::arch::asm!( - "MRC p{cp}, #{op1}, {0}, c{crn}, c{crm}, #{op2}", - out(reg) a, - cp = const CP, - op1 = const OP1, - crn = const CRN, - crm = const CRM, - op2 = const OP2, - options(nostack, nomem) - ) - } + core::arch::asm!( + "MRC p{cp}, #{op1}, {0}, c{crn}, c{crm}, #{op2}", + out(reg) a, + cp = const CP, + op1 = const OP1, + crn = const CRN, + crm = const CRM, + op2 = const OP2, + options(nostack, nomem) + ); a } @@ -67,18 +64,16 @@ pub fn mrc(a: u32, b: u32) { - unsafe { - core::arch::asm!( - "MCRR p{cp}, #{op1}, {0}, {1}, c{crm}", - in(reg) a, - in(reg) b, - cp = const CP, - op1 = const OP1, - crm = const CRM, - options(nostack, nomem) - ) - } +pub unsafe fn mcrr(a: u32, b: u32) { + core::arch::asm!( + "MCRR p{cp}, #{op1}, {0}, {1}, c{crm}", + in(reg) a, + in(reg) b, + cp = const CP, + op1 = const OP1, + crm = const CRM, + options(nostack, nomem) + ); } /// This instruction moves two Coprocessor Registers to Registers. @@ -90,22 +85,20 @@ pub fn mcrr(a: u32, b: u32) { /// - OP1: First optional operation for the coprocessor. /// - CRM: Coprocessor register M. #[inline(always)] -pub fn mrrc() -> (u32, u32) { +pub unsafe fn mrrc() -> (u32, u32) { // Preallocate the values. let a: u32; let b: u32; - unsafe { - core::arch::asm!( - "MRRC p{cp}, #{opc}, {0}, {1}, c{crm}", - out(reg) a, - out(reg) b, - cp = const CP, - opc = const OPC, - crm = const CRM, - options(nostack, nomem) - ) - } + core::arch::asm!( + "MRRC p{cp}, #{opc}, {0}, {1}, c{crm}", + out(reg) a, + out(reg) b, + cp = const CP, + opc = const OPC, + crm = const CRM, + options(nostack, nomem) + ); (a, b) } From 2f6baef4154f1f134b22406c0c7d0235b138ff27 Mon Sep 17 00:00:00 2001 From: Andres Date: Thu, 26 Mar 2026 23:21:28 +0100 Subject: [PATCH 09/12] fix: Format, clippy --- cortex-m/src/coprocessor.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cortex-m/src/coprocessor.rs b/cortex-m/src/coprocessor.rs index 2e286f9f..a34527f7 100644 --- a/cortex-m/src/coprocessor.rs +++ b/cortex-m/src/coprocessor.rs @@ -14,7 +14,7 @@ pub unsafe fn mcr( value: u32, ) { - core::arch::asm!( + unsafe { core::arch::asm!( "MCR p{cp}, #{op1}, {0}, c{crn}, c{crm}, #{op2}", in(reg) value, cp = const CP, @@ -23,7 +23,7 @@ pub unsafe fn mcr( -) -> u32 { +pub unsafe fn mrc() +-> u32 { let a: u32; - core::arch::asm!( + unsafe { core::arch::asm!( "MRC p{cp}, #{op1}, {0}, c{crn}, c{crm}, #{op2}", out(reg) a, cp = const CP, @@ -50,7 +50,7 @@ pub unsafe fn mrc(a: u32, b: u32) { - core::arch::asm!( + unsafe { core::arch::asm!( "MCRR p{cp}, #{op1}, {0}, {1}, c{crm}", in(reg) a, in(reg) b, @@ -73,7 +73,7 @@ pub unsafe fn mcrr(a: u32, b: u32 op1 = const OP1, crm = const CRM, options(nostack, nomem) - ); + )}; } /// This instruction moves two Coprocessor Registers to Registers. @@ -90,7 +90,7 @@ pub unsafe fn mrrc() -> (u32, u32 let a: u32; let b: u32; - core::arch::asm!( + unsafe { core::arch::asm!( "MRRC p{cp}, #{opc}, {0}, {1}, c{crm}", out(reg) a, out(reg) b, @@ -98,7 +98,7 @@ pub unsafe fn mrrc() -> (u32, u32 opc = const OPC, crm = const CRM, options(nostack, nomem) - ); + )}; (a, b) } From e3ebba51bd840b2a89b0dd7006db0d668bf27ba1 Mon Sep 17 00:00:00 2001 From: Andres Date: Thu, 26 Mar 2026 23:23:01 +0100 Subject: [PATCH 10/12] fix: Rerun cargo fmt after clippy, I really need to make a hook for this --- cortex-m/src/coprocessor.rs | 84 ++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 38 deletions(-) diff --git a/cortex-m/src/coprocessor.rs b/cortex-m/src/coprocessor.rs index a34527f7..11d77e53 100644 --- a/cortex-m/src/coprocessor.rs +++ b/cortex-m/src/coprocessor.rs @@ -14,16 +14,18 @@ pub unsafe fn mcr( value: u32, ) { - unsafe { core::arch::asm!( - "MCR p{cp}, #{op1}, {0}, c{crn}, c{crm}, #{op2}", - in(reg) value, - cp = const CP, - op1 = const OP1, - crn = const CRN, - crm = const CRM, - op2 = const OP2, - options(nostack, nomem) - )}; + unsafe { + core::arch::asm!( + "MCR p{cp}, #{op1}, {0}, c{crn}, c{crm}, #{op2}", + in(reg) value, + cp = const CP, + op1 = const OP1, + crn = const CRN, + crm = const CRM, + op2 = const OP2, + options(nostack, nomem) + ) + }; } /// This instruction moves one Coprocessor Register to a Register. @@ -41,16 +43,18 @@ pub unsafe fn mrc u32 { let a: u32; - unsafe { core::arch::asm!( - "MRC p{cp}, #{op1}, {0}, c{crn}, c{crm}, #{op2}", - out(reg) a, - cp = const CP, - op1 = const OP1, - crn = const CRN, - crm = const CRM, - op2 = const OP2, - options(nostack, nomem) - )}; + unsafe { + core::arch::asm!( + "MRC p{cp}, #{op1}, {0}, c{crn}, c{crm}, #{op2}", + out(reg) a, + cp = const CP, + op1 = const OP1, + crn = const CRN, + crm = const CRM, + op2 = const OP2, + options(nostack, nomem) + ) + }; a } @@ -65,15 +69,17 @@ pub unsafe fn mrc(a: u32, b: u32) { - unsafe { core::arch::asm!( - "MCRR p{cp}, #{op1}, {0}, {1}, c{crm}", - in(reg) a, - in(reg) b, - cp = const CP, - op1 = const OP1, - crm = const CRM, - options(nostack, nomem) - )}; + unsafe { + core::arch::asm!( + "MCRR p{cp}, #{op1}, {0}, {1}, c{crm}", + in(reg) a, + in(reg) b, + cp = const CP, + op1 = const OP1, + crm = const CRM, + options(nostack, nomem) + ) + }; } /// This instruction moves two Coprocessor Registers to Registers. @@ -90,15 +96,17 @@ pub unsafe fn mrrc() -> (u32, u32 let a: u32; let b: u32; - unsafe { core::arch::asm!( - "MRRC p{cp}, #{opc}, {0}, {1}, c{crm}", - out(reg) a, - out(reg) b, - cp = const CP, - opc = const OPC, - crm = const CRM, - options(nostack, nomem) - )}; + unsafe { + core::arch::asm!( + "MRRC p{cp}, #{opc}, {0}, {1}, c{crm}", + out(reg) a, + out(reg) b, + cp = const CP, + opc = const OPC, + crm = const CRM, + options(nostack, nomem) + ) + }; (a, b) } From 8bd9668bec009d2e3054de94eb7995440f4a99b9 Mon Sep 17 00:00:00 2001 From: Andres Date: Fri, 27 Mar 2026 13:29:21 +0100 Subject: [PATCH 11/12] fix: Add asm_cfg to all coprocessor instructions --- cortex-m/src/coprocessor.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cortex-m/src/coprocessor.rs b/cortex-m/src/coprocessor.rs index 11d77e53..c6c4c0d2 100644 --- a/cortex-m/src/coprocessor.rs +++ b/cortex-m/src/coprocessor.rs @@ -1,5 +1,7 @@ //! Coprocessor access assembly instructions. +use cortex_m_macros::asm_cfg; + /// This instruction moves one Register to a Coprocessor Register. /// This function generates inline assembly and needs the instruction configuration /// during compilation time (i.e. as `const`). @@ -10,6 +12,7 @@ /// - CRN: Coprocessor register N. /// - CRM: Coprocessor register M. /// - OP2: Second optional operation for the coprocessor. +#[asm_cfg(any(armv7m, armv8m))] #[inline(always)] pub unsafe fn mcr( value: u32, @@ -38,6 +41,7 @@ pub unsafe fn mcr() -> u32 { @@ -67,6 +71,7 @@ pub unsafe fn mrc(a: u32, b: u32) { unsafe { @@ -90,6 +95,7 @@ pub unsafe fn mcrr(a: u32, b: u32 /// - CP: The coprocessor's index. /// - OP1: First optional operation for the coprocessor. /// - CRM: Coprocessor register M. +#[asm_cfg(any(armv7m, armv8m))] #[inline(always)] pub unsafe fn mrrc() -> (u32, u32) { // Preallocate the values. From ef09ed2dd610d0fb84aad6fb7c9d496b4a8551d2 Mon Sep 17 00:00:00 2001 From: Andres Date: Fri, 27 Mar 2026 17:47:43 +0100 Subject: [PATCH 12/12] fmt: Set inline before asm_cfg --- cortex-m/src/coprocessor.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cortex-m/src/coprocessor.rs b/cortex-m/src/coprocessor.rs index c6c4c0d2..7238781e 100644 --- a/cortex-m/src/coprocessor.rs +++ b/cortex-m/src/coprocessor.rs @@ -12,8 +12,8 @@ use cortex_m_macros::asm_cfg; /// - CRN: Coprocessor register N. /// - CRM: Coprocessor register M. /// - OP2: Second optional operation for the coprocessor. -#[asm_cfg(any(armv7m, armv8m))] #[inline(always)] +#[asm_cfg(any(armv7m, armv8m))] pub unsafe fn mcr( value: u32, ) { @@ -41,8 +41,8 @@ pub unsafe fn mcr() -> u32 { let a: u32; @@ -71,8 +71,8 @@ pub unsafe fn mrc(a: u32, b: u32) { unsafe { core::arch::asm!( @@ -95,8 +95,8 @@ pub unsafe fn mcrr(a: u32, b: u32 /// - CP: The coprocessor's index. /// - OP1: First optional operation for the coprocessor. /// - CRM: Coprocessor register M. -#[asm_cfg(any(armv7m, armv8m))] #[inline(always)] +#[asm_cfg(any(armv7m, armv8m))] pub unsafe fn mrrc() -> (u32, u32) { // Preallocate the values. let a: u32;