fn start_read_operation(
        &self,
        address: I2cAddress,
        buffer: &mut [u8],
        start: bool,
        will_continue: bool,
        stop: bool,
        deadline: Deadline,
    ) -> Result<Option<Instant>, Error> {
        // We don't support single I2C reads larger than the FIFO. This should be
        // enforced by `VariableChunkIterMut` used in `Driver::read` and
        // `Driver::read_async`.
        debug_assert!(buffer.len() <= I2C_FIFO_SIZE);

        let cmd_iterator = &mut self.regs().comd_iter();

        self.setup_read(address, buffer, start, will_continue, cmd_iterator)?;

        if stop {
            add_cmd(cmd_iterator, Command::Stop)?;
        } else {
            add_cmd(cmd_iterator, Command::End)?;
        }
        self.start_transmission();
        let deadline = deadline.start(buffer.len() + start as usize);

        Ok(deadline)
    }
Executes an I2C read operation.
- `addr` is the address of the slave device.
- `buffer` is the buffer to store the read data.
- `start` indicates whether the operation should start by a START
condition and sending the address.
- `stop` indicates whether the operation should end with a STOP
condition.
- `will_continue` indicates whether there is another read operation
following this one and we should not nack the last byte.
- `cmd_iterator` is an iterator over the command registers.
esp-hal/src/i2c/master/mod.rs