USB self-loop: HS host DFU-downloads firmware to an FS DFU device, uploads + verifies.
More...
|
| enum | dfu_config_t : uint32_t {
k_dfu_thread_stack = 4096U
,
k_dfu_host_stack = 8192U
,
k_dfu_usbx_pool_bytes = 32768U
,
k_dfu_idle_ticks = 50U
,
k_dfu_boot_wait_ticks = 500U
,
k_dfu_retry_ticks = 3000U
,
k_dfu_baud = 115200U
,
k_dfu_print_cap = 160U
,
k_dfu_dev_priority = 8U
,
k_dfu_host_priority = 24U
} |
| | Compile-time settings: threads, pool, console, cadence. More...
|
| enum | dfu_hex_t : uint8_t {
k_dfu_hex_chars_u16 = 4U
,
k_dfu_hex_chars_u32 = 8U
,
k_dfu_dec_chars_u32 = 10U
,
k_dfu_nibble_bits = 4U
,
k_dfu_hex_digit_split = 10U
} |
| | Hex/decimal text-formatter sizing constants. More...
|
| enum | dfu_mask_t : uint32_t {
k_dfu_nibble_mask = 0xFU
,
k_dfu_dec_radix = 10U
} |
| | Bit-mask constants used by the text formatters. More...
|
| enum | dfu_geom_t : uint32_t {
k_dfu_xfer_size = 64U
,
k_dfu_blocks = 8U
,
k_dfu_image_bytes = 512U
,
k_dfu_no_mismatch = 0xFFFFFFFFU
,
k_dfu_pat_blk_mul = 131U
,
k_dfu_pat_idx_mul = 7U
,
k_dfu_pat_bias = 0xA5U
,
k_dfu_byte_mask = 0xFFU
,
k_dfu_dev_addr = 1U
,
k_dfu_intf = 0U
,
k_dfu_config_val = 1U
} |
| | Firmware-image geometry + pattern constants. More...
|
| enum | dfu_phase_t : uint32_t {
k_dfu_phase_boot = 0U
,
k_dfu_phase_init = 1U
,
k_dfu_phase_enum = 2U
,
k_dfu_phase_download = 3U
,
k_dfu_phase_upload = 4U
,
k_dfu_phase_pass = 5U
} |
| | J-Link probe values marking host-ladder progress. More...
|
| enum | usb_langid_byte_t : uint8_t {
k_usb_langid_en_us_lo = 0x09U
,
k_usb_langid_en_us_hi = 0x04U
} |
| enum | dfu_req_t : uint16_t {
k_dfu_bm_std_dev_in = 0x80U
,
k_dfu_bm_std_dev_out = 0x00U
,
k_dfu_bm_class_if_out = 0x21U
,
k_dfu_bm_class_if_in = 0xA1U
,
k_dfu_breq_get_desc = 0x06U
,
k_dfu_breq_set_addr = 0x05U
,
k_dfu_breq_set_config = 0x09U
,
k_dfu_breq_dnload = 0x01U
,
k_dfu_breq_upload = 0x02U
,
k_dfu_breq_getstatus = 0x03U
,
k_dfu_breq_abort = 0x06U
,
k_dfu_desc_device = 0x01U
,
k_dfu_dev_desc_len = 18U
,
k_dfu_off_dev_pid = 10U
,
k_dfu_byte_bits = 8U
,
k_dfu_getstatus_len = 6U
,
k_dfu_off_status_state = 4U
,
k_dfu_state_dnload_idle = 5U
,
k_dfu_state_idle = 2U
} |
| | Chapter-9 + DFU class request / descriptor constants. More...
|
| enum | dfu_enum_tune_t : uint32_t {
k_dfu_vbus_settle_ms = 200U
,
k_dfu_attach_to_ms = 2000U
,
k_dfu_debounce_ms = 500U
,
k_dfu_reset_hold_ms = 50U
,
k_dfu_recovery_ms = 20U
,
k_dfu_addr_settle_ms = 5U
,
k_dfu_status_poll_ms = 2U
,
k_dfu_status_tries = 50U
,
k_dfu_enum_tries = 8U
,
k_dfu_attach_spin = 50000000U
} |
| | Timing / retry tunables for the polled enumeration + status polling. More...
|
|
| void | _tx_timer_interrupt (void) |
| | ThreadX 1 ms tick worker.
|
| void | SysTick_Handler (void) |
| | Service the SysTick exception selected by the linked application.
|
| static void | dfu_pattern_fill (uint32_t block, uint8_t *out, uint32_t len) |
| | Fill a firmware block with this block's deterministic bytes.
|
| static VOID | dfu_device_worker (ULONG arg) |
| | Device-side worker: bring the DFU device up, then park.
|
| static uint8_t | dfu_nibble_to_hex (uint32_t nibble) |
| | Format one nibble (0..15) into an uppercase hex character.
|
| static uint32_t | dfu_str_len (const char *text) |
| | Bounded ASCII string length (cap k_dfu_print_cap).
|
| static ra8_err_t | dfu_sci_write (const uint8_t *data, uint32_t len) |
| | Push a literal block over the J-Link OB CDC console (SCI8) polled.
|
| static ra8_err_t | dfu_print (const char *text) |
| | Print a NUL-terminated ASCII string over the console.
|
| static ra8_err_t | dfu_print_hex (uint32_t value, uint8_t digits) |
| | Print a value as fixed-width uppercase hex.
|
| static ra8_err_t | dfu_print_dec (uint32_t value) |
| | Print a uint32_t as ASCII decimal.
|
| static ra8_err_t | dfu_print_fail (const char *what, ra8_err_t err) |
| | Print "FAIL <what> err=0xNNNNNNNN" on its own line.
|
| static ra8_err_t | dfu_host_pass (void) |
| | Run the full host pass: enumerate, download, upload-verify.
|
| static VOID | dfu_host_worker (ULONG arg) |
| | Host-side worker: retry the full pass until it succeeds, then park.
|
| VOID | tx_application_define (VOID *first_unused_memory) |
| | ThreadX application-define hook.
|
| static void | dfu_panic_halt (void) |
| | Halt forever in WFI – panic stop on init failure.
|
| static void | dfu_route_usb_or_halt (void) |
| | Route both ports' pins: FS as device, HS as host.
|
| static void | dfu_setup_or_halt (void) |
| | Bring CGC + both USB clocks + SysTick + SCI8 + LEDs + pins up.
|
| void | main (void) |
| | Application entry: bring the board up, then hand off to ThreadX.
|
USB self-loop: HS host DFU-downloads firmware to an FS DFU device, uploads + verifies.
- Tag
- [Ring 6 / APP] {World: S}
Rehearses a firmware-update-over-USB path entirely on-chip. The two USB ports are cabled to EACH OTHER and one image runs both stacks:
- USBFS (J11) = DEVICE: a ThreadX + USBX DFU class in DFU mode (bInterfaceProtocol 0x02, so it enumerates straight into dfuIDLE – no runtime/detach round-trip). Its write callback captures each downloaded block into a RAM "firmware" image; its read callback serves the image back on UPLOAD. DFU runs entirely over EP0 control transfers (no data endpoints).
- USBHS (J7) = HOST: a self-contained polled host on the first-party ra8_usb_host_* primitives. It enumerates the device, DFU_DNLOADs a deterministic multi-block image (with DFU_GETSTATUS polling + the zero-length manifest block), then DFU_UPLOADs it back and byte-checks it – proving the control-OUT firmware path round-trips intact.
The download exercises the host control-OUT data stage added to ra8_usb_host_control_xfer for this app (DFU_DNLOAD carries the firmware block in the SETUP data stage host -> device).
Verdicts stream over SCI8 (J-Link OB CDC console, 115200) and are mirrored in J-Link-readable probes (s_dbg_*).
Pinout
FS device: P4_07 VBUS sense, P5_00 VBUSEN GPIO LOW (device role), P8_14 D+, P8_15 D- (PSEL usb_fs). HS host: SW4-8 to Host via the U15 expander, PD07 HIGH (U18 supplies J7 VBUS), P4_08 USBHS_VBUS (PSEL usb_hs). Console: PD_02/ PD_03 SCI8 (PSEL sci_async).
- Author
- Brighton Sikarskie
- Date
- 2026-06-15
- Copyright
- Copyright (c) 2026 Brighton Sikarskie SPDX-License-Identifier: MIT
- Since
- 0.1.0
Definition in file main.c.
| VOID dfu_device_worker |
( |
ULONG | arg | ) |
|
|
static |
Device-side worker: bring the DFU device up, then park.
- Parameters
-
| [in] | arg | ThreadX entry argument (unused). |
- Returns
- Never returns.
- Precondition
- tx_application_define created this thread.
-
USB-FS pins + 48 MHz clock are up (main did both).
- Postcondition
- The FS device is attached in DFU mode; the DFU class services EP0.
-
On any bring-up failure the thread exits (s_dbg_dev_step frozen).
- Note
- The DFU class runs its own thread; this worker only brings it up.
- Since
- 0.1.0
Definition at line 412 of file main.c.
References k_dfu_idle_ticks, k_ra8_dfu_slot_b, k_ra8_ok, k_ra8_usb_speed_fs, ra8_dfu_device_set_target(), ra8_dfu_device_start(), ra8_dfu_device_worker_step(), s_dbg_dev_step, s_dbg_host_err, s_device_framework, s_language_id_framework, s_string_framework, s_usbx_pool, and tx_thread_sleep.
Run the full host pass: enumerate, download, upload-verify.
- Returns
- First failing step's error, or k_ra8_ok.
- Return values
-
- Precondition
- Device-side DFU class is registered (other thread).
-
The self-loop cable connects J7 to J11.
- Postcondition
- On success s_dbg_pass_count advanced and LED2 is on.
-
On failure the host controller is deinitialized for a clean retry.
- Note
- Blocking; runs on the low-priority host thread.
- Since
- 0.1.0
Definition at line 681 of file main.c.
References ra8_dfu_host_result_t::blocks_ok, dfu_pattern_fill(), dfu_print(), dfu_print_dec(), dfu_print_fail(), dfu_print_hex(), k_dfu_blocks, k_dfu_hex_chars_u16, k_dfu_image_bytes, k_dfu_phase_download, k_dfu_phase_init, k_dfu_phase_pass, k_dfu_xfer_size, k_ra8_board_led2, k_ra8_ok, k_ra8_usb_speed_hs, ra8_dfu_host_result_t::mismatch, ra8_dfu_host_result_t::pid, ra8_board_led_on(), ra8_dfu_host_run(), s_dbg_blocks_ok, s_dbg_mismatch, s_dbg_pass_count, s_dbg_phase, s_dbg_pid, and s_dfu_image.
| void SysTick_Handler |
( |
void | | ) |
|
Service the SysTick exception selected by the linked application.
Service one SysTick event for the core timebase.
Service one SysTick event for the core timebase.
Resolves to the weak core timebase handler unless a strong RTOS or application handler overrides it. The vector table references the selected implementation without owning its subsystem policy.
- Precondition
- Entered for a SysTick exception with a valid exception frame.
-
The selected handler's timebase or scheduler state is initialised.
- Postcondition
- The selected implementation has processed one SysTick event.
-
The vector table itself remains unchanged.
- Note
- Runs in handler mode; thread-safety follows the selected implementation.
- Since
- 0.1.0
The weak firmware implementation advances the millisecond counter, then services linked ThreadX and USB hooks when their weak symbols and readiness state permit. The host-test implementation advances only the counter. An application may replace either weak definition with a strong handler.
- Precondition
- The handler is entered for one SysTick event or a host-test equivalent.
-
On target, ra8_time_init() configured the SysTick period.
- Postcondition
- s_tick_ms has advanced by exactly one.
-
Optional subsystem hooks run only when linked and ready.
- Note
- IRQ-safe; the weak symbol may be overridden by an application handler.
- Since
- 0.1.0
Service the SysTick exception selected by the linked application.
The weak firmware implementation advances the millisecond counter, then services linked ThreadX and USB hooks when their weak symbols and readiness state permit. The host-test implementation advances only the counter. An application may replace either weak definition with a strong handler.
- Precondition
- The handler is entered for one SysTick event or a host-test equivalent.
-
On target, ra8_time_init() configured the SysTick period.
- Postcondition
- s_tick_ms has advanced by exactly one.
-
Optional subsystem hooks run only when linked and ready.
- Note
- IRQ-safe; the weak symbol may be overridden by an application handler.
- Since
- 0.1.0
Service the SysTick exception selected by the linked application.
- Precondition
- Called from exception context (IPSR == 15).
-
_tx_initialize_low_level has programmed SysTick.
- Postcondition
- One ThreadX tick elapsed; PendSV may be pending.
Definition at line 81 of file main.c.
References _tx_timer_interrupt(), ra8_time_on_tick(), s_tx_kernel_up, and ux_dcd_ra8_usb_irq_reenable().
| VOID tx_application_define |
( |
VOID * | first_unused_memory | ) |
|
ThreadX application-define hook.
Spawns both workers.
- Parameters
-
| [in] | first_unused_memory | Sentinel (unused; static stacks). |
- Returns
- void.
- Precondition
- Called from tx_kernel_enter after scheduler init.
-
Static stacks are reserved at file scope.
- Postcondition
- Two auto-start workers are queued; s_tx_kernel_up is true.
-
The scheduler runs the device DFU bring-up + the host DFU ladder.
- Note
- Called once at boot; not thread-safe.
- Since
- 0.1.0
Definition at line 774 of file main.c.
References dfu_device_worker(), dfu_host_worker(), k_dfu_dev_priority, k_dfu_host_priority, k_dfu_host_stack, k_dfu_thread_stack, s_device_stack, s_device_thread, s_device_thread_name, s_host_stack, s_host_thread, s_host_thread_name, s_tx_kernel_up, TX_AUTO_START, TX_NO_TIME_SLICE, and tx_thread_create.