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
44
45#include <stdint.h>
46#include <string.h>
47
48#include "ra8_board_ek_ra8d2.h"
49#include "ra8_boot_entry.h"
50#include "ra8_cgc.h"
51#include "ra8_err.h"
52#include "ra8_gpio_constants.h"
53#include "ra8_isr.h"
54#include "ra8_port_constants.h"
55#include "ra8_port_utils.h"
56#include "ra8_time.h"
57#include "ra8_usb.h"
59
60#ifndef RA8_OFF_TARGET
61#include "tx_api.h"
62#include "ux_api.h"
63#include "ux_dcd_ra8_usb.h"
64#include "ux_device_class_dfu.h"
65#include "ux_device_stack.h"
66
67extern void _tx_timer_interrupt(void);
68
76static volatile bool s_tx_kernel_up = false;
77
78void SysTick_Handler(void);
87#endif
88
89/* -------------------------------------------------------------------------- */
90/* Pinout (FSP-aligned, EK-RA8D2 v1 User's Manual) */
91/* -------------------------------------------------------------------------- */
92
95
98
101
104
107
110
111/* The J-Link OB CDC console (SCI8, PD_02 TXD / PD_03 RXD) bring-up -- pin
112 * routing, baud, and SCI init -- is owned by ra8_board_uart_console_init(). */
113
114/* Compile-time tunables, image geometry, text-formatter sizing, the host
115 * progress-phase markers, and the Chapter-9 + DFU request constants all live in
116 * "usb_selftest_dfu_steps.h" (shared with the host-ladder sibling). */
117
118#ifndef RA8_OFF_TARGET
119
120/* -------------------------------------------------------------------------- */
121/* ThreadX workers + USBX pool storage */
122/* -------------------------------------------------------------------------- */
123
134
143
149static volatile uint32_t s_dfu_image_len;
150
151/* -------------------------------------------------------------------------- */
152/* J-Link probes (device side) */
153/* -------------------------------------------------------------------------- */
154
155/* The host-ladder probes (s_dbg_phase / s_dbg_pid / s_dbg_blocks_ok /
156 * s_dbg_mismatch / s_dbg_pass_count) live in the host-ladder sibling, the only
157 * translation unit that reads or writes them. */
158
160static volatile uint32_t s_dbg_dev_writes;
162static volatile uint32_t s_dbg_dev_step;
164static volatile uint32_t s_dbg_host_err;
165
166/* -------------------------------------------------------------------------- */
167/* USB descriptors (DFU mode: single DFU interface, EP0 only) */
168/* -------------------------------------------------------------------------- */
169
170/* DFU-mode framework: device (PID 0x0019) + one config with a single DFU
171 * interface (class 0xFE / subclass 0x01 / protocol 0x02 = DFU mode, so USBX
172 * enumerates straight into dfuIDLE) + the DFU functional descriptor
173 * (CAN_DNLOAD | CAN_UPLOAD | MANIFESTATION_TOLERANT, wTransferSize 64). No data
174 * endpoints -- DFU runs over EP0. Layout per DFU 1.1 + USB 2.0 sec 9.6. */
175static UCHAR s_device_framework[] = {
176 /* Device descriptor (18 bytes). idVendor 0x1209, idProduct 0x0019. */
177 0x12U,
178 0x01U,
179 0x00U,
180 0x02U,
181 0x00U,
182 0x00U,
183 0x00U,
184 0x40U,
185 0x09U,
186 0x12U,
187 0x19U,
188 0x00U,
189 0x00U,
190 0x01U,
191 0x01U,
192 0x02U,
193 0x03U,
194 0x01U,
195 /* Configuration descriptor (wTotalLength 0x1B = 27). */
196 0x09U,
197 0x02U,
198 0x1BU,
199 0x00U,
200 0x01U,
201 0x01U,
202 0x00U,
203 0x80U,
204 0x32U,
205 /* DFU interface (class 0xFE, subclass 0x01, protocol 0x02 = DFU mode). */
206 0x09U,
207 0x04U,
208 0x00U,
209 0x00U,
210 0x00U,
211 0xFEU,
212 0x01U,
213 0x02U,
214 0x00U,
215 /* DFU functional descriptor. bmAttributes 0x07, wTransferSize 64,
216 bcdDFUVersion 0x0110. */
217 0x09U,
218 0x21U,
219 0x07U,
220 0xFFU,
221 0x00U,
222 0x40U,
223 0x00U,
224 0x10U,
225 0x01U,
226};
227
233static UCHAR s_string_framework[] = {
234 /* idx 1: "Brighton Sikarskie". */
235 0x09U,
236 0x04U,
237 0x01U,
238 0x12U,
239 'B',
240 'r',
241 'i',
242 'g',
243 'h',
244 't',
245 'o',
246 'n',
247 ' ',
248 'S',
249 'i',
250 'k',
251 'a',
252 'r',
253 's',
254 'k',
255 'i',
256 'e',
257 /* idx 2: "RA8D2 DFU". */
258 0x09U,
259 0x04U,
260 0x02U,
261 0x09U,
262 'R',
263 'A',
264 '8',
265 'D',
266 '2',
267 ' ',
268 'D',
269 'F',
270 'U',
271 /* idx 3: serial "00000019". */
272 0x09U,
273 0x04U,
274 0x03U,
275 0x08U,
276 '0',
277 '0',
278 '0',
279 '0',
280 '0',
281 '0',
282 '1',
283 '9',
284};
285
286/* USBX LANGID descriptor 0x0409 (English-US), little-endian byte pair. */
287typedef enum : uint8_t {
291
294
295/* -------------------------------------------------------------------------- */
296/* Device side: USBX DFU class callbacks */
297/* -------------------------------------------------------------------------- */
298
310static VOID dfu_activate(VOID* dfu)
311{
312 (void)dfu;
313}
314
326static VOID dfu_deactivate(VOID* dfu)
327{
328 (void)dfu;
329}
330
348static UINT
349dfu_write(VOID* dfu, ULONG block_number, const UCHAR* data, ULONG length, ULONG* media_status)
350{
351 (void)dfu;
352 const ULONG off = block_number * (ULONG)k_dfu_xfer_size;
353 if ((length > 0UL) && (off + length <= (ULONG)sizeof(s_dfu_image))) {
354 (void)memcpy(&s_dfu_image[off], data, (size_t)length);
355 if ((uint32_t)(off + length) > s_dfu_image_len) {
356 s_dfu_image_len = (uint32_t)(off + length);
357 }
359 }
360 *media_status = (ULONG)UX_SLAVE_CLASS_DFU_MEDIA_STATUS_OK;
361 return UX_SUCCESS;
362}
363
381static UINT dfu_read(VOID* dfu, ULONG block_number, UCHAR* data, ULONG length, ULONG* actual_length)
382{
383 (void)dfu;
384 const ULONG off = block_number * (ULONG)k_dfu_xfer_size;
385 if (off >= (ULONG)s_dfu_image_len) {
386 *actual_length = 0UL;
387 return UX_SUCCESS;
388 }
389 ULONG remain = (ULONG)s_dfu_image_len - off;
390 if (remain > length) {
391 remain = length;
392 }
393 (void)memcpy(data, &s_dfu_image[off], (size_t)remain);
394 *actual_length = remain;
395 return UX_SUCCESS;
396}
397
411static UINT dfu_get_status(VOID* dfu, ULONG* media_status)
412{
413 (void)dfu;
414 *media_status = (ULONG)UX_SLAVE_CLASS_DFU_MEDIA_STATUS_OK;
415 return UX_SUCCESS;
416}
417
431static UINT dfu_notify(VOID* dfu, ULONG notification)
432{
433 (void)dfu;
434 (void)notification;
435 return UX_SUCCESS;
436}
437
450{
451 if (_ux_system_initialize(s_usbx_pool, k_dfu_usbx_pool_bytes, UX_NULL, 0) != UX_SUCCESS) {
452 return UX_ERROR;
453 }
454 return _ux_device_stack_initialize((UCHAR*)UX_NULL,
455 0,
457 sizeof(s_device_framework),
459 sizeof(s_string_framework),
462 UX_NULL);
463}
464
478typedef UINT (
479 *dfu_write_cb_t)(VOID* dfu, ULONG block_number, UCHAR* data, ULONG length, ULONG* media_status);
480
493{
494 UX_SLAVE_CLASS_DFU_PARAMETER dfu_params = {
495 .ux_slave_class_dfu_parameter_will_detach = 0UL,
496 .ux_slave_class_dfu_parameter_capabilities =
497 (ULONG)(UX_SLAVE_CLASS_DFU_CAPABILITY_CAN_DOWNLOAD |
498 UX_SLAVE_CLASS_DFU_CAPABILITY_CAN_UPLOAD),
499 .ux_slave_class_dfu_parameter_instance_activate = dfu_activate,
500 .ux_slave_class_dfu_parameter_instance_deactivate = dfu_deactivate,
501 .ux_slave_class_dfu_parameter_read = dfu_read,
502 .ux_slave_class_dfu_parameter_write = (dfu_write_cb_t)dfu_write,
503 .ux_slave_class_dfu_parameter_get_status = dfu_get_status,
504 .ux_slave_class_dfu_parameter_notify = dfu_notify,
505 .ux_slave_class_dfu_parameter_framework = s_device_framework,
506 .ux_slave_class_dfu_parameter_framework_length = (ULONG)sizeof(s_device_framework),
507 };
508 static UCHAR s_class_name[] = "ux_slave_class_dfu";
509
510 return _ux_device_stack_class_register(s_class_name,
511 _ux_device_class_dfu_entry,
512 1,
513 0,
514 &dfu_params);
515}
516
528static VOID dfu_device_worker(ULONG arg)
529{
530 (void)arg;
531
532 UINT ux = dfu_usbx_stack_up();
533 if (ux != UX_SUCCESS) {
534 s_dbg_host_err = (uint32_t)ux;
535 return;
536 }
537 s_dbg_dev_step = 1U;
538 ux = dfu_class_register();
539 if (ux != UX_SUCCESS) {
540 s_dbg_host_err = (uint32_t)ux;
541 return;
542 }
543 s_dbg_dev_step = 2U;
545 if (e != k_ra8_ok) {
546 s_dbg_host_err = (uint32_t)e;
547 return;
548 }
549 s_dbg_dev_step = 3U;
551 if (e != k_ra8_ok) {
552 s_dbg_host_err = (uint32_t)e;
553 return;
554 }
555 s_dbg_dev_step = 4U;
556 while (1) {
558 }
559}
560
572static VOID dfu_host_worker(ULONG arg)
573{
574 (void)arg;
575
577 for (;;) {
578 const ra8_err_t err = dfu_host_pass();
579 if (err == k_ra8_ok) {
580 break;
581 }
582 s_dbg_host_err = (uint32_t)err;
584 }
585 while (1) {
587 }
588}
589
601VOID tx_application_define(VOID* first_unused_memory)
602{
603 static CHAR s_device_thread_name[] = "dfu_device";
604 static CHAR s_host_thread_name[] = "dfu_host";
605
606 (void)first_unused_memory;
607 s_tx_kernel_up = true;
611 0UL,
621 0UL,
628}
629#endif /* !RA8_OFF_TARGET */
630
631/* -------------------------------------------------------------------------- */
632/* Startup */
633/* -------------------------------------------------------------------------- */
634
645static void dfu_panic_halt(void)
646{
647 while (1) {
648 __asm__ volatile("wfi");
649 }
650}
651
686
697static void dfu_setup_or_halt(void)
698{
699 uint32_t cpuclk0_hz = 0U;
700 if (ra8_cgc_init() != k_ra8_ok) {
702 }
705 }
708 }
711 }
712 if (ra8_time_init(cpuclk0_hz) != k_ra8_ok) {
714 }
717 }
720 }
723 }
725}
726
736void main(void)
737{
739
741
742#ifndef RA8_OFF_TARGET
743 tx_kernel_enter();
744#endif
745
747}
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_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_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 volatile uint32_t s_dbg_dev_step
Device worker progress: 1 stack, 2 class, 3 dcd, 4 attach, 5 parked.
Definition main.c:219
static CHAR s_device_thread_name[]
Definition main.c:201
static UCHAR s_device_framework[]
USBX device + DFU descriptors: a DFU-mode interface (bInterfaceProtocol 0x02, enumerates straight int...
Definition main.c:206
static volatile uint32_t s_dbg_dev_writes
Device-side download block-write count.
Definition main.c:212
static const ra8_port_pin_t k_dfu_pin_hs_vbus
USBHS_VBUS sense pin (P4_08, PSEL = 0x14).
Definition main.c:107
static void dfu_panic_halt(void)
Halt forever in WFI – panic stop on init failure.
Definition main.c:739
static ra8_err_t dfu_host_pass(void)
Run the full host pass: enumerate, download, upload-verify.
Definition main.c:595
static const ra8_port_pin_t k_dfu_pin_hs_pwr
J7 host-power switch (PD07): HIGH = U18 supplies VBUS.
Definition main.c:110
static const ra8_port_pin_t k_dfu_pin_fs_vbusen
USBFS VBUSEN (P5_00) – GPIO LOW for the device role.
Definition main.c:98
static VOID dfu_host_worker(ULONG arg)
Host-side worker: retry the full pass until it succeeds, then park.
Definition main.c:666
@ k_dfu_usbx_pool_bytes
USBX memory pool (bytes).
Definition main.c:123
@ k_dfu_host_priority
Host worker priority (below USBX).
Definition main.c:130
@ k_dfu_retry_ticks
Pause between ladder retries.
Definition main.c:126
@ k_dfu_boot_wait_ticks
Host start delay (1 ms ticks).
Definition main.c:125
@ k_dfu_dev_priority
Device bring-up worker priority.
Definition main.c:129
@ k_dfu_thread_stack
Device worker stack (bytes).
Definition main.c:121
@ k_dfu_baud
J-Link OB CDC log baud.
Definition main.c:127
@ k_dfu_idle_ticks
Parked-loop back-off (ticks).
Definition main.c:124
@ k_dfu_host_stack
Host worker stack (bytes).
Definition main.c:122
static VOID dfu_device_worker(ULONG arg)
Device-side worker: bring the DFU device up, then park.
Definition main.c:362
static const ra8_port_pin_t k_dfu_pin_fs_dm
USBFS D- (P8_15).
Definition main.c:104
static void dfu_setup_or_halt(void)
Bring CGC + both USB clocks + SysTick + SCI8 + LEDs + pins up.
Definition main.c:791
static const ra8_port_pin_t k_dfu_pin_fs_dp
USBFS D+ (P8_14).
Definition main.c:101
static const ra8_port_pin_t k_dfu_pin_fs_vbus
USBFS VBUS sense pin (P4_07, PSEL = 0x13).
Definition main.c:95
static void dfu_route_usb_or_halt(void)
Route both ports' pins: FS as device, HS as host.
Definition main.c:756
static volatile uint32_t s_dbg_host_err
Host-ladder first failing return code (0 = none).
Definition main.c:216
@ k_dfu_xfer_size
wTransferSize: bytes per DFU block.
Definition main.c:162
@ k_dfu_image_bytes
k_dfu_blocks * k_dfu_xfer_size.
Definition main.c:164
static UCHAR s_dfu_image[k_dfu_image_bytes]
Device-side RAM "firmware" image: the DFU write callback stores each downloaded block here; the read ...
Definition main.c:212
static volatile uint32_t s_dfu_image_len
Highest byte offset the device has captured (download high-water mark).
Definition main.c:219
UINT(* dfu_write_cb_t)(VOID *dfu, ULONG block_number, UCHAR *data, ULONG length, ULONG *media_status)
Signature of the USBX DFU download-write callback field.
Definition main.c:479
static VOID dfu_activate(VOID *dfu)
DFU activate callback.
Definition main.c:310
static UINT dfu_read(VOID *dfu, ULONG block_number, UCHAR *data, ULONG length, ULONG *actual_length)
DFU read callback – serve one block of the RAM image on UPLOAD.
Definition main.c:381
static UINT dfu_usbx_stack_up(void)
Bring USBX system + device stack up with the DFU framework.
Definition main.c:449
static UINT dfu_get_status(VOID *dfu, ULONG *media_status)
DFU get-status callback – report the media always ready.
Definition main.c:411
static VOID dfu_deactivate(VOID *dfu)
DFU deactivate callback.
Definition main.c:326
static UINT dfu_write(VOID *dfu, ULONG block_number, const UCHAR *data, ULONG length, ULONG *media_status)
DFU write callback – store one downloaded block into the RAM image.
Definition main.c:349
static UINT dfu_class_register(void)
Register the DFU class against configuration 1, interface 0.
Definition main.c:492
static UINT dfu_notify(VOID *dfu, ULONG notification)
DFU notify callback – accept begin/end/manifest notifications.
Definition main.c:431
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+.
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 * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
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
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).
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.
Shared constants + host-side DFU ladder interface for usb_selftest_dfu.
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.