ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
main.c
Go to the documentation of this file.
1
75
76#include <stdint.h>
77#include <string.h>
78
79#include "ra8_board_ek_ra8d2.h"
80#include "ra8_boot_entry.h"
81#include "ra8_cgc.h"
82#include "ra8_err.h"
83#include "ra8_gpio_constants.h"
84#include "ra8_isr.h"
85#include "ra8_port_constants.h"
86#include "ra8_port_utils.h"
87#include "ra8_time.h"
88#include "ra8_usb.h"
89
90#ifndef RA8_OFF_TARGET
91#include "tx_api.h"
92#include "ux_api.h"
93#include "ux_dcd_ra8_usb.h"
94#include "ux_device_class_hid.h"
95#include "ux_device_stack.h"
96
97/* SysTick handler lives in libs/ra8_core/src/ra8_time.c -- the project's
98 * shared weak SysTick_Handler dispatches into ThreadX (via a weak
99 * extern to `_tx_timer_interrupt`) AND re-arms the USB storm-guard
100 * NVIC line (via a weak extern to `ux_dcd_ra8_usb_irq_reenable`), so
101 * no per-app override is needed. Closes Issue #8. */
102#endif
103
104/* -------------------------------------------------------------------------- */
105/* Pinout (FSP-aligned, EK-RA8D2 v1 User's Manual) */
106/* -------------------------------------------------------------------------- */
107
119
120/* -------------------------------------------------------------------------- */
121/* Tunables */
122/* -------------------------------------------------------------------------- */
123
133
147
161
173
174#ifndef RA8_OFF_TARGET
175
176/* -------------------------------------------------------------------------- */
177/* ThreadX worker + USBX pool storage */
178/* -------------------------------------------------------------------------- */
179
189
196
203
210static UX_SLAVE_CLASS_HID* s_hid_class = UX_NULL;
211
225volatile uint32_t g_usb_hid_match = 0U;
226
235volatile uint32_t g_usb_hid_mismatch = 0U;
236
237/* -------------------------------------------------------------------------- */
238/* HID Report Descriptor (3-button + X/Y boot mouse) */
239/* -------------------------------------------------------------------------- */
240
276static UCHAR s_report_descriptor[] = {
277 0x05U, 0x01U, /* Usage Page (Generic Desktop) */
278 0x09U, 0x02U, /* Usage (Mouse) */
279 0xA1U, 0x01U, /* Collection (Application) */
280 0x09U, 0x01U, /* Usage (Pointer) */
281 0xA1U, 0x00U, /* Collection (Physical) */
282 0x05U, 0x09U, /* Usage Page (Buttons) */
283 0x19U, 0x01U, /* Usage Min (1) */
284 0x29U, 0x03U, /* Usage Max (3) */
285 0x15U, 0x00U, /* Logical Min (0) */
286 0x25U, 0x01U, /* Logical Max (1) */
287 0x95U, 0x03U, /* Report Count (3) */
288 0x75U, 0x01U, /* Report Size (1) */
289 0x81U, 0x02U, /* Input (Data,Var,Abs) */
290 0x95U, 0x01U, /* Report Count (1) */
291 0x75U, 0x05U, /* Report Size (5) */
292 0x81U, 0x03U, /* Input (Cnst,Var,Abs) padding */
293 0x05U, 0x01U, /* Usage Page (Generic Desktop) */
294 0x09U, 0x30U, /* Usage (X) */
295 0x09U, 0x31U, /* Usage (Y) */
296 0x15U, 0x81U, /* Logical Min (-127) */
297 0x25U, 0x7FU, /* Logical Max ( 127) */
298 0x75U, 0x08U, /* Report Size (8) */
299 0x95U, 0x02U, /* Report Count (2) */
300 0x81U, 0x06U, /* Input (Data,Var,Rel) */
301 0xC0U, /* End Collection (Physical) */
302 0xC0U, /* End Collection (Application) */
303};
304
305/* -------------------------------------------------------------------------- */
306/* USB descriptors (DEVICE + CONFIG + INTERFACE + HID + EP IN) */
307/* -------------------------------------------------------------------------- */
308
309/* VID/PID matches the prior bare-metal app (pid.codes test range). The
310 * configuration is one HID interface, one interrupt-IN endpoint, no
311 * OUT endpoint -- the boot mouse class profile.
312 *
313 * Total config-blob length:
314 * 9 (config) + 9 (interface) + 9 (HID class) + 7 (EP IN) = 34 bytes.
315 *
316 * Layout per USB 2.0 sec 9.6 and HID 1.11 sec 6.2.1.
317 */
318static UCHAR s_device_framework_fs[] = {
319 /* Device descriptor (USB 2.0 sec 9.6.1) -- 18 bytes. */
320 0x12U,
321 0x01U,
322 0x00U,
323 0x02U,
324 0x00U,
325 0x00U,
326 0x00U,
327 0x40U,
328 0x09U,
329 0x12U,
330 0x01U,
331 0x00U,
332 0x00U,
333 0x01U,
334 0x01U,
335 0x02U,
336 0x03U,
337 0x01U,
338 /* Configuration descriptor (USB 2.0 sec 9.6.3) -- 9 bytes.
339 * bmAttributes = 0x80 (bus-powered). 0xC0 (self-powered)
340 * conflicted with bMaxPower=100mA (50 * 2). */
341 0x09U,
342 0x02U,
343 0x22U,
344 0x00U,
345 0x01U,
346 0x01U,
347 0x00U,
348 0x80U,
349 0x32U,
350 /* Interface descriptor -- HID, boot subclass, mouse protocol. */
351 0x09U,
352 0x04U,
353 0x00U,
354 0x00U,
355 0x01U,
356 0x03U,
357 0x01U,
358 0x02U,
359 0x00U,
360 /* HID class descriptor (HID 1.11 sec 6.2.1) -- 9 bytes.
361 * Report-descriptor length is sizeof(s_report_descriptor) = 52,
362 * little-endian (0x34, 0x00). */
363 0x09U,
364 0x21U,
365 0x11U,
366 0x01U,
367 0x00U,
368 0x01U,
369 0x22U,
370 0x34U,
371 0x00U,
372 /* Endpoint descriptor: EP1 IN, interrupt, 8-byte MPS, 10 ms poll. */
373 0x07U,
374 0x05U,
375 0x81U,
376 0x03U,
377 0x08U,
378 0x00U,
379 0x0AU,
380};
381
382/* String descriptors -- vendor / product / serial. Each entry:
383 * 2 bytes lang-id, 1 byte string index, 1 byte string length,
384 * then ASCII bytes. */
385static UCHAR s_string_framework[] = {
386 /* idx 1: "Brighton Sikarskie" (18 chars). */
387 0x09U,
388 0x04U,
389 0x01U,
390 0x12U,
391 'B',
392 'r',
393 'i',
394 'g',
395 'h',
396 't',
397 'o',
398 'n',
399 ' ',
400 'S',
401 'i',
402 'k',
403 'a',
404 'r',
405 's',
406 'k',
407 'i',
408 'e',
409 /* idx 2: "EK-RA8D2 HID Mouse" (18 chars). */
410 0x09U,
411 0x04U,
412 0x02U,
413 0x12U,
414 'E',
415 'K',
416 '-',
417 'R',
418 'A',
419 '8',
420 'D',
421 '2',
422 ' ',
423 'H',
424 'I',
425 'D',
426 ' ',
427 'M',
428 'o',
429 'u',
430 's',
431 'e',
432 /* idx 3: "00000001" (8 chars). */
433 0x09U,
434 0x04U,
435 0x03U,
436 0x08U,
437 '0',
438 '0',
439 '0',
440 '0',
441 '0',
442 '0',
443 '0',
444 '1',
445};
446
447/* USBX LANGID descriptor 0x0409 (English-US), little-endian byte pair. */
448typedef enum : uint8_t {
452
454
455/* -------------------------------------------------------------------------- */
456/* HID activate / deactivate callbacks */
457/* -------------------------------------------------------------------------- */
458
470static VOID demo_hid_activate(VOID* hid_instance)
471{
472 s_hid_class = (UX_SLAVE_CLASS_HID*)hid_instance;
473}
474
486static VOID demo_hid_deactivate(VOID* hid_instance)
487{
488 (void)hid_instance;
489 s_hid_class = UX_NULL;
490}
491
511static UINT demo_hid_get_callback(UX_SLAVE_CLASS_HID* hid, UX_SLAVE_CLASS_HID_EVENT* hid_event)
512{
513 (void)hid;
514 hid_event->ux_device_class_hid_event_length = (ULONG)k_demo_hid_report_bytes;
515 hid_event->ux_device_class_hid_event_report_id = 0UL;
516 hid_event->ux_device_class_hid_event_report_type = (ULONG)UX_DEVICE_CLASS_HID_REPORT_TYPE_INPUT;
517 hid_event->ux_device_class_hid_event_buffer[k_demo_hid_idx_buttons] = 0U;
518 hid_event->ux_device_class_hid_event_buffer[k_demo_hid_idx_dx] = 0U;
519 hid_event->ux_device_class_hid_event_buffer[k_demo_hid_idx_dy] = 0U;
520 return UX_SUCCESS;
521}
522
523/* -------------------------------------------------------------------------- */
524/* Worker thread: bring USBX up + jiggle loop */
525/* -------------------------------------------------------------------------- */
526
540static void demo_build_jiggle(demo_phase_t phase, UCHAR* report)
541{
542 int8_t dx = k_demo_jiggle_zero;
543 int8_t dy = k_demo_jiggle_zero;
544 switch (phase) {
547 break;
550 break;
553 break;
554 case k_demo_phase_up:
556 break;
558 default:
559 break;
560 }
561 report[k_demo_hid_idx_buttons] = 0U;
562 report[k_demo_hid_idx_dx] = (UCHAR)dx;
563 report[k_demo_hid_idx_dy] = (UCHAR)dy;
564}
565
581{
582 if (_ux_system_initialize(s_usbx_pool, k_demo_usbx_pool_bytes, UX_NULL, 0) != UX_SUCCESS) {
583 return UX_ERROR;
584 }
585 return _ux_device_stack_initialize((UCHAR*)UX_NULL,
586 0,
588 sizeof(s_device_framework_fs),
590 sizeof(s_string_framework),
593 UX_NULL);
594}
595
611{
612 UX_SLAVE_CLASS_HID_PARAMETER hid_params = {
613 .ux_slave_class_hid_instance_activate = demo_hid_activate,
614 .ux_slave_class_hid_instance_deactivate = demo_hid_deactivate,
615 .ux_device_class_hid_parameter_report_address = s_report_descriptor,
616 .ux_device_class_hid_parameter_report_id = 0UL,
617 .ux_device_class_hid_parameter_report_length = (ULONG)sizeof(s_report_descriptor),
618 .ux_device_class_hid_parameter_callback = UX_NULL,
619 .ux_device_class_hid_parameter_get_callback = demo_hid_get_callback,
620 };
621 static UCHAR s_class_name[] = "ux_slave_class_hid";
622
623 return _ux_device_stack_class_register(s_class_name,
624 _ux_device_class_hid_entry,
625 1,
626 0,
627 &hid_params);
628}
629
644{
645 UX_SLAVE_CLASS_HID_EVENT hid_event;
646 (void)memset(&hid_event, 0, sizeof(hid_event));
647 hid_event.ux_device_class_hid_event_length = (ULONG)k_demo_hid_report_bytes;
648 hid_event.ux_device_class_hid_event_report_id = 0UL;
649 hid_event.ux_device_class_hid_event_report_type = (ULONG)UX_DEVICE_CLASS_HID_REPORT_TYPE_INPUT;
650 demo_build_jiggle(*phase, hid_event.ux_device_class_hid_event_buffer);
651
652 if (_ux_device_class_hid_event_set(s_hid_class, &hid_event) == UX_SUCCESS) {
654 *phase = (demo_phase_t)(((uint8_t)(*phase + 1U)) % k_demo_phase_count);
655 g_usb_hid_match += 1U;
656 } else {
657 g_usb_hid_mismatch += 1U;
658 }
659}
660
661static VOID demo_worker(ULONG arg)
662{
663 (void)arg;
664
665 if (demo_usbx_stack_up() != UX_SUCCESS) {
666 return;
667 }
668 if (demo_hid_class_register() != UX_SUCCESS) {
669 return;
670 }
672 return;
673 }
675 return;
676 }
677
678 /* Jiggle loop. INTSTS0 is drained by the bridge's own polled-dispatch
679 * worker (spawned inside ux_dcd_ra8_usb_initialize BEFORE the
680 * ra8_usb_device_attach(true) above raised DPRPU), so this thread
681 * only needs to push HID reports once per period. */
683 while (1) {
684 if (s_hid_class == UX_NULL) {
686 continue;
687 }
688 demo_jiggle_send(&phase);
690 }
691}
692
693/* -------------------------------------------------------------------------- */
694/* ThreadX kernel entry: spawn the worker */
695/* -------------------------------------------------------------------------- */
696
708VOID tx_application_define(VOID* first_unused_memory)
709{
710 static CHAR s_thread_name[] = "usb_hid_device";
711
712 (void)first_unused_memory;
716 0UL,
719 8U, /* priority */
720 8U, /* preempt threshold */
723}
724#endif /* !RA8_OFF_TARGET */
725
726/* -------------------------------------------------------------------------- */
727/* Startup helpers */
728/* -------------------------------------------------------------------------- */
729
739static void demo_panic_halt(void)
740{
741 while (1) {
742 __asm__ volatile("wfi");
743 }
744}
745
759[[nodiscard]] static ra8_err_t demo_pins_init(void)
760{
762 if (err != k_ra8_ok) {
763 return err;
764 }
765 /* VBUSEN as GPIO output LOW for USB device mode. Peripheral routing
766 * forces VBUSEN HIGH (host mode) which blocks device enumeration. */
768 if (err != k_ra8_ok) {
769 return err;
770 }
772 if (err != k_ra8_ok) {
773 return err;
774 }
776}
777
789void main(void)
790{
791 uint32_t cpuclk0_hz = 0U;
792
793 if (ra8_cgc_init() != k_ra8_ok) {
795 }
796 /* Bring up PLL2 -> USBCKCR / USBCKDIVCR so USBFS sees a spec-compliant
797 * 48 MHz reference (PLL2P 240 MHz / 5). Without this the SIE never
798 * leaves Powered after host bus-reset. */
801 }
804 }
805 if (ra8_time_init(cpuclk0_hz) != k_ra8_ok) {
807 }
810 }
811 if (demo_pins_init() != k_ra8_ok) {
813 }
814
816
817#ifndef RA8_OFF_TARGET
818 /* tx_kernel_enter is __noreturn -- it never comes back. */
819 tx_kernel_enter();
820#endif
821
823}
void main(void)
Secure fallback main entry point.
Definition main.c:37
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
void tx_application_define(void *first_unused_memory)
ThreadX system-define hook: build worker thread + byte pool.
Definition main.c:942
static UCHAR s_string_framework[]
USBX string descriptor table (vendor / product / serial).
Definition main.c:299
static UCHAR s_usbx_pool[k_wlun_usbx_pool_bytes]
USBX memory pool (USBX uses tx_byte_pool internally).
Definition main.c:193
usb_langid_byte_t
Definition main.c:358
@ k_usb_langid_en_us_lo
LANGID 0x0409 low byte.
Definition main.c:359
@ k_usb_langid_en_us_hi
LANGID 0x0409 high byte.
Definition main.c:360
static UCHAR s_device_framework_fs[]
Definition main.c:234
static UCHAR s_language_id_framework[]
USBX language-id table – US English.
Definition main.c:368
static void demo_panic_halt(void)
Halt forever in WFI – used as a panic stop on init failure.
Definition main.c:93
static const ra8_port_pin_t k_demo_pin_vbus
USB_FS VBUS pin, packed ra8_port_pin_t.
Definition main.c:153
static ra8_err_t demo_pins_init(void)
Route the four USB-FS pins to the USBFS controller.
Definition main.c:491
static const ra8_port_pin_t k_demo_pin_dp
USB_FS D+ pin, packed ra8_port_pin_t.
Definition main.c:157
static const ra8_port_pin_t k_demo_pin_vbusen
USB_FS VBUSEN pin, packed ra8_port_pin_t.
Definition main.c:155
static const ra8_port_pin_t k_demo_pin_dm
USB_FS D- pin, packed ra8_port_pin_t.
Definition main.c:159
static CHAR s_thread_name[]
Definition main.c:212
static UINT demo_usbx_stack_up(void)
Brings USBX system + device stack up with the FS framework.
Definition main.c:481
@ 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
demo_jiggle_t
Per-step cursor delta values for the autonomous jiggle.
Definition main.c:156
@ k_demo_jiggle_zero
No motion on the inactive axis.
Definition main.c:158
@ k_demo_jiggle_neg
Reverse of k_step.
Definition main.c:159
@ k_demo_jiggle_step
Magnitude of each jiggle step.
Definition main.c:157
static void demo_build_jiggle(demo_phase_t phase, UCHAR *report)
Build the boot-mouse report for one phase of the jiggle.
Definition main.c:540
static UINT demo_hid_get_callback(UX_SLAVE_CLASS_HID *hid, UX_SLAVE_CLASS_HID_EVENT *hid_event)
HID GET_REPORT / SET_REPORT control-pipe callback.
Definition main.c:511
volatile uint32_t g_usb_hid_match
HIL liveness counter – incremented on every successful _ux_device_class_hid_event_set (a HID report q...
Definition main.c:225
demo_hid_report_t
Sizing for the boot-protocol mouse input report.
Definition main.c:141
@ k_demo_hid_idx_dy
Byte offset for Y delta.
Definition main.c:145
@ k_demo_hid_idx_dx
Byte offset for X delta.
Definition main.c:144
@ k_demo_hid_report_bytes
Boot mouse report width.
Definition main.c:142
@ k_demo_hid_idx_buttons
Byte offset for buttons.
Definition main.c:143
@ k_demo_jiggle_period_ticks
ThreadX ticks between sends.
Definition main.c:131
static VOID demo_hid_deactivate(VOID *hid_instance)
HID deactivate callback.
Definition main.c:486
volatile uint32_t g_usb_hid_mismatch
HIL failure counter – incremented when _ux_device_class_hid_event_set returns a non-success status (q...
Definition main.c:235
static VOID demo_hid_activate(VOID *hid_instance)
HID activate callback.
Definition main.c:470
static UINT demo_hid_class_register(void)
Registers the HID class with the configured report descriptor.
Definition main.c:610
demo_phase_t
Index into the four-step jiggle pattern.
Definition main.c:166
@ k_demo_phase_count
Modulus.
Definition main.c:171
@ k_demo_phase_left
-X, 0Y.
Definition main.c:169
@ k_demo_phase_down
0X, +Y.
Definition main.c:168
@ k_demo_phase_right
+X, 0Y.
Definition main.c:167
@ k_demo_phase_up
0X, -Y.
Definition main.c:170
static void demo_jiggle_send(demo_phase_t *phase)
Push a single HID jiggle event in the given phase.
Definition main.c:643
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.
ra8_err_t ra8_board_led_init(ra8_board_led_id_t led)
Configure led as a digital output, initial level low (off).
@ k_ra8_board_led1
LED1, BLUE, P600 (jumper E27).
@ k_ra8_board_usbfs_pin_dm
P8_15 D-.
@ k_ra8_board_usbfs_pin_vbusen
P5_00 VBUSEN GPIO.
@ k_ra8_board_usbfs_pin_vbus
P4_07 VBUS sense.
@ k_ra8_board_usbfs_pin_dp
P8_14 D+.
Boot entry points shared between a vector table and its startup code.
High-level Clock Generation Circuit driver.
ra8_err_t ra8_cgc_get_clock_hz(ra8_clock_id_t id, uint32_t *out_hz)
Query the current frequency of a clock-tree domain.
Definition ra8_cgc.c:132
@ k_ra8_clock_id_cpuclk0
Cortex-M85 CPUCLK0.
Definition ra8_cgc.h:70
ra8_err_t ra8_cgc_init(void)
Configure the clock tree to a safe default.
Definition ra8_cgc.c:727
ra8_err_t ra8_cgc_usbfs_clock_enable(void)
Bring up the USB-FS module clock (USBCKCR / USBCKDIVCR).
Error Code Definitions for ra8-firmware.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
void * memset(void *dst, int value, size_t n)
Fill memory with a constant byte value.
PSEL codes for peripheral pin routing on the RA8D2.
@ k_ra8_psel_usb_fs
10011b: USB Full-Speed.
NVIC + ICU IELSR allocator.
void ra8_isr_globals_enable(void)
Globally enable maskable interrupts (PRIMASK = 0).
Definition ra8_isr.c:439
Typed Port / Pin Constants for the RA8D2 IOPORT Module.
ra8_port_pin_t
Packed (port << 8) | pin pin identifier.
@ k_ra8_level_low
Drive or read 0.
High-level GPIO helpers on top of the PORT + PFS register layer.
ra8_err_t ra8_gpio_output_init(ra8_port_pin_t pin, ra8_level_t init_level)
Configure a pin as a digital output and drive it to an initial level.
Definition gpio.c:88
ra8_err_t ra8_pfs_route_peripheral(ra8_port_pin_t pin, ra8_psel_t psel, const char *owner)
Route a pin to a non-IRQ peripheral function via PFS.PSEL.
Definition gpio.c:238
SysTick-based tick counter, delay and timestamp helpers.
ra8_err_t ra8_time_init(uint32_t cpu_hz)
Initialise SysTick for a 1 kHz tick interrupt.
Definition ra8_time.c:59
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_fs
Full-Speed controller (USBFS @ 0x40250000).
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.
static UCHAR s_report_descriptor[]
static UX_SLAVE_CLASS_HID * s_hid_class
Active HID class instance, captured by the activate callback.
USBX device-controller-driver (DCD) bridge to ra8_usb.
ra8_err_t ux_dcd_ra8_usb_initialize(ra8_usb_speed_t speed)
Register the ra8_usb bridge as the active USBX DCD.