IBI Payload and Mandatory Data Byte

The IBI Payload is any data sent by the Target that follows the Dynamic Address after an IBI request is ACKed by the Controller. The first byte of the payload that immediately follows the Dynamic Address is referred to as IBI Mandatory Data Byte and is accessed using the I3CxIBIMB register. This Target module will always send one (the Mandatory Data Byte) or more bytes of payload data once the IBI request is accepted by the Controller, which is indicated by the BCR2 bit (BCR2 = 1). This is communicated to the Controller during the Dynamic Address Assignment procedure or when the Controller requests for it using the GETBCR (Get Bus Characteristics Register) Direct Common Command Code (CCC).

The Controller sets the maximum payload size using the SETMRL (Set Maximum Read Length) CCC. This value is stored in the read-only I3CxIBIPSZ IBI Payload Size register. A payload size value of zero indicates that the IBI payload is only the Mandatory Data Byte. Any other payload size value indicates the size of payload (excluding Mandatory Data Byte) in bytes. Hence, the minimum payload size supported by the Target is one byte (the Mandatory Data Byte) and the maximum payload size is 256 bytes. The Controller can use the GETMRL (Get Maximum Read Length) CCC to read the value of the maximum payload size stored in the I3CxIBIPSZ register.

Once the Controller ACKs the IBI request, it cannot decline the reception of the Mandatory Data Byte since it is transmitted in Push-Pull mode and must wait for the next T-bit. After receiving the Mandatory Data Byte, the Controller can continue to receive further payload data from the Target in Push-Pull mode or terminate any subsequent transmission by asserting the End-of-Data T-bit (Restart) or transmitting a Stop. The frame format of a successful IBI transaction is shown in Figure 1.

The I3CxIBIMB Mandatory Data Byte provides the Controller additional information about the event that has happened and is divided into two fields as defined by MIPI:

  1. 1.As per MIPI specification, the Most Significant bit (IBIMB7) of the I3CxIBIMB Mandatory Data Byte signifies timing information or pending read notification. Since this Target module does not support either, IBIMB7 bit is reserved and will always read ‘0’.
  2. 2.MIPI Alliance maintains a web-based registry of defined Mandatory Data Byte use case values at https://www.mipi.org/MIPI_I3C_mandatory_data_byte_values_public.
The user can write the payload data to be sent to the I3CxTXB Transmit Buffer, which feeds into the Transmit FIFO. Once the Target sends the I3CxIBIMB Mandatory Data Byte, it will start sending the payload from the Transmit FIFO. The Target will continue to send the payload until the Transmit FIFO becomes empty (and asserts the End-of-Data T-bit), or if the Controller aborts the transaction by asserting the End-of-Data T-bit (a Restart condition) or a Stop. If the Controller aborts the payload transmission, then the IBIAEIF error interrupt flag is set. Refer to the pseudo-code shown in IBI Request Pseudo-code Using Polling below for more information.
The user software can use the IBI payload to communicate the specific details of an interrupt. If the Controller NACKs or disables the IBI request on the bus, then the user software can use the INTPEND bits to store the interrupt number of the pending interrupt (a value of 0 indicates no interrupts are pending). This is reported to the Controller when it inquires for the device status through GETSTATUS CCC. The encoding of the INTPEND bits allow the Target to report up to 15 numbered interrupts. If more than one interrupt is pending in the user software, it is recommended to return the interrupt number of the highest priority pending interrupt.
Tip: Before making any IBI requests, it is recommended to check the maximum payload size that the Controller will accept by reading the value in the I3CxIBIPSZ register. If the Target continues to send payload data that exceeds the maximum payload size set by the Controller, the Controller may either accept or terminate the transaction depending upon any private contract between the Target and the Controller or the Controller’s ability to receive them.
Tip: It is recommended for the user to 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 section Interrupts and DMA Triggers and "DMA - Direct Memory Access" chapter for more information.
Figure 1. Successful IBI Transaction Frame Format

IBI Request Pseudo-code Using Polling

uint8_t payloadData[SIZE];  // payload data to be sent

uint8_t I3C1_Target_IBI()
    // Check Target's operating mode first
    if(I3C1STATbits.OPMD != 0b01) {
        // Target is operating in I2C mode, cannot perform IBI
        return 1;

    // Check if Controller has disabled IBI requests
    if(!I3C1ECbits.IBIEN) {
        // Controller has disabled IBI requests
        return 1;

    // Begin IBI request
    I3C1CONbits.IBIREQ = 1;

    // Mandatory Data Byte in I3C1IBIMB is sent automatically
    // Send IBI Payload

    // Check whether IBI process is complete
    while(I3C1CONbits.IBIREQ);  // IBIREQ clears when process is complete

    // Check if IBI completed successfully
    if(I3C1PIR1bits.IBIDONEIF) { /* Successful IBI */ }
    else if(I3C1ERRIR0bits.IBIEIF || I3C1ERRIR1bits.IBIAEIF) { /* Error */ }

uint8_t I3C1_Target_IBI_SendPayload()
    uint16_t payloadSize = I3C1IBIPSZ;  // Max Payload Size set by Controller
    uint8_t i = 0;

    while(i < SIZE) {

        // Wait for Tx Buffer to become empty

        // Write payload data to Transmit buffer and increment pointer
        I3C1TXB = payloadData[i++];

        // Check if payload size overflow
        if(i >= payloadSize) {
            // Software has exceeded max Payload Size set by the Controller
            // Take appropriate action

        // Perform error checking if desired
        // Check for Tx Underrun Error or Tx Write Error
        // if(I3C1ERRIR0bits.TXUIF || I3C1ERRIR1bits.TXWEIF) { ... }

        // Check for Controller aborting transaction prematurely
        if(I3C1PIR0bits.PCIF || I3C1PIR0bits.RSCIF || I3C1PIR1bits.TCOMPIF) {
            return 1;  // end of transaction with Controller abort

    // Wait for Stop or Restart for End of Transaction
    while(!I3C1PIR0bits.PCIF && !I3C1PIR0bits.RSCIF && !I3C1PIR1bits.TCOMPIF) 
        // While waiting, check for additional errors (if desired)
        // if(I3C1ERRIR0bits.TXUIF || I3C1ERRIR1bits.TXWEIF) { ... }

    return 0;