diff options
author | barthess <barthess@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2011-02-10 16:35:28 +0000 |
---|---|---|
committer | barthess <barthess@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2011-02-10 16:35:28 +0000 |
commit | eafaa7d6cfafb767ddf58caba640d63f418c5af6 (patch) | |
tree | d9052ace217210266c692a0417b2c52853a97dab | |
parent | c2d458110ccf32fd9c28850f5c953e12e4ef9b2c (diff) | |
download | ChibiOS-eafaa7d6cfafb767ddf58caba640d63f418c5af6.tar.gz ChibiOS-eafaa7d6cfafb767ddf58caba640d63f418c5af6.tar.bz2 ChibiOS-eafaa7d6cfafb767ddf58caba640d63f418c5af6.zip |
I2C. 10-bit slave addressing done. Not tested at all.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2729 35acf78f-673a-0410-8e92-d51de3d6d3f4
-rw-r--r-- | os/hal/include/i2c.h | 18 | ||||
-rw-r--r-- | os/hal/platforms/STM32/i2c_lld.c | 63 |
2 files changed, 55 insertions, 26 deletions
diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 5a85ed5f7..5f4b2cc6f 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -71,14 +71,16 @@ * @brief Driver state machine possible states.
*/
typedef enum {
- I2C_UNINIT = 0, /**< Not initialized. */
- I2C_STOP = 1, /**< Stopped. */
- I2C_READY = 2, /**< Ready. */
- I2C_MACTIVE = 3, /**< START condition sent. */
- I2C_MTRANSMIT = 4, /**< Master transmitting. */
- I2C_MRECEIVE = 5, /**< Master receiving. */
- I2C_MWAIT_TF = 6, /**< Master wait Transmission Finished */
- I2C_MERROR = 7 /**< Error condition. */
+ I2C_UNINIT = 0, /**< Not initialized. */
+ I2C_STOP = 1, /**< Stopped. */
+ I2C_READY = 2, /**< Ready. Start condition generated. */
+ I2C_MACTIVE = 3, /**< I2C configured and waiting start cond. */
+ I2C_10BIT_HANDSHAKE = 4, /**< 10-bit address sending */
+ I2C_MWAIT_ADDR_ACK = 5, /**< Waiting ACK on address sending. */
+ I2C_MTRANSMIT = 6, /**< Master transmitting. */
+ I2C_MRECEIVE = 7, /**< Master receiving. */
+ I2C_MWAIT_TF = 8, /**< Master wait Transmission Finished */
+ I2C_MERROR = 9 /**< Error condition. */
} i2cstate_t;
#include "i2c_lld.h"
diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 68e42972c..aecb1d24d 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -110,32 +110,59 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { int n = 0; int m = 0; + /* In 10-bit addressing mode, + – To enter Transmitter mode, a master sends the header (11110xx0) and then the + slave address, (where xx denotes the two most significant bits of the address). + – To enter Receiver mode, a master sends the header (11110xx0) and then the + slave address. Then it should send a repeated Start condition followed by the + header (11110xx1), (where xx denotes the two most significant bits of the + address). + The TRA bit indicates whether the master is in Receiver or Transmitter mode.*/ + if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// start bit sent i2cp->id_state = I2C_MACTIVE; - /*TODO: 10 bit address handling - In 10-bit addressing mode, - – To enter Transmitter mode, a master sends the header (11110xx0) and then the - slave address, (where xx denotes the two most significant bits of the address). - – To enter Receiver mode, a master sends the header (11110xx0) and then the - slave address. Then it should send a repeated Start condition followed by the - header (11110xx1), (where xx denotes the two most significant bits of the - address). - The TRA bit indicates whether the master is in Receiver or Transmitter mode.*/ - - i2cp->id_i2c->DR = (i2cp->id_slave_config->address << 1) | - i2cp->id_slave_config->rw_bit; // write slave address in DR + + if(!(i2cp->id_slave_config->address & 0x8000)){ // slave address is 7-bit + i2cp->id_i2c->DR = ((i2cp->id_slave_config->address & 0x7F) << 1) | + i2cp->id_slave_config->rw_bit; + i2cp->id_state = I2C_MWAIT_ADDR_ACK; + return; + } + else{ // slave address is 10-bit + i2cp->id_state = I2C_10BIT_HANDSHAKE; + // send MSB with header. LSB = 0. + i2cp->id_i2c->DR = ((i2cp->id_slave_config->address >> 7) & 0x6) | 0xF0; + return; + } + } + + // "wait" interrupt with ADD10 flag + if ((i2cp->id_state == I2C_10BIT_HANDSHAKE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADD10)){ + i2cp->id_i2c->DR = i2cp->id_slave_config->address & 0x00FF; // send remaining bits of address + if (!(i2cp->id_slave_config->rw_bit)) + // in transmit mode there is nothing to do with 10-bit handshaking + i2cp->id_state = I2C_MWAIT_ADDR_ACK; return; } - if ((i2cp->id_state == I2C_MACTIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADD10)){// header sent + // "wait" interrupt with ADDR + if ((i2cp->id_state == I2C_10BIT_HANDSHAKE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address ACKed + i2cp->id_i2c->CR1 |= I2C_CR1_START; + return; + } + if ((i2cp->id_state == I2C_10BIT_HANDSHAKE) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// restart generated + // send MSB with header. LSB = 1 + i2cp->id_i2c->DR = ((i2cp->id_slave_config->address >> 7) & 0x6) | 0xF1; + i2cp->id_state = I2C_MWAIT_ADDR_ACK; + return; } - // "wait" interrupt with ADDR flag - if ((i2cp->id_state == I2C_MACTIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address successfully sent - if(i2cp->id_i2c->SR2 & I2C_SR2_TRA){ - i2c_lld_txbyte(i2cp); // send first byte + // "wait" interrupt with ADDR (ADD10 in 10-bit receiver mode) flag + if ((i2cp->id_state == I2C_MWAIT_ADDR_ACK) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR & I2C_SR1_ADD10)){// address ACKed + if(i2cp->id_i2c->SR2 & I2C_SR2_TRA){// I2C is transmitting data i2cp->id_state = I2C_MTRANSMIT; // change state + i2c_lld_txbyte(i2cp); // send first byte return; } else { @@ -145,7 +172,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { */ if (i2cp->id_slave_config->rxbytes > 1) i2cp->id_i2c->CR1 |= I2C_CR1_ACK; // set ACK bit - i2cp->id_state = I2C_MRECEIVE; // change status + i2cp->id_state = I2C_MRECEIVE; // change state return; } } |