RV32 SoC DS UG
High-Perf RV32 SoC DS UG
RV64 SoC DS UG API and Examples
Embedded IDE UG
Loading...
Searching...
No Matches
Overview

Welcome to the Board Support Package (BSP) for the Efinix Sapphire SoC. This BSP allows software running on the RISC-V processor to interact with on-chip peripherals such as SPI, I2C, GPIO, and Timers.

The drivers are designed to be bare-metal compliant, lightweight, and capable of running with or without an operating system (RTOS).

Driver Implementation Model

The BSP follows an Instance-Based driver model. Each peripheral driver consists of two main data structures:

  • Hardware Register Map (*_hwreg_t): A structure that maps directly to the physical memory address of the peripheral. This is typically used internally by the driver to read/write hardware registers.
  • Software Instance (*_instance_t): A high-level structure that holds the Configuration State (Shadow Registers) and a pointer to the hardware base address. @ Unlike traditional drivers that write to hardware immediately, this BSP uses a "Configure-then-Apply" pattern to ensure atomic updates:
    1. Modify: Update the settings in the instance structure (e.g., spi.cpol = HIGH).
    2. Apply: Call the *_applyConfig() function to flush these settings to the hardware.

Initialization Sequence

To use a specific driver, user must follow this initialization flow:

Step Action Description
1 Instantiate: Declare the driver instance structure.
2 Link: Assign the hardware base address (defined in soc.h).
3 Configure: Set the desired parameters (Prescalers, Modes, Interrupts).
4 Apply: Call *_applyConfig() to initialize the hardware.
5 Enable: (Optional) Register the interrupt handler via the PLIC.

Usage Example

This example shows how to instantiate I2C using i2c_instance_t and i2c_hwreg_t.

Step 1–3: Instantiate, Link, Configure

#include "i2c/i2c.h"
#define I2C_FREQ 100000
#define I2C_ADDR 0x67<<1
#define I2C_CTRL_HZ SYSTEM_CLINT_HZ
#define I2C_CTRL (i2c_hwreg_t *)SYSTEM_I2C_1_IO_CTRL
i2c_instance_t I2C_inst = {
.hwreg = I2C_CTRL,
.slaveAddress = I2C_ADDR,
.samplingClockDivider = 3,
.timeout = I2C_CTRL_HZ/1000,
.tsuDat = I2C_CTRL_HZ/(I2C_FREQ*5),
.tLow = I2C_CTRL_HZ/(I2C_FREQ*2),
.tHigh = I2C_CTRL_HZ/(I2C_FREQ*2),
.tBuf = I2C_CTRL_HZ/(I2C_FREQ),
};
I2C driver API definitions.
I2C instance. Holds the software registers and hardware pointer.
Definition i2c.h:290

Step 4: Apply Config

void main() {
i2c_applyConfig(&I2C_inst);
void bsp_init()
Initialize Board Support Package Peripherals.
Definition bsp.c:6
void i2c_applyConfig(i2c_instance_t *inst)
Apply the software configuration to the hardware.
Definition i2c.c:83

Step 5a: Enable Machine Mode Trap (External Interrupt)

}
void trap_entry(void)
The Main Trap Entry Point (Naked).
Definition mtrap.c:129
void irq_enable(void)
Enable Global Interrupts (MIE bit).
Definition irq.c:56
void irq_setType(cpu_irq_t enable)
Enable specific CPU interrupt sources.
Definition irq.c:76
void irq_setTrapVector(void(*trap_vector)(void))
Set the Machine Trap Vector (mtvec).
Definition irq.c:46
@ IRQ_EXTERNAL
Definition irq.h:122

Step 5b: Register I2C Interrupt Handler

Ensure the IRQ handler function name exactly matches an entry in the IRQ dispatch table to use the custom IRQ.

Using an incorrect handler name will cause the interrupt to fall back to irq_handleDefault.

printf("Interrupt triggered by I2C.\n");
}
int irq_m_i2c0_handler(void)
See also
Example Software Demos for all available demos.
mtrap.c for the full details of available IRQ Handler.

Revision History

Version Date Author Description of Changes
1.0.0 2026-06-01 Efinix Initial BSP release.

View License and Legal Information