mirror of
https://github.com/paparazzi/paparazzi.git
synced 2026-05-20 11:28:58 +08:00
Add software-I2C (#2514)
This commit is contained in:
@@ -69,7 +69,7 @@ COMMON_DEMO_SRCS += $(SRC_ARCH)/led_hw.c
|
||||
COMMON_DEMO_SRCS += $(SRC_ARCH)/mcu_periph/gpio_arch.c
|
||||
endif
|
||||
|
||||
COMMON_DEMO_SRCS += mcu_periph/i2c.c $(SRC_ARCH)/mcu_periph/i2c_arch.c
|
||||
COMMON_DEMO_SRCS += mcu_periph/i2c.c mcu_periph/softi2c.c $(SRC_ARCH)/mcu_periph/i2c_arch.c
|
||||
COMMON_DEMO_SRCS += mcu_periph/uart.c
|
||||
COMMON_DEMO_SRCS += $(SRC_ARCH)/mcu_periph/uart_arch.c
|
||||
ifeq ($(ARCH), linux)
|
||||
|
||||
@@ -136,6 +136,7 @@ endif # TARGET == fbw
|
||||
|
||||
ifneq ($(TARGET), fbw)
|
||||
$(TARGET).srcs += mcu_periph/i2c.c
|
||||
$(TARGET).srcs += mcu_periph/softi2c.c
|
||||
$(TARGET).srcs += $(SRC_ARCH)/mcu_periph/i2c_arch.c
|
||||
endif
|
||||
|
||||
|
||||
@@ -120,6 +120,7 @@ endif
|
||||
##
|
||||
|
||||
$(TARGET).srcs += mcu_periph/i2c.c
|
||||
$(TARGET).srcs += mcu_periph/softi2c.c
|
||||
$(TARGET).srcs += $(SRC_ARCH)/mcu_periph/i2c_arch.c
|
||||
|
||||
include $(CFG_SHARED)/uart.makefile
|
||||
|
||||
@@ -91,6 +91,7 @@ endif
|
||||
#
|
||||
ifneq ($(TARGET),fbw)
|
||||
$(TARGET).srcs += mcu_periph/i2c.c
|
||||
$(TARGET).srcs += mcu_periph/softi2c.c
|
||||
$(TARGET).srcs += $(SRC_ARCH)/mcu_periph/i2c_arch.c
|
||||
endif
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
</header>
|
||||
<makefile>
|
||||
<file name="i2c.c" dir="mcu_periph"/>
|
||||
<file name="softi2c.c" dir="mcu_periph"/>
|
||||
<file_arch name="i2c_arch.c" dir="mcu_periph"/>
|
||||
</makefile>
|
||||
</module>
|
||||
|
||||
@@ -46,6 +46,12 @@
|
||||
#define I2C_THREAD_STACK_SIZE 512
|
||||
#endif
|
||||
|
||||
|
||||
static bool i2c_chibios_idle(struct i2c_periph *p) __attribute__((unused));
|
||||
static bool i2c_chibios_submit(struct i2c_periph *p, struct i2c_transaction *t) __attribute__((unused));
|
||||
static void i2c_chibios_setbitrate(struct i2c_periph *p, int bitrate) __attribute__((unused));
|
||||
|
||||
|
||||
#if USE_I2C1 || USE_I2C2 || USE_I2C3 || USE_I2C4
|
||||
|
||||
// private I2C init structure
|
||||
@@ -209,6 +215,10 @@ static THD_WORKING_AREA(wa_thd_i2c1, I2C_THREAD_STACK_SIZE);
|
||||
*/
|
||||
void i2c1_hw_init(void)
|
||||
{
|
||||
i2c1.idle = i2c_chibios_idle;
|
||||
i2c1.submit = i2c_chibios_submit;
|
||||
i2c1.setbitrate = i2c_chibios_setbitrate;
|
||||
|
||||
i2cStart(&I2CD1, &i2cfg1);
|
||||
i2c1.reg_addr = &I2CD1;
|
||||
i2c1.errors = &i2c1_errors;
|
||||
@@ -263,6 +273,10 @@ static THD_WORKING_AREA(wa_thd_i2c2, I2C_THREAD_STACK_SIZE);
|
||||
*/
|
||||
void i2c2_hw_init(void)
|
||||
{
|
||||
i2c2.idle = i2c_chibios_idle;
|
||||
i2c2.submit = i2c_chibios_submit;
|
||||
i2c2.setbitrate = i2c_chibios_setbitrate;
|
||||
|
||||
i2cStart(&I2CD2, &i2cfg2);
|
||||
i2c2.reg_addr = &I2CD2;
|
||||
i2c2.errors = &i2c2_errors;
|
||||
@@ -317,6 +331,10 @@ static THD_WORKING_AREA(wa_thd_i2c3, I2C_THREAD_STACK_SIZE);
|
||||
*/
|
||||
void i2c3_hw_init(void)
|
||||
{
|
||||
i2c3.idle = i2c_chibios_idle;
|
||||
i2c3.submit = i2c_chibios_submit;
|
||||
i2c3.setbitrate = i2c_chibios_setbitrate;
|
||||
|
||||
i2cStart(&I2CD3, &i2cfg3);
|
||||
i2c3.reg_addr = &I2CD3;
|
||||
i2c3.init_struct = NULL;
|
||||
@@ -372,6 +390,10 @@ static THD_WORKING_AREA(wa_thd_i2c4, 128);
|
||||
*/
|
||||
void i2c4_hw_init(void)
|
||||
{
|
||||
i2c4.idle = i2c_chibios_idle;
|
||||
i2c4.submit = i2c_chibios_submit;
|
||||
i2c4.setbitrate = i2c_chibios_setbitrate;
|
||||
|
||||
i2cStart(&I2CD4, &i2cfg4);
|
||||
i2c4.reg_addr = &I2CD4;
|
||||
i2c4.init_struct = NULL;
|
||||
@@ -411,7 +433,7 @@ void i2c_event(void) {}
|
||||
* Empty, for paparazzi compatibility only. Bitrate is already
|
||||
* set in i2cX_hw_init()
|
||||
*/
|
||||
void i2c_setbitrate(struct i2c_periph *p __attribute__((unused)), int bitrate __attribute__((unused))) {}
|
||||
static void i2c_chibios_setbitrate(struct i2c_periph *p __attribute__((unused)), int bitrate __attribute__((unused))) {}
|
||||
|
||||
/**
|
||||
* i2c_submit() function
|
||||
@@ -430,7 +452,7 @@ void i2c_setbitrate(struct i2c_periph *p __attribute__((unused)), int bitrate __
|
||||
* @param[in] p pointer to a @p i2c_periph struct
|
||||
* @param[in] t pointer to a @p i2c_transaction struct
|
||||
*/
|
||||
bool i2c_submit(struct i2c_periph *p, struct i2c_transaction *t)
|
||||
static bool i2c_chibios_submit(struct i2c_periph *p, struct i2c_transaction *t)
|
||||
{
|
||||
#if USE_I2C1 || USE_I2C2 || USE_I2C3 || USE_I2C4
|
||||
// sys lock
|
||||
@@ -469,7 +491,7 @@ bool i2c_submit(struct i2c_periph *p, struct i2c_transaction *t)
|
||||
*
|
||||
* Empty, for paparazzi compatibility only
|
||||
*/
|
||||
bool i2c_idle(struct i2c_periph *p __attribute__((unused)))
|
||||
static bool i2c_chibios_idle(struct i2c_periph *p __attribute__((unused)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,12 @@
|
||||
#define I2C_THREAD_PRIO 10
|
||||
#endif
|
||||
|
||||
|
||||
static bool i2c_linux_idle(struct i2c_periph *p __attribute__((unused))) __attribute__((unused));
|
||||
static bool i2c_linux_submit(struct i2c_periph *p, struct i2c_transaction *t) __attribute__((unused));
|
||||
static void i2c_linux_setbitrate(struct i2c_periph *p __attribute__((unused)), int bitrate __attribute__((unused))) __attribute__((unused));
|
||||
|
||||
|
||||
static void *i2c_thread(void *thread_data);
|
||||
|
||||
// private I2C init structure
|
||||
@@ -66,16 +72,16 @@ void i2c_event(void)
|
||||
{
|
||||
}
|
||||
|
||||
void i2c_setbitrate(struct i2c_periph *p __attribute__((unused)), int bitrate __attribute__((unused)))
|
||||
static void i2c_linux_setbitrate(struct i2c_periph *p __attribute__((unused)), int bitrate __attribute__((unused)))
|
||||
{
|
||||
}
|
||||
|
||||
bool i2c_idle(struct i2c_periph *p __attribute__((unused)))
|
||||
static bool i2c_linux_idle(struct i2c_periph *p __attribute__((unused)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool i2c_submit(struct i2c_periph *p, struct i2c_transaction *t)
|
||||
static bool i2c_linux_submit(struct i2c_periph *p, struct i2c_transaction *t)
|
||||
{
|
||||
// get mutex lock and condition
|
||||
pthread_mutex_t *mutex = &(((struct i2c_thread_t *)(p->init_struct))->mutex);
|
||||
@@ -204,6 +210,10 @@ struct i2c_thread_t i2c0_thread;
|
||||
|
||||
void i2c0_hw_init(void)
|
||||
{
|
||||
i2c0.idle = i2c_linux_idle;
|
||||
i2c0.submit = i2c_linux_submit;
|
||||
i2c0.setbitrate = i2c_linux_setbitrate;
|
||||
|
||||
i2c0.reg_addr = (void *)open("/dev/i2c-0", O_RDWR);
|
||||
i2c0.errors = &i2c0_errors;
|
||||
|
||||
@@ -224,6 +234,10 @@ struct i2c_thread_t i2c1_thread;
|
||||
|
||||
void i2c1_hw_init(void)
|
||||
{
|
||||
i2c1.idle = i2c_linux_idle;
|
||||
i2c1.submit = i2c_linux_submit;
|
||||
i2c1.setbitrate = i2c_linux_setbitrate;
|
||||
|
||||
i2c1.reg_addr = (void *)open("/dev/i2c-1", O_RDWR);
|
||||
i2c1.errors = &i2c1_errors;
|
||||
|
||||
@@ -244,6 +258,10 @@ struct i2c_thread_t i2c2_thread;
|
||||
|
||||
void i2c2_hw_init(void)
|
||||
{
|
||||
i2c2.idle = i2c_linux_idle;
|
||||
i2c2.submit = i2c_linux_submit;
|
||||
i2c2.setbitrate = i2c_linux_setbitrate;
|
||||
|
||||
i2c2.reg_addr = (void *)open("/dev/i2c-2", O_RDWR);
|
||||
i2c2.errors = &i2c2_errors;
|
||||
|
||||
@@ -264,6 +282,10 @@ struct i2c_thread_t i2c3_thread;
|
||||
|
||||
void i2c3_hw_init(void)
|
||||
{
|
||||
i2c3.idle = i2c_linux_idle;
|
||||
i2c3.submit = i2c_linux_submit;
|
||||
i2c3.setbitrate = i2c_linux_setbitrate;
|
||||
|
||||
i2c3.reg_addr = (void *)open("/dev/i2c-3", O_RDWR);
|
||||
i2c3.errors = &i2c3_errors;
|
||||
|
||||
|
||||
@@ -33,6 +33,12 @@
|
||||
#include BOARD_CONFIG
|
||||
#include "armVIC.h"
|
||||
|
||||
|
||||
static bool i2c_lpc21_idle(struct i2c_periph *p) __attribute__((unused));
|
||||
static bool i2c_lpc21_submit(struct i2c_periph *p, struct i2c_transaction *t) __attribute__((unused));
|
||||
static void i2c_lpc21_setbitrate(struct i2c_periph *p, int bitrate) __attribute__((unused));
|
||||
|
||||
|
||||
///////////////////
|
||||
// I2C Automaton //
|
||||
///////////////////
|
||||
@@ -231,6 +237,9 @@ uint8_t i2c0_vic_channel;
|
||||
/* SCL0 on P0.2 */
|
||||
void i2c0_hw_init(void)
|
||||
{
|
||||
i2c0.idle = i2c_lpc21_idle;
|
||||
i2c0.submit = i2c_lpc21_submit;
|
||||
i2c0.setbitrate = i2c_lpc21_setbitrate;
|
||||
|
||||
i2c0.reg_addr = I2C0;
|
||||
i2c0_vic_channel = VIC_I2C0;
|
||||
@@ -316,6 +325,9 @@ uint8_t i2c1_vic_channel;
|
||||
/* SCL1 on P0.11 */
|
||||
void i2c1_hw_init(void)
|
||||
{
|
||||
i2c1.idle = i2c_lpc21_idle;
|
||||
i2c1.submit = i2c_lpc21_submit;
|
||||
i2c1.setbitrate = i2c_lpc21_setbitrate;
|
||||
|
||||
i2c1.reg_addr = I2C1;
|
||||
i2c1_vic_channel = VIC_I2C1;
|
||||
@@ -341,12 +353,12 @@ void i2c1_hw_init(void)
|
||||
#endif /* USE_I2C1 */
|
||||
|
||||
|
||||
bool i2c_idle(struct i2c_periph *p)
|
||||
static bool i2c_lpc21_idle(struct i2c_periph *p)
|
||||
{
|
||||
return p->status == I2CIdle;
|
||||
}
|
||||
|
||||
bool i2c_submit(struct i2c_periph *p, struct i2c_transaction *t)
|
||||
static bool i2c_lpc21_submit(struct i2c_periph *p, struct i2c_transaction *t)
|
||||
{
|
||||
|
||||
uint8_t idx;
|
||||
@@ -383,7 +395,7 @@ bool i2c_submit(struct i2c_periph *p, struct i2c_transaction *t)
|
||||
|
||||
void i2c_event(void) { }
|
||||
|
||||
void i2c_setbitrate(struct i2c_periph *p, int bitrate)
|
||||
static void i2c_lpc21_setbitrate(struct i2c_periph *p, int bitrate)
|
||||
{
|
||||
int period = 15000000 / 2 / bitrate;
|
||||
// Max 400kpbs
|
||||
|
||||
@@ -77,5 +77,6 @@ static inline void gpio_setup_input(uint32_t port __attribute__((unused)), uint1
|
||||
static inline void gpio_set(uint32_t port __attribute__((unused)), uint16_t pin __attribute__((unused))) {}
|
||||
static inline void gpio_clear(uint32_t port __attribute__((unused)), uint16_t pin __attribute__((unused))) {}
|
||||
static inline void gpio_toggle(uint32_t port __attribute__((unused)), uint16_t pin __attribute__((unused))) {}
|
||||
static inline uint16_t gpio_get(uint32_t gpioport __attribute__((unused)), uint16_t gpios __attribute__((unused))) { return FALSE; }
|
||||
|
||||
#endif /* GPIO_ARCH_H */
|
||||
|
||||
@@ -27,16 +27,19 @@
|
||||
#include "mcu_periph/i2c.h"
|
||||
|
||||
|
||||
bool i2c_idle(struct i2c_periph *p __attribute__((unused))) { return true; }
|
||||
bool i2c_submit(struct i2c_periph *p __attribute__((unused)), struct i2c_transaction *t __attribute__((unused))) { return true;}
|
||||
static bool __attribute__((unused)) i2c_sim_idle(struct i2c_periph *p __attribute__((unused))) { return true; }
|
||||
static bool __attribute__((unused)) i2c_sim_submit(struct i2c_periph *p __attribute__((unused)), struct i2c_transaction *t __attribute__((unused))) { return true;}
|
||||
static void __attribute__((unused)) i2c_sim_setbitrate(struct i2c_periph *p __attribute__((unused)), int bitrate __attribute__((unused))) { }
|
||||
void i2c_event(void) { }
|
||||
void i2c_setbitrate(struct i2c_periph *p __attribute__((unused)), int bitrate __attribute__((unused))) { }
|
||||
|
||||
#if USE_I2C0
|
||||
struct i2c_errors i2c0_errors;
|
||||
|
||||
void i2c0_hw_init(void)
|
||||
{
|
||||
i2c0.idle = i2c_sim_idle;
|
||||
i2c0.submit = i2c_sim_submit;
|
||||
i2c0.setbitrate = i2c_sim_setbitrate;
|
||||
i2c0.errors = &i2c0_errors;
|
||||
ZEROS_ERR_COUNTER(i2c0_errors);
|
||||
}
|
||||
@@ -48,6 +51,9 @@ struct i2c_errors i2c1_errors;
|
||||
|
||||
void i2c1_hw_init(void)
|
||||
{
|
||||
i2c1.idle = i2c_sim_idle;
|
||||
i2c1.submit = i2c_sim_submit;
|
||||
i2c1.setbitrate = i2c_sim_setbitrate;
|
||||
i2c1.errors = &i2c1_errors;
|
||||
ZEROS_ERR_COUNTER(i2c1_errors);
|
||||
}
|
||||
@@ -59,6 +65,9 @@ struct i2c_errors i2c2_errors;
|
||||
|
||||
void i2c2_hw_init(void)
|
||||
{
|
||||
i2c2.idle = i2c_sim_idle;
|
||||
i2c2.submit = i2c_sim_submit;
|
||||
i2c2.setbitrate = i2c_sim_setbitrate;
|
||||
i2c2.errors = &i2c2_errors;
|
||||
ZEROS_ERR_COUNTER(i2c2_errors);
|
||||
}
|
||||
|
||||
@@ -38,6 +38,11 @@
|
||||
#include "mcu_periph/gpio.h"
|
||||
|
||||
|
||||
static bool i2c_stm32_idle(struct i2c_periph *periph) __attribute__((unused));
|
||||
static bool i2c_stm32_submit(struct i2c_periph *periph, struct i2c_transaction *t) __attribute__((unused));
|
||||
static void i2c_stm32_setbitrate(struct i2c_periph *periph, int bitrate) __attribute__((unused));
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -845,6 +850,9 @@ struct i2c_errors i2c1_errors;
|
||||
|
||||
void i2c1_hw_init(void)
|
||||
{
|
||||
i2c1.idle = i2c_stm32_idle;
|
||||
i2c1.submit = i2c_stm32_submit;
|
||||
i2c1.setbitrate = i2c_stm32_setbitrate;
|
||||
|
||||
i2c1.reg_addr = (void *)I2C1;
|
||||
i2c1.init_struct = NULL;
|
||||
@@ -916,6 +924,9 @@ struct i2c_errors i2c2_errors;
|
||||
|
||||
void i2c2_hw_init(void)
|
||||
{
|
||||
i2c2.idle = i2c_stm32_idle;
|
||||
i2c2.submit = i2c_stm32_submit;
|
||||
i2c2.setbitrate = i2c_stm32_setbitrate;
|
||||
|
||||
i2c2.reg_addr = (void *)I2C2;
|
||||
i2c2.init_struct = NULL;
|
||||
@@ -989,6 +1000,9 @@ struct i2c_errors i2c3_errors;
|
||||
|
||||
void i2c3_hw_init(void)
|
||||
{
|
||||
i2c3.idle = i2c_stm32_idle;
|
||||
i2c3.submit = i2c_stm32_submit;
|
||||
i2c3.setbitrate = i2c_stm32_setbitrate;
|
||||
|
||||
i2c3.reg_addr = (void *)I2C3;
|
||||
i2c3.init_struct = NULL;
|
||||
@@ -1054,7 +1068,7 @@ void i2c3_er_isr(void)
|
||||
// -short wires, low capacitance bus: IMU: high speed
|
||||
// -long wires with a lot of capacitance: motor controller: put speed as low as possible
|
||||
|
||||
void i2c_setbitrate(struct i2c_periph *periph, int bitrate)
|
||||
static void i2c_stm32_setbitrate(struct i2c_periph *periph, int bitrate)
|
||||
{
|
||||
// If NOT Busy
|
||||
if (i2c_idle(periph)) {
|
||||
@@ -1312,7 +1326,7 @@ void i2c_event(void)
|
||||
/////////////////////////////////////////////////////////
|
||||
// Implement Interface Functions
|
||||
|
||||
bool i2c_submit(struct i2c_periph *periph, struct i2c_transaction *t)
|
||||
static bool i2c_stm32_submit(struct i2c_periph *periph, struct i2c_transaction *t)
|
||||
{
|
||||
if (periph->watchdog > WD_DELAY) {
|
||||
return false;
|
||||
@@ -1349,7 +1363,7 @@ bool i2c_submit(struct i2c_periph *periph, struct i2c_transaction *t)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool i2c_idle(struct i2c_periph *periph)
|
||||
static bool i2c_stm32_idle(struct i2c_periph *periph)
|
||||
{
|
||||
// This is actually a difficult function:
|
||||
// -simply reading the status flags can clear bits and corrupt the transaction
|
||||
|
||||
+14
-1
@@ -43,10 +43,14 @@
|
||||
#define USING_UART 1
|
||||
#include "mcu_periph/uart.h"
|
||||
#endif
|
||||
#if USE_I2C0 || USE_I2C1 || USE_I2C2 || USE_I2C3 || USE_I2C4
|
||||
#if USE_I2C0 || USE_I2C1 || USE_I2C2 || USE_I2C3 || USE_I2C4 || USE_SOFTI2C0 || USE_SOFTI2C1
|
||||
#define USING_I2C 1
|
||||
#include "mcu_periph/i2c.h"
|
||||
#endif
|
||||
#if USE_SOFTI2C0 || USE_SOFTI2C1
|
||||
#define USING_SOFTI2C 1
|
||||
#include "mcu_periph/softi2c.h"
|
||||
#endif
|
||||
#if USE_ADC
|
||||
#include "mcu_periph/adc.h"
|
||||
#endif
|
||||
@@ -176,6 +180,12 @@ void mcu_init(void)
|
||||
#ifdef USE_I2C4
|
||||
i2c4_init();
|
||||
#endif
|
||||
#ifdef USE_SOFTI2C0
|
||||
softi2c0_init();
|
||||
#endif
|
||||
#ifdef USE_SOFTI2C1
|
||||
softi2c1_init();
|
||||
#endif
|
||||
#if USE_ADC
|
||||
adc_init();
|
||||
#endif
|
||||
@@ -250,6 +260,9 @@ void mcu_event(void)
|
||||
#if USING_I2C
|
||||
i2c_event();
|
||||
#endif
|
||||
#if USING_SOFTI2C
|
||||
softi2c_event();
|
||||
#endif
|
||||
|
||||
#if USE_USB_SERIAL
|
||||
VCOM_event();
|
||||
|
||||
@@ -249,6 +249,14 @@ static void send_i2c4_err(struct transport_tx *trans, struct link_device *dev)
|
||||
|
||||
#endif /* USE_I2C4 */
|
||||
|
||||
#if USE_SOFTI2C0
|
||||
extern void send_softi2c0_err(struct transport_tx *trans, struct link_device *dev);
|
||||
#endif /* USE_SOFTI2C0 */
|
||||
|
||||
#if USE_SOFTI2C1
|
||||
extern void send_softi2c1_err(struct transport_tx *trans, struct link_device *dev);
|
||||
#endif /* USE_SOFTI2C1 */
|
||||
|
||||
#if PERIODIC_TELEMETRY
|
||||
static void send_i2c_err(struct transport_tx *trans __attribute__((unused)),
|
||||
struct link_device *dev __attribute__((unused)))
|
||||
@@ -278,13 +286,21 @@ static void send_i2c_err(struct transport_tx *trans __attribute__((unused)),
|
||||
case 4:
|
||||
#if USE_I2C4
|
||||
send_i2c4_err(trans, dev);
|
||||
#endif
|
||||
case 5:
|
||||
#if USE_SOFTI2C0
|
||||
send_softi2c0_err(trans, dev);
|
||||
#endif
|
||||
case 6:
|
||||
#if USE_SOFTI2C1
|
||||
send_softi2c1_err(trans, dev);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
_i2c_nb_cnt++;
|
||||
if (_i2c_nb_cnt == 5) {
|
||||
if (_i2c_nb_cnt == 7) {
|
||||
_i2c_nb_cnt = 0;
|
||||
}
|
||||
}
|
||||
@@ -354,6 +370,7 @@ bool i2c_blocking_transmit(struct i2c_periph *p, struct i2c_transaction *t,
|
||||
// Wait for transaction to complete
|
||||
float start_t = get_sys_time_float();
|
||||
while (t->status == I2CTransPending || t->status == I2CTransRunning) {
|
||||
if (p->spin) p->spin(p);
|
||||
if (get_sys_time_float() - start_t > I2C_BLOCKING_TIMEOUT) {
|
||||
break; // timeout after 1 second
|
||||
}
|
||||
@@ -375,6 +392,7 @@ bool i2c_blocking_receive(struct i2c_periph *p, struct i2c_transaction *t,
|
||||
// Wait for transaction to complete
|
||||
float start_t = get_sys_time_float();
|
||||
while (t->status == I2CTransPending || t->status == I2CTransRunning) {
|
||||
if (p->spin) p->spin(p);
|
||||
if (get_sys_time_float() - start_t > I2C_BLOCKING_TIMEOUT) {
|
||||
break; // timeout after 1 second
|
||||
}
|
||||
@@ -396,6 +414,7 @@ bool i2c_blocking_transceive(struct i2c_periph *p, struct i2c_transaction *t,
|
||||
// Wait for transaction to complete
|
||||
float start_t = get_sys_time_float();
|
||||
while (t->status == I2CTransPending || t->status == I2CTransRunning) {
|
||||
if (p->spin) p->spin(p);
|
||||
if (get_sys_time_float() - start_t > I2C_BLOCKING_TIMEOUT) {
|
||||
break; // timeout after 1 second
|
||||
}
|
||||
|
||||
@@ -135,7 +135,18 @@ struct i2c_transaction {
|
||||
|
||||
/** I2C peripheral structure.
|
||||
*/
|
||||
struct i2c_periph;
|
||||
typedef bool i2c_idle_fn_t(struct i2c_periph *p);
|
||||
typedef bool i2c_submit_fn_t(struct i2c_periph *p, struct i2c_transaction *t);
|
||||
typedef void i2c_setbitrate_fn_t(struct i2c_periph *p, int bitrate);
|
||||
typedef void i2c_spin_fn_t(struct i2c_periph *p); // To update peripherals within tight loops, e.g. the blocking functions. Leave NULL if not required.
|
||||
|
||||
struct i2c_periph {
|
||||
/* architecture-specific functions */
|
||||
i2c_idle_fn_t *idle;
|
||||
i2c_submit_fn_t *submit;
|
||||
i2c_setbitrate_fn_t *setbitrate;
|
||||
i2c_spin_fn_t *spin;
|
||||
/* circular buffer holding transactions */
|
||||
struct i2c_transaction *trans[I2C_TRANSACTION_QUEUE_LEN];
|
||||
uint8_t trans_insert_idx;
|
||||
@@ -223,6 +234,18 @@ extern void i2c4_init(void);
|
||||
#endif /* USE_I2C4 */
|
||||
|
||||
|
||||
#if USE_SOFTI2C0
|
||||
extern struct i2c_periph softi2c0;
|
||||
extern void softi2c0_init(void);
|
||||
#endif /* USE_SOFTI2C0 */
|
||||
|
||||
|
||||
#if USE_SOFTI2C1
|
||||
extern struct i2c_periph softi2c1;
|
||||
extern void softi2c1_init(void);
|
||||
#endif /* USE_SOFTI2C1 */
|
||||
|
||||
|
||||
/** Initialize I2C peripheral */
|
||||
extern void i2c_init(struct i2c_periph *p);
|
||||
|
||||
@@ -230,7 +253,9 @@ extern void i2c_init(struct i2c_periph *p);
|
||||
* @param p i2c peripheral to be used
|
||||
* @return TRUE if idle
|
||||
*/
|
||||
extern bool i2c_idle(struct i2c_periph *p);
|
||||
static inline bool i2c_idle(struct i2c_periph *p) {
|
||||
return p->idle(p);
|
||||
}
|
||||
|
||||
/** Submit a I2C transaction.
|
||||
* Must be implemented by the underlying architecture
|
||||
@@ -238,13 +263,18 @@ extern bool i2c_idle(struct i2c_periph *p);
|
||||
* @param t i2c transaction
|
||||
* @return TRUE if insertion to the transaction queue succeeded
|
||||
*/
|
||||
extern bool i2c_submit(struct i2c_periph *p, struct i2c_transaction *t);
|
||||
static inline bool i2c_submit(struct i2c_periph *p, struct i2c_transaction *t) {
|
||||
return p->submit(p, t);
|
||||
}
|
||||
|
||||
/** Set I2C bitrate.
|
||||
* @param p i2c peripheral to be used
|
||||
* @param bitrate bitrate
|
||||
*/
|
||||
extern void i2c_setbitrate(struct i2c_periph *p, int bitrate);
|
||||
static inline void i2c_setbitrate(struct i2c_periph *p, int bitrate) {
|
||||
p->setbitrate(p, bitrate);
|
||||
}
|
||||
|
||||
extern void i2c_event(void);
|
||||
|
||||
/*
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Tom van Dijk <tomvand@users.noreply.github.com>
|
||||
*
|
||||
* This file is part of paparazzi.
|
||||
*
|
||||
* paparazzi is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* paparazzi is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with paparazzi; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file mcu_periph/softi2c.h
|
||||
* Platform-independent software I2C implementation.
|
||||
* Can be used transparently in place of the hardware I2C in i2c.h.
|
||||
*/
|
||||
|
||||
#ifndef MCU_PERIPH_SOFTI2C_H
|
||||
#define MCU_PERIPH_SOFTI2C_H
|
||||
|
||||
#include "mcu_periph/i2c.h"
|
||||
|
||||
|
||||
void softi2c_event(void);
|
||||
|
||||
|
||||
#if USE_SOFTI2C0
|
||||
extern void softi2c0_hw_init(void);
|
||||
#endif /* USE_SOFTI2C0 */
|
||||
|
||||
#if USE_SOFTI2C1
|
||||
extern void softi2c1_hw_init(void);
|
||||
#endif /* USE_SOFTI2C1 */
|
||||
|
||||
|
||||
#endif // MCU_PERIPH_SOFTI2C_H
|
||||
Reference in New Issue
Block a user