ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_display_pal_lcd.c File Reference

LCD backend (ra8_glcdc) implementation for the display PAL. More...

#include "ra8_display_pal_lcd.h"
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "ra8_attributes.h"
#include "ra8_board_ek_ra8d2.h"
#include "ra8_cache.h"
#include "ra8_check.h"
#include "ra8_display_pal.h"
#include "ra8_display_pal_internal.h"
#include "ra8_err.h"
#include "ra8_glcdc.h"
#include "ra8_log.h"
#include "ra8_time.h"
Include dependency graph for ra8_display_pal_lcd.c:

Go to the source code of this file.

Data Structures

struct  lcd_ctx_t
 LCD backend private context attached to the PAL handle. More...

Enumerations

enum  disp_lcd_mask_t : uint32_t { k_rgb565_mask = 0xFFFFU }
 RGB565 pixel mask. More...
enum  ra8_display_pal_lcd_const_t : uint32_t {
  k_lcd_bringup_settle_ms = 200U ,
  k_lcd_bg_color_black = 0U ,
  k_lcd_fb_align_bytes = 64U ,
  k_lcd_rgb565_bpp = 2U
}
 Numeric constants used by the LCD backend bring-up. More...

Functions

static void internal_lcd_dsb (void)
 DSB memory barrier on Cortex-M, no-op on the host test build.
static ra8_err_t internal_lcd_validate_cfg (const display_cfg_t *cfg)
 Validate the caller's display_cfg_t against the LCD backend's expectations.
static ra8_err_t internal_lcd_bringup_panel (const display_cfg_t *cfg)
 Drive the GPIO + GLCDC sequence that powers the panel up and starts scan-out.
static void internal_lcd_snapshot (const display_cfg_t *cfg)
 Populate s_lcd_ctx from the validated cfg.
static ra8_err_t internal_lcd_check_rect (const display_caps_t *caps, display_rect_t r)
 Confirm a rectangle stays inside the active framebuffer.
static ra8_err_t internal_lcd_init (const display_cfg_t *cfg, void **out_ctx)
 LCD backend init – validate, panel bring-up, snapshot.
static ra8_err_t internal_lcd_get_caps (const void *ctx, display_caps_t *out)
 Vtable get_caps – O(1) copy from s_lcd_ctx.caps.
static ra8_err_t internal_lcd_get_framebuffer (void *ctx, display_fb_t *out)
 Vtable get_framebuffer – hand back the FB descriptor.
static ra8_err_t internal_lcd_flush (void *ctx, display_rect_t rect, display_refresh_hint_t hint)
 Vtable flush – DSB barrier, validate rect.
static ra8_err_t internal_lcd_clear (void *ctx, uint32_t color)
 Vtable clear – fill the framebuffer with a uniform RGB565 value.
static ra8_err_t internal_lcd_deinit (void *ctx)
 Vtable deinit – tear the GLCDC down and drop state.

Variables

static const char *const s_tag = "ra8_display_pal_lcd"
 Module log tag.
static lcd_ctx_t s_lcd_ctx
 Single LCD backend context – one display per board.
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.

Detailed Description

LCD backend (ra8_glcdc) implementation for the display PAL.

Tag
[Ring 4 / PAL] {World: NS}

Wraps the existing libs/ra8_hal/src/ra8_glcdc.c HAL plus the EK-RA8D2 panel power-on sequence into the display_backend_iface_t shape the PAL dispatcher consumes. The 6-step bring-up that used to be duplicated in every LCD-using app's lcd_bringup_panel collapses into a single display_init call.

Definition in file ra8_display_pal_lcd.c.

Enumeration Type Documentation

◆ disp_lcd_mask_t

enum disp_lcd_mask_t : uint32_t

RGB565 pixel mask.

Enumerator
k_rgb565_mask 

Rgb565 mask.

Definition at line 46 of file ra8_display_pal_lcd.c.

◆ ra8_display_pal_lcd_const_t

enum ra8_display_pal_lcd_const_t : uint32_t

Numeric constants used by the LCD backend bring-up.

Since
0.1.0
Enumerator
k_lcd_bringup_settle_ms 

Pin/clock settle after board_glcdc_init.

k_lcd_bg_color_black 

24-bit ARGB for BG plane.

k_lcd_fb_align_bytes 

AXI burst alignment (HUM Ch 63).

k_lcd_rgb565_bpp 

Bytes per RGB565 pixel.

Definition at line 56 of file ra8_display_pal_lcd.c.

Function Documentation

◆ internal_lcd_bringup_panel()

ra8_err_t internal_lcd_bringup_panel ( const display_cfg_t * cfg)
static

Drive the GPIO + GLCDC sequence that powers the panel up and starts scan-out.

Mirrors the lcd_bringup_panel helper that used to live in every LCD-using app: panel power-on, board GLCDC routing, settle, GLCDC init, BG clear, start(true), layer1_show. Returns on the first error – callers must treat a non-ok return as "panel may be in any state" and not call deinit.

Parameters
[in]cfgCaller configuration (validated upstream).
Returns
ra8_err_t Error code from the first failing HAL call, or k_ra8_ok once GR1 is showing.
Return values
k_ra8_okPanel is up and GR1 is visible.
(fromra8_board_*) Forwarded from the board helpers.
(fromra8_glcdc_*) Forwarded from the GLCDC HAL.
Precondition
internal_lcd_validate_cfg returned k_ra8_ok for cfg.
MSTP and CGC are already initialised by the boot path.
Postcondition
On success: GLCDC scanning out, GR1 visible over BG black.
On failure: state is implementation-defined; caller bails.
Note
Not thread-safe; single-shot init helper.
Since
0.1.0

Definition at line 190 of file ra8_display_pal_lcd.c.

References display_cfg_t::framebuffer, display_cfg_t::height_px, k_lcd_bg_color_black, k_lcd_bringup_settle_ms, k_ra8_board_glcdc_fmt_rgb888, k_ra8_glcdc_fmt_rgb565, k_ra8_ok, display_cfg_t::panel_timing, ra8_board_glcdc_init(), ra8_board_lcd_panel_power_on(), ra8_delay_ms(), ra8_glcdc_init(), ra8_glcdc_layer1_show(), ra8_glcdc_set_background_color(), ra8_glcdc_start(), and display_cfg_t::width_px.

◆ internal_lcd_check_rect()

ra8_err_t internal_lcd_check_rect ( const display_caps_t * caps,
display_rect_t r )
static

Confirm a rectangle stays inside the active framebuffer.

Compound boolean intentionally split into four sequential checks so MC/DC vectors are trivial.

Parameters
[in]capsBackend capabilities.
[in]rCandidate rectangle.
Returns
ra8_err_t Error code.
Return values
k_ra8_okRectangle fits.
k_ra8_err_invalid_argRectangle would step out of bounds.
Precondition
caps reflects the bound framebuffer.
r has been zero-initialised by the caller.
Postcondition
No state mutated.
Return depends solely on inputs.
Note
Thread-safe.
Since
0.1.0

Definition at line 287 of file ra8_display_pal_lcd.c.

References display_rect_t::h, display_caps_t::height_px, k_ra8_err_invalid_arg, k_ra8_ok, display_rect_t::w, display_caps_t::width_px, display_rect_t::x, and display_rect_t::y.

Referenced by internal_lcd_flush().

◆ internal_lcd_clear()

ra8_err_t internal_lcd_clear ( void * ctx,
uint32_t color )
static

Vtable clear – fill the framebuffer with a uniform RGB565 value.

Tight CPU loop; not the fastest possible (DMA would beat this) but the simplest correct implementation.

Parameters
[in]ctxBackend context.
[in]colorPixel value (low 16 bits used).
Returns
ra8_err_t Error code.
Return values
k_ra8_okBuffer cleared.
k_ra8_err_null_ptrctx was NULL.
Precondition
internal_lcd_init has succeeded.
Framebuffer is reachable from the CPU.
Postcondition
Every pixel of the FB equals color & 0xFFFF.
DSB barrier issued so the GLCDC sees the writes.
Note
Not thread-safe with concurrent paint loops.
Since
0.1.0

Definition at line 504 of file ra8_display_pal_lcd.c.

References lcd_ctx_t::fb, display_fb_t::height_px, internal_lcd_dsb(), k_ra8_ok, k_rgb565_mask, display_fb_t::pixels, ra8_cache_dcache_clean_by_addr(), RA8_CHECK_NULL_PTR, s_tag, display_fb_t::stride_bytes, and display_fb_t::width_px.

◆ internal_lcd_deinit()

ra8_err_t internal_lcd_deinit ( void * ctx)
static

Vtable deinit – tear the GLCDC down and drop state.

Forwards to ra8_glcdc_deinit which disables scan-out and clears the registers. GPIO pins claimed during ra8_board_lcd_panel_power_on are left claimed (a follow-up init either does a chip reset first or stays bound).

Parameters
[in]ctxBackend context.
Returns
ra8_err_t Error code from ra8_glcdc_deinit (or k_ra8_err_null_ptr if ctx was NULL).
Return values
k_ra8_okTear-down succeeded.
k_ra8_err_null_ptrctx was NULL.
Precondition
internal_lcd_init has succeeded.
No concurrent paint loops.
Postcondition
s_lcd_ctx.started == false.
s_lcd_ctx.fb.pixels == nullptr.
Note
Not thread-safe.
Since
0.1.0

Definition at line 551 of file ra8_display_pal_lcd.c.

References lcd_ctx_t::fb, display_fb_t::pixels, RA8_CHECK_NULL_PTR, ra8_glcdc_deinit(), s_tag, and lcd_ctx_t::started.

◆ internal_lcd_dsb()

void internal_lcd_dsb ( void )
inlinestatic

DSB memory barrier on Cortex-M, no-op on the host test build.

Guarded with RA8_OFF_TARGET so the host x86 build does not try to assemble the ARMv8-M dsb instruction. Matches the pattern used by ra8_reset.c and ra8_lpm.c.

Precondition
None.
None.
Postcondition
Prior register / memory writes are observable.
No state mutated.
Note
Inlined; zero-overhead on the host.
Since
0.1.0

Definition at line 100 of file ra8_display_pal_lcd.c.

Referenced by internal_lcd_clear(), and internal_lcd_flush().

◆ internal_lcd_flush()

ra8_err_t internal_lcd_flush ( void * ctx,
display_rect_t rect,
display_refresh_hint_t hint )
static

Vtable flush – DSB barrier, validate rect.

LCD scans continuously so flush is essentially a no-op (the caller's writes will land on the next scan). We still validate rect so callers writing backend-agnostic code learn about out-of-bounds rectangles at the LCD path rather than first discovering them on e-ink. hint is ignored.

Parameters
[in]ctxBackend context.
[in]rectRegion the caller painted.
[in]hintRefresh-mode intent (ignored for LCD).
Returns
ra8_err_t Error code.
Return values
k_ra8_okBarrier issued.
k_ra8_err_null_ptrctx was NULL.
k_ra8_err_invalid_argrect leaves the framebuffer.
Precondition
internal_lcd_init has succeeded.
None.
Postcondition
Panel state is unchanged until the next scan picks up the writes.
No state mutated.
Note
Thread-safe.
Since
0.1.0

Definition at line 451 of file ra8_display_pal_lcd.c.

References lcd_ctx_t::caps, lcd_ctx_t::fb, display_rect_t::h, internal_lcd_check_rect(), internal_lcd_dsb(), k_ra8_ok, display_fb_t::pixels, ra8_cache_dcache_clean_by_addr(), RA8_CHECK_NULL_PTR, s_tag, display_fb_t::stride_bytes, and display_rect_t::y.

◆ internal_lcd_get_caps()

ra8_err_t internal_lcd_get_caps ( const void * ctx,
display_caps_t * out )
static

Vtable get_caps – O(1) copy from s_lcd_ctx.caps.

The caps were snapshotted from cfg at init time.

Parameters
[in]ctxBackend context.
[out]outCapabilities snapshot.
Returns
ra8_err_t Error code.
Return values
k_ra8_okCaps written.
k_ra8_err_null_ptrEither argument was NULL.
Precondition
internal_lcd_init has succeeded.
out is writable.
Postcondition
*out equals the stored caps.
No state mutated.
Note
Thread-safe.
Since
0.1.0

Definition at line 381 of file ra8_display_pal_lcd.c.

References lcd_ctx_t::caps, k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.

◆ internal_lcd_get_framebuffer()

ra8_err_t internal_lcd_get_framebuffer ( void * ctx,
display_fb_t * out )
static

Vtable get_framebuffer – hand back the FB descriptor.

Returns the same buffer the caller passed in via cfg.

Parameters
[in]ctxBackend context.
[out]outFramebuffer descriptor.
Returns
ra8_err_t Error code.
Return values
k_ra8_okDescriptor written.
k_ra8_err_null_ptrEither argument was NULL.
Precondition
internal_lcd_init has succeeded.
out is writable.
Postcondition
*out.pixels matches cfg.framebuffer.
No state mutated.
Note
Thread-safe relative to other PAL calls.
Since
0.1.0

Definition at line 413 of file ra8_display_pal_lcd.c.

References lcd_ctx_t::fb, k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.

◆ internal_lcd_init()

ra8_err_t internal_lcd_init ( const display_cfg_t * cfg,
void ** out_ctx )
static

LCD backend init – validate, panel bring-up, snapshot.

Vtable entry for k_display_backend_lcd_ra8_glcdc. The body is short because the heavy lifting is in the two internal helpers above; this matches the NASA P10 Rule 4 per-function size budget.

Parameters
[in]cfgCaller configuration.
[out]out_ctxFilled with the backend context pointer.
Returns
ra8_err_t Error code.
Return values
k_ra8_okBackend ready.
k_ra8_err_null_ptrRequired pointer was NULL.
k_ra8_err_invalid_argDimensions / buffer size invalid.
k_ra8_err_not_supportedPixel format other than RGB565.
k_ra8_err_busyBackend already started.
Precondition
PAL dispatcher has not bound a backend yet.
Clocks and MSTP have been initialised by the caller's boot path.
Postcondition
Panel is powered and scanning out the caller's framebuffer.
s_lcd_ctx.started == true on success.
Note
Not thread-safe.
Since
0.1.0

Definition at line 337 of file ra8_display_pal_lcd.c.

References internal_lcd_bringup_panel(), internal_lcd_snapshot(), internal_lcd_validate_cfg(), k_ra8_err_busy, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_log_error, s_lcd_ctx, and s_tag.

◆ internal_lcd_snapshot()

void internal_lcd_snapshot ( const display_cfg_t * cfg)
static

Populate s_lcd_ctx from the validated cfg.

Snapshotting cfg into the context lets get_caps / get_framebuffer answer without touching the cfg pointer again – the caller may free its cfg after init returns.

Parameters
[in]cfgValidated caller configuration.
Precondition
internal_lcd_validate_cfg returned k_ra8_ok.
cfg is alive for the duration of the call (read-only).
Postcondition
s_lcd_ctx mirrors cfg's geometry + framebuffer pointer.
s_lcd_ctx.started == true.
Note
Not thread-safe.
Since
0.1.0

Definition at line 244 of file ra8_display_pal_lcd.c.

References display_cfg_t::framebuffer, display_cfg_t::height_px, k_display_pixfmt_rgb565, k_lcd_rgb565_bpp, s_lcd_ctx, and display_cfg_t::width_px.

Referenced by internal_lcd_init().

◆ internal_lcd_validate_cfg()

ra8_err_t internal_lcd_validate_cfg ( const display_cfg_t * cfg)
static

Validate the caller's display_cfg_t against the LCD backend's expectations.

Rejects NULL framebuffer, zero / negative dimensions, undersized buffer, and any non-RGB565 pixel format. Run before any hardware call so a failure leaves the panel untouched.

Parameters
[in]cfgCaller configuration.
Returns
ra8_err_t Error code.
Return values
k_ra8_okConfiguration accepted.
k_ra8_err_null_ptrFramebuffer pointer was NULL.
k_ra8_err_invalid_argDimensions or buffer size out of range.
k_ra8_err_not_supportedPixel format other than RGB565.
Precondition
None.
None.
Postcondition
No state mutated.
Returned value depends solely on cfg.
Note
Thread-safe.
Since
0.1.0

Definition at line 139 of file ra8_display_pal_lcd.c.

References display_cfg_t::framebuffer, display_cfg_t::framebuffer_bytes, display_cfg_t::height_px, k_display_pixfmt_rgb565, k_lcd_rgb565_bpp, k_ra8_err_invalid_arg, k_ra8_err_not_supported, k_ra8_ok, display_cfg_t::panel_timing, display_cfg_t::pixfmt, RA8_CHECK_NULL_PTR, s_tag, and display_cfg_t::width_px.

Referenced by internal_lcd_init().

Variable Documentation

◆ k_display_backend_lcd_ra8_glcdc

const display_backend_iface_t k_display_backend_lcd_ra8_glcdc
Initial value:
= {
.get_caps = internal_lcd_get_caps,
.get_framebuffer = internal_lcd_get_framebuffer,
}
static ra8_err_t internal_lcd_get_framebuffer(void *ctx, display_fb_t *out)
Vtable get_framebuffer – hand back the FB descriptor.
static ra8_err_t internal_lcd_flush(void *ctx, display_rect_t rect, display_refresh_hint_t hint)
Vtable flush – DSB barrier, validate rect.
static ra8_err_t internal_lcd_deinit(void *ctx)
Vtable deinit – tear the GLCDC down and drop state.
static ra8_err_t internal_lcd_clear(void *ctx, uint32_t color)
Vtable clear – fill the framebuffer with a uniform RGB565 value.
static ra8_err_t internal_lcd_get_caps(const void *ctx, display_caps_t *out)
Vtable get_caps – O(1) copy from s_lcd_ctx.caps.
static ra8_err_t internal_lcd_init(const display_cfg_t *cfg, void **out_ctx)
LCD backend init – validate, panel bring-up, snapshot.

LCD backend vtable – pass its address through display_cfg_t.iface to drive the EK-RA8D2 panel.

The vtable's init callback runs the full GLCDC bring-up:

  1. ra8_board_lcd_panel_power_on – toggle RESET_L low/high and assert BLEN.
  2. ra8_board_glcdc_init(k_ra8_board_glcdc_fmt_rgb888) – pin and clock setup for the parallel-RGB bus.
  3. 200 ms settle delay (panel POR + pin direction).
  4. ra8_glcdc_init with the caller's framebuffer / dimensions.
  5. ra8_glcdc_set_background_color(0x000000) – BG plane black.
  6. ra8_glcdc_start(true) – enable scan-out.
  7. ra8_glcdc_layer1_show – expose Graphics 1 over the FB.

The matching deinit callback turns the panel back off.

Note
Only one display can be initialised at a time; calling display_init while a previous handle is still live returns k_ra8_err_busy.
Since
0.1.0

Definition at line 566 of file ra8_display_pal_lcd.c.

◆ s_lcd_ctx

lcd_ctx_t s_lcd_ctx
static

Single LCD backend context – one display per board.

Definition at line 80 of file ra8_display_pal_lcd.c.

Referenced by internal_lcd_init(), and internal_lcd_snapshot().

◆ s_tag

const char* const s_tag = "ra8_display_pal_lcd"
static

Module log tag.

Definition at line 43 of file ra8_display_pal_lcd.c.