top of page
Search

UniDAP overview and first time usage

Writer: Andre Reuter
Andre Reuter
11 minutes ago
4 min read

Getting started with a brand new UniDAP is easy and doesn't require much tools.


Freshly made UniDAPs ready for first time bootloader flashing
Freshly made UniDAPs ready for first time bootloader flashing


What is it?


The UniDAP is another debugger/programmer hardware for ARM MCUs. It's design to run standard DAPLink firmware on the STM32F103. You can find all hardware related files and more detailed description in https://github.com/Reutronix/uni-dap-v3


Many open-source hardware projects exist which already provide programming and debugging functionality with the DAPLink firmware. UniDAP is a bit different. Via the same USB port, a USB to SPI/I2C interface is provided via an onboard USB hub connecting to a CH347F. The USB interface itself is galvanically isolated.


This makes the UniDAP an universal (where the "Uni" comes from) tool for debugging and bringing-up hardware without depending on first stage firmware.


Why not modifying the DAPLink firmware to expose SPI and I2C endpoints? I wanted to use the main firmware with minimal modification, so I don't need to maintain a fork and to avoid potential hardware limitations. Also, the CH347F is inexpensive and extermely flexible.


Using the UniDAP


The UniDAP project primarily serves as a low cost debugger and programmer for MCUs with SWD interface. The idea is that it costs less to build your own UniDAP than buying the standard options in the market, while getting more functionalities. To enable its core functionality the first thing to do is load it with the DAPLink firmware bootloader.


But what if budget is really tight, and this is the first debugger of the lab, how does one flashes the debugger firmware without a programmer?


That was exactly the situation I found myself in when first designing this hardware.


The STM32F103 was chosen for several reasons, it's cheap, readily available, the DAPLink project supports it for a long time, it comes in easy hand solderable packages and has good performance for this application. And it has a factory loaded UART bootloader! This is the key to solve the problem of programming without a fancy programmer.


To enter in UART bootloader mode, STM32F103's BOOT0 pin needs to be pulled high and BOOT1 low. Then USART1 can be used to program the device, using STM32CubeProgrammer, for example.


In UniDAP schematics, USART1 is connected to UART0 of the CH347F and BOOT0 pin is connected to GPIO0 (usually listed as the CTS pin). This way the first time programming of the UniDAP can be done entirely via the CH347F interface. No extra connector or wires soldered to pads needed and no extra hardware. Of course, there are exposed pads on the bottom layer connected to the MCU's SWD interface and USART1, in case one already have another UniDAP for example, and want to flash a new one via SWD.



The bottom left exposed pads on UniDAP's bottom layer connect the MCU's programming port directly.
The bottom left exposed pads on UniDAP's bottom layer connect the MCU's programming port directly.

Programming the UniDAP for the first time via the CH347F in Linux


  1. Download the drivers for the CH347 from the manufacturer's website

  2. Extract the zip file and follow the README.md guide to install the driver and dynamic library

  3. Create a new rule file, for example:

sudo nano /etc/udev/rules.d/99-ch37.rules
  1. Add the following to the newly created file:

#SUBSYSTEM=="usb", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55de", MODE:="0666" KERNEL=="ch34x*", MODE="0666"
  1. Reload the udev rules:

sudo udevadm control --reload-rules && sudo udevadm trigger
  1. Verify if your user is in the dialout group and if not run:

sudo usermod -aG dialout $USER
  1. You'll need to log out and log back in for the changes to take effect (reboot is best) and that's it! With the device plugged in, run the following to verify:

ls /dev | grep ch347

You should see ch34x_pis* devices in the output.


If you've followed the manufacturer's instruction, the dynamic library which is now pasted /usr/lib can now be used to drive the GPIOs we need in order to program the UniDAP.


I'm personally much more comfortable with Python, so I'll be wrapping the library in Python using ctypes module. The following snippet can be used to toggle IO0:


import ctypes

# change for your port
port = '/dev/ch34x_pis1'

ch347 = ctypes.CDLL("/usr/lib/libch347.so")
# opening the device returns a handle used to indentify it
pid = ch347.CH347OpenDevice(ctypes.c_char_p(port.encode('utf-8')))

dir_gpio = ctypes.c_uint8(0)
dir_ptr = ctypes.pointer(dir_gpio)

gpio_data = ctypes.c_uint8(0)
ptr = ctypes.pointer(gpio_data)

ch347.CH347GPIO_Get(pid, dir_ptr, ptr)
print(f'Current IO0 state = {(ptr.contents.value >> 0) & 1}')

# Last char is GPIO level. Writing 0x0, sets CTS0 (GPIO0) to 0.
# To flash the bootloader firmware, set GPIO0 to 1, reset the interface, and write the firmware using cube programmer, for example
# Then set GPIO0 to 0 and reset interface.
ch347.CH347GPIO_Set(pid, ctypes.c_char(0x01), ctypes.c_char(0x01), ctypes.c_char(0x01))

ch347.CH347GPIO_Get(pid, dir_ptr, ptr)
print(f'New IO0 state = {(ptr.contents.value >> 0) & 1}')

After toggling IO0 to 1 and having the interface reset, the device is now in bootloader mode. Using STM32CubeProgrammer, you can download the bootloader firmware (firmware images can be found in the GitHub repository).


And that's it! After flashing the DAPLink bootloader, you can flash the interface firmware via drag and drop programming. You can find instructions on how to do it in the project's GitHub repository.





 
 
 

Comments


Commenting on this post isn't available anymore. Contact the site owner for more info.
bottom of page