0b01
), the Controller can communicate to the Target
directly by specifying the Target’s Dynamic Address. The Controller uses a Private
Write Transfer to write data to the Target directly and a Private Read
Transfer to read data from the Target directly.0
’ (write) for Private Write
Transfer and ‘1
’ (read) for Private Read Transfer. If the Dynamic
Address in the address header matches with the Target’s Dynamic Address in the I3CxDADR
register, the Target ACKs the request and sets the DADRIF interrupt flag bit. The RNW status bits are also set according to the R/W
bit in the address header(2). The Target NACKs the request if the Dynamic Address in
the address header does not match the address in I3CxDADR register.In Private Write Transfer, following the address header, the Controller will continue to send 9-bit I3C Data Words (8-bit Data and a Parity T-bit). The data becomes available for the user to read from the I3CxRXB Receive Buffer. The Controller can continue to send data until it reaches the maximum data write length specified in the I3CxMWL register, and then ends the transaction with a Stop or Restart. The Controller determines the maximum data write length by using the SETMWL CCC. The Controller can read back this data using the GETMWL CCC.
The Private Write Transaction Flow is shown in Figure 1. The general frame format for Private Write Transaction is shown in Figure 2 and a pseudo-code is shown in Pseudo-code for Private Write Transaction below.
0
) using the T-bit indicating to the Controller to end
the transaction. The Controller can also choose to abort the transaction by asserting
the T-bit (End-of-Data = 0
), which is equivalent to a Restart condition
on the bus, represented through the RSCIF interrupt flag. (Refer to Transition Bit (T-Bit) for more details.)Before sending any data, it is recommended to check the maximum data read length that the Controller will accept by reading the value in the I3CxMRL register. The Controller determines the maximum data read length, if possible, by using the SETMRL CCC. The Controller can read back this data using the GETMRL CCC.
The Private Read Transaction Flow is shown in Figure 3. The general frame format for Private Read Transaction is shown in Figure 4 and a pseudo-code is shown in Pseudo-code for Private Read Transaction below.
0b00
.uint8_t rxData[SIZE];
uint8_t I3C1_Target_PrivateWrite()
{
uint16_t i = 0;
// Check Target's operating mode first
if(I3C1STATbits.OPMD != 0b01) {
return 1; // Target is operating in I2C mode, abort
}
// Check if Dynamic Address Match occured in Write mode
if(!I2C1STATbits.DADRIF || !I3C1STATbits.RNW == 0b10) {
return 1; // abort if no dynamic address match or Read mode
}
while(i < SIZE) {
// Wait for data to become available in Rx Buffer
while(!I3C1STATbits.RXBF);
// Read data from Receive buffer and increment pointer
rxData[i++] = I3C1RXB;
// Check if maxWrLen overflow
if(I3C1ERRIR1bits.MWLOEIF) {
// Controller has exceeded Max Write Length
// Take appropriate action
}
// Perform error checking if desired
// Check for Rx Overrun Error or Rx Read Error
// if(I3C1ERRIR0bits.RXOIF || I3C1ERRIR1bits.RXREIF) { ... }
// Check for Stop or Restart for End of Transaction
if(I3C1PIR0bits.PCIF || I3C1PIR0bits.RSCIF || I3C1PIR1bits.TCOMPIF) {
return 0; // end of transaction with successful write
}
}
// Code execution reaches here when rxData[] is full
// Wait for Stop or Restart for End of Transaction
while(!I3C1PIR0bits.PCIF && !I3C1PIR0bits.RSCIF && !I3C1PIR1bits.TCOMPIF) {
// While waiting, check for additional errors (optional)
// if(I3C1ERRIR1bits.MWLOEIF || I3C1ERRIR0bits.RXOIF || I3C1ERRIR1bits.RXREIF) { ... }
}
return 1; // end of transaction with possible data overflow
}
uint8_t txData[SIZE];
uint8_t I3C1_Target_PrivateRead()
{
uint16_t i = 0;
// Check Target's operating mode first
if(I3C1STATbits.OPMD != 0b01) {
return 1; // Target is operating in I2C mode, abort
}
// Check if Dynamic Address Match occured in Read mode
if(!I2C1STATbits.DADRIF || !I3C1STATbits.RNW == 0b01) {
return 1; // abort if no dynamic address match or Write mode
}
while(i < SIZE) {
// Wait for Tx Buffer to become empty
while(!I3C1STATbits.TXBE);
// Write data to Transmit buffer and increment pointer
I3C1TXB = txData[i++];
// Check if maxRdLen overflow
if(i >= I3C1MRL) {
// Software has exceeded Max Read Length 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 abort (possibly premature)
if(I3C1PIR0bits.PCIF || I3C1PIR0bits.RSCIF || I3C1PIR1bits.TCOMPIF) {
return 1; // end of transaction with Controller abort
}
}
// Code execution reaches here when all data from txData[] has been sent
// Wait for Stop or Restart for End of Transaction
while(!I3C1PIR0bits.PCIF && !I3C1PIR0bits.RSCIF && !I3C1PIR1bits.TCOMPIF) {
// While waiting, check for additional errors (optional)
// if(I3C1ERRIR0bits.TXUIF || I3C1ERRIR1bits.TXWEIF) { ... }
}
return 0; // end of transaction with possible data underflow
}