Author Topic: RP2040 baremetal starter project  (Read 2305 times)

0 Members and 1 Guest are viewing this topic.

Online ataradov

  • Super Contributor
  • ***
  • Posts: 9014
  • Country: us
    • Personal site
RP2040 baremetal starter project
« on: December 31, 2021, 10:26:15 pm »
I've got a few RPi Pico boards when they were released. Well, now their time has come. I decided to have a closer look at them and I made my typical bare-metal starter project that I make for every device I work with. The code can be found here https://github.com/ataradov/mcu-starter-projects/tree/master/rp2040

I did not use their header files or SDK, since they are just horrible, IMO. I generated my own header file from SVD file using SVDConv utility from ARM. The result is not perfect by any means, but it is at least usable.

Initial loader is built as a part of the project itself. The project is made so that initial loader transfers the application from the flash into SRAM and entire application is linked in SRAM. Flash remains accessible in XIP mode. It is never used by the compiler generated code, but you can store any data there and read it manually.

The loader uses plain SPI mode to not mess with the QSPI settings in the different flash devices. I have a "clean" version of the QSPI initialization for the flash on RPi Pico if anyone wants that. But I found that QSPI mode does not actually increase performance that much to bother with it for generic code. I tested with the main code running from SRAM and doing CRC32 calculation on the entire 2 MB flash. So the access pattern is linear (in 32-bit words) with minor data processing in-between. QSPI was 1.6 times faster that SPI in that test. Cache did not matter that much here (as it is constantly trashed by long linear access). Cache does matter A LOT if you also run from that flash. The test was ~30 times slower in that case. But this project runs entirely from SRAM, so this is not an issue.

Also note that if you are using the flash in the main application, then you probably need to adjust XIP_SSI->BAUDR, since SPI clock would be 60 MHz with 120 MHz core clock, and 0x03 command only goes up to 50MHz. If you are using flash a lot, you may get better performance by dropping CPU clock to 100 MHz and leaving the divider as is.

The project also includes a tool to generate UF2 file with correct CRC32 for the bootloader section. It can also just update the binary file itself if you have some other way to place files into the flash. There are probably other tools like this out there. I have not really looked.

When I have more time I'll have a look at using both cores and USB, as this is the only not trivial peripheral there.
Alex
 
The following users thanked this post: abraxalito, MK14, Jacon, I wanted a rude username

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 9794
  • Country: fr
Re: RP2040 baremetal starter project
« Reply #1 on: January 01, 2022, 02:03:45 am »
I've written my own build environment as well, but using the SDK files so far.

I did not use their header files or SDK, since they are just horrible, IMO.

What did you find horrible about them?
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 9014
  • Country: us
    • Personal site
Re: RP2040 baremetal starter project
« Reply #2 on: January 01, 2022, 02:24:43 am »
What did you find horrible about them?
A bunch of unconventional stuff. Starting with peripheral definitions in lower case. Things split into a million files for no reason (Atmel does the same and I hate it too).

Lack of bit-field unions is not great either. I prefer let the compiler do the math rather than do a bunch of bit-ops when I need to change the value of a multi-bit field in a register.
Alex
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 9794
  • Country: fr
Re: RP2040 baremetal starter project
« Reply #3 on: January 01, 2022, 02:39:03 am »
What did you find horrible about them?
A bunch of unconventional stuff. Starting with peripheral definitions in lower case.

Oh, yeah. Not my style either, but that was definitely not a deal-breaker either. I've seen worse in terms of bad style.

Things split into a million files for no reason (Atmel does the same and I hate it too).

OK, this one is horribly annoying. The NXP SDK is structured exactly in the same way. It's largely due to their use of CMake, which promotes this heavily hierarchical structure of sources files. It's not just that there are many source files - it's also that they are each in their own subdirectory!! The alleged benefit is that one can fine-tune compiler options for each and every file, because each is associated with its own CMake file! The practical benefit of that in this kind of case is almost exactly zero.

Lack of bit-field unions is not great either. I prefer let the compiler do the math rather than do a bunch of bit-ops when I need to change the value of a multi-bit field in a register.

Yeah. Well, these days, compilers are indeed largely smart enough to group operations when you use bit fields, so bit masks have no advantage for performance reasons. But... bit fields are not portable. That would be the only rationale for not using bit fields. Making it compiler-proof.

Which in itself is a questionable issue since those definitions are entirely target-dependent, and, the main two compilers that are commonly used for ARM Cortex dev, GCC and Clang, both treat bit fields the same way. I've never used armcc - and I don't think it's even currently supported by the Pico SDK - but I think it does treat bit fields also in the same way as GCC...

« Last Edit: January 01, 2022, 02:42:00 am by SiliconWizard »
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 9014
  • Country: us
    • Personal site
Re: RP2040 baremetal starter project
« Reply #4 on: January 01, 2022, 02:45:56 am »
But... bit fields are not portable. That would be the only rationale for not using bit fields. Making it compiler-proof.
I don't care. They are portable among all reasonable compilers. And I don't use goofy compilers, so they are pretty much guaranteed to work for me. In fact, not being compatible with leading compilers is the issue of the compiler not the code. If you take seriously all the stuff that is missing from the "official" standard, you will live a sad life.

There are a whole bunch of other attributes and stuff that pretty much ties this code to GCC/Clang and I realistically see no reason for any other compilers to exist or use them.

Also, new (v6) ARMCC is just Clang, so it will work the same way as GCC.
« Last Edit: January 01, 2022, 02:51:13 am by ataradov »
Alex
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 3795
  • Country: us
Re: RP2040 baremetal starter project
« Reply #5 on: January 02, 2022, 08:02:39 am »
Quote
Things split into a million files for no reason
Quote
It's not just that there are many source files - it's also that they are each in their own subdirectory!
Yeah.  With interdependencies on the directory structure.
I tried setting up an Atmel-style top-level "io.h" file that included all of the struct and register definitions so I wouldn't have to have a hundred "-I" options on the compile line, and it does work, because some file that ought to be rp2040 specific (address_mapped.h: "Low-level types and (atomic) accessors for memory-mapped hardware registers") ends up including pico.h (which is theoretically a board-specific definition file)  and "hardware/regs/addressmap.h"

Essentially, they've mixed up their chip definitions with their library and SDK definitions, and pretty much required a specific (and unusual) build environment :-(

Did we mention yet that the file paths are redundantly redundant?  Like ".../rp2040/hardware_regs/include/hardware/regs/adc.h" ?

One of the early problems that cropped up was that the micropython (one of their preferred tools) build on windows ended up generating compile commands that exceeded window's maximum command length.  (Yeah, bad for windows having a limited command line length.  But it's about 8k bytes, which ... is pretty ridiculous to exceed!)

I'm not sure that it's "awful", but it's surely ... annoying.
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 9794
  • Country: fr
Re: RP2040 baremetal starter project
« Reply #6 on: January 02, 2022, 05:08:26 pm »
Did we mention yet that the file paths are redundantly redundant?  Like ".../rp2040/hardware_regs/include/hardware/regs/adc.h" ?

That's part of the heavy hiearchical structure of the files and directories. Not only does every .c file lives in its own subdirectory, but each also has its own 'include' subdirectory with the corresponding header file(s), and as you showed here, the include subdir can have also subdirectories. All this is structured to accomodate a certain way of using CMake, as I said. As I got it, it allows them to "define" each feature support as a kind of independent "module", making adding one easier and independant of the rest. The idea could be interesting at first sight, but it just ends up as a huge mess.

Note: to be fair, it probably makes the life of the maintainers of the SDK easier (as long as they master this structure), as adding "features" is probably a bit easier. And, for users, it's alright too as long as you use CMake, and use it as instructed. It also makes it possible and easy to cherry-pick the SDK features you want, instead of having to build and link against the whole shebang. So, that's very modular. But for people using other build tools, or using CMake in a different way, that's pure hell. So, you're stuck with their way of doing things. Or, you have a lot of annoying work to do. I did write my own Makefiles from this SDK, but it needs to deal with a lot of directories, and that's pretty annoying indeed.
« Last Edit: January 02, 2022, 05:33:50 pm by SiliconWizard »
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 3795
  • Country: us
Re: RP2040 baremetal starter project
« Reply #7 on: January 02, 2022, 10:23:50 pm »
Quote
it probably makes the life of the maintainers of the SDK easier, as adding "features" is probably a bit easier.
I'm not sure I'd mind so much if it was just the (SDK) *code* that was structured this way.
But having the (theoretically codeless) device definitions set up like this is not good.

 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 9794
  • Country: fr
Re: RP2040 baremetal starter project
« Reply #8 on: January 02, 2022, 10:26:26 pm »
They probably did this out of consistency, but if all you want to use are those definition files, you can extract them, put them in one single directory and use them like that.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 9014
  • Country: us
    • Personal site
Re: RP2040 baremetal starter project
« Reply #9 on: January 02, 2022, 11:40:59 pm »
They probably did this out of consistency, but if all you want to use are those definition files, you can extract them, put them in one single directory and use them like that.
You would have to do some editing/post-processing too, since they all use #include with long paths.
Alex
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 9794
  • Country: fr
Re: RP2040 baremetal starter project
« Reply #10 on: January 03, 2022, 12:23:25 am »
They probably did this out of consistency, but if all you want to use are those definition files, you can extract them, put them in one single directory and use them like that.
You would have to do some editing/post-processing too, since they all use #include with long paths.

Yeah, the include directives use relative paths, consistent with this frantic hierarchical scheme.

So yeah, if you're only going to use those definitions headers, better generate your own from SVD, as you did.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 9014
  • Country: us
    • Personal site
Re: RP2040 baremetal starter project
« Reply #11 on: January 05, 2022, 04:08:00 am »
I've added RP2040 as a platform to Free-DAP, which required adding USB (HID and CDC) - https://github.com/ataradov/free-dap/tree/master/platform/rp2040. So now I have a clean USB stack. But to be fair, their own simple bare metal USB example is also pretty clean and useful.

I also added pre-built UF2 image that can turn any Raspberry Pi Pico into a CMSIS-DAP debugger.

Next I want to move the DAP part to the second core, mostly just to see how the multi-core thing works. And then implement SWD (and may be JTAG) low level transfers with PIO controllers. Again, mostly to have a practical thing to be used as a learning tool.

But the more I work with this chip, the more I like it. I ordered 50 pcs to have some in stock to be used in random projects.
Alex
 
The following users thanked this post: abraxalito, newbrain

Offline Rudolph Riedel

  • Contributor
  • Posts: 38
  • Country: de
Re: RP2040 baremetal starter project
« Reply #12 on: January 05, 2022, 03:57:15 pm »
I have not checked in a while since I quickly lost interested in the RP2040 again.
But the includes, yes, I was surprised that there were no CMSIS parts included.
So instead of Systick_Handler() it was isr_systick() and there was no SysTick_Config().
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf