|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Real USB-DFU MRAM bootloader: boot the active app slot, or accept a DFU update. More...
#include <stdint.h>#include "ra8_board_ek_ra8d2.h"#include "ra8_boot_entry.h"#include "ra8_cgc.h"#include "ra8_dfu.h"#include "ra8_dfu_device.h"#include "ra8_err.h"#include "ra8_gpio_constants.h"#include "ra8_isr.h"#include "ra8_port_constants.h"#include "ra8_port_utils.h"#include "ra8_sci.h"#include "ra8_time.h"#include "ra8_usb.h"#include "tx_api.h"#include "ux_api.h"#include "ux_dcd_ra8_usb.h"#include "ux_device_class_dfu.h"#include "ux_device_stack.h"Go to the source code of this file.
Enumerations | |
| enum | blc_config_t : uint32_t { k_blc_thread_stack = 4096U , k_blc_usbx_pool_bytes = 32768U , k_blc_idle_ticks = 50U , k_blc_baud = 115200U , k_blc_sci_channel = 8U , k_blc_print_cap = 160U , k_blc_dev_priority = 8U } |
| Compile-time settings: thread, pool, console, cadence. More... | |
| enum | blc_hex_t : uint8_t { k_blc_hex_chars_u32 = 8U , k_blc_nibble_bits = 4U , k_blc_hex_digit_split = 10U } |
| Hex text-formatter sizing constants. More... | |
| enum | blc_mask_t : uint32_t { k_blc_nibble_mask = 0xFU } |
| 4-bit nibble mask for the hex formatter. More... | |
| enum | blc_scb_t : uintptr_t { k_blc_scb_aircr_addr = 0xE000ED0CU } |
| Cortex-M85 System Control Block address used by the DFU-commit reset. More... | |
| enum | blc_reset_t : uint32_t { k_blc_aircr_sysreset = 0x05FA0004U } |
| AIRCR write to request a system reset (VECTKEY 0x05FA | SYSRESETREQ). More... | |
| enum | usb_langid_byte_t : uint8_t { k_usb_langid_en_us_lo = 0x09U , k_usb_langid_en_us_hi = 0x04U } |
| USBX LANGID descriptor 0x0409 (English-US), little-endian byte pair. More... | |
| enum | blc_dbg_t : uint32_t { k_blc_dbg_unset = 0xFFFFFFFFU } |
| J-Link debug-probe "not yet written" sentinel. More... | |
Functions | |
| void | _tx_timer_interrupt (void) |
| ThreadX 1 ms tick worker. | |
| void | SysTick_Handler (void) |
| Service the SysTick exception selected by the linked application. | |
| static uint8_t | blc_nibble_to_hex (uint32_t nibble) |
| Format one nibble (0..15) into an uppercase hex character. | |
| static uint32_t | blc_str_len (const char *text) |
| Bounded ASCII string length (cap k_blc_print_cap). | |
| static ra8_err_t | blc_print (const char *text) |
| Print a NUL-terminated ASCII string over SCI8 (polled). | |
| static ra8_err_t | blc_print_hex (uint32_t value) |
| Print a value as fixed-width (8-digit) uppercase hex. | |
| static ra8_dfu_action_t | blc_decide (ra8_dfu_slot_t *out_target) |
| Read the trigger + both slots and resolve the reset-time action. | |
| static void | blc_boot_slot (ra8_dfu_slot_t slot) |
| Copy a validated slot's image to the SRAM run base and launch it. | |
| static void | blc_system_reset (void) |
| Request a system reset via AIRCR.SYSRESETREQ. | |
| static VOID | blc_device_worker (ULONG arg) |
| DFU device worker: bring the DFU class up, drain commits, reset on done. | |
| VOID | tx_application_define (VOID *first_unused_memory) |
| ThreadX application-define hook. | |
| static void | blc_panic_halt (void) |
| Halt forever in WFI – panic stop on init failure. | |
| static void | blc_route_usb_or_halt (void) |
| Route the USB-FS device pins (P4_07/P5_00/P8_14/P8_15). | |
| static void | blc_setup_or_halt (void) |
| Bring CGC + USB-FS clock + SysTick + SCI8 + LEDs + pins up. | |
| void | main (void) |
| Application entry: decide, then boot a slot or enter the DFU device. | |
Variables | |
| static volatile bool | s_tx_kernel_up = false |
| Gates ThreadX tick delivery until tx_application_define has run. | |
| static const ra8_port_pin_t | k_blc_pin_fs_vbus = (ra8_port_pin_t)k_ra8_board_usbfs_pin_vbus |
| USBFS VBUS sense pin (P4_07, PSEL = 0x13). | |
| static const ra8_port_pin_t | k_blc_pin_fs_vbusen = (ra8_port_pin_t)k_ra8_board_usbfs_pin_vbusen |
| USBFS VBUSEN (P5_00) – GPIO LOW for the device role. | |
| static const ra8_port_pin_t | k_blc_pin_fs_dp = (ra8_port_pin_t)k_ra8_board_usbfs_pin_dp |
| USBFS D+ (P8_14). | |
| static const ra8_port_pin_t | k_blc_pin_fs_dm = (ra8_port_pin_t)k_ra8_board_usbfs_pin_dm |
| USBFS D- (P8_15). | |
| static const ra8_port_pin_t | k_blc_pin_sci_tx = (ra8_port_pin_t)k_ra8_board_uart_console_pin_txd |
| J-Link OB CDC TX pin (PD_02 – SCI8 TX). | |
| static const ra8_port_pin_t | k_blc_pin_sci_rx = (ra8_port_pin_t)k_ra8_board_uart_console_pin_rxd |
| J-Link OB CDC RX pin (PD_03 – SCI8 RX). | |
| static volatile uint32_t | g_dfu_trigger |
| No-init SRAM word an application writes (== k_ra8_dfu_trigger_magic) before resetting to request the bootloader's DFU mode. | |
| static TX_THREAD | s_device_thread |
| ThreadX TCB for the USBX device-side worker thread. | |
| static UCHAR | s_device_stack [k_blc_thread_stack] |
| Stack backing storage for s_device_thread. | |
| static UCHAR | s_usbx_pool [k_blc_usbx_pool_bytes] |
| USBX memory pool (USBX uses tx_byte_pool internally). | |
| static UCHAR | s_device_framework [] |
| USBX device + DFU descriptors: a DFU-mode interface (bInterfaceProtocol 0x02, enumerates straight into dfuIDLE) + the DFU functional descriptor (CAN_DNLOAD | CAN_UPLOAD, wTransferSize 64). | |
| static UCHAR | s_string_framework [] |
| USBX string descriptor table (vendor / product / serial). | |
| static UCHAR | s_language_id_framework [] = {k_usb_langid_en_us_lo, k_usb_langid_en_us_hi} |
| USBX language-id table – US English. | |
| static volatile uint32_t | s_dbg_action = k_blc_dbg_unset |
| Boot decision outcome (ra8_dfu_action_t), J-Link-readable. | |
| static volatile uint32_t | s_dbg_target = k_blc_dbg_unset |
| Slot the DFU path targets (ra8_dfu_slot_t), J-Link-readable. | |
| static volatile uint32_t | s_dbg_dev_step |
| Device worker progress: 4 = DFU class attached. | |
| static volatile uint32_t | s_dbg_dev_err |
| Device bring-up error (0 = none). | |
| volatile uint32_t | g_blc_dfu_tick = 0U |
| HIL liveness counter – advanced once per DFU device service step. | |
Real USB-DFU MRAM bootloader: boot the active app slot, or accept a DFU update.
The immutable first 128 KiB of code-MRAM. At every reset it:
On a JUMP it copies the slot's image body to a fixed SRAM run base (k_ra8_dfu_run_base), points VTOR there, loads the image's initial MSP, and branches to its reset vector – a same-world (Secure) hand-off. Copy-to-run means an app is linked ONCE at the run base and the same image boots from either slot (no per-slot build). On DFU it brings up the USBX DFU device (libs/ra8_dfu) on USB-FS (J11), programs the INACTIVE slot as the host DFU_DNLOADs it, and soft-resets once the image header is committed so the next boot decision selects the freshly written slot.
Brick-safety: the bootloader region is never erased, a freshly written bad slot fails its CRC (so the older valid slot still boots), and SWD re-flash of the bootloader is always available. The DFU path writes only the inactive slot – no BTFLG, no option-setting, nothing irreversible.
FS device: P4_07 VBUS sense, P5_00 VBUSEN GPIO LOW (device role; the USB host supplies VBUS), P8_14 D+, P8_15 D- (PSEL usb_fs). Console: PD_02/PD_03 SCI8 (PSEL sci_async, 115200 to the J-Link OB CDC).
Definition in file main.c.
| enum blc_config_t : uint32_t |
Compile-time settings: thread, pool, console, cadence.
| enum blc_dbg_t : uint32_t |
| enum blc_hex_t : uint8_t |
| enum blc_mask_t : uint32_t |
| enum blc_reset_t : uint32_t |
| enum blc_scb_t : uintptr_t |
Cortex-M85 System Control Block address used by the DFU-commit reset.
Accessed by absolute address (the project does not vendor a CMSIS SCB struct). AIRCR is the Secure alias since the bootloader runs Secure. The copy-to-run hand-off's VTOR write lives in ra8_dfu_launch.
| Enumerator | |
|---|---|
| k_blc_scb_aircr_addr | SCB->AIRCR (reset control). |
| enum usb_langid_byte_t : uint8_t |
|
extern |
ThreadX 1 ms tick worker.
|
static |
Copy a validated slot's image to the SRAM run base and launch it.
Reads the slot header for its img_len / entry, then delegates to the shared ra8_dfu_launch, which cross-checks the run target, copies the image body from the slot to k_ra8_dfu_run_base in SRAM, and branches to it. Because an app is linked ONCE at the run base, the same image boots from either slot. ra8_dfu_launch returns here only when the run target fails validation (a corrupted entry/length), in which case main drops to DFU.
| [in] | slot | Slot to boot (A or B); already passed ra8_dfu_slot_valid. |
slot is A or B and passed CRC validation in blc_decide. Definition at line 529 of file main.c.
References ra8_dfu_img_hdr_t::entry, ra8_dfu_img_hdr_t::img_len, k_ra8_ok, ra8_dfu_launch(), ra8_dfu_read_header(), and ra8_dfu_slot_base().
Referenced by main().
|
static |
Read the trigger + both slots and resolve the reset-time action.
Reads and clears the one-shot g_dfu_trigger, validates both slots (CRC over the body) and their sequence numbers, then folds them through the pure ra8_dfu_boot_decide policy. The DFU target (the slot to program) is the INACTIVE slot, or Slot A when neither slot is valid.
| [out] | out_target | Slot the DFU path should program. Non-NULL. |
| k_ra8_dfu_action_jump_a | Boot Slot A. |
| k_ra8_dfu_action_jump_b | Boot Slot B. |
| k_ra8_dfu_action_dfu | Stay in the DFU device. |
out_target is non-NULL. Definition at line 482 of file main.c.
References g_dfu_trigger, k_ra8_dfu_action_dfu, k_ra8_dfu_slot_a, k_ra8_dfu_slot_b, k_ra8_dfu_slot_none, k_ra8_dfu_trigger_magic, ra8_dfu_boot_decide(), ra8_dfu_other_slot(), ra8_dfu_select_slot(), ra8_dfu_slot_seq(), and ra8_dfu_slot_valid().
Referenced by main().
|
static |
DFU device worker: bring the DFU class up, drain commits, reset on done.
| [in] | arg | ThreadX entry argument (unused). |
Definition at line 575 of file main.c.
References blc_print(), blc_system_reset(), g_blc_dfu_tick, k_blc_idle_ticks, k_ra8_ok, k_ra8_usb_speed_fs, ra8_dfu_device_committed(), ra8_dfu_device_last_error(), ra8_dfu_device_start(), ra8_dfu_device_worker_step(), s_dbg_dev_err, s_dbg_dev_step, s_device_framework, s_language_id_framework, s_string_framework, s_usbx_pool, and tx_thread_sleep.
Referenced by tx_application_define().
|
static |
Format one nibble (0..15) into an uppercase hex character.
| [in] | nibble | 4-bit value. |
| '0' | For a zero nibble. |
Definition at line 384 of file main.c.
References k_blc_hex_digit_split.
Referenced by blc_print_hex().
|
static |
Halt forever in WFI – panic stop on init failure.
Definition at line 652 of file main.c.
Referenced by blc_route_usb_or_halt(), blc_setup_or_halt(), and main().
|
staticnodiscard |
Print a NUL-terminated ASCII string over SCI8 (polled).
| [in] | text | String to print (CR/LF included by the caller). |
| k_ra8_ok | All bytes queued. |
text is non-NULL. text is NUL-terminated within k_blc_print_cap bytes. Definition at line 428 of file main.c.
References blc_str_len(), k_blc_sci_channel, and ra8_sci_write_polling().
Referenced by blc_device_worker(), and main().
|
staticnodiscard |
Print a value as fixed-width (8-digit) uppercase hex.
| [in] | value | Value to print. |
| k_ra8_ok | All bytes queued. |
Definition at line 445 of file main.c.
References blc_nibble_to_hex(), k_blc_hex_chars_u32, k_blc_nibble_bits, k_blc_nibble_mask, k_blc_sci_channel, and ra8_sci_write_polling().
Referenced by main().
|
static |
Route the USB-FS device pins (P4_07/P5_00/P8_14/P8_15).
Definition at line 670 of file main.c.
References blc_panic_halt(), k_blc_pin_fs_dm, k_blc_pin_fs_dp, k_blc_pin_fs_vbus, k_blc_pin_fs_vbusen, k_ra8_level_low, k_ra8_ok, k_ra8_psel_usb_fs, ra8_gpio_output_init(), and ra8_pfs_route_peripheral().
Referenced by blc_setup_or_halt().
|
static |
Bring CGC + USB-FS clock + SysTick + SCI8 + LEDs + pins up.
Definition at line 717 of file main.c.
References blc_panic_halt(), blc_route_usb_or_halt(), k_blc_baud, k_blc_pin_sci_rx, k_blc_pin_sci_tx, k_blc_sci_channel, k_ra8_board_led1, k_ra8_clock_id_cpuclk0, k_ra8_clock_id_pclka, k_ra8_ok, k_ra8_psel_sci_async, k_ra8_sci_data_8, k_ra8_sci_parity_none, k_ra8_sci_stop_1, ra8_board_led_init(), ra8_cgc_get_clock_hz(), ra8_cgc_init(), ra8_cgc_usbfs_clock_enable(), ra8_pfs_route_peripheral(), ra8_psa_crypto_init(), ra8_sci_init(), and ra8_time_init().
Referenced by main().
|
static |
Bounded ASCII string length (cap k_blc_print_cap).
| [in] | text | NUL-terminated string. |
| 0 | For an empty string. |
text is non-NULL with readable storage. text fits the cap. Definition at line 404 of file main.c.
References k_blc_print_cap.
Referenced by blc_print().
|
static |
Request a system reset via AIRCR.SYSRESETREQ.
Never returns.
Definition at line 550 of file main.c.
References k_blc_aircr_sysreset, and k_blc_scb_aircr_addr.
Referenced by blc_device_worker().
| void main | ( | void | ) |
Application entry: decide, then boot a slot or enter the DFU device.
The application entry point Reset_Handler hands control to.
Definition at line 777 of file main.c.
References blc_boot_slot(), blc_decide(), blc_panic_halt(), blc_print(), blc_print_hex(), blc_setup_or_halt(), k_ra8_dfu_action_jump_a, k_ra8_dfu_action_jump_b, k_ra8_dfu_run_base, k_ra8_dfu_slot_a, k_ra8_dfu_slot_b, ra8_dfu_device_set_target(), ra8_isr_globals_enable(), s_dbg_action, and s_dbg_target.
| 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.
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.
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.
Service the SysTick exception selected by the linked application.
Definition at line 92 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 the single DFU device worker.
| [in] | first_unused_memory | Sentinel (unused; static stacks). |
Definition at line 619 of file main.c.
References blc_device_worker(), k_blc_dev_priority, k_blc_thread_stack, s_device_stack, s_device_thread, s_device_thread_name, s_tx_kernel_up, TX_AUTO_START, TX_NO_TIME_SLICE, and tx_thread_create.
| volatile uint32_t g_blc_dfu_tick = 0U |
HIL liveness counter – advanced once per DFU device service step.
Flashed standalone (the HIL scenario), neither application slot is valid, so blc_decide deterministically returns k_ra8_dfu_action_dfu and control ends up in blc_device_worker's service loop. This counter is incremented on every pass of that loop, so a J-Link double-halt mem32 read (scripts/ hil_jlink_memprobe.sh, HIL_MODE=jlink_memprobe) sees it advance and proves the bootloader booted, decided "no bootable slot", and brought the USBX DFU device up – not merely that the chip is alive with PC in MRAM. A copy-to-run jump to a valid slot would leave this counter frozen (PC moves to the SRAM run window); the dfu_copy_to_run app gates that path instead.
Global (non-static) and volatile so the symbol stays linker-visible for nm and the increment is not optimized away.
Definition at line 366 of file main.c.
Referenced by blc_device_worker().
|
static |
No-init SRAM word an application writes (== k_ra8_dfu_trigger_magic) before resetting to request the bootloader's DFU mode.
Lives in .noinit (survives a warm reset, never bss-cleared). The bootloader reads it once and clears it, so the request is one-shot.
Definition at line 184 of file main.c.
Referenced by blc_decide().
|
static |
|
static |
|
static |
USBFS VBUS sense pin (P4_07, PSEL = 0x13).
Definition at line 107 of file main.c.
Referenced by blc_route_usb_or_halt().
|
static |
USBFS VBUSEN (P5_00) – GPIO LOW for the device role.
Definition at line 110 of file main.c.
Referenced by blc_route_usb_or_halt().
|
static |
J-Link OB CDC RX pin (PD_03 – SCI8 RX).
Definition at line 122 of file main.c.
Referenced by blc_setup_or_halt().
|
static |
J-Link OB CDC TX pin (PD_02 – SCI8 TX).
Definition at line 119 of file main.c.
Referenced by blc_setup_or_halt().
|
static |
Boot decision outcome (ra8_dfu_action_t), J-Link-readable.
Definition at line 337 of file main.c.
Referenced by main().
|
static |
|
static |
|
static |
Slot the DFU path targets (ra8_dfu_slot_t), J-Link-readable.
Definition at line 339 of file main.c.
Referenced by main().
|
static |
USBX device + DFU descriptors: a DFU-mode interface (bInterfaceProtocol 0x02, enumerates straight into dfuIDLE) + the DFU functional descriptor (CAN_DNLOAD | CAN_UPLOAD, wTransferSize 64).
DFU runs over EP0.
Definition at line 206 of file main.c.
Referenced by blc_device_worker(), dfu_class_register(), dfu_device_worker(), and dfu_usbx_stack_up().
|
static |
Stack backing storage for s_device_thread.
|
static |
|
static |
|
static |
|
static |
Gates ThreadX tick delivery until tx_application_define has run.
|
static |