aboutsummaryrefslogtreecommitdiffstats
path: root/libmaple/i2c.c
diff options
context:
space:
mode:
authorBarry Carter <barry.carter@robotfuzz.com>2012-09-04 22:24:25 +0100
committerBarry Carter <barry.carter@robotfuzz.com>2012-09-04 22:24:25 +0100
commit576457f5477597c3bc88f06cbae01c01a459c32e (patch)
tree1d06cf1099407f98ef243cf56d1bc40af29574e4 /libmaple/i2c.c
parentef5c4b9f30da2f4b9a0edd4231e95b3ef8a88d43 (diff)
downloadlibrambutan-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>
Diffstat (limited to 'libmaple/i2c.c')
-rw-r--r--libmaple/i2c.c40
1 files changed, 35 insertions, 5 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;