ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
tz_secure_only_usb_hs_steps.c
Go to the documentation of this file.
1
26
28
29#include <stdint.h>
30#include <string.h>
31
32#include "ra8_board_ek_ra8d2.h"
33#include "ra8_err.h"
34#include "ra8_isr.h"
35#include "ra8_usb.h"
36#include "ra8_usb_regs.h"
37
39typedef enum : uintptr_t {
40 k_usbhs_psarb_addr = 0x40204004UL,
41 k_usbhs_pparb_addr = 0x4020401CUL,
43
50
51#ifndef RA8_OFF_TARGET
52#include "tx_api.h"
53#include "ux_api.h"
54#include "ux_dcd_ra8_usb.h"
55#include "ux_device_class_cdc_acm.h"
56#include "ux_device_stack.h"
57#include "ux_system.h"
58
59/* SysTick handler lives in libs/ra8_core/src/ra8_time.c -- the project's
60 * shared weak SysTick_Handler dispatches into ThreadX (via a weak
61 * extern to `_tx_timer_interrupt`) AND re-arms the USB storm-guard
62 * NVIC line (via a weak extern to `ux_dcd_ra8_usb_irq_reenable`), so
63 * no per-app override is needed. Closes Issue #8. */
64
65/* -------------------------------------------------------------------------- */
66/* ThreadX worker + USBX pool storage */
67/* -------------------------------------------------------------------------- */
68
76
83
101
107static UCHAR s_intenb0_watchdog_stack[1024U];
108
122volatile uint32_t s_intenb0_rearm_count = 0U;
123
130volatile uint32_t s_intenb0_watchdog_started = 0U;
131
148volatile uint32_t s_host_kick_done = 0U;
149
156
165/* Note the placement of `volatile`: we want the POINTER itself to be
166 * volatile so the worker re-reads it from memory each loop iteration.
167 * `volatile UX_SLAVE_CLASS_CDC_ACM*` would only make the pointee
168 * volatile and the compiler is free to cache the NULL pointer value
169 * in a register -- which is exactly the bug that masked the activate
170 * write for the entire echo loop. */
171static UX_SLAVE_CLASS_CDC_ACM* volatile s_cdc_acm = UX_NULL;
172
173/* JLink-readable counters: how many times activate / deactivate ran. */
174volatile uint32_t s_cdc_activate_count = 0U;
175volatile uint32_t s_cdc_activate_post_put = 0U;
176volatile uint32_t s_cdc_deactivate_count = 0U;
177volatile uint32_t s_pendsv_observed_run_count = 0U;
178
183typedef struct {
184 volatile uint32_t loop_iter;
185 volatile uint32_t loop_cdc_null;
186 volatile uint32_t loop_pre_read;
187 volatile uint32_t loop_post_read;
188 volatile uint32_t loop_read_ok;
189 volatile uint32_t loop_read_zero;
190 volatile uint32_t loop_pre_write;
191 volatile uint32_t loop_post_write;
193
201
219static volatile uint32_t s_boot_probe = 0U;
220
235volatile uint16_t s_syscfg_in_echo_loop = 0U;
236
244volatile uint16_t s_lpsts_in_echo_loop = 0U;
245
264volatile uint32_t s_psar_state = 0U;
265
282volatile uint32_t s_ppar_state = 0U;
283
301
309static TX_SEMAPHORE s_cdc_active_sem;
310
311/* Forward declarations -------------------------------------------------- */
312
313static VOID intenb0_watchdog_entry(ULONG arg);
314
315/* -------------------------------------------------------------------------- */
316/* CDC-ACM activate / deactivate callbacks */
317/* -------------------------------------------------------------------------- */
318
330static VOID demo_cdc_activate(VOID* cdc_instance)
331{
332 s_cdc_acm = (UX_SLAVE_CLASS_CDC_ACM*)cdc_instance;
333 if (_ux_system_slave != UX_NULL) {
334 _ux_system_slave->ux_system_slave_device.ux_slave_device_state =
335 (unsigned long)UX_DEVICE_CONFIGURED;
336 }
338 /* Enable bridge-side auto-echo for the CDC bulk pair (EP2 OUT -> EP1 IN).
339 * The worker thread DOES get scheduled now (the IRQ-mask + SysTick re-
340 * enable in ux_dcd_ra8_usb.c stops the USBR-driven storm) and the proper
341 * _ux_device_class_cdc_acm_read / _write path works for individual
342 * packets, but the per-transfer round-trip latency is ~1 ms ThreadX
343 * tick because of the IRQ re-enable cadence. Auto-echo bypasses the
344 * thread mode entirely and runs the mirror inside the dispatch
345 * handler -- which is invoked on every real BRDY/BEMP -- so the
346 * throughput is line-rate and integrity is perfect. */
348 (void)tx_semaphore_put(&s_cdc_active_sem);
350}
351
363static VOID demo_cdc_deactivate(VOID* cdc_instance)
364{
365 (void)cdc_instance;
367 s_cdc_acm = UX_NULL;
368}
369
370/* -------------------------------------------------------------------------- */
371/* Worker thread: bring USBX up + echo loop */
372/* -------------------------------------------------------------------------- */
373
412
432{
433 static UCHAR s_class_name[] = "ux_slave_class_cdc_acm";
434
435 UX_SLAVE_CLASS_CDC_ACM_PARAMETER cdc_params = {
436 .ux_slave_class_cdc_acm_instance_activate = demo_cdc_activate,
437 .ux_slave_class_cdc_acm_instance_deactivate = demo_cdc_deactivate,
438 .ux_slave_class_cdc_acm_parameter_change = UX_NULL,
439 };
441 return _ux_device_stack_class_register(s_class_name,
442 _ux_device_class_cdc_acm_entry,
443 1, /* configuration # */
444 0, /* interface # */
445 &cdc_params) == UX_SUCCESS;
446}
447
479static bool demo_worker_start_dcd(void)
480{
482 s_host_kick_done = 0U;
485 return false;
486 }
490 return false;
491 }
493 return true;
494}
495
515{
516 static CHAR s_thread_name[] = "usbhs_intenb0_wdog";
517
521 0UL,
524 15U, /* lower priority than echo worker */
525 15U,
528}
529
548{
551 volatile const uint32_t* const psarb_p = (volatile const uint32_t*)k_usbhs_psarb_addr;
552 volatile const uint32_t* const pparb_p = (volatile const uint32_t*)k_usbhs_pparb_addr;
553 s_psar_state = *psarb_p;
554 s_ppar_state = *pparb_p;
555}
556
571static void demo_worker_echo_loop(void)
572{
573 UCHAR buf[k_demo_echo_buf_bytes];
574 ULONG n = 0UL;
575 while (1) {
576 s_demo_diag.loop_iter++;
577 UX_SLAVE_CLASS_CDC_ACM* cdc_snap = (UX_SLAVE_CLASS_CDC_ACM*)s_cdc_acm;
578 if (cdc_snap == UX_NULL) {
579 s_demo_diag.loop_cdc_null++;
580 /* Bounded-wait sleep instead of WAIT_FOREVER/relinquish. On this
581 * silicon both tx_semaphore_get(TX_WAIT_FOREVER) and a tight
582 * relinquish loop leave the worker un-schedulable once an
583 * ISR-context activate runs. tx_thread_sleep with a small tick
584 * count keeps the thread on a timer-resume path, which PendSV
585 * does pick up here. The next iteration re-reads volatile
586 * s_cdc_acm and proceeds. */
588 continue;
589 }
590 if (_ux_system_slave != UX_NULL) {
591 _ux_system_slave->ux_system_slave_device.ux_slave_device_state =
592 (unsigned long)UX_DEVICE_CONFIGURED;
593 }
594 s_demo_diag.loop_pre_read++;
595 UINT read_status = _ux_device_class_cdc_acm_read(cdc_snap, buf, sizeof(buf), &n);
596 s_demo_diag.loop_post_read++;
597 if (read_status != UX_SUCCESS) {
599 continue;
600 }
601 s_demo_diag.loop_read_ok++;
602 if (n == 0UL) {
603 s_demo_diag.loop_read_zero++;
604 continue;
605 }
606 s_demo_diag.loop_pre_write++;
607 if (_ux_device_class_cdc_acm_write(cdc_snap, buf, n, &n) != UX_SUCCESS) {
608 continue;
609 }
610 s_demo_diag.loop_post_write++;
611 for (ULONG i = 0UL; i < n; i++) {
613 }
614 }
615}
616
628static VOID demo_worker(ULONG arg)
629{
630 (void)arg;
631
633 if (!demo_worker_usbx_init()) {
634 return;
635 }
637 return;
638 }
639 if (!demo_worker_start_dcd()) {
640 return;
641 }
643
647}
648
649/* -------------------------------------------------------------------------- */
650/* INTENB0 re-arm watchdog */
651/* -------------------------------------------------------------------------- */
652
666{
667 (void)arg;
668 volatile r_usb_regs_t* reg = ra8_usb_hs();
670 while (1) {
671 if (reg->INTENB0 != (uint16_t)k_ra8_int0_full_mask) {
672 reg->INTENB0 = (uint16_t)k_ra8_int0_full_mask;
674 }
675 tx_thread_sleep(1UL);
676 }
677}
678
679/* -------------------------------------------------------------------------- */
680/* ThreadX kernel entry: spawn the worker */
681/* -------------------------------------------------------------------------- */
682
683VOID tx_application_define(VOID* first_unused_memory)
684{
685 static CHAR s_semaphore_name[] = "cdc_active";
686 static CHAR s_thread_name[] = "usb_cdc_echo_hs";
687
688 (void)first_unused_memory;
689 (void)tx_semaphore_create(&s_cdc_active_sem, s_semaphore_name, 0U);
693 0UL,
696 8U, /* priority */
697 8U, /* preempt threshold */
700}
701#endif /* !RA8_OFF_TARGET */
static TX_THREAD s_demo_thread
Definition main.c:237
demo_config_t
Compile-time settings for the HTTPS client demo.
Definition main.c:87
@ k_demo_thread_stack
Demo thread stack.
Definition main.c:89
static UCHAR s_demo_stack[k_demo_thread_stack]
Definition main.c:238
static UCHAR s_usbx_pool[k_wlun_usbx_pool_bytes]
USBX memory pool (USBX uses tx_byte_pool internally).
Definition main.c:193
static CHAR s_thread_name[]
Definition main.c:212
static UX_SLAVE_CLASS_CDC_ACM * s_cdc_acm
Active CDC-ACM class instance, captured by the activate callback.
Definition main.c:195
static TX_SEMAPHORE s_cdc_active_sem
Posted by the activate callback so the echo worker blocks on it instead of polling s_cdc_acm with tx_...
Definition main.c:205
volatile demo_diag_t s_demo_diag
Externally-readable counters for demo loop progress.
Definition main.c:182
static VOID demo_cdc_activate(VOID *cdc_instance)
CDC-ACM activate callback.
Definition main.c:420
@ k_demo_echo_buf_bytes
One bulk-FS packet per recv/send.
Definition main.c:121
@ k_demo_idle_ticks
Idle back-off when no class active.
Definition main.c:122
@ k_demo_usbx_pool_bytes
USBX pool: 32 KiB; CDC-ACM enum exhausts 16 KiB.
Definition main.c:120
static VOID demo_worker(ULONG arg)
Worker thread entry.
Definition main.c:602
static VOID demo_cdc_deactivate(VOID *cdc_instance)
CDC-ACM deactivate callback.
Definition main.c:457
Board-support layer for the Renesas EK-RA8D2 v1 evaluation kit.
ra8_err_t ra8_board_led_toggle(ra8_board_led_id_t led)
Toggle led's output state.
@ k_ra8_board_led1
LED1, BLUE, P600 (jumper E27).
Error Code Definitions for ra8-firmware.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
NVIC + ICU IELSR allocator.
Native USB controller driver public API (device + host modes).
ra8_err_t ra8_usb_device_attach(ra8_usb_speed_t speed, bool attached)
Raise / drop the D+ pull-up to advertise the device to the host.
@ k_ra8_usb_speed_hs
High-Speed controller (USBHS @ 0x40351000).
USB Full-Speed + High-Speed controller layout for the Renesas RA8D2.
static volatile uint16_t * ra8_usbhs_lpsts(void)
Get pointer to USBHS LPSTS register.
@ k_ra8_int0_full_mask
Device-mode event mask: BRDY | NRDY | BEMP | CTRT | DVST | VBSE.
static volatile r_usb_regs_t * ra8_usb_hs(void)
Get pointer to the USB HS controller register block.
unsigned int UINT
ThreadX-compatible unsigned int (host stub).
#define tx_thread_create
#define tx_thread_sleep
#define TX_NO_TIME_SLICE
char CHAR
ThreadX-compatible CHAR (host stub).
#define TX_AUTO_START
unsigned long ULONG
ThreadX-compatible unsigned long (host stub).
Opaque thread stand-in for the host build.
Demo-loop counters; read via JLink to localise stalls.
Definition main.c:165
USB FS / HS register window (device-mode subset).
volatile uint16_t INTENB0
+0x030 Interrupt Enable 0.
volatile uint16_t SYSCFG
+0x000 System Configuration.
volatile uint16_t s_lpsts_in_echo_loop
LPSTS snapshot on first echo-loop iteration.
static bool demo_worker_usbx_init(void)
Bring up USBX system + device stack with HS+FS frameworks.
volatile uint32_t s_pendsv_observed_run_count
static TX_THREAD s_intenb0_watchdog_thread
ThreadX TCB for the INTENB0 re-arm watchdog.
volatile uint32_t s_psar_state
Snapshot of R_PSCU->PSARB on entry to the echo loop.
VOID tx_application_define(VOID *first_unused_memory)
volatile uint32_t s_intenb0_watchdog_started
Set to 1 once the watchdog thread has begun polling.
boot_probe_step_t
Bisect-probe step values for s_boot_probe.
@ k_boot_probe_post_board_usbhs_init
after ra8_board_usbhs_device_init.
@ k_boot_probe_pre_dev_stack_init
before _ux_device_stack_init.
@ k_boot_probe_post_dev_attach
after ra8_usb_device_attach.
@ k_boot_probe_enter_echo_loop
entering echo while(1).
@ k_boot_probe_post_ux_dcd_init
after ux_dcd_ra8_usb_initialize.
@ k_boot_probe_thread_entry
worker entry.
@ k_boot_probe_pre_sys_init
before _ux_system_initialize.
@ k_boot_probe_pre_class_register
before _ux_device_stack_class_register.
@ k_boot_probe_pre_ux_dcd_init
before ux_dcd_ra8_usb_initialize.
@ k_boot_probe_pre_dev_attach
before ra8_usb_device_attach.
@ k_boot_probe_pre_board_usbhs_init
before ra8_board_usbhs_device_init.
volatile uint32_t s_ppar_state
Snapshot of R_PSCU->PPARB on entry to the echo loop.
usbhs_sec_reg_addr_t
USBHS security/privilege attribution register addresses.
@ k_usbhs_psarb_addr
Peripheral Security Attribution B.
@ k_usbhs_pparb_addr
Peripheral Privilege Attribution B.
volatile uint32_t s_intenb0_rearm_count
Number of times the watchdog has re-asserted INTENB0 = 0xFF00.
static bool demo_worker_start_dcd(void)
Plug the DCD bridge into the device stack and attach the bus.
volatile uint32_t s_cdc_activate_post_put
static VOID demo_cdc_activate(VOID *cdc_instance)
CDC-ACM activate callback.
static UCHAR s_intenb0_watchdog_stack[1024U]
Stack backing storage for the INTENB0 watchdog thread.
static VOID demo_worker(ULONG arg)
Worker thread entry.
volatile uint32_t s_host_kick_done
Set to 1 once the host-mode PHY analog kick has been applied.
static void demo_worker_spawn_intenb0_watchdog(void)
Spawn the INTENB0 re-arm watchdog thread.
static void demo_worker_echo_loop(void)
Run the CDC-ACM echo loop forever.
static void demo_worker_capture_echo_probes(void)
Capture bisect probes ONCE on entry to the echo loop.
static bool demo_worker_register_cdc(void)
Register the CDC-ACM class against configuration 1, interface 0.
volatile uint32_t s_cdc_activate_count
static VOID intenb0_watchdog_entry(ULONG arg)
Watchdog entry: re-asserts USBHS INTENB0 = 0xFF00 if cleared.
volatile uint16_t s_syscfg_in_echo_loop
SYSCFG snapshot taken on the FIRST iteration of the echo loop.
static VOID demo_cdc_deactivate(VOID *cdc_instance)
CDC-ACM deactivate callback.
static volatile uint32_t s_boot_probe
Temporary bisect probe for USBHS bring-up HardFault.
volatile uint32_t s_cdc_deactivate_count
examples/ek_ra8d2/hw_validated/manual/tz_secure_only_usb_hs/inc/tz_secure_only_usb_hs_steps....
UCHAR s_tz_secure_only_usb_hs_language_id_framework[k_tz_secure_only_usb_hs_language_id_framework_len]
USBX language-id table – US English (LANGID 0x0409).
UCHAR s_tz_secure_only_usb_hs_device_framework_fs[k_tz_secure_only_usb_hs_device_framework_fs_len]
Full-Speed CDC-ACM composite device framework (64-byte bulk MPS).
UCHAR s_tz_secure_only_usb_hs_string_framework[k_tz_secure_only_usb_hs_string_framework_len]
USBX string descriptor table (vendor / product / serial).
UCHAR s_tz_secure_only_usb_hs_device_framework_hs[k_tz_secure_only_usb_hs_device_framework_hs_len]
High-Speed CDC-ACM composite device framework (512-byte bulk MPS).
USBX device-controller-driver (DCD) bridge to ra8_usb.
void ux_dcd_ra8_usb_auto_echo_enable(uint8_t out_pipe, uint8_t in_pipe)
Enable ISR-side auto-echo from a bulk OUT pipe to a bulk IN pipe.
ra8_err_t ux_dcd_ra8_usb_initialize(ra8_usb_speed_t speed)
Register the ra8_usb bridge as the active USBX DCD.