ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
c6_cam_app.c
Go to the documentation of this file.
1
17
18#include <stdint.h>
19
20#include "c6_camera_server.h"
21#include "nx_ether_driver_c6.h"
22#include "ra8_attributes.h"
23#include "ra8_board_ek_ra8d2.h"
24#include "ra8_c6link.h"
25#include "ra8_c6link_wifi.h"
26#include "ra8_err.h"
28#include "ra8_esp_hosted_port.h"
29#include "ra8_isr.h"
30#include "ra8_mstp.h"
31#include "ra8_net_provision.h"
32#include "ra8_sdramc.h"
33#include "ra8_secure.h"
34#include "ra8_time.h"
35#include "tx_api.h"
36
37static uint32_t s_cpuclk_hz;
38static uint32_t s_pclka_hz;
41static CHAR s_worker_name[] = "c6_cam_stream";
45static volatile uint32_t s_events;
46static volatile uint8_t s_connected;
47static volatile uint8_t s_disconnected;
48static volatile uint16_t s_disconnect_reason;
55
67{
68 while (true) {
69 __asm volatile("wfi");
70 }
71}
72
84{
85 ra8_board_clock_rates_t clock_rates = {};
86 if (ra8_board_clocks_init(&clock_rates) != k_ra8_ok) {
88 }
89 s_cpuclk_hz = clock_rates.cpuclk0_hz;
90 s_pclka_hz = clock_rates.pclka_hz;
91 if (ra8_mstp_init() != k_ra8_ok) {
93 }
94 if (ra8_isr_init() != k_ra8_ok) {
96 }
99 }
102 }
103 c6_cam_puts("c6_cam: entering C6 handshake\r\n");
104}
105
118RA8_INTERNAL static void internal_c6_cam_on_event(void* ctx, const ra8_c6link_event_t* event)
119{
120 (void)ctx;
121 if (event == nullptr) {
122 return;
123 }
124 s_events++;
126 s_connected = 1U;
127 } else if (event->kind == k_ra8_c6link_event_sta_disconnected) {
128 s_disconnected = 1U;
129 s_disconnect_reason = event->reason;
130 } else {
131 /* Boot and bare Wi-Fi events are counted but need no state latch. */
132 }
133}
134
147RA8_INTERNAL static void internal_c6_cam_report_fault(const char* stage, ra8_err_t err)
148{
149 c6_cam_puts("c6_cam: FAIL ");
150 c6_cam_puts(stage);
151 c6_cam_puts(" err=");
153 c6_cam_puts("\r\n");
154}
155
170{
171 ra8_c6link_cfg_t cfg = {};
173 if (err != k_ra8_ok) {
174 return err;
175 }
176 cfg.arena = s_arena;
177 cfg.arena_bytes = (uint32_t)sizeof(s_arena);
180 cfg.cb_ctx = nullptr;
181 return ra8_c6link_open(&s_link, &cfg);
182}
183
198{
199 for (uint32_t i = 0U; i < (uint32_t)k_c6_cam_assoc_polls; i++) {
200 (void)ra8_c6link_poll(&s_link, (uint16_t)k_ra8_c6link_announce_transfers, nullptr);
201 if (s_connected != 0U) {
202 return true;
203 }
204 if (s_disconnected != 0U) {
205 return false;
206 }
208 }
209 return false;
210}
211
226{
228 c6_cam_puts("c6_cam: link_open=");
230 c6_cam_puts("\r\n");
231 if (err != k_ra8_ok) {
232 return false;
233 }
234 ra8_c6link_fw_version_t version = {};
236 if (err != k_ra8_ok) {
237 internal_c6_cam_report_fault("await_ready", err);
238 return false;
239 }
240 c6_cam_puts("c6_cam: coprocessor fw=");
241 c6_cam_put_u32(version.major);
242 c6_cam_puts(".");
243 c6_cam_put_u32(version.minor);
244 c6_cam_puts(".");
245 c6_cam_put_u32(version.patch);
246 c6_cam_puts("\r\n");
247 return true;
248}
249
267 const ra8_net_credentials_t* credentials)
268{
270 if (err != k_ra8_ok) {
271 internal_c6_cam_report_fault("wifi_start", err);
272 return false;
273 }
274 err = ra8_c6link_wifi_mac(&s_link, mac);
275 if (err != k_ra8_ok) {
276 internal_c6_cam_report_fault("wifi_mac", err);
277 return false;
278 }
279 ra8_c6link_sta_cfg_t station = {};
280 err = ra8_c6link_sta_cfg_set(&station, credentials->ssid, credentials->psk);
281 if (err != k_ra8_ok) {
282 ra8_secure_memzero(&station, sizeof(station));
283 internal_c6_cam_report_fault("sta_cfg_set", err);
284 return false;
285 }
286 s_connected = 0U;
287 s_disconnected = 0U;
289 err = ra8_c6link_wifi_join(&s_link, &station);
290 ra8_secure_memzero(&station, sizeof(station));
291 if (err != k_ra8_ok) {
292 internal_c6_cam_report_fault("wifi_join", err);
293 return false;
294 }
296 c6_cam_puts("c6_cam: FAIL association reason=");
298 c6_cam_puts(" events=");
299 c6_cam_put_u32((uint32_t)s_events);
300 c6_cam_puts("\r\n");
301 return false;
302 }
303 c6_cam_puts("c6_cam: associated events=");
304 c6_cam_put_u32((uint32_t)s_events);
305 c6_cam_puts("\r\n");
306 return true;
307}
308
325 const ra8_net_credentials_t* credentials)
326{
327 ra8_c6link_mac_t mac = {};
328 if (!internal_c6_cam_associate(&mac, credentials)) {
329 return false;
330 }
331
332 const ra8_err_t err = c6_cam_net_up(&s_link, &mac, lease);
333 if ((err != k_ra8_ok) || !lease->bound) {
334 c6_cam_puts("c6_cam: FAIL DHCP err=");
336 c6_cam_puts("\r\n");
337 return false;
338 }
339 return true;
340}
341
357{
358 const ra8_err_t camera = c6_cam_camera_init();
359 if (camera != k_ra8_ok) {
360 c6_cam_puts("c6_cam: FAIL camera init err=");
363 c6_cam_puts("\r\n");
364 return false;
365 }
366 const uint8_t* startup_jpeg = nullptr;
367 uint32_t startup_jpeg_bytes = 0U;
368 c6_cam_frame_timing_t startup_timing = {};
369 const ra8_err_t startup_capture =
370 c6_cam_camera_capture_jpeg(&startup_jpeg, &startup_jpeg_bytes, &startup_timing);
371 if (startup_capture != k_ra8_ok) {
372 c6_cam_puts("c6_cam: FAIL camera selftest err=");
373 c6_cam_puts(ra8_err_to_str(startup_capture));
375 c6_cam_puts("\r\n");
376 return false;
377 }
378 c6_cam_puts("c6_cam: camera selftest=PASS jpeg_bytes=");
379 c6_cam_put_u32(startup_jpeg_bytes);
380 c6_cam_puts(" capture_ms=");
381 c6_cam_put_u32(startup_timing.capture_ms);
382 c6_cam_puts("\r\n");
383 c6_cam_puts("c6_cam: camera=PASS ");
385 c6_cam_puts("\r\n");
386 return true;
387}
388
404{
405 if (ra8_sdramc_init() != k_ra8_ok) {
406 c6_cam_puts("c6_cam: FAIL SDRAM init\r\n");
407 return false;
408 }
409 c6_cam_puts("c6_cam: sdram=PASS\r\n");
410 const ra8_err_t audio = c6_cam_audio_start();
411 if (audio != k_ra8_ok) {
412 c6_cam_puts("c6_cam: FAIL audio init err=");
414 c6_cam_puts("\r\n");
415 return false;
416 }
417 c6_cam_puts("c6_cam: audio=PASS mic=MIC1 fs=16000Hz pcm=20bit\r\n");
419}
420
433{
434 (void)input;
435 if (s_port_err != k_ra8_ok) {
436 c6_cam_puts("c6_cam: FAIL esp-hosted port init err=");
438 c6_cam_puts("\r\n");
440 }
442 ra8_net_credentials_t credentials = {};
445 &credentials);
446 if (provisioned != k_ra8_ok) {
447 internal_c6_cam_report_fault("runtime provisioning", provisioned);
448 ra8_net_provision_clear(&credentials);
450 }
452 ra8_net_provision_clear(&credentials);
454 }
456 ra8_net_provision_clear(&credentials);
458 }
459 c6_cam_lease_t lease = {};
460 if (!internal_c6_cam_join(&lease, &credentials)) {
461 ra8_net_provision_clear(&credentials);
463 }
464 ra8_net_provision_clear(&credentials);
465 c6_cam_puts("c6_cam: PASS Wi-Fi and DHCP ip=");
466 c6_cam_put_ip(lease.ip);
467 c6_cam_puts("\r\n");
468 c6_cam_puts("\r\nc6_cam: open http://");
469 c6_cam_put_ip(lease.ip);
470 c6_cam_puts("/\r\n");
472}
473
474void tx_application_define(void* first_unused_memory)
475{
476 (void)first_unused_memory;
477 const ra8_esp_hosted_port_cfg_t cfg = {
478 .pclk_hz = s_pclka_hz,
479 .sck_hz = (uint32_t)k_c6_cam_sck_hz,
480 .edge_poll_ms = (uint16_t)k_c6_cam_edge_poll_ms,
481 .sci_channel = (uint8_t)k_ra8_board_pmod1_sci_channel,
482 };
487 0U,
489 (ULONG)sizeof(s_worker_stack),
494 c6_cam_puts("c6_cam: FAIL worker create\r\n");
495 }
496}
497
498int32_t c6_cam_app_run(void)
499{
502 c6_cam_puts("c6_cam: entering ThreadX\r\n");
503 tx_kernel_enter();
505 return 0;
506}
static volatile uint8_t s_disconnected
Definition c6_cam_app.c:47
static uint32_t s_cpuclk_hz
Definition c6_cam_app.c:37
static volatile uint8_t s_connected
Definition c6_cam_app.c:46
static bool internal_c6_cam_join(c6_cam_lease_t *lease, const ra8_net_credentials_t *credentials)
Join configured Wi-Fi and acquire a DHCP lease.
Definition c6_cam_app.c:324
static void internal_c6_cam_setup_or_halt(void)
Initialize shared clocks, services, and the diagnostic console.
Definition c6_cam_app.c:83
static ra8_c6link_t s_link
Definition c6_cam_app.c:44
static bool internal_c6_cam_prepare_camera(void)
Initialize the camera backend and prove one startup JPEG capture.
Definition c6_cam_app.c:356
static bool internal_c6_cam_prepare_link(void)
Open the C6 link and await firmware readiness.
Definition c6_cam_app.c:225
static void internal_c6_cam_on_event(void *ctx, const ra8_c6link_event_t *event)
Latch station connection events from the C6 link.
Definition c6_cam_app.c:118
static volatile uint32_t s_events
Definition c6_cam_app.c:45
static TX_THREAD s_worker
Definition c6_cam_app.c:40
static bool internal_c6_cam_wait_connected(void)
Poll for a station association result.
Definition c6_cam_app.c:197
static bool internal_c6_cam_associate(ra8_c6link_mac_t *mac, const ra8_net_credentials_t *credentials)
Start station mode and associate with the configured AP.
Definition c6_cam_app.c:266
static const ra8_net_provision_uart_t s_provision_uart
Board-console binding for the shared runtime provisioner.
Definition c6_cam_app.c:50
static CHAR s_worker_name[]
Definition c6_cam_app.c:41
static UCHAR s_worker_stack[k_c6_cam_worker_stack]
Definition c6_cam_app.c:42
static uint8_t s_arena[k_c6_cam_arena_bytes]
Definition c6_cam_app.c:43
static bool internal_c6_cam_prepare_media(void)
Initialize and self-test the audio and camera backends.
Definition c6_cam_app.c:403
static volatile uint16_t s_disconnect_reason
Definition c6_cam_app.c:48
int32_t c6_cam_app_run(void)
Run the shared runtime-provisioned C6, DHCP, and HTTP application flow.
Definition c6_cam_app.c:498
static void internal_c6_cam_report_fault(const char *stage, ra8_err_t err)
Emit one standardized application failure line.
Definition c6_cam_app.c:147
static uint32_t s_pclka_hz
Definition c6_cam_app.c:38
static ra8_err_t s_port_err
Definition c6_cam_app.c:39
static ra8_err_t internal_c6_cam_open_link(void)
Bind and open the raw ESP-hosted C6 link.
Definition c6_cam_app.c:169
void tx_application_define(void *first_unused_memory)
Definition c6_cam_app.c:474
static void internal_c6_cam_halt(void)
Park the application after a terminal failure.
Definition c6_cam_app.c:66
static void internal_c6_cam_worker_entry(ULONG input)
Run the network, audio, camera, and HTTP worker workflow.
Definition c6_cam_app.c:432
Shared contracts for ESP32-C6 browser camera servers.
void c6_cam_http_serve(void)
Serve the browser UI and fresh JPEG frames forever.
Definition c6_cam_net.c:550
void c6_cam_put_u32(uint32_t value)
Write one unsigned decimal value to SCI8.
ra8_err_t c6_cam_camera_init(void)
Camera image and board-switch initialization, then one CEU capture.
@ k_c6_cam_arena_bytes
C6-link caller-owned arena size.
@ k_c6_cam_worker_prio
ThreadX worker priority.
@ k_c6_cam_uart_baud
Diagnostic console baud rate.
@ k_c6_cam_edge_poll_ms
C6 interrupt-edge poll period.
@ k_c6_cam_sck_hz
Camera-stream ESP-hosted SPI rate.
@ k_c6_cam_assoc_polls
Maximum association status polls.
@ k_c6_cam_assoc_gap_ms
Delay between association polls.
@ k_c6_cam_worker_stack
Worker thread stack bytes.
@ k_c6_cam_boot_wait_ms
C6 boot stabilization delay.
ra8_err_t c6_cam_audio_start(void)
Start continuous MIC1 capture into the SDRAM audio ring.
void c6_cam_put_ip(uint32_t ip)
Write one IPv4 address to SCI8.
ra8_err_t c6_cam_camera_capture_jpeg(const uint8_t **out_jpeg, uint32_t *out_bytes, c6_cam_frame_timing_t *out_timing)
ra8_err_t c6_cam_net_up(ra8_c6link_t *link, const ra8_c6link_mac_t *mac, c6_cam_lease_t *out)
Bind NetX to an associated raw C6 link and obtain a DHCP lease.
Definition c6_cam_net.c:107
void c6_cam_puts(const char *text)
Write a bounded NUL-terminated string to SCI8.
void c6_cam_camera_report_last_error(void)
Emit backend-specific diagnostics for the last capture failure.
const char * c6_cam_camera_description(void)
Human-readable description of the selected camera backend.
NetX Duo network driver shim that bridges onto the ESP32-C6 link.
void nx_ether_driver_c6_rx(void *ctx, const uint8_t *frame, uint16_t len)
Receive callback the application registers with ra8_c6link_open.
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Board-support layer for the Renesas EK-RA8D2 v1 evaluation kit.
@ k_ra8_board_pmod1_sci_channel
Pmod1 (J26) Simple-SPI is SCI2.
ra8_err_t ra8_board_uart_console_read(uint8_t *out, size_t cap, size_t *out_len)
Polled non-blocking read from the J-Link OB VCOM console.
ra8_err_t ra8_board_clocks_init(ra8_board_clock_rates_t *out_rates)
Initialize the standard EK-RA8D2 clock tree and return its rates.
ra8_err_t ra8_board_uart_console_write(const uint8_t *data, size_t len)
Polled blocking write to the J-Link OB VCOM console.
ra8_err_t ra8_board_uart_console_init(uint32_t baud)
Configure SCI8 + PD02/PD03 as the debug-console UART.
Error Code Definitions for ra8-firmware.
@ k_ra8_err_not_initialized
Module not initialized – _init() not yet called successfully.
Definition ra8_err.h:235
@ 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
const char * ra8_err_to_str(ra8_err_t err)
Human-readable string for an error code.
Definition ra8_log.c:737
Public entry point of the RA8D2 + ThreadX port of esp-hosted.
struct ra8_esp_hosted_port_cfg ra8_esp_hosted_port_cfg_t
ra8_err_t ra8_esp_hosted_port_init(const ra8_esp_hosted_port_cfg_t *cfg)
Bring the esp-hosted port up and publish the OS-abstraction vtable.
NVIC + ICU IELSR allocator.
ra8_err_t ra8_isr_init(void)
Initialise the ra8_isr table.
Definition ra8_isr.c:229
void ra8_isr_globals_enable(void)
Globally enable maskable interrupts (PRIMASK = 0).
Definition ra8_isr.c:439
Ref-counted Module Stop Control wrapper for the RA8D2.
ra8_err_t ra8_mstp_init(void)
Re-establish the ra8_mstp ref-count table from current hardware state.
Definition ra8_mstp.c:291
Runtime network provisioning contract for EK-RA8D2 applications.
struct ra8_net_credentials ra8_net_credentials_t
struct ra8_net_provision_uart ra8_net_provision_uart_t
@ k_ra8_net_provision_timeout_ms
Standard application RX timeout.
ra8_err_t ra8_net_provision_receive(const ra8_net_provision_uart_t *uart, uint32_t timeout_ms, ra8_net_credentials_t *out)
Prompt once and receive one provisioning line within a fixed timeout.
void ra8_net_provision_clear(ra8_net_credentials_t *credentials)
Explicitly erase one decoded credential record.
External SDRAM controller driver (framework).
ra8_err_t ra8_sdramc_init(void)
Initialise the external SDRAM at k_ra8_sdram_base_addr.
Definition ra8_sdramc.c:257
Secure-comparison primitives for the crypto / secure-boot paths.
void ra8_secure_memzero(void *ptr, size_t len)
Securely zero a buffer such that the write cannot be optimised away.
Definition ra8_secure.c:37
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_delay_ms(uint32_t ms)
Busy-wait for at least ms milliseconds.
Definition ra8_time.c:129
unsigned int UINT
ThreadX-compatible unsigned int (host stub).
#define TX_SUCCESS
#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.
Per-frame pipeline latency exposed in HTTP Server-Timing headers.
uint32_t capture_ms
Camera capture latency.
DHCP lease returned by the raw, bench-validated C6/NetX path.
bool bound
True after a lease is bound.
uint32_t ip
Assigned IPv4 address.
Clock rates published by the standard EK-RA8D2 bring-up.
uint32_t pclka_hz
Peripheral clock A rate in hertz.
uint32_t cpuclk0_hz
Main Cortex-M85 clock rate in hertz.
char psk[k_ra8_net_provision_psk_bytes_max+1U]
NUL-terminated PSK storage.
char ssid[k_ra8_net_provision_ssid_bytes_max+1U]
NUL-terminated SSID storage.