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
48
49#include <stdint.h>
50
51#include "ra8_board_ek_ra8d2.h"
52#include "ra8_boot_entry.h"
53#include "ra8_cgc.h"
54#include "ra8_display_pal.h"
55#include "ra8_display_pal_lcd.h"
56#include "ra8_err.h"
57#include "ra8_glcdc.h"
58#include "ra8_isr.h"
59#include "ra8_mstp.h"
60#include "ra8_panel.h"
61#include "ra8_panel_timing.h"
62#include "ra8_time.h"
63
76typedef enum : uint16_t {
77 k_gh_fb_w = 512U,
78 k_gh_fb_h = 512U,
81
88typedef enum : uint16_t {
89 k_gh_color_bg = 0x001FU,
90 k_gh_color_x = 0xFFE0U,
93
100typedef enum : uint32_t {
101 k_gh_uart_baud = 115200U,
102 k_gh_fnv_offset = 2166136261U,
103 k_gh_fnv_prime = 16777619U,
109
115[[gnu::aligned(k_ra8_board_fb_align_bytes)]] static uint16_t
116 s_framebuffer[(uint32_t)k_gh_fb_w * (uint32_t)k_gh_fb_h];
117
130 .framebuffer = s_framebuffer,
131 .framebuffer_bytes = sizeof(s_framebuffer),
132 .width_px = (uint16_t)k_gh_fb_w,
133 .height_px = (uint16_t)k_gh_fb_h,
134 .pixfmt = k_display_pixfmt_rgb565,
135 .panel_timing = &s_ra8_panel_ek_ra8d2_timing,
136};
137
145volatile uint32_t g_glcdc_hil_ok = 0U;
153volatile uint32_t g_glcdc_hil_crc = 0U;
161volatile uint32_t g_glcdc_hil_status = 0U;
169volatile uint32_t g_glcdc_hil_heartbeat = 0U;
170
171static const uint8_t k_gh_msg_boot[] = "glcdc-hil: boot\r\n";
172static const uint8_t k_gh_msg_fail_init[] = "glcdc-hil: FAIL init\r\n";
173static const uint8_t k_gh_msg_fail_glcdc[] = "glcdc-hil: FAIL glcdc\r\n";
174static const uint8_t k_gh_msg_pre[] = "glcdc-hil: layer1=ok dim=";
175static const uint8_t k_gh_msg_x[] = "x";
176static const uint8_t k_gh_msg_crc[] = " crc=";
177static const uint8_t k_gh_msg_pass[] = " PASS\r\n";
178
179/* ===========================================================================
180 * Console
181 * ===========================================================================
182 */
183
185static void gh_print(const uint8_t* msg, uint32_t len)
186{
187 (void)ra8_board_uart_console_write(msg, (size_t)len);
188}
189
191static void gh_panic_halt(void)
192{
193 gh_print(k_gh_msg_fail_init, (uint32_t)sizeof(k_gh_msg_fail_init) - 1U);
194 while (1) {
195 __asm__ volatile("wfi");
196 }
197}
198
200static void gh_print_hex(uint32_t value)
201{
202 uint8_t buf[k_gh_hex_nibbles];
203 for (uint32_t i = 0U; i < (uint32_t)k_gh_hex_nibbles; i++) {
204 const uint32_t shift = ((uint32_t)k_gh_hex_nibbles - 1U - i) * (uint32_t)k_gh_nibble_bits;
205 const uint32_t nib = (value >> shift) & (uint32_t)k_gh_nibble_mask;
206 buf[i] = (uint8_t)((nib < (uint32_t)k_gh_dec_ten) ? ('0' + nib) : ('A' + (nib - k_gh_dec_ten)));
207 }
208 gh_print(buf, (uint32_t)k_gh_hex_nibbles);
209}
210
212static void gh_print_uint(uint32_t value)
213{
214 uint8_t buf[k_gh_dec_ten];
215 uint32_t n = 0U;
216 if (value == 0U) {
217 buf[n] = '0';
218 n++;
219 }
220 while ((value > 0U) && (n < (uint32_t)k_gh_dec_ten)) {
221 buf[n] = (uint8_t)('0' + (value % (uint32_t)k_gh_dec_ten));
222 n++;
223 value /= (uint32_t)k_gh_dec_ten;
224 }
225 for (uint32_t i = 0U; i < n; i++) {
226 gh_print(&buf[n - 1U - i], 1U);
227 }
228}
229
230/* ===========================================================================
231 * Deterministic framebuffer pattern
232 * ===========================================================================
233 */
234
236static void gh_fb_fill(uint16_t color)
237{
238 for (uint32_t i = 0U; i < (uint32_t)k_gh_fb_w * (uint32_t)k_gh_fb_h; i++) {
239 s_framebuffer[i] = color;
240 }
241}
242
244static void gh_draw_x(uint16_t color)
245{
246 for (uint16_t x = 0U; x < (uint16_t)k_gh_fb_w; x++) {
247 const int32_t y_down = ((int32_t)x * (int32_t)k_gh_fb_h) / (int32_t)k_gh_fb_w;
248 const int32_t y_up = ((int32_t)k_gh_fb_h - 1) - y_down;
249 for (int32_t dy = -(int32_t)k_gh_x_thickness; dy <= (int32_t)k_gh_x_thickness; dy++) {
250 const int32_t yy_down = y_down + dy;
251 const int32_t yy_up = y_up + dy;
252 if ((yy_down >= 0) && (yy_down < (int32_t)k_gh_fb_h)) {
253 s_framebuffer[((uint32_t)yy_down * (uint32_t)k_gh_fb_w) + (uint32_t)x] = color;
254 }
255 if ((yy_up >= 0) && (yy_up < (int32_t)k_gh_fb_h)) {
256 s_framebuffer[((uint32_t)yy_up * (uint32_t)k_gh_fb_w) + (uint32_t)x] = color;
257 }
258 }
259 }
260}
261
263static void gh_draw_border(uint16_t color)
264{
265 const uint32_t last_row = ((uint32_t)k_gh_fb_h - 1U) * (uint32_t)k_gh_fb_w;
266 for (uint32_t x = 0U; x < (uint32_t)k_gh_fb_w; x++) {
267 s_framebuffer[x] = color;
268 s_framebuffer[last_row + x] = color;
269 }
270 for (uint32_t y = 0U; y < (uint32_t)k_gh_fb_h; y++) {
271 const uint32_t row = y * (uint32_t)k_gh_fb_w;
272 s_framebuffer[row] = color;
273 s_framebuffer[row + (uint32_t)k_gh_fb_w - 1U] = color;
274 }
275}
276
278static void gh_render_pattern(void)
279{
280 gh_fb_fill((uint16_t)k_gh_color_bg);
281 gh_draw_x((uint16_t)k_gh_color_x);
283#ifndef RA8_OFF_TARGET
284 __asm__ volatile("dsb" ::: "memory");
285#endif
286}
287
289static uint32_t gh_framebuffer_hash(void)
290{
291 const uint8_t* p = (const uint8_t*)s_framebuffer;
292 const size_t n = sizeof(s_framebuffer);
293 uint32_t hsh = (uint32_t)k_gh_fnv_offset;
294 for (size_t i = 0U; i < n; i++) {
295 hsh = (hsh ^ (uint32_t)p[i]) * (uint32_t)k_gh_fnv_prime;
296 }
297 return hsh;
298}
299
300/* ===========================================================================
301 * GLCDC bring-up + programmed-layer proof
302 * ===========================================================================
303 */
304
328static bool gh_glcdc_programmed(void)
329{
330 display_handle_t* d = nullptr;
332 return false;
333 }
334 if (d == nullptr) {
335 return false;
336 }
337 display_fb_t fb = {};
338 if (display_get_framebuffer(d, &fb) != k_ra8_ok) {
339 return false;
340 }
341 if (fb.pixels != (void*)s_framebuffer) {
342 return false;
343 }
344 uint32_t status_mask = 0U;
345 if (ra8_glcdc_get_status(&status_mask) != k_ra8_ok) {
346 return false;
347 }
348 g_glcdc_hil_status = status_mask;
349 return true;
350}
351
353static void gh_setup_or_halt(void)
354{
355 uint32_t cpuclk0_hz = 0U;
356 if ((ra8_cgc_init() != k_ra8_ok) || (ra8_mstp_init() != k_ra8_ok)) {
358 }
361 }
362 if (ra8_time_init(cpuclk0_hz) != k_ra8_ok) {
364 }
367 }
368}
369
370/* ===========================================================================
371 * Boot + main
372 * ===========================================================================
373 */
374
384void main(void)
385{
388 gh_print(k_gh_msg_boot, (uint32_t)sizeof(k_gh_msg_boot) - 1U);
389
391
392 if (!gh_glcdc_programmed()) {
393 gh_print(k_gh_msg_fail_glcdc, (uint32_t)sizeof(k_gh_msg_fail_glcdc) - 1U);
394 while (1) {
395 __asm__ volatile("wfi");
396 }
397 }
398 g_glcdc_hil_ok = 1U;
400
401 gh_print(k_gh_msg_pre, (uint32_t)sizeof(k_gh_msg_pre) - 1U);
402 gh_print_uint((uint32_t)k_gh_fb_w);
403 gh_print(k_gh_msg_x, (uint32_t)sizeof(k_gh_msg_x) - 1U);
404 gh_print_uint((uint32_t)k_gh_fb_h);
405 gh_print(k_gh_msg_crc, (uint32_t)sizeof(k_gh_msg_crc) - 1U);
406 gh_print_hex((uint32_t)g_glcdc_hil_crc);
407 gh_print(k_gh_msg_pass, (uint32_t)sizeof(k_gh_msg_pass) - 1U);
408
409 while (1) {
411 __asm__ volatile("wfi");
412 }
413}
void main(void)
Secure fallback main entry point.
Definition main.c:37
static uint16_t s_framebuffer[(size_t) k_panel_height_px *(size_t) k_panel_width_px]
1024x600 RGB565 framebuffer in external SDRAM (GLCDC scans this).
Definition main.c:67
static const uint8_t k_gh_msg_pre[]
Definition main.c:174
static bool gh_glcdc_programmed(void)
Bring the GLCDC layer-1 path up and prove it is programmed.
Definition main.c:328
static uint32_t gh_framebuffer_hash(void)
FNV-1a-32 over the rendered framebuffer bytes.
Definition main.c:289
static void gh_render_pattern(void)
Paint the full deterministic render pattern.
Definition main.c:278
glcdc_hil_console_t
SCI8 J-Link OB console + text-format constants.
Definition main.c:100
@ k_gh_dec_ten
Hex digit / decimal split + buf.
Definition main.c:107
@ k_gh_hex_nibbles
Hex digits in a 32-bit value.
Definition main.c:104
@ k_gh_uart_baud
Console baud.
Definition main.c:101
@ k_gh_fnv_prime
FNV-1a-32 prime.
Definition main.c:103
@ k_gh_nibble_mask
Low-nibble mask.
Definition main.c:106
@ k_gh_nibble_bits
Bits per hex nibble.
Definition main.c:105
@ k_gh_fnv_offset
FNV-1a-32 offset basis.
Definition main.c:102
static void gh_fb_fill(uint16_t color)
Fill the whole framebuffer with color.
Definition main.c:236
static void gh_setup_or_halt(void)
Bring up clocks/MSTP/time + the SCI8 console; halt on failure.
Definition main.c:353
static void gh_print_uint(uint32_t value)
Print a small unsigned integer in decimal.
Definition main.c:212
static void gh_draw_border(uint16_t color)
Draw a 1-px border around the whole framebuffer in color.
Definition main.c:263
glcdc_hil_color_t
RGB565 palette for the deterministic render pattern.
Definition main.c:88
@ k_gh_color_border
White 1-px frame.
Definition main.c:91
@ k_gh_color_x
Yellow diagonal X.
Definition main.c:90
@ k_gh_color_bg
Dark blue field.
Definition main.c:89
static void gh_print_hex(uint32_t value)
Print value as 8 uppercase hex digits.
Definition main.c:200
volatile uint32_t g_glcdc_hil_ok
1 once the GLCDC layer-1 render path is confirmed programmed.
Definition main.c:145
static const uint8_t k_gh_msg_x[]
Definition main.c:175
static const uint8_t k_gh_msg_fail_init[]
Definition main.c:172
static const uint8_t k_gh_msg_pass[]
Definition main.c:177
volatile uint32_t g_glcdc_hil_status
Last GLCDC SYS_STAT snapshot (diagnostic; not part of the CRC).
Definition main.c:161
static const uint8_t k_gh_msg_fail_glcdc[]
Definition main.c:173
volatile uint32_t g_glcdc_hil_crc
FNV-1a-32 of the rendered framebuffer (the on-bench baseline).
Definition main.c:153
glcdc_hil_geom_t
Framebuffer geometry constants.
Definition main.c:76
@ k_gh_fb_w
Framebuffer width, pixels.
Definition main.c:77
@ k_gh_fb_h
Framebuffer height, pixels.
Definition main.c:78
@ k_gh_x_thickness
Diagonal-X half thickness, pixels.
Definition main.c:79
static void gh_panic_halt(void)
Park forever in WFI after a fatal init error.
Definition main.c:191
static void gh_draw_x(uint16_t color)
Draw a thick corner-to-corner X in color.
Definition main.c:244
static void gh_print(const uint8_t *msg, uint32_t len)
Emit a byte run on the SCI8 console.
Definition main.c:185
static const uint8_t k_gh_msg_crc[]
Definition main.c:176
volatile uint32_t g_glcdc_hil_heartbeat
Bumps on every idle-loop pass after a passing render.
Definition main.c:169
static const display_cfg_t k_gh_display_cfg
Display PAL config selecting the GLCDC LCD backend.
Definition main.c:128
static const uint8_t k_gh_msg_boot[]
Definition main.c:171
Board-support layer for the Renesas EK-RA8D2 v1 evaluation kit.
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.
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
Display Platform Abstraction Layer for the RA8D2.
@ k_display_pixfmt_rgb565
16 bpp, 5/6/5 packed.
ra8_err_t display_get_framebuffer(const display_handle_t *d, display_fb_t *out)
Return the framebuffer descriptor the backend is targeting.
struct display_handle display_handle_t
ra8_err_t display_init(const display_cfg_t *cfg, display_handle_t **out_handle)
Initialise the display PAL and bring the selected backend up to a state where display_flush succeeds.
LCD backend (ra8_glcdc) for the display PAL.
const display_backend_iface_t k_display_backend_lcd_ra8_glcdc
LCD backend vtable – pass its address through display_cfg_t.iface to drive the EK-RA8D2 panel.
Error Code Definitions for ra8-firmware.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
Graphics LCD Controller driver (two-layer with alpha blending).
ra8_err_t ra8_glcdc_get_status(uint32_t *out_mask)
Read GLCDC status register (VSYNC/HSYNC/underflow).
Definition ra8_glcdc.c:828
NVIC + ICU IELSR allocator.
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
Active display-panel descriptor for the EK-RA8D2 (ER-TFT070-6).
@ k_ra8_board_fb_align_bytes
GLCDC AXI burst alignment, in bytes.
Definition ra8_panel.h:108
EK-RA8D2 panel timing as the HAL's ra8_glcdc_timing_t (ER-TFT070-6).
static const ra8_glcdc_timing_t s_ra8_panel_ek_ra8d2_timing
EK-RA8D2 ER-TFT070-6 RGB timing for ra8_glcdc_init / the LCD backend.
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
Configuration descriptor passed into display_init.
Framebuffer descriptor returned by display_get_framebuffer.
void * pixels
Base of pixel data (RGB565 unless noted).