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
33
34#include <stddef.h>
35#include <stdint.h>
36
37#include "font_fixture.h"
38#include "ra8_board_ek_ra8d2.h"
39#include "ra8_boot_entry.h"
40#include "ra8_cgc.h"
41#include "ra8_err.h"
42#include "ra8_isr.h"
43#include "ra8_mstp.h"
44#include "ra8_time.h"
45#include "reflow.h"
46
48typedef enum : uint32_t {
49 k_lk_view_w = 280U,
50 k_lk_view_h = 360U,
52 k_lk_ink = 0xFF101010U,
53 k_lk_link_col = 0xFF2A52BEU,
54 k_lk_uart_baud = 115200U,
55 k_lk_fnv_offset = 2166136261U,
56 k_lk_fnv_prime = 16777619U,
62
65
67static const char k_lk_chapter[] =
68 "<html><body><h1>Chapter One</h1>"
69 "<p>Jump to the <a href=\"ch2.xhtml\">next chapter</a> or skip to the "
70 "<a href=\"#foot\">footnote</a> below for the citation.</p>"
71 "<p>Body paragraph with enough words to occupy a couple of lines so the "
72 "layout has real content to paginate around the links.</p>"
73 "<p id=\"foot\">Footnote: this is the cited reference text.</p></body></html>";
74
75static const uint8_t k_msg_boot[] = "ereader-link-hil: boot\r\n";
76static const uint8_t k_msg_fail[] = "ereader-link-hil: FAIL init\r\n";
77static const uint8_t k_msg_lerr[] = "ereader-link-hil: FAIL layout\r\n";
78static const uint8_t k_msg_pre[] = "ereader-link-hil: links=";
79static const uint8_t k_msg_cross[] = " cross=";
80static const uint8_t k_msg_frag[] = " frag=";
81static const uint8_t k_msg_apage[] = " apage=";
82static const uint8_t k_msg_geom[] = " geom=";
83static const uint8_t k_msg_eol[] = "\r\n";
84static const uint8_t k_msg_yes[] = "Y";
85static const uint8_t k_msg_no[] = "N";
86
88static void lk_print(const uint8_t* msg, uint32_t len)
89{
90 (void)ra8_board_uart_console_write(msg, (size_t)len);
91}
92
94static void lk_panic_halt(const uint8_t* msg, uint32_t len)
95{
96 lk_print(msg, len);
97 __asm__ volatile("bkpt #0");
98 while (1) {
99 __asm__ volatile("wfi");
100 }
101}
102
104static void lk_print_hex(uint32_t value)
105{
106 uint8_t buf[k_lk_hex_nibbles];
107 for (uint32_t i = 0U; i < (uint32_t)k_lk_hex_nibbles; i++) {
108 const uint32_t shift = ((uint32_t)k_lk_hex_nibbles - 1U - i) * (uint32_t)k_lk_nibble_bits;
109 const uint32_t nib = (value >> shift) & (uint32_t)k_lk_nibble_mask;
110 buf[i] = (uint8_t)((nib < (uint32_t)k_lk_dec_ten) ? ('0' + nib) : ('A' + (nib - k_lk_dec_ten)));
111 }
112 lk_print(buf, (uint32_t)k_lk_hex_nibbles);
113}
114
116static void lk_print_uint(uint32_t value)
117{
118 uint8_t buf[k_lk_dec_ten];
119 uint32_t n = 0U;
120 if (value == 0U) {
121 buf[n] = '0';
122 n++;
123 }
124 while ((value > 0U) && (n < (uint32_t)k_lk_dec_ten)) {
125 buf[n] = (uint8_t)('0' + (value % (uint32_t)k_lk_dec_ten));
126 n++;
127 value /= (uint32_t)k_lk_dec_ten;
128 }
129 for (uint32_t i = 0U; i < n; i++) {
130 lk_print(&buf[n - 1U - i], 1U);
131 }
132}
133
135static void lk_print_bool(bool yes)
136{
137 if (yes) {
138 lk_print(k_msg_yes, (uint32_t)sizeof(k_msg_yes) - 1U);
139 } else {
140 lk_print(k_msg_no, (uint32_t)sizeof(k_msg_no) - 1U);
141 }
142}
143
145static uint32_t lk_geom_hash(void)
146{
147 const uint8_t* p = (const uint8_t*)s_engine.link_rects;
148 const size_t n = (size_t)s_engine.link_rect_count * sizeof(s_engine.link_rects[0]);
149 uint32_t hsh = (uint32_t)k_lk_fnv_offset;
150 for (size_t i = 0U; i < n; i++) {
151 hsh = (hsh ^ (uint32_t)p[i]) * (uint32_t)k_lk_fnv_prime;
152 }
153 return hsh;
154}
155
164static void lk_probe_rect(uint32_t idx, bool* out_cross, bool* out_frag)
165{
166 const reflow_link_rect_t* rect = &s_engine.link_rects[idx];
167 const int32_t cx = rect->x + (rect->w / 2);
168 const int32_t cy = rect->y + (rect->h / 2);
169 uint32_t off = 0U;
170 uint32_t len = 0U;
171 if (reflow_hit_test_link(&s_engine, rect->page_index, cx, cy, &off, &len) != k_ra8_ok) {
172 return;
173 }
175 uint32_t pl = 0U;
176 uint32_t fo = 0U;
177 uint32_t fl = 0U;
178 if (reflow_href_split((const char*)&s_engine.text_pool[off], len, &kind, &pl, &fo, &fl) !=
179 k_ra8_ok) {
180 return;
181 }
182 if ((kind == k_reflow_href_chapter) || (kind == k_reflow_href_chapter_fragment)) {
183 *out_cross = true;
184 }
185 if (kind == k_reflow_href_fragment) {
186 *out_frag = true;
187 }
188}
189
191static void lk_setup_or_halt(void)
192{
193 uint32_t cpuclk0_hz = 0U;
194 if ((ra8_cgc_init() != k_ra8_ok) || (ra8_mstp_init() != k_ra8_ok)) {
195 lk_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
196 }
198 lk_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
199 }
200 if (ra8_time_init(cpuclk0_hz) != k_ra8_ok) {
201 lk_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
202 }
204 lk_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
205 }
206}
207
216void main(void)
217{
220 lk_print(k_msg_boot, (uint32_t)sizeof(k_msg_boot) - 1U);
221
222 if (reflow_init((uint16_t)k_lk_view_w,
223 (uint16_t)k_lk_view_h,
225 (size_t)k_ahem_ttf_len,
226 (uint16_t)k_lk_font_px,
227 (uint32_t)k_lk_ink,
228 (uint32_t)k_lk_link_col,
229 &s_engine) != k_ra8_ok) {
230 lk_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
231 }
232 uint32_t pages = 0U;
234 (const uint8_t*)k_lk_chapter,
235 (uint32_t)(sizeof(k_lk_chapter) - 1U),
236 &pages) != k_ra8_ok) {
237 lk_panic_halt(k_msg_lerr, (uint32_t)sizeof(k_msg_lerr) - 1U);
238 }
239
240 /* Synthesise a tap at the centre of every link rect; classify each. */
241 bool cross = false;
242 bool frag = false;
243 for (uint32_t i = 0U; i < s_engine.link_rect_count; ++i) {
244 lk_probe_rect(i, &cross, &frag);
245 }
246
247 /* Resolve the same-chapter "#foot" fragment to its page. */
248 uint32_t apage = 0U;
249 if (reflow_find_anchor(&s_engine, "foot", (uint32_t)(sizeof("foot") - 1U), &apage) != k_ra8_ok) {
250 apage = (uint32_t)k_lk_view_h; /* sentinel: not found */
251 }
252
253 lk_print(k_msg_pre, (uint32_t)sizeof(k_msg_pre) - 1U);
254 lk_print_uint(s_engine.link_target_count);
255 lk_print(k_msg_cross, (uint32_t)sizeof(k_msg_cross) - 1U);
256 lk_print_bool(cross);
257 lk_print(k_msg_frag, (uint32_t)sizeof(k_msg_frag) - 1U);
258 lk_print_bool(frag);
259 lk_print(k_msg_apage, (uint32_t)sizeof(k_msg_apage) - 1U);
260 lk_print_uint(apage);
261 lk_print(k_msg_geom, (uint32_t)sizeof(k_msg_geom) - 1U);
263 lk_print(k_msg_eol, (uint32_t)sizeof(k_msg_eol) - 1U);
264
265 while (1) {
266 __asm__ volatile("wfi");
267 }
268}
void main(void)
Secure fallback main entry point.
Definition main.c:37
static const uint8_t k_msg_pre[]
Definition main.c:151
static const uint8_t k_msg_boot[]
Definition main.c:140
static const uint8_t k_msg_fail[]
Definition main.c:63
static reflow_t s_engine
Reflow engine (glyph / page / token / text pools live inside).
Definition main.c:199
static const uint8_t k_msg_eol[]
Definition main.c:328
static const uint8_t k_msg_geom[]
Definition main.c:73
static const uint8_t k_msg_lerr[]
Definition main.c:71
static const uint8_t k_ahem_ttf[]
Ahem TTF bytes.
static const uint32_t k_ahem_ttf_len
Length of k_ahem_ttf in bytes.
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
Error Code Definitions for ra8-firmware.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
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
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
HTML / CSS reflow + paginate engine for the ra8d2 ereader.
ra8_err_t reflow_hit_test_link(const reflow_t *engine, uint32_t page_idx, int32_t x, int32_t y, uint32_t *out_href_off, uint32_t *out_href_len)
Hit-test a point on a page against the laid-out <a> link rectangles.
Definition reflow_link.c:36
ra8_err_t reflow_layout_chapter(reflow_t *engine, const uint8_t *xhtml_buf, size_t xhtml_len, uint32_t *out_total_pages)
Parse + lay out one chapter of XHTML.
ra8_err_t reflow_find_anchor(const reflow_t *engine, const char *id, uint32_t id_len, uint32_t *out_page)
Find the page of a same-chapter id anchor (for #fragment jumps).
Definition reflow_link.c:88
ra8_err_t reflow_href_split(const char *href, uint32_t len, reflow_href_kind_t *out_kind, uint32_t *out_path_len, uint32_t *out_frag_off, uint32_t *out_frag_len)
Split + classify an <a href> into a path part and a #fragment.
ra8_err_t reflow_init(uint16_t viewport_w, uint16_t viewport_h, const uint8_t *font_data, size_t font_len, uint16_t font_px, uint32_t body_color, uint32_t link_color, reflow_t *out_engine)
Initialise a reflow engine for a given viewport / font.
reflow_href_kind_t
Classification of an in-content <a href> target.
@ k_reflow_href_fragment
"#id" – same-chapter anchor.
@ k_reflow_href_chapter_fragment
"path#id" – chapter + anchor.
@ k_reflow_href_empty
Empty / whitespace-only href.
@ k_reflow_href_chapter
"path" – another chapter, no frag.
Reflow / pagination engine state.