Close

Haque in a Flash

A project log for Careless WSPR

A desultorily executed Weak Signal Propagation Reporter beacon.

ziggurat29ziggurat29 08/15/2019 at 15:061 Comment

Summary

The STM32F103C8 on the BluePill (and really I guess every board using that part) is rumoured to have 128KiB flash, despite the datasheet's claims otherwise.  I lightly hacked the project to test this theory out.  It seems to work!

Deets

The datasheets indicate that the STM32F103x8 has 64KiB flash and the STM32F103xB has 128KiB flash.  Otherwise, they have the same capability.  The chips do identify themselves over the SWD interface, and mine definitely reports itself as the 'C8, and not the 'CB (plus, the part markings).  However, I read somewhere (alas, can't cite, but apparently this is well-known) that it seems that STMicroelectronics opted for some economies and these parts actually the same die, and in fact both devices have 128KiB flash!  If you think about how much it costs to set up a production line, it starts to make sense how this saves them money -- there's no extra cost for the silicon, but there's a lot of extra cost for the tooling.  They probably do a final programming step during qualification that fixes the identity.  Fortunately, it seems that this doesn't actually inhibit access to that extra 64 KiB.  Here is how I hacked my build system to enable its use.

Hacking OpenOCD

The System Workbench toolchain embeds OpenOCD to operate the debugger/programmer.  This tool uses a bunch of config files that describe the chip's capabilities.  There are two locations which have configs for this chip:

C:\Ac6\SystemWorkbench\plugins\fr.ac6.mcu.debug_2.5.0.201904120827\resources\openocd\scripts\target
C:\Ac6\SystemWorkbench\plugins\fr.ac6.mcu.debug_2.5.0.201904120827\resources\openocd\st_scripts\target

The 'fr.ac6.mcu.debug_2.5.0.201904120827' is quite possibly different on your system because it involves the version number that you deployed.  But you can figure that part out for yourself.

In each of those locations is a file:

stm32f1x.cfg

I renamed this to 'stm32f1x.cfg.orig' and made a new copy named 'stm32f1x.cfg' which I hacked.  If you scroll down a ways, there is a part '# flash size will be probed' that is where we make a change:

# flash size will be probed
set _FLASHNAME $_CHIPNAME.flash
#HHH I hacked the size to 128k
flash bank $_FLASHNAME stm32f1x 0x08000000 0x20000 0 0 $_TARGETNAME

So we are simply not probing, but rather explicitly telling the tool that we have 0x20000 (128 Ki) of flash.

I went ahead and modded both copies of 'stm32f1x.cfg', however it appears that the operative one is the one that is in the 'openocd\st_scripts\target' location.

Fair warning:  if you later download an update of the system, you will probably need to re-apply this hack, because new copies of files will be deployed.  You'll know if this happens though, because things will break (if you're using the high memory).

Hacking the Build Config

Next, we need to tell the linker about the flash.  This is done in the root of the project, in 'STM32F103C8Tx_FLASH.ld'.  Near the start of that file is explicitly stated the size of the RAM and Flash.  I changed it to this:

/* Specify the memory areas */
MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 20K
/* HHH I hacked the size */
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 128K
}

My project build now is well below the 64 KiB barrier, but I modded the persistent settings file to specify the last page of the 128 KiB instead of the same for the 64 KiB.  This made it easy to prove that stuff can be stored there.

//HHH I modded this to get 128K #define FLASH_SETTINGS_END_ADDR 0x08010000
#define FLASH_SETTINGS_END_ADDR 0x08020000

Then I did a clean and rebuilt.  I started the debugger, and you will see along the way a message:

Info : device id = 0x20036410
Info : ignoring flash probed value, using configured bank size
Info : flash size = 128kbytes

So it's on.

I connected to the monitor, and persisted settings.  Then I connected with 'STM32 ST-LINK Utility'.  This will think there is 64 KiB because of the part identification, however there is a handy 'Size' field in the 'Memory Display:' section, and you can just type in 0x20000.  Now you can read and erase the pages out to the full 128 KiB.

Wow.  Thanks STM!  Well, I suppose there is no guarantee this will last forever, but this is a fairly old part, so it is also fairly unlikely that they will produce new masks or alter the finalization process that would prohibit using the upper 64 KiB.  In a professional product I would not do something like this, I would just buy the 'B' version that officially has the extra flash, but it's very handy to know this on this developer board that I did not design and build that you can get a little more code space if you need it.

Next

Back to implementing the WSPR task

Discussions

Alan Green wrote 08/15/2019 at 21:15 point

Nice! Thank you for the tips.

  Are you sure? yes | no