34 #include "mcu_periph/i2c_arch.h"
45 #ifndef I2C_THREAD_STACK_SIZE
46 #define I2C_THREAD_STACK_SIZE 512
55 #if USE_I2C1 || USE_I2C2 || USE_I2C3 || USE_I2C4
59 #if defined(STM32F7XX) || defined(STM32H7XX)
74 static const systime_t tmo = TIME_US2I(10000000 / PERIODIC_FREQUENCY);
76 static iomode_t palReadLineMode(ioline_t line)
78 ioportid_t port = PAL_PORT(line);
81 ret |= (port->MODER >> (pad*2)) & 0x3;
82 ret |= ((port->OTYPER >> pad)&1) << 2;
83 ret |= ((port->OSPEEDR >> (pad*2))&3) << 3;
84 ret |= ((port->PUPDR >> (pad*2))&3) << 5;
86 ret |= ((port->AFRL >> (pad*4))&0xF) << 7;
88 ret |= ((port->AFRH >> ((pad-8)*4))&0xF) << 7;
94 static void i2c_clear_bus(
struct i2c_init *i)
96 const iomode_t mode_saved = palReadLineMode(i->line_scl);
97 palSetLineMode(i->line_scl, PAL_MODE_OUTPUT_PUSHPULL);
98 for(
uint8_t j = 0; j < 20; j++) {
99 palToggleLine(i->line_scl);
100 chThdSleepMicroseconds(10);
102 palSetLineMode(i->line_scl, mode_saved);
107 const iomode_t mode_saved = palReadLineMode(i->line_sda);
108 palSetLineMode(i->line_sda, PAL_MODE_INPUT);
109 uint8_t ret = palReadLine(i->line_sda);
110 palSetLineMode(i->line_sda, mode_saved);
126 i2cAcquireBus((I2CDriver *)
p->reg_addr);
128 if (
p->trans_insert_idx ==
p->trans_extract_idx) {
141 #if defined(STM32F7XX) || defined(STM32H7XX)
143 memcpy(i->dma_buf, (
void *)t->
buf, (
size_t)(t->
len_w));
144 cacheBufferFlush(i->dma_buf, t->
len_w);
145 status = i2cMasterTransmitTimeout(
146 (I2CDriver *)
p->reg_addr,
151 cacheBufferInvalidate(i->dma_buf, t->
len_r);
152 memcpy((
void *)t->
buf, i->dma_buf, (
size_t)(t->
len_r));
154 status = i2cMasterTransmitTimeout(
155 (I2CDriver *)
p->reg_addr,
162 #if defined(STM32F7XX) || defined(STM32H7XX)
164 status = i2cMasterReceiveTimeout(
165 (I2CDriver *)
p->reg_addr,
169 cacheBufferInvalidate(i->dma_buf, t->
len_r);
170 memcpy((
void *)t->
buf, i->dma_buf, (
size_t)(t->
len_r));
172 status = i2cMasterReceiveTimeout(
173 (I2CDriver *)
p->reg_addr,
182 p->trans_extract_idx++;
184 p->trans_extract_idx = 0;
199 p->errors->unexpected_event_cnt++;
201 if(i2c_read_sda(i) == 0) {
204 i2cStart((I2CDriver *)
p->reg_addr, &i->cfg);
210 i2cflags_t errors = i2cGetErrors((I2CDriver *)
p->reg_addr);
211 if (errors & I2C_BUS_ERROR) {
212 p->errors->miss_start_stop_cnt++;
214 if (errors & I2C_ARBITRATION_LOST) {
215 p->errors->arb_lost_cnt++;
217 if (errors & I2C_ACK_FAILURE) {
218 p->errors->ack_fail_cnt++;
220 if (errors & I2C_OVERRUN) {
221 p->errors->over_under_cnt++;
223 if (errors & I2C_PEC_ERROR) {
224 p->errors->pec_recep_cnt++;
227 p->errors->timeout_tlow_cnt++;
229 if (errors & I2C_SMB_ALERT) {
230 p->errors->smbus_alert_cnt++;
237 i2cReleaseBus((I2CDriver *)
p->reg_addr);
245 static void thd_i2c(
void *arg)
249 chRegSetThreadName(init_s->name);
252 handle_i2c_thd(i2cp);
262 .sem = __SEMAPHORE_DATA(i2c1_init_s.sem, 0),
272 void i2c1_hw_init(
void)
278 i2cStart(&I2CD1, &i2c1_init_s.cfg);
279 i2c1.reg_addr = &I2CD1;
280 i2c1.errors = &i2c1_init_s.errors;
281 i2c1.init_struct = &i2c1_init_s;
283 chThdCreateStatic(wa_thd_i2c1,
sizeof(wa_thd_i2c1),
284 NORMALPRIO + 1, thd_i2c, (
void *)&i2c1);
293 .sem = __SEMAPHORE_DATA(i2c2_init_s.sem, 0),
303 void i2c2_hw_init(
void)
309 i2cStart(&I2CD2, &i2c2_init_s.cfg);
310 i2c2.reg_addr = &I2CD2;
311 i2c2.errors = &i2c2_init_s.errors;
312 i2c2.init_struct = &i2c2_init_s;
314 chThdCreateStatic(wa_thd_i2c2,
sizeof(wa_thd_i2c2),
315 NORMALPRIO + 1, thd_i2c, (
void *)&i2c2);
324 .sem = __SEMAPHORE_DATA(i2c3_init_s.sem, 0),
334 void i2c3_hw_init(
void)
340 i2cStart(&I2CD3, &i2c3_init_s.cfg);
341 i2c3.reg_addr = &I2CD3;
342 i2c3.errors = &i2c3_init_s.errors;
343 i2c3.init_struct = &i2c3_init_s;
345 chThdCreateStatic(wa_thd_i2c3,
sizeof(wa_thd_i2c3),
346 NORMALPRIO + 1, thd_i2c, (
void *)&i2c3);
353 #if defined(STM32H7XX)
361 .sem = __SEMAPHORE_DATA(i2c4_init_s.sem, 0),
371 void i2c4_hw_init(
void)
377 i2cStart(&I2CD4, &i2c4_init_s.cfg);
378 i2c4.reg_addr = &I2CD4;
379 i2c4.errors = &i2c4_init_s.errors;
380 i2c4.init_struct = &i2c4_init_s;
382 chThdCreateStatic(wa_thd_i2c4,
sizeof(wa_thd_i2c4),
383 NORMALPRIO + 1, thd_i2c, (
void *)&i2c4);
422 #if USE_I2C1 || USE_I2C2 || USE_I2C3 || USE_I2C4
426 temp =
p->trans_insert_idx + 1;
428 if (temp ==
p->trans_extract_idx) {
430 p->errors->queue_full_cnt++;
439 p->trans[
p->trans_insert_idx] = t;
440 p->trans_insert_idx = temp;
443 chSemSignal(&((
struct i2c_init *)
p->init_struct)->sem);
#define I2C_THREAD_STACK_SIZE
static bool i2c_chibios_idle(struct i2c_periph *p)
i2c_idle() function
static bool i2c_chibios_submit(struct i2c_periph *p, struct i2c_transaction *t)
i2c_submit() function
static void i2c_chibios_setbitrate(struct i2c_periph *p, int bitrate)
i2c_setbitrate() function
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.
enum I2CTransactionStatus status
Transaction status.
uint8_t slave_addr
Slave address.
uint8_t len_w
Number of bytes to write/transmit.
void i2c_event(void)
i2c_event() function
#define I2C_TRANSACTION_QUEUE_LEN
I2C transaction queue length.
#define I2C_BUF_LEN
I2C buffer length.
void i2c_init(struct i2c_periph *p)
Initialize I2C peripheral.
@ I2CTransSuccess
transaction successfully finished by I2C driver
@ I2CTransFailed
transaction failed
@ I2CTransPending
transaction is pending in queue
I2C transaction structure.
Architecture independent I2C (Inter-Integrated Circuit Bus) API.
THD_WORKING_AREA(wa_thd_ap, THD_WORKING_AREA_MAIN)
PRINT_CONFIG_VAR(ONELOOP_ANDI_FILT_CUTOFF)
Specific RAM section for DMA usage on F7.
#define IN_DMA_SECTION(var)
#define IN_BDMA_SECTION(var)
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.