diff --git a/conf/autopilot/lisa_test_progs.makefile b/conf/autopilot/lisa_test_progs.makefile index 694707ab39..b6f29d928c 100644 --- a/conf/autopilot/lisa_test_progs.makefile +++ b/conf/autopilot/lisa_test_progs.makefile @@ -182,7 +182,7 @@ test_baro.CFLAGS += -I$(SRC_LISA) -I$(SRC_BOARD) test_baro.srcs += $(SRC_BOARD)/test_baro.c test_baro.srcs += $(SRC_BOARD)/baro_board.c test_baro.CFLAGS += -DUSE_I2C2 -test_baro.srcs += mcu_periph/i2c.c $(SRC_ARCH)/mcu_periph/i2c_arch.c +test_baro.srcs += mcu_periph/i2c.c $(SRC_ARCH)/mcu_periph/i2c_arch.rewritten.c # diff --git a/sw/airborne/arch/stm32/mcu_periph/i2c_arch.h b/sw/airborne/arch/stm32/mcu_periph/i2c_arch.h index 50519ea24c..159ef2c360 100644 --- a/sw/airborne/arch/stm32/mcu_periph/i2c_arch.h +++ b/sw/airborne/arch/stm32/mcu_periph/i2c_arch.h @@ -29,8 +29,7 @@ #define I2C_HW_H #include "mcu_periph/i2c.h" -#include - +#include #ifdef USE_I2C1 diff --git a/sw/airborne/arch/stm32/mcu_periph/i2c_arch.rewritten.c b/sw/airborne/arch/stm32/mcu_periph/i2c_arch.rewritten.c index 09f19ff27d..2da4cd09de 100644 --- a/sw/airborne/arch/stm32/mcu_periph/i2c_arch.rewritten.c +++ b/sw/airborne/arch/stm32/mcu_periph/i2c_arch.rewritten.c @@ -1,9 +1,9 @@ #include "mcu_periph/i2c.h" -#include -#include -#include -#include +#include +#include +#include +#include //#define I2C_DEBUG_LED @@ -62,6 +62,8 @@ static inline void LED_ERROR(uint8_t base, uint8_t nr) ////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// +/* Not used in libopencm3 implementation. Keeping commented for reference. */ +#if 0 #ifdef USE_I2C1 static I2C_InitTypeDef I2C1_InitStruct = { .I2C_Mode = I2C_Mode_I2C, @@ -84,6 +86,10 @@ static I2C_InitTypeDef I2C2_InitStruct = { .I2C_ClockSpeed = 300000 }; #endif +#endif + +#define I2C1_CLOCK_SPEED 40000 +#define I2C2_CLOCK_SPEED 30000 ////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// @@ -94,6 +100,9 @@ static I2C_InitTypeDef I2C2_InitStruct = { // Referring to STM32 manual: // -Doc ID 13902 Rev 11 +/* This macros are defined in libopencm3 already. Keeping commented for reference. */ + +#if 0 // Status Register 1 #define I2C_SR1_BIT_SB (1<<0) // Start Condition Met @@ -130,11 +139,27 @@ static I2C_InitTypeDef I2C2_InitStruct = { #define I2C_CR2_BIT_ITEVTEN (1<<9) // Event Interrupt #define I2C_CR2_BIT_ITBUFEN (1<<10) // Buffer Interrupt +#endif + +// Error bit mask +// XXX: consider moving this define into libopencm3 +#define I2C_SR1_ERR_MASK (I2C_SR1_SMBALERT | \ + I2C_SR1_TIMEOUT | \ + I2C_SR1_PECERR | \ + I2C_SR1_OVR | \ + I2C_SR1_AF | \ + I2C_SR1_ARLO | \ + I2C_SR1_BERR) // Bit Control #define BIT_X_IS_SET_IN_REG(X,REG) (((REG) & (X)) == (X)) +// disable and enable irq functions are not implemented in libopencm3 defining them here +// XXX: consider moving this definitions into libopencm3 +static inline void __disable_irq(void) { asm volatile ("cpsid i"); } +static inline void __enable_irq(void) { asm volatile ("cpsie i"); } + // Critical Zones #define __I2C_REG_CRITICAL_ZONE_START __disable_irq(); @@ -265,10 +290,10 @@ static inline void LED_SHOW_ACTIVE_BITS(I2C_TypeDef *regs) } #endif -static inline void PPRZ_I2C_SEND_STOP(I2C_TypeDef *regs) +static inline void PPRZ_I2C_SEND_STOP(u32 i2c) { // Man: p722: Stop generation after the current byte transfer or after the current Start condition is sent. - regs->CR1 |= I2C_CR1_BIT_STOP; + I2C_CR1(i2c) |= I2C_CR1_STOP; #ifdef I2C_DEBUG_LED LED2_ON(); @@ -282,7 +307,7 @@ static inline void PPRZ_I2C_SEND_STOP(I2C_TypeDef *regs) static inline void PPRZ_I2C_SEND_START(struct i2c_periph *periph) { - I2C_TypeDef *regs = (I2C_TypeDef *) periph->reg_addr; + u32 i2c = (u32) periph->reg_addr; // Reset the buffer pointer to the first byte periph->idx_buf = 0; @@ -302,12 +327,12 @@ static inline void PPRZ_I2C_SEND_START(struct i2c_periph *periph) #endif // Enable Error IRQ, Event IRQ but disable Buffer IRQ - regs->CR2 |= I2C_CR2_BIT_ITERREN; - regs->CR2 |= I2C_CR2_BIT_ITEVTEN; - regs->CR2 &= ~ I2C_CR2_BIT_ITBUFEN; + I2C_CR2(i2c) |= I2C_CR2_ITERREN; + I2C_CR2(i2c) |= I2C_CR2_ITEVTEN; + I2C_CR2(i2c) &= ~ I2C_CR2_ITBUFEN; // Issue a new start - regs->CR1 = (I2C_CR1_BIT_START | I2C_CR1_BIT_PE); + I2C_CR1(i2c) = (I2C_CR1_START | I2C_CR1_PE); periph->status = I2CStartRequested; } @@ -329,35 +354,35 @@ enum STMI2CSubTransactionStatus { // Doc ID 13902 Rev 11 p 710/1072 // Transfer Sequence Diagram for Master Transmitter -static inline enum STMI2CSubTransactionStatus stmi2c_send(I2C_TypeDef *regs, struct i2c_periph *periph, struct i2c_transaction *trans) +static inline enum STMI2CSubTransactionStatus stmi2c_send(u32 i2c, struct i2c_periph *periph, struct i2c_transaction *trans) { - uint16_t SR1 = regs->SR1; + uint16_t SR1 = I2C_SR1(i2c); // Start Condition Was Just Generated - if (BIT_X_IS_SET_IN_REG( I2C_SR1_BIT_SB, SR1 ) ) + if (BIT_X_IS_SET_IN_REG( I2C_SR1_SB, SR1 ) ) { // Disable buffer interrupt - regs->CR2 &= ~ I2C_CR2_BIT_ITBUFEN; + I2C_CR2(i2c) &= ~ I2C_CR2_ITBUFEN; // Send Slave address and wait for ADDR interrupt - regs->DR = trans->slave_addr; + I2C_DR(i2c) = trans->slave_addr; // Document the current Status periph->status = I2CAddrWrSent; } // Address Was Sent - else if (BIT_X_IS_SET_IN_REG(I2C_SR1_BIT_ADDR, SR1) ) + else if (BIT_X_IS_SET_IN_REG(I2C_SR1_ADDR, SR1) ) { // Now read SR2 to clear the ADDR status Bit - uint16_t SR2 __attribute__ ((unused)) = regs->SR2; + uint16_t SR2 __attribute__ ((unused)) = I2C_SR2(i2c); // Maybe check we are transmitting (did not loose arbitration for instance) - // if (! BIT_X_IS_SET_IN_REG(I2C_SR2_BIT_TRA, SR2)) { } + // if (! BIT_X_IS_SET_IN_REG(I2C_SR2_TRA, SR2)) { } // update: this should be caught by the ARLO error: so we will not arrive here // Send First max 2 bytes - regs->DR = trans->buf[0]; + I2C_DR(i2c) = trans->buf[0]; if (trans->len_w > 1) { - regs->DR = trans->buf[1]; + I2C_DR(i2c) = trans->buf[1]; periph->idx_buf = 2; } else @@ -368,28 +393,28 @@ static inline enum STMI2CSubTransactionStatus stmi2c_send(I2C_TypeDef *regs, str // Enable buffer-space available interrupt // only if there is more to send: wait for TXE, no more to send: wait for BTF if ( periph->idx_buf < trans->len_w) - regs->CR2 |= I2C_CR2_BIT_ITBUFEN; + I2C_CR2(i2c) |= I2C_CR2_ITBUFEN; // Document the current Status periph->status = I2CSendingByte; } // The buffer is not full anymore AND we were not waiting for BTF - else if ((BIT_X_IS_SET_IN_REG(I2C_SR1_BIT_TXE, SR1) ) && (BIT_X_IS_SET_IN_REG(I2C_CR2_BIT_ITBUFEN, regs->CR2)) ) + else if ((BIT_X_IS_SET_IN_REG(I2C_SR1_TxE, SR1) ) && (BIT_X_IS_SET_IN_REG(I2C_CR2_ITBUFEN, I2C_CR2(i2c))) ) { // Send the next byte - regs->DR = trans->buf[periph->idx_buf]; + I2C_DR(i2c) = trans->buf[periph->idx_buf]; periph->idx_buf++; // All bytes Sent? Then wait for BTF instead if ( periph->idx_buf >= trans->len_w) { // Not interested anymore to know the buffer has space left - regs->CR2 &= ~ I2C_CR2_BIT_ITBUFEN; + I2C_CR2(i2c) &= ~ I2C_CR2_ITBUFEN; // Next interrupt will be BTF (or error) } } // BTF: means last byte was sent - else if (BIT_X_IS_SET_IN_REG(I2C_SR1_BIT_BTF, SR1) ) + else if (BIT_X_IS_SET_IN_REG(I2C_SR1_BTF, SR1) ) { if (trans->type == I2CTransTx) { @@ -410,49 +435,49 @@ static inline enum STMI2CSubTransactionStatus stmi2c_send(I2C_TypeDef *regs, str // Doc ID 13902 Rev 11 p 714/1072 // Transfer Sequence Diagram for Master Receiver for N=1 -static inline enum STMI2CSubTransactionStatus stmi2c_read1(I2C_TypeDef *regs, struct i2c_periph *periph, struct i2c_transaction *trans) +static inline enum STMI2CSubTransactionStatus stmi2c_read1(u32 i2c, struct i2c_periph *periph, struct i2c_transaction *trans) { - uint16_t SR1 = regs->SR1; + uint16_t SR1 = I2C_SR1(i2c); // Start Condition Was Just Generated - if (BIT_X_IS_SET_IN_REG( I2C_SR1_BIT_SB, SR1 ) ) + if (BIT_X_IS_SET_IN_REG( I2C_SR1_SB, SR1 ) ) { - regs->CR2 &= ~ I2C_CR2_BIT_ITBUFEN; - regs->DR = trans->slave_addr | 0x01; + I2C_CR2(i2c) &= ~ I2C_CR2_ITBUFEN; + I2C_DR(i2c) = trans->slave_addr | 0x01; // Document the current Status periph->status = I2CAddrRdSent; } // Address Was Sent - else if (BIT_X_IS_SET_IN_REG(I2C_SR1_BIT_ADDR, SR1) ) + else if (BIT_X_IS_SET_IN_REG(I2C_SR1_ADDR, SR1) ) { // First Clear the ACK bit: after the next byte we do not want new bytes - regs->CR1 &= ~ I2C_CR1_BIT_POS; - regs->CR1 &= ~ I2C_CR1_BIT_ACK; + I2C_CR1(i2c) &= ~ I2C_CR1_POS; + I2C_CR1(i2c) &= ~ I2C_CR1_ACK; // --- next to steps MUST be executed together to avoid missing the stop __I2C_REG_CRITICAL_ZONE_START; // Only after setting ACK, read SR2 to clear the ADDR (next byte will start arriving) - uint16_t SR2 __attribute__ ((unused)) = regs->SR2; + uint16_t SR2 __attribute__ ((unused)) = I2C_SR2(i2c); // Schedule a Stop - PPRZ_I2C_SEND_STOP(regs); + PPRZ_I2C_SEND_STOP(i2c); __I2C_REG_CRITICAL_ZONE_STOP; // --- end of critical zone ----------- // Enable the RXNE: it will trigger as soon as the 1 byte is received to get the result - regs->CR2 |= I2C_CR2_BIT_ITBUFEN; + I2C_CR2(i2c) |= I2C_CR2_ITBUFEN; // Document the current Status periph->status = I2CReadingLastByte; } // As soon as there is 1 byte ready to read, we have our byte - else if (BIT_X_IS_SET_IN_REG(I2C_SR1_BIT_RXNE, SR1) ) + else if (BIT_X_IS_SET_IN_REG(I2C_SR1_RxNE, SR1) ) { - regs->CR2 &= ~ I2C_CR2_BIT_ITBUFEN; - trans->buf[0] = regs->DR; + I2C_CR2(i2c) &= ~ I2C_CR2_ITBUFEN; + trans->buf[0] = I2C_DR(i2c); // We got all the results (stop condition might still be in progress but this is the last interrupt) trans->status = I2CTransSuccess; @@ -473,24 +498,24 @@ static inline enum STMI2CSubTransactionStatus stmi2c_read1(I2C_TypeDef *regs, st // Doc ID 13902 Rev 11 p 713/1072 // Transfer Sequence Diagram for Master Receiver for N=2 -static inline enum STMI2CSubTransactionStatus stmi2c_read2(I2C_TypeDef *regs, struct i2c_periph *periph, struct i2c_transaction *trans) +static inline enum STMI2CSubTransactionStatus stmi2c_read2(u32 i2c, struct i2c_periph *periph, struct i2c_transaction *trans) { - uint16_t SR1 = regs->SR1; + uint16_t SR1 = I2C_SR1(i2c); // Start Condition Was Just Generated - if (BIT_X_IS_SET_IN_REG( I2C_SR1_BIT_SB, SR1 ) ) + if (BIT_X_IS_SET_IN_REG( I2C_SR1_SB, SR1 ) ) { // according to the datasheet: instantly shedule a NAK on the second received byte: - regs->CR2 &= ~ I2C_CR2_BIT_ITBUFEN; - regs->CR1 |= I2C_CR1_BIT_ACK; - regs->CR1 |= I2C_CR1_BIT_POS; - regs->DR = trans->slave_addr | 0x01; + I2C_CR2(i2c) &= ~ I2C_CR2_ITBUFEN; + I2C_CR1(i2c) |= I2C_CR1_ACK; + I2C_CR1(i2c) |= I2C_CR1_POS; + I2C_DR(i2c) = trans->slave_addr | 0x01; // Document the current Status periph->status = I2CAddrRdSent; } // Address Was Sent - else if (BIT_X_IS_SET_IN_REG(I2C_SR1_BIT_ADDR, SR1) ) + else if (BIT_X_IS_SET_IN_REG(I2C_SR1_ADDR, SR1) ) { // --- make absolutely sure this command is not delayed too much after the previous: // --- the NAK bits must be set before the first byte arrived: allow other interrupts here @@ -499,13 +524,13 @@ static inline enum STMI2CSubTransactionStatus stmi2c_read2(I2C_TypeDef *regs, st // if transfer of DR was finished already then we will get too many bytes // BEFORE clearing ACK, read SR2 to clear the ADDR (next byte will start arriving) // clearing ACK after the byte transfer has already started will NACK the next (2nd) - uint16_t SR2 __attribute__ ((unused)) = regs->SR2; + uint16_t SR2 __attribute__ ((unused)) = I2C_SR2(i2c); // NOT First Clear the ACK bit but only AFTER clearing ADDR - regs->CR1 &= ~ I2C_CR1_BIT_ACK; + I2C_CR1(i2c) &= ~ I2C_CR1_ACK; // Disable the RXNE and wait for BTF - regs->CR2 &= ~ I2C_CR2_BIT_ITBUFEN; + I2C_CR2(i2c) &= ~ I2C_CR2_ITBUFEN; __I2C_REG_CRITICAL_ZONE_STOP; // --- end of critical zone ----------- @@ -516,17 +541,17 @@ static inline enum STMI2CSubTransactionStatus stmi2c_read2(I2C_TypeDef *regs, st periph->status = I2CReadingByte; } // Receive buffer if full, master is halted: BTF - else if (BIT_X_IS_SET_IN_REG(I2C_SR1_BIT_BTF, SR1) ) + else if (BIT_X_IS_SET_IN_REG(I2C_SR1_BTF, SR1) ) { // Stop condition MUST be set BEFORE reading the DR // otherwise since there is new buffer space a new byte will be read - PPRZ_I2C_SEND_STOP(regs); + PPRZ_I2C_SEND_STOP(i2c); // Document the current Status periph->status = I2CStopRequested; - trans->buf[0] = regs->DR; - trans->buf[1] = regs->DR; + trans->buf[0] = I2C_DR(i2c); + trans->buf[1] = I2C_DR(i2c); // We got all the results trans->status = I2CTransSuccess; @@ -543,25 +568,25 @@ static inline enum STMI2CSubTransactionStatus stmi2c_read2(I2C_TypeDef *regs, st // Doc ID 13902 Rev 11 p 712/1072 // Transfer Sequence Diagram for Master Receiver for N>2 -static inline enum STMI2CSubTransactionStatus stmi2c_readmany(I2C_TypeDef *regs, struct i2c_periph *periph, struct i2c_transaction *trans) +static inline enum STMI2CSubTransactionStatus stmi2c_readmany(u32 i2c, struct i2c_periph *periph, struct i2c_transaction *trans) { - uint16_t SR1 = regs->SR1; + uint16_t SR1 = I2C_SR1(i2c); // Start Condition Was Just Generated - if (BIT_X_IS_SET_IN_REG( I2C_SR1_BIT_SB, SR1 ) ) + if (BIT_X_IS_SET_IN_REG( I2C_SR1_SB, SR1 ) ) { - regs->CR2 &= ~ I2C_CR2_BIT_ITBUFEN; + I2C_CR2(i2c) &= ~ I2C_CR2_ITBUFEN; // The first data byte will be acked in read many so the slave knows it should send more - regs->CR1 &= ~ I2C_CR1_BIT_POS; - regs->CR1 |= I2C_CR1_BIT_ACK; + I2C_CR1(i2c) &= ~ I2C_CR1_POS; + I2C_CR1(i2c) |= I2C_CR1_ACK; // Clear the SB flag - regs->DR = trans->slave_addr | 0x01; + I2C_DR(i2c) = trans->slave_addr | 0x01; // Document the current Status periph->status = I2CAddrRdSent; } // Address Was Sent - else if (BIT_X_IS_SET_IN_REG(I2C_SR1_BIT_ADDR, SR1) ) + else if (BIT_X_IS_SET_IN_REG(I2C_SR1_ADDR, SR1) ) { periph->idx_buf = 0; @@ -569,23 +594,23 @@ static inline enum STMI2CSubTransactionStatus stmi2c_readmany(I2C_TypeDef *regs, // only enable if MORE than 3 bytes need to be read if (periph->idx_buf < (trans->len_r - 3)) { - regs->CR2 |= I2C_CR2_BIT_ITBUFEN; + I2C_CR2(i2c) |= I2C_CR2_ITBUFEN; } // ACK is still on to get more DATA // Read SR2 to clear the ADDR (next byte will start arriving) - uint16_t SR2 __attribute__ ((unused)) = regs->SR2; + uint16_t SR2 __attribute__ ((unused)) = I2C_SR2(i2c); // Document the current Status periph->status = I2CReadingByte; } // one or more bytes are available AND we were interested in Buffer interrupts - else if ( (BIT_X_IS_SET_IN_REG(I2C_SR1_BIT_RXNE, SR1) ) && (BIT_X_IS_SET_IN_REG(I2C_CR2_BIT_ITBUFEN, regs->CR2)) ) + else if ( (BIT_X_IS_SET_IN_REG(I2C_SR1_RxNE, SR1) ) && (BIT_X_IS_SET_IN_REG(I2C_CR2_ITBUFEN, I2C_CR2(i2c))) ) { // read byte until 3 bytes remain to be read (e.g. len_r = 6, -> idx=3 means idx 3,4,5 = 3 remain to be read if (periph->idx_buf < (trans->len_r - 3)) { - trans->buf[periph->idx_buf] = regs->DR; + trans->buf[periph->idx_buf] = I2C_DR(i2c); periph->idx_buf ++; } // from : 3bytes -> last byte: do nothing @@ -593,10 +618,10 @@ static inline enum STMI2CSubTransactionStatus stmi2c_readmany(I2C_TypeDef *regs, // finally: this was the last byte else if (periph->idx_buf >= (trans->len_r - 1)) { - regs->CR2 &= ~ I2C_CR2_BIT_ITBUFEN; + I2C_CR2(i2c) &= ~ I2C_CR2_ITBUFEN; // Last Value - trans->buf[periph->idx_buf] = regs->DR; + trans->buf[periph->idx_buf] = I2C_DR(i2c); periph->idx_buf ++; // We got all the results @@ -608,18 +633,18 @@ static inline enum STMI2CSubTransactionStatus stmi2c_readmany(I2C_TypeDef *regs, // Check for end of transaction: start waiting for BTF instead of RXNE if (periph->idx_buf < (trans->len_r - 3)) { - regs->CR2 |= I2C_CR2_BIT_ITBUFEN; + I2C_CR2(i2c) |= I2C_CR2_ITBUFEN; } else // idx >= len-3: there are 3 bytes to be read { // We want to halt I2C to have sufficient time to clear ACK, so: // Stop listening to RXNE as it will be triggered infinitely since we did not empty the buffer // on the next (second in buffer) received byte BTF will be set (buffer full and I2C halted) - regs->CR2 &= ~ I2C_CR2_BIT_ITBUFEN; + I2C_CR2(i2c) &= ~ I2C_CR2_ITBUFEN; } } // Buffer is full while this was not a RXNE interrupt - else if (BIT_X_IS_SET_IN_REG(I2C_SR1_BIT_BTF, SR1) ) + else if (BIT_X_IS_SET_IN_REG(I2C_SR1_BTF, SR1) ) { // Now the shift register and data register contain data(n-2) and data(n-1) // And I2C is halted so we have time @@ -628,14 +653,14 @@ static inline enum STMI2CSubTransactionStatus stmi2c_readmany(I2C_TypeDef *regs, __I2C_REG_CRITICAL_ZONE_START; // First we clear the ACK while the SCL is held low by BTF - regs->CR1 &= ~ I2C_CR1_BIT_ACK; + I2C_CR1(i2c) &= ~ I2C_CR1_ACK; // Now that ACK is cleared we read one byte: instantly the last byte is being clocked in... - trans->buf[periph->idx_buf] = regs->DR; + trans->buf[periph->idx_buf] = I2C_DR(i2c); periph->idx_buf ++; // Now the last byte is being clocked. Stop in MUST be set BEFORE the transfer of the last byte is complete - PPRZ_I2C_SEND_STOP(regs); + PPRZ_I2C_SEND_STOP(i2c); __I2C_REG_CRITICAL_ZONE_STOP; // --- end of critical zone ----------- @@ -644,12 +669,12 @@ static inline enum STMI2CSubTransactionStatus stmi2c_readmany(I2C_TypeDef *regs, periph->status = I2CStopRequested; // read the byte2 we had in the buffer (BTF means 2 bytes available) - trans->buf[periph->idx_buf] = regs->DR; + trans->buf[periph->idx_buf] = I2C_DR(i2c); periph->idx_buf ++; // Ask for an interrupt to read the last byte (which is normally still busy now) // The last byte will be received with RXNE - regs->CR2 |= I2C_CR2_BIT_ITBUFEN; + I2C_CR2(i2c) |= I2C_CR2_ITBUFEN; } else // Event Logic Error { @@ -666,39 +691,39 @@ static inline void i2c_error(struct i2c_periph *periph) { uint8_t err_nr = 0; periph->errors->er_irq_cnt; - if (I2C_GetITStatus(periph->reg_addr, I2C_IT_AF)) { /* Acknowledge failure */ + if ((I2C_SR1((u32)periph->reg_addr) & I2C_SR1_AF) != 0) { /* Acknowledge failure */ periph->errors->ack_fail_cnt++; - I2C_ClearITPendingBit(periph->reg_addr, I2C_IT_AF); + I2C_SR1((u32)periph->reg_addr) &= ~I2C_SR1_AF; err_nr = 1; } - if (I2C_GetITStatus(periph->reg_addr, I2C_IT_BERR)) { /* Misplaced Start or Stop condition */ + if ((I2C_SR1((u32)periph->reg_addr) & I2C_SR1_BERR) != 0) { /* Misplaced Start or Stop condition */ periph->errors->miss_start_stop_cnt++; - I2C_ClearITPendingBit(periph->reg_addr, I2C_IT_BERR); + I2C_SR1((u32)periph->reg_addr) &= ~I2C_SR1_BERR; err_nr = 2; } - if (I2C_GetITStatus(periph->reg_addr, I2C_IT_ARLO)) { /* Arbitration lost */ + if ((I2C_SR1((u32)periph->reg_addr) & I2C_SR1_ARLO) != 0) { /* Arbitration lost */ periph->errors->arb_lost_cnt++; - I2C_ClearITPendingBit(periph->reg_addr, I2C_IT_ARLO); + I2C_SR1((u32)periph->reg_addr) &= ~I2C_SR1_ARLO; err_nr = 3; } - if (I2C_GetITStatus(periph->reg_addr, I2C_IT_OVR)) { /* Overrun/Underrun */ + if ((I2C_SR1((u32)periph->reg_addr) & I2C_SR1_OVR) != 0) { /* Overrun/Underrun */ periph->errors->over_under_cnt++; - I2C_ClearITPendingBit(periph->reg_addr, I2C_IT_OVR); + I2C_SR1((u32)periph->reg_addr) &= ~I2C_SR1_OVR; err_nr = 4; } - if (I2C_GetITStatus(periph->reg_addr, I2C_IT_PECERR)) { /* PEC Error in reception */ + if ((I2C_SR1((u32)periph->reg_addr) & I2C_SR1_PECERR) != 0) { /* PEC Error in reception */ periph->errors->pec_recep_cnt++; - I2C_ClearITPendingBit(periph->reg_addr, I2C_IT_PECERR); + I2C_SR1((u32)periph->reg_addr) &= ~I2C_SR1_PECERR; err_nr = 5; } - if (I2C_GetITStatus(periph->reg_addr, I2C_IT_TIMEOUT)) { /* Timeout or Tlow error */ + if ((I2C_SR1((u32)periph->reg_addr) & I2C_SR1_TIMEOUT) != 0) { /* Timeout or Tlow error */ periph->errors->timeout_tlow_cnt++; - I2C_ClearITPendingBit(periph->reg_addr, I2C_IT_TIMEOUT); + I2C_SR1((u32)periph->reg_addr) &= ~I2C_SR1_TIMEOUT; err_nr = 6; } - if (I2C_GetITStatus(periph->reg_addr, I2C_IT_SMBALERT)) { /* SMBus alert */ + if ((I2C_SR1((u32)periph->reg_addr) & I2C_SR1_SMBALERT) != 0) { /* SMBus alert */ periph->errors->smbus_alert_cnt++; - I2C_ClearITPendingBit(periph->reg_addr, I2C_IT_SMBALERT); + I2C_SR1((u32)periph->reg_addr) &= ~I2C_SR1_SMBALERT; err_nr = 7; } @@ -710,38 +735,38 @@ static inline void i2c_error(struct i2c_periph *periph) } -static inline void stmi2c_clear_pending_interrupts(I2C_TypeDef *regs) +static inline void stmi2c_clear_pending_interrupts(u32 i2c) { - uint16_t SR1 = regs->SR1; + uint16_t SR1 = I2C_SR1(i2c); // Certainly do not wait for buffer interrupts: // ------------------------------------------- - regs->CR2 &= ~ I2C_CR2_BIT_ITBUFEN; // Disable TXE, RXNE + I2C_CR2(i2c) &= ~ I2C_CR2_ITBUFEN; // Disable TXE, RXNE // Error interrupts are handled separately: // --------------------------------------- // Clear Event interrupt conditions: // -------------------------------- - + // Start Condition Was Generated - if (BIT_X_IS_SET_IN_REG( I2C_SR1_BIT_SB, SR1 ) ) + if (BIT_X_IS_SET_IN_REG( I2C_SR1_SB, SR1 ) ) { // SB: cleared by software when reading SR1 and writing to DR - regs->DR = 0x00; + I2C_DR(i2c) = 0x00; } // Address Was Sent - if (BIT_X_IS_SET_IN_REG(I2C_SR1_BIT_ADDR, SR1) ) + if (BIT_X_IS_SET_IN_REG(I2C_SR1_ADDR, SR1) ) { // ADDR: Cleared by software when reading SR1 and then SR2 - uint16_t SR2 __attribute__ ((unused)) = regs->SR2; + uint16_t SR2 __attribute__ ((unused)) = I2C_SR2(i2c); } // Byte Transfer Finished - if (BIT_X_IS_SET_IN_REG(I2C_SR1_BIT_BTF, SR1) ) + if (BIT_X_IS_SET_IN_REG(I2C_SR1_BTF, SR1) ) { // SB: cleared by software when reading SR1 and reading/writing to DR - uint8_t dummy __attribute__ ((unused)) = regs->DR; - regs->DR = 0x00; + uint8_t dummy __attribute__ ((unused)) = I2C_DR(i2c); + I2C_DR(i2c) = 0x00; } } @@ -827,7 +852,7 @@ static inline void i2c_irq(struct i2c_periph *periph) #endif // Save Some Direct Access to the I2C Registers ... - I2C_TypeDef *regs = (I2C_TypeDef *) periph->reg_addr; + u32 i2c = (u32) periph->reg_addr; ///////////////////////////// // Check if we were ready ... @@ -855,7 +880,7 @@ static inline void i2c_irq(struct i2c_periph *periph) i2c_error(periph); // Clear Running Events - stmi2c_clear_pending_interrupts(regs); + stmi2c_clear_pending_interrupts(i2c); // Mark this as a special error periph->errors->last_unexpected_event++; @@ -875,7 +900,7 @@ static inline void i2c_irq(struct i2c_periph *periph) /////////////////////////// // If there was an error: - if (( regs->SR1 & I2C_SR1_BITS_ERR ) != 0x0000) + if (( I2C_SR1(i2c) & I2C_SR1_ERR_MASK ) != 0x0000) { #ifdef I2C_DEBUG_LED @@ -902,7 +927,7 @@ static inline void i2c_irq(struct i2c_periph *periph) i2c_error(periph); // Clear Running Events - stmi2c_clear_pending_interrupts(regs); + stmi2c_clear_pending_interrupts(i2c); // Now continue as if everything was normal from now on ret = STMI2C_SubTra_Ready; @@ -924,19 +949,19 @@ static inline void i2c_irq(struct i2c_periph *periph) switch (trans->len_r) { case 1: - ret = stmi2c_read1(regs,periph,trans); + ret = stmi2c_read1(i2c,periph,trans); break; case 2: - ret = stmi2c_read2(regs,periph,trans); + ret = stmi2c_read2(i2c,periph,trans); break; default: - ret = stmi2c_readmany(regs,periph,trans); + ret = stmi2c_readmany(i2c,periph,trans); break; } } else // TxRx or Tx { - ret = stmi2c_send(regs,periph,trans); + ret = stmi2c_send(i2c,periph,trans); } } @@ -968,7 +993,7 @@ static inline void i2c_irq(struct i2c_periph *periph) #endif // Clear Running Events - stmi2c_clear_pending_interrupts(regs); + stmi2c_clear_pending_interrupts(i2c); } // RxTx -> Restart and do Rx part @@ -976,10 +1001,10 @@ static inline void i2c_irq(struct i2c_periph *periph) { trans->type = I2CTransRx; periph->status = I2CStartRequested; - regs->CR1 |= I2C_CR1_BIT_START; + I2C_CR1(i2c) |= I2C_CR1_START; // Silent any BTF that would occur before SB - regs->DR = 0x00; + I2C_DR(i2c) = 0x00; } // If a restart is not needed: Rx part or Tx-only else @@ -989,10 +1014,10 @@ static inline void i2c_irq(struct i2c_periph *periph) { // Program a stop - PPRZ_I2C_SEND_STOP(regs); + PPRZ_I2C_SEND_STOP(i2c); // Silent any BTF that would occur before STOP is executed - regs->DR = 0x00; + I2C_DR(i2c) = 0x00; } // Jump to the next transaction @@ -1049,10 +1074,10 @@ volatile uint32_t i2c1_watchdog_counter; void i2c1_hw_init(void) { - i2c1.reg_addr = I2C1; - i2c1.init_struct = &I2C1_InitStruct; - i2c1.scl_pin = GPIO_Pin_6; - i2c1.sda_pin = GPIO_Pin_7; + i2c1.reg_addr = (void *)I2C1; + i2c1.init_struct = NULL; + i2c1.scl_pin = GPIO_I2C1_SCL; + i2c1.sda_pin = GPIO_I2C1_SDA; i2c1.errors = &i2c1_errors; i2c1_watchdog_counter = 0; @@ -1065,65 +1090,62 @@ void i2c1_hw_init(void) { #else /* reset peripheral to default state ( sometimes not achieved on reset :( ) */ - //I2C_DeInit(I2C1); + //i2c_reset(I2C1); - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); - NVIC_InitTypeDef NVIC_InitStructure; + /* Configure priority grouping 0 bits for pre-emption priority and 4 bits for sub-priority. */ + scb_set_priority_grouping(SCB_AIRCR_PRIGROUP_NOGROUP_SUB16); /* Configure and enable I2C1 event interrupt --------------------------------*/ - NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); + nvic_set_priority(NVIC_I2C1_EV_IRQ, 0); + nvic_enable_irq(NVIC_I2C1_EV_IRQ); /* Configure and enable I2C1 err interrupt ----------------------------------*/ - NVIC_InitStructure.NVIC_IRQChannel = I2C1_ER_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); + nvic_set_priority(NVIC_I2C1_ER_IRQ, 1); + nvic_enable_irq(NVIC_I2C1_ER_IRQ); /* Enable peripheral clocks -------------------------------------------------*/ /* Enable I2C1 clock */ - RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); + rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_I2C1EN); /* Enable GPIOB clock */ - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Pin = i2c1.scl_pin | i2c1.sda_pin; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; - GPIO_Init(GPIOB, &GPIO_InitStructure); + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, + i2c1.scl_pin | i2c1.sda_pin); - I2C_DeInit(I2C1); + i2c_reset(I2C1); // enable peripheral - I2C_Cmd(I2C1, ENABLE); + i2c_peripheral_enable(I2C1); - I2C_Init(I2C1, i2c1.init_struct); + /* + * XXX: there is a function to do that already in libopencm3 but I am not + * sure if it is correct, using direct register instead (esden) + */ + //i2c_set_own_7bit_slave_address(I2C1, 0); + I2C_OAR1(I2C1) = 0 | 0x4000; // enable error interrupts - I2C_ITConfig(I2C1, I2C_IT_ERR, ENABLE); + I2C_CR2(I2C1) |= I2C_CR2_ITERREN; - i2c_setbitrate(&i2c2, I2C2_InitStruct.I2C_ClockSpeed); + i2c_setbitrate(&i2c2, I2C2_CLOCK_SPEED); #endif } -void i2c1_ev_irq_handler(void) { - I2C_TypeDef *regs = (I2C_TypeDef *) i2c1.reg_addr; - regs->CR2 &= ~ I2C_CR2_BIT_ITERREN; +void i2c1_ev_isr(void) { + u32 i2c = (u32) i2c1.reg_addr; + I2C_CR2(i2c) &= ~I2C_CR2_ITERREN; i2c_irq(&i2c1); i2c1_watchdog_counter = 0; - regs->CR2 |= I2C_CR2_BIT_ITERREN; + I2C_CR2(i2c) |= I2C_CR2_ITERREN; } -void i2c1_er_irq_handler(void) { - I2C_TypeDef *regs = (I2C_TypeDef *) i2c1.reg_addr; - regs->CR2 &= ~ I2C_CR2_BIT_ITEVTEN; +void i2c1_er_isr(void) { + u32 i2c = (u32) i2c1.reg_addr; + I2C_CR2(i2c) &= ~I2C_CR2_ITEVTEN; i2c_irq(&i2c1); i2c1_watchdog_counter = 0; - regs->CR2 |= I2C_CR2_BIT_ITEVTEN; + I2C_CR2(i2c) |= I2C_CR2_ITEVTEN; } #endif /* USE_I2C1 */ @@ -1135,10 +1157,10 @@ volatile uint32_t i2c2_watchdog_counter; void i2c2_hw_init(void) { - i2c2.reg_addr = I2C2; - i2c2.init_struct = &I2C2_InitStruct; - i2c2.scl_pin = GPIO_Pin_10; - i2c2.sda_pin = GPIO_Pin_11; + i2c2.reg_addr = (void *)I2C2; + i2c2.init_struct = NULL; + i2c2.scl_pin = GPIO_I2C2_SCL; + i2c2.sda_pin = GPIO_I2C2_SDA; i2c2.errors = &i2c2_errors; i2c2_watchdog_counter = 0; @@ -1146,64 +1168,61 @@ void i2c2_hw_init(void) { ZEROS_ERR_COUNTER(i2c2_errors); /* reset peripheral to default state ( sometimes not achieved on reset :( ) */ - //I2C_DeInit(I2C2); + //i2c_reset(I2C2); - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); - NVIC_InitTypeDef NVIC_InitStructure; + /* Configure priority grouping 0 bits for pre-emption priority and 4 bits for sub-priority. */ + scb_set_priority_grouping(SCB_AIRCR_PRIGROUP_NOGROUP_SUB16); /* Configure and enable I2C2 event interrupt --------------------------------*/ - NVIC_InitStructure.NVIC_IRQChannel = I2C2_EV_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); + nvic_set_priority(NVIC_I2C2_EV_IRQ, 0); + nvic_enable_irq(NVIC_I2C2_EV_IRQ); /* Configure and enable I2C2 err interrupt ----------------------------------*/ - NVIC_InitStructure.NVIC_IRQChannel = I2C2_ER_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); + nvic_set_priority(NVIC_I2C2_ER_IRQ, 1); + nvic_enable_irq(NVIC_I2C2_ER_IRQ); /* Enable peripheral clocks -------------------------------------------------*/ /* Enable I2C2 clock */ - RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); + rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_I2C2EN); /* Enable GPIOB clock */ - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Pin = i2c2.scl_pin | i2c2.sda_pin; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; - GPIO_Init(GPIOB, &GPIO_InitStructure); + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, + i2c2.scl_pin | i2c2.sda_pin); - I2C_DeInit(I2C2); + i2c_reset(I2C2); // enable peripheral - I2C_Cmd(I2C2, ENABLE); + i2c_peripheral_enable(I2C2); - I2C_Init(I2C2, i2c2.init_struct); + /* + * XXX: there is a function to do that already in libopencm3 but I am not + * sure if it is correct, using direct register instead (esden) + */ + //i2c_set_own_7bit_slave_address(I2C2, 0); + I2C_OAR1(I2C2) = 0 | 0x4000; // enable error interrupts - I2C_ITConfig(I2C2, I2C_IT_ERR, ENABLE); + I2C_CR2(I2C1) |= I2C_CR2_ITERREN; - i2c_setbitrate(&i2c2, I2C2_InitStruct.I2C_ClockSpeed); + i2c_setbitrate(&i2c2, I2C2_CLOCK_SPEED); } -void i2c2_ev_irq_handler(void) { - I2C_TypeDef *regs = (I2C_TypeDef *) i2c2.reg_addr; - regs->CR2 &= ~ I2C_CR2_BIT_ITERREN; +void i2c2_ev_isr(void) { + u32 i2c = (u32) i2c2.reg_addr; + I2C_CR2(i2c) &= ~I2C_CR2_ITERREN; i2c_irq(&i2c2); i2c2_watchdog_counter = 0; - regs->CR2 |= I2C_CR2_BIT_ITERREN; + I2C_CR2(i2c) |= I2C_CR2_ITERREN; } -void i2c2_er_irq_handler(void) { - I2C_TypeDef *regs = (I2C_TypeDef *) i2c2.reg_addr; - regs->CR2 &= ~ I2C_CR2_BIT_ITEVTEN; +void i2c2_er_isr(void) { + u32 i2c = (u32) i2c2.reg_addr; + I2C_CR2(i2c) &= ~I2C_CR2_ITEVTEN; i2c_irq(&i2c2); i2c2_watchdog_counter = 0; - regs->CR2 |= I2C_CR2_BIT_ITEVTEN; + I2C_CR2(i2c) |= I2C_CR2_ITEVTEN; } #endif /* USE_I2C2 */ @@ -1221,10 +1240,7 @@ void i2c_setbitrate(struct i2c_periph *periph, int bitrate) volatile int devider; volatile int risetime; - I2C_TypeDef *regs = (I2C_TypeDef *) periph->reg_addr; - - // store (just for fun) - I2C2_InitStruct.I2C_ClockSpeed = bitrate; + u32 i2c = (u32) periph->reg_addr; /***************************************************** Bitrate: @@ -1272,18 +1288,18 @@ void i2c_setbitrate(struct i2c_periph *periph, int bitrate) // CCR can only be written when PE is disabled // p731 note 5 - regs->CR1 &= ~ I2C_CR1_BIT_PE; + I2C_CR1(i2c) &= ~ I2C_CR1_PE; // 1) - regs->CR2 = 0x0324; + I2C_CR2(i2c) = 0x0324; // 2) - //regs->CCR = 0x8000 + devider; - regs->CCR = 0x0000 + devider; + //I2C_CCR(i2c) = 0x8000 + devider; + I2C_CCR(i2c) = 0x0000 + devider; // 3) - regs->TRISE = risetime; + I2C_TRISE(i2c) = risetime; // Re-Enable - regs->CR1 |= I2C_CR1_BIT_PE; + I2C_CR1(i2c) |= I2C_CR1_PE; __enable_irq(); @@ -1431,7 +1447,7 @@ bool_t i2c_idle(struct i2c_periph* periph) // This is actually a difficult function: // -simply reading the status flags can clear bits and corrupt the transaction - I2C_TypeDef *regs = (I2C_TypeDef *) periph->reg_addr; + u32 i2c = (u32) periph->reg_addr; #ifdef I2C_DEBUG_LED #ifdef USE_I2C1 @@ -1444,7 +1460,7 @@ bool_t i2c_idle(struct i2c_periph* periph) // First we check if the software thinks it is ready if (periph->status == I2CIdle) - return ! (BIT_X_IS_SET_IN_REG( I2C_SR2_BIT_BUSY, regs->SR2 ) ); + return ! (BIT_X_IS_SET_IN_REG( I2C_SR2_BUSY, I2C_SR2(i2c) ) ); else return FALSE; } diff --git a/sw/airborne/boards/lisa_m/baro_board.c b/sw/airborne/boards/lisa_m/baro_board.c index 8e686c004e..6e7fc2fd1e 100644 --- a/sw/airborne/boards/lisa_m/baro_board.c +++ b/sw/airborne/boards/lisa_m/baro_board.c @@ -1,6 +1,6 @@ #include "subsystems/sensors/baro.h" -#include +#include struct Baro baro; struct BaroBoard baro_board; @@ -75,16 +75,14 @@ void baro_init(void) { bmp085_baro_read_calibration(); /* STM32 specific (maybe this is a LISA/M specific driver anyway?) */ - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_Init(GPIOB, &GPIO_InitStructure); + gpio_clear(GPIOB, GPIO0); + gpio_set_mode(GPIOB, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_PULL_UPDOWN, GPIO0); } static inline int baro_eoc(void) { - return GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0); + return gpio_get(GPIOB, GPIO0); } static inline void bmp085_request_pressure(void) diff --git a/sw/airborne/boards/lisa_m/test_baro.c b/sw/airborne/boards/lisa_m/test_baro.c index bb8d09d242..60fee68726 100644 --- a/sw/airborne/boards/lisa_m/test_baro.c +++ b/sw/airborne/boards/lisa_m/test_baro.c @@ -80,15 +80,15 @@ static inline void main_periodic_task( void ) { RunOnceEvery(256, { DOWNLINK_SEND_I2C_ERRORS(DefaultChannel, DefaultDevice, - &i2c2_errors.ack_fail_cnt, - &i2c2_errors.miss_start_stop_cnt, - &i2c2_errors.arb_lost_cnt, - &i2c2_errors.over_under_cnt, - &i2c2_errors.pec_recep_cnt, - &i2c2_errors.timeout_tlow_cnt, - &i2c2_errors.smbus_alert_cnt, - &i2c2_errors.unexpected_event_cnt, - &i2c2_errors.last_unexpected_event); + &i2c2.errors->ack_fail_cnt, + &i2c2.errors->miss_start_stop_cnt, + &i2c2.errors->arb_lost_cnt, + &i2c2.errors->over_under_cnt, + &i2c2.errors->pec_recep_cnt, + &i2c2.errors->timeout_tlow_cnt, + &i2c2.errors->smbus_alert_cnt, + &i2c2.errors->unexpected_event_cnt, + &i2c2.errors->last_unexpected_event); }); }