aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbarthess <barthess@35acf78f-673a-0410-8e92-d51de3d6d3f4>2011-01-30 23:28:02 +0000
committerbarthess <barthess@35acf78f-673a-0410-8e92-d51de3d6d3f4>2011-01-30 23:28:02 +0000
commit25d42f8b9061f28f553e42afd0d7835a47bbb9c3 (patch)
tree392760f5bb19c9896f77185138958cd86390c240
parent47cd88dcc6eba547ffadbea2981ddc8a6729a15a (diff)
downloadChibiOS-25d42f8b9061f28f553e42afd0d7835a47bbb9c3.tar.gz
ChibiOS-25d42f8b9061f28f553e42afd0d7835a47bbb9c3.tar.bz2
ChibiOS-25d42f8b9061f28f553e42afd0d7835a47bbb9c3.zip
I2C. Master receiving and master trasmitting written. Needs testing and debugging.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2699 35acf78f-673a-0410-8e92-d51de3d6d3f4
-rw-r--r--os/hal/platforms/STM32/i2c_lld.c127
-rw-r--r--os/hal/platforms/STM32/i2c_lld.h19
2 files changed, 73 insertions, 73 deletions
diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c
index d092d66d4..9d655c68d 100644
--- a/os/hal/platforms/STM32/i2c_lld.c
+++ b/os/hal/platforms/STM32/i2c_lld.c
@@ -40,7 +40,7 @@ I2CDriver I2CD2;
*
* @return The error flags.
*/
-static i2cflags_t translate_errors(uint16_t sr) {
+static i2cflags_t translate_i2c_errors(uint16_t sr) {
i2cflags_t sts = 0;
if (sr & USART_SR_ORE)
@@ -58,13 +58,54 @@ static i2cflags_t translate_errors(uint16_t sr) {
static void i2c_serve_error_interrupt(I2CDriver *i2cp) {
- // TODO:remove this stub
- //simply trap for errors
+ // TODO:remove this stub and write normal handler
+ // this is simply trap for errors
while TRUE{
- translate_errors(i2cp->id_i2c->SR1);
+ translate_i2c_errors(i2cp->id_i2c->SR1);
}
}
+/* This function handle all regular interrupt conditions
+ *
+ */
+static void i2c_serve_event_interrupt(I2CDriver *i2cp) {
+
+ if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// start bit sent
+ i2cp->id_state = I2C_MACTIVE;
+ i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) |
+ i2cp->id_slave_config->rw_bit; // write slave address in DR
+ }
+
+ // now "wait" interrupt with ADDR flag
+ // TODO: 10 bit address handling here
+ if ((i2cp->id_state == I2C_MACTIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address successfully sent
+ if(i2cp->id_slave_config->rw_bit == I2C_WRITE){
+ i2c_lld_txbyte(i2cp); // send first byte
+ i2cp->id_state = I2C_MTRANSMIT; // change state
+ }
+ else {
+ i2c_lld_rxbyte(i2cp); // read first byte
+ i2cp->id_state = I2C_MRECEIVE; // change status
+ }
+ }
+
+ // transmitting bytes one by one
+ if ((i2cp->id_state == I2C_MTRANSMIT) && (i2cp->id_i2c->SR1 & I2C_SR1_TXE)){
+ if (i2c_lld_txbyte(i2cp))
+ i2cp->id_state = I2C_MWAIT_TF; // last byte written
+ }
+
+ //receiving bytes one by one
+ if ((i2cp->id_state == I2C_MRECEIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_RXNE)){
+ if (i2c_lld_txbyte(i2cp))
+ i2cp->id_state = I2C_MWAIT_TF; // last byte read
+ }
+
+ // "wait" BTF bit in status register
+ if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){
+ i2cp->id_slave_config->id_callback(i2cp, i2cp->id_slave_config);
+ }
+}
#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__)
@@ -239,10 +280,14 @@ bool_t i2c_lld_rxbyte(I2CDriver *i2cp) {
#define rxbuf i2cp->id_slave_config->rxbuf
#define rxbufhead i2cp->id_slave_config->rxbufhead
#define rxdepth i2cp->id_slave_config->rxdepth
+ #define rxbytes i2cp->id_slave_config->rxbytes
if (rxbufhead < rxdepth){
rxbuf[rxbufhead] = i2cp->id_i2c->DR;
rxbufhead++;
+ if ((rxbytes - rxbufhead) == 1)
+ // clear ACK bit for automatically send NACK
+ i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK);
return(FALSE);
}
@@ -250,61 +295,18 @@ bool_t i2c_lld_rxbyte(I2CDriver *i2cp) {
#undef rxbuf
#undef rxbufhead
#undef rxdepth
+ #undef rxbytes
return(TRUE); // last byte read
}
-/* This function handle all regular interrupt conditions
- *
- */
-static void i2c_serve_event_interrupt(I2CDriver *i2cp) {
-
- if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// start bit sent
- i2cp->id_state = I2C_MACTIVE;
- i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) |
- i2cp->id_slave_config->rw_bit; // write slave address in DR
- }
-
- // now "wait" interrupt with ADDR flag
- // TODO: 10 bit address handling here
- // TODO: setup here transmission via DMA like in ADC
- if ((i2cp->id_state == I2C_MACTIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address successfully sent
- if(i2cp->id_slave_config->rw_bit == I2C_WRITE){
- i2c_lld_txbyte(i2cp); // send first byte
- i2cp->id_state = I2C_MTRANSMIT; // change state
- }
- else {
- i2c_lld_rxbyte(i2cp); // read first byte
- i2cp->id_state = I2C_MRECEIVE; // change stat
- }
- }
-
- // transmitting bytes one by one
- if ((i2cp->id_state == I2C_MTRANSMIT) && (i2cp->id_i2c->SR1 & I2C_SR1_TXE)){
- if (i2c_lld_txbyte(i2cp))
- i2cp->id_state = I2C_MWAIT_TF; // last byte written
- }
-
- //receiving bytes one by one
- if ((i2cp->id_state == I2C_MRECEIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_RXNE)){
- if (i2c_lld_txbyte(i2cp))
- i2cp->id_state = I2C_MWAIT_TF; // last byte read
- }
+void i2c_lld_master_start(I2CDriver *i2cp){
+ i2cp->id_i2c->CR1 |= I2C_CR1_START;
+}
- // "wait" BTF bit in status register
- if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){
- if (i2cp->id_slave_config->restart){ // restart need
- i2cp->id_state = I2C_MACTIVE;
- //i2cp->id_i2c->CR1 |= I2C_CR1_START; // send restart
- i2cp->id_slave_config->id_restart_callback(i2cp, i2cp->id_slave_config); // callback call
- }
- else {
- i2cp->id_state = I2C_READY;
- i2cp->id_i2c->CR1 |= I2C_CR1_STOP; // stop communication
- i2cp->id_slave_config->id_stop_callback(i2cp, i2cp->id_slave_config); // callback call
- }
- }
+void i2c_lld_master_stop(I2CDriver *i2cp){
+ i2cp->id_i2c->CR1 |= I2C_CR1_STOP;
}
@@ -314,9 +316,8 @@ void i2c_lld_master_transmitI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){
i2cp->id_slave_config = i2cscfg;
i2cp->id_slave_config->rw_bit = I2C_WRITE;
-
- // generate start condition. Later transmission goes asynchronously
- i2cp->id_i2c->CR1 |= I2C_CR1_START;
+ // generate start condition. Later transmission goes in background
+ i2c_lld_master_start(i2cp);
}
void i2c_lld_master_receiveI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){
@@ -325,19 +326,14 @@ void i2c_lld_master_receiveI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){
i2cp->id_slave_config = i2cscfg;
i2cp->id_slave_config->rw_bit = I2C_READ;
- // reset restart flag
- i2cp->id_slave_config->restart = FALSE;
-
// generate (re)start condition. Later connection goes asynchronously
- i2cp->id_i2c->CR1 |= I2C_CR1_START;
- // TODO: need to clear ACK bit somewhere
+ i2c_lld_master_start(i2cp);
}
/**
- * @brief Transmits data ever the I2C bus as master.
- * TODO:@details
+ * @brief Transmits data ever the I2C bus as masteri2cp.
*
* @param[in] i2cp pointer to the @p I2CDriver object
* @param[in] i2cscfg pointer to the @p I2CSlaveConfig object
@@ -384,10 +380,9 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t re
}
}
else i2cp->id_i2c->CR1 |= I2C_CR1_STOP; // generate stop condition
-
-
}
+
/**
* @brief Receives data from the I2C bus.
* @details Before receive data from I2C slave you must manually sent them some
@@ -432,4 +427,6 @@ void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) {
chSysUnlock();
}
+
+
#endif // HAL_USE_I2C
diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h
index 1b684a167..bac1dfff0 100644
--- a/os/hal/platforms/STM32/i2c_lld.h
+++ b/os/hal/platforms/STM32/i2c_lld.h
@@ -90,17 +90,21 @@ typedef struct I2CSlaveConfig I2CSlaveConfig;
/**
* @brief I2C notification callback type.
+ * @details This function must be used to send start or stop events to I2C bus,
+ * and change states of I2CDriver.
*
- * @param[in] i2cp FIXME: pointer to the @p I2CDriver object triggering the
+ * @param[in] i2cp pointer to the @p I2CDriver object triggering the
+ * callback
+ * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object triggering the
* callback
*/
typedef void (*i2ccallback_t)(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg);
-//typedef void (*i2ccallback_t)(void);
+
/**
* @brief I2C error notification callback type.
*
- * @param[in] i2cp FIXME: pointer to the @p I2CDriver object triggering the
+ * @param[in] i2cp TODO: pointer to the @p I2CDriver object triggering the
* callback
*/
typedef void (*i2cerrorcallback_t)(void);
@@ -143,8 +147,7 @@ struct I2CSlaveConfig{
* by DMA buffer events
* @p NULL then the callback is disabled.
*/
- i2ccallback_t id_stop_callback;
- i2ccallback_t id_restart_callback;
+ i2ccallback_t id_callback;
/**
* @brief Callback pointer.
* @note TODO: I don't know, when this callback is inwoked
@@ -242,17 +245,17 @@ extern "C" {
void i2c_lld_init(void);
void i2c_lld_start(I2CDriver *i2cp);
void i2c_lld_stop(I2CDriver *i2cp);
-void i2c_lld_master_start(I2CDriver *i2cp, uint16_t header);
+
+void i2c_lld_master_start(I2CDriver *i2cp);
void i2c_lld_master_stop(I2CDriver *i2cp);
void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart);
-bool_t i2c_lld_txbyte(I2CDriver *i2cp); // helper function
void i2c_lld_master_transmitI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg);
+bool_t i2c_lld_txbyte(I2CDriver *i2cp); // helper function
void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg);
void i2c_lld_master_receiveI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg);
bool_t i2c_lld_rxbyte(I2CDriver *i2cp);
-//static i2cflags_t translate_errors(uint16_t sr);
#ifdef __cplusplus
}