33 #include <libopencm3/stm32/rcc.h>
34 #include <libopencm3/stm32/gpio.h>
35 #include <libopencm3/cm3/nvic.h>
36 #include <libopencm3/cm3/scb.h>
42 #include "i2c_debug_led.h"
43 #endif // I2C_DEBUG_LED
51 #define I2C_SR1_ERR_MASK (I2C_SR1_SMBALERT | \
61 #define BIT_X_IS_SET_IN_REG(X,REG) (((REG) & (X)) == (X))
70 #define __I2C_REG_CRITICAL_ZONE_START __disable_irq();
71 #define __I2C_REG_CRITICAL_ZONE_STOP __enable_irq();
74 #ifndef NVIC_I2C_IRQ_PRIO
75 #define NVIC_I2C1_IRQ_PRIO 0
76 #define NVIC_I2C2_IRQ_PRIO 0
77 #define NVIC_I2C3_IRQ_PRIO 0
79 #define NVIC_I2C1_IRQ_PRIO NVIC_I2C_IRQ_PRIO
80 #define NVIC_I2C2_IRQ_PRIO NVIC_I2C_IRQ_PRIO
81 #define NVIC_I2C3_IRQ_PRIO NVIC_I2C_IRQ_PRIO
84 #if USE_I2C1 || USE_I2C2 || USE_I2C3
86 static void i2c_setup_gpio(
uint32_t i2c)
93 GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN,
101 GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN,
110 #elif defined(STM32F4)
112 static void i2c_setup_gpio(
uint32_t i2c)
120 gpio_set_output_options(
GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_25MHZ,
130 gpio_set_output_options(
I2C2_GPIO_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_25MHZ,
195 i2c_enable_interrupt(i2c, I2C_CR2_ITERREN);
196 i2c_enable_interrupt(i2c, I2C_CR2_ITEVTEN);
197 i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
200 i2c_nack_current(i2c);
201 i2c_disable_ack(i2c);
203 i2c_peripheral_enable(i2c);
234 i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
243 uint16_t SR2 __attribute__((unused)) = I2C_SR2(i2c);
250 i2c_send_data(i2c, trans->
buf[0]);
251 if (trans->
len_w > 1) {
252 i2c_send_data(i2c, trans->
buf[1]);
261 i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN);
270 i2c_send_data(i2c, trans->
buf[periph->
idx_buf]);
276 i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
305 i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
314 i2c_nack_current(i2c);
315 i2c_disable_ack(i2c);
321 uint16_t SR2 __attribute__((unused)) = I2C_SR2(i2c);
330 i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN);
337 i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
338 trans->
buf[0] = I2C_DR(i2c);
365 i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
382 uint16_t SR2 __attribute__((unused)) = I2C_SR2(i2c);
385 i2c_disable_ack(i2c);
388 i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
407 trans->
buf[0] = I2C_DR(i2c);
408 trans->
buf[1] = I2C_DR(i2c);
430 i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
432 i2c_nack_current(i2c);
447 i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN);
452 uint16_t SR2 __attribute__((unused)) = I2C_SR2(i2c);
468 i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
471 trans->
buf[periph->
idx_buf] = i2c_get_data(i2c);
482 i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN);
487 i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
499 i2c_disable_ack(i2c);
502 trans->
buf[periph->
idx_buf] = i2c_get_data(i2c);
517 trans->
buf[periph->
idx_buf] = i2c_get_data(i2c);
522 i2c_enable_interrupt(i2c, I2C_CR2_ITBUFEN);
603 i2c_disable_interrupt(i2c, I2C_CR2_ITBUFEN);
614 i2c_send_data(i2c, 0x00);
619 uint16_t SR2 __attribute__((unused)) = I2C_SR2(i2c);
624 uint8_t dummy __attribute__((unused)) = i2c_get_data(i2c);
625 i2c_send_data(i2c, 0x00);
801 switch (trans->
len_r) {
853 i2c_send_data(i2c, 0x00);
864 i2c_send_data(i2c, 0x00);
915 #error "The STM32 doesn't have I2C0, use I2C1 or I2C2"
921 #ifndef I2C1_CLOCK_SPEED
922 #define I2C1_CLOCK_SPEED 200000
928 void i2c1_hw_init(
void)
931 i2c1.reg_addr = (
void *)
I2C1;
932 i2c1.init_struct = NULL;
933 i2c1.errors = &i2c1_errors;
949 nvic_enable_irq(NVIC_I2C1_EV_IRQ);
953 nvic_enable_irq(NVIC_I2C1_ER_IRQ);
957 rcc_periph_clock_enable(RCC_I2C1);
959 i2c_setup_gpio(
I2C1);
961 rcc_periph_reset_pulse(RST_I2C1);
964 i2c_peripheral_enable(
I2C1);
966 i2c_set_own_7bit_slave_address(
I2C1, 0);
969 i2c_enable_interrupt(
I2C1, I2C_CR2_ITERREN);
975 void i2c1_ev_isr(
void)
978 i2c_disable_interrupt(i2c, I2C_CR2_ITERREN);
981 i2c_enable_interrupt(i2c, I2C_CR2_ITERREN);
984 void i2c1_er_isr(
void)
987 i2c_disable_interrupt(i2c, I2C_CR2_ITEVTEN);
990 i2c_enable_interrupt(i2c, I2C_CR2_ITEVTEN);
998 #ifndef I2C2_CLOCK_SPEED
999 #define I2C2_CLOCK_SPEED 300000
1005 void i2c2_hw_init(
void)
1008 i2c2.reg_addr = (
void *)I2C2;
1009 i2c2.init_struct = NULL;
1010 i2c2.errors = &i2c2_errors;
1021 nvic_enable_irq(NVIC_I2C2_EV_IRQ);
1025 nvic_enable_irq(NVIC_I2C2_ER_IRQ);
1029 rcc_periph_clock_enable(RCC_I2C2);
1032 i2c_setup_gpio(I2C2);
1034 rcc_periph_reset_pulse(RST_I2C2);
1037 i2c_peripheral_enable(I2C2);
1039 i2c_set_own_7bit_slave_address(I2C2, 0);
1042 i2c_enable_interrupt(I2C2, I2C_CR2_ITERREN);
1047 void i2c2_ev_isr(
void)
1050 i2c_disable_interrupt(i2c, I2C_CR2_ITERREN);
1053 i2c_enable_interrupt(i2c, I2C_CR2_ITERREN);
1056 void i2c2_er_isr(
void)
1059 i2c_disable_interrupt(i2c, I2C_CR2_ITEVTEN);
1062 i2c_enable_interrupt(i2c, I2C_CR2_ITEVTEN);
1068 #if USE_I2C3 && defined STM32F4
1071 #ifndef I2C3_CLOCK_SPEED
1072 #define I2C3_CLOCK_SPEED 300000
1074 PRINT_CONFIG_VAR(I2C3_CLOCK_SPEED)
1078 void i2c3_hw_init(
void)
1081 i2c3.reg_addr = (
void *)I2C3;
1082 i2c3.init_struct = NULL;
1083 i2c3.errors = &i2c3_errors;
1094 nvic_enable_irq(NVIC_I2C3_EV_IRQ);
1098 nvic_enable_irq(NVIC_I2C3_ER_IRQ);
1102 rcc_periph_clock_enable(RCC_I2C3);
1105 i2c_setup_gpio(I2C3);
1107 rcc_periph_reset_pulse(RST_I2C3);
1110 i2c_peripheral_enable(I2C3);
1112 i2c_set_own_7bit_slave_address(I2C3, 0);
1115 i2c_enable_interrupt(I2C3, I2C_CR2_ITERREN);
1120 void i2c3_ev_isr(
void)
1123 i2c_disable_interrupt(i2c, I2C_CR2_ITERREN);
1126 i2c_enable_interrupt(i2c, I2C_CR2_ITERREN);
1129 void i2c3_er_isr(
void)
1132 i2c_disable_interrupt(i2c, I2C_CR2_ITEVTEN);
1135 i2c_enable_interrupt(i2c, I2C_CR2_ITEVTEN);
1149 volatile int devider;
1150 volatile int risetime;
1171 if (bitrate < 3000) {
1178 devider = (rcc_apb1_frequency / 2000) / (bitrate / 1000);
1186 if (devider >= 4095) {
1191 risetime = 1000000 / (bitrate / 1000) / 6 / 28;
1193 if (risetime < 10) {
1198 if (risetime >= 31) {
1207 i2c_peripheral_disable(i2c);
1211 i2c_set_clock_frequency(i2c, I2C_CR2_FREQ_36MHZ);
1213 i2c_set_clock_frequency(i2c, I2C_CR2_FREQ_42MHZ);
1217 i2c_set_ccr(i2c, devider);
1219 i2c_set_trise(i2c, risetime);
1222 i2c_peripheral_enable(i2c);
1226 #ifdef I2C_DEBUG_LED
1244 #define WD_DELAY 20 // number of ticks with 2ms - 40ms delay before resetting the bus
1245 #define WD_RECOVERY_TICKS 18 // number of generated SCL clocking pulses
1247 #if USE_I2C1 || USE_I2C2 || USE_I2C3
1248 static inline void i2c_scl_set(
uint32_t i2c)
1267 static inline void i2c_scl_toggle(
uint32_t i2c)
1286 static inline bool i2c_sda_get(
uint32_t i2c)
1307 static void i2c_wd_check(
struct i2c_periph *periph)
1314 i2c_disable_interrupt(i2c, I2C_CR2_ITEVTEN);
1315 i2c_disable_interrupt(i2c, I2C_CR2_ITERREN);
1322 trans = periph->
trans[i];
1326 i2c_peripheral_disable(i2c);
1349 if (i2c_sda_get(i2c)) {
1352 i2c_scl_toggle(i2c);
1357 i2c_setup_gpio(i2c);
1361 i2c_peripheral_enable(i2c);
1362 i2c_set_own_7bit_slave_address(i2c, 0);
1363 i2c_enable_interrupt(i2c, I2C_CR2_ITERREN);
1403 i2c_wd_check(&i2c1);
1407 i2c_wd_check(&i2c2);
1410 i2c_wd_check(&i2c3);
1426 if (temp >= I2C_TRANSACTION_QUEUE_LEN) { temp = 0; }
1446 #ifdef I2C_DEBUG_LED
1448 if (periph == &i2c1) {
1454 #ifdef I2C_DEBUG_LED
1475 #ifdef I2C_DEBUG_LED
1477 if (periph == &i2c1) {
static void LED2_OFF(void)
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 LED1_ON(void)
static void gpio_toggle(ioportid_t port, uint16_t pin)
Toggle a gpio output to low level.
#define I2C3_GPIO_PORT_SDA
static void LED_SHOW_ACTIVE_BITS(I2C_TypeDef *regs)
static void LED2_ON(void)
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
static void LED_ERROR(uint8_t base, uint8_t nr)
#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
static void LED1_OFF(void)
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.
if(PrimarySpektrumState.SpektrumTimer)