imxrt-rs / imxrt-hal

Rust for NXP i.MX RT
Apache License 2.0
133 stars 33 forks source link

Implementing the imx rt1170 #118

Open tyalie opened 2 years ago

tyalie commented 2 years ago

this is less of a feature request but a question on how this should be realised according to the organisation of the imxrt-rs project. For context I'm trying to write a HAL layer for the imx rt1170, which is a package containing a Cortex M4 and M7 that share the same memory, hardware acceleration modules and GPIO pins. See the product page provided by NXP which includes a nice overview diagram.

I've seen that others before tried to implement such a dual core MCU in Rust but they haven't used this HAL afaik, e.g. https://github.com/japaric/lpcxpresso54114

I first wanted to evaluate how this should be implemented, e.g. in it's own project referencing to the imxrt-hal, just using the embedded-hal project, merged into here, ...? But also how one would go further on and what I should look into to adapt this project to multi core processors

teburd commented 2 years ago

There are many ways to do this, and I don't think a HAL necessarily needs to know exactly all the details of how.

What the HAL could do in this case however is provide all the peripheral IP drivers and present each core a set of them in a sensible way. Some of the IP as you mentioned is shared (GPIO, memory, probably some others?) and in those cases the safest thing to do is allocate those IPs to a specific core and leave it there. The next safest thing is to create a synchronization mechanism, perhaps as simple as an atomic that you can cas on to "take", such that only one core can take ownership of the shared peripheral.

For these systems there's a few approaches you could take to then actually program them. Two entirely separate programs that get loaded and then communicate in some safe manner (maybe a pre arranged memory region as a shared memory channel) or use a SMP/AMP aware RTOS that can schedule tasks for you.

In all cases above, I think the HAL is almost entirely there to provide a toolbox of drivers, not necessarily put a hard line on how you should write your software. That's you and your design's business.

Now, that's not to say the HAL shouldn't support all the tools there. If there are are IPI's to interrupt the there core, that should be supported. If there are specific IPs tied to specific cores, that should be supported. If there are shared IPs, that too should be supported in a safe way. Perhaps with atomics and a well known placement of the Peripherals struct in memory so the atomics could work.

tyalie commented 2 years ago

Oh yeah. I hadn't yet though about the complexity of sharing the objects and I'll need to dive deeper into the chip to tell you how exactly it is realised in the existing C SDK. Because it really really does sound like trouble, but also the CPUs themselves have their own dedicated RAMs too (L1, L2, ...).

What I wanted to know more is how you have organised your project and wish to proceed. I've looked a bit into https://github.com/imxrt-rs/imxrt-hal/issues/56 and found the discussion quite interesting. But I have yet to find another MCU implementation using this HAL that isn't imx rt1060. So to break it down, should I create my own project, import the HAL and write the implementation, or should I fork this project and write the imx rt1170 implementation in a directory?

I think there will be quite a few interesting questions yet to discuss. You've mentioned one, but there's also the issue of compiling for multiple CPU targets, building the HEX correctly, how to write code for both CPU cores (NXP solves it with ifdef flags in their code), ... But also the extended feature sets like CANFD, hardware acceleration for 2d graphics, ... that might be interesting to look at in the future

teburd commented 2 years ago

Create a imxrt1170-hal directory (and crate) within the imxrt-hal workspace on a fork, and go ham. We can always improve things later if we need to.

If you end up needing to share code (almost 100% certain you will), look at how its been done so far. Sometimes in a separate crate (imxrt-dma, imxrt-ccm, etc) if its a large enough driver. But really you could probably create like a imxrt-flexspi or imxrt-lpspi and so on type crate in the workspace if you need to for now for sharing some of that stuff.

See how nrf does it https://github.com/nrf-rs/nrf-hal for where I was wanting to go with this

tyalie commented 2 years ago

Thank you so much. ^^

If I have further questions is there any chat room or something available, instead of using an issue for that?

teburd commented 2 years ago

I setup a matrix chat awhile ago, happy to hang out there and answer questions. @mciantyre is arguably the primary author at this point and I've never gotten him on a chat :-)

https://matrix.to/#/#imxrt-rs:matrix.org

mciantyre commented 2 years ago

Agreed with all @teburd's points. A few other quick thoughts:

I'll admit, I've been slow to join the chat 😛 I'm heads-down studying for a midterm. I'll jump in the chat sometime next week. Thanks for setting that up.

tyalie commented 2 years ago

Yes. Building the RAL first sounds like a good idea.

But regarding the boot-up I don't think that the teensy4-rs crate is enough. The multicore processor has a special boot-up sequence in order to get both cores running. I'm honestly not even sure here how one would build the rust code that supports multiple cores for example.

mciantyre commented 2 years ago

From my brief study of this chip, the CM7 typically boots first. Then the CM7 boots the CM4. I'm getting the latter information from this application note.

If we're using the 1170EVK for bringup, the CM7 can boot from flash over FlexSPI, similar to the Teensy 4 and other EVKs. If we want to ignore the multicore aspect while we do peripheral porting and bring-up, we might be able to make progress with just the CM7.

mciantyre commented 2 years ago

I was able to boot the CM7 on the 1170EVK, and blink its LED, all from stable Rust (some (inline) assembly required). The prototype is over here.

See the repo docs for up-to-date info. As of this writing, the TL;DR is

git clone https://github.com/mciantyre/imxrt-rt && cd imxrt-rt
cargo build --features=board/imxrt1170evk-cm7 --examples --target=thumbv7em-none-eabihf
pyocd load --format=elf --target=mimxrt1170_cm7 target/thumbv7em-none-eabihf/debug/examples/blink-blocking
[ Reset board using pyOCD, press / release SW3, etc. ]

It relies on exploratory RAL support for the 1170 core(s). I'm taking notes about RAL support in imxrt-rs/imxrt-ral#26.

tyalie commented 2 years ago

Oh wow. I'm very impressed. In the past months we have been trying to get these chips implemented and running in our environment using the NXP SDK and the more I worked with these chips the more daring the task of implementing Rust support felt.

You've my gratitude for going the first steps. This is amazing

mciantyre commented 1 year ago

121 adds basic 1170 support to imxrt-hal. It lets us share common driver code -- timers, low-power peripherals, DMA, USB -- across 10xx and 11xx chips. Of the 21 included hardware examples, 19 of them should build and run on an 1170EVK's Cortex-M7.

Supporting the 1170 is still a daring task, and this latest effort was focused on peripheral porting. To quickly summarize notable 11xx HAL shortcomings:

  1. Nothing attempted on the Cortex-M4.
  2. No power management for either core.
  3. Basically no clock management for either core.