diff options
author | Barry Carter <barry.carter@robotfuzz.com> | 2012-09-04 22:24:25 +0100 |
---|---|---|
committer | Barry Carter <barry.carter@robotfuzz.com> | 2012-09-04 22:24:25 +0100 |
commit | 576457f5477597c3bc88f06cbae01c01a459c32e (patch) | |
tree | 1d06cf1099407f98ef243cf56d1bc40af29574e4 | |
parent | ef5c4b9f30da2f4b9a0edd4231e95b3ef8a88d43 (diff) | |
download | librambutan-576457f5477597c3bc88f06cbae01c01a459c32e.tar.gz librambutan-576457f5477597c3bc88f06cbae01c01a459c32e.zip |
I2C slave support cleanups.
Added fix for corner case where badly behaving master doesn't NACK and we don't get the callbacks fires.
Removed my own name from several places and added attribution to the correct place.
Updated include comments to reference the fact it now supports I2C slave
Signed-off-by:- Barry Carter <barry.carter@gmail.com>
-rw-r--r-- | libmaple/i2c.c | 40 | ||||
-rw-r--r-- | libmaple/include/libmaple/i2c.h | 13 | ||||
-rw-r--r-- | libmaple/include/libmaple/i2c_common.h | 2 |
3 files changed, 46 insertions, 9 deletions
diff --git a/libmaple/i2c.c b/libmaple/i2c.c index b8e622d..6c609d9 100644 --- a/libmaple/i2c.c +++ b/libmaple/i2c.c @@ -28,9 +28,11 @@ /** * @file libmaple/i2c.c * @author Perry Hung <perry@leaflabs.com> + * @author Barry Carter <barry.carter@gmail.com> * @brief Inter-Integrated Circuit (I2C) support. * - * Currently, only master mode is supported. + * Master and Slave supported + * Slave code added Barry Carter 2012 */ #include "i2c_private.h" @@ -218,6 +220,26 @@ void i2c_master_enable(i2c_dev *dev, uint32 flags) { dev->state = I2C_STATE_IDLE; } +/** + * @brief Initialize an I2C device as slave (and master) + * @param dev Device to enable + * @param flags Bitwise or of the following I2C options: + * I2C_FAST_MODE: 400 khz operation, + * I2C_DUTY_16_9: 16/9 Tlow/Thigh duty cycle (only applicable for + * fast mode), + * I2C_BUS_RESET: Reset the bus and clock out any hung slaves on + * initialization, + * I2C_10BIT_ADDRESSING: Enable 10-bit addressing, + * I2C_REMAP: (deprecated, STM32F1 only) Remap I2C1 to SCL/PB8 + * SDA/PB9. + * I2C_SLAVE_DUAL_ADDRESS: Slave can respond on 2 i2C addresses + * I2C_SLAVE_GENERAL_CALL: SLA+W broadcast to all general call + * listeners on bus. Addr 0x00 + * I2C_SLAVE_USE_RX_BUFFER: Use a buffer to receive the incoming + * data. Callback at end of recv + * I2C_SLAVE_USE_TX_BUFFER: Use a buffer to transmit data. + * Callback will be called before tx + */ void i2c_slave_enable(i2c_dev *dev, uint32 flags) { i2c_disable(dev); i2c_master_enable(dev, dev->config_flags | flags); @@ -322,11 +344,10 @@ void _i2c_irq_handler(i2c_dev *dev) { */ dev->timestamp = systick_uptime(); - /* Add Slave support - * Barry Carter 2012 - * barry.carter@gmail.com + /* + * Add Slave support */ - + /* Check to see if MSL master slave bit is set */ if ((sr2 & I2C_SR2_MSL) != I2C_SR2_MSL) { /* 0 = slave mode 1 = master */ @@ -459,6 +480,15 @@ void _i2c_irq_handler(i2c_dev *dev) { /* The callback with the data will happen on a NACK of the last data byte. * This is handled in the error IRQ (AF bit) */ + /* Handle the case where the master misbehaves by sending no NACK */ + if (dev->state != I2C_STATE_IDLE) { + if (dev->state == I2C_STATE_SL_RX) { + if (dev->i2c_slave_recv_callback != NULL) (*(dev->i2c_slave_recv_callback))(dev->i2c_slave_msg); + } + else { + if (dev->i2c_slave_transmit_callback != NULL) (*(dev->i2c_slave_transmit_callback))(dev->i2c_slave_msg); + } + } } sr1 = sr2 = 0; diff --git a/libmaple/include/libmaple/i2c.h b/libmaple/include/libmaple/i2c.h index d4eac61..5a9da58 100644 --- a/libmaple/include/libmaple/i2c.h +++ b/libmaple/include/libmaple/i2c.h @@ -29,12 +29,19 @@ * @file libmaple/include/libmaple/i2c.h * @brief Inter-Integrated Circuit (I2C) peripheral support * - * Currently master-only. Usage notes: + * Supports Master and Slave. + * Master Usage notes: * * - Enable an I2C device with i2c_master_enable(). * - Initialize an array of struct i2c_msg to suit the bus * transactions (reads/writes) you wish to perform. * - Call i2c_master_xfer() to do the work. + * + * Slave Usage notes: + * - Enable I2C slave by calling i2c_slave_enable(). + * Check flags for usage. Enabling master also enabled slave. + * - initialise the i2c_msg struct and the data buffer + * - initialise the callback functions */ #ifndef _LIBMAPLE_I2C_H_ @@ -201,7 +208,7 @@ typedef struct i2c_msg { #define I2C_SLAVE_USE_RX_BUFFER 0x10 // Use a buffered message when doing a slave recv #define I2C_SLAVE_USE_TX_BUFFER 0x20 // Use a buffered message when doing a slave transmit #define I2C_SLAVE_DUAL_ADDRESS 0x40 // Enable the dual slave address scheme -#define I2C_SLAVE_GENERAL_CALL 0x80 // Enable the dual slave address scheme +#define I2C_SLAVE_GENERAL_CALL 0x80 // Enable the general call on address 0x00 void i2c_master_enable(i2c_dev *dev, uint32 flags); #define I2C_ERROR_PROTOCOL (-1) @@ -411,7 +418,7 @@ static inline void i2c_set_trise(i2c_dev *dev, uint32 trise) { dev->regs->TRISE = trise; } -/* Barry Carter +/* * Slave support */ diff --git a/libmaple/include/libmaple/i2c_common.h b/libmaple/include/libmaple/i2c_common.h index 5debcb8..93e17e2 100644 --- a/libmaple/include/libmaple/i2c_common.h +++ b/libmaple/include/libmaple/i2c_common.h @@ -93,7 +93,7 @@ typedef struct i2c_dev { volatile i2c_state state; /**< Device state */ uint32 config_flags; /**< Configuration flags */ - /* Barry Carter + /* * Slave implementation. Callback functions in this struct allow * for a separate callback function for each I2C unit available onboard */ |