ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_board_ra8p1.c
Go to the documentation of this file.
1
25
26#include "ra8_board_ra8p1.h"
27
28#include <stddef.h>
29#include <stdint.h>
30
31#include "ra8_cgc.h"
32#include "ra8_elc_regs.h"
33#include "ra8_err.h"
34#include "ra8_gpio_constants.h"
35#include "ra8_icu.h"
36#include "ra8_icu_regs.h"
37#include "ra8_isr.h"
38#include "ra8_port_constants.h"
39#include "ra8_port_utils.h"
40#include "ra8_sci.h"
41
42/* =============================================================================
43 * Board identity
44 * =============================================================================
45 */
46
47const char* const k_ra8_board_name = "RA8P1 foundation board";
48const char* const k_ra8_board_doc_rev = "R01UH1064EJ (chip HUM)";
49const char* const k_ra8_board_mcu = "R7KA8P1KFLCAC";
50
52{
53 if (out == nullptr) {
55 }
58 out->mcu = k_ra8_board_mcu;
59 return k_ra8_ok;
60}
61
62/* =============================================================================
63 * 1. User LEDs (provisional; mirrored from EK-RA8D2)
64 * =============================================================================
65 */
66
83
85{
86 if (out_pin == nullptr) {
88 }
89 if ((uint8_t)led >= (uint8_t)k_ra8_board_led_count) {
91 }
92 *out_pin = s_led_pins[led];
93 return k_ra8_ok;
94}
95
97{
99 ra8_err_t err = ra8_board_led_pin(led, &pin);
100 if (err != k_ra8_ok) {
101 return err;
102 }
104}
105
107{
109 ra8_err_t err = ra8_board_led_pin(led, &pin);
110 if (err != k_ra8_ok) {
111 return err;
112 }
114}
115
117{
119 ra8_err_t err = ra8_board_led_pin(led, &pin);
120 if (err != k_ra8_ok) {
121 return err;
122 }
124}
125
127{
129 ra8_err_t err = ra8_board_led_pin(led, &pin);
130 if (err != k_ra8_ok) {
131 return err;
132 }
133 return ra8_gpio_toggle(pin);
134}
135
136/* =============================================================================
137 * 2. User switches (provisional; mirrored from EK-RA8D2)
138 * =============================================================================
139 */
140
154
156static const uint8_t s_sw_irq_nums[k_ra8_board_sw_count] = {
159};
160
162{
163 if (out_pin == nullptr) {
165 }
166 if ((uint8_t)sw >= (uint8_t)k_ra8_board_sw_count) {
168 }
169 *out_pin = s_sw_pins[sw];
170 return k_ra8_ok;
171}
172
174{
176 ra8_err_t err = ra8_board_sw_pin(sw, &pin);
177 if (err != k_ra8_ok) {
178 return err;
179 }
181}
182
184{
185 if (out_pressed == nullptr) {
187 }
189 ra8_err_t err = ra8_board_sw_pin(sw, &pin);
190 if (err != k_ra8_ok) {
191 return err;
192 }
194 err = ra8_gpio_read(pin, &lvl);
195 if (err != k_ra8_ok) {
196 /* ra8_gpio_read returns k_ra8_ok for valid port-0 SW pins off-target. */
197 return err; /* GCOVR_EXCL_LINE -- static board pins/channels cannot fail validation */
198 }
199 /* Buttons are active-low: low level == pressed. */
201 return k_ra8_ok;
202}
203
205{
206 if (cb == nullptr) {
208 }
209 if ((uint8_t)sw >= (uint8_t)k_ra8_board_sw_count) {
211 }
212 /* Step 1: configure the ICU IRQ pin for falling-edge detection so a button
213 * press (active-low) latches the IRQCR channel. The digital filter samples at
214 * PCLKB to debounce contact bounce (RA8P1 ICU is byte-identical to the RA8D2,
215 * HUM R01UH1064EJ Ch 14 "Interrupt Controller Unit"). */
216 const ra8_icu_irq_cfg_t cfg = {
218 .filter_div = k_ra8_icu_fclksel_pclkb,
219 .filter_en = true,
220 };
222 if (err != k_ra8_ok) {
223 /* ra8_icu_configure_irq_pin succeeds for IRQ12/13 (well within 32-channel limit). */
224 return err; /* GCOVR_EXCL_LINE -- static board pins/channels cannot fail validation */
225 }
226
227 /* Step 2: route the ELC event for the IRQ channel through an IELSR slot and
228 * enable the matching NVIC line. SW1 -> IRQ13, SW2 -> IRQ12 (provisional). */
229 const ra8_elc_event_t evt =
231 return ra8_isr_register(evt, (ra8_isr_handler_t)cb, ctx, k_ra8_isr_prio_default, nullptr);
232}
233
234/* =============================================================================
235 * 3. Debug UART console (provisional; mirrored from EK-RA8D2 J-Link OB VCOM)
236 * =============================================================================
237 */
238
251static bool s_uart_console_initialized = false;
252
270
272{
273 if (baud == 0U) {
275 }
276
277 /* SCI8's baud generator is fed by PCLKA. Read it from CGC at runtime so the
278 * BRR tracks whatever the application's CGC tree settled on instead of an
279 * assumed constant (the classic 2x-too-fast UART bug). */
280 uint32_t pclka_hz = 0U;
282 if (err != k_ra8_ok) {
283 /* ra8_cgc_get_clock_hz with a valid clock-id and non-null out always returns k_ra8_ok. */
284 return err; /* GCOVR_EXCL_LINE -- static board pins/channels cannot fail validation */
285 }
286 if (pclka_hz < (uint32_t)k_ra8_board_uart_console_min_pclka_hz) {
288 }
289
290 /* Route PD02 -> TXD8, PD03 -> RXD8 (PSEL = SCI async). */
293 "ra8_board.uart.console.txd");
294 if (err != k_ra8_ok) {
295 return err;
296 }
299 "ra8_board.uart.console.rxd");
300 if (err != k_ra8_ok) {
301 return err;
302 }
303
304 const ra8_sci_cfg_t cfg = {
305 .baud = baud,
306 .data_bits = k_ra8_sci_data_8,
307 .parity = k_ra8_sci_parity_none,
308 .stop_bits = k_ra8_sci_stop_1,
309 .pclk_hz = pclka_hz,
310 };
312 if (err != k_ra8_ok) {
313 return err;
314 }
316 return k_ra8_ok;
317}
318
319ra8_err_t ra8_board_uart_console_write(const uint8_t* data, size_t len)
320{
321 if (len == 0U) {
322 return k_ra8_ok;
323 }
324 if (data == nullptr) {
326 }
329 }
330 return ra8_sci_write_polling((uint8_t)k_ra8_board_uart_console_sci_channel, data, (uint32_t)len);
331}
332
333ra8_err_t ra8_board_uart_console_read(uint8_t* out, size_t cap, size_t* out_len)
334{
335 if (out_len == nullptr) {
337 }
338 *out_len = 0U;
339 if (cap == 0U) {
340 return k_ra8_ok;
341 }
342 if (out == nullptr) {
344 }
347 }
348
349 /* Polled non-blocking drain: pull bytes while data is available, stop the
350 * moment ra8_sci_getc_polling reports nothing. The cap bounds the loop
351 * (NASA Rule 2). */
352 for (size_t i = 0U; i < cap; ++i) {
353 uint8_t byte = 0U;
354 const ra8_err_t err =
356 if (err != k_ra8_ok) {
357 /* No byte available yet -- treat as a non-blocking stop. */
358 return k_ra8_ok;
359 }
360 out[i] = byte;
361 *out_len += 1U;
362 }
363 return k_ra8_ok;
364}
365
367{
370 }
371 /* Defer to ra8_sci_flush, which spins on CSR.TEND for the SCI8 channel and
372 * carries the register-access HUM citation. Lets a panic handler drain the
373 * failure log before WFI gates the SCI clock. */
375}
static const uint8_t s_sw_irq_nums[k_ra8_board_sw_count]
Lookup table from ra8_board_sw_id_t to ICU IRQ channel.
static const ra8_port_pin_t s_led_pins[k_ra8_board_led_count]
Lookup table from ra8_board_led_id_t to ra8_port_pin_t.
static const ra8_port_pin_t s_sw_pins[k_ra8_board_sw_count]
Lookup table from ra8_board_sw_id_t to ra8_port_pin_t.
ra8_board_uart_console_clock_t
Minimum SCI module operating clock accepted by the console init.
@ k_ra8_board_uart_console_min_pclka_hz
RA8 board UART console minimum pclka Hz.
static bool s_uart_console_initialized
Tracks whether ra8_board_uart_console_init has succeeded.
const char *const k_ra8_board_doc_rev
"R20UT5523EG0101 Rev 1.01".
const char *const k_ra8_board_name
Human-readable strings identifying this BSP target.
ra8_board_sw_id_t
Identifiers for the on-board user push-buttons.
@ k_ra8_board_sw_count
RA8 board sw count.
@ k_ra8_board_sw1
SW1, P009, IRQ13-DS (jumper E31).
@ k_ra8_board_sw2
SW2, P008, IRQ12-DS (jumper E32).
const char *const k_ra8_board_mcu
"R7KA8D2KFLCAC".
@ k_ra8_board_sw2_irq
SW2 -> IRQ12-DS.
@ k_ra8_board_sw1_irq
SW1 -> IRQ13-DS.
void(* ra8_board_sw_irq_cb_t)(void *ctx)
Switch IRQ callback signature.
ra8_board_sw_state_t
Logical "pressed" / "released" state.
@ k_ra8_board_sw_released
RA8 board sw released.
@ k_ra8_board_sw_pressed
RA8 board sw pressed.
ra8_board_led_id_t
Identifiers for the three user LEDs on EK-RA8D2 v1.
@ k_ra8_board_led2
LED2, GREEN, P303 (jumper E26).
@ k_ra8_board_led_count
RA8 board led count.
@ k_ra8_board_led1
LED1, BLUE, P600 (jumper E27).
@ k_ra8_board_led3
LED3, RED, PA07 (jumper E28).
ra8_board_eth_pin_t pin
Pin.
@ k_ra8_board_uart_console_pin_txd
PD02 TXD.
@ k_ra8_board_uart_console_pin_rxd
PD03 RXD.
@ k_ra8_board_uart_console_sci_channel
PD02/PD03 -> SCI8 (verified on real EK-RA8D2 v1 silicon).
ra8_err_t ra8_board_sw_pin(ra8_board_sw_id_t sw, ra8_port_pin_t *out_pin)
Translate a board switch id into its underlying ra8_port_pin_t.
ra8_err_t ra8_board_uart_console_read(uint8_t *out, size_t cap, size_t *out_len)
Polled non-blocking read from the J-Link OB VCOM console.
ra8_err_t ra8_board_led_toggle(ra8_board_led_id_t led)
Toggle led's output state.
ra8_err_t ra8_board_sw_attach_irq(ra8_board_sw_id_t sw, ra8_board_sw_irq_cb_t cb, void *ctx)
Wire sw to the ICU and register a falling-edge callback.
ra8_err_t ra8_board_sw_read(ra8_board_sw_id_t sw, ra8_board_sw_state_t *out_pressed)
Sample the current state of sw.
ra8_err_t ra8_board_sw_init(ra8_board_sw_id_t sw)
Configure a switch pin as an input with internal pull-up.
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.
ra8_err_t ra8_board_led_pin(ra8_board_led_id_t led, ra8_port_pin_t *out_pin)
Translate a board LED id into its underlying ra8_port_pin_t.
ra8_err_t ra8_board_led_init(ra8_board_led_id_t led)
Configure led as a digital output, initial level low (off).
ra8_err_t ra8_board_led_on(ra8_board_led_id_t led)
Drive led HIGH (light it).
ra8_err_t ra8_board_get_info(ra8_board_info_t *out)
Copy the three board-identity strings into out.
ra8_err_t ra8_board_uart_console_flush(void)
Block until every byte queued on the J-Link OB VCOM console has finished clocking out on the wire.
ra8_err_t ra8_board_led_off(ra8_board_led_id_t led)
Drive led LOW (extinguish it).
Board-support layer for the Renesas RA8P1 (R7KA8P1KFLCAC) target board.
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_pclka
PCLKA.
Definition ra8_cgc.h:73
Event Link Controller (ELC) register layout for the Renesas RA8D2.
ra8_elc_event_t
Partial list of ELC events (populate as drivers need them).
@ k_ra8_elc_event_icu_irq12
External pin interrupt 12 (HUM Ch 14 ELC event 0x00D).
@ k_ra8_elc_event_icu_irq13
External pin interrupt 13 (HUM Ch 14 ELC event 0x00E).
Error Code Definitions for ra8-firmware.
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_err_not_initialized
Module not initialized – _init() not yet called successfully.
Definition ra8_err.h:235
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
PSEL codes for peripheral pin routing on the RA8D2.
@ k_ra8_psel_sci_async
00100b: SCI async serial (UART).
Interrupt Control Unit driver (IRQ pins, NMI).
ra8_err_t ra8_icu_configure_irq_pin(uint8_t irq_num, const ra8_icu_irq_cfg_t *cfg)
Programme one IRQCRi register.
Definition ra8_icu.c:76
Interrupt Control Unit (ICU) register layout for the Renesas RA8D2.
@ k_ra8_icu_fclksel_pclkb
00: sample every PCLKB cycle.
@ k_ra8_icu_irqmd_falling
00: falling edge.
NVIC + ICU IELSR allocator.
void(* ra8_isr_handler_t)(void *ctx)
Driver-supplied callback invoked on interrupt entry.
Definition ra8_isr.h:128
@ k_ra8_isr_prio_default
Middle priority.
Definition ra8_isr.h:107
ra8_err_t ra8_isr_register(ra8_elc_event_t event, ra8_isr_handler_t handler, void *ctx, uint8_t priority, uint16_t *out_slot)
Allocate an IELSR slot for an ELC event + handler.
Definition ra8_isr.c:296
Typed Port / Pin Constants for the RA8D2 IOPORT Module.
ra8_port_pin_t
Packed (port << 8) | pin pin identifier.
@ k_ra8_pin_none
Sentinel: no pin selected.
@ k_ra8_port_3
RA8 port 3.
@ k_ra8_port_6
RA8 port 6.
@ k_ra8_port_0
RA8 port 0.
@ k_ra8_port_10
RA8 port 10.
#define RA8_PIN(port, pin)
Build a ra8_port_pin_t from explicit port / pin indices.
ra8_level_t
Digital output / input level.
@ k_ra8_level_high
Drive or read 1.
@ k_ra8_level_low
Drive or read 0.
@ k_ra8_pin_7
RA8 pin 7.
@ k_ra8_pin_9
RA8 pin 9.
@ k_ra8_pin_8
RA8 pin 8.
@ k_ra8_pin_0
RA8 pin 0.
@ k_ra8_pin_3
RA8 pin 3.
@ k_ra8_pull_up
Internal pull-up.
High-level GPIO helpers on top of the PORT + PFS register layer.
ra8_err_t ra8_gpio_read(ra8_port_pin_t pin, ra8_level_t *out_level)
Read a previously-configured input.
Definition gpio.c:210
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_toggle(ra8_port_pin_t pin)
Toggle a previously-configured output.
Definition gpio.c:182
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
Full-featured Serial Communications Interface driver.
ra8_err_t ra8_sci_write_polling(uint8_t channel, const uint8_t *data, uint32_t len)
Send len bytes by polling (convenience wrapper).
Definition ra8_sci.c:516
@ k_ra8_sci_stop_1
RA8 SCI stop 1.
Definition ra8_sci.h:81
@ k_ra8_sci_parity_none
RA8 SCI parity none.
Definition ra8_sci.h:71
ra8_err_t ra8_sci_init(uint8_t channel, const ra8_sci_cfg_t *cfg)
Initialise an SCI channel using the descriptor.
Definition ra8_sci.c:410
ra8_err_t ra8_sci_getc_polling(uint8_t channel, uint8_t *out_byte)
Poll-receive one byte (blocking, bounded spin).
Definition ra8_sci.c:496
@ k_ra8_sci_data_8
RA8 SCI data 8.
Definition ra8_sci.h:91
ra8_err_t ra8_sci_flush(uint8_t channel)
Block until the channel's transmit shift register is empty.
Definition ra8_sci.c:543
Snapshot of board identity strings.
const char * doc_rev
Same value as k_ra8_board_doc_rev.
const char * mcu
Same value as k_ra8_board_mcu.
const char * name
Same value as k_ra8_board_name.
One external-IRQ-pin configuration descriptor.
Definition ra8_icu.h:65
Configuration descriptor for ra8_sci_init.
Definition ra8_sci.h:103