How to enable multiple I2C Slave Addresses with RIIC Code Generator?

How to enable multiple I2C Slave Addresses with RIIC Code Generator?

How to enable multiple I2C Slave Addresses with RIIC Code Generator?

One key feature of the RX I2C-bus Interface (RIIC) is its support for up to three unique 7-bit or 10-bit slave addresses in I2C slave operation. This article explains how to enable multi-slave address detection in I2C slave operation using the RX RIIC Slave Code Generator Driver, and provides the brief instructions to address two use cases below.

Question:

How to enable the detection of multiple slave addresses using the RIIC Slave Code Generator?

Answer:

Step 1: Open the RX Smart Configurator (.scfg)

Step 2: Add I2C Slave Mode Code Generator software component

  • Configuration name: provide a name

  • Mode: select I2C mode

  • Resource: select RIICi(i=0,1,2)

Step 3: Once the Config_RIIC is added, enable the Slave address setting through the Configure pane.

  • In the example below, slave address 0, 1, and 2 (0x12, 0x13, 0x14) are all set and enabled in Smart Configurator. Click 'Generate Code'.

  • Based on the above setting, the generated initialization function (R_Config_RIIC0_Create) by Smart Configurator contains the corresponding bit configuration for ICSER (I2C Bus Status Enable Register).
    The SAR0E, SAR1E and SAR2E bits in the ICSER register control whether the Slave address in registers SARL0,1,2 and SARU0,1,2 are enabled for address detection. 
    With the support from Smart Configurator, manual configuration of these RIIC registers is not necessary.

  • Now the RIIC slave is able to automatically acknowledge your configured Slave addresses and continue the Master Write Slave Read or Master Read Slave Write, but driver will not indicate which Slave Address is detected.

Step 4: To get such information, we need to manually implement the code for reading the Slave address detection flags in the RIIC interrupt service routine because the RIIC Slave Code Generator driver does not support such feature.

  • Make a copy of Config_RIICi_user.c from "smc_gen/Config_RIICi" and place it in the src folder. (i=0,1 or2)
    By doing so, this prevents newly added code from being overwritten by auto-generated code.

  • Exclude the original Config_RIICi_user.c from build.

     

  • Then the new Config_RIICi_user.c which is under the src folder, will be included from build

     

Step 5: Open the new Config_RIICi_user.c file and add the following code to the three locations below.

  • Create constant macros for helping the flag status bit value identification in ICSR1

    Config_RIIC0_user.c

    /* Start user code for pragma. Do not edit comment generated here */ #define MULTI_SLAVE_ADDR_DETECTION (1) #define ICSR1_AAS0_BIT (0x01U) #define ICSR1_AAS1_BIT (0x02U) #define ICSR1_AAS2_BIT (0x04U) /* End user code. Do not edit comment generated here */

 

  • Create a variable to store the index of acknowledged slave address

    Config_RIIC0_user.c - R_Config_RIIC0_Create_UserInit

    /* Start user code for global. Do not edit comment generated here */ #if MULTI_SLAVE_ADDR_DETECTION iic_slave_address_acked_t iic_slave_address_acked = IIC_SLAVE_ADDR_NOT_DETECTED; #endif /* End user code. Do not edit comment generated here */ /*********************************************************************************************************************** * Function Name: R_Config_RIIC0_Create_UserInit * Description : This function adds user code after initializing the RIIC0 bus interface * Arguments : None * Return Value : None ***********************************************************************************************************************/ void R_Config_RIIC0_Create_UserInit(void) { /* Start user code for user init. Do not edit comment generated here */ #if MULTI_SLAVE_ADDR_DETECTION iic_slave_address_acked = IIC_SLAVE_ADDR_NOT_DETECTED; #endif /* End user code. Do not edit comment generated here */ }

     

    r_cg_userdefine.h

    /*/*********************************************************************************************************************** Typedef definitions ***********************************************************************************************************************/ /* Start user code for type define. Do not edit comment generated here */ typedef enum e_iic_slave_address_acked { IIC_SLAVE_ADDR_NOT_DETECTED = 0x0, IIC_SLAVE_ADDR_1_DETECTED = 0x1, IIC_SLAVE_ADDR_2_DETECTED = 0x2, IIC_SLAVE_ADDR_3_DETECTED = 0x4 }iic_slave_address_acked_t;

 

  • To obtain which slave address along with the Master Write Slave Read or Master Read Slave Write request, user can add code to store the Slave Address Detection Flag value from ISCR1 (I2C-bus Status Register 1) to our created variable during the first dummy read in RXI ISR

    Config_RIIC0_user.c - r_Config_RIIC0_receive_interrupt

    /*********************************************************************************************************************** * Function Name: r_Config_RIIC0_receive_interrupt * Description : This function is RXI0 interrupt service routine * Arguments : None * Return Value : None ***********************************************************************************************************************/ #if FAST_INTERRUPT_VECTOR == VECT_RIIC0_RXI0 #pragma interrupt r_Config_RIIC0_receive_interrupt(vect=VECT(RIIC0,RXI0),fint) #else #pragma interrupt r_Config_RIIC0_receive_interrupt(vect=VECT(RIIC0,RXI0)) #endif static void r_Config_RIIC0_receive_interrupt(void) { volatile uint8_t dummy; if (_10_IIC_SLAVE_RECEIVES_DATA == g_riic0_state) { if (1U > g_riic0_dummy_read_count) { dummy = RIIC0.ICDRR; g_riic0_dummy_read_count++; #if MULTI_SLAVE_ADDR_DETECTION iic_slave_address_acked = (iic_slave_address_acked_t)(RIIC0.ICSR1.BYTE & 0x7); #endif return; } RIIC0.ICMR3.BIT.ACKWP = 1U; RIIC0.ICMR3.BIT.ACKBT = 0U; *gp_riic0_rx_address = RIIC0.ICDRR; gp_riic0_rx_address++; g_riic0_rx_count++; if (1U == RIIC0.ICSR2.BIT.STOP) { /* check stop request */ g_riic0_state = _14_IIC_SLAVE_RECEIVES_STOP; } else if (g_riic0_rx_count == g_riic0_rx_length) { g_riic0_state = _14_IIC_SLAVE_RECEIVES_STOP; } else { /* Do nothing */ } } else if (_11_IIC_SLAVE_SENDS_DATA == g_riic0_state) { dummy = RIIC0.ICDRR; #if MULTI_SLAVE_ADDR_DETECTION iic_slave_address_acked = (iic_slave_address_acked_t)(RIIC0.ICSR1.BYTE & 0x7); #endif     } else { /* Do nothing */ } }

Note that the above steps from 1 to 5 are mainly for identifying which Slave Address is detected/acknowledged from the corresponding I2C Master Read and Write operation. To get the RIIC Slave operation work properly, user is expected to implement the required operation sequence.
An example code of RIIC Slave operation on RSK-RX130 is attached as below for the reference. By applying the above implementation, RX130 is be able to acknowledge multiple slave addresses and processing the corresponding master write slave read operation.
Through connecting the RSK-RX130 G1CUSB0 with PC, the UART console will print out the below after the operation is completed.
Required pin wiring:

  • Connect JA1-SDA with PMOD1 Pin 2

  • Connect JA1-SCL with PMOD1 Pin 3  

rsk_rx130_riic_slave_read_sci_i2c_master_write_example.zip