Everyone should be using the STM32CubeIDE as opposed to something like Arduino. It’s a full on professional IDE, it is completely free, and it is supported by ST. But most importantly, it supports JTAG debugging with trivially cheap extra HW ($15), which makes all the difference.
I was going to do a YouTube to show how to use the STM32CubeIDE with Daisy, but it turned out to be complicated. But it is so easy to get started let me try to describe it here.
After you get the IDE from ST and install it and bring it up the first time, there will be a welcome screen. You can close that and go to the Project Explorer window. Here it will ask you what type of project you want to create.
Select this:

Then click the browse button to go to an example project (example DaisyExamples/pod/SimpleOscillator). Select that folder. Type the project name into the text box. Make sure to select the MCU ARM GCC toolchain. Click Finish.
You should now be able to open that folder, and you can right click on it and say Build Project. It’s that simple. The reason this works is because there are already a working makefiles in the example folder. It’s also possible to set up projects to use the native Eclipse system, which might be more intuitive in the long run, but this gets us started with the examples, and as long as one is willing to update the makefiles as a project changes, it works fine
To debug, make sure you have hooked up the debug HW and power to the Daisy. Then find the little bug icon in the toolbar, click the little triangle to the right. Select Debug As, then STM32 C/C++ application. A configuration dialog will pop up, you can just say OK.
It will take a bit to load the program, but when it does, it should halt right inside “main”, and now you are driving a professional Dev system.
There is a ton to learn about it, but it will do everything you want, finding code definitions, displaying local variables (if they aren’t optimized out) all the good stuff. It’s worth learning in depth, but getting started is simple
Here are links to the dev HW:
https://www.digikey.com/en/products/detail/stmicroelectronics/STLINK-V3MINIE/16284301?utm_adgroup=&utm_source=google&utm_medium=cpc&utm_campaign=PMax%20Shopping_Product_Low%20ROAS%20Categories&utm_term=&utm_content=&utm_id=go_cmp-20243063506_adg-_ad-__dev-c_ext-_prd-16284301_sig-Cj0KCQjwwO20BhCJARIsAAnTIVRvlakozoerkfrFGk47nmI5_mDLS4Z5pbHfUs-Jt6ZHdPW9ytuqHNAaAuRhEALw_wcB&gad_source=1&gbraid=0AAAAADrbLlispVvaNN_UnDN144SFfwXRR&gclid=Cj0KCQjwwO20BhCJARIsAAnTIVRvlakozoerkfrFGk47nmI5_mDLS4Z5pbHfUs-Jt6ZHdPW9ytuqHNAaAuRhEALw_wcB
https://www.digikey.com/en/products/detail/olimex-ltd/ARM-JTAG-20-10/3471401?utm_adgroup=&utm_source=google&utm_medium=cpc&utm_campaign=PMax%20Shopping_Product_Low%20ROAS%20Categories&utm_term=&utm_content=&utm_id=go_cmp-20243063506_adg-_ad-__dev-c_ext-_prd-3471401_sig-Cj0KCQjwwO20BhCJARIsAAnTIVRZR-Yu0SHPMTJ6m0M3i5-KXJF26bgO_EW7ctLJD3W6xHoLq_rT9-0aAj94EALw_wcB&gad_source=1&gbraid=0AAAAADrbLlispVvaNN_UnDN144SFfwXRR&gclid=Cj0KCQjwwO20BhCJARIsAAnTIVRZR-Yu0SHPMTJ6m0M3i5-KXJF26bgO_EW7ctLJD3W6xHoLq_rT9-0aAj94EALw_wcB
2 Likes
What’s the advantage over VS Code? Both can debug with STLINK.
And how is that JTAG adapter relevant in the Daisy context?
2 Likes
Eh, I just wrote a python script with a gui that does it for me after frustrations. Place it in your project folder and it takes care of the rest.
import sys
import os
import subprocess
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QLabel
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QClipboard
class DFUProgrammer(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle('DFU Programmer')
self.setGeometry(100, 100, 400, 300)
layout = QVBoxLayout()
self.label = QLabel('No .bin file found in build directory', self)
self.label.setAlignment(Qt.AlignCenter)
layout.addWidget(self.label)
self.program_button = QPushButton('Program', self)
self.program_button.setEnabled(False)
self.program_button.clicked.connect(self.program_dfu)
layout.addWidget(self.program_button)
self.clean_button = QPushButton('Clean Build', self)
self.clean_button.clicked.connect(self.clean_build)
layout.addWidget(self.clean_button)
self.build_button = QPushButton('Build', self)
self.build_button.clicked.connect(self.build)
layout.addWidget(self.build_button)
self.copy_button = QPushButton('Copy', self)
self.copy_button.clicked.connect(self.copy_to_clipboard)
layout.addWidget(self.copy_button)
self.setLayout(layout)
def find_bin_file(self):
directory = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'build')
if os.path.isdir(directory):
for file in os.listdir(directory):
if file.endswith('.bin'):
return os.path.join(directory, file)
return None
def program_dfu(self):
self.bin_file_path = self.find_bin_file()
if self.bin_file_path:
directory = os.path.dirname(self.bin_file_path)
command = f'dfu-util -a 0 -s 0x08000000:leave -D {os.path.basename(self.bin_file_path)}'
try:
result = subprocess.run(command, cwd=directory, shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
self.label.setText(f'Programming successful:\n{result.stdout.decode()}')
except subprocess.CalledProcessError as e:
self.label.setText(f'Error:\n{e.stderr.decode()}')
else:
self.label.setText('No .bin file found in build directory')
self.program_button.setEnabled(False)
def clean_build(self):
self.run_make_command('make clean')
def build(self):
self.run_make_command('make')
def run_make_command(self, command):
directory = os.path.dirname(os.path.abspath(__file__))
try:
result = subprocess.run(command, cwd=directory, shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
self.label.setText(f'{command} successful:\n{result.stdout.decode()}')
if command == 'make':
self.bin_file_path = self.find_bin_file()
if self.bin_file_path:
self.label.setText(f'Selected file: {os.path.basename(self.bin_file_path)}')
self.program_button.setEnabled(True)
else:
self.label.setText('No .bin file found in build directory')
self.program_button.setEnabled(False)
except subprocess.CalledProcessError as e:
self.label.setText(f'Error during {command}:\n{e.stderr.decode()}')
def copy_to_clipboard(self):
clipboard = QApplication.clipboard()
clipboard.setText(self.label.text())
if __name__ == '__main__':
app = QApplication(sys.argv)
window = DFUProgrammer()
window.show()
sys.exit(app.exec_())
This post was mainly directed at folks who are using something like Arduino and so don’t have access to a proper debug environment. VScode is fine. But I do find the Eclipse based STM32CubeIDE superior to VScode for debug and C++ code development. But VScode with ST-Link is similar.
And technically it isn’t JTAG debugging, it’s SWD debugging, so you are right about that. But it is debugging based on a hardware debug probe.
@ryan_pwm I’m not sure what this has to do with my post. My post was about a development and debug environment, not a DFU tool
Then the link to the JTAG cable seems irrelevant.
I had to buy that cable as my ST-link didn’t come with one. Are you saying that the other ST-link that I linked comes with a cable with that smaller connector?
I’ve got 3 STLINK, 2x mini, 1x mini-e. I know the ones I got from ElectroSmith came with cables. I think the one I got from Mouser came with cable, but now I’m not certain.