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

ThreadX + USBX CDC ACM echo for EK-RA8D2 (USB-FS). More...

#include <stdint.h>
#include <string.h>
#include "ra8_board_ek_ra8d2.h"
#include "ra8_boot_entry.h"
#include "ra8_cgc.h"
#include "ra8_err.h"
#include "ra8_gpio_constants.h"
#include "ra8_isr.h"
#include "ra8_log.h"
#include "ra8_port_constants.h"
#include "ra8_port_utils.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_cdc_acm.h"
#include "ux_device_stack.h"
#include "ux_system.h"
Include dependency graph for main.c:

Go to the source code of this file.

Data Structures

struct  demo_diag_t
 Demo-loop counters; read via JLink to localise stalls. More...

Enumerations

enum  demo_config_t : uint32_t {
  k_demo_thread_stack = 8192U ,
  k_demo_usbx_pool_bytes = 32768U ,
  k_demo_echo_buf_bytes = 64U ,
  k_demo_idle_ticks = 1U
}
 Compile-time settings for the echo loop and ThreadX worker. More...
enum  usb_langid_byte_t : uint8_t {
  k_usb_langid_en_us_lo = 0x09U ,
  k_usb_langid_en_us_hi = 0x04U
}

Functions

static VOID demo_cdc_activate (VOID *cdc_instance)
 CDC-ACM activate callback.
static VOID demo_cdc_deactivate (VOID *cdc_instance)
 CDC-ACM deactivate callback.
static UINT demo_usbx_stack_up (void)
 Brings USBX system + device stack up with the FS framework.
static UINT demo_cdc_class_register (void)
 Registers the CDC-ACM class against the device-stack configuration.
static void demo_pin_configured_state (void)
 Pin USBX peripheral state at CONFIGURED.
static void demo_echo_iter (UCHAR *buf, ULONG cap)
 One iteration of the CDC echo loop.
static VOID demo_worker (ULONG arg)
 Worker thread entry.
VOID tx_application_define (VOID *first_unused_memory)
 ThreadX application-define hook.
static void demo_panic_halt (void)
 Halt forever in WFI – panic stop on init failure.
static ra8_err_t demo_pins_init (void)
 Route the four USB-FS pins to the USBFS controller.
void main (void)
 Application entry.

Variables

static const ra8_port_pin_t k_demo_pin_vbus = (ra8_port_pin_t)k_ra8_board_usbfs_pin_vbus
 USB-FS pin identifiers, packed ra8_port_pin_t (port << 8 | pin).
static const ra8_port_pin_t k_demo_pin_vbusen = (ra8_port_pin_t)k_ra8_board_usbfs_pin_vbusen
static const ra8_port_pin_t k_demo_pin_dp = (ra8_port_pin_t)k_ra8_board_usbfs_pin_dp
static const ra8_port_pin_t k_demo_pin_dm = (ra8_port_pin_t)k_ra8_board_usbfs_pin_dm
static TX_THREAD s_demo_thread
 ThreadX TCB for the USBX worker thread.
static UCHAR s_demo_stack [k_demo_thread_stack]
 Stack backing storage for s_demo_thread.
static UCHAR s_usbx_pool [k_demo_usbx_pool_bytes]
 USBX memory pool (USBX uses tx_byte_pool internally).
static UX_SLAVE_CLASS_CDC_ACM * s_cdc_acm = UX_NULL
 Active CDC-ACM class instance, captured by activate callback.
volatile demo_diag_t s_demo_diag = {}
static TX_SEMAPHORE s_cdc_active_sem
 Posted by demo_cdc_activate; demo thread blocks on it instead of polling s_cdc_acm with tx_thread_sleep (which never returned on this silicon – SysTick may be silenced under polled-dispatch worker load).
static UCHAR s_device_framework_fs []
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.

Detailed Description

ThreadX + USBX CDC ACM echo for EK-RA8D2 (USB-FS).

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

Brings the chip up via ra8_cgc_init() (XTAL -> PLL1 -> CPUCLK0 = 1 GHz, PCLKA = 125 MHz), routes the four USB-FS pins per the EK-RA8D2 v1 User's Manual to the on-board USB-FS receptacle, hands control to ThreadX, and brings the CDC ACM device class up via Eclipse USBX (_ux_device_class_cdc_acm_initialize). The class sits on top of the project's port/usbx/ux_dcd_ra8_usb bridge to the hand-written ra8_usb register-level driver (HUM Ch. 36 USBFS, sec. 36.2.x for SYSCFG / DCPCFG / DCPMAXP / PIPECFG / CFIFO). The host actually enumerates the device because USBX's chapter-9 state machine answers SETUP packets through the DCD bridge.

Once enumerated, the worker thread loops on _ux_device_class_cdc_acm_read -> _ux_device_class_cdc_acm_write (echo). LED1 toggles per byte echoed.

Pinout (USB-FS, FSP-aligned)

Net Pin PFS PSEL
USB_FS_VBUS P4_07 k_ra8_psel_usb_fs (0x13)
USB_FS_VBUSEN P5_00 k_ra8_psel_usb_fs (0x13)
USB_FS_DP P8_14 k_ra8_psel_usb_fs (0x13)
USB_FS_DM P8_15 k_ra8_psel_usb_fs (0x13)

Sequence

  1. ra8_cgc_init() – standard FSP-quickstart clock tree.
  2. ra8_time_init for back-off delays.
  3. ra8_pfs_route_peripheral for the four USB-FS pins.
  4. ra8_board_led_init(k_ra8_board_led1) for visual heartbeat.
  5. ThreadX tx_kernel_enter() – spins the scheduler.
  6. tx_application_define – spawns one worker thread that:
    • Allocates USBX memory pool and calls _ux_system_initialize + _ux_device_stack_initialize.
    • Calls _ux_device_stack_class_register for the CDC-ACM class.
    • Calls ux_dcd_ra8_usb_initialize(k_ra8_usb_speed_fs) to plug our DCD bridge into USBX.
    • Calls ra8_usb_device_attach(true) so the host begins enumeration.
    • Drops into the echo loop.

Verification (macOS)

After flashing, the EK-RA8D2's USB-FS receptacle (J11) enumerates as /dev/cu.usbmodem*. Open it RDWR with picocom or screen and type characters; every byte echoes back and LED1 toggles per byte.

Author
Brighton Sikarskie
Date
2026-05-02
Since
0.1.0

Definition in file main.c.

Enumeration Type Documentation

◆ demo_config_t

enum demo_config_t : uint32_t

Compile-time settings for the echo loop and ThreadX worker.

Enumerator
k_demo_thread_stack 

Worker thread stack (bytes).

k_demo_usbx_pool_bytes 

USBX pool: 32 KiB; CDC-ACM enum exhausts 16 KiB.

k_demo_echo_buf_bytes 

One bulk-FS packet per recv/send.

k_demo_idle_ticks 

Idle back-off when no class active.

Definition at line 118 of file main.c.

◆ usb_langid_byte_t

enum usb_langid_byte_t : uint8_t
Enumerator
k_usb_langid_en_us_lo 

LANGID 0x0409 low byte.

k_usb_langid_en_us_hi 

LANGID 0x0409 high byte.

Definition at line 393 of file main.c.

Function Documentation

◆ demo_cdc_activate()

VOID demo_cdc_activate ( VOID * cdc_instance)
static

CDC-ACM activate callback.

Captures the live class instance.

Parameters
[in]cdc_instancePointer to UX_SLAVE_CLASS_CDC_ACM.
Precondition
Called from the USBX class thread.
Postcondition
s_cdc_acm points at the live CDC-ACM class.
Note
USBX guarantees serialization with the deactivate callback.
Since
0.1.0

Definition at line 420 of file main.c.

References s_cdc_acm, s_cdc_active_sem, and ux_dcd_ra8_usb_auto_echo_enable().

◆ demo_cdc_class_register()

UINT demo_cdc_class_register ( void )
static

Registers the CDC-ACM class against the device-stack configuration.

Returns
UINT UX_SUCCESS on success, propagated USBX error otherwise.
Return values
UX_SUCCESSClass registered.
Precondition
demo_usbx_stack_up has succeeded.
demo_cdc_activate / demo_cdc_deactivate are defined.
Postcondition
CDC-ACM class is bound to configuration 1, interface 0.
Activation callback will post s_cdc_active_sem.
Note
Not re-entrant.
Since
0.1.0

Definition at line 511 of file main.c.

References demo_cdc_activate(), and demo_cdc_deactivate().

◆ demo_cdc_deactivate()

VOID demo_cdc_deactivate ( VOID * cdc_instance)
static

CDC-ACM deactivate callback.

Drops the live class pointer.

Parameters
[in]cdc_instanceUnused.
Precondition
Called from the USBX class thread.
Postcondition
s_cdc_acm is UX_NULL.
Note
USBX guarantees serialization with the activate callback.
Since
0.1.0

Definition at line 457 of file main.c.

References s_cdc_acm.

◆ demo_echo_iter()

void demo_echo_iter ( UCHAR * buf,
ULONG cap )
static

One iteration of the CDC echo loop.

Parameters
[in,out]bufScratch buffer (echo data).
[in]capBuffer capacity in bytes.
Precondition
Worker is running and s_cdc_acm is non-NULL.
buf is non-NULL with cap bytes.
Postcondition
Diag counters updated.
LED1 toggled once per echoed byte on success.
Note
Returns on each iteration; outer loop reinvokes.
Since
0.1.0

Definition at line 565 of file main.c.

References demo_pin_configured_state(), k_demo_idle_ticks, k_ra8_board_led1, ra8_board_led_toggle(), s_cdc_acm, s_demo_diag, and tx_thread_sleep.

◆ demo_panic_halt()

void demo_panic_halt ( void )
static

Halt forever in WFI – panic stop on init failure.

Precondition
Called only after a fatal error in boot.
Postcondition
CPU is parked.
Note
Not reachable post-boot.
Since
0.1.0

Definition at line 687 of file main.c.

◆ demo_pin_configured_state()

void demo_pin_configured_state ( void )
static

Pin USBX peripheral state at CONFIGURED.

Works around a residual DVSQ-poll race on this silicon that can leave ux_slave_device_state at ATTACHED after SET_CONFIGURATION, breaking _ux_device_class_cdc_acm_read's state gate. Safe to assert once s_cdc_acm is non-NULL.

Precondition
Called from worker thread context.
s_cdc_acm is non-NULL (CDC class activated).
Postcondition
_ux_system_slave->...ux_slave_device_state is CONFIGURED.
Read/write APIs accept transfers.
Note
Inline candidate; called every iteration.
Since
0.1.0

Definition at line 543 of file main.c.

◆ demo_pins_init()

ra8_err_t demo_pins_init ( void )
staticnodiscard

Route the four USB-FS pins to the USBFS controller.

Returns
Error from the first failing route call, or k_ra8_ok.
Return values
k_ra8_okAll four pins routed.
Precondition
IOPORT module is reachable.
Single-threaded init context.
Postcondition
On success the four USB-FS pins are in USB peripheral mode.
Note
Not thread-safe.
Since
0.1.0

Definition at line 707 of file main.c.

References k_demo_pin_dm, k_demo_pin_dp, k_demo_pin_vbus, k_demo_pin_vbusen, k_ra8_level_low, k_ra8_ok, k_ra8_psel_usb_fs, ra8_gpio_output_init(), and ra8_pfs_route_peripheral().

◆ demo_usbx_stack_up()

UINT demo_usbx_stack_up ( void )
static

Brings USBX system + device stack up with the FS framework.

Returns
UINT UX_SUCCESS on success, propagated USBX error otherwise.
Return values
UX_SUCCESSStack initialized.
Precondition
USBX memory pool s_usbx_pool is at file scope.
Caller is in thread context (USBX requires ThreadX services).
Postcondition
On success, the device stack accepts class registrations.
On failure, USBX state is undefined; caller should bail.
Note
Single-call; not idempotent.
Since
0.1.0

Definition at line 481 of file main.c.

References k_demo_usbx_pool_bytes, s_device_framework_fs, s_language_id_framework, s_string_framework, and s_usbx_pool.

◆ demo_worker()

VOID demo_worker ( ULONG arg)
static

Worker thread entry.

Brings USBX + CDC up, then echoes forever.

Parameters
[in]argUnused (ThreadX entry signature).
Precondition
tx_application_define started this thread auto-start.
Postcondition
Thread loops forever; never returns.
Note
Single-instance worker; not designed for re-entry.
Since
0.1.0

Definition at line 602 of file main.c.

References demo_cdc_class_register(), demo_echo_iter(), demo_usbx_stack_up(), k_demo_echo_buf_bytes, k_demo_idle_ticks, k_ra8_ok, k_ra8_usb_speed_fs, ra8_usb_device_attach(), s_cdc_acm, s_cdc_active_sem, s_demo_diag, tx_thread_sleep, TX_WAIT_FOREVER, and ux_dcd_ra8_usb_initialize().

◆ main()

void main ( void )

Application entry.

The application entry point Reset_Handler hands control to.

Brings up CGC + USB-FS pins + LED1 + ThreadX.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On clean entry the CPU stays in tx_kernel_enter forever.
On any HAL init failure the function halts in WFI.
Note
Single entry point; not re-entrant.
Since
0.1.0

Definition at line 743 of file main.c.

References demo_panic_halt(), demo_pins_init(), k_ra8_board_led1, k_ra8_clock_id_cpuclk0, k_ra8_ok, ra8_board_led_init(), ra8_cgc_get_clock_hz(), ra8_cgc_init(), ra8_cgc_usbfs_clock_enable(), ra8_isr_globals_enable(), ra8_log_info, ra8_log_init(), and ra8_time_init().

◆ tx_application_define()

VOID tx_application_define ( VOID * first_unused_memory)

ThreadX application-define hook.

Spawns the demo worker.

Parameters
[in]first_unused_memorySentinel (unused; static stacks).
Precondition
Called from tx_kernel_enter after scheduler init.
Postcondition
One auto-start worker thread is queued.
Note
Called once at boot; not thread-safe.
Since
0.1.0

Definition at line 654 of file main.c.

References demo_worker(), k_demo_thread_stack, s_cdc_active_sem, s_demo_stack, s_demo_thread, s_thread_name, TX_AUTO_START, TX_NO_TIME_SLICE, and tx_thread_create.

Variable Documentation

◆ k_demo_pin_dm

Definition at line 108 of file main.c.

◆ k_demo_pin_dp

Definition at line 107 of file main.c.

◆ k_demo_pin_vbus

const ra8_port_pin_t k_demo_pin_vbus = (ra8_port_pin_t)k_ra8_board_usbfs_pin_vbus
static

USB-FS pin identifiers, packed ra8_port_pin_t (port << 8 | pin).

Built as a runtime cast so clang-tidy's enum-range check is happy with the otherwise out-of-enum value.

Since
0.1.0

Definition at line 105 of file main.c.

◆ k_demo_pin_vbusen

const ra8_port_pin_t k_demo_pin_vbusen = (ra8_port_pin_t)k_ra8_board_usbfs_pin_vbusen
static

Definition at line 106 of file main.c.

◆ s_cdc_acm

UX_SLAVE_CLASS_CDC_ACM* s_cdc_acm = UX_NULL
static

Active CDC-ACM class instance, captured by activate callback.

Note
Read by worker; written by USBX class thread.
Since
0.1.0

Definition at line 159 of file main.c.

◆ s_cdc_active_sem

TX_SEMAPHORE s_cdc_active_sem
static

Posted by demo_cdc_activate; demo thread blocks on it instead of polling s_cdc_acm with tx_thread_sleep (which never returned on this silicon – SysTick may be silenced under polled-dispatch worker load).

Note
Single-producer (USBX class thread), single-consumer (demo).
Since
0.1.0

Definition at line 193 of file main.c.

◆ s_demo_diag

volatile demo_diag_t s_demo_diag = {}

Definition at line 182 of file main.c.

◆ s_demo_stack

UCHAR s_demo_stack[k_demo_thread_stack]
static

Stack backing storage for s_demo_thread.

Since
0.1.0

Definition at line 144 of file main.c.

◆ s_demo_thread

TX_THREAD s_demo_thread
static

ThreadX TCB for the USBX worker thread.

Note
Single-writer (worker only).
Since
0.1.0

Definition at line 137 of file main.c.

◆ s_device_framework_fs

UCHAR s_device_framework_fs[]
static

Definition at line 205 of file main.c.

◆ s_language_id_framework

UCHAR s_language_id_framework[] = {k_usb_langid_en_us_lo, k_usb_langid_en_us_hi}
static

USBX language-id table – US English.

Since
0.1.0

Definition at line 403 of file main.c.

◆ s_string_framework

UCHAR s_string_framework[]
static

USBX string descriptor table (vendor / product / serial).

Each entry: 2 bytes lang-id, 1 byte string index, 1 byte length, then ASCII bytes.

Since
0.1.0

Definition at line 330 of file main.c.

◆ s_usbx_pool

UCHAR s_usbx_pool[k_demo_usbx_pool_bytes]
static

USBX memory pool (USBX uses tx_byte_pool internally).

Since
0.1.0

Definition at line 151 of file main.c.