i2c slave block transfer driver library

Dependents:   i2c_slave_block_example i2c_lora_slave

I2C block read/write slave

operates with I2C master using the i2c_smbus_read_i2c_block_data() and i2c_smbus_write_i2c_block_data() calls.

Tested with raspberry pi as master.
STM32Lx nucleo as slave.

signal pinmbed slaveRPi master
GND6
SCLD155
SDAD143
IRQany avail pinany avail pin

IRQ pin is implemented in application, not in this library. (see example)

Up to 32byte length per transfer.
Raspberry pi I2C doesnt support SMBUS block read, so I2C block transfers are supported here.
SMBUS block transfers are variable length. Instead, here in this driver, I2C block length is mapped to command byte by const array cmd_to_length[] (see example)

master write to slave

For i2c_smbus_write_i2c_block_data() from master, this driver lets the main loop on slave take the write request. The main loop on slave calls service_i2c(), which then calls service_i2c_write() upon each write from master. This occurs thru a circular buffer, permitting the slave to take its time doing the request, while the master can issue several back-to-back requests without delays.

clock stretching

For i2c_smbus_read_i2c_block_data(): Since raspberry pi doesnt support clock stretching out the the box, providing transmit data must be done in the interrupt service routine. fill_tx_buf() populates the transmit buffer to be sent to master, which must be done immediately because this occurs inside interrupt handler. If I2C master were to support clock stretching, then transmit buffer work could be done in main loop of slave.
/media/uploads/dudmuck/i2c_rpi_nucleo_sm_.png
An STM32 running at 32MHz is unlikely to operate with 400KHz I2C. Use 100KHz speed with 32MHz CPU, or use faster speed CPU for 400KHz I2C.

Committer:
Wayne Roberts
Date:
Thu Jan 24 17:22:37 2019 -0800
Revision:
2:ff709de859ed
Parent:
1:914409dc83b1
Child:
4:7ab789db70da
prevent denied transfer from being processed

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Wayne Roberts 0:20421a857bd5 1 #include <stdint.h>
Wayne Roberts 0:20421a857bd5 2 #include <stdbool.h>
Wayne Roberts 0:20421a857bd5 3
Wayne Roberts 0:20421a857bd5 4 #ifdef __cplusplus
Wayne Roberts 0:20421a857bd5 5 extern "C" {
Wayne Roberts 0:20421a857bd5 6 #endif
Wayne Roberts 0:20421a857bd5 7
Wayne Roberts 0:20421a857bd5 8 typedef enum {
Wayne Roberts 0:20421a857bd5 9 STATE_NONE = 0,
Wayne Roberts 0:20421a857bd5 10 STATE_CMD, // 1
Wayne Roberts 0:20421a857bd5 11 STATE_XFERING, // 2
Wayne Roberts 0:20421a857bd5 12 STATE_SEND_DONE, // 3
Wayne Roberts 0:20421a857bd5 13 } state_e;
Wayne Roberts 0:20421a857bd5 14
Wayne Roberts 0:20421a857bd5 15 int smbus_init(uint8_t slaveAddress);
Wayne Roberts 0:20421a857bd5 16
Wayne Roberts 0:20421a857bd5 17 #define _RX_BUF_SIZE 320
Wayne Roberts 0:20421a857bd5 18 typedef struct {
Wayne Roberts 0:20421a857bd5 19 uint8_t cbuf[_RX_BUF_SIZE];
Wayne Roberts 0:20421a857bd5 20 unsigned cbuf_in, cbuf_out;
Wayne Roberts 0:20421a857bd5 21 //TODO bool c_overrun;
Wayne Roberts 0:20421a857bd5 22
Wayne Roberts 0:20421a857bd5 23 uint8_t tx_buf[32];
Wayne Roberts 0:20421a857bd5 24 uint8_t tx_buf_len;
Wayne Roberts 0:20421a857bd5 25 } i2c_slave_t;
Wayne Roberts 0:20421a857bd5 26
Wayne Roberts 0:20421a857bd5 27
Wayne Roberts 0:20421a857bd5 28 extern i2c_slave_t i2c;
Wayne Roberts 0:20421a857bd5 29
Wayne Roberts 1:914409dc83b1 30 bool cmd_allowed(uint8_t); // return false if slave cannot take this cmd now
Wayne Roberts 2:ff709de859ed 31 void fill_tx_buf(uint8_t); //provided by application
Wayne Roberts 0:20421a857bd5 32
Wayne Roberts 0:20421a857bd5 33 void service_i2c(void);
Wayne Roberts 0:20421a857bd5 34 void service_i2c_write(uint8_t cmd, uint8_t len, const uint8_t* req); // provided by application
Wayne Roberts 0:20421a857bd5 35
Wayne Roberts 0:20421a857bd5 36 #ifdef __cplusplus
Wayne Roberts 0:20421a857bd5 37 }
Wayne Roberts 0:20421a857bd5 38 #endif