37.3.1 Module Setup in I3C Mode

The I3C Target module can be set up to operate in I3C mode by following the recommended order of settings shown in Table 37-20. An example setup code is shown in Module Setup in I3C Mode below.

Important: The I3C Target module always starts by operating in I2C mode (OPMD = 0b00) until it is assigned a Dynamic Address by the Controller either through the Hot-Join Mechanism process or regular Dynamic Address Assignment.
Table 37-20. Recommended Module Setup Order for I3C® Mode Operation
Setting Description Section Reference
Pad Buffer Selection Set SDA/SCL pins as open-drain inputs and select an appropriate pad buffer (I3C LV/FST Buffer) using the RxyFEAT register. 37.2.3.2 SDA and SCL Pins
Module Clock Select the appropriate clock for the I3C module using I3CxCLK register. 37.2.1 I3C Module Clock
Bus Conditions Select the appropriate values for I3CxBIDL and I3CxBAVL registers based on the I3C clock speed to match the Bus Idle and Bus Available conditions. 37.2.3.4 I3C Bus Conditions
Bus Time-out (optional) If the bus time-out feature is desired, the feature can be enabled using BTOEN bit in RxyFEAT register. The bus time-out threshold can be set using I3CxBTO register. 37.2.3.4.4 Bus Time-out
In-Band Interrupt and Hot-Join The arbitration request retry limit for IBI and Hot-Join can be set using the I3CxRETRY register. The IBI Mandatory Data Byte and Payload Size can be set using the I3CxIBIMDB and I3CxIBIPSZ registers. The module can be made Hot-Join capable by setting the HJCAP bit.

37.2.8 Hot-Join Mechanism

37.2.9 In-Band Interrupt (IBI)

Static Address Set the desired static address for the I3C module using I3CxSADR register. 37.2.4.2.1 I2C Static Address
Provisional ID and Device ID Set the Provisional ID for the I3C module using the I3CxPID0 through I3CxPID5 registers. In addition, set an appropriate Device ID using the I3CxDCR register.

37.2.3.1 I3C Characteristics Registers

37.2.6.1 Provisional ID

Speed Limitations If the device/application is speed limited, set the BCR0 bit in I3CxBCR register. Set the maximum read/write speed and read turnaround times using the I3CxMWS, I3CxMRS and I3CxMRT registers. 37.2.3.3 Speed Limitations
Buffers and FIFO The CLRRXB and CLRTXB bits in the I3CxCON register can be used to clear the receive and transmit buffers and FIFO immediately after the I3C module is enabled. 37.2.4.4 Transmit and Receive Buffers and FIFO
Static Address SDR Mode If desired, the Static Address SDR Mode can be enabled using the SASDRMD bit. 37.2.6.4 Static Address SDR Mode
Private Transaction Configure ACK control for Private Transactions using ACKP and ACKPOS bits. Change Maximum Read/Write Lengths as necessary using I3CxMRL and I3CxMWL registers. 37.2.10 Private Transaction
Interrupts Clear all the module-level and system-level interrupt flags. Enable the desired interrupts by setting the appropriate interrupt enable bits. Remember to enable the system-level interrupt controller to generate the enabled interrupts. 37.2.14 Interrupts and DMA Triggers
Module Enable Enable the I3C module in the end by setting the EN bit.
Tip: It is recommended that the user set up and use DMA to read and write from the I3C Transmit and Receive Buffers to ensure that the CPU is able to keep up with the higher I3C speeds. Refer to the Interrupts and DMA Triggers section and the "DMA - Direct Memory Access" chapter for more information.

Module Setup in I3C® Mode

// RxyFEAT Buffer Selection
#define GPIO_BUFFER         0b000   // ST/CMOS or LVBUF/TTL selected through INLVLx
#define I2C_BUFFER          0b001
#define SMB2_BUFFER         0b010
#define SMB3_BUFFER         0b011
#define I3CFST_BUFFER       0b100   // Only for >1.62V (set VDDIOxMD config properly)
#define I3CLV_BUFFER        0b101   // Only for <1.62V (set VDDIOxMD config properly)

void I3C1_Target_Setup()
{
    // Assumption: RC0/RC1 pins are SCL/SDA
    
    // Ensure module is turned off for setup
    I3C1CON0bits.EN = 0;            
    
    // Note: VDDIOxMD config bit must be set properly

    // Set SDA/SCL pins to be open-drain inputs
    ODCONCbits.ODCC0 = 1;
    ODCONCbits.ODCC1 = 1;
    TRISCbits.TRISC0 = 1;
    TRISCbits.TRISC1 = 1;
    
    // Select I3C FST/LV buffer
    RC0FEATbits.I3CBUF = I3CFST_BUFFER;
    RC1FEATbits.I3CBUF = I3CFST_BUFFER;
    
    // Enable/Disable I2C features on I3C pads as needed
    I3C1I2CCONbits.FLTEN = 0;       // 50 ns glitch filter
    I3C1I2CCONbits.SDAHT = 0b00;    // SDA Hold Time
    
    // Select Clock
    I3C1CLK = 0x01;         // 0x01=Fosc   

    // Set Bus Idle and Bus Available Conditions
    I3C1BIDL = 12800;       // 200us
    I3C1BAVL = 64;          // 1us   

    // Bus Timeout settings (optional)
    I3C1CON0bits.BTOEN = 0; // Enable/Disable Bus Timeout
    I3C1BTO = 164;          // 32*F_scl @ F_scl=12.5MHz (or any appropriate value)

    // IBI/HJ Settings
    // HJCAP=0: module responds to ENTDAA all the time and cannot request HJ
    // HJCAP=1: module cannot respond to ENTDAA unless HJ is requested first
    I3C1FEATbits.HJCAP = 0; // HJ capable or not?
    I3C1RETRY = 3;          // Number of retries for IBI and HJ
    I3C1IBIMDB = 0xA5;      // IBI Mandatory Byte (0x00 = User Defined)
    I3C1IBIPSZ = 0;         // Payload size (0 = unlimited, 8-bit value)  

    // Static Address
    I3C1SADR = 0x30;        // Static Address  

    // Set Provisional ID
    I3C1PID5 = 0x06;        // PID[37:33] is MIPI Manufacturer ID (Microchip = 0x034D<<1 = 0x069A)
    I3C1PID4 = 0x9A;        // PID32=0 (PID[31:0] is vendor defined)
    I3C1PID3 = 0x11;        // PID[31:16] is Part ID
    I3C1PID2 = 0x22;
    I3C1PID1 = 0x33;        // PID[15:12] is Instance ID
    I3C1PID0 = 0x44;        // PID[11:0] is vendor defined   

    // Set Initial Device Status for GETSTATUS CCC
    I3C1DSTAT0 = 0x00;      // Activity mode, Protocol Error, Pending Interrupt
    I3C1DSTAT1 = 0x00;      // Vendor Reserved   

    // Is device speed limited? (application dependent)
    I3C1BCRbits.BCR0 = 1;   // Speed limited (If no, BCR0=0)
    
    // Device Characteristics
    I3C1DCR = 0xC6;         // 0xC6 = Microcontroller
    
    // Add support for Get Max Data Speed (GETMXDS CCC) since device is speed limited (BCR0=1 above)
    I3C1MWS = 0x00;         // Max Write Speed
    I3C1MRS = 0x00;         // Max Read Speed (specified Clock-to-Data Turnaround Time)
    I3C1MRT = 0;            // Max Read Turnaround Time (in us) // 24-bit
    
    // Clear buffers and FIFOs
    I3C1CON0bits.CLRRXB = 1; // Clears RXB Rx Buffer and Rx FIFO
    I3C1CON0bits.CLRTXB = 1; // Clears TXB Tx Buffer and Tx FIFO
    
    // Static Address SDR Mode Enable?
    I3C1CON1bits.SASDRMD = 0;
    
    // Private Transaction Settings
    // Default Private Write/Read ACK setting
    I3C1CON0bits.ACKP = 0;   // 0=ACK; 1=NACK
    I3C1CON1bits.ACKPOS = 0; // 0=One-shot disabled
    
    // Max Rd and Max Wr Lengths
    I3C1MRL = 0;            // 0=unlimited (16-bit value)
    I3C1MWL = 0;
    
    // Clear all interrupt flags (x = appropriate PIR register)
    I3C1PIR0 = 0x00;        // Module-level general interrupts
    I3C1PIR1 = 0x00;
    I3C1ERRIR0 = 0x00;      // Module-level error interrupts
    I3C1ERRIR1 = 0x00;
    PIRxbits.I3C1IF = 0;    // System-level general interrupt
    PIRxbits.I3C1EIF = 0;   // System-level error interrupt
    PIRxbits.I3C1TXIF = 0;  // System-level transmit interrupt
    PIRxbits.I3C1RXIF = 0;  // System-level receive interrupt
    PIRxbits.I3C1RIF = 0;   // System-level reset interrupt   

    // Enable interrupts as needed (x = appropriate PIE register)
    I3C1PIE0 = 0x00;
    I3C1PIE1 = 0x00;
    I3C1ERRIE0 = 0x00;
    I3C1ERRIE1 = 0x00;
    PIExbits.I3C1IE = 0;  
    PIExbits.I3C1EIE = 0;   
    PIExbits.I3C1TXIE = 0;  
    PIExbits.I3C1RXIE = 0;  
    PIExbits.I3C1RIE = 0;     
    
    // Enable Target Module
    I3C1CON0bits.EN = 1;        
}