33 #include <libopencm3/stm32/rcc.h>
34 #include <libopencm3/stm32/gpio.h>
35 #include <libopencm3/cm3/nvic.h>
36 #include <libopencm3/cm3/scb.h>
47 #define I2C_SR1_ERR_MASK (I2C_SR1_SMBALERT | \
57 #define BIT_X_IS_SET_IN_REG(X,REG) (((REG) & (X)) == (X))
66 #define __I2C_REG_CRITICAL_ZONE_START __disable_irq();
67 #define __I2C_REG_CRITICAL_ZONE_STOP __enable_irq();
70 #ifndef NVIC_I2C_IRQ_PRIO
71 #define NVIC_I2C1_IRQ_PRIO 0
72 #define NVIC_I2C2_IRQ_PRIO 0
73 #define NVIC_I2C3_IRQ_PRIO 0
75 #define NVIC_I2C1_IRQ_PRIO NVIC_I2C_IRQ_PRIO
76 #define NVIC_I2C2_IRQ_PRIO NVIC_I2C_IRQ_PRIO
77 #define NVIC_I2C3_IRQ_PRIO NVIC_I2C_IRQ_PRIO
80 #if USE_I2C1 || USE_I2C2 || USE_I2C3
82 static void i2c_setup_gpio(
uint32_t i2c)
89 GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN,
97 GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN,
106 #elif defined(STM32F4)
108 #define I2C1_GPIO_AF GPIO_AF4
112 #define I2C2_GPIO_AF GPIO_AF4
115 #ifndef I2C3_GPIO_SCL_AF
116 #define I2C3_GPIO_SCL_AF GPIO_AF4
118 #ifndef I2C3_GPIO_SDA_AF
119 #define I2C3_GPIO_SDA_AF GPIO_AF4
122 static void i2c_setup_gpio(
uint32_t i2c)
130 gpio_set_output_options(
GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_25MHZ,
140 gpio_set_output_options(
I2C2_GPIO_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_25MHZ,
184 i2c_enable_interrupt(i2c, I2C_CR2_ITERREN);
185 i2c_enable_interrupt(i2c, I2C_CR2_ITEVTEN);
186 i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
189 i2c_nack_current(i2c);
190 i2c_disable_ack(i2c);
192 i2c_peripheral_enable(i2c);
223 i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
232 uint16_t SR2 __attribute__((unused)) = I2C_SR2(i2c);
239 i2c_send_data(i2c, trans->
buf[0]);
240 if (trans->
len_w > 1) {
241 i2c_send_data(i2c, trans->
buf[1]);
250 i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN);
259 i2c_send_data(i2c, trans->
buf[periph->
idx_buf]);
265 i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
294 i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
303 i2c_nack_current(i2c);
304 i2c_disable_ack(i2c);
310 uint16_t SR2 __attribute__((unused)) = I2C_SR2(i2c);
319 i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN);
326 i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
327 trans->
buf[0] = I2C_DR(i2c);
354 i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
371 uint16_t SR2 __attribute__((unused)) = I2C_SR2(i2c);
374 i2c_disable_ack(i2c);
377 i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
396 trans->
buf[0] = I2C_DR(i2c);
397 trans->
buf[1] = I2C_DR(i2c);
419 i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
421 i2c_nack_current(i2c);
436 i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN);
441 uint16_t SR2 __attribute__((unused)) = I2C_SR2(i2c);
457 i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
460 trans->
buf[periph->
idx_buf] = i2c_get_data(i2c);
471 i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN);
476 i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
488 i2c_disable_ack(i2c);
491 trans->
buf[periph->
idx_buf] = i2c_get_data(i2c);
506 trans->
buf[periph->
idx_buf] = i2c_get_data(i2c);
511 i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN);
564 i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
575 i2c_send_data(i2c, 0x00);
580 uint16_t SR2 __attribute__((unused)) = I2C_SR2(i2c);
585 uint8_t dummy __attribute__((unused)) = i2c_get_data(i2c);
586 i2c_send_data(i2c, 0x00);
737 switch (trans->
len_r) {
779 i2c_send_data(i2c, 0x00);
790 i2c_send_data(i2c, 0x00);
833 #error "The STM32 doesn't have I2C0, use I2C1 or I2C2"
839 #ifndef I2C1_CLOCK_SPEED
840 #define I2C1_CLOCK_SPEED 200000
846 void i2c1_hw_init(
void)
849 i2c1.reg_addr = (
void *)
I2C1;
850 i2c1.init_struct = NULL;
851 i2c1.errors = &i2c1_errors;
862 nvic_enable_irq(NVIC_I2C1_EV_IRQ);
866 nvic_enable_irq(NVIC_I2C1_ER_IRQ);
870 rcc_periph_clock_enable(RCC_I2C1);
872 i2c_setup_gpio(
I2C1);
874 rcc_periph_reset_pulse(RST_I2C1);
877 i2c_peripheral_enable(
I2C1);
879 i2c_set_own_7bit_slave_address(
I2C1, 0);
882 i2c_enable_interrupt(
I2C1, I2C_CR2_ITERREN);
887 void i2c1_ev_isr(
void)
890 i2c_disable_interrupt(i2c, I2C_CR2_ITERREN);
893 i2c_enable_interrupt(i2c, I2C_CR2_ITERREN);
896 void i2c1_er_isr(
void)
899 i2c_disable_interrupt(i2c, I2C_CR2_ITEVTEN);
902 i2c_enable_interrupt(i2c, I2C_CR2_ITEVTEN);
910 #ifndef I2C2_CLOCK_SPEED
911 #define I2C2_CLOCK_SPEED 300000
917 void i2c2_hw_init(
void)
920 i2c2.reg_addr = (
void *)I2C2;
921 i2c2.init_struct = NULL;
922 i2c2.errors = &i2c2_errors;
933 nvic_enable_irq(NVIC_I2C2_EV_IRQ);
937 nvic_enable_irq(NVIC_I2C2_ER_IRQ);
941 rcc_periph_clock_enable(RCC_I2C2);
944 i2c_setup_gpio(I2C2);
946 rcc_periph_reset_pulse(RST_I2C2);
949 i2c_peripheral_enable(I2C2);
951 i2c_set_own_7bit_slave_address(I2C2, 0);
954 i2c_enable_interrupt(I2C2, I2C_CR2_ITERREN);
959 void i2c2_ev_isr(
void)
962 i2c_disable_interrupt(i2c, I2C_CR2_ITERREN);
965 i2c_enable_interrupt(i2c, I2C_CR2_ITERREN);
968 void i2c2_er_isr(
void)
971 i2c_disable_interrupt(i2c, I2C_CR2_ITEVTEN);
974 i2c_enable_interrupt(i2c, I2C_CR2_ITEVTEN);
980 #if USE_I2C3 && defined STM32F4
983 #ifndef I2C3_CLOCK_SPEED
984 #define I2C3_CLOCK_SPEED 300000
986 PRINT_CONFIG_VAR(I2C3_CLOCK_SPEED)
990 void i2c3_hw_init(
void)
993 i2c3.reg_addr = (
void *)I2C3;
994 i2c3.init_struct = NULL;
995 i2c3.errors = &i2c3_errors;
1006 nvic_enable_irq(NVIC_I2C3_EV_IRQ);
1010 nvic_enable_irq(NVIC_I2C3_ER_IRQ);
1014 rcc_periph_clock_enable(RCC_I2C3);
1017 i2c_setup_gpio(I2C3);
1019 rcc_periph_reset_pulse(RST_I2C3);
1022 i2c_peripheral_enable(I2C3);
1024 i2c_set_own_7bit_slave_address(I2C3, 0);
1027 i2c_enable_interrupt(I2C3, I2C_CR2_ITERREN);
1032 void i2c3_ev_isr(
void)
1035 i2c_disable_interrupt(i2c, I2C_CR2_ITERREN);
1038 i2c_enable_interrupt(i2c, I2C_CR2_ITERREN);
1041 void i2c3_er_isr(
void)
1044 i2c_disable_interrupt(i2c, I2C_CR2_ITEVTEN);
1047 i2c_enable_interrupt(i2c, I2C_CR2_ITEVTEN);
1061 volatile int devider;
1062 volatile int risetime;
1083 if (bitrate < 3000) {
1090 devider = (rcc_apb1_frequency / 2000) / (bitrate / 1000);
1098 if (devider >= 4095) {
1103 risetime = 1000000 / (bitrate / 1000) / 6 / 28;
1105 if (risetime < 10) {
1110 if (risetime >= 31) {
1119 i2c_peripheral_disable(i2c);
1123 i2c_set_clock_frequency(i2c, I2C_CR2_FREQ_36MHZ);
1125 i2c_set_clock_frequency(i2c, I2C_CR2_FREQ_42MHZ);
1129 i2c_set_ccr(i2c, devider);
1131 i2c_set_trise(i2c, risetime);
1134 i2c_peripheral_enable(i2c);
1141 #define WD_DELAY 20 // number of ticks with 2ms - 40ms delay before resetting the bus
1142 #define WD_RECOVERY_TICKS 18 // number of generated SCL clocking pulses
1144 #if USE_I2C1 || USE_I2C2 || USE_I2C3
1145 static inline void i2c_scl_set(
uint32_t i2c)
1164 static inline void i2c_scl_toggle(
uint32_t i2c)
1183 static inline bool i2c_sda_get(
uint32_t i2c)
1204 static void i2c_wd_check(
struct i2c_periph *periph)
1211 i2c_disable_interrupt(i2c, I2C_CR2_ITEVTEN);
1212 i2c_disable_interrupt(i2c, I2C_CR2_ITERREN);
1219 trans = periph->
trans[i];
1223 i2c_peripheral_disable(i2c);
1246 if (i2c_sda_get(i2c)) {
1249 i2c_scl_toggle(i2c);
1254 i2c_setup_gpio(i2c);
1258 i2c_peripheral_enable(i2c);
1259 i2c_set_own_7bit_slave_address(i2c, 0);
1260 i2c_enable_interrupt(i2c, I2C_CR2_ITERREN);
1300 i2c_wd_check(&i2c1);
1304 i2c_wd_check(&i2c2);
1307 i2c_wd_check(&i2c3);
1323 if (temp >= I2C_TRANSACTION_QUEUE_LEN) { temp = 0; }
volatile uint16_t arb_lost_cnt
#define I2C_TRANSACTION_QUEUE_LEN
I2C transaction queue length.
#define I2C3_GPIO_PORT_SCL
volatile uint16_t miss_start_stop_cnt
volatile uint8_t buf[I2C_BUF_LEN]
Transaction buffer With I2C_BUF_LEN number of bytes.
uint16_t len_r
Number of bytes to read/receive.
static void __enable_irq(void)
transaction successfully finished by I2C driver
static void i2c_irq(struct i2c_periph *periph)
Some architecture independent helper functions for GPIOs.
transmit and receive transaction
uint8_t trans_extract_idx
bool i2c_idle(struct i2c_periph *p)
i2c_idle() function
static void __disable_irq(void)
volatile uint16_t queue_full_cnt
#define BIT_X_IS_SET_IN_REG(X, REG)
void i2c_setbitrate(struct i2c_periph *p, int bitrate)
i2c_setbitrate() function
struct i2c_errors * errors
#define __I2C_REG_CRITICAL_ZONE_STOP
static enum STMI2CSubTransactionStatus stmi2c_readmany(uint32_t i2c, struct i2c_periph *periph, struct i2c_transaction *trans)
void gpio_setup_output(ioportid_t port, uint16_t gpios)
Setup one or more pins of the given GPIO port as outputs.
volatile uint32_t er_irq_cnt
static void gpio_toggle(ioportid_t port, uint16_t pin)
Toggle a gpio output to low level.
#define I2C3_GPIO_PORT_SDA
void gpio_enable_clock(uint32_t port)
Enable the relevant clock.
#define __I2C_REG_CRITICAL_ZONE_START
uint8_t len_w
Number of bytes to write/transmit.
#define NVIC_I2C1_IRQ_PRIO
#define ZEROS_ERR_COUNTER(_i2c_err)
static enum STMI2CSubTransactionStatus stmi2c_read2(uint32_t i2c, struct i2c_periph *periph, struct i2c_transaction *trans)
Architecture independent timing functions.
static void i2c_error(struct i2c_periph *periph)
struct i2c_transaction * trans[I2C_TRANSACTION_QUEUE_LEN]
volatile uint16_t over_under_cnt
bool i2c_submit(struct i2c_periph *p, struct i2c_transaction *t)
i2c_submit() function
static enum STMI2CSubTransactionStatus stmi2c_read1(uint32_t i2c, struct i2c_periph *periph, struct i2c_transaction *trans)
I2C transaction structure.
enum I2CTransactionStatus status
Transaction status.
#define NVIC_I2C2_IRQ_PRIO
volatile uint16_t unexpected_event_cnt
uint8_t slave_addr
Slave address.
I2C peripheral structure.
static uint8_t gpio_get(ioportid_t port, uint16_t pin)
Get level of a gpio.
STMI2CSubTransactionStatus
#define NVIC_I2C3_IRQ_PRIO
transmit only transaction
volatile int16_t watchdog
volatile uint32_t last_unexpected_event
static enum STMI2CSubTransactionStatus stmi2c_send(uint32_t i2c, struct i2c_periph *periph, struct i2c_transaction *trans)
volatile uint16_t wd_reset_cnt
volatile uint16_t smbus_alert_cnt
#define WD_RECOVERY_TICKS
void i2c_event(void)
i2c_event() function
enum I2CTransactionType type
Transaction type.
#define I2C1_CLOCK_SPEED
I2C defines.
#define SysTimeTimerStart(_t)
volatile uint16_t pec_recep_cnt
void gpio_setup_input(ioportid_t port, uint16_t gpios)
Setup one or more pins of the given GPIO port as inputs.
static void PPRZ_I2C_SEND_START(struct i2c_periph *periph)
static void gpio_set(ioportid_t port, uint16_t pin)
Set a gpio output to high level.
transaction is pending in queue
static void stmi2c_clear_pending_interrupts(uint32_t i2c)
static void PPRZ_I2C_SEND_STOP(uint32_t i2c)
volatile uint16_t ack_fail_cnt
volatile uint16_t timeout_tlow_cnt
Architecture independent I2C (Inter-Integrated Circuit Bus) API.