ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_sdfont.c
Go to the documentation of this file.
1
30
31#include "ra8_sdfont.h"
32
33#include <stdint.h>
34
35#include "ra8_attributes.h"
36#include "ra8_check.h"
37#include "ra8_err.h"
38#include "ra8_fs.h"
39#include "ra8_gpio_constants.h"
40#include "ra8_port_utils.h"
41#include "ra8_sci_spi.h"
42#include "ra8_sdmmc_spi.h"
43#include "ra8_spi.h"
44
51static const char* s_tag = "SDFONT";
52
59static const char* s_default_name = "FONT.OTF";
60
66typedef enum : uint32_t {
69
76typedef struct {
77 uint8_t channel;
78 uint32_t pclka_hz;
81
89
90/* ---------------------------------------------------------------------------
91 * ra8_sdmmc_spi transport shim (Dependency Inversion seam) over ra8_sci_spi.
92 * ---------------------------------------------------------------------------
93 */
94
111RA8_INTERNAL static ra8_err_t internal_set_clock(void* ctx, uint32_t hz)
112{
113 RA8_CHECK_NULL_PTR(ctx, s_tag, "ctx");
114 const sdfont_ctx_t* c = (const sdfont_ctx_t*)ctx;
115 return ra8_sci_spi_set_clock(c->channel, hz, c->pclka_hz);
116}
117
134RA8_INTERNAL static ra8_err_t internal_cs(void* ctx, bool asserted)
135{
136 RA8_CHECK_NULL_PTR(ctx, s_tag, "ctx");
137 const sdfont_ctx_t* c = (const sdfont_ctx_t*)ctx;
138 return ra8_gpio_write(c->cs, asserted ? k_ra8_level_low : k_ra8_level_high);
139}
140
159RA8_INTERNAL static ra8_err_t internal_xfer(void* ctx, const uint8_t* tx, uint8_t* rx, uint32_t len)
160{
161 RA8_CHECK_NULL_PTR(ctx, s_tag, "ctx");
162 const sdfont_ctx_t* c = (const sdfont_ctx_t*)ctx;
163 return ra8_sci_spi_xfer(c->channel, tx, rx, len);
164}
165
166/* ---------------------------------------------------------------------------
167 * Bring-up helpers
168 * ---------------------------------------------------------------------------
169 */
170
189{
190 RA8_CHECK_NULL_PTR(cfg, s_tag, "cfg");
191
192 s_ctx.channel = cfg->spi_channel;
193 s_ctx.pclka_hz = cfg->pclka_hz;
194 s_ctx.cs = cfg->cs;
195
197 if (err != k_ra8_ok) {
198 return err;
199 }
200 err = ra8_pfs_route_peripheral(cfg->cipo, k_ra8_psel_sci_async, "sdfont.cipo");
201 if (err != k_ra8_ok) {
202 return err;
203 }
204 err = ra8_pfs_route_peripheral(cfg->copi, k_ra8_psel_sci_async, "sdfont.copi");
205 if (err != k_ra8_ok) {
206 return err;
207 }
209 if (err != k_ra8_ok) {
210 return err;
211 }
212 const ra8_sci_spi_cfg_t spi_cfg = {
213 .baud_hz = (uint32_t)k_ra8_sdmmc_spi_clock_init_hz,
214 .pclk_hz = cfg->pclka_hz,
215 .mode = k_ra8_spi_mode_0,
216 .lsb_first = false,
217 };
218 return ra8_sci_spi_init(cfg->spi_channel, &spi_cfg);
219}
220
239{
240 RA8_CHECK_NULL_PTR(out_mount, s_tag, "out_mount");
241
242 const ra8_sdmmc_spi_transport_t transport = {
243 .set_clock = internal_set_clock,
244 .cs = internal_cs,
245 .xfer = internal_xfer,
246 .ctx = &s_ctx,
247 };
248 ra8_err_t err = ra8_sdmmc_spi_init(&transport);
249 if (err != k_ra8_ok) {
250 return err;
251 }
252 ra8_fs_backend_t backend = {};
253 err = ra8_sdmmc_spi_bind_fs_backend(&backend);
254 if (err != k_ra8_ok) {
255 return err;
256 }
257 return ra8_fs_mount(&backend, out_mount);
258}
259
285 ra8_fs_mount_t* mount,
286 const char* name,
287 ra8_fs_file_t** out_file,
288 ra8_sdfont_source_t* out_source)
289{
290 RA8_CHECK_NULL_PTR(cfg, s_tag, "cfg");
291 RA8_CHECK_NULL_PTR(mount, s_tag, "mount");
292 RA8_CHECK_NULL_PTR(out_file, s_tag, "out_file");
293
294 *out_source = k_ra8_sdfont_source_card;
295 ra8_err_t err = ra8_fs_open(mount, name, k_ra8_fs_mode_read, out_file);
296
297 /* Self-provision only when the file is genuinely absent and a blob is
298 * configured. Kept as separate single-condition guards (not one compound
299 * decision) so each branch is independently covered without MC/DC vectors. */
300 if (err != k_ra8_err_not_found) {
301 return err;
302 }
303 if (cfg->provision_blob == nullptr) {
304 return err; /* provisioning disabled -- propagate k_ra8_err_not_found */
305 }
306 if (cfg->provision_len == 0U) {
307 return err; /* nothing to write -- propagate k_ra8_err_not_found */
308 }
309 err = ra8_fs_write_file(mount, name, cfg->provision_blob, cfg->provision_len);
310 if (err != k_ra8_ok) {
311 return err;
312 }
314 return ra8_fs_open(mount, name, k_ra8_fs_mode_read, out_file);
315}
316
339internal_read_font(ra8_fs_file_t* file, uint8_t* buf, uint32_t cap, uint32_t* out_len)
340{
341 RA8_CHECK_NULL_PTR(file, s_tag, "file");
342 RA8_CHECK_NULL_PTR(buf, s_tag, "buf");
343 RA8_CHECK_NULL_PTR(out_len, s_tag, "out_len");
344
345 uint32_t got = 0U;
346 const ra8_err_t err = ra8_fs_read(file, buf, cap, &got);
347 (void)ra8_fs_close(file);
348 if (err != k_ra8_ok) {
349 return err;
350 }
351 if (got < (uint32_t)k_sdfont_min_bytes) {
352 return k_ra8_err_no_data;
353 }
354 *out_len = got;
355 return k_ra8_ok;
356}
357
379 const uint8_t* buf,
380 const uint32_t* out_len,
381 uint32_t cap)
382{
383 RA8_CHECK_NULL_PTR(cfg, s_tag, "cfg");
384 RA8_CHECK_NULL_PTR(buf, s_tag, "buf");
385 RA8_CHECK_NULL_PTR(out_len, s_tag, "out_len");
386 if (cap == 0U) {
388 }
389 return k_ra8_ok;
390}
391
393 uint8_t* buf,
394 uint32_t cap,
395 uint32_t* out_len,
396 ra8_sdfont_source_t* out_source)
397{
398 ra8_err_t err = internal_validate(cfg, buf, out_len, cap);
399 if (err != k_ra8_ok) {
400 return err;
401 }
402
403 err = internal_bringup_spi(cfg);
404 if (err != k_ra8_ok) {
405 return err;
406 }
407 ra8_fs_mount_t* mount = nullptr;
408 err = internal_mount(&mount);
409 if (err != k_ra8_ok) {
410 return err;
411 }
412
413 const char* name = (cfg->filename != nullptr) ? cfg->filename : s_default_name;
414 ra8_fs_file_t* file = nullptr;
416 err = internal_open_or_provision(cfg, mount, name, &file, &src);
417 if (err == k_ra8_ok) {
418 err = internal_read_font(file, buf, cap, out_len);
419 }
420 (void)ra8_fs_unmount(mount);
421 if (err != k_ra8_ok) {
422 return err;
423 }
424
425 if (out_source != nullptr) {
426 *out_source = src;
427 }
428 return k_ra8_ok;
429}
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
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_err_no_data
No application data available (e.g.
Definition ra8_err.h:202
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_not_found
Requested item not found (lookup / search missed).
Definition ra8_err.h:173
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Minimal FAT12/FAT16/FAT32 filesystem adapter (read + write).
ra8_err_t ra8_fs_mount(const ra8_fs_backend_t *backend, ra8_fs_mount_t **out_handle)
Mount a FAT volume from a block-device backend, auto-selecting the first partition.
ra8_err_t ra8_fs_read(ra8_fs_file_t *file, uint8_t *buf, uint32_t max_len, uint32_t *got_len)
Read up to max_len bytes; advance the cluster chain on cluster crossings.
ra8_err_t ra8_fs_open(ra8_fs_mount_t *handle, const char *path, ra8_fs_mode_t mode, ra8_fs_file_t **out_file)
Open or create a file by path, 8.3 or long.
ra8_err_t ra8_fs_unmount(ra8_fs_mount_t *handle)
Unmount a previously mounted volume and release its slot.
ra8_err_t ra8_fs_close(ra8_fs_file_t *file)
Close an open file, stamping its final modification time.
ra8_err_t ra8_fs_write_file(ra8_fs_mount_t *handle, const char *path, const uint8_t *data, uint32_t len)
Create a whole file in one call (provisioning helper).
@ k_ra8_fs_mode_read
Read-only, must exist.
PSEL codes for peripheral pin routing on the RA8D2.
@ k_ra8_psel_sci_async
00100b: SCI async serial (UART).
ra8_port_pin_t
Packed (port << 8) | pin pin identifier.
@ k_ra8_level_high
Drive or read 1.
@ k_ra8_level_low
Drive or read 0.
High-level GPIO helpers on top of the PORT + PFS register layer.
ra8_err_t ra8_gpio_output_init(ra8_port_pin_t pin, ra8_level_t init_level)
Configure a pin as a digital output and drive it to an initial level.
Definition gpio.c:88
ra8_err_t ra8_gpio_write(ra8_port_pin_t pin, ra8_level_t level)
Drive a previously-configured output to the given level.
Definition gpio.c:154
ra8_err_t ra8_pfs_route_peripheral(ra8_port_pin_t pin, ra8_psel_t psel, const char *owner)
Route a pin to a non-IRQ peripheral function via PFS.PSEL.
Definition gpio.c:238
SCI Simple-SPI controller-mode driver (polling, full-duplex).
ra8_err_t ra8_sci_spi_set_clock(uint8_t channel, uint32_t baud_hz, uint32_t pclk_hz)
Re-program the bit-rate without otherwise reconfiguring.
ra8_err_t ra8_sci_spi_xfer(uint8_t channel, const uint8_t *tx, uint8_t *rx, uint32_t len)
Full-duplex multi-byte transfer.
ra8_err_t ra8_sci_spi_init(uint8_t channel, const ra8_sci_spi_cfg_t *cfg)
Bring an SCI channel up as a Simple-SPI controller.
static ra8_err_t internal_validate(const ra8_sdfont_cfg_t *cfg, const uint8_t *buf, const uint32_t *out_len, uint32_t cap)
Validate the public load arguments (precondition gate).
Definition ra8_sdfont.c:378
static sdfont_ctx_t s_ctx
Single-shot transport context for the SD bus shim.
Definition ra8_sdfont.c:88
static ra8_err_t internal_mount(ra8_fs_mount_t **out_mount)
Run SD identification and mount the FAT volume.
Definition ra8_sdfont.c:238
static ra8_err_t internal_read_font(ra8_fs_file_t *file, uint8_t *buf, uint32_t cap, uint32_t *out_len)
Read an open font into the caller buffer and validate its length.
Definition ra8_sdfont.c:339
static ra8_err_t internal_cs(void *ctx, bool asserted)
Transport chip-select callback: drive CS low (asserted) or high.
Definition ra8_sdfont.c:134
static ra8_err_t internal_bringup_spi(const ra8_sdfont_cfg_t *cfg)
Route the Pmod SPI pins to SCI Simple-SPI and init the channel.
Definition ra8_sdfont.c:188
ra8_err_t ra8_sdfont_load(const ra8_sdfont_cfg_t *cfg, uint8_t *buf, uint32_t cap, uint32_t *out_len, ra8_sdfont_source_t *out_source)
Mount the Pmod SD card and load a font, provisioning it if absent.
Definition ra8_sdfont.c:392
static const char * s_default_name
Default 8.3 font filename used when the caller passes NULL.
Definition ra8_sdfont.c:59
static ra8_err_t internal_open_or_provision(const ra8_sdfont_cfg_t *cfg, ra8_fs_mount_t *mount, const char *name, ra8_fs_file_t **out_file, ra8_sdfont_source_t *out_source)
Open the font for reading, provisioning from the blob if absent.
Definition ra8_sdfont.c:284
static ra8_err_t internal_xfer(void *ctx, const uint8_t *tx, uint8_t *rx, uint32_t len)
Transport transfer callback: full-duplex byte exchange.
Definition ra8_sdfont.c:159
static ra8_err_t internal_set_clock(void *ctx, uint32_t hz)
Transport set-clock callback: retune the SCI baud divider.
Definition ra8_sdfont.c:111
sdfont_limits_t
Sanity floors for a loaded font.
Definition ra8_sdfont.c:66
@ k_sdfont_min_bytes
Smallest plausible TTF/OTF header – guards a truncated read.
Definition ra8_sdfont.c:67
Load a TTF/OTF font off a Pmod SD card, self-provisioning if absent.
ra8_sdfont_source_t
Provenance of the font bytes returned by ra8_sdfont_load.
Definition ra8_sdfont.h:70
@ k_ra8_sdfont_source_card
File already on the card; read as-is.
Definition ra8_sdfont.h:71
@ k_ra8_sdfont_source_provisioned
File was absent; written from the blob, then read back from the card.
Definition ra8_sdfont.h:72
SD card driver in SPI-mode (PMOD-attached cards).
@ k_ra8_sdmmc_spi_clock_init_hz
Mandatory init clock floor.
ra8_err_t ra8_sdmmc_spi_init(const ra8_sdmmc_spi_transport_t *transport)
Run the SD SPI-mode identification sequence on a card.
ra8_err_t ra8_sdmmc_spi_bind_fs_backend(ra8_fs_backend_t *out_backend)
Populate an ra8_fs_backend_t that mounts onto this SD driver.
SPI_B controller driver (RA8D2 Type-B SPI peripheral).
@ k_ra8_spi_mode_0
CPOL=0, CPHA=0.
Definition ra8_spi.h:62
Block-device interface that ra8_fs runs on top of.
Open-file state.
Cached parse of one mounted FAT volume.
Configuration descriptor for ra8_sci_spi_init.
Definition ra8_sci_spi.h:49
SD-card font-store bus description + provisioning policy.
Definition ra8_sdfont.h:92
ra8_port_pin_t copi
Controller-Out / Peripheral-In pin.
Definition ra8_sdfont.h:96
uint32_t provision_len
Length of provision_blob in bytes.
Definition ra8_sdfont.h:102
ra8_port_pin_t sck
SPI clock pin.
Definition ra8_sdfont.h:94
ra8_port_pin_t cipo
Controller-In / Peripheral-Out pin.
Definition ra8_sdfont.h:95
uint8_t spi_channel
SCI channel in Simple-SPI mode (Pmod2 = SCI0 = 0).
Definition ra8_sdfont.h:93
ra8_port_pin_t cs
Chip-select pin, driven as a GPIO output.
Definition ra8_sdfont.h:97
const char * filename
8.3 file to load; NULL selects "FONT.OTF".
Definition ra8_sdfont.h:99
const uint8_t * provision_blob
Fallback font written if the file is absent; NULL disables provisioning (read-only load).
Definition ra8_sdfont.h:100
uint32_t pclka_hz
PCLKA rate (Hz) feeding the SCI baud divider.
Definition ra8_sdfont.h:98
Driver-to-bus binding (Dependency Inversion seam).
Bus context handed to the ra8_sdmmc_spi transport callbacks.
Definition ra8_sdfont.c:76
ra8_port_pin_t cs
Chip-select GPIO pin.
Definition ra8_sdfont.c:79
uint32_t pclka_hz
PCLKA rate for the baud shim.
Definition ra8_sdfont.c:78
uint8_t channel
SCI Simple-SPI channel.
Definition ra8_sdfont.c:77