Skip to content
chuck todd edited this page Mar 20, 2018 · 2 revisions

Slave Mode

Observations:

The ESP32 does not stretch SCL. When the peripherals are configured for SLAVE Mode, data for transmission must be in the fifo before the Master device requests it. If a Master device requests 4 bytes of data from a ESP32 that is configured as SLAVE, and there are only 3 bytes in the txFifo, the ESP32 will send the three bytes of valid data then continue to send 0xFF as long as the master clocks SCL.

requestFrom() txEmpty Interrupts will be generated in the SLAVE Mode ESP32 both:

  • int_status.tx_send_empty whenever the contents of txFifo falls Below fifo_conf.nonfifo_tx_thres
  • int_status.tx_fifo_empty whenever the contents of txFifo is Equal or Below fifo_conf.tx_fifo_empty_thrhd

But, neither of these interrupt will cause SCL to be stretched. So data must be added to the txFifo before it is needed else 0xFF with be emitted.

I can envision a couple of methods to work with this limitation:

  • Trigger the onRequest() after the Master Read request, to fill the fifo for the next request. This would require a dummy read, then a full read of valid data. The dummy read equivalent to Wire.requestFrom(id,0); would trigger the SLAVE to flush it's txFifo, reload by calling onRequest().
  • Coordinate between a Master Write (Wire.onReceive()) and the Master Read (Wire.onRequest()). The Master Write would be considered a command that would trigger onRequest() to fill the txFifo with the 'requested' data. This method is similar to how most I2C devices work. A Write() command is issued to set an 'internal' device pointer. After the 'Write()' command completes, Wire.onReceive() then process the address pointer adjustment, then executes Wire.onRequest() which reloads the txFifo. This pre-staged data is now waiting for the 'Read()' operation. 'Read()' operations could be of infinite length, each time the txFifo reached its threshold values the onRequest() call-back would be executed to refill the txfifo.
  • Leave the txFifo empty which cause the peripheral to emit 0xFF, call onRequest(), hope the call returns soon enough to satisfy the Master, Personally I think this last idea is bonkers.

SLAVE MODE generates interrupts for Other Slave ID's

If a ESP32 is configured as SLAVE, the ISR will trigger during any Address NAK.

  • The ISR will receive a 0x400 (ack_err).
  • And 0x80 (trans_complete), Both Read and Write mode.

SLAVE MODE interrupt sequence when Address matches Programmed values.

  • 0x10 (slave_tran_comp), actually SLAVE_TRAN_START read or write can be detected by status_reg.slave_rw
    This interrupt is generated after the address match has occurred, and the first data byte is moving into or out of the fifo.
  • 0x02 (tx_fifo_empty) onRequest() if fifo_conf.tx_fifo_empty_thrhd is reached.
  • 0x01 (rx_fifo_full) onReceive() if fifo_conf.rx_fifo_full_thrhd is reached.
  • 0x400 (ack_err) an last byte during onRequest()
  • 0x80 (trans_complete) STOP signal