ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
cam_ceu.c
Go to the documentation of this file.
1
17
18#include "cam_ceu.h"
19
20#include <stdint.h>
21
22#include "ra8_check.h"
23#include "ra8_err.h"
24#include "ra8_port_regs.h"
25#include "ra8_port_utils.h"
26#include "ra8_systick.h"
27
28/* =============================================================================
29 * DVP diagnostic constants (typed enums -- no magic numbers)
30 * =============================================================================
31 */
32
41
47
49typedef struct {
50 volatile r_port_regs_t* port4;
51 volatile r_port_regs_t* port7;
52 volatile r_port_regs_t* port9;
55
57typedef struct {
58 uint32_t prior;
59 uint32_t run_samples;
62 uint32_t high_min;
63 uint32_t high_max;
64 uint32_t low_min;
65 uint32_t low_max;
66 uint32_t high_cycles_min;
67 uint32_t high_cycles_max;
68 uint8_t data_min;
69 uint8_t data_max;
70 uint8_t data_and;
71 uint8_t data_or;
72 uint8_t prior_data;
74
81static const cam_ceu_pin_t s_ceu_pins[] = {
82 {k_ra8_port_4, k_ra8_pin_0}, /* D0 P400 (VIO_D0) */
83 {k_ra8_port_9, k_ra8_pin_2}, /* D1 P902 (VIO_D1) */
84 {k_ra8_port_4, k_ra8_pin_5}, /* D2 P405 (VIO_D2) */
85 {k_ra8_port_4, k_ra8_pin_6}, /* D3 P406 (VIO_D3) */
86 {k_ra8_port_7, k_ra8_pin_0}, /* D4 P700 (VIO_D4) */
87 {k_ra8_port_7, k_ra8_pin_1}, /* D5 P701 (VIO_D5) */
88 {k_ra8_port_7, k_ra8_pin_2}, /* D6 P702 (VIO_D6) */
89 {k_ra8_port_7, k_ra8_pin_3}, /* D7 P703 (VIO_D7) */
90 {k_ra8_port_11, k_ra8_pin_2}, /* VSYNC PB02 (VIO_VD) */
91 {k_ra8_port_11, k_ra8_pin_3}, /* HSYNC PB03 (VIO_HD) */
92 {k_ra8_port_11, k_ra8_pin_4}, /* PCLK PB04 (VIO_CLK) */
93};
94
106static void cam_release_probe_pins(uint32_t count)
107{
108 const uint32_t pin_count = (uint32_t)(sizeof(s_ceu_pins) / sizeof(s_ceu_pins[0]));
109 const uint32_t bounded = (count < pin_count) ? count : pin_count;
110 for (uint32_t i = 0U; i < bounded; i += 1U) {
112 }
113}
114
129{
130 const uint32_t pin_count = (uint32_t)(sizeof(s_ceu_pins) / sizeof(s_ceu_pins[0]));
131 uint32_t claimed = 0U;
132 for (; claimed < pin_count; claimed += 1U) {
133 const ra8_port_pin_t pin = RA8_PIN(s_ceu_pins[claimed].port, s_ceu_pins[claimed].pin);
135 cam_release_probe_pins(claimed);
137 }
138 }
139 return k_ra8_ok;
140}
141
158{
159 RA8_CHECK_NULL_PTR(ports, "cam", "probe_ports");
160 const cam_probe_ports_t resolved = {
161 .port4 = ra8_port(k_ra8_port_4),
162 .port7 = ra8_port(k_ra8_port_7),
163 .port9 = ra8_port(k_ra8_port_9),
164 .port11 = ra8_port(k_ra8_port_11),
165 };
166 if ((resolved.port4 == nullptr) || (resolved.port7 == nullptr) || (resolved.port9 == nullptr) ||
167 (resolved.port11 == nullptr)) {
168 return k_ra8_err_hw_error;
169 }
170 *ports = resolved;
171 return k_ra8_ok;
172}
173
186[[gnu::always_inline]] static inline uint8_t cam_read_probe_data(const cam_probe_ports_t* ports)
187{
188 /* HUM Ch 20.2 "PCNTR2 : Port Control Register 2" p 841 */
189 const uint32_t p4 = ports->port4->PCNTR2;
190 const uint32_t p7 = ports->port7->PCNTR2;
191 const uint32_t p9 = ports->port9->PCNTR2;
192 return (
193 uint8_t)(((p4 >> 0U) & 1U) | (((p9 >> 2U) & 1U) << 1U) |
194 (((p4 >> (uint32_t)k_cam_data_d2_pin_bit) & 1U) << 2U) | (((p4 >> 6U) & 1U) << 3U) |
195 (((p7 >> 0U) & 1U) << 4U) | (((p7 >> 1U) & 1U) << (uint32_t)k_cam_data_d5_out_bit) |
196 (((p7 >> 2U) & 1U) << 6U) | (((p7 >> 3U) & 1U) << (uint32_t)k_cam_data_d7_out_bit));
197}
198
212[[gnu::always_inline]] static inline uint32_t cam_read_probe_sync(const cam_probe_ports_t* ports,
213 uint32_t sync_mask)
214{
215 /* HUM Ch 20.2 "PCNTR2 : Port Control Register 2" p 841 */
216 return ports->port11->PCNTR2 & sync_mask;
217}
218
231static void cam_sync_state_init(cam_sync_state_t* state, uint32_t prior)
232{
233 const uint32_t now = ra8_dwt_cyccnt_read();
234 const cam_sync_state_t initial = {
235 .prior = prior,
236 .run_samples = 1U,
237 .run_start_cycles = now,
238 .prior_pclk_cycles = now,
239 .high_min = UINT32_MAX,
240 .low_min = UINT32_MAX,
241 .high_cycles_min = UINT32_MAX,
242 .data_min = UINT8_MAX,
243 .data_and = UINT8_MAX,
244 };
245 *state = initial;
246}
247
261[[gnu::always_inline]] static inline void
263{
264 if ((probe->data_samples != 0U) && (data != state->prior_data)) {
265 probe->data_changes += 1U;
266 }
267 state->data_min = (data < state->data_min) ? data : state->data_min;
268 state->data_max = (data > state->data_max) ? data : state->data_max;
269 state->data_and = (uint8_t)(state->data_and & data);
270 state->data_or = (uint8_t)(state->data_or | data);
271 state->prior_data = data;
272 probe->data_samples += 1U;
273}
274
289[[gnu::always_inline]] static inline void cam_record_sync_sample(const cam_probe_ports_t* ports,
290 uint32_t current,
291 cam_sync_state_t* state,
293{
294 const uint32_t changed = current ^ state->prior;
295 probe->vsync_edges += ((changed & (1UL << (uint32_t)k_ra8_pin_2)) != 0U) ? 1U : 0U;
296 probe->hsync_edges += ((changed & (1UL << (uint32_t)k_ra8_pin_3)) != 0U) ? 1U : 0U;
297 if ((changed & (1UL << (uint32_t)k_ra8_pin_4)) != 0U) {
298 const uint32_t now = ra8_dwt_cyccnt_read();
299 const uint32_t half_period = now - state->prior_pclk_cycles;
300 probe->pclk_edges += 1U;
301 probe->pclk_half_cycles_min =
302 (half_period < probe->pclk_half_cycles_min) ? half_period : probe->pclk_half_cycles_min;
303 state->prior_pclk_cycles = now;
304 if (((current & (1UL << (uint32_t)k_ra8_pin_4)) != 0U) &&
305 ((current & (1UL << (uint32_t)k_ra8_pin_3)) != 0U)) {
306 cam_record_probe_data(state, probe, cam_read_probe_data(ports));
307 }
308 }
309 if ((current & (1UL << (uint32_t)k_ra8_pin_3)) ==
310 (state->prior & (1UL << (uint32_t)k_ra8_pin_3))) {
311 state->run_samples += 1U;
312 } else if ((state->prior & (1UL << (uint32_t)k_ra8_pin_3)) != 0U) {
313 const uint32_t run_cycles = ra8_dwt_cyccnt_read() - state->run_start_cycles;
314 state->high_min = (state->run_samples < state->high_min) ? state->run_samples : state->high_min;
315 state->high_max = (state->run_samples > state->high_max) ? state->run_samples : state->high_max;
316 state->high_cycles_min =
317 (run_cycles < state->high_cycles_min) ? run_cycles : state->high_cycles_min;
318 state->high_cycles_max =
319 (run_cycles > state->high_cycles_max) ? run_cycles : state->high_cycles_max;
320 state->run_samples = 1U;
322 } else {
323 state->low_min = (state->run_samples < state->low_min) ? state->run_samples : state->low_min;
324 state->low_max = (state->run_samples > state->low_max) ? state->run_samples : state->low_max;
325 state->run_samples = 1U;
327 }
328 state->prior = current;
329}
330
344static void
345cam_measure_sync(const cam_probe_ports_t* ports, uint32_t sync_mask, cam_ceu_sync_probe_t* probe)
346{
347 cam_sync_state_t state = {};
348 cam_sync_state_init(&state, cam_read_probe_sync(ports, sync_mask));
349 probe->pclk_half_cycles_min = UINT32_MAX;
350 for (uint32_t i = 0U; i < (uint32_t)k_cam_sync_samples; i += 1U) {
351 cam_record_sync_sample(ports, cam_read_probe_sync(ports, sync_mask), &state, probe);
352 }
353 probe->hsync_high_min = (state.high_min == UINT32_MAX) ? 0U : state.high_min;
354 probe->hsync_high_max = state.high_max;
355 probe->hsync_low_min = (state.low_min == UINT32_MAX) ? 0U : state.low_min;
356 probe->hsync_low_max = state.low_max;
357 probe->hsync_high_cycles_min = (state.high_cycles_min == UINT32_MAX) ? 0U : state.high_cycles_min;
359 probe->pclk_half_cycles_min =
360 (probe->pclk_half_cycles_min == UINT32_MAX) ? 0U : probe->pclk_half_cycles_min;
361 probe->data_min = (state.data_min == UINT8_MAX) ? 0U : state.data_min;
362 probe->data_max = state.data_max;
363 probe->data_and = (probe->data_samples == 0U) ? 0U : state.data_and;
364 probe->data_or = state.data_or;
365}
366
380static void
381cam_measure_lines(const cam_probe_ports_t* ports, uint32_t sync_mask, cam_ceu_sync_probe_t* probe)
382{
383 uint32_t prior = cam_read_probe_sync(ports, sync_mask);
384 for (uint32_t i = 0U;
385 (i < (uint32_t)k_cam_sync_samples) && ((prior & (1UL << (uint32_t)k_ra8_pin_3)) != 0U);
386 i += 1U) {
387 prior = cam_read_probe_sync(ports, sync_mask);
388 }
389 for (uint32_t i = 0U;
390 (i < (uint32_t)k_cam_sync_samples) && ((prior & (1UL << (uint32_t)k_ra8_pin_3)) == 0U);
391 i += 1U) {
392 prior = cam_read_probe_sync(ports, sync_mask);
393 }
394 uint32_t line_pclk = 0U;
395 uint32_t line_sum = 0U;
396 uint32_t line_min = UINT32_MAX;
397 for (uint32_t i = 0U; i < (uint32_t)k_cam_sync_samples; i += 1U) {
398 const uint32_t current = cam_read_probe_sync(ports, sync_mask);
399 const uint32_t changed = current ^ prior;
400 if (((changed & (1UL << (uint32_t)k_ra8_pin_4)) != 0U) &&
401 ((current & (1UL << (uint32_t)k_ra8_pin_4)) != 0U) &&
402 ((current & (1UL << (uint32_t)k_ra8_pin_3)) != 0U)) {
403 line_pclk += 1U;
404 }
405 if (((changed & (1UL << (uint32_t)k_ra8_pin_3)) != 0U) &&
406 ((current & (1UL << (uint32_t)k_ra8_pin_3)) == 0U)) {
407 line_min = (line_pclk < line_min) ? line_pclk : line_min;
408 probe->line_pclk_max = (line_pclk > probe->line_pclk_max) ? line_pclk : probe->line_pclk_max;
409 line_sum += line_pclk;
410 probe->line_pclk_long += (line_pclk > (uint32_t)k_cam_long_line_pclk) ? 1U : 0U;
411 probe->measured_lines += 1U;
412 line_pclk = 0U;
413 }
414 prior = current;
415 }
416 probe->line_pclk_min = (line_min == UINT32_MAX) ? 0U : line_min;
417 probe->line_pclk_mean = (probe->measured_lines == 0U) ? 0U : (line_sum / probe->measured_lines);
418}
419
421{
422 RA8_CHECK_NULL_PTR(out_probe, "cam", "sync_probe");
423 *out_probe = (cam_ceu_sync_probe_t){};
425 if (err != k_ra8_ok) {
426 return err;
427 }
428 cam_probe_ports_t ports = {};
429 err = cam_get_probe_ports(&ports);
430 if (err == k_ra8_ok) {
431 const uint32_t sync_mask = (1UL << (uint32_t)k_ra8_pin_2) | (1UL << (uint32_t)k_ra8_pin_3) |
432 (1UL << (uint32_t)k_ra8_pin_4);
433 cam_measure_sync(&ports, sync_mask, out_probe);
434 cam_measure_lines(&ports, sync_mask, out_probe);
435 }
436 cam_release_probe_pins((uint32_t)(sizeof(s_ceu_pins) / sizeof(s_ceu_pins[0])));
437 return err;
438}
static uint8_t cam_read_probe_data(const cam_probe_ports_t *ports)
Reconstruct VIO_D[7:0] from the three GPIO input banks.
Definition cam_ceu.c:186
static void cam_measure_lines(const cam_probe_ports_t *ports, uint32_t sync_mask, cam_ceu_sync_probe_t *probe)
Measure active-line PCLK counts with three bounded sampling loops.
Definition cam_ceu.c:381
static void cam_measure_sync(const cam_probe_ports_t *ports, uint32_t sync_mask, cam_ceu_sync_probe_t *probe)
Run the bounded sync/data sampling pass and finalize its statistics.
Definition cam_ceu.c:345
static ra8_err_t cam_claim_probe_pins(void)
Claim every parallel-camera pin as a temporary GPIO input.
Definition cam_ceu.c:128
static const cam_ceu_pin_t s_ceu_pins[]
The 11 EK-RA8D2 J35 parallel-camera pins that feed the CEU: VIO_D[7:0], VIO_VD, VIO_HD,...
Definition cam_ceu.c:81
static ra8_err_t cam_get_probe_ports(cam_probe_ports_t *ports)
Resolve the four register banks that carry the camera signals.
Definition cam_ceu.c:157
static void cam_sync_state_init(cam_sync_state_t *state, uint32_t prior)
Initialize sync-sampling state from the first masked sample.
Definition cam_ceu.c:231
static uint32_t cam_read_probe_sync(const cam_probe_ports_t *ports, uint32_t sync_mask)
Read and mask the three camera sync signals from PORT11.
Definition cam_ceu.c:212
static void cam_release_probe_pins(uint32_t count)
Release a bounded prefix of the temporary camera GPIO claims.
Definition cam_ceu.c:106
static void cam_record_probe_data(cam_sync_state_t *state, cam_ceu_sync_probe_t *probe, uint8_t data)
Fold one active-line camera byte into the probe statistics.
Definition cam_ceu.c:262
cam_ceu_poll_t
Bounded GPIO signal-activity sampling constants.
Definition cam_ceu.c:34
@ k_cam_data_d7_out_bit
Reconstructed byte bit for camera D7.
Definition cam_ceu.c:38
@ k_cam_long_line_pclk
Diagnostic threshold for long HREF lines.
Definition cam_ceu.c:39
@ k_cam_sync_samples
GPIO samples for live-sync diagnostic.
Definition cam_ceu.c:35
@ k_cam_data_d2_pin_bit
P405 bit position for camera D2.
Definition cam_ceu.c:36
@ k_cam_data_d5_out_bit
Reconstructed byte bit for camera D5.
Definition cam_ceu.c:37
static void cam_record_sync_sample(const cam_probe_ports_t *ports, uint32_t current, cam_sync_state_t *state, cam_ceu_sync_probe_t *probe)
Fold one masked sync sample into edge, timing, and data statistics.
Definition cam_ceu.c:289
ra8_err_t cam_probe_sync_activity(cam_ceu_sync_probe_t *out_probe)
Measure DVP sync, clock, and data activity before CEU routing.
Definition cam_ceu.c:420
App-specific GPIO diagnostic for the parallel DVP camera signals.
ra8_board_eth_pin_t pin
Pin.
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
Error Code Definitions for ra8-firmware.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_hw_error
Generic hardware fault detected (error flag set, fault interrupt).
Definition ra8_err.h:310
@ k_ra8_err_gpio_conflict
GPIO pin already owned by another peripheral or driver.
Definition ra8_err.h:318
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
ra8_port_pin_t
Packed (port << 8) | pin pin identifier.
ra8_port_t
Port indices for the RA8D2 IOPORT module.
@ k_ra8_port_9
RA8 port 9.
@ k_ra8_port_7
RA8 port 7.
@ k_ra8_port_11
RA8 port 11.
@ k_ra8_port_4
RA8 port 4.
#define RA8_PIN(port, pin)
Build a ra8_port_pin_t from explicit port / pin indices.
ra8_pin_t
Pin indices within an IOPORT port (0..15).
@ k_ra8_pin_4
RA8 pin 4.
@ k_ra8_pin_6
RA8 pin 6.
@ k_ra8_pin_1
RA8 pin 1.
@ k_ra8_pin_2
RA8 pin 2.
@ k_ra8_pin_5
RA8 pin 5.
@ k_ra8_pin_0
RA8 pin 0.
@ k_ra8_pin_3
RA8 pin 3.
@ k_ra8_pull_none
No internal pull.
IOPORT (GPIO) register layout for the Renesas RA8D2.
static volatile r_port_regs_t * ra8_port(ra8_port_t port)
Get the PORT register window for a given port index.
High-level GPIO helpers on top of the PORT + PFS register layer.
ra8_err_t ra8_gpio_input_init(ra8_port_pin_t pin, ra8_pin_pull_t pull)
Configure a pin as a digital input.
Definition gpio.c:121
ra8_err_t ra8_gpio_release(ra8_port_pin_t pin)
Release a GPIO pin claim.
Definition gpio.c:233
Cortex-M85 SysTick + DWT cycle-counter timebase primitive.
uint32_t ra8_dwt_cyccnt_read(void)
Sample the DWT cycle counter (DWT_CYCCNT).
One CEU DVP pin: MCU port/pin routed to the CEU peripheral.
Definition cam_ceu.c:43
ra8_pin_t pin
MCU pin within the port.
Definition cam_ceu.c:45
ra8_port_t port
MCU port.
Definition cam_ceu.c:44
Snapshot of DVP sync activity observed through GPIO input samples.
Definition cam_ceu.h:26
uint32_t vsync_edges
Observed VIO_VD transitions.
Definition cam_ceu.h:27
uint32_t hsync_edges
Observed VIO_HD transitions.
Definition cam_ceu.h:28
uint32_t measured_lines
Completed HREF pulses measured in PCLK edges.
Definition cam_ceu.h:39
uint8_t data_and
AND reduction of sampled VIO_D[7:0].
Definition cam_ceu.h:46
uint32_t hsync_high_cycles_min
Shortest high run, CPU cycles.
Definition cam_ceu.h:33
uint32_t hsync_low_min
Shortest observed low run, samples.
Definition cam_ceu.h:31
uint32_t line_pclk_long
HREF pulses exceeding 1024 sampled PCLK rises.
Definition cam_ceu.h:43
uint8_t data_min
Minimum sampled VIO_D[7:0] value.
Definition cam_ceu.h:44
uint32_t pclk_edges
Observed VIO_CLK transitions.
Definition cam_ceu.h:35
uint32_t pclk_half_cycles_min
Shortest observed VIO_CLK half-period.
Definition cam_ceu.h:36
uint32_t hsync_high_max
Longest observed high run, samples.
Definition cam_ceu.h:30
uint8_t data_or
OR reduction of sampled VIO_D[7:0].
Definition cam_ceu.h:47
uint32_t line_pclk_mean
Mean PCLK rises inside measured HREF pulses.
Definition cam_ceu.h:42
uint32_t line_pclk_max
Maximum PCLK rises inside one HREF pulse.
Definition cam_ceu.h:41
uint32_t line_pclk_min
Minimum PCLK rises inside one HREF pulse.
Definition cam_ceu.h:40
uint32_t data_samples
Data bytes sampled on active-line PCLK rises.
Definition cam_ceu.h:37
uint8_t data_max
Maximum sampled VIO_D[7:0] value.
Definition cam_ceu.h:45
uint32_t hsync_high_min
Shortest observed high run, samples.
Definition cam_ceu.h:29
uint32_t data_changes
Changes between consecutive sampled bytes.
Definition cam_ceu.h:38
uint32_t hsync_low_max
Longest observed low run, samples.
Definition cam_ceu.h:32
uint32_t hsync_high_cycles_max
Longest high run, CPU cycles.
Definition cam_ceu.h:34
GPIO register banks used while sampling the parallel camera bus.
Definition cam_ceu.c:49
volatile r_port_regs_t * port9
D1 input bank.
Definition cam_ceu.c:52
volatile r_port_regs_t * port4
D0, D2, and D3 input bank.
Definition cam_ceu.c:50
volatile r_port_regs_t * port7
D4 through D7 input bank.
Definition cam_ceu.c:51
volatile r_port_regs_t * port11
VSYNC, HSYNC, and PCLK.
Definition cam_ceu.c:53
Accumulator for the bounded sync/data sampling pass.
Definition cam_ceu.c:57
uint32_t run_start_cycles
Cycle counter at HSYNC run start.
Definition cam_ceu.c:60
uint8_t data_min
Minimum sampled camera byte.
Definition cam_ceu.c:68
uint8_t prior_data
Previously sampled camera byte.
Definition cam_ceu.c:72
uint8_t data_and
AND reduction of camera bytes.
Definition cam_ceu.c:70
uint8_t data_or
OR reduction of camera bytes.
Definition cam_ceu.c:71
uint32_t low_min
Minimum low run in samples.
Definition cam_ceu.c:64
uint32_t high_max
Maximum high run in samples.
Definition cam_ceu.c:63
uint32_t high_cycles_max
Maximum high run in CPU cycles.
Definition cam_ceu.c:67
uint32_t low_max
Maximum low run in samples.
Definition cam_ceu.c:65
uint32_t high_min
Minimum high run in samples.
Definition cam_ceu.c:62
uint8_t data_max
Maximum sampled camera byte.
Definition cam_ceu.c:69
uint32_t run_samples
Samples in the current HSYNC run.
Definition cam_ceu.c:59
uint32_t high_cycles_min
Minimum high run in CPU cycles.
Definition cam_ceu.c:66
uint32_t prior_pclk_cycles
Cycle counter at prior PCLK edge.
Definition cam_ceu.c:61
uint32_t prior
Previous masked sync sample.
Definition cam_ceu.c:58
Per-port IOPORT register window.
volatile uint32_t PCNTR2
PCNTR2 – { EIDR[31:16], PIDR[15:0] } (read-only).