Skip to content

motor_controller: migrate to the new USB device stack - #74

Merged
rosterloh merged 1 commit into
mainfrom
fix/motor-controller-usb-next
Aug 14, 2026
Merged

motor_controller: migrate to the new USB device stack#74
rosterloh merged 1 commit into
mainfrom
fix/motor-controller-usb-next

Conversation

@rosterloh

Copy link
Copy Markdown
Owner

Fixes west twister -T applications/motor_controller, which could not build this app at all.

Root cause

CONFIG_USB_DEVICE_STACK now carries select DEPRECATED, and the entire legacy stack — usb_device.c, usb_descriptor.c, usb_transfer.c, plus the SoC's bossa.c — is built from __deprecated APIs. Under twister's -Werror every one is fatal. Nothing in the app caused it; nothing in the app could suppress it.

src/usb.c already carried a complete port to the new stack, dead behind #if defined(CONFIG_USB_DEVICE_STACK_NEXT) with the Kconfig commented out. Enabling it needed one API fix: usbd_register_all_classes() has since gained a fourth blocklist argument.

BOSSA 1200-baud reset, reimplemented

soc/atmel/sam0/common/bossa.c hangs off CDC_ACM_DTE_RATE_CALLBACK_SUPPORT, a legacy-only symbol, so under the new stack BOOTLOADER_BOSSA_DEVICE_NAME is unsatisfiable and the file compiles to nothing. Without a replacement, west flash would need a manual double-tap of reset every time. It is reimplemented in usb.c off USBD_MSG_CDC_ACM_LINE_CODING, using the same magic value and SRAM location as bossa.c.

What was given up to make it fit

The new stack costs ~13 KB more flash and ~3.2 KB more RAM, on a part already at 98.89% flash / 99.51% RAM — 160 bytes of RAM free.

Cut Saves
kernel/device/i2c shells + INIT_STACKS, THREAD_MONITOR, THREAD_STACK_INFO ~7.5 KB flash
SHELL_HELP, SHELL_HISTORY, SHELL_TAB help strings + line editing; every command still works
DYNAMIXEL_LOG_LEVEL_DBG debug log strings — set it locally when debugging the bus
LV_Z_VDB_SIZE 10% → 5% ~3.2 KB RAM; still ~13 display lines per flush

⚠️ Those shell symbols default to y once SHELL is on — deleting the lines is a no-op, they need an explicit =n. That cost me a build to discover and is called out in prj.conf.

Before (main) After
FLASH 234,936 B — 98.89% 236,780 B — 99.67% (788 B free)
RAM 32,608 B — 99.51% 31,712 B — 96.78%

RAM is healthier than before; flash is considerably tighter. This app has no room left — anything added from here needs something removed.

Also: USBD_CDC_ACM_LOG_LEVEL must be OFF, not ERR. cdc_acm_uart0 is zephyr,shell-uart, so with SHELL_LOG_BACKEND the driver would log over the transport it is logging about; usbd_cdc_acm.c makes that a hard #warning.

Two pre-existing problems surfaced and fixed

  • tests.yaml had no platform_allow, so twister fanned out over ~60 platforms this board-specific app was never meant to build on, reporting their missing-devicetree-node failures as its own. 64 configs → 2.
  • debug.conf set CONFIG_DEBUG_OPTIMIZATIONS=y (-Os-Og), which adds ~56 KB to a 99%-full image. Verified against main: it overflows by 56,040 B there too — this config has never linked on any revision; it only looked green because twister aborted on the USB deprecation first. Dropped, with reasoning recorded: the normal build already compiles -gdwarf-4, so gdb has full symbols at -Os.

Verification

2 test scenarios (102 configurations) selected, 100 configurations filtered
0 failed, 0 errored, with no warnings in 45.60 seconds
2 test configurations were only built  (build_only: true)

Not runtime-verified — no hardware available to this session. Neither USB enumeration nor the reimplemented 1200-baud reset has been exercised on a board. If the reset path is wrong, west flash needs a manual double-tap until it's fixed; recoverable, but worth checking first thing.

🤖 Generated with Claude Code

CONFIG_USB_DEVICE_STACK now carries `select DEPRECATED`, and the whole legacy
stack -- usb_device.c, usb_descriptor.c, usb_transfer.c and the SoC's bossa.c
-- is built from __deprecated APIs. Under twister's -Werror every one of those
is fatal, so `west twister -T applications/motor_controller` could not build
this app at all. Nothing in the app caused it and nothing in the app could
suppress it.

src/usb.c already carried a complete port to the new stack, dead behind
`#if defined(CONFIG_USB_DEVICE_STACK_NEXT)` with the Kconfig commented out in
prj.conf. Enabling it needed one API fix: usbd_register_all_classes() has since
gained a fourth `blocklist` argument.

Two things the new stack does not bring with it:

1. BOSSA 1200-baud touch reset. soc/atmel/sam0/common/bossa.c hangs off
   CDC_ACM_DTE_RATE_CALLBACK_SUPPORT, a legacy-only symbol, so under the new
   stack BOOTLOADER_BOSSA_DEVICE_NAME is unsatisfiable and the file compiles to
   nothing. Without a replacement, bossac could no longer put the board into
   its bootloader and every `west flash` would need a manual double-tap of
   reset. It is reimplemented in usb.c off USBD_MSG_CDC_ACM_LINE_CODING, using
   the same magic value and SRAM location as bossa.c.

2. Room. The new stack costs ~13 KB more flash and ~3.2 KB more RAM than the
   legacy one, on a part that was already at 98.89% flash and 99.51% RAM --
   160 bytes of RAM free. Making it fit meant giving things up:

     - kernel/device/i2c shells and the thread instrumentation they pull in
       (INIT_STACKS, THREAD_MONITOR, THREAD_STACK_INFO): ~7.5 KB flash. Note
       these default to y once SHELL is on, so they need an explicit =n.
     - SHELL_HELP, SHELL_HISTORY, SHELL_TAB: help strings and line-editing
       conveniences. Every command still works.
     - DYNAMIXEL_LOG_LEVEL_DBG: debug log strings, better set locally.
     - LV_Z_VDB_SIZE 10% -> 5% (~3.2 KB RAM). Still ~13 display lines per
       flush; costs redraw cycles, not correctness.

   Result: 99.67% flash (788 B free), 96.78% RAM -- RAM is now healthier than
   before, flash considerably tighter. This app has no room left.

USBD_CDC_ACM_LOG_LEVEL must be OFF rather than ERR: cdc_acm_uart0 is
zephyr,shell-uart, and with SHELL_LOG_BACKEND the driver would log over the
transport it is logging about. usbd_cdc_acm.c makes that a hard #warning.

Two pre-existing problems surfaced on the way, both fixed here:

- tests.yaml had no platform_allow, so twister fanned out over ~60 platforms
  this board-specific app was never meant to build on and reported their
  missing-devicetree-node failures as its own.
- debug.conf set CONFIG_DEBUG_OPTIMIZATIONS=y (-Os -> -Og), which adds ~56 KB
  to a 99%-full image. Verified against main: it overflows by 56,040 B there
  too, so this config has never linked -- it only looked green because twister
  aborted on the USB deprecation first. Dropped, with the reasoning recorded:
  the normal build already compiles -gdwarf-4, so gdb has full symbols at -Os.

Verified: `west twister -T applications/motor_controller` builds both the
default and debug configurations, 0 failed / 0 errored. Not runtime-verified --
no hardware available, so neither USB enumeration nor the 1200-baud reset has
been exercised on a board.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@rosterloh
rosterloh merged commit 55c5336 into main Aug 14, 2026
8 checks passed
@rosterloh
rosterloh deleted the fix/motor-controller-usb-next branch August 14, 2026 09:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant