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
43
44#include <stdint.h>
45
46#include "ra8_board_ek_ra8d2.h"
47#include "ra8_boot_entry.h"
48#include "ra8_cgc.h"
49#include "ra8_err.h"
50#include "ra8_i3c.h"
51#include "ra8_isr.h"
52#include "ra8_lsm6dso.h"
53#include "ra8_mstp.h"
54#include "ra8_port_utils.h"
55#include "ra8_time.h"
56
57/* =============================================================================
58 * App-wide tunables
59 * =============================================================================
60 */
61
71
75
76/* =============================================================================
77 * Tiny printf-equivalents for HIL log scraping
78 * =============================================================================
79 */
80
82static const uint8_t k_imu_demo_banner_ok[] = "lsm6dso: who_am_i=0x6c\r\n";
83static const uint8_t k_imu_demo_banner_bad[] = "lsm6dso: who_am_i mismatch\r\n";
84static const uint8_t k_imu_demo_banner_nak[] = "lsm6dso: I2C NAK\r\n";
85static const uint8_t k_imu_demo_banner_err[] = "lsm6dso: read error\r\n";
86
95static void imu_demo_panic_halt(void)
96{
97 while (1) {
98 __asm__ volatile("wfi");
99 }
100}
101
102/* =============================================================================
103 * Tiny integer -> decimal serialiser for the periodic log line
104 * =============================================================================
105 */
106
109typedef enum : uint32_t {
112
133static uint32_t imu_demo_i32_to_dec(int32_t value, uint8_t* out)
134{
135 uint8_t tmp[k_imu_demo_int_str_cap] = {};
136 uint32_t n = 0U;
137 bool neg = false;
138 /* Two's complement edge case: INT16_MIN. We work in int32_t so we
139 * have headroom to negate. */
140 int32_t v = value;
141 if (v < 0) {
142 neg = true;
143 v = -v;
144 }
145 if (v == 0) {
146 tmp[n++] = (uint8_t)'0';
147 } else {
148 while (v > 0 && n < (uint32_t)k_imu_demo_int_str_cap) {
149 tmp[n++] = (uint8_t)('0' + (uint8_t)((uint32_t)v % k_imu_decimal_base));
150 v = (int32_t)((uint32_t)v / k_imu_decimal_base);
151 }
152 }
153 if (neg && n < (uint32_t)k_imu_demo_int_str_cap) {
154 tmp[n++] = (uint8_t)'-';
155 }
156 /* Reverse into the caller's buffer. */
157 for (uint32_t i = 0U; i < n; ++i) {
158 out[i] = tmp[n - 1U - i];
159 }
160 if (n < (uint32_t)k_imu_demo_int_str_cap) {
161 out[n] = 0U;
162 }
163 return n;
164}
165
166/* =============================================================================
167 * IIC_B bus adapter for the ra8_lsm6dso transport interface
168 * =============================================================================
169 */
170
172typedef struct {
173 uint8_t channel;
174 uint8_t addr7;
176
192static ra8_err_t imu_demo_iic_read(void* ctx, uint8_t reg, uint8_t* buf, uint32_t len)
193{
194 const imu_demo_iic_ctx_t* c = (const imu_demo_iic_ctx_t*)ctx;
195 return ra8_i3c_transfer(c->channel, c->addr7, &reg, 1U, buf, len);
196}
197
214typedef enum : uint32_t {
217
218static ra8_err_t imu_demo_iic_write(void* ctx, uint8_t reg, const uint8_t* buf, uint32_t len)
219{
220 if (len > (uint32_t)k_imu_demo_iic_tx_cap - 1U) {
222 }
223 uint8_t scratch[k_imu_demo_iic_tx_cap] = {};
224 scratch[0] = reg;
225 for (uint32_t i = 0U; i < len; ++i) {
226 scratch[i + 1U] = buf[i];
227 }
228 const imu_demo_iic_ctx_t* c = (const imu_demo_iic_ctx_t*)ctx;
229 return ra8_i3c_write(c->channel, c->addr7, scratch, len + 1U, false);
230}
231
232/* =============================================================================
233 * Init helpers
234 * =============================================================================
235 */
236
245static void imu_demo_clocks_or_halt(uint32_t* out_pclka_hz)
246{
247 uint32_t cpuclk0_hz = 0U;
248 if (ra8_cgc_init() != k_ra8_ok) {
250 }
253 }
254 if (ra8_cgc_get_clock_hz(k_ra8_clock_id_pclka, out_pclka_hz) != k_ra8_ok) {
256 }
257 if (ra8_mstp_init() != k_ra8_ok) {
259 }
260 if (ra8_time_init(cpuclk0_hz) != k_ra8_ok) {
262 }
263}
264
273static void imu_demo_pfs_or_halt(void)
274{
277 }
280 }
281}
282
288static void imu_demo_setup_or_halt(void)
289{
290 uint32_t pclka_hz = 0U;
291 imu_demo_clocks_or_halt(&pclka_hz);
293
296 }
297 const ra8_i3c_cfg_t iic_cfg = {
298 .mode = k_ra8_i3c_mode_i2c,
299 .bus_hz = k_imu_demo_bus_hz,
300 .pclka_hz = pclka_hz,
301 };
302 if (ra8_i3c_init((uint8_t)k_imu_demo_iic_channel, &iic_cfg) != k_ra8_ok) {
304 }
307 }
310 }
311}
312
321static void imu_demo_tx(const uint8_t* bytes, uint32_t len)
322{
323 (void)ra8_board_uart_console_write(bytes, (size_t)len);
324}
325
335static void imu_demo_emit_kv(const uint8_t* label, uint32_t label_len, int32_t value)
336{
337 uint8_t buf[k_imu_demo_int_str_cap] = {};
338 imu_demo_tx(label, label_len);
339 const uint32_t n = imu_demo_i32_to_dec(value, buf);
340 imu_demo_tx(buf, n);
341}
342
343/* =============================================================================
344 * Main-loop helpers (kept out of main() to satisfy NASA P10 Rule 4).
345 * =============================================================================
346 */
347
369{
370 uint8_t who = 0U;
371 const ra8_err_t r = ra8_lsm6dso_who_am_i(dev, &who);
372 if (r != k_ra8_ok) {
376 }
377 if (who != (uint8_t)k_lsm6dso_who_am_i_value) {
381 }
382 imu_demo_tx(k_imu_demo_banner_ok, (uint32_t)(sizeof(k_imu_demo_banner_ok) - 1U));
383}
384
418
440{
441 static const uint8_t k_label_prefix[] = "lsm6dso: ax=";
442 static const uint8_t k_label_ay[] = " ay=";
443 static const uint8_t k_label_az[] = " az=";
444 static const uint8_t k_label_gx[] = " gx=";
445 static const uint8_t k_label_gy[] = " gy=";
446 static const uint8_t k_label_gz[] = " gz=";
447 static const uint8_t k_label_temp[] = " temp=";
448 static const uint8_t k_label_newline[] = "\r\n";
449
450 ra8_lsm6dso_xyz_t a = {};
451 ra8_lsm6dso_xyz_t g = {};
452 int32_t tcenti = 0;
453 const ra8_err_t ra = ra8_lsm6dso_read_accel(dev, &a);
454 const ra8_err_t rg = ra8_lsm6dso_read_gyro(dev, &g);
455 const ra8_err_t rt = ra8_lsm6dso_read_temp(dev, &tcenti);
456 if (ra != k_ra8_ok || rg != k_ra8_ok || rt != k_ra8_ok) {
459 return;
460 }
461 imu_demo_emit_kv(k_label_prefix, (uint32_t)(sizeof(k_label_prefix) - 1U), a.x);
462 imu_demo_emit_kv(k_label_ay, (uint32_t)(sizeof(k_label_ay) - 1U), a.y);
463 imu_demo_emit_kv(k_label_az, (uint32_t)(sizeof(k_label_az) - 1U), a.z);
464 imu_demo_emit_kv(k_label_gx, (uint32_t)(sizeof(k_label_gx) - 1U), g.x);
465 imu_demo_emit_kv(k_label_gy, (uint32_t)(sizeof(k_label_gy) - 1U), g.y);
466 imu_demo_emit_kv(k_label_gz, (uint32_t)(sizeof(k_label_gz) - 1U), g.z);
467 imu_demo_emit_kv(k_label_temp, (uint32_t)(sizeof(k_label_temp) - 1U), tcenti);
468 imu_demo_tx(k_label_newline, (uint32_t)(sizeof(k_label_newline) - 1U));
469}
470
471/* =============================================================================
472 * Main
473 * =============================================================================
474 */
475
487void main(void)
488{
491
492 imu_demo_iic_ctx_t ctx = {
493 .channel = (uint8_t)k_imu_demo_iic_channel,
494 .addr7 = (uint8_t)k_lsm6dso_i2c_addr_sa0_high,
495 };
496 const ra8_lsm6dso_bus_t bus = {
497 .read_regs = imu_demo_iic_read,
498 .write_regs = imu_demo_iic_write,
499 .ctx = &ctx,
500 };
501 ra8_lsm6dso_t dev = {};
502 if (ra8_lsm6dso_init(&dev, &bus) != k_ra8_ok) {
506 }
507
509 /* Configure: +-2 g, +-250 dps, 104 Hz. */
510 imu_demo_configure(&dev);
511
512 while (1) {
516 }
517
519}
void main(void)
Secure fallback main entry point.
Definition main.c:37
static void imu_demo_clocks_or_halt(uint32_t *out_pclka_hz)
Bring CGC + SysTick + MSTP up; return PCLKA via out_pclka_hz.
Definition main.c:245
static void imu_demo_sample_and_emit(ra8_lsm6dso_t *dev)
Read one cycle of accel + gyro + temperature and emit the log line.
Definition main.c:439
static const uint8_t k_imu_demo_banner_nak[]
Definition main.c:84
static void imu_demo_pfs_or_halt(void)
Route IIC channel-0 SCL/SDA via PFS.
Definition main.c:273
static void imu_demo_setup_or_halt(void)
Bring CGC + SysTick + console + IIC_B up.
Definition main.c:288
static void imu_demo_configure(ra8_lsm6dso_t *dev)
Apply the demo's fixed sensor configuration (+-2 g, +-250 dps, 104 Hz).
Definition main.c:403
static void imu_demo_emit_kv(const uint8_t *label, uint32_t label_len, int32_t value)
Emit a labelled signed integer: "<label>=<n>".
Definition main.c:335
static void imu_demo_tx(const uint8_t *bytes, uint32_t len)
Emit one line of bytes via the BSP UART console (SCI8).
Definition main.c:321
static void imu_demo_panic_halt(void)
Park forever after a fatal error.
Definition main.c:95
static const ra8_port_pin_t k_imu_demo_pin_scl
MikroBUS SDA/SCL routed through Arduino D14/D15 to SDA1/SCL1.
Definition main.c:73
static void imu_demo_check_who_am_i(ra8_lsm6dso_t *dev)
Verify the LSM6DSO is alive and is the expected silicon.
Definition main.c:368
static const ra8_port_pin_t k_imu_demo_pin_sda
Definition main.c:74
static ra8_err_t imu_demo_iic_read(void *ctx, uint8_t reg, uint8_t *buf, uint32_t len)
Transport adapter: read N bytes starting at register reg.
Definition main.c:192
static const uint8_t k_imu_demo_banner_err[]
Definition main.c:85
imu_demo_iic_cap_t
Transport adapter: write N bytes starting at register reg.
Definition main.c:214
@ k_imu_demo_iic_tx_cap
Imu demo iic TX cap.
Definition main.c:215
static const uint8_t k_imu_demo_banner_ok[]
Banner line scraped by hil.conf.
Definition main.c:82
static const uint8_t k_imu_demo_banner_bad[]
Definition main.c:83
imu_demo_str_cap_t
Result buffer for one decimal int16_t (max "-32768" = 6 bytes plus the trailing NUL).
Definition main.c:109
@ k_imu_demo_int_str_cap
Imu demo int str cap.
Definition main.c:110
static ra8_err_t imu_demo_iic_write(void *ctx, uint8_t reg, const uint8_t *buf, uint32_t len)
Definition main.c:218
static uint32_t imu_demo_i32_to_dec(int32_t value, uint8_t *out)
Convert a signed 16-bit int into a decimal ASCII string.
Definition main.c:133
imu_demo_const_t
App-wide tunables.
Definition main.c:63
@ k_imu_demo_baud
Imu demo baud.
Definition main.c:65
@ k_imu_demo_bus_hz
Imu demo bus Hz.
Definition main.c:67
@ k_imu_demo_period_ms
Imu demo period ms.
Definition main.c:66
@ k_imu_demo_iic_channel
Imu demo iic channel.
Definition main.c:68
@ k_imu_decimal_base
Radix for integer-to-ASCII.
Definition main.c:64
Board-support layer for the Renesas EK-RA8D2 v1 evaluation kit.
@ k_ra8_board_mikrobus_iic_b_channel
RA8 board mikrobus iic b channel.
ra8_err_t ra8_board_led_toggle(ra8_board_led_id_t led)
Toggle led's output state.
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).
@ 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.
@ k_ra8_board_led2
LED2, GREEN, P303 (jumper E26).
@ k_ra8_board_led1
LED1, BLUE, P600 (jumper E27).
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_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
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.
I3C Bus Interface driver – unified native-I3C + I2C-compat modes.
ra8_err_t ra8_i3c_transfer(uint8_t channel, uint8_t addr, const uint8_t *wr, uint32_t wr_len, uint8_t *rd, uint32_t rd_len)
Write-then-read with repeated-START framing (I2C mode).
Definition ra8_i3c.c:702
@ k_ra8_i3c_mode_i2c
Legacy I2C-compatibility controller.
Definition ra8_i3c.h:69
ra8_err_t ra8_i3c_write(uint8_t channel, uint8_t addr, const uint8_t *data, uint32_t len, bool restart)
Write len bytes to addr.
Definition ra8_i3c.c:621
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
NVIC + ICU IELSR allocator.
void ra8_isr_globals_enable(void)
Globally enable maskable interrupts (PRIMASK = 0).
Definition ra8_isr.c:439
ST LSM6DSO 6-DoF IMU driver (accel + gyro + temperature).
ra8_err_t ra8_lsm6dso_set_odr(ra8_lsm6dso_t *dev, ra8_lsm6dso_odr_t odr)
Program the Output Data Rate for both the accelerometer and the gyroscope.
ra8_err_t ra8_lsm6dso_read_temp(ra8_lsm6dso_t *dev, int32_t *out_centi_c)
Read the on-die temperature in centi-degrees Celsius.
ra8_err_t ra8_lsm6dso_read_gyro(ra8_lsm6dso_t *dev, ra8_lsm6dso_xyz_t *out)
Read one gyroscope sample (raw 16-bit two's-complement).
ra8_err_t ra8_lsm6dso_init(ra8_lsm6dso_t *out_dev, const ra8_lsm6dso_bus_t *bus)
Bind a transport to a driver instance.
ra8_err_t ra8_lsm6dso_set_gyro_range(ra8_lsm6dso_t *dev, ra8_lsm6dso_g_fs_t fs)
Program the gyroscope full-scale range.
@ k_lsm6dso_i2c_addr_sa0_high
SDO/SA0 tied high.
Definition ra8_lsm6dso.h:98
@ k_lsm6dso_who_am_i_value
WHO_AM_I expected value (DS12140 sec 9.11).
Definition ra8_lsm6dso.h:79
@ k_lsm6dso_odr_104hz
104 Hz (normal mode).
ra8_err_t ra8_lsm6dso_read_accel(ra8_lsm6dso_t *dev, ra8_lsm6dso_xyz_t *out)
Read one accelerometer sample (raw 16-bit two's-complement).
ra8_err_t ra8_lsm6dso_who_am_i(ra8_lsm6dso_t *dev, uint8_t *out_id)
Read the WHO_AM_I register.
ra8_err_t ra8_lsm6dso_set_accel_range(ra8_lsm6dso_t *dev, ra8_lsm6dso_xl_fs_t fs)
Program the accelerometer full-scale range.
@ k_lsm6dso_g_fs_250dps
+-250 dps (default).
@ k_lsm6dso_xl_fs_2g
+-2 g, sens 0.061 mg/LSB (default).
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
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
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
Adapter context: holds channel + 7-bit address.
Definition main.c:172
uint8_t channel
IIC_B channel (0 on RA8D2).
Definition main.c:173
uint8_t addr7
7-bit peripheral address.
Definition main.c:174
Per-channel bring-up configuration for ra8_i3c_init.
Definition ra8_i3c.h:90
Transport interface bound at ra8_lsm6dso_init time.
Per-instance driver state.
3-axis raw sample (X, Y, Z as 16-bit two's-complement counts).
int16_t y
Y-axis raw count.
int16_t z
Z-axis raw count.
int16_t x
X-axis raw count.