modm-io / modm

modm: a C++23 library generator for AVR and ARM Cortex-M devices
https://modm.io
Mozilla Public License 2.0
749 stars 132 forks source link

Support for HiFive1 board #278

Closed nesos closed 3 years ago

nesos commented 5 years ago

Hey everyone, I'm thinking about implementing platform support for the HiFive1 board. The board is a somewhat Arduino compatible board with a FE310 RISC-V microcontroller at its heart. You can find some information about the hardware here: https://www.sifive.com/boards/hifive1 I think it would be nice to support RISC-V and this board would be a nice platform to demonstrate this.

My question now is if you guys are interested in supporting RISC-V in general and this board in particular. I'd offer my help to implement the platform drivers.

Greeting, Ben

salkinium commented 5 years ago

In short, yes we are, there are tentative plans by @rleh to add the gd32vf103cbt6 target with the Sipeed Longan Nano Board since that has similar if not identical peripherals to STM32.

However, regardless of the board we first need to implement RISC-V support, ie. modm:platform:risc-v module, probably very similar in features to the modm:platform:cortex-m module and at the very least add a minimal device file for your target, so that the identifier is known to modm.

There's a lot more detail in the ATSAM port issue here: https://github.com/modm-io/modm/issues/189#issuecomment-485135716 And PR: https://github.com/modm-io/modm/pull/194

I suggest you hack something very minimal into place using whatever method you can get to work, and then we iterate over that, since this is a lot of specialized work and hard to describe for me what to do in detail.

salkinium commented 5 years ago

Ah, you're from the DLR and using OUTPOST, so you already know lbuild pretty well. I would ignore modm-devices for now, since we're only adding one board/target, and there aren't a lot of RISC-V microcontrollers available yet, so the scaling isn't that much of an issue. Our custom device files are placed here.

nesos commented 5 years ago

I'm not quite sure if there should be a modm:platform:risc-v platform. The only thing that this chip shares with other RISC-V chips the instruction set. All of the core components like interrupt handling is specific to this core. So for this specific chip it would make more sense to have like a "e31" platform, pretty much as we have a Cortex platform instead of an ARM platform. What do you think?

salkinium commented 5 years ago

I think my blissful ignorance of how RISC-V works is endless 🤦‍♂️

The users depend on the modm:platform:core, for STM32 that contains only the STM32 specific things since everything else is delegated to the common Cortex-M module. But You don't have to partition it that way, you can put it all in that one module and we'll split it up on demand later.

Don't worry too much about naming things, we'll figure it out on the way.

rleh commented 5 years ago

I think there are currently at least three RISC-V targets of interest:

Since only compilers and ISA seem to be common to the targets, I agree with @nesos opinion that an E31 variant of modm:platform:core module seems suitable. Maybe in the future with more commercial RISV-C microcontrollers available some similarities show up, a risc-v module could become interesting.

ekiwi commented 5 years ago

I asked someone from SiFive about machine readable documentation for the E31 and they pointed me to this: https://github.com/sifive/freedom-e-sdk/tree/v201905-branch/bsp/sifive-hifive1-revb

@salkinium Does your device file generator infrastructure support reading .dts files?

salkinium commented 5 years ago

@salkinium Does your device file generator infrastructure support reading .dts files?

Nope, because there is no code infrastructure for Device Tree outside of the linux kernel (not true, there is one in Zephyr). It's almost like it's not even a standard file format or something. 🙄

But of course it's probably not diffcult to hack something together.

nesos commented 5 years ago

So, on my quest to set up a minimal blinky example for the HiFive1 I came to the point where i got scons to tell which gcc to use. So far I got that the scripts for setting up compilers are in ext/dlr/scons-build-tools/site-tools. I have to create a new compiler-riscv64-none-eabi toolchain script. Shall I put it into the scons-build-tools fork in modm or somewhere else in the project tree?

salkinium commented 5 years ago

Shall I put it into the scons-build-tools fork in modm

Yes! Our fork is functionally slightly different and more up-to-date than the original DLR one.

ekiwi commented 5 years ago

. It's almost like it's not even a standard file format or something

At least it is more standardized than ST's custom XML stuff, right?

Is there any other data that you need? Like a register map or similar?

salkinium commented 5 years ago

At least it is more standardized than ST's custom XML stuff, right?

Last time I looked, Device Trees (in general) are somewhat useless since the ones that exist are completely or partially written by hand and thus even if they are syntactically correct, they do not use the same names or even the same concepts for describing hardware. Similarly the CMSIS-SVD files are standardized, however their content and quality still strongly varies. A standard without sensible enforcement is utterly useless.

Is there any other data that you need? Like a register map or similar?

Memory sections, GPIO pinmux per package, and peripheral instances would be very good. But I would not start a whole new parser for just a few devices, when I have to provide half the data manually anyways.

nesos commented 5 years ago

Okay, so I put together a minimal setup to get the HiFive1 running. You can have a look at it on my fork here: https://github.com/nesos/modm/tree/feature/hifive1

The setup doesn't do much right now. It is barely more than the startup code and the linker script. But building the example lets the RGB LED light up white.

The next steps for me now is to get interrupts and the clock module working so that the LED will actually blink

nesos commented 5 years ago

I'm currently implementing the clock module and stumbled upon a problem. As far as i understand it, the clock is meant to be driven by a 1ms timer. The E31 core does only have one timer interrupt that is driven by the "RTC" which is basically only a 64 bit timer. The problem there is, that this driven by an external 32.768 kHz crystal and fed to a counter and trigger an interrupt when it reaches a certain value. The setup looks something like this:

Crystal --> Core Timer Counter --> Core Timer Interrupt

With this setup I can't achieve a 1 kHz time base. Could that be a problem? Can I base the clock on a different time base instead? However I can imagine running on 1 kHz instead could cause some issues

Edit: Okay never mind, it looks like the PWM peripheral is meant to be used as timers as well

salkinium commented 5 years ago

Alternatively you could leave the timer free-running, and just do the conversion to ms on call to the now() function (perhaps cached, so you only compute this max once per ms). The overhead would probably be similar to an interrupt. (Kinda like this)

But it's easier to use a different timer interrupt instead.

nesos commented 5 years ago

Oh, thanks for the hint. This is actually a bit easier as I can just read out the RTC Counter to calculate the time and don't need any interrupts.

nesos commented 5 years ago

The blinky example is now working with the HiFive1 board! I implemented the clock and GPIO modules for the platform. Software timers work as well although the method using the low frequency timer is not the most precise one.

You can have a look at it on my fork. I'm not sure the structure and especially the registers access in the GPIO module is that clean and efficient. Feedback to this is very welcome!

salkinium commented 5 years ago

Do you want to open a Draft PR? That makes it easier to provide feedback and discussion.