Month: July 2024

Creating two USB CDC/ACM interfaces on NuttX

It is hard to get the USB Composite creating two USB/Serial interfaces when you aren’t expert in USB protocol, but after some tinkering I was able to get it working:

[28670.308677] usb 3-5: new full-speed USB device number 32 using xhci_hcd
[28670.459397] usb 3-5: New USB device found, idVendor=03eb, idProduct=2022, bcdDevice=10.10
[28670.459409] usb 3-5: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[28670.459413] usb 3-5: Product: Composite device
[28670.459416] usb 3-5: Manufacturer: NuttX
[28670.459419] usb 3-5: SerialNumber: 0101
[28670.463882] cdc_acm 3-5:1.0: ttyACM0: USB ACM device
[28670.464175] cdc_acm 3-5:1.2: ttyACM1: USB ACM device

Basically I modified the rp2040_composite.c to register the CDC/ACM twice, changing:

dev[n].devinfo.ifnobase = 0;
dev[n].minor = 0;

for the first interface and:

dev[n].devinfo.ifnobase = 2;
dev[n].minor = 1;

for the second interface!

The complete modification for future reference:

diff --git a/boards/arm/rp2040/common/src/rp2040_composite.c b/boards/arm/rp2040/common/src/rp2040_composite.c
index 9b059f48fe..e00c9d2794 100644
--- a/boards/arm/rp2040/common/src/rp2040_composite.c
+++ b/boards/arm/rp2040/common/src/rp2040_composite.c
@@ -250,7 +250,7 @@ void *board_composite_connect(int port, int configid)
 
       /* Interfaces */
 
-      dev[n].devinfo.ifnobase = ifnobase;             /* Offset to Interface-IDs */
+      dev[n].devinfo.ifnobase = 0;                    /* Offset to Interface-IDs */
       dev[n].minor = 0;                               /* The minor interface number */
 
       /* Strings */
@@ -259,12 +259,45 @@ void *board_composite_connect(int port, int configid)
 
       /* Endpoints */
 
-      dev[n].devinfo.epno[CDCACM_EP_INTIN_IDX]   = 3;
-      dev[n].devinfo.epno[CDCACM_EP_BULKIN_IDX]  = 4;
-      dev[n].devinfo.epno[CDCACM_EP_BULKOUT_IDX] = 5;
+      dev[n].devinfo.epno[CDCACM_EP_INTIN_IDX]   = 1;
+      dev[n].devinfo.epno[CDCACM_EP_BULKIN_IDX]  = 2;
+      dev[n].devinfo.epno[CDCACM_EP_BULKOUT_IDX] = 3;
       n++;
 #endif
 
+#ifdef CONFIG_CDCACM_COMPOSITE
+      /* Configure the CDC/ACM device */
+
+      /* Ask the cdcacm driver to fill in the constants we didn't
+       * know here.
+       */
+
+      cdcacm_get_composite_devdesc(&dev[n]);
+
+      /* Overwrite and correct some values... */
+
+      /* The callback functions for the CDC/ACM class */
+
+      dev[n].classobject  = cdcacm_classobject;
+      dev[n].uninitialize = cdcacm_uninitialize;
+
+      /* Interfaces */
+
+      dev[n].devinfo.ifnobase = 2;                    /* Offset to Interface-IDs */
+      dev[n].minor = 1;                               /* The minor interface number */
+
+      /* Strings */
+
+      dev[n].devinfo.strbase = strbase;               /* Offset to String Numbers */
+
+      /* Endpoints */
+
+      dev[n].devinfo.epno[CDCACM_EP_INTIN_IDX]   = 4;
+      dev[n].devinfo.epno[CDCACM_EP_BULKIN_IDX]  = 5;
+      dev[n].devinfo.epno[CDCACM_EP_BULKOUT_IDX] = 6;
+      n++;
+#endif
+       //
       return composite_initialize(composite_getdevdescs(), dev, n);
     }
   else

I configure to use the composite board profile:

$ ./tools/configure.sh raspberrypi-pico:composite

And removed the USB MSC support (to let only USB CDC/ACM).

Unsecuring S32K146 using JLink

J-Link>con
Please specify device / core. <Default>: ATSAMD51P19A
Type '?' for selection dialog
Device>S32K146
Specify target interface speed [kHz]. <Default>: 4000 kHz
Speed>
Device "S32K146" selected.


Connecting to target via SWD
InitTarget() start
SWD selected. Executing JTAG -> SWD switching sequence.

Device will be unsecured now.
InitTarget() end - Took 19.4s
Found SW-DP with ID 0x2BA01477
DPv0 detected
CoreSight SoC-400 or earlier
Scanning AP map to find all available APs
AP[2]: Stopped AP scan as end of AP map has been reached
AP[0]: AHB-AP (IDR: 0x24770011)
AP[1]: JTAG-AP (IDR: 0x001C0000)
Iterating through AP map to find AHB-AP to use
AP[0]: Core found
AP[0]: AHB-AP ROM base: 0xE00FF000
CPUID register: 0x410FC241. Implementer code: 0x41 (ARM)
Found Cortex-M4 r0p1, Little endian.
FPUnit: 6 code (BP) slots and 2 literal slots
CoreSight components:
ROMTbl[0] @ E00FF000
[0][0]: E000E000 CID B105E00D PID 000BB00C SCS-M7
[0][1]: E0001000 CID B105E00D PID 003BB002 DWT
[0][2]: E0002000 CID B105E00D PID 002BB003 FPB
[0][3]: E0000000 CID B105E00D PID 003BB001 ITM
[0][4]: E0040000 CID B105900D PID 000BB9A1 TPIU
[0][5]: E0041000 CID B105900D PID 000BB925 ETM
Initializing 126976 bytes work RAM @ 0x1FFF0000
Reset: Halt core after reset via DEMCR.VC_CORERESET.
Reset: Reset device via AIRCR.SYSRESETREQ.
Memory zones:
  Zone: "Default" Description: Default access mode
Cortex-M4 identified.
J-Link>

Compiling Cura on Ubuntu 22.04

UPDATED: I discovered that this procedure only install the Documentation, Cura moved from CMake to conan, you can install it thi way: https://github.com/Ultimaker/Cura/wiki/Running-Cura-from-Source

I decided to compile Cura 5 on Linux (I don’t like these AppImage files, too slow, lot of duplication, etc).

So, after downloading it, I created a build directory inside the source file, enter inside this directory and ran “cmake ..”.

Unfortunatelly I was getting this nasty error:

CMake Error at cmake/thirdpartydeps.cmake:54 (MESSAGE):
  Cannot find plib header files
Call Stack (most recent call first):
  src/libs/tgfclient/CMakeLists.txt:13 (ADD_PLIB_INCLUDEDIR)


-- Configuring incomplete, errors occurred!
See also "/home/alan/Downloads/Cura-5.3.1/CMakeFiles/CMakeOutput.log".
See also "/home/alan/Downloads/Cura-5.3.1/CMakeFiles/CMakeError.log".

Fortunately the solution was here: https://sourceforge.net/p/speed-dreams/discussion/865036/thread/7e2ee9af/

Not exactly, because “cmake -i” is no log supported, but it gave me a hint, and then I did it:

$ cmake -DPLIB_INCLUDE_DIR=/usr/include/plib ..

Creality K1C with Klipper firmware and mainsail

I got this step error:

8:02 PM
[CLEAR_NOZZLE_QUICK] end_pos[2]:2.9989062500000028
8:02 PM
[CLEAR_NOZZLE_QUICK] src_pos[2]:3.1710085227272966
8:01 PM
Run Current: 0.56A Hold Current: 0.56A
8:01 PM
y_park = 104.5
8:01 PM
x_park = -104.5
8:01 PM
x_axes: xyz
8:01 PM
x_axes: xyz
8:01 PM
wait temp end
8:01 PM
File selected
8:01 PM
File opened:3DBenchy.gcode Size:3135094
7:58 PM
{'code': 'key526', 'msg': 'PR_ERR_CODE_HAVE_LOST_STEP: Z-axis motor step loss was found.', 'values': ['RUN_G29_Z check last point res_z:(0.8845624999999828) out of lost_step_dis:0.5']}
7:58 PM
{'code': 'key526', 'msg': 'PR_ERR_CODE_HAVE_LOST_STEP: Z-axis motor step loss was found.', 'values': ['RUN_G29_Z check last point res_z:(0.8845624999999828) out of lost_step_dis:0.5']}
7:58 PM
{'code': 'key526', 'msg': 'PR_ERR_CODE_HAVE_LOST_STEP: Z-axis motor step loss was found.', 'values': ['RUN_G29_Z check last point res_z:(0.8845624999999828) out of lost_step_dis:0.5']}
7:58 PM
[RAISE_ERROR]{'code': 'key526', 'msg': 'PR_ERR_CODE_HAVE_LOST_STEP: Z-axis motor step loss was found.', 'values': ['RUN_G29_Z check last point res_z:(0.8845624999999828) out of lost_step_dis:0.5']}
7:58 PM
probe at 109.999,125.498 is z=-0.076000
7:58 PM
probe at 79.999,125.498 is z=-0.025832
7:58 PM
probe at 80.000,109.998 is z=0.058594
7:58 PM
probe at 110.000,109.998 is z=-0.017341
7:58 PM
probe at 140.000,109.998 is z=-0.085937
7:58 PM
probe at 140.000,94.498 is z=2.954417
7:57 PM
probe at 109.999,94.498 is z=3.106459
7:57 PM
probe at 79.999,94.498 is z=3.140000
7:57 PM
8 | (140.0, 125.5) | (140.0, 125.5)
7:57 PM
7 | (110.0, 125.5) | (110.0, 125.5)
7:57 PM
6 | (80.0, 125.5) | (80.0, 125.5)
7:57 PM
5 | (80.0, 110.0) | (80.0, 110.0)
7:57 PM
4 | (110.0, 110.0) | (110.0, 110.0)
7:57 PM
3 | (140.0, 110.0) | (140.0, 110.0)
7:57 PM
2 | (140.0, 94.5) | (140.0, 94.5)
7:57 PM
1 | (110.0, 94.5) | (110.0, 94.5)
7:57 PM
0 | (80.0, 94.5) | (80.0, 94.5)
7:57 PM
bed_mesh: generated points
Index | Tool Adjusted | Probe
7:57 PM
Generating new points...
7:57 PM
KAMP adjustments successful. Happy KAMPing!
7:57 PM
Adapted mesh bounds: 79.9995,94.498, 140.0,125.502
7:57 PM
Fuzz amount is 0, mesh points not fuzzed.
7:57 PM
Mesh margin is 0, margin not increased.
7:57 PM
Default mesh bounds: 5.0,5.0, 215.0,215.0
7:57 PM
Adapted probe count: 3,3
7:57 PM
Default probe count: 5,5
7:57 PM
Algorithm: lagrange
7:57 PM
Starting Adaptive Bed Mesh...
7:55 PM
[CLEAR_NOZZLE_QUICK] end_pos[2]:2.9731250000000014
7:55 PM
[CLEAR_NOZZLE_QUICK] src_pos[2]:3.134999999999998
7:55 PM
Run Current: 0.56A Hold Current: 0.56A
7:54 PM
y_park = 104.5
7:54 PM
x_park = -104.5
7:53 PM
x_axes: xyz
7:53 PM
x_axes: xyz
7:53 PM
wait temp end
7:53 PM
File selected
7:53 PM
File opened:3DBenchy.gcode Size:3135094
7:49 PM
{"code":"key111", "msg": "Extrude below minimum temp
7:49 PM
{"code":"key111", "msg": "Extrude below minimum temp
See the 'min_extrude_temp' config option for details", "values": []}
7:48 PM
y_park = 104.5
7:48 PM
x_park = -104.5
7:47 PM
x_axes: xyz
7:47 PM
x_axes: xyz
7:47 PM
File selected
7:47 PM
File opened:CE6_TST-PROGBASE_Rev. A2.gcode Size:764883
7:46 PM
SET_HEATER_TEMPERATURE HEATER=extruder TARGET=210
7:46 PM
SET_HEATER_TEMPERATURE HEATER=extruder TARGET=220
7:40 PM
{"code":"key111", "msg": "Extrude below minimum temp
7:40 PM
{"code":"key111", "msg": "Extrude below minimum temp
See the 'min_extrude_temp' config option for details", "values": []}
7:38 PM
y_park = 104.5
7:38 PM
x_park = -104.5
7:38 PM
move xy
7:38 PM
x_axes is NULL
7:35 PM
File selected
7:35 PM
File opened:CE6_TST-PROGBASE_Rev. A2.gcode Size:764883
7:35 PM
SDCARD_PRINT_FILE FILENAME="CE6_TST-PROGBASE_Rev. A2.gcode"

How to discover why ELF binary is not running

If you face an issue like this:

$ ./UltiMaker-Cura
bash: ./UltiMaker-Cura: No such file or directory

And you confirmed that the file has execution permission:

$ ls -l UltiMaker-Cura 
-rwxr-xr-x 1 alan alan 11006560 jul 11 18:21 UltiMaker-Cura

Also you confirmed it is an ELF file (no mistake)

$ file UltiMaker-Cura 
UltiMaker-Cura: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter lib64/ld-linux-x86-64.so.2, BuildID[sha1]=aa5cd8892ec75e94945edf5de21c0673ae51ac17, for GNU/Linux 2.6.32, stripped

So, readelf is your friend:

$ readelf -a UltiMaker-Cura | grep NEEDED
 0x0000000000000001 (NEEDED) Shared library: [libdl.so.2]
 0x0000000000000001 (NEEDED) Shared library: [libz.so.1]
 0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0]
 0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
 
$ readelf -a UltiMaker-Cura | grep interpreter
 [Requesting program interpreter: lib64/ld-linux-x86-64.so.2]

$ apt-file search ld-linux-x86-64.so.2
libc6: /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
libc6: /lib64/ld-linux-x86-64.so.2
libc6-amd64-cross: /usr/x86_64-linux-gnu/lib/ld-linux-x86-64.so.2
libc6-amd64-cross: /usr/x86_64-linux-gnu/lib64/ld-linux-x86-64.so.2
libc6-amd64-i386-cross: /usr/i686-linux-gnu/lib64/ld-linux-x86-64.so.2
libc6-amd64-x32-cross: /usr/x86_64-linux-gnux32/lib64/ld-linux-x86-64.so.2
libc6-prof: /lib/libc6-prof/x86_64-linux-gnu/ld-linux-x86-64.so.2

$ cp /usr/x86_64-linux-gnu/lib64/ld-linux-x86-64.so.2 lib64/

$ ./UltiMaker-Cura
[72119] Failed to execute script 'cura_app' due to unhandled exception!

Flashing NuttX on STM32G0B1VC using JLink

These are the steps to flash NuttX RTOS binary into STM32G0B1 chip:

$ JLinkExe -if swd
SEGGER J-Link Commander V7.92c (Compiled Aug 30 2023 14:58:04)
DLL version V7.92c, compiled Aug 30 2023 14:57:42

Connecting to J-Link via USB...O.K.
Firmware: J-Link ARM V8 compiled Nov 28 2014 13:44:46
Hardware version: V8.00
J-Link uptime (since boot): N/A (Not supported by this model)
S/N: 268006167
License(s): FlashBP, GDB
OEM: SEGGER-EDU
VTref=2.730V

Type "connect" to establish a target connection, '?' for help

J-Link>con
Please specify device / core. <Default>: STM32G0B1VC
Type '?' for selection dialog
Device>
Specify target interface speed [kHz]. <Default>: 4000 kHz
Speed>
Device "STM32G0B1VC" selected.
Connecting to target via SWD
InitTarget() start
SWD selected. Executing JTAG -> SWD switching sequence.
DAP initialized successfully.
InitTarget() end - Took 29.2ms
Found SW-DP with ID 0x0BC11477
DPv0 detected
CoreSight SoC-400 or earlier
Scanning AP map to find all available APs
AP[1]: Stopped AP scan as end of AP map has been reached
AP[0]: AHB-AP (IDR: 0x04770031)
Iterating through AP map to find AHB-AP to use
AP[0]: Core found
AP[0]: AHB-AP ROM base: 0xF0000000
CPUID register: 0x410CC601. Implementer code: 0x41 (ARM)
Found Cortex-M0 r0p1, Little endian.
FPUnit: 4 code (BP) slots and 0 literal slots
CoreSight components:
ROMTbl[0] @ F0000000
[0][0]: E00FF000 CID B105100D PID 000BB4C0 ROM Table
ROMTbl[1] @ E00FF000
[1][0]: E000E000 CID B105E00D PID 000BB008 SCS
[1][1]: E0001000 CID B105E00D PID 000BB00A DWT
[1][2]: E0002000 CID B105E00D PID 000BB00B FPB
Memory zones:
  Zone: "Default" Description: Default access mode
Cortex-M0 identified.

J-Link>erase
No address range specified, 'Erase Chip' will be executed
'erase': Performing implicit reset & halt of MCU.
Reset: Halt core after reset via DEMCR.VC_CORERESET.
Reset: Reset device via AIRCR.SYSRESETREQ.
Erasing device...
J-Link: Flash download: Total time needed: 0.157s (Prepare: 0.080s, Compare: 0.000s, Erase: 0.036s, Program: 0.000s, Verify: 0.000s, Restore: 0.040s)
J-Link: Flash download: Total time needed: 0.177s (Prepare: 0.078s, Compare: 0.000s, Erase: 0.057s, Program: 0.000s, Verify: 0.000s, Restore: 0.041s)
J-Link: Flash download: Total time needed: 0.092s (Prepare: 0.055s, Compare: 0.000s, Erase: 0.015s, Program: 0.000s, Verify: 0.000s, Restore: 0.022s)
Erasing done.

J-Link>loadbin nuttx.hex, 0
'loadbin': Performing implicit reset & halt of MCU.
Reset: Halt core after reset via DEMCR.VC_CORERESET.
Reset: Reset device via AIRCR.SYSRESETREQ.
Downloading file [nuttx.hex]...
J-Link: Flash download: Bank 0 @ 0x08000000: 3 ranges affected (108544 bytes)
J-Link: Flash download: Total: 1.359s (Prepare: 0.076s, Compare: 0.028s, Erase: 0.024s, Program & Verify: 1.190s, Restore: 0.040s)
J-Link: Flash download: Program & Verify speed: 89 KB/s
J-Link: Flash download: Bank 1 @ 0x08020000: 2 ranges affected (112640 bytes)
J-Link: Flash download: Total: 1.772s (Prepare: 0.077s, Compare: 0.023s, Erase: 0.025s, Program & Verify: 1.603s, Restore: 0.041s)
J-Link: Flash download: Program & Verify speed: 68 KB/s
O.K.
J-Link>

How a supposed malfunction revealed another hidden feature of NuttX

NuttX RTOS is full of features that few people know that exist, mainly because these features were added during it development and none documentation was created to explain about it.

I will report here what happened with I was helping my friend Marco Casarolli to fix an issue in this configuration. He was trying to get telnet working on his board, but instead of showing the “nsh> ” prompt to let him access the NuttX terminal he was receiving something completely different:

uIP command shell -- NuttX style
Type '?' and return for help
uIP 1.0> 

After some time he realized that he selected the incorrect telnetd in the menuconfig. He selected CONFIG_EXAMPLES_TELNETD instead of CONFIG_SYSTEM_TELNETD !!!

Then after some time that he fixed that I realized that telnetd example actually is an way to create custom control to the board configuration over telnet, without enabling the more powerful “nsh> “. It avoids security risks!

After realizing it I decided that it was better to make its function clear to let people to extend it, now it will present this message:

Device Configuration over Telnet
You can add functions to setup your device
Type '?' and press <enter> for help
cfg>

Now its purpose is clear and reveal a new feature that was “hidden” on NuttX.

Update: That feature also reveal about the history of NuttX network stack that started as a port of uIP from Adam Dunkels until evolve on something completely different. That “uIP command shell” came from telnetd-shell.c existent on uIP source tree.