ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
usb_selftest_dfu_steps.c File Reference

Host-side DFU ladder + console helpers for usb_selftest_dfu. More...

#include "usb_selftest_dfu_steps.h"
#include <stdint.h>
#include <string.h>
#include "ra8_board_ek_ra8d2.h"
#include "ra8_err.h"
#include "ra8_time.h"
#include "ra8_usb.h"
Include dependency graph for usb_selftest_dfu_steps.c:

Go to the source code of this file.

Functions

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 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_ctrl_get_dev_desc (uint8_t *desc)
 GET_DESCRIPTOR(DEVICE) over the polled control engine.
static ra8_err_t dfu_enum_hunt (uint8_t *desc)
 Wait for attach, then bus-reset + read the device descriptor.
static ra8_err_t dfu_enum_set_address (void)
 SET_ADDRESS to k_dfu_dev_addr, then retarget the DCP.
static ra8_err_t dfu_enum_set_config (void)
 SET_CONFIGURATION(::k_dfu_config_val) on the addressed device.
static ra8_err_t dfu_getstatus (uint8_t *out_state)
 DFU_GETSTATUS: read the 6-byte status and return the bState field.
static ra8_err_t dfu_wait_state (uint8_t want_state)
 Poll DFU_GETSTATUS until the device reports want_state.
static ra8_err_t dfu_dnload_block (uint16_t block, uint8_t *data, uint16_t len)
 DFU_DNLOAD one block, then poll to dfuDNLOAD-IDLE.
static ra8_err_t dfu_download_all (void)
 Download the whole rehearsal image, then DFU_ABORT back to dfuIDLE.
static ra8_err_t dfu_upload_verify (void)
 DFU_UPLOAD the image back block by block and byte-check each.
static ra8_err_t dfu_host_enumerate (void)
 Enumerate the looped-back device: descriptor hunt, address, config.
ra8_err_t dfu_host_pass (void)
 Run the full host pass: enumerate, download, upload-verify.

Variables

static volatile uint32_t s_dbg_phase
 Host-ladder phase marker (dfu_phase_t).
static volatile uint32_t s_dbg_pid
 Device-reported product id captured at enumeration.
static volatile uint32_t s_dbg_blocks_ok
 Blocks the host confirmed byte-equal on upload (expect k_dfu_blocks).
static volatile uint32_t s_dbg_mismatch = (uint32_t)k_dfu_no_mismatch
 First mismatching block, or k_dfu_no_mismatch.
static volatile uint32_t s_dbg_pass_count
 Completed full passes (sticky success counter).

Detailed Description

Host-side DFU ladder + console helpers for usb_selftest_dfu.

Tag
[Ring 6 / APP] {World: S}

Holds the polled USB-HS host ladder (enumerate -> DFU_DNLOAD -> DFU_UPLOAD verify) together with the SCI8 console text-formatter helpers and the shared per-block firmware pattern, split out of main.c so each translation unit stays under the file-size cap. main.c drives the device-side DFU class, the board bring-up, and the ThreadX worker threads; it calls into here only through dfu_host_pass.

The J-Link probes that mark host-ladder progress (s_dbg_phase and friends) live here because only the host ladder reads or writes them; the device-side probes stay in main.c.

Author
Brighton Sikarskie
Date
2026-06-15
Since
0.1.0

Definition in file usb_selftest_dfu_steps.c.

Function Documentation

◆ dfu_ctrl_get_dev_desc()

ra8_err_t dfu_ctrl_get_dev_desc ( uint8_t * desc)
staticnodiscard

GET_DESCRIPTOR(DEVICE) over the polled control engine.

Parameters
[out]descReceives the 18-byte device descriptor.
Returns
Read outcome.
Return values
k_ra8_okAll 18 bytes arrived.
k_ra8_err_hw_errorA short descriptor came back.
Precondition
The bus is reset and the DCP targets the device's current address.
desc holds at least k_dfu_dev_desc_len bytes.
Postcondition
desc carries the device descriptor on success.
No global state changes.
Note
Blocking (polled control transfer).
Since
0.1.0

Definition at line 279 of file usb_selftest_dfu_steps.c.

References k_dfu_bm_std_dev_in, k_dfu_breq_get_desc, k_dfu_byte_bits, k_dfu_desc_device, k_dfu_dev_desc_len, k_ra8_err_hw_error, k_ra8_ok, k_ra8_usb_speed_hs, and ra8_usb_host_control_xfer().

Referenced by dfu_enum_hunt().

◆ dfu_dnload_block()

ra8_err_t dfu_dnload_block ( uint16_t block,
uint8_t * data,
uint16_t len )
staticnodiscard

DFU_DNLOAD one block, then poll to dfuDNLOAD-IDLE.

Parameters
[in]blockThe DFU block sequence number (wValue).
[in]dataBlock payload (control-OUT data stage).
[in]lenBlock length in bytes.
Returns
First failing step's error, or k_ra8_ok.
Return values
k_ra8_okThe block was downloaded and the device is DNLOAD-IDLE.
Precondition
The device is configured in DFU mode (dfuIDLE / dfuDNLOAD-IDLE).
data holds len bytes.
Postcondition
The device captured the block; the state machine is DNLOAD-IDLE.
No global state changes.
Note
Blocking; uses the host control-OUT data stage.
Since
0.1.0

Definition at line 472 of file usb_selftest_dfu_steps.c.

References dfu_wait_state(), k_dfu_bm_class_if_out, k_dfu_breq_dnload, k_dfu_intf, k_dfu_state_dnload_idle, k_ra8_ok, k_ra8_usb_speed_hs, and ra8_usb_host_control_xfer().

Referenced by dfu_download_all().

◆ dfu_download_all()

ra8_err_t dfu_download_all ( void )
staticnodiscard

Download the whole rehearsal image, then DFU_ABORT back to dfuIDLE.

Returns
First failing step's error, or k_ra8_ok.
Return values
k_ra8_okAll blocks downloaded; the device is back in dfuIDLE.
Precondition
The device is configured in DFU mode.
The DFU functional descriptor advertises CAN_DOWNLOAD.
Postcondition
The device captured k_dfu_image_bytes; the state machine is dfuIDLE.
On failure the caller logs the offending step.
Note
Blocking; runs on the host worker thread. The "real" DFU end-of-download (zero-length DFU_DNLOAD -> MANIFEST) is intentionally NOT used here: this USBX DFU class is not manifestation-tolerant, so after MANIFEST it parks in dfuMANIFEST-WAIT-RESET and only a USB bus reset returns it to a usable state – which would tear down the in-place UPLOAD round-trip. DFU_ABORT returns dfuDNLOAD-IDLE -> dfuIDLE without a reset, so the same enumerated device can immediately be UPLOAD-verified.
Since
0.1.0

Definition at line 505 of file usb_selftest_dfu_steps.c.

References dfu_dnload_block(), dfu_pattern_fill(), dfu_wait_state(), k_dfu_blocks, k_dfu_bm_class_if_out, k_dfu_breq_abort, k_dfu_intf, k_dfu_state_idle, k_dfu_xfer_size, k_ra8_ok, k_ra8_usb_speed_hs, and ra8_usb_host_control_xfer().

Referenced by dfu_host_pass().

◆ dfu_enum_hunt()

ra8_err_t dfu_enum_hunt ( uint8_t * desc)
staticnodiscard

Wait for attach, then bus-reset + read the device descriptor.

Parameters
[out]descReceives the winning 18-byte device descriptor.
Returns
Hunt outcome.
Return values
k_ra8_okThe device answered at address 0.
k_ra8_err_hw_timeoutNothing attached / nothing answered.
Precondition
ra8_usb_host_init ran (host up, J7 VBUS supplied).
ra8_time_init has run (ms delays).
Postcondition
On success the DCP targets address 0 with UACT on.
On failure the bus is left in the last attempt's state.
Note
Blocking; worst case a few seconds.
Since
0.1.0

Definition at line 310 of file usb_selftest_dfu_steps.c.

References dfu_ctrl_get_dev_desc(), k_dfu_attach_spin, k_dfu_attach_to_ms, k_dfu_debounce_ms, k_dfu_enum_tries, k_dfu_recovery_ms, k_dfu_reset_hold_ms, k_dfu_vbus_settle_ms, k_ra8_err_hw_timeout, k_ra8_ok, k_ra8_usb_speed_hs, ra8_delay_ms(), ra8_time_ms(), ra8_usb_host_bus_reset(), ra8_usb_host_line_state(), ra8_usb_host_set_target(), and ra8_usb_host_set_uact().

Referenced by dfu_host_enumerate().

◆ dfu_enum_set_address()

ra8_err_t dfu_enum_set_address ( void )
staticnodiscard

SET_ADDRESS to k_dfu_dev_addr, then retarget the DCP.

Returns
First failing step's error, or k_ra8_ok.
Return values
k_ra8_okThe DCP now targets the operating address.
Precondition
dfu_enum_hunt succeeded (device answering at address 0).
The bus is active (UACT on).
Postcondition
Later transfers carry tokens to k_dfu_dev_addr.
The set-address recovery delay has elapsed.
Note
Blocking (one control transfer + settle).
Since
0.1.0

Definition at line 350 of file usb_selftest_dfu_steps.c.

References k_dfu_addr_settle_ms, k_dfu_bm_std_dev_out, k_dfu_breq_set_addr, k_dfu_dev_addr, k_ra8_ok, k_ra8_usb_speed_hs, ra8_delay_ms(), ra8_usb_host_control_xfer(), and ra8_usb_host_set_target().

Referenced by dfu_host_enumerate().

◆ dfu_enum_set_config()

ra8_err_t dfu_enum_set_config ( void )
staticnodiscard

SET_CONFIGURATION(::k_dfu_config_val) on the addressed device.

Returns
Control-transfer outcome.
Return values
k_ra8_okThe device entered the Configured state (dfuIDLE).
Precondition
dfu_enum_set_address succeeded.
The DCP targets k_dfu_dev_addr.
Postcondition
On success the DFU class is active in DFU mode.
No global state changes.
Note
Blocking (one control transfer).
Since
0.1.0

Definition at line 378 of file usb_selftest_dfu_steps.c.

References k_dfu_bm_std_dev_out, k_dfu_breq_set_config, k_dfu_config_val, k_ra8_usb_speed_hs, and ra8_usb_host_control_xfer().

Referenced by dfu_host_enumerate().

◆ dfu_getstatus()

ra8_err_t dfu_getstatus ( uint8_t * out_state)
staticnodiscard

DFU_GETSTATUS: read the 6-byte status and return the bState field.

Parameters
[out]out_stateReceives the DFU state machine byte.
Returns
Control-transfer outcome.
Return values
k_ra8_okStatus read; out_state valid.
k_ra8_err_hw_errorA short status payload came back.
Precondition
The device is configured in DFU mode.
out_state is non-NULL.
Postcondition
out_state holds bState on success.
No global state changes.
Note
Blocking (one control-IN transfer).
Since
0.1.0

Definition at line 403 of file usb_selftest_dfu_steps.c.

References k_dfu_bm_class_if_in, k_dfu_breq_getstatus, k_dfu_getstatus_len, k_dfu_intf, k_dfu_off_status_state, k_ra8_err_hw_error, k_ra8_ok, k_ra8_usb_speed_hs, and ra8_usb_host_control_xfer().

Referenced by dfu_wait_state().

◆ dfu_host_enumerate()

ra8_err_t dfu_host_enumerate ( void )
staticnodiscard

Enumerate the looped-back device: descriptor hunt, address, config.

Runs the k_dfu_phase_enum portion of the host pass – fetch the device descriptor, latch the product id into s_dbg_pid, assign the bus address, select configuration 1, and print the enumerated pid. Any failing step deinitializes the host controller so the caller can retry cleanly.

Returns
ra8_err_t First failing step's error, or k_ra8_ok.
Return values
k_ra8_okDevice enumerated and the pid line printed.
k_ra8_err_invalid_statePropagated descriptor / control-transfer error.
Precondition
ra8_usb_host_init has already succeeded (controller is up).
The self-loop cable connects J7 to J11.
Postcondition
On success s_dbg_pid holds the device product id.
On failure the host controller is deinitialized.
Note
Blocking; runs on the low-priority host thread.
Since
0.1.0

Definition at line 595 of file usb_selftest_dfu_steps.c.

References dfu_enum_hunt(), dfu_enum_set_address(), dfu_enum_set_config(), dfu_print(), dfu_print_fail(), dfu_print_hex(), k_dfu_byte_bits, k_dfu_dev_desc_len, k_dfu_hex_chars_u16, k_dfu_off_dev_pid, k_dfu_phase_enum, k_ra8_ok, k_ra8_usb_speed_hs, ra8_usb_host_deinit(), s_dbg_phase, and s_dbg_pid.

Referenced by dfu_host_pass().

◆ dfu_host_pass()

ra8_err_t dfu_host_pass ( void )
nodiscard

Run the full host pass: enumerate, download, upload-verify.

Returns
First failing step's error, or k_ra8_ok.
Return values
k_ra8_okThe pass printed DFU PASS.
Precondition
Device-side DFU class is registered (other thread).
The self-loop cable connects J7 to J11.
Postcondition
On success the host pass counter 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 629 of file usb_selftest_dfu_steps.c.

References dfu_download_all(), dfu_host_enumerate(), dfu_print(), dfu_print_dec(), dfu_print_fail(), dfu_upload_verify(), k_dfu_blocks, k_dfu_phase_download, k_dfu_phase_init, k_dfu_phase_pass, k_dfu_phase_upload, k_ra8_board_led2, k_ra8_ok, k_ra8_usb_speed_hs, ra8_board_led_on(), ra8_usb_host_deinit(), ra8_usb_host_init(), s_dbg_pass_count, and s_dbg_phase.

◆ dfu_nibble_to_hex()

uint8_t dfu_nibble_to_hex ( uint32_t nibble)
static

Format one nibble (0..15) into an uppercase hex character.

Parameters
[in]nibble4-bit value.
Returns
ASCII '0'..'9' or 'A'..'F'.
Return values
'0'For a zero nibble.
Precondition
Caller has masked the value to 4 bits.
None beyond the mask contract.
Postcondition
Returned byte is printable hex.
No state changes.
Note
Pure function.
Since
0.1.0

Definition at line 98 of file usb_selftest_dfu_steps.c.

References k_dfu_hex_digit_split.

Referenced by dfu_print_hex().

◆ dfu_pattern_fill()

void dfu_pattern_fill ( uint32_t block,
uint8_t * out,
uint32_t len )
static

Fill a firmware block with this block's deterministic bytes.

Byte i = (block*131 + i*7 + 0xA5) & 0xFF – distinct per block so the upload check proves the bytes read back are the ones downloaded.

Parameters
[in]blockThe block index (0..k_dfu_blocks-1).
[out]outDestination buffer.
[in]lenBytes to fill.
Returns
void.
Precondition
out has len writable bytes; len <= k_dfu_xfer_size.
block < k_dfu_blocks.
Postcondition
out[0..len-1] hold the block's pattern bytes.
No global state changes.
Note
Pure function.
Since
0.1.0

Definition at line 73 of file usb_selftest_dfu_steps.c.

References k_dfu_byte_mask, k_dfu_pat_bias, k_dfu_pat_blk_mul, and k_dfu_pat_idx_mul.

Referenced by dfu_download_all(), and dfu_upload_verify().

◆ dfu_print()

ra8_err_t dfu_print ( const char * text)
staticnodiscard

Print a NUL-terminated ASCII string over the console.

Parameters
[in]textString to print (CR/LF included by the caller).
Returns
ra8_err_t propagated from the SCI helper.
Return values
k_ra8_okAll bytes queued.
Precondition
SCI8 init already ran; text is non-NULL.
text is NUL-terminated within k_dfu_print_cap bytes.
Postcondition
The string bytes are in the SCI8 TX FIFO.
No other state changes.
Note
Blocking polled TX.
Since
0.1.0

Definition at line 160 of file usb_selftest_dfu_steps.c.

References dfu_sci_write(), and dfu_str_len().

Referenced by dfu_host_enumerate(), dfu_host_pass(), and dfu_print_fail().

◆ dfu_print_dec()

ra8_err_t dfu_print_dec ( uint32_t value)
staticnodiscard

Print a uint32_t as ASCII decimal.

Parameters
[in]valueValue to print.
Returns
ra8_err_t propagated from the SCI helper.
Return values
k_ra8_okAll bytes queued.
Precondition
SCI8 init already ran.
None beyond console readiness.
Postcondition
One ASCII decimal token is in the SCI8 TX FIFO.
No other state changes.
Note
Blocking polled TX.
Since
0.1.0

Definition at line 204 of file usb_selftest_dfu_steps.c.

References dfu_sci_write(), k_dfu_dec_chars_u32, and k_dfu_dec_radix.

Referenced by dfu_host_pass().

◆ dfu_print_fail()

ra8_err_t dfu_print_fail ( const char * what,
ra8_err_t err )
staticnodiscard

Print "FAIL <what> err=0xNNNNNNNN" on its own line.

Parameters
[in]whatShort description of the failed step.
[in]errError code returned by the step.
Returns
ra8_err_t propagated from the SCI helpers.
Return values
k_ra8_okThe diagnostic line is queued.
Precondition
SCI8 init already ran; what is NUL-terminated within the cap.
None beyond console readiness.
Postcondition
One diagnostic line is in the SCI8 TX FIFO.
No other state changes.
Note
Blocking polled TX.
Since
0.1.0

Definition at line 241 of file usb_selftest_dfu_steps.c.

References dfu_print(), dfu_print_hex(), k_dfu_hex_chars_u32, and k_ra8_ok.

Referenced by dfu_host_enumerate(), and dfu_host_pass().

◆ dfu_print_hex()

ra8_err_t dfu_print_hex ( uint32_t value,
uint8_t digits )
staticnodiscard

Print a value as fixed-width uppercase hex.

Parameters
[in]valueValue to print.
[in]digitsHex digit count (4 for u16, 8 for u32).
Returns
ra8_err_t propagated from the SCI helper.
Return values
k_ra8_okAll bytes queued.
Precondition
SCI8 init already ran.
digits is at most k_dfu_hex_chars_u32.
Postcondition
One fixed-width hex token is in the SCI8 TX FIFO.
No other state changes.
Note
Blocking polled TX.
Since
0.1.0

Definition at line 178 of file usb_selftest_dfu_steps.c.

References dfu_nibble_to_hex(), dfu_sci_write(), k_dfu_hex_chars_u32, k_dfu_nibble_bits, and k_dfu_nibble_mask.

Referenced by dfu_host_enumerate(), and dfu_print_fail().

◆ dfu_sci_write()

ra8_err_t dfu_sci_write ( const uint8_t * data,
uint32_t len )
staticnodiscard

Push a literal block over the J-Link OB CDC console (SCI8) polled.

Parameters
[in]dataBuffer to send.
[in]lenByte count.
Returns
ra8_err_t passthrough from ra8_board_uart_console_write.
Return values
k_ra8_okAll bytes queued.
Precondition
data is non-NULL; the board console init already ran.
len excludes any NUL terminator.
Postcondition
Bytes are in the SCI8 TX FIFO.
No other state changes.
Note
Blocking polled TX.
Since
0.1.0

Definition at line 143 of file usb_selftest_dfu_steps.c.

References ra8_board_uart_console_write().

Referenced by dfu_print(), dfu_print_dec(), and dfu_print_hex().

◆ dfu_str_len()

uint32_t dfu_str_len ( const char * text)
static

Bounded ASCII string length (cap k_dfu_print_cap).

Parameters
[in]textNUL-terminated string.
Returns
Number of bytes before the NUL, capped.
Return values
0For an empty string.
Precondition
text is non-NULL with readable storage.
text fits the cap.
Postcondition
No state changes.
Return value never exceeds k_dfu_print_cap.
Note
Bounded scan.
Since
0.1.0

Definition at line 118 of file usb_selftest_dfu_steps.c.

References k_dfu_print_cap.

Referenced by dfu_print().

◆ dfu_upload_verify()

ra8_err_t dfu_upload_verify ( void )
staticnodiscard

DFU_UPLOAD the image back block by block and byte-check each.

Returns
Verify outcome.
Return values
k_ra8_okAll blocks matched their downloaded pattern.
k_ra8_err_invalid_sizeA block returned the wrong length.
k_ra8_err_invalid_stateA block's bytes differed.
Precondition
dfu_download_all succeeded; the device is in dfuIDLE.
The DFU functional descriptor advertises CAN_UPLOAD.
Postcondition
s_dbg_blocks_ok counts verified blocks; s_dbg_mismatch records the first bad block on failure.
No device state retained between blocks.
Note
Blocking; one control-IN per block.
Since
0.1.0

Definition at line 545 of file usb_selftest_dfu_steps.c.

References dfu_pattern_fill(), k_dfu_blocks, k_dfu_bm_class_if_in, k_dfu_breq_upload, k_dfu_intf, k_dfu_xfer_size, k_ra8_err_invalid_size, k_ra8_err_invalid_state, k_ra8_ok, k_ra8_usb_speed_hs, memcmp(), ra8_usb_host_control_xfer(), s_dbg_blocks_ok, and s_dbg_mismatch.

Referenced by dfu_host_pass().

◆ dfu_wait_state()

ra8_err_t dfu_wait_state ( uint8_t want_state)
staticnodiscard

Poll DFU_GETSTATUS until the device reports want_state.

Parameters
[in]want_stateThe DFU bState the caller is waiting for.
Returns
Poll outcome.
Return values
k_ra8_okThe device reached want_state.
k_ra8_err_hw_timeoutIt did not within k_dfu_status_tries.
Precondition
The device is configured in DFU mode.
A control transfer (DNLOAD) preceded this.
Postcondition
On success the state machine is at want_state.
On failure the last poll's state is whatever the device held.
Note
Blocking; bounded poll with ms pacing.
Since
0.1.0

Definition at line 442 of file usb_selftest_dfu_steps.c.

References dfu_getstatus(), k_dfu_status_poll_ms, k_dfu_status_tries, k_ra8_err_hw_timeout, k_ra8_ok, and ra8_delay_ms().

Referenced by dfu_dnload_block(), and dfu_download_all().

Variable Documentation

◆ s_dbg_blocks_ok

volatile uint32_t s_dbg_blocks_ok
static

Blocks the host confirmed byte-equal on upload (expect k_dfu_blocks).

Definition at line 48 of file usb_selftest_dfu_steps.c.

◆ s_dbg_mismatch

volatile uint32_t s_dbg_mismatch = (uint32_t)k_dfu_no_mismatch
static

First mismatching block, or k_dfu_no_mismatch.

Definition at line 50 of file usb_selftest_dfu_steps.c.

◆ s_dbg_pass_count

volatile uint32_t s_dbg_pass_count
static

Completed full passes (sticky success counter).

Definition at line 52 of file usb_selftest_dfu_steps.c.

◆ s_dbg_phase

volatile uint32_t s_dbg_phase
static

Host-ladder phase marker (dfu_phase_t).

Definition at line 44 of file usb_selftest_dfu_steps.c.

◆ s_dbg_pid

volatile uint32_t s_dbg_pid
static

Device-reported product id captured at enumeration.

Definition at line 46 of file usb_selftest_dfu_steps.c.