LCSC, I found a surprisingly cheap ARM M0 MCU. At the time it was 16.6c in single-unit quantities, with no higher-volume pricing listed. From the datasheet LCSC has posted, there was enough information in English to tell that it has 2kB RAM, 16kB flash, and runs up to 32MHz with a 1.8V to 3.6V power supply. Although the part number suggests it may be a clone or is compatible with the STM32F030, it's not. The part number for the STM32F030 clone is HK32F030F4P6.
Some additional searching brought me to some Chinese web sites that advertised the chip as a 32-bit replacement for the STM8S003. The pinout matches the STM8S003F3P6, so in theory it is a drop-in replacement for the 8S003. Unlike the STM32F0, it has no serial bootloader, so programming has to be done via SWD. And with no bootloader support, there's no need to be able to remap the flash from 0x0800000 to 0x0000000 like the STM32. A small change to the linker script should be all it takes to handle that difference. Even though I wasn't sure how or if I'd be able to program the chips, I went ahead and ordered a few of them. I already had some TSSOP20 breakout boards, so the challenge would be in the software, and the programming hardware.
Since I'm cheap, I didn't want to buy a dedicated DAPlink programmer. I have a STM32F103 "blue pill", so I considered converting it to a black magic probe. But since I've been playing with the CH554 series of chips, I decided to try running CMSIS-DAP firmware on a CH552. If you're not familiar with CMSIS-DAP and SWD, I recommend Chris Coleman's blog post. Before I tried it with with the HK32F030MF4P6, I needed to try it with a known good target. Since I had recently been working with a STM32F030, that's what I chose to try first.
The two main alternatives for open-source CMSIS-DAP software for downloading, running, and debugging target firmware are OpenOCD and pyOCD. pyOCD is much simpler to use than OpenOCD; after installing it with pip, 'pyocd list' found my CH552 CMSIS-DAP:
However that's as far as I could get with pyOCD. There seems to be a bug in the CMSIS-DAP firmware or pyOCD around the handling of the DAP_INFO message. Fixing the bug may be a project for another day, but for the time being I decided to figure out how to use OpenOCD.
To use OpenOCD, you need to create a configuration file with information about your debug adapter and target. It's all documented, however it's very complicated given that OpenOCD does a whole lot more than pyOCD. It's also complicated by the fact that since the release of v0.10.0, there have been updates that have made material changes to the configuration file syntax. I had a working configuration file on Windows that wouldn't work on Linux. On Linux I was running OpenOCD v0.10.0-4, but on windows I was running v0.10.0-15. After installing the xPack project OpenOCD build on Linux, the same config file worked on both Linux and Windows, which I named "cmsis-dap.cfg":
adapter driver cmsis-dap
transport select swd
adapter speed 100
swd newdap chip cpu -enable
dap create chip.dap -chain-position chip.cpu
target create chip.cpu cortex_m -dap chip.dap
With dupont jumpers connecting SWCLK, SWDIO, VDD, and VSS on my STM32F030 breakout board, here's the output from openocd.
After making the same connections (factoring the different pinout) to the HK32F030MF4P6, I was getting no response from the MCU. Before connecting, I had done the usual checks for shorts and continuity, making sure all my solder connections were good. Next I tried just connecting VDD and VSS, while I probed each pin. Pin 2, SWDIO, was pulled high to 3V3, as was nRST. All other pins were low, close to 0V. The STM32F030 pulls SWDIO and nRST high too. I tried reconnecting SWDIO and SWCLK, and connecting a line to control nRST. I added "reset_config trst_and_srst" to my config file, and still didn't get a response. Looking at the debug output from openocd (-d flag) shows the target isn't responding to SWD commands:
Debug: 179 99 cmsis_dap_usb.c:728 cmsis_dap_swd_read_process(): SWD ack not OK @ 0 JUNK Debug: 180 99 command.c:626 run_command(): Command 'dap init' failed with error code -4
Since the datasheet says that after reset, pin 2 functions as SWDIO, and pin 11 functions as SWCLK, I'm at a bit of an impasse. I'll try hooking up my oscilloscope to the SWDIO and SWCLK lines to make sure the signals are clean. I've read that in some ARM MCUs, DAP works while the device is in reset, so I'll peruse the openocd docs to figure out how to hold nRST low while communicating with the target. And of course, suggestions are welcome.
Before I finish this post, I wanted to explain the reference to a "ten cent" MCU. LCSC does not list volume pricing for the part, but when I searched for the manufacturer's name, "Shenzhen Hangshun Chip Technology Development", I found an article about the company. In the article, the company president, Liu Jiping, refers to the 10c ($0.1) price. I suspect that pricing is for quantities over 1000. Assuming these chips can actually be programmed with a basic SWD adapter, then even paying 20c for a 20-pin, 32MHz M0 MCU looks like a good deal to me.
Read part 2 to find out how I got SWD working.