From Arduino to RTOS

Hi Manny. I’m in Canada at the moment, but when I get back to the UK, I’ll check out the latest version.

Thanks.

I recommend considering STM32 seriously for this and future project. Wire range of MCU, extensive community support, good prices, and affordable hardware debuggers.

https://docs.platformio.org/en/latest/platforms/ststm32.html#frameworks

You can start for example playing with one of the inexpensive ‘black pill’ STM32F401 or SMT32F411 modules https://www.amazon.com/dp/B0B68N34S4 . For hardware debugger search for st-link v2, even the originals are affordable.

With proper design, even a non blocking single thread sketch can be very powerful, but there are RTOS’s available such as Zephyr.

https://docs.platformio.org/en/latest/platforms/ststm32.html#frameworks

Thanks for your thoughts. I am not very expierenced with STM32 mcus. I see two problems. The amount of hardware is overwhelming and wifi/bt is harder to add.
In addition, the project is currently built with Arduino framework and I would like to run the code on ne new platform without changes. Would this be possible?
I am working alone on this project, so I won’t be able to Port all the libraries to the new RTOS.

You are mentioning zypher. I have not used it yet, but I neared of it. What is about CubeIDE? Is this a framework or just an IDE? I would like to stick with pio. What is with Mbed os? I’ve read recently that it’s not very good?

I’ve done first tests with ESP32 and at least it’s possible to combine stuff (threads) from freeRTOS and still using the Arduino framework.
Would something similar possible with STM32?

I am going to build a custom board based on the new controller. Are there advantages or disadvantages when using STM32 or esp32?

Thanks for your input!

If you need WiFi or BT, I would consider ESP32 over STM32. Both have low cost hardware debugger which I consider a must for myself. Also, sticking with platformio is a good approach, and is what I am doing.

Platformio docs tell you what frameworks it supports for each architecture. If you switch to use an RTOS, you need to make sure to have thread safe code, e.g. protecting common resources with synchronization elements. This is something that you don’t need to worry about in a loop() style programming.

I recently completed a similar project, custom ESP32 board, platformio, and some usage of FreeRTOS. In my case, I picked the espidf framework over Arduino, with is the standard ESP32 SDK, without the Arduino abstractions.

Thanks for your thoughts and sharing your project.
It’s very interesting to see how you solved it. It should be a good guidance for me, as it’s similar to my project.

I do currently no use wifi/bt and it’s not absolutely needed. There are a few situations where it makes sense and would help to ease the process. I still would like to have it on board, to make the project future-proof. There are for sure, a few use cases I haven’t thought about, where I can use it.
Would you still go for ESP32 or use a STM32 and add an external wifi/bt chip to my schematics?
The downside of wifi/bt is, that the implementation is huge. Once enabled, I’ll loose 2/3 of the available memory on ESP32.

All my tests with ESP32 are based on espidf framework.
I am primarily keen on threading, as this is the biggest downside currently for me when only relying on Arduino framework.
I do not like, that it’s C based. I would prefer C++. I know it’s possible to write C++, but there were a few where I had (smaller) problems.

As I said, I would like to combine espidf with Arduino framework to keep my current code compatible.
I do not have the knowledge and resources to re-write every single library I am using to get rid of the Arduino layer.

My biggest concerns are about the graphics library.
I am currently using ILI9341_due lib, because it is supporting DMA (my current board is based on Arduino Due).
I looked into LVGL and the results are looking great. I was also able to setup a test project with a simulator, but didn’t manage to make it work with the actual hardware.
I am using displays with ILI9341 or ST7789 controller (240x320px) and I am not sure, if I need to write the driver for it. I hadn’t time yet to dig deeper into this, yet …

I wouldn’t add bt/wifi to an STM32, and would go with an ESP32 instead. The ESP32 is also better supported on platformio with threading out of the box (use the espidf framework). I am struggling now with setting a platformio STM32 project with FreeRTOS, and had to go through a bunch of workarounds.

As for LVGL, you may need to develop a driver but you can find examples on the internet. The driver is relatively simple and is primarily a function that renders a given rectangular area of the screen with pixels that are provided in a buffer. It doesn’t need to deal with primitives such as draw line or draw circle.

Regarding Arduino code, I saw this but didn’t play with it yet. STM32duino FreeRTOS - Arduino Reference . Potentially you can have STM32 Arduino that also have threading. Not sure how good it is.

1 Like

One thing that I learned after two weeks of struggling. If you want to use STM32 with FreeRTOS and files generated from a Cube IDE .ioc file, the way to go is baremetal (no fraemwork) rather than framework=stm32cube.

Discussion here

Example here

I am using a small shell script to update the platformio project with new files generated in the Cube IDE. There are some tweaks to do such as -I for the include files and replacing main.c and freertos.c with your own main files but much less frustration, so far, than with framework = stm32cube.

This is the script I use to update the baremetal platformio project with changes in the files generated by the cube ide project.

#!/bin/bash -x

dst="../platformio-baremetal"

rm -r $dst/lib/Core
cp -r Core $dst/lib/Core

# Patch Core related stuff
mv  $dst/lib/Core/Src/freertos.c  $dst/lib/Core/Src/freertos.c.ignored
mv  $dst/lib/Core/Src/main.c  $dst/lib/Core/Src/main.c.ignored

rm -rf $dst/src/startup
mv $dst/lib/Core/Startup $dst/src/startup

rm -r $dst/lib/Drivers
cp -r Drivers $dst/lib/Drivers

rm -r $dst/lib/Middlewares
cp -r Middlewares $dst/lib/Middlewares

rm -r $dst/lib/USB_DEVICE
cp -r USB_DEVICE $dst/lib/USB_DEVICE

cp STM32H750VBTX_FLASH.ld  $dst/STM32H750VBTX_FLASH.ld

And my platformio.ini looks like this

[env:weact_mini_h750vbtx]
platform = ststm32
board = weact_mini_h750vbtx
build_type = debug
debug_tool = stlink
upload_protocol = stlink
debug_build_flags = -O0 -ggdb3 -g3
board_build.ldscript = STM32H750VBTX_FLASH.ld
lib_archive = no
lib_deps = 
  Core
  Drivers
  Middlewares
  USB_DEVICE
build_flags =
  -mfpu=fpv4-sp-d16 
  -mfloat-abi=softfp  -Wl,-Map,${BUILD_DIR}/firmware.map
  -mthumb 
  -D debug
  -D USE_HAL_DRIVER
  -Ilib/Core/Inc
  -Ilib/Core/ThreadSafe
  -Ilib/Drivers/CMSIS/Device/ST/STM32H7xx/Include
  -Ilib/Drivers/CMSIS/Include
  -Ilib/Drivers/STM32H7xx_HAL_Driver/Inc
  -Ilib/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc
  -Ilib/Middlewares/ST/STM32_USB_Device_Library/Core/Inc
  -Ilib/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS
  -Ilib/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/Include
  -Ilib/Middlewares/Third_Party/FreeRTOS/Source/include
  -Ilib/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F
  -Ilib/USB_DEVICE/App
  -Ilib/USB_DEVICE/Target

Thanks. I think ESP32 is not a too bad choice.
I’ll try to develop a prototype … :grinning:

I really appreciate your detailed insights in your projects and your progress and thoughts.

I recommend having a hardware debugger. It makes things much simpler. For ESP32, this one works great for me Amazon.com (cost $28 about 6 months ago).

Good point! Thanks for pointing this out. It’s actually something I haven’t considered yet.
But I totally agree. I need an easy solution for debugging, especially during the initial phase of development.

For my better understanding: Is it possible to debug through USB or do I have to connect via JTAG or something similar?
I do have the Atmel ICE debugger for my current custom Arduino Due compatible board.
But It’s not very handy as I have to open the enclosure and the connection is not too stable.

Do you recommend including the debugger in my schematics or is this typically an external tool, I’ll connect when necessary?
Placing these components makes the production board only more expensive, as it is (hopefully) usually not used. Though, when problems occur, it can be helpful if it’s onboard…

Yes, it needs to be jtag, such that the debugger has full control over the MCU. I suggest including it in the design, and then you have the option to populate only a few development units though, those connectors are inexpensive. For example, if you are using JLCPCB SMD service to assemble your boards you can use this one PZ127VS-12-10-H10-A38 | XFCN | Pin Headers | JLCPCB , and the electrical are here ble_stepper_motor_analyzer/stepper_monitor.pdf at main · zapta/ble_stepper_motor_analyzer · GitHub .

I also recommend adding the standard ESP32 DTR/RTS circuit because it will simplify reflashing the boards via the USB port (not related to the jtag debugger, user in the field or when you develop without the debugger).

Thanks for your amazing guidance! It’s really helpful!
Yes indeed, I am planning to use the JLCPCB assembling service. I am also currently designing the schematics with EasyEDA due to this reason. As you might have noticed, I am no expert in electronic engineering, but it feels like a solid toolchain :wink:

I have an older STM32 development board and as far as I remember it was possible to debug through the USB connection as the debugger was on this board.
Would this be possible with ESP32, too? If I got you right, I need the JTAG connector on my board and in addition also the ESP32 Prog board for debugging, right?

I was not aware, that DTR/RTS are necessary for flashing - thanks!
My current design offers only a pin header where I can plugin the ESP32 DevKit board. In the first step, I want to bring all sensors and accessories together and see if it’s working.

Once it is running, I will try to replace the DevKit with a custom ESP32 design…
So for the current prototype flashing is not a problem, but for the next gen it will be important :slight_smile:

Though, I should add the JTAG connector for debugging, as it is not available on the DevKit afaik.

EasyEDA makes it simpler to order from JLCPCB because you don’t need to deal with things like position and BOM files and possible mismatches. BTW, my schematic has the JLCPCB part number next to each part so it may help you find useful parts. ble_stepper_motor_analyzer/stepper_monitor.pdf at main · zapta/ble_stepper_motor_analyzer · GitHub

The STM32 board you had may be one of the ST dev boards that in addition to the STM32 device also has STLink V2 debugger https://www.st.com/resource/en/data_brief/nucleo-f030r8.pdf .

You need different debuggers for the STM32 and ESP32 unless you buy a generic (expensive) debugger such as Segger. They also use different signals, ARM SWD vs JTAG. Both though have relatively inexpensive debuggers from the vendor such that you don’t need to spend hundreds of dollars.

RTS/DTS are used for the reboot sequence such that when you flush through the USB, the ESP32 enters a bootloader mode to accept the new upload. They are standard on virtually all ESP32 boards thought some boards have a too small capacitor from EN to ground (I use 2.2 us) which make the mechanism not to work reliable.

If you want, you can also solder the jtag cable to the pins of the ESP32 dev kit, for debugging on the prototype. This is how I started.

BTW, this may help you select pins to use in your project. #363 Which ESP32 pins are safe to use? - YouTube

And last thing, once you move to an RTOS, you will need of course to use synchronization when multiple tasks access the same resource, semaphores, mutexts, queues, and so on. Single threading Arduino style has it’s advantages. :wink:

You’re right, it is the STM32L152RE dev board.
It’s handy to debug through USB.
Would it be possible to implement something similar with ESP32?

I am currently using this ESP32 DevKit v1 board: https://www.mischianti.org/wp-content/uploads/2020/11/ESP32-DOIT-DEV-KIT-v1-pinout-mischianti.png
How would I connect the JTAG to this?

The amount of different ESP32 mcu’s are overwhelming, too.
Which one would you recommend? I probably need a bunch of GPIOs.
The used dev board has actually too less pins and I workaround by combining LEDs of my buttons.

True, multithreading brings a whole new level of complexity.
The good news are, that with RTOS I can use threads, but I don’t have to :wink:
I am thinking about drawing the display or calculating a pitch angle in the background as separate threads …
I’ll have to figure it out. This probably will be a work in progress for a long time to bring the whole Arduino project to ESPIDF.

Would it be possible to implement something similar with ESP32?

I think so. You can find links to reference design and schematic at
the bottom here Introduction to the ESP-Prog Board - - — ESP-IoT-Solution latest documentation

How would I connect the JTAG to this?

Look at J5 here ble_stepper_motor_analyzer/kicad/stepper_monitor.pdf at main · zapta/ble_stepper_motor_analyzer · GitHub , you will need ground + four signals.

Which one would you recommend?

I went with the most basic one, ESP32-WROOM-32U-N4 (JLCPCB C328062). This is an external antenna version, I believe it’s ESP32-WROOM-32D. There is an identical one with an on board antenna. BTW, do you plan to run it on battery? The ESP32 in general is ‘power hungry’.

BTW, if you use the version with the onboard antenna, look at fig 16 here ESP Hardware Design Guidelines - ESP32 - — ESP Hardware Design Guidelines latest documentation on recommended and non recommended placements. It likes PCB edge on it’s ‘right’.

The good news are, that with RTOS I can use threads, but I don’t have to :wink:

You are right. It gives you opportunities to the future.

Thanks for all the detailed information.
I’ll have a closer look to the debugging problem. Including a custom ESP-Prog board would be an option. It’s still not completely clear to me how to use USB for UART and add debugger to the same port.

I am afraid, I do not have 4 signals left.
Need to figure it out, if and how I could use it. Anyhow, thanks for pointing this out :slight_smile:

I probably will use an onboard antenna. Wifi/BT will only be necessary for configuration and not during operation. So it will be more convenient and at least not a hard requirement for now. But as I said, I want the hardware to be future proof and wireless connectivity is probably useful for new use cases :wink:
Thanks for pointing out the design guidelines. I noticed, that the antenna on all dev boards I’ve seen is on the edge, so I assumed there are some rules :slight_smile:
Currently I have a few use cases when I connect the device to a smartphone via USB cable. This is only possible with Android for now, but I would love to make it iOS compatible via BT …

Yes, it’s a portable device and will be driven by a battery.
Currently I am using a 2400mAh LiPo. I was searching for a comparison of power consumption, and as far as I remember the ESP32 was at least not worse than the Arduino Due.
Unfortunately, I do no longer have the sources …
Now knowing it will be running on battery, would you recommend another MCU?

When I plug the debugger to the computer, I get two new devices in the device manager

image

Then in the Zadig tool I see them as 0 and 1 and the debugger instructions tell you to configure interface 0 one as WinUsb and leave interface 1 as a COM device. I guess that interface 1 is the serial port you are looking for and that the FTDI ic has rx/tx pins for that interface. Never seen anybody doing it but I think it’s a great idea if it works, an ESP32 board with builtin hardware debugger,a single USB connector, and seamless integration with platformio.

Interesting.
I am working on macOS, but I do see a similar behavior for my AVR programmer.
I am using the AVR programmer for flashing the 16u2 IC of my current board, which acts as USB to UART bridge.
I’ve built a customer firmware to avoid resetting the main MCU, when connecting.
On Windows this can be prevented with the RTS signal, if I remember correctly. But on macOS it always resets…

I never used the other port. Was always wondering what it is for :wink:
If I got you right, then one port is the standard USB/UART interface and the other is the programming port/jtag port.

This is definitely something I would like to build :slight_smile:
Hope I can make it work …
Still working on my schematics for the first prototype with the ESP32 DevKit. :wink:

When I connect the ESP32 programmer/debugger to a Mac I see these two new ports, so I presume the situation is similar to Windows.

/dev/cu.usbserial-1200
/dev/tty.usbserial-1200
/dev/cu.usbserial-1201
/dev/tty.usbserial-1201

On Mac I don’t need to manually reset the ESP32 when uploading. Platform IO uses esptool and it’s was designed to use the DTR/RTS trick. I think this is the same with the Arduino IDE which also uses the esptool. On my custom ESP32 board, I don’t even have a reset button or boot button. Never needed them.

https://docs.espressif.com/projects/esptool/en/latest/esp32/advanced-topics/boot-mode-selection.html

Sorry, I was talking about Arduino Due.
As far as I know, the Due is kind of special as there is a magical baud rate of 1200 to bring the device in the programming mode. In that case, the Due will reset. One can prevent this behavior on Windows by suppressing the RTS signal, but on macOS (I even think on unix systems) it’s not possible due to the driver implementation.
That’s why I implemented a workaround. The controller does no longer reset when connecting with baud rate 1200. In addition I introduced another magical baud rate of 1800 to force a reset.

Typically on a Due it does not stand out, as the board is powered on as soon as the USB cable is plugged in. On my custom board, I do have a different schematic as I do not want to power the device on, while charging …

Anyhow, didn’t want to make it more complex :wink:
Just wanna say, that the AVR programmer also pops up as two usb devices :slight_smile:

1 Like