37.2.9.1 IBI Payload and Mandatory Data Byte
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 which is stored in the I3CxIBIPSZ IBI Payload Size register. The firmware can choose to override this value by writing to the I3CxIBIPSZ register. 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 pulling the End-of-Data T-bit low (Restart condition on the bus) or transmitting a Stop. The frame format of a successful IBI transaction is shown in Figure 37-45.
The I3CxIBIMDB Mandatory Data Byte provides the Controller additional information about the event that has happened and is divided into two fields as defined by MIPI.
- IBIMDB[7:5] – Interrupt Group Identifier (3 bits)
- IBIMDB[4:0] – Specific Interrupt Identifier (5 bits)
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 I3CxIBIMDB Mandatory Data Byte, it will start sending the payload from the Transmit FIFO. The Target continues to send the payload until one of the following conditions occurs (refer to the pseudo-code shown in IBI Request Pseudo-code Using Polling for more information):
- Transmit FIFO becomes empty; Target pulls the End-of-Data T-bit low and sets the IBIDONEIF and TCOMPIF flags
- Maximum Payload Size (I3CxIBIPSZ)
limit is reached; Target pulls the End-of-Data T-bit low despite Transmit FIFO not
being empty (TXFNE =
1
) and sets the IBIDONEIF and TCOMPIF flags - Controller aborts the payload transmission by pulling the End-of-Data T-bit low (a Restart condition), in which case the Target sets the ABEIF error alongside the IBIDONEIF and TCOMPIF flags
IBI Request Pseudo-code Using Polling
uint8_t payloadData[SIZE]; // payload data to be sent void I3C1_Target_IBI_Setup() { // Set bus available time I3C1BAVL = 64; // 1us @ I3C1CLK=64MHz // Set Bus Timeout (optional; to recover from stalled Controller) I3C1CON0bits.BTOEN = 0; I3C1BTO = 164; // 32*F_scl @ F_scl=12.5MHz // Set retry limit and mandatory byte I3C1RETRY = 3; // 0=unlimited; 8-bit value I3C1IBIMDB = 0x00; // IBI Mandatory Byte (0x00 = User Defined) // Initialize payload to send for(uint8_t i=0; i<SIZE; i++) { txData[i] = i; } // Validate Payload Size if(I3C1IBIPSZ > SIZE || I3C1IBIPSZ == 0) { // 0=unlimited (8-bit value) I3C1IBIPSZ = SIZE; } // Pre-load Transmit buffer to prevent an EOD after mandatory byte while(!I3C1STAT0bits.TXBE); I3C1TXB = payloadData[0]; } void I3C1_Target_IBI_SendPayload() { uint8_t i = 1; // payloadData[0] is already loaded into TXB while(i < SIZE) { // Wait for Tx Buffer to become empty while(!I3C1STAT0bits.TXBE); // Write data to Transmit buffer and increment pointer I3C1TXB = payloadData[i++]; // Perform error checking if desired // Check for Tx Underrun Error or Tx Write Error // if(I3C1ERRIR0bits.TXUIF || I3C1ERRIR1bits.TXWEIF) { ... } // Check for End of Transaction if(I3C1PIR1bits.TCOMPIF) { if(I3C1STAT1bits.TXFNE) { return 0; // end of transaction due to payload size overflow } else if(I3C1ERRIR1bits.ABEIF) { return 0; // end of transaction due to Controller abort } else return 0; // end of transaction due to TXFIFO empty } } } void I3C1_Target_IBI() { // Check if Target is ready for IBI if(I3C1STAT0bits.OPMD == 0b01 && I3C1ECbits.IBIEN) { // Begin IBI request I3C1CON0bits.IBIREQ = 1; // Mandatory Data Byte in I3C1IBIMDB is sent automatically // Send IBI Payload I3C1_Target_IBI_SendPayload(); // Check whether IBI process is complete while(I3C1CON0bits.IBIREQ); // IBIREQ clears when process is complete // Check if IBI completed successfully if(I3C1PIR1bits.IBIDONEIF) { /* Successful IBI */ } else if(I3C1ERRIR0bits.IBIEIF || I3C1ERRIR1bits.ABEIF) { /* Error */ } } }