aboutsummaryrefslogtreecommitdiff
path: root/macros/src
diff options
context:
space:
mode:
authorGravatar David Watson <david@neonquill.com> 2022-07-03 12:24:11 -0400
committerGravatar Henrik Tjäder <henrik@tjaders.com> 2022-07-27 21:04:24 +0200
commit368ab1d4fb780386f3162c7a84502e301af7f3b0 (patch)
tree04f56317f1e5a2f98c07275415107b5a9f40ce56 /macros/src
parent981fa1fb30a70ec2416778b3e8daa491108deb41 (diff)
downloadrtic-368ab1d4fb780386f3162c7a84502e301af7f3b0.tar.gz
rtic-368ab1d4fb780386f3162c7a84502e301af7f3b0.tar.zst
rtic-368ab1d4fb780386f3162c7a84502e301af7f3b0.zip
Remove use of basepri register on thumbv8m.base
The basepri register appears to be aviable on thumbv8m.main but not thumbv8m.base. At the very least, attempting to compile against a Cortex-M23 based Microchip ATSAML10E16A generates an error: ``` error[E0432]: unresolved import `cortex_m::register::basepri` --> /Users/dwatson/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-rtic-1.1.3/src/export.rs:25:5 | 25 | use cortex_m::register::basepri; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `basepri` in `register` ``` This is an attempt to account for the fact that thumbv8m.base (M23) MCUs don't have the BASEPRI register but have more than 32 interrupts. This moves away from the architecture specific config flags and switches to a more functional flag. Make the mask size depend on the max interrupt id Rather than assuming a fixed interrupt count of 32 this code uses an array of u32 bitmasks to calculate the priority mask. The size of this array is calculated at compile time based on the size of the largest interrupt id being used in the target code. For thumbv6m this should be equivalent to the previous version that used a single u32 mask. For thumbv8m.base it will be larger depending on the interrupts used. Don't write 0s to the ISER and ICER registers Writing 0s to these registers is a no-op. Since these masks should be calculated at compile time, this conditional should result in writes being optimized out of the code. Prevent panic on non-arm targets Panicking on unknown targets was breaking things like the doc build on linux. This change should only panic when building on unknown arm targets.
Diffstat (limited to 'macros/src')
-rw-r--r--macros/src/codegen/assertions.rs11
-rw-r--r--macros/src/codegen/shared_resources.rs19
-rw-r--r--macros/src/codegen/util.rs5
3 files changed, 26 insertions, 9 deletions
diff --git a/macros/src/codegen/assertions.rs b/macros/src/codegen/assertions.rs
index f6a098b5..66e54095 100644
--- a/macros/src/codegen/assertions.rs
+++ b/macros/src/codegen/assertions.rs
@@ -22,15 +22,16 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
}
let device = &extra.device;
- let arm_v6_checks: Vec<_> = app
+ let chunks_name = util::priority_mask_chunks_ident();
+ let no_basepri_checks: Vec<_> = app
.hardware_tasks
.iter()
.filter_map(|(_, task)| {
if !util::is_exception(&task.args.binds) {
let interrupt_name = &task.args.binds;
Some(quote!(
- if (#device::Interrupt::#interrupt_name as u32) > 31 {
- ::core::panic!("An interrupt above value 31 is used while in armv6");
+ if (#device::Interrupt::#interrupt_name as usize) >= (#chunks_name * 32) {
+ ::core::panic!("An interrupt out of range is used while in armv6 or armv8m.base");
}
))
} else {
@@ -41,8 +42,8 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
let const_check = quote! {
const _CONST_CHECK: () = {
- if rtic::export::is_armv6() {
- #(#arm_v6_checks)*
+ if !rtic::export::have_basepri() {
+ #(#no_basepri_checks)*
} else {
// TODO: Add armv7 checks here
}
diff --git a/macros/src/codegen/shared_resources.rs b/macros/src/codegen/shared_resources.rs
index 47f8faf0..53bb4823 100644
--- a/macros/src/codegen/shared_resources.rs
+++ b/macros/src/codegen/shared_resources.rs
@@ -112,6 +112,8 @@ pub fn codegen(
let device = &extra.device;
let mut uses_exceptions_with_resources = false;
+ let mut mask_ids = Vec::new();
+
for (&priority, name) in interrupt_ids.chain(app.hardware_tasks.values().flat_map(|task| {
if !util::is_exception(&task.args.binds) {
Some((&task.args.priority, &task.args.binds))
@@ -141,12 +143,13 @@ pub fn codegen(
})) {
let v = prio_to_masks.entry(priority - 1).or_insert(Vec::new());
v.push(quote!(#device::Interrupt::#name as u32));
+ mask_ids.push(quote!(#device::Interrupt::#name as u32));
}
- // Call rtic::export::create_mask([u32; N]), where the array is the list of shifts
+ // Call rtic::export::create_mask([Mask; N]), where the array is the list of shifts
let mut mask_arr = Vec::new();
- // NOTE: 0..3 assumes max 4 priority levels according to M0 spec
+ // NOTE: 0..3 assumes max 4 priority levels according to M0, M23 spec
for i in 0..3 {
let v = if let Some(v) = prio_to_masks.get(&i) {
v.clone()
@@ -159,18 +162,26 @@ pub fn codegen(
));
}
+ // Generate a constant for the number of chunks needed by Mask.
+ let chunks_name = util::priority_mask_chunks_ident();
+ mod_app.push(quote!(
+ #[doc(hidden)]
+ #[allow(non_upper_case_globals)]
+ const #chunks_name: usize = rtic::export::compute_mask_chunks([#(#mask_ids),*]);
+ ));
+
let masks_name = util::priority_masks_ident();
mod_app.push(quote!(
#[doc(hidden)]
#[allow(non_upper_case_globals)]
- const #masks_name: [u32; 3] = [#(#mask_arr),*];
+ const #masks_name: [rtic::export::Mask<#chunks_name>; 3] = [#(#mask_arr),*];
));
if uses_exceptions_with_resources {
mod_app.push(quote!(
#[doc(hidden)]
#[allow(non_upper_case_globals)]
- const __rtic_internal_V6_ERROR: () = rtic::export::v6_panic();
+ const __rtic_internal_V6_ERROR: () = rtic::export::no_basepri_panic();
));
}
diff --git a/macros/src/codegen/util.rs b/macros/src/codegen/util.rs
index 0f3dca7c..0a3edc20 100644
--- a/macros/src/codegen/util.rs
+++ b/macros/src/codegen/util.rs
@@ -253,6 +253,11 @@ pub fn static_shared_resource_ident(name: &Ident) -> Ident {
mark_internal_name(&format!("shared_resource_{}", name))
}
+/// Generates an Ident for the number of 32 bit chunks used for Mask storage.
+pub fn priority_mask_chunks_ident() -> Ident {
+ mark_internal_name("MASK_CHUNKS")
+}
+
pub fn priority_masks_ident() -> Ident {
mark_internal_name("MASKS")
}