Tuesday, March 5, 2024

Open source software for programming Silicon Labs microcontrollers using C2 interface

The C2 Programmer is designed for programming Silicon Labs microcontrollers over the C2 interface by the use of an AVR microcontroller with the necessary firmware and an USB to serial adapter. The software is written in JavaScript and is based on ScriptCommunicator by Stefan Zieker.

Custom open source C2 programmer

What does it do

  • Save flash memory to .bin (binary), .txt (hex format) or .hex (Intel hex) file.
  • Write an Intel hex file to flash memory.
  • Erase device option.



Why use a custom programmer when you can buy one? The reason I have started developing this software is not necessarily cost related. I could have just bought a programmer and be done with it instead of coding hours and hours, but I thought it will be a good addition for the community since being custom made it can be... customized. There are other reasons such as, maybe the commercial one is not available in your area or not in stock, or you might want to program only one or two microcontrollers and consider is not worth investing in a programmer.

Actually this is how the project started. I have an RDM-6300 RFID card reader that I thought is a writer too. Then I saw it's using the C8051F330 microcontroller from Silabs and decided to give it a try and make it also write RFID cards or at least add support for other chips. By not buying a programmer I made one that I could use in my project and also make it available for others.

Note that debugging is not supported so if you need this feature, consider buying a commercial programmer.

Theory of operation

Application on the computer instructs the firmware on an AVR microcontroller on what commands to send to the C2 interface of the programmed device. The communication between computer and programming device (the AVR) is done using an USB to serial converter. 

C2 programmer diagram

The application is build on top of ScriptCommunicator which is a scriptable cross-platform data terminal that supports serial port (RS232, USB to serial), UDP, TCP client/server, SPI, I2C, and CAN. Script Communicator it's an awesome application that unfortunately is not that well known. The best part is that the interface can be made to look how you want by using the Qt Designer included with the app.

How to program a microcontroller over C2 interface

Silicon Labs microcontrollers can be programmed by using a bootloader over UART or via the C2 interface. Both methods need 2 pins. What I like about the C2 interface method is that you don't need a bootloader that takes space on the flash memory.

Hardware and C2 interface pins

C2 interface of the programmed microcontroller has two pins: C2CK (clock) and C2D (data). By default these pins are mapped to the AVR pins as follows: C2CK to PC1 and C2D to PC0. Pin numbers and port can be changed inside C2.h file.

Power Supply: many Silabs microcontrollers are 3.3v devices so do not apply 5V on VDD. However the Reset and GPIO pins are 5v tolerant. Consult the datasheet first. If you can, use 3.3v for programmer (AVR) and programmed device, or 3.3v for programmed device and 5v for AVR if the Silabs microcontroller can handle 5V on the GPIO pins.

AVR clock frequency: Silabs devices are set to use the internal 24MHz oscillator during C2 initialization for faster read/write speeds so the AVR should have an external 16MHz crystal oscillator. At 16MHz the datasheet recommend using a power supply of 5V. Provided that all devices from Silicon Labs are 5v tolerant, then powering the AVR from 5v is not an issue.

C2 in-system programming: if you have external things that can pull the C2D and/or C2CK pins high or low during programming, then you need to use isolation resistors as shows in this application note: AN124: Pin Sharing Techniques for the C2 Interface.

UART interface: the TX and RX pins of the programmer needs to be connected to a USB to serial adapter. This can be an external module or a custom compact board can be created with everything on the same board. The code is set to use the UART0 peripheral.

Flash and RAM requirements: the AVR microcontroller needs to have at least 7k of flash memory and 370 bytes of RAM when UART TX and RX buffers are set to 64 bytes in size. Or 6.7k and 180 bytes of RAM when the buffers are 16 bytes in size each.

UART TX and RX buffers: the size in bytes should be equal or greater to the size of data length record of the Intel hex file (more on this later). From my experience both Simplicity Studio and Microchip Studio output Intel hex files with 16 bytes per record for compatibility reasons. This programmer adapts to any data lengths up to 255. Having more bytes per record increases the speed but from what I know you can not make Simplicity Studio use larger data lengths than 16 bytes. By default the buffers are set to 64 but if you need to shave some RAM you could set them to 16 or 32.

Script Communicator app

The C2 Programmer is based on ScriptCommunicator, that can be downloaded from these links:



Extract the zip archive to any location.

C2 Programmer GUI

The application can be opened using C2 Programmer.sce which will launch the Script Communicator. First time you need to select Open with then More apps then Look for another app on the PC and select the ScriptCommunicator.exe from the folder where you unzipped the application. This ndeds to be done only once if you select to always use this app to open .sce files.

C2 programmer GUI

Connecting to programmer is done by selecting the port from the COM port list then press Connect button. The baud rate is set to 115200 and cannot be changed in GUI only in software since I believe this is a good serial transfer rate. But if you wish to change the serial settings, the application settings should match the ones in the firmware loaded on the AVR.

After the serial port in active, the programmer will send a signature to the interface and if it is recognized then the initialization procedure continues with reading Device ID and device Revision ID. The device in this case is the programmed device - the Silabs microcontroller. The interface finds the microcontroller family based on the device ID. Knowing what type of microcontroller is, is very important since many parameters differs from one family to another. After the programmed device has been identified, it is considered ready to accept instructions.

The Max Flash Memory Address is a list with top valid addresses in hex format for different microcontrollers. Reading past this address will result in an error. The maximum address can be found in the datasheet in the Flash memory section.

This is only used when reading flash memory to a file.

Saving flash memory to file

Start and end address can be used to read the whole memory or just a section. The type of file extension can be: bin, txt or hex.

.bin file: raw integer bytes are saved in a binary file. The file can be viewed in hex using an application like HxD.

.txt file: a text file that can be viewed in Notepad. Each byte is represented in hex format with spaces between them.

.hex file: flash is saved in Intel hex format with 16 bytes data length for compatibility reasons. The parameter can be changed in the JavaScript file. Detailed information about the Intel HEX file format can be found here: https://developer.arm.com/documentation/ka003292/latest/.

Writing flash memory from file

Only Intel HEX file format is supported at the moment. The data size can be 16, 32, 64, 128 bytes since the code will adapt to the detected size. 

C2 Programmer as an USB to Serial

Since the C2 programmer already needs an USB to serial adapter, it is preferred to use the same serial adapter to communicate with the target device (the SiLabs microcontroller). For this purpose, I have implemented the 'Programmer Mode' function that when is set to 'Serial', the programmer will ignore data over serial line.

Data sent from SiLab device over UART must end in '\n' character to be displayed in the console in Serial mode.

Note that this feature is experimental and will not work in all cases. When the programmed device uses the TX and RX pins too often, the programming will fail since both devices cannot use the UART at the same time. It will work only when the programmer manages to receive the command when UART line is idle.

Connecting the pins

Programmer and target device have the TX and RX pins connected in parallel: TX to TX and RX to RX. Both can receive so no issues here. But both cannot send since the TX pins are output pins and they can short each other. Each pin (RX and TX) of the SiLabs microcontroller must be connected to the AVR TX and RX pins through 2.2k resistors. Value is not that critical. Although the RX pin is an input is still better to use a resistor in case the UART on target device is not configured and pins are connected in reverse.

Programmer Mode - Serial

When this mode is selected, the programmer's firmware ignores everything on the UART and disables it's TX pin so that the target device can use the TX pin.

Programmer Mode - Programming

Programmer is set back to default mode of operation and target device cannot transmit over UART.

The workflow

The idea is, you use the Simplicity Studio to compile the code and generate the hex file. Point the application to the hex file. Load the hex file to the microcontroller. After the path to the hex file is set, the interface will not prompt you for it each time you press the button, but instead will just write the flash. This is for convenience. If you wish to flash using another file, just disconnect the serial port using the button and reconnect it again so the file path is erased and you will be prompted again to choose the file.

The C2 Interface

It is not necessary to know how C2 interface works to be able to use the application, however I will cover the basics for those interested.

The C2 interface is a proprietary 2-wire serial interface used to program and debug SiLabs microcontrollers. These two pins are:

  • C2CK / Reset - the clock signal generated by the programming device. This pin is shared with the Reset functionality. If the pin will be low for more than 20us then the device will be reset. When used as a C2CK, the pin should not be held low for more than 5us.
  • C2D / GPIO - bidirectional data line. When C2 is idle, the pin state is defined by the user and it works as a GPIO pin. When C2 is active, the pin is set as high impedance input by the target device and the programmer sets the state as high or low as the transmitted data dictates. When C2 interface sends data back to the programmer, the roles are reversed, now the target device has C2D set to output and programmer to input mode.

C2 Interface (C2I) is used to communicate with the Programming Interface (PI) that can access the Flash or EPROM. Here is a diagram of the internal structure.

If you wish to know more about the C2 interface, there is an application note from SiLabs that covers all the details: AN127: Flash Programming via the C2 Interface.

Increasing serial transfer rate by adjusting Latency Timer

Serial communication speed can be greatly increased just by lowering the latency time value. This works on a Windows operating system, so I'm not sure about others.

To change the latency timer, open Device Manager by right clicking on the lower left corner on the screen. If the USB to serial is connected, it will be listed under Ports (COM & LPT). Right click on it and select Properties.

Increasing serial transfer rate in Windows

Under Port Settings tab click on Advanced...

Changing latency on serial port

Finally select a value for Latency Timer of 6 or 8 ms.

Decreasing latency time for serial port in Windows

Using a logic analyzer I noticed 20 ms or so, of dead times after the microcontroller was sending a response to the application and the data being received from Windows driver. After lowering the latency time the programming speed increased visibly since it just waited n ms doing nothing for each block of bytes. From my understanding, after the operating system serial driver receives some data, it is stored in a buffer and is delivered to the listening application only after the latency time expires. Is like someone is talking and you wait a certain amount of silence before replying to ensure the person finished saying whatever they were saying.

What I had to learn to be aware of when listening to responses from the programmer in script, is that with a lower latency the data won't be received all at once. For example if the programmer was sending 'OK', many times only 'O' would be received so the logic must know until when to buffer the data and to clear the buffer. In this example you need to store received bytes until 'OK' was received then take action and clear the buffer.

Although the software is free, you can donate any amount if you would like so, at paypal.me/alientransducer.


v1.0 C2 Programmer Folder can be downloaded as a zip file. Includes all the neccesary files: firmware for AVR, GUI application and UART library.
v1.0 05-03-2024:
- release date.

No comments:

Post a Comment