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

Adding support for the ESP32C3 #733

Merged
merged 2 commits into from
Sep 27, 2023
Merged

Adding support for the ESP32C3 #733

merged 2 commits into from
Sep 27, 2023

Conversation

onsdagens
Copy link
Contributor

As discussed, this adds support for the ESP32C3.

It relies on forks of both the runtime and the hal for interrupt preemption, my next goal is possibly getting those upstreamed as well.

@onsdagens
Copy link
Contributor Author

As a sidenote, this should generalize well to the other ESP RISC-V MCUs but i don't have any to play around with.

@onsdagens
Copy link
Contributor Author

onsdagens commented Apr 15, 2023

@romancardenas has suggested splitting up export like here https://github.com/greenlsi/rtic/tree/master/rtic%2Fsrc%2Fexport for better modularity. I think for now it might be overkill, but depending on how many unique backends we expect to support, it could be a good idea.

@onsdagens onsdagens marked this pull request as ready for review April 15, 2023 16:32
@romancardenas
Copy link
Contributor

romancardenas commented Apr 15, 2023

If you don't like all those submodule folders, we could also leave it as export::riscv_common, export::riscv_esp32c3... And forget about things like export::riscv_backend::esp32c3.

In any case, I do believe that we should move the feature-gated definitions of functions like pend from rtic::export.rs to a backend-specific module for easier maintenance and better separation of concerns.

@onsdagens
Copy link
Contributor Author

I've been able to move things around a bit, now this only relies on changes to the hal, the rt remains untouched. I've also fixed some weird errors regarding feature selection, which i'm not sure how they made it in there to begin with.

@romancardenas
Copy link
Contributor

@steewbsd and I have re-structured the export module of our fork so it has less folders. Have a look, maybe you prefer it that way.

Copy link
Contributor

@romancardenas romancardenas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice piece of work! I see we more or less reached the same point. Let's try to clarify the structure stuff and then I will adapt our fork to include yours :D

@@ -323,6 +323,14 @@ pub fn interrupt_exit(_app: &App, _analysis: &CodegenAnalysis) -> Vec<TokenStrea
vec![]
}

pub fn async_entry(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this new hook is required by ESP32C3 for un-pending the dispatchers' interrupt, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep

@@ -20,7 +20,7 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 {
quote!(#dispatcher();)
} else {
quote!(loop {
rtic::export::nop()
continue;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious: why do you avoid the nop function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like it achieves the same end result (this is just an empty idle generated when you don't give one), without the need for exporting nop. I guess there is no specific reason, just the solution i came up with.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is effectively equivalent, then I'm in

@@ -6,11 +6,20 @@ use syn::{Ident, PatType};

const RTIC_INTERNAL: &str = "__rtic_internal";

//this is named something else in the esp32c3 pac
#[cfg(not(feature = "riscv-esp32c3"))]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check this. We had a similar issue and tackled this way. The idea is to avoid feature gates out of codegen::bindings.

rtic/Cargo.toml Outdated
esp32c3 = {version = "0.13.0", optional = true}
#next goal is getting the neccessary changes to the hal upstreamed
#esp32c3-hal = { git = "https://github.com/onsdagens/esp-hal", branch="scaled_back", optional = true}
esp32c3-hal = { git = "https://github.com/onsdagens/esp-hal", branch="interrupt_preemption", optional = true}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you depend both on the PAC and the HAL. Could you explain to me why? Maybe we need this as well for the SLIC implementation

#[cfg(feature = "riscv-esp32c3")]
pub use riscv_esp32c3::*;

///I think all of these "pends" and "unpends" should be moved to /export/<device>.rs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same. We propose this structure.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, i'll align this with your proposal

@@ -0,0 +1,105 @@
use esp32c3::INTERRUPT_CORE0; //priority threshold control
pub use esp32c3::{Interrupt, Peripherals};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you set your core peripherals as the PAC's peripherals. So this is basically what we have done. Thus, the core peripherals and device peripherals will be exactly the same. This is why I wonder if the core peripherals are needed for RISC-V targets, as there is no such thing. Maybe we can make it optional and include it only for Cortex. However, I think @korken89 would rather not modify struct fields depending on the backend.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that API is set in stone - if there is a good reason to deviate I see no reason to strictly follow the old one :)

romancardenas
romancardenas previously approved these changes May 3, 2023
Copy link
Contributor

@romancardenas romancardenas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

As a side note, it would be worth discussing removing from the API rtic::export::peripherals and rtic::export::nop at the next meeting. The prior looks too Cortex-M-driven, and the latter can just be continue.

@onsdagens
Copy link
Contributor Author

Some breaking changes if you've been using this fork. I've moved it to use the new upcoming direct-vectoring feature in the esp-riscv-rt. This changes the syntax of the interrupt handlers slightly, and takes advantage of the interrupt vector table, improving task dispatch latency dramatically.

If you're using the esp32c3-hal, you must enable the interrupt-preemption and direct-vectoring features, and make sure you're using the latest version of the crate from the esp-hal repo. Similarly, if you're only running esp-riscv-rt, you must enable those same features.

For some minimal examples check out https://github.com/perlindgren/esp32c3-test/tree/rtic_sw_tasks

@onsdagens
Copy link
Contributor Author

onsdagens commented Sep 26, 2023

Rebased on upstream now with Per adding a drop-in replacement of atomics in rtic-common and rtic-sync with portable-atomic to move us away from the imac target and the shaky emulation it requires. There is also a new, less PoC, example in https://github.com/perlindgren/esp32c3-test/tree/rtic_sw_tasks using the UsbSerialJtag peripheral to communicate with the host, and a more advanced example here https://github.com/perlindgren/esp32c3-rtic-tau , with more things to come.

@perlindgren
Copy link
Collaborator

Manually testing for toxic effects of portable_atomic.

extern "C" fn test_atomics(offset: u8) -> AtomicU8 {
    (84 + offset).into()
}
42000174 <test_atomics>:
42000174: 13 05 45 05  	addi	a0, a0, 84
42000178: 13 75 f5 0f  	andi	a0, a0, 255
4200017c: 82 80            	ret

It's not a complete test of course, but it looks as expected (compiled in release mode, without overflow checks).

There is no reason to believe any other natively supported atomic data structures should cause problems.

korken89
korken89 previously approved these changes Sep 27, 2023
Copy link
Collaborator

@korken89 korken89 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you for the effort!

@onsdagens onsdagens reopened this Sep 27, 2023
@korken89 korken89 added this pull request to the merge queue Sep 27, 2023
Merged via the queue into rtic-rs:master with commit 2b2208e Sep 27, 2023
88 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants