How to flash an LED: writing ARM assembly for an STM32 microcontroller
mcla.ug
mcla.ug
It was a very frustrating experience, but articles like this make me want to dive in and try again!
It will even spit out multiple project types - everything from ARM Keil/MDK/uVision to just a simple makefile.
I think there’s some actually interesting work being done with standardization like SVD files, but too many vendors treat them like second class citizens compared to their bulky code gen solutions.
1 @ Set BR8 field in GPIOA_BSRR, to clear GPIOA8
2 movw r1, #0x0000
3 movt r1, #0x0100
you can just use a mov to get that value. Any 8-bit value shifted left any number of bits is synthesizable using one MOVSo you could do `mov r1, #0x01000000` right? nice.
I spent a month and got things working with a modern toolchain C/CMake/GCC/OpenOCD but gave up on further work bc I couldn't nail down a lot of details. micro programming outside arduino is painful and backward. it's stuck in the 90s
A little typo I think I spotted: ' So, to turn on our LED we want to set the BR8 field, and to turn it off, we want to set the BS8 field.'
Should this be: ' So, to turn on our LED we want to clear the BR8 field, and to turn it off, we want to set the BS8 field. '
This isn't a typo, actually. If you look at the documentation of the BSRR register (which is screenshotted in the blog post), it says of BRy:
> These bits are write-only [...] [Setting to 1] Resets the corresponding ODRx bit
So setting BR8 in the BSRR clears the ORD8 bit in the output data register. Because our LED is active low, this turns the LED on.
The indirection can make this a little confusing, I hope this cleans it up!
Do you happen to know of any great learning resources, basically more posts like you've written that go into lots of details and explain why things are done?
Thanks again!
They use IP from synopsis, but <rumor>synopsis refuses to allow their docs to be published so every manufacturer has to read them and regurgitate them into their own docs in their own words</rumor>. In any case official STM docs are incomplete. See their driver source - it accesses undocumented registers and sets undocumented bits in documented regs. Without them the usb core will not start or run.
Your options are to carefully rewrite STM's libs (which are based on real synopsis docs and DO work) or use them as is. Both solutions IMHO leave you subject to STM's EULA and such
this is the #1 issue in stm32
a close #2 is the their so-smart-it-is-useless i2c controller. I know of no project that uses it. Everyone bitbangs i2c master on stm32. The hardware unit is very easy to wedge to a point where only a power cycle unwedges it.
https://github.com/STMicroelectronics/STM32CubeF4/tree/maste...
(I've chosen the version for STM32F4 arbitrarily; if there's something similar in one of their other USB support libraries, feel free to point to that instead.)
I will say that STM has definitely released better tools that make it much easier to get designs up and running (STM32Cube specifically).
More so for Microchip than Atmel --- it's pretty common to find on some of their newer and more complex parts a ton of errata, among which there are some extremely "WTF!?" ones like "feature X does not work at all".
This Rust library is an abstract USB library that can implement CDC serial https://docs.rs/usb-device/0.2.5/usb_device/, and this library connects it to the STM32 USB peripheral https://github.com/stm32-rs/stm32-usbd
Examples here: https://github.com/stm32-rs/stm32-usbd-examples
To put it another way -- the IP protections on the current library are a matter of copyright law, and the protections are on the code itself. The facts of which bits do what -- which are embodied in that code -- are not protected (or protectable!), and can be reused freely.
Though given Oracle's current legal proceedings that might change...
Here is an example in C using libopencm3, that uses timers to trigger an interrupt used to flash LEDs https://github.com/libopencm3/libopencm3-examples/tree/maste...
This would take a fair bit more code to configure the timer, and setup an interrupt to handle the timer.
Using the interrupt driven approach, can led to better performance both in CPU time (async communication with slower periphials etc) and battery life (sleep states).