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

Battery state-of-charge monitor over a MAX17048-class fuel gauge. More...

#include <stdint.h>
#include "ra8_batt.h"
#include "ra8_board_ek_ra8d2.h"
#include "ra8_boot_entry.h"
#include "ra8_cgc.h"
#include "ra8_err.h"
#include "ra8_i2c_bus_ops.h"
#include "ra8_i3c.h"
#include "ra8_io_i2c_bus.h"
#include "ra8_io_i2c_bus_i3c_compat.h"
#include "ra8_isr.h"
#include "ra8_mstp.h"
#include "ra8_port_constants.h"
#include "ra8_port_utils.h"
#include "ra8_smbus.h"
#include "ra8_time.h"
Include dependency graph for main.c:

Go to the source code of this file.

Enumerations

enum  bm_consts_t : uint32_t {
  k_bm_uart_baud = 115200U ,
  k_bm_bus_hz = 100000U ,
  k_bm_iic_chan = (uint32_t)k_ra8_board_mikrobus_iic_b_channel ,
  k_bm_period_ms = 1000U ,
  k_bm_fg_addr = 0x36U ,
  k_bm_reg_soc = 0x04U ,
  k_bm_reg_crate = 0x16U ,
  k_bm_sign_mask = 0x80U ,
  k_bm_soc_max = 100U ,
  k_bm_dec_ten = 10U ,
  k_bm_dec_digits = 3U
}
 Console / bus / fuel-gauge knobs (no magic numbers). More...

Functions

static void bm_print (const uint8_t *msg, uint32_t len)
 Emit a byte run on the SCI8 console.
static void bm_panic_halt (const uint8_t *msg, uint32_t len)
 Print the fail banner and trap (ra8_emulator halts on the BKPT).
static void bm_print_uint (uint32_t value)
 Print a small unsigned integer (0..100) in decimal.
static void bm_print_nag (ra8_batt_nag_t nag, uint8_t soc)
 Emit the low/critical battery nag line for nag at soc.
static ra8_err_t bm_pins_init (void)
 Route the MikroBUS IIC SCL/SDA via PFS.
static void bm_setup_or_halt (uint32_t *out_pclka_hz)
 Bring up clocks/MSTP/time + the SCI8 console; halt on failure.
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.
void main (void)
 The application entry point Reset_Handler hands control to.

Variables

static const ra8_port_pin_t k_bm_pin_scl = (ra8_port_pin_t)k_ra8_board_mikrobus_i2c_scl
 MikroBUS SCL routed through the Pmod1 I2C side (SCL1).
static const ra8_port_pin_t k_bm_pin_sda = (ra8_port_pin_t)k_ra8_board_mikrobus_i2c_sda
 MikroBUS SDA routed through the Pmod1 I2C side (SDA1).
static ra8_io_i2c_bus_t s_bm_bus
 Bound I2C bus handle the SMBus layer's injected seam points at.
static const uint8_t k_msg_boot [] = "battery-monitor: boot\r\n"
static const uint8_t k_msg_fail [] = "battery-monitor: FAIL init\r\n"
static const uint8_t k_msg_open [] = "battery: FAIL open\r\n"
static const uint8_t k_msg_nak [] = "battery: NAK (no fuel gauge)\r\n"
static const uint8_t k_msg_pre [] = "battery: soc="
static const uint8_t k_msg_pct [] = "% chg="
static const uint8_t k_msg_ok [] = " PASS\r\n"
static const uint8_t k_msg_nag_low [] = "battery: NAG LOW soc="
static const uint8_t k_msg_nag_crit [] = "battery: NAG CRITICAL soc="
static const uint8_t k_msg_nag_tail [] = "%\r\n"
volatile uint32_t g_bat_soc = 0U
 Last read state-of-charge percent (0..100).
volatile uint32_t g_bat_chg = 0U
 1 when the fuel gauge reports a positive (charging) rate.
volatile uint32_t g_bat_nag = 0U
 Last raised nag level (ra8_batt_nag_t), 0 when none this poll.
volatile uint32_t g_bat_heartbeat = 0U
 Bumps once per poll – liveness for headless probes.

Detailed Description

Battery state-of-charge monitor over a MAX17048-class fuel gauge.

Tag
[Ring 6 / APP] {World: S}

Reads battery state-of-charge + charge direction from a MAX17048-class I2C fuel gauge (7-bit address 0x36) on the MikroBUS / Pmod1 IIC_B bus and reports them on the SCI8 console once a second:

  • SOC (register 0x04): the high byte is the integer percent, so a single SMBus Read-Byte-Data of 0x04 yields the battery % directly.
  • CRATE (register 0x16): a signed charge rate. Its high byte's sign bit is 0 while charging (positive rate) and 1 while discharging (negative), so reading the high byte tells the charge direction.

Each second: battery: soc=NN% chg=Y/N PASS. Each reading is also folded into the ra8_batt nag policy, which prints a one-shot battery: NAG LOW (SOC <=20%) or battery: NAG CRITICAL (SOC <=10%) on the descent into each band – edge-triggered with hysteresis, so a steady low battery does not spam. g_bat_soc / g_bat_chg / g_bat_nag / g_bat_heartbeat mirror the result for headless probing.

Note
Headless-emulator status. tools/ra8_emulator models the MAX17048 fuel gauge (board_periph_i2c.c): its SOC + CRATE registers are driven by the fake battery state (settable via --battery <pct> / --charge), so this app reads a real percent over the modelled I2C bus and reaches its banner headlessly. On a stock EK-RA8D2 the fuel gauge is not fitted (a NAK banner prints), so the app lives in hw_pending/ until a real fuel-gauge board is on the MikroBUS. See README.md for the bench plan.
Since
0.1.0

Definition in file main.c.

Enumeration Type Documentation

◆ bm_consts_t

enum bm_consts_t : uint32_t

Console / bus / fuel-gauge knobs (no magic numbers).

Enumerator
k_bm_uart_baud 

Console baud.

k_bm_bus_hz 

IIC_B bit rate.

k_bm_iic_chan 

IIC_B channel (0).

k_bm_period_ms 

Poll period.

k_bm_fg_addr 

MAX17048 7-bit I2C address.

k_bm_reg_soc 

SOC register (high byte = integer percent).

k_bm_reg_crate 

CRATE register (signed charge rate).

k_bm_sign_mask 

High-byte sign bit (1 = negative).

k_bm_soc_max 

SOC clamp for display.

k_bm_dec_ten 

Decimal base.

k_bm_dec_digits 

Max decimal digits for a 0..100 value.

Definition at line 58 of file main.c.

Function Documentation

◆ bm_panic_halt()

void bm_panic_halt ( const uint8_t * msg,
uint32_t len )
static

Print the fail banner and trap (ra8_emulator halts on the BKPT).

Definition at line 144 of file main.c.

References bm_print().

Referenced by bm_read_or_halt(), bm_setup_or_halt(), and main().

◆ bm_pins_init()

ra8_err_t bm_pins_init ( void )
staticnodiscard

Route the MikroBUS IIC SCL/SDA via PFS.

Definition at line 187 of file main.c.

References k_bm_pin_scl, k_bm_pin_sda, k_ra8_err_hw_init_failed, k_ra8_ok, k_ra8_psel_iic, and ra8_pfs_route_peripheral().

Referenced by bm_setup_or_halt().

◆ bm_print()

void bm_print ( const uint8_t * msg,
uint32_t len )
static

Emit a byte run on the SCI8 console.

Definition at line 138 of file main.c.

References ra8_board_uart_console_write().

Referenced by bm_panic_halt(), bm_print_nag(), bm_print_uint(), and main().

◆ bm_print_nag()

void bm_print_nag ( ra8_batt_nag_t nag,
uint8_t soc )
static

Emit the low/critical battery nag line for nag at soc.

Definition at line 173 of file main.c.

References bm_print(), bm_print_uint(), k_msg_nag_crit, k_msg_nag_low, k_msg_nag_tail, k_ra8_batt_nag_critical, and k_ra8_batt_nag_low.

Referenced by main().

◆ bm_print_uint()

void bm_print_uint ( uint32_t value)
static

Print a small unsigned integer (0..100) in decimal.

Definition at line 154 of file main.c.

References bm_print(), k_bm_dec_digits, and k_bm_dec_ten.

Referenced by bm_print_nag(), and main().

◆ bm_read_or_halt()

void bm_read_or_halt ( uint8_t * out_soc,
uint8_t * out_chg )
static

Read SOC + the CRATE-sign from the fuel gauge; halt on a bus NAK.

Parameters
[out]out_soc1-byte SOC high byte = integer percent (clamped to 100).
[out]out_chg1 when the CRATE high byte's sign bit is clear (charging).
Note
Charge decode is a single condition: CRATE high-byte bit 7 clear means a positive (charging) rate. Not a compound boolean decision, so no MC/DC vector set applies; the path is exercised by the ra8_emulator gate, not a host test.
Precondition
ra8_smbus_init succeeded.
Postcondition
*out_soc / *out_chg reflect the fuel gauge; halts on NAK.
Since
0.1.0

Definition at line 231 of file main.c.

References bm_panic_halt(), k_bm_fg_addr, k_bm_reg_crate, k_bm_reg_soc, k_bm_sign_mask, k_bm_soc_max, k_msg_nak, k_ra8_ok, and ra8_smbus_read_byte_data().

Referenced by main().

◆ bm_setup_or_halt()

void bm_setup_or_halt ( uint32_t * out_pclka_hz)
static

Bring up clocks/MSTP/time + the SCI8 console; halt on failure.

Definition at line 196 of file main.c.

References bm_panic_halt(), bm_pins_init(), k_bm_uart_baud, k_msg_fail, k_ra8_clock_id_cpuclk0, k_ra8_clock_id_pclka, k_ra8_ok, ra8_board_uart_console_init(), ra8_cgc_get_clock_hz(), ra8_cgc_init(), ra8_mstp_init(), and ra8_time_init().

Referenced by main().

◆ main()

void main ( void )

The application entry point Reset_Handler hands control to.

Returns void, not int. This is a freestanding image: there is no hosted C environment, no process and nothing to report an exit status to. ISO C fixes main at int only for a hosted implementation; for a freestanding one (C23 5.1.2.1) the startup function's name and type are implementation-defined, and this is that definition. Reset_Handler discards no value because there is none to discard, and if main ever does return, startup halts the CPU rather than resuming anything.

The firmware lane is compiled -ffreestanding (see cmake/ra8_add_app.cmake) and the flag and this signature travel together: without it both GCC and clang reject a non-int main (-Wmain / -Wmain-return-type). Do not remove one without the other.

That coupling is why the declaration sits behind __STDC_HOSTED__ == 0, which -ffreestanding sets and a hosted build does not. The guard is not defensive dressing: this header is reachable from host builds (the unit tests compile ra8_core natively), and an unguarded void main(void); makes every hosted translation unit that includes it fail with conflicting types for 'main' against its own ISO int main. The declaration therefore exists exactly where its contract does.

Hosted first-party code – everything under tests/ and tools/ – uses the ISO int main(...) contract instead, because it genuinely does run under an OS that reads the exit status. scripts/checks/check_entry_points.py holds each domain to its own contract (#707).

Declared here, once, for the same reason SystemInit is: every vector_table.c used to restate it as a local extern int32_t main(void);, sixteen copies that no compiler ever compared against the definition – and roughly thirty of them had silently drifted out of agreement with the main they called.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has configured the clock tree and VTOR.
Postcondition
Control does not return; the image runs until reset or halt.
Any value the application wanted to report has been logged, not returned.
Note
Not thread-safe; single-threaded startup context only.
Warning
Only valid while the translation unit is compiled -ffreestanding. A hosted build rejects this signature.
See also
SystemInit()
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up CGC + BSP audio then plays blocks.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On clean entry the CPU stays in the playback loop forever.
On any HAL init failure the function halts in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up CGC + GPT triple, runs sweep.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On clean entry the CPU stays in the sweep loop forever.
On any HAL init failure the function halts in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up clocks + UART + RMII pins, then ThreadX.

Precondition
Reset_Handler has copied .data and zeroed .bss.
Postcondition
On clean entry the kernel runs the worker thread once.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up clocks + UART, then enters ThreadX.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On clean entry the kernel runs the worker thread forever.
On any HAL init failure the function halts in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up LED, console, SDHI pins, then ThreadX.

Precondition
Reset_Handler has copied .data + zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
CPUCLK0 is raised to the PLL1 target before the kernel starts.
On clean entry the SD card thread runs forever.
On any HAL init failure the function halts in __WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up CGC + USB-FS + UAC1, then enters the iso-IN feed loop forever.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On clean entry the CPU stays in the iso-IN feed loop forever.
On any HAL init failure the function halts in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
SystemInit set VTOR / FPU / priority grouping.

The application entry point Reset_Handler hands control to.

See file header.

Precondition
Boot init has completed.
The secure-boot library's BLXNS into NS image either failed or was skipped (the call site in ra8_trustzone_init is a no-op on host builds).
Postcondition
Diagnostic counter latched, CPU parked in a halt loop.
Function never returns.
Note
Single-threaded entry.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
On success g_eoh_chapters / g_eoh_crc hold the parsed results, the banner is emitted, and g_eoh_heartbeat advances once per frame.
On any failure g_eoh_err is non-zero and the CPU parks (no heartbeat).
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The chapters/ch0-CRC banner is emitted; the CPU then loops in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
On success the g_etoc_* result globals hold the parsed TOC values, the banner is emitted, and g_etoc_heartbeat advances once per frame.
On any failure g_etoc_err is non-zero and the CPU parks (no heartbeat).
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss; SystemInit set VTOR/FPU.
Postcondition
The shelf scans on the panel; taps open books, browse, and read.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The slab/arena/tile/vmem banner is emitted; the CPU then loops in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
On success the cache globals are latched and g_pc_heartbeat advances.
On any failure g_pc_err is non-zero and the CPU parks (no heartbeat).
Since
0.1.0

The application entry point Reset_Handler hands control to.

Profiles power modes once a second.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On clean entry the CPU stays in the profile + blink loop.
On any HAL hard error LED2 latches ON.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler has copied .data and zeroed .bss.
The shared board boot files installed the vector table.
Postcondition
The demo has run once and its verdict banner is streaming steadily.
The CPU idles re-emitting the banner (or halts after a fatal init error).
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up the clocks, console, SPI, and SD card, then runs the shared ra8_io VFS round-trip over the SD-over-SPI block device. On success it prints the exact PASS banner the HIL runner and ra8_emulator smoke gate scrape for; on any failure it prints FAIL and parks the core.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On a clean run the CPU loops forever after the PASS banner.
On any failure the function prints FAIL and halts in WFI.
Note
Not thread-safe; this is the single-threaded app entry.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Initialises logging and the console, brings up the OSPI NOR volume, runs the erase-before-write round-trip, and prints a single PASS/FAIL verdict line over SCI8 before parking in an infinite loop.

Precondition
SystemInit configured VTOR / FPU / priority grouping.
The OSPI NOR array is present (modelled in ra8_emulator, real on silicon).
Postcondition
Exactly one PASS or FAIL verdict line has been queued on SCI8.
Control parks in an infinite loop; the function never returns.
Note
Single-threaded; runs to the park loop on the main stack.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The page-count + render-hash banner is emitted; the CPU loops in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The cal=OK / cal=SKIP result and the finger-free touchcal: ready sentinel are emitted; the CPU then loops in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The open=OK touch banner is emitted; the CPU then loops in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Both USB controllers' clocks and pins come up before the kernel so the workers only deal with stack bring-up.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR, FPU, priority grouping.
Postcondition
On clean entry the CPU stays in tx_kernel_enter forever.
On any HAL init failure the function halts in WFI.
Note
Single entry point; not re-entrant.
Since
0.1.0

Definition at line 246 of file main.c.

References bm_panic_halt(), bm_print(), bm_print_nag(), bm_print_uint(), bm_read_or_halt(), bm_setup_or_halt(), g_bat_chg, g_bat_heartbeat, g_bat_nag, g_bat_soc, k_bm_bus_hz, k_bm_iic_chan, k_bm_period_ms, k_msg_boot, k_msg_fail, k_msg_ok, k_msg_open, k_msg_pct, k_msg_pre, k_ra8_batt_nag_none, k_ra8_i3c_mode_i2c, k_ra8_ok, ra8_batt_monitor_init(), ra8_batt_update(), ra8_delay_ms(), ra8_i3c_init(), ra8_io_i2c_bus_as_ops(), ra8_io_i2c_bus_bind_i3c_compat(), ra8_isr_globals_enable(), ra8_smbus_init(), and s_bm_bus.

Variable Documentation

◆ g_bat_chg

volatile uint32_t g_bat_chg = 0U

1 when the fuel gauge reports a positive (charging) rate.

Note
Read externally only.
Since
0.1.0

Definition at line 119 of file main.c.

Referenced by main().

◆ g_bat_heartbeat

volatile uint32_t g_bat_heartbeat = 0U

Bumps once per poll – liveness for headless probes.

Note
Read externally only.
Since
0.1.0

Definition at line 135 of file main.c.

Referenced by main().

◆ g_bat_nag

volatile uint32_t g_bat_nag = 0U

Last raised nag level (ra8_batt_nag_t), 0 when none this poll.

Note
Read externally only.
Since
0.1.0

Definition at line 127 of file main.c.

Referenced by main().

◆ g_bat_soc

volatile uint32_t g_bat_soc = 0U

Last read state-of-charge percent (0..100).

Note
Read externally only (HIL / board emulator).
Since
0.1.0

Definition at line 111 of file main.c.

Referenced by main().

◆ k_bm_pin_scl

MikroBUS SCL routed through the Pmod1 I2C side (SCL1).

Definition at line 77 of file main.c.

Referenced by bm_pins_init().

◆ k_bm_pin_sda

MikroBUS SDA routed through the Pmod1 I2C side (SDA1).

Definition at line 79 of file main.c.

Referenced by bm_pins_init().

◆ k_msg_boot

const uint8_t k_msg_boot[] = "battery-monitor: boot\r\n"
static

Definition at line 94 of file main.c.

◆ k_msg_fail

const uint8_t k_msg_fail[] = "battery-monitor: FAIL init\r\n"
static

Definition at line 95 of file main.c.

◆ k_msg_nag_crit

const uint8_t k_msg_nag_crit[] = "battery: NAG CRITICAL soc="
static

Definition at line 102 of file main.c.

Referenced by bm_print_nag().

◆ k_msg_nag_low

const uint8_t k_msg_nag_low[] = "battery: NAG LOW soc="
static

Definition at line 101 of file main.c.

Referenced by bm_print_nag().

◆ k_msg_nag_tail

const uint8_t k_msg_nag_tail[] = "%\r\n"
static

Definition at line 103 of file main.c.

Referenced by bm_print_nag().

◆ k_msg_nak

const uint8_t k_msg_nak[] = "battery: NAK (no fuel gauge)\r\n"
static

Definition at line 97 of file main.c.

Referenced by bm_read_or_halt(), and sd_read_whoami_or_halt().

◆ k_msg_ok

const uint8_t k_msg_ok[] = " PASS\r\n"
static

Definition at line 100 of file main.c.

◆ k_msg_open

const uint8_t k_msg_open[] = "battery: FAIL open\r\n"
static

Definition at line 96 of file main.c.

◆ k_msg_pct

const uint8_t k_msg_pct[] = "% chg="
static

Definition at line 99 of file main.c.

Referenced by main().

◆ k_msg_pre

const uint8_t k_msg_pre[] = "battery: soc="
static

Definition at line 98 of file main.c.

◆ s_bm_bus

ra8_io_i2c_bus_t s_bm_bus
static

Bound I2C bus handle the SMBus layer's injected seam points at.

File-scope because the seam's ctx references it for the whole run.

Note
Written once during bring-up, then read-only.
Warning
Do not rebind while the SMBus layer is initialised.
Since
0.1.0

Definition at line 92 of file main.c.

Referenced by main().