Fun with 8-bit micro


Although I’ve worked with micro-controllers for the past few years, it always felt like there was a barrier preventing me from understanding how these work at a low level. In recent months it became more obvious that this barrier is, in fact, caused by all the abstractions that exist in the modern coding environment for micro-controllers.

Every micro-controller vendor nowadays provides their own IDE and SDK, supposedly to make the life of an embedded engineer a lot easier. While it does seem to make life easier, the abstraction prevents you from understanding what’s going on at a low level. (From here on, “micro” will be used as shorthand for micro-controller.)


Why do you even need to understand anything at a low level?

Understanding things at a low level makes debugging a lot easier, and if you understand what’s going on under the hood, you can easily switch to a different micro.

Anybody can use a micro nowadays without understanding what’s going on inside, but it eventually becomes obvious that the one you chose at first is preventing you from switching to another. This is because each comes with its own SDK, and the user mostly interacts with ready-to-use function calls. Switching means learning a new SDK and a new way of abstracting things, which can be frustrating and ultimately sends the user back to the one they started with.

There’s no standard way of interacting with these abstractions across modern micros. The only way to really understand them is to dive into the SDK’s functions and figure out what’s going on. These functions often contain initialization routines, direct register calls, bus interactions, and so on. If you’re not familiar with such concepts, it simply looks intimidating.

Hoarded Micros A typical micro-controller hoarder’s collection

To work through this feeling, my recent focus has shifted to coding at a low level of abstraction. I deliberately chose an 8-bit micro for this “bare-metal” work (even though that term isn’t a favorite of mine). An 8-bit architecture has the advantage of a very minimal setup and allows direct hardware manipulation, which makes it a lot easier to get started compared to a 32-bit one. A modern 32-bit architecture is complex enough that it would most likely make me quit the moment I started.

Another reason is how cheap and tiny these chips can be. Modern 8-bit micros pack in features like USB and DMA, while also offering much faster instruction speed compared to the standard MCS-51.

Hardware setup

I had a few CH552 micros left over from a previous project, and it felt like the perfect opportunity to get started. This 8-bit micro has 16KB of ROM, 256 bytes of internal RAM, and 1KB of xRAM. Along with standard 8051 peripherals, it also supports USB Type-C, a DMA bus, and touch keys. All this in a 3x3 mm package costing 40 cents per unit.

CH552_Dev Janky setup re-purposing a CH552 debugger from another project

The above board conveniently had 1 gpio connected to a led, 4 gpio’s connected to a breakout and another 2 exposed for uart communication. Those 4 gpio’s also seemed like a perfect candidate to drive a micro bipolar stepper that I got hold of few months ago.

This tiny stepper motor is directly connected to the output ports which are configured as push-pull. Adding a driver would be the right way, but seems like this setup is enough to drive the motor and test the code. Speed and direction are controlled through the USB CDC interface. If you’re curious about this stepper, you can get more detail on it and the setup in an upcoming blog post.

Also, if anyone is looking for a similar micro from a Western manufacturer, the EFM series from Silicon Labs, the STM8 series from STMicroelectronics, or the PIC16 series from Microchip might be worth a look. These are all enhanced 8-bit controller series. Some, like the EFM series, are enhanced 8051 cores, while others follow proprietary architectures.

Getting started


1 . Clone the repository
git clone https://github.com/Nandish-KK/8bitfun.git
cd 8bitfun/

2 . Create a virtual Python environment and activate it.
  python3 -m venv .venv
  source ./venv/bin/activate

3 . Install dependencies.
  pip install pyusb pyserial ch55xtool
  sudo apt install makebin

4 . Connect the CH552 device to USB in flash mode and execute the flashing script with the corresponding example code.
   ./flash.sh blink.c

Notes

  • Make sure the virtual environment is active before flashing.
  • Executing ./flash.sh yourcode.c will compile, generate a binary, and flash the code.
  • The build files are inside the build folder.