Skip to content

Commit 01e041c

Browse files
committed
Interrupt generation for riscv
1 parent 828b7b8 commit 01e041c

File tree

3 files changed

+86
-12
lines changed

3 files changed

+86
-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);
@@ -86,14 +92,43 @@ pub fn render(opts: &super::Options, ir: &IR, d: &Device, path: &str) -> Result<
8692
pub enum Interrupt {
8793
#interrupts
8894
}
95+
));
8996

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

131+
out.extend(quote!(
97132
#[cfg(feature = "rt")]
98133
mod _vectors {
99134
unsafe extern "C" {
@@ -124,12 +159,23 @@ pub fn render(opts: &super::Options, ir: &IR, d: &Device, path: &str) -> Result<
124159
});
125160
}
126161

127-
out.extend(quote! {
128-
#[cfg(feature = "rt")]
129-
pub use cortex_m_rt::interrupt;
130-
#[cfg(feature = "rt")]
131-
pub use Interrupt as interrupt;
132-
});
162+
match opts.target {
163+
Target::CortexM => {
164+
out.extend(quote! {
165+
#[cfg(feature = "rt")]
166+
pub use cortex_m_rt::interrupt;
167+
#[cfg(feature = "rt")]
168+
pub use Interrupt as interrupt;
169+
});
170+
}
171+
Target::Riscv => {
172+
// TODO: Do we need to export something from riscv_rt here?
173+
out.extend(quote! {
174+
#[cfg(feature = "rt")]
175+
pub use Interrupt as interrupt;
176+
});
177+
}
178+
}
133179

134180
Ok(out)
135181
}

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: DefmtOption,
83+
target: Target,
7684
}
7785

7886
/// Option for generating code for `defmt` support.
@@ -101,6 +109,7 @@ impl Options {
101109
Self {
102110
common_module: CommonModule::Builtin,
103111
defmt: DefmtOption::Feature("defmt".to_owned()),
112+
target: Target::default(),
104113
}
105114
}
106115

@@ -136,6 +145,12 @@ impl Options {
136145
pub fn defmt(&self) -> &DefmtOption {
137146
&self.defmt
138147
}
148+
149+
/// Select what kind fo target to generate code for.
150+
pub fn with_target(mut self, target: Target) -> Self {
151+
self.target = target;
152+
self
153+
}
139154
}
140155

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

src/main.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ struct GenShared {
148148
/// Add defmt support to the generated code unconditionally.
149149
#[clap(long)]
150150
yes_defmt: bool,
151+
152+
/// Specify the target architecture for the generated code.
153+
#[clap(long)]
154+
target: Option<generate::Target>,
151155
}
152156

153157
fn main() -> Result<()> {
@@ -283,6 +287,7 @@ fn gen(args: Generate) -> Result<()> {
283287
}
284288

285289
let generate_opts = get_generate_opts(args.gen_shared)?;
290+
286291
let items = generate::render(&ir, &generate_opts).unwrap();
287292
fs::write("lib.rs", items.to_string())?;
288293

@@ -488,8 +493,16 @@ fn get_generate_opts(args: GenShared) -> Result<generate::Options> {
488493
(true, true) => bail!("--no-defmt and --yes-defmt are mutually exclusive"),
489494
};
490495

496+
let target = match args.target {
497+
None => generate::Target::CortexM,
498+
Some(target) => target,
499+
};
500+
501+
491502
let opts = generate::Options::default()
492503
.with_common_module(common_module)
493-
.with_defmt(defmt);
504+
.with_defmt(defmt)
505+
.with_target(target);
506+
494507
Ok(opts)
495508
}

0 commit comments

Comments
 (0)