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
50
51#include <stdint.h>
52#include <string.h>
53
54#include "ra8_board_ek_ra8d2.h"
55#include "ra8_boot_entry.h"
56#include "ra8_cgc.h"
57#include "ra8_err.h"
58#include "ra8_fs.h"
59#include "ra8_gpio_constants.h"
60#include "ra8_isr.h"
61#include "ra8_port_constants.h"
62#include "ra8_port_utils.h"
63#include "ra8_time.h"
64#include "ra8_usb.h"
65#include "ra8_usb_hmsc.h"
66#include "ra8_xspi.h"
68
69#ifndef RA8_OFF_TARGET
70#include "tx_api.h"
71#include "ux_api.h"
72#include "ux_dcd_ra8_usb.h"
73#include "ux_device_class_storage.h"
74#include "ux_device_stack.h"
75
76/* Strong SysTick override: route the tick into BOTH the ra8_time millisecond
77 * counter (for ra8_delay_ms and the polled host stack's timeouts) AND
78 * ThreadX's timer (for tx_thread_sleep and USBX class-thread scheduling).
79 * The 1 ms pulse also recovers the DCD's storm-guard NVIC mask. */
80
81extern void _tx_timer_interrupt(void);
82
94static volatile bool s_tx_kernel_up = false;
95
96void SysTick_Handler(void);
105#endif
106
107/* -------------------------------------------------------------------------- */
108/* Pinout (FSP-aligned, EK-RA8D2 v1 User's Manual) */
109/* -------------------------------------------------------------------------- */
110
113
116
119
122
125
128
129#ifndef RA8_OFF_TARGET
130
131/* -------------------------------------------------------------------------- */
132/* ThreadX workers + USBX pool storage */
133/* -------------------------------------------------------------------------- */
134
142
149
157
164
171
172/* SCSI INQUIRY strings -- 8 / 16 / 4 byte fields per SBC-3. */
173static UCHAR s_msc_vendor_id[] = "RA8D2 ";
174static UCHAR s_msc_product_id[] = "SELFTEST OSPI RO";
175static UCHAR s_msc_product_rev[] = "0001";
176
177/* -------------------------------------------------------------------------- */
178/* J-Link probes */
179/* -------------------------------------------------------------------------- */
180
182static volatile uint32_t s_dbg_ospi_id;
184static volatile uint32_t s_dbg_ospi_prov = (uint32_t)k_selftest_no_mismatch;
185
186/* -------------------------------------------------------------------------- */
187/* USB descriptors (DEVICE + CONFIG + MSC interface + endpoints) */
188/* -------------------------------------------------------------------------- */
189
190/* Single-interface MSC config: bulk-only transport, SCSI command set.
191 * EP1 IN + EP2 OUT, 64-byte MPS. PID 0x000E marks the self-test
192 * identity apart from the Mac-facing usb_msc_mram (0x000C). */
193static UCHAR s_device_framework_fs[] = {
194 /* Device descriptor (USB 2.0 sec 9.6.1) -- 18 bytes. */
195 0x12U,
196 0x01U,
197 0x00U,
198 0x02U,
199 0x00U, /* class = per-interface */
200 0x00U,
201 0x00U,
202 0x40U,
203 0x09U,
204 0x12U,
205 0x10U, /* PID = 0x0010 (pid.codes test). */
206 0x00U,
207 0x00U,
208 0x01U,
209 0x01U,
210 0x02U,
211 0x03U,
212 0x01U,
213 /* Configuration descriptor (32 bytes total). */
214 0x09U,
215 0x02U,
216 0x20U,
217 0x00U,
218 0x01U,
219 0x01U,
220 0x00U,
221 0x80U,
222 0x32U,
223 /* Interface descriptor -- MSC, SCSI, BBB. */
224 0x09U,
225 0x04U,
226 0x00U,
227 0x00U,
228 0x02U,
229 0x08U,
230 0x06U,
231 0x50U,
232 0x00U,
233 /* Bulk-IN endpoint (EP1 IN, 64-byte MPS). */
234 0x07U,
235 0x05U,
236 0x81U,
237 0x02U,
238 0x40U,
239 0x00U,
240 0x00U,
241 /* Bulk-OUT endpoint (EP2 OUT, 64-byte MPS). */
242 0x07U,
243 0x05U,
244 0x02U,
245 0x02U,
246 0x40U,
247 0x00U,
248 0x00U,
249};
250
258static UCHAR s_string_framework[] = {
259 /* idx 1: "Brighton Sikarskie". */
260 0x09U,
261 0x04U,
262 0x01U,
263 0x12U,
264 'B',
265 'r',
266 'i',
267 'g',
268 'h',
269 't',
270 'o',
271 'n',
272 ' ',
273 'S',
274 'i',
275 'k',
276 'a',
277 'r',
278 's',
279 'k',
280 'i',
281 'e',
282 /* idx 2: "RA8D2 SELFTEST". */
283 0x09U,
284 0x04U,
285 0x02U,
286 0x0EU,
287 'R',
288 'A',
289 '8',
290 'D',
291 '2',
292 ' ',
293 'S',
294 'E',
295 'L',
296 'F',
297 'T',
298 'E',
299 'S',
300 'T',
301 /* idx 3: serial. */
302 0x09U,
303 0x04U,
304 0x03U,
305 0x08U,
306 '0',
307 '0',
308 '0',
309 '0',
310 '0',
311 '0',
312 '1',
313 '0',
314};
315
316/* USBX LANGID descriptor 0x0409 (English-US), little-endian byte pair. */
317typedef enum : uint8_t {
321
328
329/* -------------------------------------------------------------------------- */
330/* Threads */
331/* -------------------------------------------------------------------------- */
332
351{
352 if (_ux_system_initialize(s_usbx_pool, k_selftest_usbx_pool_bytes, UX_NULL, 0) != UX_SUCCESS) {
353 return UX_ERROR;
354 }
355 return _ux_device_stack_initialize((UCHAR*)UX_NULL,
356 0,
358 sizeof(s_device_framework_fs),
360 sizeof(s_string_framework),
363 UX_NULL);
364}
365
384{
385 UX_SLAVE_CLASS_STORAGE_PARAMETER msc_params;
386 (void)memset(&msc_params, 0, sizeof(msc_params));
387 msc_params.ux_slave_class_storage_parameter_number_lun = 1UL;
388 msc_params.ux_slave_class_storage_parameter_vendor_id = s_msc_vendor_id;
389 msc_params.ux_slave_class_storage_parameter_product_id = s_msc_product_id;
390 msc_params.ux_slave_class_storage_parameter_product_rev = s_msc_product_rev;
391
392 msc_params.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_last_lba =
394 msc_params.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_block_length =
396 msc_params.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_type =
397 UX_SLAVE_CLASS_STORAGE_MEDIA_FAT_DISK;
398 msc_params.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_removable_flag =
399 UX_SLAVE_CLASS_STORAGE_MEDIA_IS_REMOVABLE;
400 msc_params.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_read_only_flag =
401 UX_TRUE;
402 msc_params.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_read =
404 msc_params.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_write =
406 msc_params.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_status =
408
409 static UCHAR s_class_name[] = "ux_slave_class_storage";
410
411 return _ux_device_stack_class_register(s_class_name,
412 _ux_device_class_storage_entry,
413 1,
414 0,
415 &msc_params);
416}
417
438{
439 static UCHAR chunk[k_ospi_erase_sector] = {};
440 const uint32_t sec_per_erase = (uint32_t)k_ospi_erase_sector / (uint32_t)k_selftest_block_size;
441 for (uint32_t e = 0U; e < (uint32_t)k_ospi_erase_count; e++) {
442 const uint32_t addr = (uint32_t)k_ospi_test_offset + (e * (uint32_t)k_ospi_erase_sector);
443 const ra8_err_t err = ra8_xspi_flash_erase_sector((uint8_t)k_ospi_instance, addr);
444 if (err != k_ra8_ok) {
445 return err;
446 }
447 }
448 for (uint32_t e = 0U; e < (uint32_t)k_ospi_erase_count; e++) {
449 for (uint32_t s = 0U; s < sec_per_erase; s++) {
450 selftest_pattern_fill((e * sec_per_erase) + s, &chunk[s * (uint32_t)k_selftest_block_size]);
451 }
452 const uint32_t addr = (uint32_t)k_ospi_test_offset + (e * (uint32_t)k_ospi_erase_sector);
453 const ra8_err_t err =
454 ra8_xspi_flash_program((uint8_t)k_ospi_instance, addr, chunk, (uint32_t)k_ospi_erase_sector);
455 if (err != k_ra8_ok) {
456 return err;
457 }
458 }
459 return k_ra8_ok;
460}
461
482{
485 if (err != k_ra8_ok) {
486 s_dbg_ospi_prov = (uint32_t)err;
487 return err;
488 }
490 if (err != k_ra8_ok) {
491 s_dbg_ospi_prov = (uint32_t)err;
492 return err;
493 }
494 uint32_t id = 0U;
495 (void)ra8_xspi_flash_read_id((uint8_t)k_ospi_instance, &id);
496 s_dbg_ospi_id = id;
498 s_dbg_ospi_prov = (uint32_t)err;
499 return err;
500}
501
523{
524 (void)arg;
525
527 return;
528 }
529 if (selftest_usbx_stack_up() != UX_SUCCESS) {
530 return;
531 }
532 if (selftest_msc_class_register() != UX_SUCCESS) {
533 return;
534 }
536 return;
537 }
539 return;
540 }
541
542 /* Idle. USBX runs the SCSI/BBB state machine on its own threads. */
543 while (1) {
545 }
546}
547
567{
568 (void)arg;
569
571 for (;;) {
572 const ra8_err_t err = selftest_host_pass();
573 if (err == k_ra8_ok) {
574 break;
575 }
577 }
578 while (1) {
580 }
581}
582
598VOID tx_application_define(VOID* first_unused_memory)
599{
600 static CHAR s_device_thread_name[] = "selftest_device";
601 static CHAR s_host_thread_name[] = "selftest_host";
602
603 (void)first_unused_memory;
604 s_tx_kernel_up = true; /* ThreadX timer state is initialized past here. */
608 0UL,
618 0UL,
625}
626#endif /* !RA8_OFF_TARGET */
627
628/* -------------------------------------------------------------------------- */
629/* Startup helpers */
630/* -------------------------------------------------------------------------- */
631
645static void selftest_panic_halt(void)
646{
647 while (1) {
648 __asm__ volatile("wfi");
649 }
650}
651
669{
670 /* FS port: device role. */
672 k_ra8_ok) {
674 }
677 }
679 k_ra8_ok) {
681 }
683 k_ra8_ok) {
685 }
686 /* HS port: host role. */
689 }
692 }
694 k_ra8_ok) {
696 }
697}
698
714static void selftest_setup_or_halt(void)
715{
716 uint32_t cpuclk0_hz = 0U;
717 if (ra8_cgc_init() != k_ra8_ok) {
719 }
722 }
725 }
728 }
729 if (ra8_time_init(cpuclk0_hz) != k_ra8_ok) {
731 }
734 }
737 }
740 }
742}
743
758void main(void)
759{
761
763
764#ifndef RA8_OFF_TARGET
765 /* tx_kernel_enter is __noreturn -- it never comes back. */
766 tx_kernel_enter();
767#endif
768
770}
void main(void)
Secure fallback main entry point.
Definition main.c:37
void tx_application_define(void *first_unused_memory)
ThreadX system-define hook: build worker thread + byte pool.
Definition main.c:942
void _tx_timer_interrupt(void)
void SysTick_Handler(void)
SysTick exception handler – tail-calls the ThreadX timer.
Definition main.c:146
static volatile bool s_tx_kernel_up
Set in tx_application_define; gates ThreadX tick delivery.
Definition main.c:86
static UCHAR s_msc_product_id[]
Definition main.c:197
static UCHAR s_host_stack[k_wlun_host_stack]
Stack backing storage for s_host_thread.
Definition main.c:186
static TX_THREAD s_device_thread
ThreadX TCB for the USBX device-side worker thread.
Definition main.c:164
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 CHAR s_host_thread_name[]
Definition main.c:202
static TX_THREAD s_host_thread
ThreadX TCB for the host-side worker thread.
Definition main.c:179
static UCHAR s_device_framework_fs[]
Definition main.c:234
static UCHAR s_msc_product_rev[]
Definition main.c:198
static UCHAR s_language_id_framework[]
USBX language-id table – US English.
Definition main.c:368
static UCHAR s_device_stack[k_wlun_thread_stack]
Stack backing storage for s_device_thread.
Definition main.c:171
static CHAR s_device_thread_name[]
Definition main.c:201
static UCHAR s_msc_vendor_id[]
Definition main.c:196
static const ra8_port_pin_t k_selftest_pin_fs_vbusen
USBFS VBUSEN (P5_00) – GPIO LOW for the device role.
Definition main.c:105
static VOID selftest_device_worker(ULONG arg)
Device-side worker: bring the FS device stack up, then park.
Definition main.c:416
static const ra8_port_pin_t k_selftest_pin_hs_vbus
USBHS_VBUS sense pin (P4_08, PSEL = 0x14).
Definition main.c:114
static VOID selftest_host_worker(ULONG arg)
Host-side worker: retry the full pass until it succeeds.
Definition main.c:457
static void selftest_setup_or_halt(void)
Bring CGC + both USB clocks + SysTick + SCI8 + LEDs + pins up.
Definition main.c:605
static void selftest_panic_halt(void)
Halt forever in WFI – panic stop on init failure.
Definition main.c:536
static const ra8_port_pin_t k_selftest_pin_fs_dm
USBFS D- (P8_15).
Definition main.c:111
static const ra8_port_pin_t k_selftest_pin_hs_pwr
J7 host-power switch (PD07): HIGH = U18 supplies VBUS (UM 6.2).
Definition main.c:117
static const ra8_port_pin_t k_selftest_pin_fs_dp
USBFS D+ (P8_14).
Definition main.c:108
static void selftest_route_usb_or_halt(void)
Route both ports' pins: FS as device, HS as host.
Definition main.c:559
static UINT selftest_usbx_stack_up(void)
Brings USBX system + FS device stack up.
Definition main.c:331
static UINT selftest_msc_class_register(void)
Registers the Mass-Storage class with the read-only MRAM LUN.
Definition main.c:364
static const ra8_port_pin_t k_selftest_pin_fs_vbus
USBFS VBUS sense pin (P4_07, PSEL = 0x13).
Definition main.c:102
static ra8_err_t selftest_ospi_provision(void)
Bring the OSPI flash up and provision the test pattern.
Definition main.c:481
static ra8_err_t selftest_ospi_write_pattern(void)
Erase the OSPI window and program the deterministic pattern.
Definition main.c:437
static volatile uint32_t s_dbg_ospi_prov
OSPI provisioning result (sentinel = pending, 0 = done, else err).
Definition main.c:184
static volatile uint32_t s_dbg_ospi_id
OSPI JEDEC id read at boot (IS25LX512M = 0x009D5A1A).
Definition main.c:182
Board-support layer for the Renesas EK-RA8D2 v1 evaluation kit.
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_led2
LED2, GREEN, P303 (jumper E26).
@ k_ra8_board_led1
LED1, BLUE, P600 (jumper E27).
ra8_err_t ra8_board_io_expander_set_usbhs_host_mode(void)
Drive the U15 I/O expander to select USB-HS HOST mode.
ra8_err_t ra8_board_uart_console_init(uint32_t baud)
Configure SCI8 + PD02/PD03 as the debug-console UART.
@ k_ra8_board_usbhs_pin_pwr
PD07 J7 host-power switch (HIGH = U18 drives 5 V VBUS).
@ k_ra8_board_usbhs_pin_vbus
P4_08 USBHS_VBUS sense.
@ 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+.
ra8_err_t ra8_board_io_expander_set_octospi_active(void)
Program the U15 I/O expander to request the Octo-SPI SW4 layout.
ra8_err_t ra8_board_xspi_pins_init(void)
Route the 12 OCTA bus pins to the xSPI peripheral and pulse RESET_L.
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).
ra8_err_t ra8_cgc_usbhs_pll_enable(void)
Bring up the USBHS PHY reference clock + module clock.
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.
Minimal FAT12/FAT16/FAT32 filesystem adapter (read + write).
PSEL codes for peripheral pin routing on the RA8D2.
@ k_ra8_psel_usb_fs
10011b: USB Full-Speed.
@ k_ra8_psel_usb_hs
10100b: USB High-Speed (e.g.
NVIC + ICU IELSR allocator.
void ra8_isr_globals_enable(void)
Globally enable maskable interrupts (PRIMASK = 0).
Definition ra8_isr.c:439
@ k_ra8_xspi_lio_1s1s1s
1S-1S-1S extended SPI.
Typed Port / Pin Constants for the RA8D2 IOPORT Module.
ra8_port_pin_t
Packed (port << 8) | pin pin identifier.
@ k_ra8_level_high
Drive or read 1.
@ 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
void ux_dcd_ra8_usb_irq_reenable(void)
Storm-guard recovery: zero the run counter and re-enable the USB IRQ.
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
void ra8_time_on_tick(void)
SysTick IRQ handler – called from the vector table.
Definition ra8_time.c:170
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).
Native USB host-side MSC (Mass Storage Class) class layer.
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).
xSPI / Octo-SPI driver (flash read/program/erase + ID/status)
ra8_err_t ra8_xspi_flash_program(uint8_t instance, uint32_t flash_addr, const uint8_t *data, uint32_t len)
Program (write) len bytes at flash_addr.
ra8_err_t ra8_xspi_init(uint8_t instance, ra8_xspi_lio_mode_t mode)
Initialise an xSPI instance in the chosen link-layer IO mode.
Definition ra8_xspi.c:372
ra8_err_t ra8_xspi_flash_erase_sector(uint8_t instance, uint32_t flash_addr)
Erase the 4 KiB sector containing flash_addr.
ra8_err_t ra8_xspi_flash_read_id(uint8_t instance, uint32_t *out_id)
Read the JEDEC ID (opcode 0x9F), returning 24 bits in a uint32_t.
Opaque thread stand-in for the host build.
@ k_selftest_no_mismatch
Probe: no mismatch found.
UINT selftest_msc_status(VOID *storage, ULONG lun, ULONG media_id, ULONG *media_status)
Storage media-status callback.
ra8_err_t selftest_host_pass(void)
One full host-side pass: enumerate, mount, browse, verify, WP.
@ k_fat_total_sectors
1 + 17 + 32 + 4096.
UINT selftest_msc_read(VOID *storage, ULONG lun, UCHAR *data_pointer, ULONG number_blocks, ULONG lba, ULONG *media_status)
Storage media-read callback: synthesize sectors over MRAM.
UINT selftest_msc_write(VOID *storage, ULONG lun, UCHAR *data_pointer, ULONG number_blocks, ULONG lba, ULONG *media_status)
Storage media-write callback: always rejects (write-protected).
@ k_selftest_boot_wait_ticks
Host start delay (1 ms ticks).
@ k_selftest_thread_stack
Device worker stack (bytes).
@ k_selftest_block_size
SCSI logical block size (bytes).
@ k_selftest_idle_ticks
Parked-loop back-off (ticks).
@ k_selftest_retry_ticks
Pause between ladder retries.
@ k_selftest_usbx_pool_bytes
USBX memory pool (bytes).
@ k_selftest_host_priority
Host worker: BELOW the USBX storage class thread (UX_THREAD_PRIORITY_CLASS = 20).
@ k_selftest_dev_priority
Device bring-up worker priority.
@ k_selftest_host_stack
Host worker stack (bytes).
@ k_selftest_baud
J-Link OB CDC log baud.
Shared constants + step prototypes for the OSPI USB self-loop app.
void selftest_pattern_fill(uint32_t win_sector, UCHAR *out)
Compute the deterministic pattern for one window data sector.
@ k_ospi_erase_count
1 MiB / 4 KiB = 256 erases.
@ k_ospi_test_offset
1 MiB into the chip (scratch).
@ k_ospi_erase_sector
IS25LX512M 4 KiB erase sector.
@ k_ospi_instance
xSPI controller instance.
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.