Skip to content

Commit 38d235c

Browse files
committed
Interrupt generation for riscv
1 parent 26983da commit 38d235c

File tree

3 files changed

+84
-12
lines changed

3 files changed

+84
-12
lines changed

src/generate/device.rs

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use anyhow::Result;
44
use proc_macro2::{Ident, Span, TokenStream};
55
use quote::quote;
66

7+
use crate::generate::Target;
78
use crate::ir::*;
89
use crate::util::{self, StringExt};
910

@@ -22,6 +23,7 @@ pub fn render(opts: &super::Options, ir: &IR, d: &Device, path: &str) -> Result<
2223
let span = Span::call_site();
2324

2425
let mut interrupts = TokenStream::new();
26+
let mut interrupt_match = TokenStream::new();
2527
let mut peripherals = TokenStream::new();
2628
let mut vectors = TokenStream::new();
2729
let mut names = vec![];
@@ -52,10 +54,14 @@ pub fn render(opts: &super::Options, ir: &IR, d: &Device, path: &str) -> Result<
5254
#[doc = #description]
5355
#name_uc = #value,
5456
});
57+
interrupt_match.extend(quote!(#value => Ok(Interrupt::#name_uc),));
58+
5559
vectors.extend(quote!(Vector { _handler: #name_uc },));
5660
names.push(name_uc);
5761
}
5862

63+
let max_interrupt_number = util::unsuffixed((pos - 1) as u64);
64+
5965
for p in sorted(&d.peripherals, |p| p.base_address) {
6066
let name = Ident::new(&p.name, span);
6167
let address = util::hex_usize(p.base_address);
@@ -90,14 +96,43 @@ pub fn render(opts: &super::Options, ir: &IR, d: &Device, path: &str) -> Result<
9096
pub enum Interrupt {
9197
#interrupts
9298
}
99+
));
93100

94-
unsafe impl cortex_m::interrupt::InterruptNumber for Interrupt {
95-
#[inline(always)]
96-
fn number(self) -> u16 {
97-
self as u16
98-
}
101+
match opts.target {
102+
Target::Riscv => {
103+
out.extend(quote!(
104+
unsafe impl riscv::InterruptNumber for Interrupt {
105+
/// Returns the number of the interrupt
106+
#[inline(always)]
107+
fn number(self) -> usize {
108+
self as usize
109+
}
110+
111+
fn from_number(number: usize) -> riscv::result::Result<Self> {
112+
match number {
113+
#interrupt_match
114+
_ => Err(riscv::result::Error::InvalidVariant(number)),
115+
}
116+
}
117+
118+
const MAX_INTERRUPT_NUMBER: usize = #max_interrupt_number;
119+
}
120+
));
99121
}
122+
Target::CortexM => {
123+
out.extend(quote!(
124+
unsafe impl cortex_m::interrupt::InterruptNumber for Interrupt {
125+
/// Returns the number of the interrupt
126+
#[inline(always)]
127+
fn number(self) -> u16 {
128+
self as u16
129+
}
130+
}
131+
));
132+
}
133+
}
100134

135+
out.extend(quote!(
101136
#[cfg(feature = "rt")]
102137
mod _vectors {
103138
extern "C" {
@@ -128,12 +163,23 @@ pub fn render(opts: &super::Options, ir: &IR, d: &Device, path: &str) -> Result<
128163
});
129164
}
130165

131-
out.extend(quote! {
132-
#[cfg(feature = "rt")]
133-
pub use cortex_m_rt::interrupt;
134-
#[cfg(feature = "rt")]
135-
pub use Interrupt as interrupt;
136-
});
166+
match opts.target {
167+
Target::CortexM => {
168+
out.extend(quote! {
169+
#[cfg(feature = "rt")]
170+
pub use cortex_m_rt::interrupt;
171+
#[cfg(feature = "rt")]
172+
pub use Interrupt as interrupt;
173+
});
174+
}
175+
Target::Riscv => {
176+
// TODO: Do we need to export something from riscv_rt here?
177+
out.extend(quote! {
178+
#[cfg(feature = "rt")]
179+
pub use Interrupt as interrupt;
180+
});
181+
}
182+
}
137183

138184
Ok(out)
139185
}

src/generate/mod.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,21 @@ pub enum CommonModule {
6666
External(TokenStream),
6767
}
6868

69+
#[derive(clap::ValueEnum, Debug, Default, Clone, Copy, PartialEq)]
70+
pub enum Target {
71+
#[default]
72+
CortexM,
73+
Riscv,
74+
}
75+
6976
/// Options for the code generator.
7077
///
7178
/// See the individual methods for the different options you can change.
7279
#[derive(Debug)]
7380
pub struct Options {
7481
common_module: CommonModule,
7582
defmt_feature: Option<String>,
83+
target: Target,
7684
}
7785

7886
impl Default for Options {
@@ -90,6 +98,7 @@ impl Options {
9098
Self {
9199
common_module: CommonModule::Builtin,
92100
defmt_feature: Some("defmt".into()),
101+
target: Target::default(),
93102
}
94103
}
95104

@@ -129,6 +138,12 @@ impl Options {
129138
pub fn defmt_feature(&self) -> Option<&str> {
130139
self.defmt_feature.as_deref()
131140
}
141+
142+
/// Select what kind fo target to generate code for.
143+
pub fn with_target(mut self, target: Target) -> Self {
144+
self.target = target;
145+
self
146+
}
132147
}
133148

134149
pub fn render(ir: &IR, opts: &Options) -> Result<TokenStream> {

src/main.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ struct Generate {
9393
/// Do not add defmt support to the generated code at all.
9494
#[clap(long)]
9595
no_defmt: bool,
96+
97+
#[clap(long)]
98+
target: Option<generate::Target>,
9699
}
97100

98101
/// Reformat a YAML
@@ -281,9 +284,17 @@ fn gen(args: Generate) -> Result<()> {
281284
true => None,
282285
false => Some(args.defmt_feature),
283286
};
287+
288+
let target = match args.target {
289+
None => generate::Target::CortexM,
290+
Some(target) => target,
291+
};
292+
284293
let generate_opts = generate::Options::default()
285294
.with_common_module(common_module)
286-
.with_defmt_feature(defmt_feature);
295+
.with_defmt_feature(defmt_feature)
296+
.with_target(target);
297+
287298
let items = generate::render(&ir, &generate_opts).unwrap();
288299
fs::write("lib.rs", items.to_string())?;
289300

0 commit comments

Comments
 (0)