29#if !defined(RA8_OFF_TARGET) && __has_include("ux_api.h")
38#include "ux_device_class_dfu.h"
39#include "ux_device_stack.h"
42typedef enum : uint32_t {
43 k_ra8_dfu_dev_block_bytes = 64U,
44 k_ra8_dfu_dev_page_mask = 0x0000001FU,
48typedef enum : uint8_t {
49 k_ra8_dfu_dev_reg_interface = 1U,
50 k_ra8_dfu_dev_reg_config = 0U,
54typedef enum : uint8_t {
55 k_ra8_dfu_dev_erased_byte = 0xFFU,
66 volatile bool prepared;
67 volatile bool manifest;
68 volatile bool committed;
69 volatile uint32_t img_len;
70 volatile uint32_t writes;
72 uint8_t stage[k_ra8_dfu_dev_block_bytes];
76static ra8_dfu_dev_ctx_t s_dev = {
83 s_dev.target = target_slot;
108RA8_INTERNAL static VOID internal_dfu_activate(VOID* dfu)
135RA8_INTERNAL static VOID internal_dfu_deactivate(VOID* dfu)
178internal_dfu_write(VOID* dfu,
ULONG block_number, UCHAR* data,
ULONG length,
ULONG* media_status)
182 s_dev.manifest =
true;
184 uint32_t len = (uint32_t)length;
185 if (len > (uint32_t)k_ra8_dfu_dev_block_bytes) {
186 len = (uint32_t)k_ra8_dfu_dev_block_bytes;
188 (void)
memcpy(s_dev.stage, data, (
size_t)len);
191 const uint32_t plen =
192 (uint32_t)((len + (uint32_t)k_ra8_dfu_dev_page_mask) & ~(uint32_t)k_ra8_dfu_dev_page_mask);
193 for (uint32_t i = len; i < plen; i++) {
194 s_dev.stage[i] = (uint8_t)k_ra8_dfu_dev_erased_byte;
196 const uint32_t off = (uint32_t)block_number * (uint32_t)k_ra8_dfu_dev_block_bytes;
202 if ((off + plen) > s_dev.img_len) {
203 s_dev.img_len = off + plen;
207 *media_status = (s_dev.prog_err ==
k_ra8_ok) ? (
ULONG)UX_SLAVE_CLASS_DFU_MEDIA_STATUS_OK
208 : (
ULONG)UX_SLAVE_CLASS_DFU_MEDIA_STATUS_ERROR;
242internal_dfu_read(VOID* dfu,
ULONG block_number, UCHAR* data,
ULONG length,
ULONG* actual_length)
245 const uint32_t off = (uint32_t)block_number * (uint32_t)k_ra8_dfu_dev_block_bytes;
246 if (off >= s_dev.img_len) {
247 *actual_length = 0UL;
250 uint32_t remain = s_dev.img_len - off;
251 if (remain > (uint32_t)length) {
252 remain = (uint32_t)length;
255 (void)
memcpy(data, (
const void*)src, (
size_t)remain);
256 *actual_length = (
ULONG)remain;
289 *media_status = (s_dev.prog_err ==
k_ra8_ok) ? (
ULONG)UX_SLAVE_CLASS_DFU_MEDIA_STATUS_OK
290 : (
ULONG)UX_SLAVE_CLASS_DFU_MEDIA_STATUS_ERROR;
322 if (notification == (
ULONG)UX_SLAVE_CLASS_DFU_NOTIFICATION_END_DOWNLOAD) {
323 s_dev.manifest =
true;
358RA8_INTERNAL static UINT internal_class_register(
unsigned char* framework, uint32_t framework_len)
360 static UCHAR s_class_name[] =
"ux_slave_class_dfu";
362 UX_SLAVE_CLASS_DFU_PARAMETER p = {
363 .ux_slave_class_dfu_parameter_will_detach = 0UL,
364 .ux_slave_class_dfu_parameter_capabilities =
365 (
ULONG)(UX_SLAVE_CLASS_DFU_CAPABILITY_CAN_DOWNLOAD |
366 UX_SLAVE_CLASS_DFU_CAPABILITY_CAN_UPLOAD),
367 .ux_slave_class_dfu_parameter_instance_activate = internal_dfu_activate,
368 .ux_slave_class_dfu_parameter_instance_deactivate = internal_dfu_deactivate,
369 .ux_slave_class_dfu_parameter_read = internal_dfu_read,
370 .ux_slave_class_dfu_parameter_write = internal_dfu_write,
371 .ux_slave_class_dfu_parameter_get_status = internal_dfu_get_status,
372 .ux_slave_class_dfu_parameter_notify = internal_dfu_notify,
373 .ux_slave_class_dfu_parameter_framework = (UCHAR*)framework,
374 .ux_slave_class_dfu_parameter_framework_length = (
ULONG)framework_len,
376 return _ux_device_stack_class_register(s_class_name,
377 _ux_device_class_dfu_entry,
378 (
ULONG)k_ra8_dfu_dev_reg_interface,
379 (
ULONG)k_ra8_dfu_dev_reg_config,
386 unsigned char* framework,
387 uint32_t framework_len,
388 unsigned char* strings,
389 uint32_t strings_len,
390 unsigned char* langids,
391 uint32_t langids_len)
393 if ((usbx_pool ==
nullptr) || (framework ==
nullptr) || (strings ==
nullptr) ||
394 (langids ==
nullptr)) {
397 if (_ux_system_initialize(usbx_pool, (
ULONG)pool_bytes, UX_NULL, 0) != UX_SUCCESS) {
400 if (_ux_device_stack_initialize((UCHAR*)UX_NULL,
403 (
ULONG)framework_len,
408 UX_NULL) != UX_SUCCESS) {
411 if (internal_class_register(framework, framework_len) != UX_SUCCESS) {
426 s_dev.prepared =
true;
437 if (s_dev.manifest && !s_dev.committed && s_dev.prepared && (s_dev.prog_err ==
k_ra8_ok)) {
438 uint32_t other_seq = 0U;
444 s_dev.committed =
true;
447 return s_dev.prog_err;
452 return s_dev.img_len;
462 return s_dev.manifest;
467 return s_dev.prog_err;
472 return s_dev.committed;
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Controller-agnostic USB-DFU MRAM bootloader core for the RA8D2.
ra8_err_t ra8_dfu_program_commit(ra8_dfu_slot_t inactive, uint32_t img_len, uint32_t seq)
Finalize a slot: CRC the programmed body, then program the header.
ra8_err_t ra8_dfu_slot_seq(ra8_dfu_slot_t slot, uint32_t *out_seq)
Read a slot header's sequence number (0 if the magic is wrong).
ra8_dfu_slot_t
Application-slot identifier.
@ k_ra8_dfu_slot_b
Slot B (0x02090000).
@ k_ra8_dfu_slot_a
Slot A (0x02020000).
ra8_err_t ra8_dfu_program_image(ra8_dfu_slot_t inactive, uint32_t img_offset, const uint8_t *data, uint32_t len)
Program one image chunk into the inactive slot's body.
uintptr_t ra8_dfu_slot_base(ra8_dfu_slot_t slot)
Return the MRAM base address of a slot.
ra8_err_t ra8_dfu_program_prepare(ra8_dfu_slot_t inactive)
Open ra8_flash and fence all writes to one slot's window.
ra8_dfu_slot_t ra8_dfu_other_slot(ra8_dfu_slot_t slot)
Return the opposite slot (A<->B).
USBX DFU device class wired to real MRAM, bound to either controller.
bool ra8_dfu_device_manifested(void)
Whether the host has signalled end-of-download / manifest.
ra8_err_t ra8_dfu_device_last_error(void)
Latched last program error (diagnostic).
ra8_err_t ra8_dfu_device_start(ra8_usb_speed_t speed, void *usbx_pool, uint32_t pool_bytes, unsigned char *framework, uint32_t framework_len, unsigned char *strings, uint32_t strings_len, unsigned char *langids, uint32_t langids_len)
Bring up USBX + the DFU class on one controller and raise D+.
void ra8_dfu_device_set_target(ra8_dfu_slot_t target_slot)
Select the slot DFU_DNLOAD programs into / DFU_UPLOAD reads from.
ra8_err_t ra8_dfu_device_worker_step(void)
Program any pending DNLOAD block into MRAM; commit on end-of-download.
uint32_t ra8_dfu_device_image_len(void)
Total image bytes accepted so far (diagnostic).
uint32_t ra8_dfu_device_block_writes(void)
Count of DNLOAD blocks programmed into MRAM (diagnostic).
bool ra8_dfu_device_committed(void)
Whether the image header has been committed (slot now bootable).
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
@ k_ra8_err_null_ptr
Pointer was NULL where a valid pointer was required.
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
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.
ra8_usb_speed_t
Selects which controller instance the call targets.
unsigned int UINT
ThreadX-compatible unsigned int (host stub).
unsigned long ULONG
ThreadX-compatible unsigned long (host stub).
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.