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
38
39#include <stdint.h>
40
41#include "ra8_batt.h"
42#include "ra8_board_ek_ra8d2.h"
43#include "ra8_boot_entry.h"
44#include "ra8_cgc.h"
45#include "ra8_err.h"
46#include "ra8_i2c_bus_ops.h"
47#include "ra8_i3c.h"
48#include "ra8_io_i2c_bus.h"
50#include "ra8_isr.h"
51#include "ra8_mstp.h"
52#include "ra8_port_constants.h"
53#include "ra8_port_utils.h"
54#include "ra8_smbus.h"
55#include "ra8_time.h"
56
75
80
93
94static const uint8_t k_msg_boot[] = "battery-monitor: boot\r\n";
95static const uint8_t k_msg_fail[] = "battery-monitor: FAIL init\r\n";
96static const uint8_t k_msg_open[] = "battery: FAIL open\r\n";
97static const uint8_t k_msg_nak[] = "battery: NAK (no fuel gauge)\r\n";
98static const uint8_t k_msg_pre[] = "battery: soc=";
99static const uint8_t k_msg_pct[] = "% chg=";
100static const uint8_t k_msg_ok[] = " PASS\r\n";
101static const uint8_t k_msg_nag_low[] = "battery: NAG LOW soc=";
102static const uint8_t k_msg_nag_crit[] = "battery: NAG CRITICAL soc=";
103static const uint8_t k_msg_nag_tail[] = "%\r\n";
104
111volatile uint32_t g_bat_soc = 0U;
112
119volatile uint32_t g_bat_chg = 0U;
120
127volatile uint32_t g_bat_nag = 0U;
128
135volatile uint32_t g_bat_heartbeat = 0U;
136
138static void bm_print(const uint8_t* msg, uint32_t len)
139{
140 (void)ra8_board_uart_console_write(msg, (size_t)len);
141}
142
144static void bm_panic_halt(const uint8_t* msg, uint32_t len)
145{
146 bm_print(msg, len);
147 __asm__ volatile("bkpt #0");
148 while (1) {
149 __asm__ volatile("wfi");
150 }
151}
152
154static void bm_print_uint(uint32_t value)
155{
156 uint8_t buf[k_bm_dec_digits];
157 uint32_t n = 0U;
158 if (value == 0U) {
159 buf[n] = '0';
160 n++;
161 }
162 while ((value > 0U) && (n < (uint32_t)k_bm_dec_digits)) {
163 buf[n] = (uint8_t)('0' + (value % (uint32_t)k_bm_dec_ten));
164 n++;
165 value /= (uint32_t)k_bm_dec_ten;
166 }
167 for (uint32_t i = 0U; i < n; i++) {
168 bm_print(&buf[n - 1U - i], 1U);
169 }
170}
171
173static void bm_print_nag(ra8_batt_nag_t nag, uint8_t soc)
174{
175 if (nag == k_ra8_batt_nag_low) {
176 bm_print(k_msg_nag_low, (uint32_t)sizeof(k_msg_nag_low) - 1U);
177 } else if (nag == k_ra8_batt_nag_critical) {
178 bm_print(k_msg_nag_crit, (uint32_t)sizeof(k_msg_nag_crit) - 1U);
179 } else {
180 return;
181 }
182 bm_print_uint((uint32_t)soc);
183 bm_print(k_msg_nag_tail, (uint32_t)sizeof(k_msg_nag_tail) - 1U);
184}
185
187[[nodiscard]] static ra8_err_t bm_pins_init(void)
188{
191 }
193}
194
196static void bm_setup_or_halt(uint32_t* out_pclka_hz)
197{
198 uint32_t cpuclk0_hz = 0U;
199 if ((ra8_cgc_init() != k_ra8_ok) || (ra8_mstp_init() != k_ra8_ok)) {
200 bm_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
201 }
204 bm_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
205 }
206 if (ra8_time_init(cpuclk0_hz) != k_ra8_ok) {
207 bm_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
208 }
209 if (bm_pins_init() != k_ra8_ok) {
210 bm_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
211 }
213 bm_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
214 }
215}
216
231static void bm_read_or_halt(uint8_t* out_soc, uint8_t* out_chg)
232{
233 uint8_t soc = 0U;
234 if (ra8_smbus_read_byte_data((uint8_t)k_bm_fg_addr, (uint8_t)k_bm_reg_soc, &soc) != k_ra8_ok) {
235 bm_panic_halt(k_msg_nak, (uint32_t)sizeof(k_msg_nak) - 1U);
236 }
237 uint8_t crate_hi = 0U;
238 if (ra8_smbus_read_byte_data((uint8_t)k_bm_fg_addr, (uint8_t)k_bm_reg_crate, &crate_hi) !=
239 k_ra8_ok) {
240 bm_panic_halt(k_msg_nak, (uint32_t)sizeof(k_msg_nak) - 1U);
241 }
242 *out_soc = (soc > (uint8_t)k_bm_soc_max) ? (uint8_t)k_bm_soc_max : soc;
243 *out_chg = ((crate_hi & (uint8_t)k_bm_sign_mask) == 0U) ? 1U : 0U;
244}
245
246void main(void)
247{
248 uint32_t pclka_hz = 0U;
249 bm_setup_or_halt(&pclka_hz);
251 bm_print(k_msg_boot, (uint32_t)sizeof(k_msg_boot) - 1U);
252
253 /* App-owned bus bring-up: IIC_B in I2C-compat mode, bound through the
254 * ra8_io facade into the SMBus layer's injected seam. A future board
255 * revision that moves the bus onto a RIIC channel only swaps the bind. */
256 const ra8_i3c_cfg_t iic_cfg = {.mode = k_ra8_i3c_mode_i2c,
257 .bus_hz = (uint32_t)k_bm_bus_hz,
258 .pclka_hz = pclka_hz};
259 ra8_i2c_bus_ops_t bus_ops = {};
260 if (ra8_i3c_init((uint8_t)k_bm_iic_chan, &iic_cfg) != k_ra8_ok) {
261 bm_panic_halt(k_msg_open, (uint32_t)sizeof(k_msg_open) - 1U);
262 }
264 bm_panic_halt(k_msg_open, (uint32_t)sizeof(k_msg_open) - 1U);
265 }
266 if (ra8_io_i2c_bus_as_ops(&s_bm_bus, &bus_ops) != k_ra8_ok) {
267 bm_panic_halt(k_msg_open, (uint32_t)sizeof(k_msg_open) - 1U);
268 }
269
270 const ra8_smbus_cfg_t cfg = {.bus = bus_ops, .pec_enabled = false};
271 if (ra8_smbus_init(&cfg) != k_ra8_ok) {
272 bm_panic_halt(k_msg_open, (uint32_t)sizeof(k_msg_open) - 1U);
273 }
274
275 ra8_batt_monitor_t nag_mon;
276 if (ra8_batt_monitor_init(&nag_mon) != k_ra8_ok) {
277 bm_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
278 }
279
280 while (1) {
281 uint8_t soc = 0U;
282 uint8_t chg = 0U;
283 bm_read_or_halt(&soc, &chg);
284 g_bat_soc = (uint32_t)soc;
285 g_bat_chg = (uint32_t)chg;
286
287 bm_print(k_msg_pre, (uint32_t)sizeof(k_msg_pre) - 1U);
288 bm_print_uint((uint32_t)soc);
289 bm_print(k_msg_pct, (uint32_t)sizeof(k_msg_pct) - 1U);
290 bm_print((chg != 0U) ? (const uint8_t*)"Y" : (const uint8_t*)"N", 1U);
291 bm_print(k_msg_ok, (uint32_t)sizeof(k_msg_ok) - 1U);
292
293 /* Fold the reading into the nag policy: a one-shot LOW / CRITICAL line
294 * prints on the descent into each band (edge-triggered, see ra8_batt). */
296 if (ra8_batt_update(&nag_mon, soc, (chg != 0U), &nag) == k_ra8_ok) {
297 g_bat_nag = (uint32_t)nag;
298 bm_print_nag(nag, soc);
299 }
300
302 ra8_delay_ms((uint32_t)k_bm_period_ms);
303 }
304 bm_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
305}
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_ok[]
Definition main.c:153
static const uint8_t k_msg_boot[]
Definition main.c:140
static const uint8_t k_msg_open[]
Definition main.c:64
static const uint8_t k_msg_fail[]
Definition main.c:63
static void bm_print_nag(ra8_batt_nag_t nag, uint8_t soc)
Emit the low/critical battery nag line for nag at soc.
Definition main.c:173
static void bm_setup_or_halt(uint32_t *out_pclka_hz)
Bring up clocks/MSTP/time + the SCI8 console; halt on failure.
Definition main.c:196
volatile uint32_t g_bat_chg
1 when the fuel gauge reports a positive (charging) rate.
Definition main.c:119
volatile uint32_t g_bat_nag
Last raised nag level (ra8_batt_nag_t), 0 when none this poll.
Definition main.c:127
static void bm_read_or_halt(uint8_t *out_soc, uint8_t *out_chg)
Read SOC + the CRATE-sign from the fuel gauge; halt on a bus NAK.
Definition main.c:231
volatile uint32_t g_bat_heartbeat
Bumps once per poll – liveness for headless probes.
Definition main.c:135
static const uint8_t k_msg_nak[]
Definition main.c:97
static const uint8_t k_msg_nag_crit[]
Definition main.c:102
static ra8_io_i2c_bus_t s_bm_bus
Bound I2C bus handle the SMBus layer's injected seam points at.
Definition main.c:92
bm_consts_t
Console / bus / fuel-gauge knobs (no magic numbers).
Definition main.c:58
@ k_bm_reg_crate
CRATE register (signed charge rate).
Definition main.c:69
@ k_bm_bus_hz
IIC_B bit rate.
Definition main.c:62
@ k_bm_period_ms
Poll period.
Definition main.c:66
@ k_bm_dec_ten
Decimal base.
Definition main.c:72
@ k_bm_uart_baud
Console baud.
Definition main.c:60
@ k_bm_fg_addr
MAX17048 7-bit I2C address.
Definition main.c:67
@ k_bm_iic_chan
IIC_B channel (0).
Definition main.c:64
@ k_bm_dec_digits
Max decimal digits for a 0..100 value.
Definition main.c:73
@ k_bm_sign_mask
High-byte sign bit (1 = negative).
Definition main.c:70
@ k_bm_soc_max
SOC clamp for display.
Definition main.c:71
@ k_bm_reg_soc
SOC register (high byte = integer percent).
Definition main.c:68
static const uint8_t k_msg_nag_tail[]
Definition main.c:103
volatile uint32_t g_bat_soc
Last read state-of-charge percent (0..100).
Definition main.c:111
static const ra8_port_pin_t k_bm_pin_sda
MikroBUS SDA routed through the Pmod1 I2C side (SDA1).
Definition main.c:79
static ra8_err_t bm_pins_init(void)
Route the MikroBUS IIC SCL/SDA via PFS.
Definition main.c:187
static const uint8_t k_msg_nag_low[]
Definition main.c:101
static void bm_panic_halt(const uint8_t *msg, uint32_t len)
Print the fail banner and trap (ra8_emulator halts on the BKPT).
Definition main.c:144
static const uint8_t k_msg_pct[]
Definition main.c:99
static const ra8_port_pin_t k_bm_pin_scl
MikroBUS SCL routed through the Pmod1 I2C side (SCL1).
Definition main.c:77
static void bm_print_uint(uint32_t value)
Print a small unsigned integer (0..100) in decimal.
Definition main.c:154
static void bm_print(const uint8_t *msg, uint32_t len)
Emit a byte run on the SCI8 console.
Definition main.c:138
Bounded, allocation-free low-battery nag policy.
ra8_err_t ra8_batt_update(ra8_batt_monitor_t *mon, uint8_t soc_pct, bool charging, ra8_batt_nag_t *out_nag)
Fold one SOC reading into the monitor and report the nag to raise.
Definition ra8_batt.c:36
ra8_batt_nag_t
The low-battery warning a single ra8_batt_update step raises.
Definition ra8_batt.h:54
@ k_ra8_batt_nag_none
No new warning this step.
Definition ra8_batt.h:55
@ k_ra8_batt_nag_critical
SOC fell to the critical band (<=10%).
Definition ra8_batt.h:57
@ k_ra8_batt_nag_low
SOC fell to the low band (<=20%).
Definition ra8_batt.h:56
ra8_err_t ra8_batt_monitor_init(ra8_batt_monitor_t *mon)
Reset a nag monitor to the un-nagged, fully-armed state.
Definition ra8_batt.c:27
Board-support layer for the Renesas EK-RA8D2 v1 evaluation kit.
@ k_ra8_board_mikrobus_iic_b_channel
RA8 board mikrobus iic b channel.
@ k_ra8_board_mikrobus_i2c_scl
J22.5 SCL (SW4-5 OFF) -> P512 SCL1.
@ k_ra8_board_mikrobus_i2c_sda
J22.6 SDA (SW4-5 OFF) -> P511 SDA1.
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
@ k_ra8_clock_id_pclka
PCLKA.
Definition ra8_cgc.h:73
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_err_hw_init_failed
Hardware peripheral failed to initialise.
Definition ra8_err.h:290
@ 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
@ k_ra8_psel_iic
00111b: IIC / I3C controller-peripheral.
Injected I2C-bus seam consumed by Ring-3 I2C device drivers.
I3C Bus Interface driver – unified native-I3C + I2C-compat modes.
@ k_ra8_i3c_mode_i2c
Legacy I2C-compatibility controller.
Definition ra8_i3c.h:69
ra8_err_t ra8_i3c_init(uint8_t channel, const ra8_i3c_cfg_t *cfg)
Initialise an I3C channel in the configured mode.
Definition ra8_i3c.c:311
ra8_io I2C-bus facade – one controller-transfer vtable over thechip's two I2C implementations.
ra8_err_t ra8_io_i2c_bus_as_ops(const ra8_io_i2c_bus_t *bus, ra8_i2c_bus_ops_t *out)
Expose a bound bus through the Ring-3 seam ra8_i2c_bus_ops_t.
I3C I2C-compatibility backend binder for the ra8_io I2C-bus facade.
ra8_err_t ra8_io_i2c_bus_bind_i3c_compat(ra8_io_i2c_bus_t *bus, uint8_t channel)
Bind bus to I3C channel channel in I2C-compatibility mode.
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
Typed Port / Pin Constants for the RA8D2 IOPORT Module.
ra8_port_pin_t
Packed (port << 8) | pin pin identifier.
High-level GPIO helpers on top of the PORT + PFS register layer.
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
SMBus 3.2 protocol layer over an injected I2C bus seam.
ra8_err_t ra8_smbus_init(const ra8_smbus_cfg_t *cfg)
Initialise the SMBus layer over the injected bus seam.
Definition ra8_smbus.c:152
ra8_err_t ra8_smbus_read_byte_data(uint8_t target_7b, uint8_t cmd, uint8_t *out_data)
Read Byte Data: register-indexed byte read (SMBus 3.2 sec 6.5.5).
Definition ra8_smbus.c:259
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
void ra8_delay_ms(uint32_t ms)
Busy-wait for at least ms milliseconds.
Definition ra8_time.c:129
Caller-owned nag state carried across ra8_batt_update calls.
Definition ra8_batt.h:85
Caller-filled I2C controller-transfer seam (write / read / write-then-read).
Per-channel bring-up configuration for ra8_i3c_init.
Definition ra8_i3c.h:90
Caller-allocated I2C-bus handle binding a backend to its context.
Configuration descriptor for ra8_smbus_init.
Definition ra8_smbus.h:87