Skip to content

Commit e6a6d15

Browse files
bors[bot]sethp
andauthored
Merge #718
718: feat: configurable link section attribute for irqs r=burrbull a=sethp This change introduces a new config field that allows `svd2rust` to target which linker sections get assigned to the `__INTERRUPTS` static, with reasonable defaults. Previously on RISC-V, the choice was always left up to the compiler, and it seemed to always pick `.rodata`. Unfortunately, in my context, that meant placing the LUT in a memory range that had a lot of highly variable latency, which cost not just time but predictability in servicing interrupts. With this change in place, I'm able to target a particular section (e.g. `.data`, or `.trap.rodata`) for the placement of the static, which grants more granular control over the ultimate loaded memory address. For the full details about the problem, please see: esp-rs/esp-hal@e29f3d5 Co-authored-by: Seth Pellegrino <seth@codecopse.net>
2 parents d1ddb1b + 1c773fb commit e6a6d15

File tree

3 files changed

+39
-5
lines changed

3 files changed

+39
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
1111
- Optimize case change/sanitize
1212
- Fix dangling implicit derives
1313
- Fix escaping <> and & characters in doc attributes
14+
- Add `interrupt_link_section` config parameter for controlling the `#[link_section = "..."]` attribute of `__INTERRUPTS`
1415

1516
## [v0.28.0] - 2022-12-25
1617

src/generate/interrupt.rs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,14 @@ pub fn render(
118118
writeln!(device_x, "PROVIDE({name} = DefaultHandler);")?;
119119
}
120120

121+
let link_section_name = config
122+
.interrupt_link_section
123+
.as_deref()
124+
.unwrap_or(".vector_table.interrupts");
125+
let link_section_attr = quote! {
126+
#[link_section = #link_section_name]
127+
};
128+
121129
root.extend(quote! {
122130
#[cfg(feature = "rt")]
123131
extern "C" {
@@ -132,7 +140,7 @@ pub fn render(
132140

133141
#[cfg(feature = "rt")]
134142
#[doc(hidden)]
135-
#[link_section = ".vector_table.interrupts"]
143+
#link_section_attr
136144
#[no_mangle]
137145
pub static __INTERRUPTS: [Vector; #n] = [
138146
#elements
@@ -144,6 +152,14 @@ pub fn render(
144152
writeln!(device_x, "PROVIDE({name} = DefaultHandler);").unwrap();
145153
}
146154

155+
let link_section_name = config
156+
.interrupt_link_section
157+
.as_deref()
158+
.unwrap_or(".vector_table.interrupts");
159+
let link_section_attr = quote! {
160+
#[link_section = #link_section_name]
161+
};
162+
147163
root.extend(quote! {
148164
#[cfg(feature = "rt")]
149165
extern "msp430-interrupt" {
@@ -158,7 +174,7 @@ pub fn render(
158174

159175
#[cfg(feature = "rt")]
160176
#[doc(hidden)]
161-
#[link_section = ".vector_table.interrupts"]
177+
#link_section_attr
162178
#[no_mangle]
163179
#[used]
164180
pub static __INTERRUPTS:
@@ -172,6 +188,12 @@ pub fn render(
172188
writeln!(device_x, "PROVIDE({name} = DefaultHandler);")?;
173189
}
174190

191+
let link_section_attr = config.interrupt_link_section.as_ref().map(|section| {
192+
quote! {
193+
#[link_section = #section]
194+
}
195+
});
196+
175197
root.extend(quote! {
176198
#[cfg(feature = "rt")]
177199
extern "C" {
@@ -186,6 +208,7 @@ pub fn render(
186208

187209
#[cfg(feature = "rt")]
188210
#[doc(hidden)]
211+
#link_section_attr
189212
#[no_mangle]
190213
pub static __EXTERNAL_INTERRUPTS: [Vector; #n] = [
191214
#elements
@@ -197,6 +220,12 @@ pub fn render(
197220
writeln!(device_x, "PROVIDE({name} = DefaultHandler);")?;
198221
}
199222

223+
let link_section_attr = config.interrupt_link_section.as_ref().map(|section| {
224+
quote! {
225+
#[link_section = #section]
226+
}
227+
});
228+
200229
root.extend(quote! {
201230
#[cfg(feature = "rt")]
202231
extern "C" {
@@ -210,6 +239,7 @@ pub fn render(
210239
}
211240

212241
#[cfg(feature = "rt")]
242+
#link_section_attr
213243
#[doc(hidden)]
214244
pub static __INTERRUPTS: [Vector; #n] = [
215245
#elements

src/util.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ pub struct Config {
5959
pub source_type: SourceType,
6060
#[cfg_attr(feature = "serde", serde(default))]
6161
pub log_level: Option<String>,
62+
#[cfg_attr(feature = "serde", serde(default))]
63+
pub interrupt_link_section: Option<String>,
6264
}
6365

6466
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -120,6 +122,7 @@ impl Default for Config {
120122
input: None,
121123
source_type: SourceType::default(),
122124
log_level: None,
125+
interrupt_link_section: None,
123126
}
124127
}
125128
}
@@ -229,15 +232,15 @@ pub trait ToSanitizedCase {
229232
impl ToSanitizedCase for str {
230233
fn to_sanitized_pascal_case(&self) -> Cow<str> {
231234
let s = Case::Pascal.sanitize(self);
232-
if s.as_bytes().get(0).unwrap_or(&0).is_ascii_digit() {
235+
if s.as_bytes().first().unwrap_or(&0).is_ascii_digit() {
233236
Cow::from(format!("_{}", s))
234237
} else {
235238
s
236239
}
237240
}
238241
fn to_sanitized_constant_case(&self) -> Cow<str> {
239242
let s = Case::Constant.sanitize(self);
240-
if s.as_bytes().get(0).unwrap_or(&0).is_ascii_digit() {
243+
if s.as_bytes().first().unwrap_or(&0).is_ascii_digit() {
241244
Cow::from(format!("_{}", s))
242245
} else {
243246
s
@@ -247,7 +250,7 @@ impl ToSanitizedCase for str {
247250
const INTERNALS: [&str; 4] = ["set_bit", "clear_bit", "bit", "bits"];
248251

249252
let s = Case::Snake.sanitize(self);
250-
if s.as_bytes().get(0).unwrap_or(&0).is_ascii_digit() {
253+
if s.as_bytes().first().unwrap_or(&0).is_ascii_digit() {
251254
format!("_{}", s).into()
252255
} else if INTERNALS.contains(&s.as_ref()) {
253256
s + "_"

0 commit comments

Comments
 (0)