[STM32F103] - Porting MicroPython to the "BluePill" board

Discussion and questions about boards that can run MicroPython but don't have a dedicated forum.
Target audience: Everyone interested in running MicroPython on other hardware.
Archer
Posts: 6
Joined: Fri Sep 08, 2017 4:33 pm

[STM32F103] - Porting MicroPython to the "BluePill" board

Post by Archer » Tue Sep 19, 2017 8:41 am

I have a few of these cheap boards from china usually referred to as the "BluePill" with a STM32F103C8T6 chip on them. They are specified as a 72Mhz ARM Cortex-M3 with 20K of ram and 64K of flash. In search of a low power alternative with more serial ports for the ESP8266's I have been running MicroPython on for the last two months I had a try at slimming the build down to fit in the 64K of flash starting from the minimal port.

Unfortunately I did not get it below 70K without loosing the REPL and I was about to give up the effort when I discovered that the silicon die used in the chips is the exact same as the STM32F103CB which has 128K of flash! See here https://github.com/texane/stlink/issues/516 As soon as I could I tried to confirm this but my ST-LINK V2 still reported only 64K of flash. Then I found a clue that the build in serial bootloader does in fact give access to the 128K flash that the chip has inside. And to my big surprise two of my boards are indeed reporting 128K flash through the serial programming mode.

The last few days I have been reading datasheets and examples and anything to give clues on how to access the GPIO pins on the STM32F103 and have it boot to the MicroPython REPL or at least show me the lines of the frozen module example. After much trial and error I have been able to modify the minimal example to compile for the STM32F103 Cortex-M3 and initialize the GPIO ports just enough to have the onboard LED turn on!

I know there is still a lot to do to make this port functional but the LED turning on shows me that the basic initialization is working and I am writing to the correct registers for the GPIO ports. My current code is based on the baremetal examples I found on github from Tom Trebisky at https://github.com/trebisky/stm32f103 and the original main.c in the minimal port. I do plan on switching from baremetal to the LowLevel "driver" headers provided by ST to make it easier to add more peripherals to the MicroPython side.

My attempt at this port is mostly out of personal interest and learning how MicroPython works under the hood. And because I want to use these boards in a few projects I have been planning for a while. But then I thought this might be interesting for other people which is why I am posting my huge first post on this forum now.

Any ideas or comments for this port are welcome.

mwm
Posts: 36
Joined: Wed Aug 09, 2017 3:52 pm

Re: [STM32F103] - Porting MicroPython to the "BluePill" board

Post by mwm » Tue Sep 19, 2017 2:48 pm

Please let us know how this goes. Besides having a couple of these, an STM32F103 port in general is of interest, as it might make using micropython for scripting on the Devo 10 (with an STM32F103VCT6) feasible. My initial reaction was no, as our app uses >128K of the 256K in the chip.

User avatar
deshipu
Posts: 1346
Joined: Thu May 28, 2015 5:54 pm

Re: [STM32F103] - Porting MicroPython to the "BluePill" board

Post by deshipu » Tue Sep 19, 2017 3:05 pm

Please remember that there is a reason why those chips have half of their flash disabled and are sold cheaper. Flash is a very finnicky thing to manufacture, and often will have faults in it. It's a common practice to take the silicon that has some of its flash faulty, disable the faulty parts and sell it as a version with less flash.

Archer
Posts: 6
Joined: Fri Sep 08, 2017 4:33 pm

Re: [STM32F103] - Porting MicroPython to the "BluePill" board

Post by Archer » Tue Sep 19, 2017 3:17 pm

I was actually waiting until I had a working "Blink-a-led" script, but here is a short session snippet that is already running right now....

Code: Select all

MicroPython v1.9.1-345-g7516332-dirty on 2017-09-19; BluePill with STM32F103CB
Type "help()" for more information.
>>> help("modules")
__main__          builtins          gc                sys
array             frozentest        micropython       uio
Plus any modules on the filesystem
>>> import gc
>>> gc.mem_
mem_free        mem_alloc
>>> gc.mem_free()
14704
>>> gc.mem_alloc()
480
>>> import frozentest
uPy
a long string that is not interned
a string that has unicode αβγ chars
b'bytes 1234\x01'
123456789
>>> 
And the memory usage for this is:

Code: Select all

LINK build/firmware.elf
   text	   data	    bss	    dec	    hex	filename
  80912	      4	  15840	  96756	  179f4	build/firmware.elf
I am now working on getting a minimal machine module to compile but getting errors instead

Code: Select all

CC modmachine.c
In file included from ../../extmod/machine_mem.h:29:0,
                 from modmachine.c:27:
modmachine.c:32:50: error: 'MP_QSTR_umachine' undeclared here (not in a function)
     { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) },
So in short I got it "functional" a few hours ago with a very minimal initilization of just the GPIO ports and USART1. :D

Archer
Posts: 6
Joined: Fri Sep 08, 2017 4:33 pm

Re: [STM32F103] - Porting MicroPython to the "BluePill" board

Post by Archer » Wed Sep 20, 2017 12:10 pm

deshipu wrote:Please remember that there is a reason why those chips have half of their flash disabled and are sold cheaper. Flash is a very finnicky thing to manufacture, and often will have faults in it. It's a common practice to take the silicon that has some of its flash faulty, disable the faulty parts and sell it as a version with less flash.
Thanks for the warning, I really did not even think about that being the reason it's not visible and sold as a lower capacity part. I guess so far I have been lucky the regions above 64K in my chip are good enough to pass verification during flashing. Not using the REPL reduced the binary to less than 40K I think but limits the use to frozen scripts compiled in. But good to know that if something does not work as expected this could be the cause.

Using MicroPython on the ESP8266 got me hooked and made me want to learn what makes it tick and write my own modules in C to do some low level stuff. So far the complex build system is giving me a headache but adding my files to SRC_QSTR seemed to solve most of my unexplained issues of "'MP_QSTR_umachine' undeclared here (not in a function)" and similar messages.

Now I have the "machine" class available with the 'mem' functions I looked into adding the Pin class which also shocked me with even more complexity. I do have a working machine.Pin.high() and machine.Pin.low() calling my test function for the GPIO flashing the only user LED on my board. Not having a realiable timer I just created a python delay() function with a for loop that took a little while to make this work...

Code: Select all

while(True):
	machine.Pin.low()
	delay()
	machine.Pin.high()
	delay()
Not exactly compatible with the standard MicroPython way to use GPIO but at least I can now call a C function and seeing the LED blink. I learned a great deal to make this work and now it's time to move from bare-metal registers to a more general Low-Level, CMIS or HAL driver to deal with the MCU registers. I have not decided what the best option is but I took a peek at Espruino and they have headers I could borrow for a while to make things work.

I also broke the "compile for linux" option with a fixed CROSS=1 and removing some of the specific linux related stuff which I now kind of regret for debug possibilities. I might start over and commit things in git this time to see what I did later.

mwm
Posts: 36
Joined: Wed Aug 09, 2017 3:52 pm

Re: [STM32F103] - Porting MicroPython to the "BluePill" board

Post by mwm » Wed Sep 20, 2017 5:38 pm

Archer wrote:Not using the REPL reduced the binary to less than 40K I think but limits the use to frozen scripts compiled in.
The latter doesn't obviously follow from the former. For my use case (user scripting a computerize RC transmitter), I don't need a REPL, but being able to run .py scripts from the SD is critical. They'll be called from the C application, triggered by external events of various kinds.

Possibly you also lost the byte compiler? That would make running .py scripts impossible.

User avatar
mcauser
Posts: 358
Joined: Mon Jun 15, 2015 8:03 am

Re: [STM32F103] - Porting MicroPython to the "BluePill" board

Post by mcauser » Tue Sep 26, 2017 10:31 pm

I've too have been trying to get MicroPython running on a F103 Blue Pill. Here's my progress so far.

STM32F1 modifications to the stm32 port:
https://github.com/mcauser/micropython/tree/stm32f103

Added STM32Cube FW F1 v1.6.0 for submodule /lib/stm32lib:
https://github.com/mcauser/stm32lib/tre ... r-F1-1.6.0

Generic Blue Pill board C8T6 64K flash, 20K ram, but using it as a CBT6 128K/20K
https://github.com/mcauser/BLUE_PILL_F103C8

Generic Blue Button board using RET6 512K flash, 64K ram
https://github.com/mcauser/BLUE_BUTTON_F103RET6

Archer
Posts: 6
Joined: Fri Sep 08, 2017 4:33 pm

Re: [STM32F103] - Porting MicroPython to the "BluePill" board

Post by Archer » Fri Sep 29, 2017 9:45 pm

mwm wrote:Possibly you also lost the byte compiler? That would make running .py scripts impossible.
I am not sure if I understand you correctly but I do think the compiler is not included into the <40K binary. I was including the frozenmodule example and that did run I believe with that small binary. Running scripts from an SD card might require a lot more FLASH because it will need the filesystem drivers to read files from it.
mcauser wrote:I've too have been trying to get MicroPython running on a F103 Blue Pill. Here's my progress so far.

STM32F1 modifications to the stm32 port:
https://github.com/mcauser/micropython/tree/stm32f103

Added STM32Cube FW F1 v1.6.0 for submodule /lib/stm32lib:
https://github.com/mcauser/stm32lib/tre ... r-F1-1.6.0

Generic Blue Pill board C8T6 64K flash, 20K ram, but using it as a CBT6 128K/20K
https://github.com/mcauser/BLUE_PILL_F103C8

Generic Blue Button board using RET6 512K flash, 64K ram
https://github.com/mcauser/BLUE_BUTTON_F103RET6
I tried compiling your version but I get all sorts of errors about missing files and eventually "Unsupported processor" in a couple of files. But I am not complaining since you have put in an enormous amount of groundwork already to make it fit into the stmhal structure. Thanks for sharing your progress, very nice work!

I knew it would take a mountain of changes to get it into stmhal which is why I have opted for bare-metal register writing. It works fine but reimplementing all the core MicroPython libraries from scratch is not a lot of fun, but very simple machine.Pin is there. I do not even dare sharing my stuff yet since it's bit's and pieces from everywhere but other than that, it does compile into a binary. I do fear a little that using the HAL will result in a large FLASH requirement or that it will slow things down while accessing the hardware.

If you would like some help maybe we can work together on making it work and support all of it's hardware from Python.

Archer
Posts: 6
Joined: Fri Sep 08, 2017 4:33 pm

Re: [STM32F103] - Porting MicroPython to the "BluePill" board

Post by Archer » Sun Oct 01, 2017 9:27 am

I have been looking into what needs to be done to get the BLUE_PILL board compiling in the smt32 port from where you are. I think you have marked all the places that need some code to support the F1 series but getting that to play nice with the existing F4 and F7 stuff gives me a headache. I am not taking back my offer to help but it's not going to be easy.

For my own port I started to migrate from bare-registers to the LowLayer drivers to make things easier. using bit's and pieces of your stmlib additions for F1 and my own downloaded ZIP from stmcube to get the startup assembly code and C initialization. It's actually really similar to how the HAL works but the LL translates into more compact code which I wanted for my stm32f103c8 port.

I have been wasting a lot of time last night figuring out why the mp_hal_stdout_tx_strn() function did not work any more. I tried everything I could possibly think off changing and I even put back my original bar-register code just to try. Nothing worked. When I looked at the binary and could not find the strings I was trying to send out on the serial line anywhere!
While integrating the startup code from ST i also switched to the ld file provided for the f103xb because some things were complaining during the build process, but somehow that ld file drops the string constants! Switching back to my original ld file made it work again somehow. Both files are quite complex to figure out why it was dropping my strings. For now I accept that it's working again and later look at those files again.

The best part is that I now got it to run at 72Mhz by using the ST examples to get all the clock initialization up and running correctly. And the binary size is not that bad either at just 78.1KB. But that will obviously change after including support for more peripherals to MicroPython.

User avatar
kfricke
Posts: 342
Joined: Mon May 05, 2014 9:13 am
Location: Germany

Re: [STM32F103] - Porting MicroPython to the "BluePill" board

Post by kfricke » Thu Oct 05, 2017 9:30 pm

This really is an interesting effort. I also have been looking for the support of lower flash sized STM32 MCUs. Even with 64k flash an experienced user can do what he wants Micropython to do. Of course this is not a beginners platform!

These days many are interested in IoT MCUs only. But the stability and robustness of those "traditional" platforms as the STM32 and it's lower end members as the F103 is still on focus for some of us!

Keep reporting your progress here please!

Post Reply