37.2.10.2 Private Read Transaction
In Private Read Transfer, following the address header, the Target continues to send 9-bit I3C Data Words (8-bit Data and an End-of-Data T-bit). The user writes the data to be sent to the I3CxTXB Transmit Buffer using the firmware or DMA, which feeds into the Transmit FIFO. The Target continues to send the data until one of the following conditions occurs:
- Transmit FIFO becomes empty; Target pulls the End-of-Data T-bit low
- Maximum Read Length (I3CxMRL)
is reached; Target pulls the End-of-Data T-bit low despite Transmit FIFO not being
empty (TXFNE =
1
), refer to the Transmit Buffer and FIFO Operation section for more information - Controller aborts the data transaction by pulling the End-of-Data T-bit low (a Restart condition); Target sets the Abort Error ABEIF flag
The Controller sets the Maximum Read Length using the SETMRL (Set Maximum Read Length) CCC, which is stored in the I3CxMRL register. The firmware can choose to override this value by writing to the I3CxMRL register. The Controller can use the GETMRL (Get Maximum Read Length) CCC to read the value of the Maximum Read Length size stored in the I3CxMRL register.
The Private Read Transaction Flow is shown in Figure 37-48. The general frame format for Private Read Transaction is shown in Figure 37-49 and a pseudo-code is shown in Pseudo-code for Private Read Transaction.
- It is highly recommended for the firmware to write to the I3CxMRL register when there are no transactions happening on the bus. In the event of a race condition when the I3CxMRL register is being written by both firmware and hardware (SETMRL CCC), firmware writes will always have precedence.
- If the user firmware or DMA is writing data to the I3CxTXB register at a slower rate than the rate at which the Target is sending data to the Controller (bus speed), there is a possibility that the Transmit FIFO will become empty before the entire data stream is sent. In this scenario, the Target will pull the End-of-Data T-bit low and the transaction will end prematurely.
- It is recommended that the user check the Maximum Read Length value stored in I3CxMRL to properly prepare the Target to send data to the Controller.
- The user can override the Maximum
Read Length value and set I3CxMRL =
0
to send unlimited data bytes.
Pseudo-code for Private Read Transaction
uint8_t txData[SIZE]; void I3C1_Target_PrivateRead_Setup() { // Initialize data to send for(uint8_t i=0; i<SIZE; i++) { txData[i] = i; } // Validate Maximum Read Length if(I3C1MRL > SIZE || I3C1MRL == 0) { // 0=unlimited (16-bit value) I3C1MRL = SIZE; } // Default Private Read ACK setting I3C1CON0bits.ACKP = 0; // 0=ACK; 1=NACK I3C1CON1bits.ACKPOS = 0; // 0=One-shot disabled; 1=enabled } void I3C1_Target_PrivateRead() { uint8_t i = 0; while(i < SIZE) { // Wait for Tx Buffer to become empty while(!I3C1STAT0bits.TXBE); // Write data to Transmit buffer and increment pointer I3C1TXB = txData[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 MRL 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 main(void) { // Perform System and I3C Initialization SYSTEM_Initialize(); I3C1_Target_Setup(); // Private Read Setup I3C1_Target_PrivateRead_Setup(); while(1) { // Set one-shot of Private Read ACK if applicable I3C1CON1bits.ACKPOS = 1; // Check if Dynamic Address Match occured in Read mode if(I3C1PIR0bits.DADRIF && I3C1STAT0bits.RNW == 0b01) { I3C1_Target_PrivateRead(); } } }