37.2.10.1 Private Write Transaction

In a Private Write Transfer, following the address header, the Controller continues to send 9-bit I3C Data Words (8-bit Data and a Parity T-bit). The data becomes available in the Receive FIFO, which feeds into the I3CxRXB Receive Buffer for the user to read through the firmware or DMA. The Controller can continue to send more data words and then end the transaction with a Stop or Restart, which is when the Transaction Complete TCOMPIF flag is set and the RNW status bits continue to hold the value until cleared by the user or overwritten in the next transaction.
The Receive FIFO in the Target continues to receive data until the Maximum Write Length (I3CxMWL register) has reached. If the Target continues to receive more data, the Maximum Write Length Overflow MWLOEIF and Receive Overrun RXOIF error flags are set, and any subsequent data are lost even if the Receive FIFO is not full. Refer to the Receive Buffer and FIFO Operation section for more information.

The Controller sets the Maximum Write Length using the SETMWL (Set Maximum Write Length) CCC, which is stored in the I3CxMWL register. The firmware can choose to override this value by writing to the I3CxMWL register. The Controller can use the GETMWL (Get Maximum Write Length) CCC to read the value of the Maximum Write Length size stored in the I3CxMWL register.

The Private Write Transaction Flow is shown in Figure 37-46. The general frame format for Private Write Transaction is shown in Figure 37-47 and a pseudo-code is shown in Pseudo-code for Private Write Transaction.

Important:
  1. It is highly recommended for the firmware to write to the I3CxMWL register when there are no transactions happening on the bus. In the event of a race condition when the I3CxMWL register is being written by both firmware and hardware (SETMWL CCC), firmware writes will always have precedence.
  2. If the user firmware or DMA is reading data from the I3CxRXB register at a slower rate than the rate at which the Target is receiving data from the Controller (bus speed), there is a possibility that the Receive FIFO becomes full. In this scenario, the Target will set the Receive Overrun RXOIF error flag, and any subsequent data are lost. Refer to the Receive Buffer and FIFO Operation section for more information.
Tip:
  1. It is recommended that the user check the Maximum Write Length value stored in I3CxMWL to properly prepare the Target to receive data from the Controller.
  2. The user can override the Maximum Write Length value and set I3CxMWL = 0 to receive unlimited data bytes.
Figure 37-46. Private Write Transaction Flow
Figure 37-47. Private Write Transfer Frame Format

Pseudo-code for Private Write Transaction

uint8_t rxData[SIZE];

void I3C1_Target_PrivateWrite_Setup()
{
    // Default Private Write ACK setting
    I3C1CON0bits.ACKP = 0;     // 0=ACK; 1=NACK
    I3C1CON1bits.ACKPOS = 0;   // 0=One-shot disabled; 1=enabled

    // Validate Maximum Write Length
    if(I3C1MWL > SIZE || I3C1MWL == 0) { // 0=unlimited (16-bit value)
        I3C1MWL = SIZE;
    }
}

void I3C1_Target_PrivateWrite()
{
    uint16_t i = 0;

    while(i < SIZE) {
        // Wait for data to become available in Rx Buffer
        while(!I3C1STAT0bits.RXBF);

        // Read data from Receive buffer and increment pointer
        rxData[i++] = I3C1RXB;

        // Perform error checking if desired
        // Check for Rx Overrun Error or Rx Read Error or maxWrLen overflow
        // if(I3C1ERRIR0bits.RXOIF || I3C1ERRIR1bits.RXREIF || I3C1ERRIR1bits.MWLOEIF) { ... }

        // Check for End of Transaction
        if(I3C1PIR1bits.TCOMPIF) {
            return 0;   // end of transaction
        }
    }
}

void main(void) {
    // Perform System and I3C Initialization
    SYSTEM_Initialize();
    I3C1_Target_Setup();

    // Private Write Setup
    I3C1_Target_PrivateWrite_Setup();

    while(1) {
        // Set one-shot of Private Write ACK if applicable
        I3C1CON1bits.ACKPOS = 1;

        // Check if Dynamic Address Match occured in Write mode
        if(I3C1PIR0bits.DADRIF && I3C1STAT0bits.RNW == 0b10) {
            I3C1_Target_PrivateWrite();
        }
    }
}