RISCV_I2C USER GUIDE


REVISION HISTORY

Revision No.
Description
Date
1.0
  • Initial release
  • 04/09/2025

    1. Overview

    1.1 I2C

    I2C, short for Inter-Integrated Circuit, is an integrated circuit bus that uses a multi-master to multi-slave architecture. It is a serial, synchronous, half-duplex communication bus that includes Serial Clock Line (SCL) and Serial Data Line (SDA), both of which are bidirectional IO lines. During communication, the clock signal is provided entirely by the master device; the data signal depends on whether the master device is performing a read or write operation. When performing a write operation, the data signal is provided by the master device. Conversely, when performing a read operation, the data signal is provided by the slave device.

    1.2 MIIC

    MIIC, or Master IIC Device, is an IP provided by SigmaStar specifically to act as the master device in I2C communications. It can communicate with various external I2C slave devices, meeting the needs of most devices that comply with the I2C communication protocol.

    The relationship between device bank and hardware groups is shown in the table below:

    MIIC Group bank addr
    HW MIIC group0 1114H
    HW MIIC group1 1115H
    HW MIIC group2 1116H
    HW MIIC group3 1117H
    HW MIIC group4 1118H
    HW MIIC group5 3EH

    2. Key Words

    sysdesc:

    RTOS is used to describe the hardware attributes of peripherals. The attribute values contained in the peripheral node can be used to configure the peripherals, similar to the device tree file of Linux.

    padmux:

    Pin Multiplexing, used to connect the functional pins of a module to specific external pins, thereby establishing signal connections.

    open-drain:

    Open Drain Output, does not output voltage. When controlling the pin to output a low level, the pin is grounded; when controlling the pin to output a high level, it is in a high-impedance state, with the external circuit responsible for driving the high level.

    push-pull:

    Push-Pull Output, capable of outputting both low and high levels. It is typically composed of two transistors or MOSFETs with similar parameters, providing strong driving capability.

    3. FUNCTION DESCRIPTION

    3.1 Communication Protocol

    A complete I2C communication sequence must include: a ​​Start Signal​​, ​​Slave Device Address with Read/Write Bit​​, ​​Acknowledge (ACK) Signal​​, ​​data of arbitrary byte length​​, and a ​​Stop Signal​​.

    ​​Start Signal: The first signal in an I2C communication sequence, generated by the master device. It indicates the beginning of communication. Electrical characteristics: SDA is pulled from high to low while SCL remains high.

    ​Slave Device Address:​​ Acts as the "unique identifier" for the slave device, sharing the address frame with the read/write bit. Occupies the upper 7 bits (for 7-bit addressing) or upper 10 bits (for 10-bit addressing). A slave device checks this address to determine if it is being addressed. Multiple devices with identical addresses on the same bus may cause communication failures or data corruption.

    ​​Read/Write Bit:​​ Indicates whether the master is writing to or reading from the slave. Bit 0 (LSB) represents the operation:​​

    0​​: Write operation;

    ​​1​​: Read operation

    Example: For a 7-bit slave address 0x50 with a read operation:

    address frame = (0x50 << 1) | 0x01 = 0xA1
    

    ​​Acknowledge (ACK) Signal:​​ A feedback signal from the receiver (slave or master) to the sender. Low level (ACK) indicates successful reception; high level (NACK) indicates failure. During master-read operations, the master becomes the receiver after transmitting the slave address. Note: The clock (SCL) is always controlled by the master.

    ​​Data:​​ Transmitted in byte units during read/write operations. For write operations, the slave address is typically followed by register addresses (8-bit or 16-bit), which are also treated as part of the data stream.

    ​​Stop Signal:​​ The final signal in a communication sequence, generated by the master. It marks the end of communication. Electrical characteristics: SDA is pulled from low to high while SCL remains high.

    I2C Communication Protocol Format as follow:


    Figure 3-1 I2C Communication Protocol Format

    3.2 Function Configuration

    Function
    Description
    Remark
    FIFO transfer Each transmission signal needs to be participated by the CPU, and different signals are sent by writing different MIIC registers When using polling mode, the CPU loading will be relatively large; the maximum amount of data transmitted at a time is 8192 bytes; this mode is recommended when the amount of data transmitted each time is relatively small
    DMA transfer The entire communication process is operated by MIIC itself, and you only need to fill in the transmission content in advance and then trigger it; HW MIIC will communicate according to the timing settings that have been filled in When using interrupt mode, the CPU loading will be smaller than FIFO mode; the maximum amount of data transmitted at a time is 4086 bytes; this mode is recommended when the amount of data transmitted each time is relatively large; when an error occurs during transmission, HW will immediately stop the communication and trigger an interrupt
    Timing adjustment Several I2C communication timings are available for adjustment. When a specific part of the timing does not meet the requirements of the slave device, adjust it in the dtsi node Adjustable timing: t-SU-STA, t-HD-STA, t-SU-STO, t-HD-STO, t-SU-DAT, t-HD-DAT
    Rate Supports adjustable communication rate range, no gear classification, and can be adjusted in the dtsi node according to actual needs Supports 50kHz - 1500KHz, and the higher rate requirement is not guaranteed
    Output mode adjustment Supports open-drain and push-pull output modes, which can be adjusted in the dtsi node MIIC does not support arbitrary adjustment of the rising/falling edge time of the waveform, which can only be changed by adjusting the output mode, and the time cannot be confirmed. The push-pull rising edge time will be faster
    Padmux Different padmux can be configured to lead the bus to different pins
    1toN Some padmux will connect several groups of PAD pins at the same time, and the signal will be provided to these groups of PADs at the same time during communication This method has the following limitations: All slave devices must be of the same type and address, and MIIC can only write data but not read data. It is generally used to connect to several identical slave devices at the same time and need to be set synchronously.
    External pull-up External pull-up must be connected to the I2C bus

    I2C Communication Timing as follow:


    Figure 3-2 I2C Timing

    MIIC supports the following configurable timing parameters:

    Timing Description
    t-SU-STA Start signal setup time
    t-HD-STA Start signal hold time
    t-SU-STO Stop signal setup time
    t-HD-STO Stop signal hold time
    t-LOW Clock low period
    t-HIGH Clock high period
    t-SU-DAT Data signal setup time
    t-HD-DAT Data signal hold time

    I2C divides communication speeds into multiple modes based on intervals:

    Speed Mode Description
    Standard-mode (Sm) Up to 100k bit/s maximum
    Fast-mode (Fm) Up to 400k bit/s maximum
    Fast-mode Plus (Fm+) Up to 1M bit/s maximum
    High-speed mode (Hs-mode) Up to 3.4M bit/s maximum
    Ultra Fast-mode (UFm) Up to 5M bit/s maximum

    Timing Requirements for Sm/Fm/Fm+ Speed Modes as follow:


    Figure 3-3 Timing Requirements for Different Speed Modes

    4. Introduction to Hardware Connections

    I2C follows a multi-master, multi-slave architecture. By definition, a single bus can host multiple master devices and multiple slave devices. Communication between devices is established through ​​slave addresses​​ and ​​acknowledge (ACK) signals.

    SigmaStar's I2C only provides one MIIC (master iic) master device on each bus, and there is no requirement for the number of slave devices, which can be set according to usage requirements.

    In addition, in accordance with the I2C standard protocol, the external pull-up must be connected to the SDA and SCL of the bus. This is because I2C communication requires the ability to output a high level, and when the device output is an open-drain output, it cannot output a high level. At this time, the help of an external pull-up is needed to realize the "Wired-AND" function and determine the final level.

    The following is an example diagram of the I2C bus:


    Figure 4-1: Example Diagram of I2C Bus

    5. RTOS USAGE INTRODUCTION

    5.1. DRIVER PATH

    sc/driver/sysdriver/i2c/os/iic_os.h
    sc/driver/sysdriver/i2c/drv/pub/drv_iic.h
    sc/driver/sysdriver/i2c/drv/src/drv_iic.c
    sc/driver/sysdriver/i2c/drv/src/drv_iic_test.c
    sc/driver/sysdriver/i2c/hal/pcupid/src/hal_iic.c
    sc/driver/sysdriver/i2c/hal/pcupid/inc/hal_iic.h
    sc/driver/sysdriver/i2c/hal/pcupid/inc/hal_iic_reg.h
    sc/driver/sysdriver/i2c/hal/pcupid/inc/hal_iic_cfg.h
    

    5.2. CONFIG Configuration

    config locate in mak/options_chipname_riscv_isw.mak,and enable CONFIG_I2C_SUPPORT

    # Feature_Name = [DRV] I2C driver support
    # Description = I2C driver support
    # Option_Selection = TRUE, FALSE
    # CONFIG_I2C_SUPPORT = TRUE
    

    5.3. SYSDESC Configuration

    pcupid-default.sys file is located in sc\driver\sysdriver\sysdesc\hal\pcupid\pub\.

    <i2c0>
        [reg_u32_u16] 0x2222800 0x200;
        [interrupts_u8] INT_IRQ_MIIC;
        [camclk_u16] CAMCLK_miic0;
        [dma_u8] 1;
        [output_mode_u8] 2;
        [speed_u32] 200000;
        [t_su_sta_u32] 0;
        [t_hd_sta_u32] 0;
        [t_su_sto_u32] 0;
        [t_hd_sto_u32] 0;
        [t_su_dat_u32] 0;
        [t_hd_dat_u32] 0;
        [status_u8] 1;
    

    The attributes supported for configuration in the Master IIC driver are as follows:

    Attribute Description Setting value Remark
    reg_u32_u16 Specify the address of the bank No modification required
    interrupts_u8 Specify the hardware interrupt number No modification required
    dma_u8 Select whether to enable DMA mode 1-enable; 0-disable Can be modified as needed
    output_mode_u8 Select the output mode 1: open drain output;
    2: open drain push 1T output;
    3: open drain push 1T strong pull-up;
    4: push-pull output
    Can be modified as needed,
    1->4 rising edge time is shortened in turn
    speed_u32 Set the communication frequency, the unit is HZ Range 50K~1500K HZ Can be modified as needed
    t_su_sta_u32 Set the start signal hold time ns value Can be modified as needed
    t_hd_sta_u32 Set the start signal establishment time ns value Can be modified as needed
    t_su_sto_u32 Set the end signal establishment time ns value Can be modified as needed
    t_hd_sto_u32 Set the end signal hold time ns value Can be modified as needed
    t_su_dat_u32 Set the end signal establishment time ns value Can be modified as needed
    t_hd_dat_u32 Set the start signal establishment time ns value Can be modified as needed
    camclk_u16 Specify the clock source No modification required
    status_u8 Select whether to enable the driver 1-enable; 0-disable Can be modified as needed

    Detailed description:

    Figure 5-1 below shows the detailed timing decomposition of miic, and Figure 5-2 shows the positions of several adjustable timings.

    Figure 5-1: MIIC Communication Timing

    Figure 5-2: MIIC Start Signal and End Signal Timing Adjustment

    Several timing adjustments are available in sysdesc, and the corresponding waveform positions are:

    Timing
    Waveform Position
    t-su-sta reg_start_setup_cnt
    t-hd-sta reg_start_cnt
    t-su-sto reg_stop_cnt
    t-hd-sto reg_stop_hold_cnt
    t-su-dat reg_lcnt - reg_sda_cnt
    t-hd-dat reg_sda_cnt

    If the attribute value in the node is 0, the driver will calculate the ns value according to the established calculation. If there is a setting, it will follow the setting value. The theoretical maximum value of the setting is U32_MAX, unit is ns.

    5.4. PADMUX Configuration

    CONFIG Configuration: CONFIG_PADMUX_SUPPORT=TRUE

    If the chipname_xxx.sys file is configured with the attribute <padmux>, then the PADMUX setting is directly configured here:

    <padmux>
        [schematic_u32_u32_u32]
            PAD_GPIOE_01    PINMUX_FOR_I2C0_MODE_1    MDRV_PUSE_I2C0_SDA,
            PAD_GPIOE_04    PINMUX_FOR_I2C1_MODE_1    MDRV_PUSE_I2C1_SCL,
            PAD_GPIOE_05    PINMUX_FOR_I2C1_MODE_1    MDRV_PUSE_I2C1_SDA,
            PAD_GPIOE_21    PINMUX_FOR_I2C2_MODE_1    MDRV_PUSE_I2C2_SCL,
            PAD_GPIOE_22    PINMUX_FOR_I2C2_MODE_1    MDRV_PUSE_I2C2_SDA,
            PAD_GPIOE_23    PINMUX_FOR_I2C3_MODE_1    MDRV_PUSE_I2C3_SCL,
            PAD_GPIOE_24    PINMUX_FOR_I2C3_MODE_1    MDRV_PUSE_I2C3_SDA,
            PAD_GPIOD_01    PINMUX_FOR_I2C4_MODE_1    MDRV_PUSE_I2C4_SCL,
            PAD_GPIOD_02    PINMUX_FOR_I2C4_MODE_1    MDRV_PUSE_I2C4_SDA,
            PAD_PM_I2C_SDA    PINMUX_FOR_PM_I2CM0_MODE_1    MDRV_PUSE_I2C5_SCL,
            PAD_PM_I2C_SDA    PINMUX_FOR_PM_I2CM0_MODE_1    MDRV_PUSE_I2C5_SDA,
        [status_u8] 1;
    

    Otherwise, enable the PADMUX driver and configure the pin multiplexing function in the chipname-xxx-padmux.c file, which is located in sc/driver/sysdriver/padmux/hal/chipname/src. You only need to add the following content to the corresponding schematic attribute:

    pad_info_t schematic[] =
    {
        {PAD_GPIOE_01    PINMUX_FOR_I2C0_MODE_1    MDRV_PUSE_I2C0_SDA},
        {PAD_GPIOE_04    PINMUX_FOR_I2C1_MODE_1    MDRV_PUSE_I2C1_SCL},
        {PAD_GPIOE_05    PINMUX_FOR_I2C1_MODE_1    MDRV_PUSE_I2C1_SDA},
        {PAD_GPIOE_21    PINMUX_FOR_I2C2_MODE_1    MDRV_PUSE_I2C2_SCL},
        {PAD_GPIOE_22    PINMUX_FOR_I2C2_MODE_1    MDRV_PUSE_I2C2_SDA},
        {PAD_GPIOE_23    PINMUX_FOR_I2C3_MODE_1    MDRV_PUSE_I2C3_SCL},
        {PAD_GPIOE_24    PINMUX_FOR_I2C3_MODE_1    MDRV_PUSE_I2C3_SDA},
        {PAD_GPIOD_01    PINMUX_FOR_I2C4_MODE_1    MDRV_PUSE_I2C4_SCL},
        {PAD_GPIOD_02    PINMUX_FOR_I2C4_MODE_1    MDRV_PUSE_I2C4_SDA},
        {PAD_PM_I2C_SDA    PINMUX_FOR_PM_I2CM0_MODE_1    MDRV_PUSE_I2C5_SCL},
        {PAD_PM_I2C_SDA    PINMUX_FOR_PM_I2CM0_MODE_1    MDRV_PUSE_I2C5_SDA},
    };
    

    The first column is the pin index number, which can be queried in sc/drivers/sysdriver/gpio/hal/chipname/pub/gpio.h;

    The second column is the mode definition, which can be queried in sc/drivers/sysdriver/gpio/hal/chipname/pub/padmux.h;

    The third column is the index name of the pin and matching mode, which can be queried in sc/drivers/sysdriver/padmux/drv/pub/drv_puse.h.

    5.5 Sample code

    The header file is located in sc/driver/sysdriver/i2c/drv/pub/drv_iic.h.

    static int i2c_ut_test(CLI_t * cli, char * p)
    {
        u8 i;
        u8 argc;
        u32 port;
        u32 slave;
        char *cmd;
        tI2cMsg msg;
        u32 addr;
        u32 value;
        u8 data[32];
        u8 e_data[32];
        int ret   = 0;
        u8 r_flag = 0;
        u32 speed = 0;
    
        argc = CliTokenCount(cli);
        if (argc < 2)
            return eCLI_PARSE_INPUT_ERROR;
    
        cmd = CliTokenPop(cli);
        if (strcmp(cmd, "r") == 0)
        {
            argc = CliTokenCount(cli);
            if (argc != 4)
                return eCLI_PARSE_INPUT_ERROR;
            r_flag = 1;
    
        }
        else if (strcmp(cmd, "w") == 0)
        {
            argc = CliTokenCount(cli);
            if (argc < 5 || argc > 6)
                return eCLI_PARSE_INPUT_ERROR;
        }
        else
        {
            return eCLI_PARSE_INPUT_ERROR;
        }
    
        if (CliTokenPopNum(cli, &port, 0) != eCLI_PARSE_OK)
        {
            return eCLI_PARSE_INPUT_ERROR;
        }
    
        if (CliTokenPopNum(cli, &slave, 0) != eCLI_PARSE_OK)
        {
            return eCLI_PARSE_INPUT_ERROR;
        }
    
        cmd = CliTokenPop(cli);
        if (strcmp(cmd, "A16D8") == 0)
        {
            msg.addr = (u16)slave;
            if (r_flag)
            {
                if (CliTokenPopNum(cli, &addr, 0) != eCLI_PARSE_OK)
                {
                    return eCLI_PARSE_INPUT_ERROR;
                }
    
                //write
                msg.flags = 0;
                data[0] = (u8)((addr >> 8) & 0xff);
                data[1] = (u8)(addr & 0xff);
                msg.buf = data;
                msg.len = 2;
                drv_i2c_master_xfer(port, &msg, 1);
    
                //read
                msg.flags = CAM_I2C_RD;
                msg.buf = data;
                msg.len = 1;
                drv_i2c_master_xfer(port, &msg, 1);
                cliPrintf(" %04x : %02x\r\n", (u16)addr, (u8)data[0]);
            }
            else
            {
                if (CliTokenPopNum(cli, &addr, 0) != eCLI_PARSE_OK)
                {
                    return eCLI_PARSE_INPUT_ERROR;
                }
    
                if (CliTokenPopNum(cli, &value, 0) != eCLI_PARSE_OK)
                {
                    return eCLI_PARSE_INPUT_ERROR;
                }
    
                CliTokenPopNum(cli, &speed, 0);
    
                data[0] = (u8)((addr >> 8) & 0xff);
                data[1] = (u8)(addr & 0xff);
                data[2] = (u8)(value & 0xff);
    
                //write
                msg.flags = 0;
                msg.buf = data;
                msg.len = 3;
    
                //set i2c speed
                if (speed)
                    drv_i2c_set_speed(port, speed);
    
                //transfer
                drv_i2c_master_xfer(port, &msg, 1);
            }
    
        }
    
        return eCLI_PARSE_OK;
    }
    

    6. API Reference

    This functional module provides the following interfaces:

    API Function
    drv_i2c_master_xfer Perform IIC transfer (synchronous)
    drv_i2c_set_speed Set iic tranfer speed

    To use these APIs, you need to include the header file sc/driver/sysdriver/i2c/drv/pub/drv_iic.h.

    The data structures defined within it are as follows:

    typedef struct i2c_msg {
        u16 addr;   /*slave address*/
        u16 flags;
    #define CAM_I2C_RD                   0x0001
    #define CAM_I2C_STOP_BEFORE_RESTART  0x0002
    #define CAM_I2C_TEN                  0x0010
    #define CAM_I2C_DMA_SAFE             0x0200
    #define CAM_I2C_RECV_LEN             0x0400
    #define CAM_I2C_NO_RD_ACK            0x0800
    #define CAM_I2C_IGNORE_NAK           0x1000
    #define CAM_I2C_REV_DIR_ADDR         0x2000
    #define CAM_I2C_NOSTART              0x4000
    #define CAM_I2C_STOP                 0x8000
        u16 len;        /*msg length*/
        u8 *buf;        /*pointer to msg data*/
    }tI2cMsg;
    

    6.1. drv_i2c_master_xfer

    • Function

      Perform a single synchronous IIC transfer with the IIC channel corresponding to para_group, using para_num para_msg entries to store the transfer information.

    • Declaration

      s32 drv_i2c_master_xfer(u8 para_group, struct i2c_msg *para_msg, s32 para_num);
      
    • Parameters

      Parameter Name Description
      para_group Device Number
      para_msg Communication Content
      para_num Information Length
    • Return Value

      Return Value Description
      0 Failure
      positive Success

    6.2 drv_i2c_set_speed

    • Function

      Set speed of the IIC channel corresponding to para_group to speed

    • Declaration

      s32 drv_i2c_set_speed(u8 para_group, u32 speed);
      
    • Parameters

      Parameter Name Description
      para_group i2c bus
      speed Transfer frequence, units is Hz
    • Return Value

      Return Value Description
      0 Success
      other Failure

    7. DEBUG

    When communication abnormalities occur, you can refer to the following aspects for troubleshooting. Several common troubleshooting directions are provided. Additionally, it is recommended to capture waveforms during the debugging process for easier analysis.

    Troubleshooting Directions
    Common Issues
    Note
    External Pull-up 1. Indicates a communication timeout error message;
    2. Captured waveform shows no change, SCL remains low;
    3. The data read and written in the captured waveform are all 0x00;
    padmux 1. Indicates no ACK signal;
    2. The waveform shows no change, the level remains constant;
    Refer to the PADMUX chapter, or the padmux module description;
    Communication Rate Communication failed, no ACK signal; Check the slave device manual to confirm the normal operating communication rate range;
    Clock Source 1. Indicates a communication timeout error message;
    2. No waveform;
    Refer to the CLKGEN module description;
    Timing Communication has no ACK signal; If the slave device has specific requirements for detailed timing, check and confirm these from the device manual;
    Slave Device Operating State Communication has no ACK signal; When the slave device is not in a normal working state, it cannot respond to signals initiated by the master device;