Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial implementation of ram proc macro #6

Merged
merged 3 commits into from
Jan 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions esp-hal-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ paste = "1.0"
riscv = { version = "0.7", optional = true }
void = { version = "1.0", default-features = false }
xtensa-lx = { version = "0.4", optional = true }
procmacros = { path = "../esp-hal-procmacros", package = "esp-hal-procmacros" }
# IMPORTANT:
# Each supported device MUST have its PAC included below along with a
# corresponding feature.
Expand All @@ -26,7 +27,7 @@ esp32s2_pac = { package = "esp32s2", git = "https://github.com/jessebraham/esp32
esp32s3_pac = { package = "esp32s3", git = "https://github.com/jessebraham/esp32s3.git", branch = "develop", optional = true }

[features]
esp32 = ["esp32_pac", "esp32_pac/rt", "xtensa-lx/lx6"]
esp32 = ["esp32_pac", "esp32_pac/rt", "xtensa-lx/lx6", "procmacros/rtc_slow"]
esp32c3 = ["esp32c3_pac", "esp32c3_pac/rt", "riscv"]
esp32s2 = ["esp32s2_pac", "esp32s2_pac/rt", "xtensa-lx/lx6"] # FIXME
esp32s3 = ["esp32s3_pac", "esp32s3_pac/rt", "xtensa-lx/lx6"] # FIXME
esp32s2 = ["esp32s2_pac", "esp32s2_pac/rt", "xtensa-lx/lx6", "procmacros/rtc_slow"] # FIXME
esp32s3 = ["esp32s3_pac", "esp32s3_pac/rt", "xtensa-lx/lx6", "procmacros/rtc_slow"] # FIXME
3 changes: 3 additions & 0 deletions esp-hal-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,6 @@ pub use delay::Delay;
pub use gpio::*;
pub use serial::Serial;
pub use timer::Timer;

use procmacros;
pub use procmacros::ram;
24 changes: 24 additions & 0 deletions esp-hal-procmacros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[package]
name = "esp-hal-procmacros"
version = "0.1.0"
authors = [
"Jesse Braham <[email protected]>",
"Björn Quentin <[email protected]>",
]
edition = "2021"
description = "Procedural macros for ESP-HAL"
repository = "https://github.com/esp-rs/esp-hal"
license = "MIT OR Apache-2.0"

[lib]
proc-macro = true

[dependencies]
quote = "1.0"
proc-macro2 = "1.0"
darling = "0.10"
syn = {version = "1.0", features = ["extra-traits", "full"]}
proc-macro-error = "1.0.4"

[features]
rtc_slow = []
91 changes: 91 additions & 0 deletions esp-hal-procmacros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
use darling::FromMeta;
use proc_macro::TokenStream;
use proc_macro::{self, Span};
use proc_macro_error::{abort, proc_macro_error};
use quote::quote;
use syn::{parse_macro_input, AttributeArgs};

#[derive(Debug, Default, FromMeta)]
#[darling(default)]
struct RamArgs {
rtc_fast: bool,
rtc_slow: bool,
uninitialized: bool,
zeroed: bool,
}

/// This attribute allows placing statics and functions into ram.
///
/// Options that can be specified are rtc_slow or rtc_fast to use the
/// RTC slow or RTC fast ram instead of the normal SRAM.
///
/// The uninitialized option will skip initialization of the memory
/// (e.g. to persist it across resets or deep sleep mode for the RTC RAM)
///
/// Not all targets support RTC slow ram.

#[proc_macro_attribute]
#[proc_macro_error]
pub fn ram(args: TokenStream, input: TokenStream) -> TokenStream {
let attr_args = parse_macro_input!(args as AttributeArgs);

let RamArgs {
rtc_fast,
rtc_slow,
uninitialized,
zeroed,
} = match FromMeta::from_list(&attr_args) {
Ok(v) => v,
Err(e) => {
return e.write_errors().into();
}
};

let item: syn::Item = syn::parse(input).expect("failed to parse input");

#[cfg(not(feature = "rtc_slow"))]
if rtc_slow {
abort!(
Span::call_site(),
"rtc_slow is not available for this target"
);
}

let is_fn = matches!(item, syn::Item::Fn(_));
let section_name = match (is_fn, rtc_fast, rtc_slow, uninitialized, zeroed) {
(true, false, false, false, false) => Ok(".rwtext"),
(true, true, false, false, false) => Ok(".rtc_fast.text"),
(true, false, true, false, false) => Ok(".rtc_slow.text"),

(false, false, false, false, false) => Ok(".data"),

(false, true, false, false, false) => Ok(".rtc_fast.data"),
(false, true, false, true, false) => Ok(".rtc_fast.noinit"),
(false, true, false, false, true) => Ok(".rtc_fast.bss"),

(false, false, true, false, false) => Ok(".rtc_slow.data"),
(false, false, true, true, false) => Ok(".rtc_slow.noinit"),
(false, false, true, false, true) => Ok(".rtc_slow.bss"),

_ => Err(()),
};

let section = match (is_fn, section_name) {
(true, Ok(section_name)) => quote! {
#[link_section = #section_name]
#[inline(never)] // make certain function is not inlined
},
(false, Ok(section_name)) => quote! {
#[link_section = #section_name]
},
(_, Err(_)) => {
abort!(Span::call_site(), "Invalid combination of ram arguments");
}
};

let output = quote! {
#section
#item
};
output.into()
}
91 changes: 91 additions & 0 deletions esp32-hal/examples/ram.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#![no_std]
#![no_main]

use core::fmt::Write;

use esp32_hal::{
pac::{Peripherals, UART0},
prelude::*,
ram,
Serial,
Timer,
};
use nb::block;
use panic_halt as _;
use xtensa_lx_rt::entry;

#[ram(rtc_fast)]
static mut SOME_INITED_DATA: [u8; 2] = [0xaa, 0xbb];

#[ram(rtc_fast, uninitialized)]
static mut SOME_UNINITED_DATA: [u8; 2] = [0; 2];

#[ram(rtc_fast, zeroed)]
static mut SOME_ZEROED_DATA: [u8; 8] = [0; 8];

#[entry]
fn main() -> ! {
let peripherals = Peripherals::take().unwrap();

let mut timer0 = Timer::new(peripherals.TIMG0);
let mut serial0 = Serial::new(peripherals.UART0).unwrap();

// Disable watchdog timer
timer0.disable();

timer0.start(10_000_000u64);

writeln!(
serial0,
"IRAM function located at {:p}",
function_in_ram as *const ()
)
.unwrap();
unsafe {
writeln!(serial0, "SOME_INITED_DATA {:x?}", SOME_INITED_DATA).unwrap();
writeln!(serial0, "SOME_UNINITED_DATA {:x?}", SOME_UNINITED_DATA).unwrap();
writeln!(serial0, "SOME_ZEROED_DATA {:x?}", SOME_ZEROED_DATA).unwrap();

SOME_INITED_DATA[0] = 0xff;
SOME_ZEROED_DATA[0] = 0xff;

writeln!(serial0, "SOME_INITED_DATA {:x?}", SOME_INITED_DATA).unwrap();
writeln!(serial0, "SOME_UNINITED_DATA {:x?}", SOME_UNINITED_DATA).unwrap();
writeln!(serial0, "SOME_ZEROED_DATA {:x?}", SOME_ZEROED_DATA).unwrap();

if SOME_UNINITED_DATA[0] != 0 {
SOME_UNINITED_DATA[0] = 0;
SOME_UNINITED_DATA[1] = 0;
}

if SOME_UNINITED_DATA[1] == 0xff {
SOME_UNINITED_DATA[1] = 0;
}

writeln!(serial0, "Counter {}", SOME_UNINITED_DATA[1]).unwrap();
SOME_UNINITED_DATA[1] += 1;
}

writeln!(
serial0,
"RTC_FAST function located at {:p}",
function_in_rtc_ram as *const ()
)
.unwrap();
writeln!(serial0, "Result {}", function_in_rtc_ram()).unwrap();

loop {
function_in_ram(&mut serial0);
block!(timer0.wait()).unwrap();
}
}

#[ram]
fn function_in_ram(serial0: &mut Serial<UART0>) {
writeln!(serial0, "Hello world!").unwrap();
}

#[ram(rtc_fast)]
fn function_in_rtc_ram() -> u32 {
42
}
8 changes: 4 additions & 4 deletions esp32-hal/memory.x
Original file line number Diff line number Diff line change
Expand Up @@ -78,16 +78,16 @@ SECTIONS {

.rtc_fast.data :
{
_rtc_fast_data_start = ABSOLUTE(.);
. = ALIGN(4);
_rtc_fast_data_start = ABSOLUTE(.);
*(.rtc_fast.data .rtc_fast.data.*)
_rtc_fast_data_end = ABSOLUTE(.);
} > rtc_fast_dram_seg AT > RODATA

.rtc_fast.bss (NOLOAD) :
{
_rtc_fast_bss_start = ABSOLUTE(.);
. = ALIGN(4);
_rtc_fast_bss_start = ABSOLUTE(.);
*(.rtc_fast.bss .rtc_fast.bss.*)
_rtc_fast_bss_end = ABSOLUTE(.);
} > rtc_fast_dram_seg
Expand All @@ -106,16 +106,16 @@ SECTIONS {

.rtc_slow.data :
{
_rtc_slow_data_start = ABSOLUTE(.);
. = ALIGN(4);
_rtc_slow_data_start = ABSOLUTE(.);
*(.rtc_slow.data .rtc_slow.data.*)
_rtc_slow_data_end = ABSOLUTE(.);
} > rtc_slow_seg AT > RODATA

.rtc_slow.bss (NOLOAD) :
{
_rtc_slow_bss_start = ABSOLUTE(.);
. = ALIGN(4);
_rtc_slow_bss_start = ABSOLUTE(.);
*(.rtc_slow.bss .rtc_slow.bss.*)
_rtc_slow_bss_end = ABSOLUTE(.);
} > rtc_slow_seg
Expand Down
2 changes: 2 additions & 0 deletions esp32-hal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ pub use self::gpio::IO;

pub mod gpio;

pub use esp_hal_common::ram;

#[no_mangle]
extern "C" fn DefaultHandler(_level: u32, _interrupt: pac::Interrupt) {}

Expand Down
1 change: 0 additions & 1 deletion esp32c3-hal/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
[target.riscv32imc-unknown-none-elf]
rustflags = [
"-C", "link-arg=-Tesp32c3-link.x",
]

[build]
Expand Down
2 changes: 2 additions & 0 deletions esp32c3-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ embedded-hal = { version = "0.2", features = ["unproven"] }
nb = "1.0"
riscv = "0.7"
void = { version = "1.0", default-features = false }
r0 = "1.0.0"

[dependencies.esp-hal-common]
path = "../esp-hal-common"
Expand All @@ -48,3 +49,4 @@ panic-halt = "0.2"
[features]
default = ["rt"]
rt = ["riscv-rt"]
normalboot = []
44 changes: 44 additions & 0 deletions esp32c3-hal/bl-esp32c3-memory.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
MEMORY
{
/*
https://github.com/espressif/esptool/blob/master/esptool.py#L1919
MEMORY_MAP = [[0x00000000, 0x00010000, "PADDING"],
[0x3C000000, 0x3C800000, "DROM"],
[0x3FC80000, 0x3FCE0000, "DRAM"],
[0x3FC88000, 0x3FD00000, "BYTE_ACCESSIBLE"],
[0x3FF00000, 0x3FF20000, "DROM_MASK"],
[0x40000000, 0x40060000, "IROM_MASK"],
[0x42000000, 0x42800000, "IROM"],
[0x4037C000, 0x403E0000, "IRAM"],
[0x50000000, 0x50002000, "RTC_IRAM"],
[0x50000000, 0x50002000, "RTC_DRAM"],
[0x600FE000, 0x60100000, "MEM_INTERNAL2"]]
*/
/* 400K of on soc RAM, 16K reserved for cache */
ICACHE : ORIGIN = 0x4037C000, LENGTH = 0x4000
/* Instruction RAM */
IRAM : ORIGIN = 0x4037C000 + 0x4000, LENGTH = 400K - 0x4000
/* Data RAM */
DRAM : ORIGIN = 0x3FC80000, LENGTH = 0x50000


/* External flash */
/* Instruction ROM */
IROM : ORIGIN = 0x42000000 + 0x20, LENGTH = 0x400000 - 0x20
/* Data ROM */
DROM : ORIGIN = 0x3C000000, LENGTH = 0x400000

/* RTC fast memory (executable). Persists over deep sleep. */
RTC_FAST : ORIGIN = 0x50000000, LENGTH = 0x2000 /*- ESP_BOOTLOADER_RESERVE_RTC*/
}

REGION_ALIAS("REGION_TEXT", IROM);
REGION_ALIAS("REGION_RODATA", DROM);

REGION_ALIAS("REGION_DATA", DRAM);
REGION_ALIAS("REGION_BSS", DRAM);
REGION_ALIAS("REGION_HEAP", DRAM);
REGION_ALIAS("REGION_STACK", DRAM);

REGION_ALIAS("REGION_RWTEXT", IRAM);
REGION_ALIAS("REGION_RTC_FAST", RTC_FAST);
Loading