Bare Metal STM32 Programming and a Quadcopters Awakening
timakro.de
timakro.de
*(uint32_t *)0x40021018 = 0x00000004;
after a few days, it will become tiresome to read and to remember all those addresses. I suggest you to use the header [0] that the ST provides for STM32F1, which is included in packages such as STMCubeF1 [1], STMCubeF0, etc.For instance, instead of using the memory address directly, you could just do
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
so it's easier to remember what is what. STMCubeF1 is a big package, but you won't be using the API/drivers ST provides (such as HAL and LL), just the header. As I understand, the STM32 community kind of rejects this API as "bloated".I have some examples here if you would like to take a look:
https://github.com/dbolgheroni/arm-makefile/blob/master/drv/...
Cheers,
[0] https://github.com/dbolgheroni/arm-makefile/blob/master/stm3... [1] https://www.st.com/en/embedded-software/stm32cubef1.html
If you're not making millions of something (cost sensitive), and not running into performance issues with the HAL, just pick a microcontroller with more than enough flash and use the HAL provided by ST. It's faster to develop with, relatively robust, good performance, and it will make your code more portable. Writing directly to registers is the perfect example of premature optimization.
I've spent the last ~7 years writing firmware on the NXP LPC8xx/18xx and the STM32 L0/L4/F7/H7. In that time I've only found a couple of errors in the HALs provided, and only once or twice needed to re-write some HAL code to increase performance. Using the HALs from the vendor saved me an immense amount of development time and made porting code between chips trivial.
*(uint32_t *)0x40021018 = 0x00000004;
Actually that line is not ok. But for another reason. Without "volatile" in there, the compiler may reorder this access with others, or remove it, or combine it with others. None of that is good.The HAL is very complete, but a bit hard to read because it supports all the (sometimes very subtle, possibly even undocumented) variations in the STM32 feature blocks. These variations have accumulated over the years.
Edit: also, the STMCube tool is a great help for configuring the chips of that family. It can configure IO pins, function blocks, the sometimes insanely flexible clock tree, generate project skeletons, estimate power consumption, etc... it is actually quite useful.
http://www.chibios.org/dokuwiki/doku.php?id=chibios:product:...
ARGH! Seriously? The STM32F103? Crazy (or should that be Craze) hobbyists using "blue pill" boards because they are cheap (and they are, like $3 on ebay) which use this bastard chip of the ST Cortex-M line and they say "gee, its a really simple circuit and since they sell for so cheap on ebay it should be a good idea to use this chip!" BZZZZZZT!
ST Micro makes much better CPUs that would be ideal for this application, they have things like on board DSP instructions in their floating point units, and can run at internal clock rates of 180 MHz with a megabyte of Flash and 384K of RAM, some of it very high performance (core coupled memory). These CPUs are no harder to put onto a PCB than the STM32F103 and they are so much more capable. And sure, they are $10 apiece instead of $1 apiece which is fine if you're making BILLIONS of these things, but a bespoke quadcopter?
Oh but its Open Source, cool, except I can't find the PCB files anywhere, if I could I could pull out that crap chip and put in a real CPU and have OSHPark make me a few. I did find the software repo : https://github.com/Crazepony and yeah, another budget quadcopter maker with a bunch of things they want to sell and an "open source" tag to try to get people to come and look. Fair enough, it made me look. It is sort of the 'freemium' hardware company model.
Sigh. I'd love something bigger than the Crazflie[1] which is like real open source (PCB and everything) and smaller than a DJI Phantom that I could play around with.
A typical quad flight controller with an STM32F4 and a decent MPU will set you back less than $30.
Python != realtime, flight-control == hard real-time
Further, my experience with Micropython so far has shown it to be pretty fluid. But I would be the first to tell you I haven't challenged it all that much.
One place which has done it correctly though is Dorna:
They kickstarted (successfully, shipping to their backers etc), now have an online store, and all of the files (both software + hardware designs) are downloadable for everyone. :)
You can get it cheaper and just solder the header yourself. Even has a micro USB support.
Truly remarkable board.
I can't vouch for the product or the seller, but for $2 shipped, the price is right.
Does it use some kind of internal clock multiplier to achieve 72MHz? Would such a magnified 8MHz to 72MHz provide a good stable clock?
I think the MCU starts running at a low speed from an internal RC oscillator, and then setting up the high speed clock source happens early in the initialization code. This code can be generated by ST's STM32Cube software, which is useful as a reference implementation even if you don't use the generated code in your project.
https://www.silabs.com/documents/public/data-sheets/Si5351-B...
The clock configuration is actually a bit complex, you can see an example from the STM32CubeMX configuration code generator tool here: https://imgur.com/S9L6U37
HS means high-speed and is used for the system clock and peripherals, while LS is low-speed and is used for the real-time clock. Peripherals have limits, like the ADC clock is shown to be 36MHz, but the maximum is 14MHz. The tool is not complaining because the ADC was not enabled for that project. Otherwise I would have to change the ADC prescaler, which take values like 2, 4, 6 etc. Thus had I enabled the ADC, I would have been forced to use a prescaler of 6, making the ADC clock 12MHz, below maximum.
To get the maximum ADC frequency of 14Mhz, I would have to lower the system clock to 56Mhz.
Other peripherals, like USB, also has some strict limits.
ST actually sells an evaluation board for learning about drone control; it has a BTLE module, four small FETs, sensors for pressure and a 9-axis IMU, a 1S battery charging circuit, and source code for some example firmware on Github. Search for 'STEVAL-FCU001V1'.
I've also seen a lot of cheap STM32-based FCU boards from the same places you'd get one of these 'blue pill' boards.
These are very useful chips to learn about, because they come in all shapes and sizes. Some focus on power efficiency, others on speed, others on connectivity or signal processing, and there aren't too many differences that you need to account for in your code.
Also, you can program and debug these using OpenOCD with a generic "ST-Link" module; they only cost a few bucks from cheap sources, or many of ST's evaluation boards have a built-in STLink probe which you can use. That lets you connect to the chip from GDB and step through your code like a normal C program, which is often a lifesaver.
I'm not sure if JTAG will even work or if they connected a pin to some sensor or similar on the board. SWD will work for sure, I saw the two SWCLK and SWDIO connectors on the board.
They're a little bulky, but if you're interested in bare-metal programming, the embedded Rust ebook[1] currently uses an STM32F3 discovery kit[2] as a target, and that board's user manual has instructions for using its ST-Link to program/debug an external application[3] like your drone.
[1]: https://rust-embedded.github.io/book/
[2]: https://octopart.com/stm32f3discovery-stmicroelectronics-241...
[3]: https://www.st.com/resource/en/user_manual/dm00063382.pdf (PDF, see section 6.2 for STLink info)
You can use JTAG probes that implement the CMSIS-DAP (also called DAPLink) protocol, so you get a probe that doesn't need any driver as is seen as an HID USB device. I ran through some problems when trying to use the ST-LINK/V2 with Linux, but that was some years ago and I don't know if things have changed since then.
CMSIS-DAP: https://os.mbed.com/handbook/CMSIS-DAP
Some probes: https://www.adafruit.com/product/2764
(I'm even piloting in this video)
There's a greater risk of fire or just general damage to the capacity of the batteries.
But for bigger batteries I recommend buying a charger that can handle 4 or more separate batteries at a time like the SkyRC Q200 or the Turnigy TQ4, or just do like me, charge each battery individually.
I can't wait to see how a STM32H7 will perform on a quadcopter, and what it will allow for :)
PX4
Ardupilot
Cleanflight
iNav
etc
Each is oriented towards different types of audiences based on features and license.
It's not free ($189), but it removes so much friction from the embedded development process.
I'm not affiliated with the company, just a happy customer.
Go for gcc or clang with cmake (or even just make) and use qt creator or visual studio code or others. You will get cmake based auto complete, access to a proper IDE color scheme of your choice, get to use your own compiler (clang, gcc, etc), and it's much more flexible. And for debugging be able to use a much more capable ozone from segger, or even gdb enabled backend in qt creator or clion.
My work flow for example is cmake and gcc regarding tooling, qt creator or visual studio code which works with cmake to give me proper context aware auto complete, and clang-tidy as a linter running in the background. I am incredibly productive with this, and am able to make use of c++17's features to go for true zero cost abstractions, while shifting checks from runtime to the compiler via types and static asserts and whatnot.
Plus, this is far more portable. No longer having to worry about project files working across diffirent versions of keil (this bit me in the ass at my last company). It's just a simple text file.
Let me advise against growing dependent on IDEs. They make it easy to get started, but soon begin to hold you back. Vim, meanwhile, takes some practice, but it repays so much, year in and year out. I have never heard of anyone who learned and then abandoned it.
[0] https://www.electronicsweekly.com/news/business/st-buys-2017...
My personal preference is to use VS Code with the GNU Arm Embedded Toolchain as well though.
Governments and/or corporations have control of the bottom layer of cell phones and TCP/IP networking. Not so for firmware and cryptography, though not for lack of trying.
I'll most probably feature your article in the issue coming out this Sunday or a week after.
Thanks!