mirror of
https://github.com/paparazzi/paparazzi.git
synced 2026-06-02 21:37:24 +08:00
[mcu] add support for I2C4 and SPI4
This commit is contained in:
@@ -105,7 +105,7 @@
|
|||||||
* @brief Enables the I2C subsystem.
|
* @brief Enables the I2C subsystem.
|
||||||
*/
|
*/
|
||||||
#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
|
#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
|
||||||
#if USE_I2C1 || USE_I2C2 || USE_I2C3
|
#if USE_I2C1 || USE_I2C2 || USE_I2C3 || USE_I2C4
|
||||||
#define HAL_USE_I2C TRUE
|
#define HAL_USE_I2C TRUE
|
||||||
#else
|
#else
|
||||||
#define HAL_USE_I2C FALSE
|
#define HAL_USE_I2C FALSE
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
#define I2C_THREAD_STACK_SIZE 512
|
#define I2C_THREAD_STACK_SIZE 512
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if USE_I2C1 || USE_I2C2 || USE_I2C3
|
#if USE_I2C1 || USE_I2C2 || USE_I2C3 || USE_I2C4
|
||||||
|
|
||||||
// private I2C init structure
|
// private I2C init structure
|
||||||
struct i2c_init {
|
struct i2c_init {
|
||||||
@@ -177,7 +177,7 @@ static void handle_i2c_thd(struct i2c_periph *p)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* USE_I2C1 || USE_I2C2 || USE_I2C3 */
|
#endif /* USE_I2C1 || USE_I2C2 || USE_I2C3 || USE_I2C4 */
|
||||||
|
|
||||||
#if USE_I2C1
|
#if USE_I2C1
|
||||||
// I2C1 config
|
// I2C1 config
|
||||||
@@ -342,6 +342,61 @@ static void thd_i2c3(void *arg)
|
|||||||
}
|
}
|
||||||
#endif /* USE_I2C3 */
|
#endif /* USE_I2C3 */
|
||||||
|
|
||||||
|
#if USE_I2C4
|
||||||
|
// I2C4 config
|
||||||
|
PRINT_CONFIG_VAR(I2C4_CLOCK_SPEED)
|
||||||
|
static SEMAPHORE_DECL(i2c4_sem, 0);
|
||||||
|
static I2CConfig i2cfg4 = I2C4_CFG_DEF;
|
||||||
|
#if defined STM32F7
|
||||||
|
// We need a special buffer for DMA operations
|
||||||
|
static IN_DMA_SECTION(uint8_t i2c4_dma_buf[I2C_BUF_LEN]);
|
||||||
|
static struct i2c_init i2c4_init_s = {
|
||||||
|
.sem = &i2c4_sem,
|
||||||
|
.cfg = &i2cfg4,
|
||||||
|
.dma_buf = i2c4_dma_buf
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
static struct i2c_init i2c4_init_s = {
|
||||||
|
.sem = &i2c4_sem,
|
||||||
|
.cfg = &i2cfg4
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
// Errors
|
||||||
|
struct i2c_errors i2c4_errors;
|
||||||
|
// Thread
|
||||||
|
static __attribute__((noreturn)) void thd_i2c4(void *arg);
|
||||||
|
static THD_WORKING_AREA(wa_thd_i2c4, 128);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* I2C4 init
|
||||||
|
*/
|
||||||
|
void i2c4_hw_init(void)
|
||||||
|
{
|
||||||
|
i2cStart(&I2CD4, &i2cfg4);
|
||||||
|
i2c4.reg_addr = &I2CD4;
|
||||||
|
i2c4.init_struct = NULL;
|
||||||
|
i2c4.errors = &i2c4_errors;
|
||||||
|
i2c4.init_struct = &i2c4_init_s;
|
||||||
|
// Create thread
|
||||||
|
chThdCreateStatic(wa_thd_i2c4, sizeof(wa_thd_i2c4),
|
||||||
|
NORMALPRIO + 1, thd_i2c4, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* I2C4 thread
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void thd_i2c4(void *arg)
|
||||||
|
{
|
||||||
|
(void) arg;
|
||||||
|
chRegSetThreadName("i2c4");
|
||||||
|
|
||||||
|
while (TRUE) {
|
||||||
|
handle_i2c_thd(&i2c4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* USE_I2C4 */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* i2c_event() function
|
* i2c_event() function
|
||||||
@@ -377,7 +432,7 @@ void i2c_setbitrate(struct i2c_periph *p __attribute__((unused)), int bitrate __
|
|||||||
*/
|
*/
|
||||||
bool i2c_submit(struct i2c_periph *p, struct i2c_transaction *t)
|
bool i2c_submit(struct i2c_periph *p, struct i2c_transaction *t)
|
||||||
{
|
{
|
||||||
#if USE_I2C1 || USE_I2C2 || USE_I2C3
|
#if USE_I2C1 || USE_I2C2 || USE_I2C3 || USE_I2C4
|
||||||
// sys lock
|
// sys lock
|
||||||
chSysLock();
|
chSysLock();
|
||||||
uint8_t temp;
|
uint8_t temp;
|
||||||
@@ -406,7 +461,7 @@ bool i2c_submit(struct i2c_periph *p, struct i2c_transaction *t)
|
|||||||
(void)p;
|
(void)p;
|
||||||
(void)t;
|
(void)t;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
#endif /* USE_I2C1 || USE_I2C2 || USE_I2C3 */
|
#endif /* USE_I2C1 || USE_I2C2 || USE_I2C3 || USE_I2C4 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -45,4 +45,8 @@ extern void i2c2_hw_init(void);
|
|||||||
extern void i2c3_hw_init(void);
|
extern void i2c3_hw_init(void);
|
||||||
#endif /* USE_I2C3 */
|
#endif /* USE_I2C3 */
|
||||||
|
|
||||||
|
#if USE_I2C4
|
||||||
|
extern void i2c4_hw_init(void);
|
||||||
|
#endif /* USE_I2C4 */
|
||||||
|
|
||||||
#endif /* I2C_HW_H */
|
#endif /* I2C_HW_H */
|
||||||
|
|||||||
@@ -167,10 +167,12 @@ static inline uint16_t spi_resolve_slave_pin(uint8_t slave)
|
|||||||
static inline uint16_t spi_resolve_CR1(struct spi_transaction *t __attribute__((unused)))
|
static inline uint16_t spi_resolve_CR1(struct spi_transaction *t __attribute__((unused)))
|
||||||
{
|
{
|
||||||
uint16_t CR1 = 0;
|
uint16_t CR1 = 0;
|
||||||
#if defined(STM32F1) || defined(STM32F4) || defined(STM32F7)
|
#if defined(STM32F1) || defined(STM32F4)
|
||||||
if (t->dss == SPIDss16bit) {
|
if (t->dss == SPIDss16bit) {
|
||||||
CR1 |= SPI_CR1_DFF;
|
CR1 |= SPI_CR1_DFF; // FIXME for F7
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(STM32F1) || defined(STM32F4) || defined(STM32F7)
|
||||||
if (t->bitorder == SPILSBFirst) {
|
if (t->bitorder == SPILSBFirst) {
|
||||||
CR1 |= SPI_CR1_LSBFIRST;
|
CR1 |= SPI_CR1_LSBFIRST;
|
||||||
}
|
}
|
||||||
@@ -443,6 +445,45 @@ void spi3_arch_init(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if USE_SPI4
|
||||||
|
static SEMAPHORE_DECL(spi4_sem, 0);
|
||||||
|
#if defined STM32F7
|
||||||
|
// We need a special buffer for DMA operations
|
||||||
|
static IN_DMA_SECTION(uint8_t spi4_dma_buf_out[SPI_DMA_BUF_LEN]);
|
||||||
|
static IN_DMA_SECTION(uint8_t spi4_dma_buf_in[SPI_DMA_BUF_LEN]);
|
||||||
|
static struct spi_init spi4_init_s = {
|
||||||
|
.sem = &spi4_sem,
|
||||||
|
.dma_buf_out = spi4_dma_buf_out,
|
||||||
|
.dma_buf_in = spi4_dma_buf_in
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
static struct spi_init spi4_init_s = {
|
||||||
|
.sem = &spi4_sem,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static __attribute__((noreturn)) void thd_spi4(void *arg)
|
||||||
|
{
|
||||||
|
(void) arg;
|
||||||
|
chRegSetThreadName("spi4");
|
||||||
|
|
||||||
|
while (TRUE) {
|
||||||
|
handle_spi_thd(&spi4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static THD_WORKING_AREA(wa_thd_spi4, 256);
|
||||||
|
|
||||||
|
void spi4_arch_init(void)
|
||||||
|
{
|
||||||
|
spi4.reg_addr = &SPID4;
|
||||||
|
spi4.init_struct = &spi4_init_s;
|
||||||
|
// Create thread
|
||||||
|
chThdCreateStatic(wa_thd_spi4, sizeof(wa_thd_spi4),
|
||||||
|
NORMALPRIO + 1, thd_spi4, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submit SPI transaction
|
* Submit SPI transaction
|
||||||
|
|||||||
+7
-1
@@ -43,7 +43,7 @@
|
|||||||
#define USING_UART 1
|
#define USING_UART 1
|
||||||
#include "mcu_periph/uart.h"
|
#include "mcu_periph/uart.h"
|
||||||
#endif
|
#endif
|
||||||
#if USE_I2C0 || USE_I2C1 || USE_I2C2 || USE_I2C3
|
#if USE_I2C0 || USE_I2C1 || USE_I2C2 || USE_I2C3 || USE_I2C4
|
||||||
#define USING_I2C 1
|
#define USING_I2C 1
|
||||||
#include "mcu_periph/i2c.h"
|
#include "mcu_periph/i2c.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -173,6 +173,9 @@ void mcu_init(void)
|
|||||||
#ifdef USE_I2C3
|
#ifdef USE_I2C3
|
||||||
i2c3_init();
|
i2c3_init();
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USE_I2C4
|
||||||
|
i2c4_init();
|
||||||
|
#endif
|
||||||
#if USE_ADC
|
#if USE_ADC
|
||||||
adc_init();
|
adc_init();
|
||||||
#endif
|
#endif
|
||||||
@@ -194,6 +197,9 @@ void mcu_init(void)
|
|||||||
#endif
|
#endif
|
||||||
#if USE_SPI3
|
#if USE_SPI3
|
||||||
spi3_init();
|
spi3_init();
|
||||||
|
#endif
|
||||||
|
#if USE_SPI4
|
||||||
|
spi4_init();
|
||||||
#endif
|
#endif
|
||||||
spi_init_slaves();
|
spi_init_slaves();
|
||||||
#endif // SPI_MASTER
|
#endif // SPI_MASTER
|
||||||
|
|||||||
@@ -206,6 +206,49 @@ static void send_i2c3_err(struct transport_tx *trans, struct link_device *dev)
|
|||||||
|
|
||||||
#endif /* USE_I2C3 */
|
#endif /* USE_I2C3 */
|
||||||
|
|
||||||
|
#if USE_I2C4
|
||||||
|
|
||||||
|
struct i2c_periph i2c4;
|
||||||
|
|
||||||
|
void i2c4_init(void)
|
||||||
|
{
|
||||||
|
i2c_init(&i2c4);
|
||||||
|
i2c4_hw_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if PERIODIC_TELEMETRY
|
||||||
|
static void send_i2c4_err(struct transport_tx *trans, struct link_device *dev)
|
||||||
|
{
|
||||||
|
uint16_t i2c4_wd_reset_cnt = i2c4.errors->wd_reset_cnt;
|
||||||
|
uint16_t i2c4_queue_full_cnt = i2c4.errors->queue_full_cnt;
|
||||||
|
uint16_t i2c4_ack_fail_cnt = i2c4.errors->ack_fail_cnt;
|
||||||
|
uint16_t i2c4_miss_start_stop_cnt = i2c4.errors->miss_start_stop_cnt;
|
||||||
|
uint16_t i2c4_arb_lost_cnt = i2c4.errors->arb_lost_cnt;
|
||||||
|
uint16_t i2c4_over_under_cnt = i2c4.errors->over_under_cnt;
|
||||||
|
uint16_t i2c4_pec_recep_cnt = i2c4.errors->pec_recep_cnt;
|
||||||
|
uint16_t i2c4_timeout_tlow_cnt = i2c4.errors->timeout_tlow_cnt;
|
||||||
|
uint16_t i2c4_smbus_alert_cnt = i2c4.errors->smbus_alert_cnt;
|
||||||
|
uint16_t i2c4_unexpected_event_cnt = i2c4.errors->unexpected_event_cnt;
|
||||||
|
uint32_t i2c4_last_unexpected_event = i2c4.errors->last_unexpected_event;
|
||||||
|
uint8_t _bus4 = 4;
|
||||||
|
pprz_msg_send_I2C_ERRORS(trans, dev, AC_ID,
|
||||||
|
&i2c4_wd_reset_cnt,
|
||||||
|
&i2c4_queue_full_cnt,
|
||||||
|
&i2c4_ack_fail_cnt,
|
||||||
|
&i2c4_miss_start_stop_cnt,
|
||||||
|
&i2c4_arb_lost_cnt,
|
||||||
|
&i2c4_over_under_cnt,
|
||||||
|
&i2c4_pec_recep_cnt,
|
||||||
|
&i2c4_timeout_tlow_cnt,
|
||||||
|
&i2c4_smbus_alert_cnt,
|
||||||
|
&i2c4_unexpected_event_cnt,
|
||||||
|
&i2c4_last_unexpected_event,
|
||||||
|
&_bus4);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* USE_I2C4 */
|
||||||
|
|
||||||
#if PERIODIC_TELEMETRY
|
#if PERIODIC_TELEMETRY
|
||||||
static void send_i2c_err(struct transport_tx *trans __attribute__((unused)),
|
static void send_i2c_err(struct transport_tx *trans __attribute__((unused)),
|
||||||
struct link_device *dev __attribute__((unused)))
|
struct link_device *dev __attribute__((unused)))
|
||||||
@@ -230,6 +273,11 @@ static void send_i2c_err(struct transport_tx *trans __attribute__((unused)),
|
|||||||
case 3:
|
case 3:
|
||||||
#if USE_I2C3
|
#if USE_I2C3
|
||||||
send_i2c3_err(trans, dev);
|
send_i2c3_err(trans, dev);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
#if USE_I2C4
|
||||||
|
send_i2c4_err(trans, dev);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -215,6 +215,14 @@ extern void i2c3_init(void);
|
|||||||
#endif /* USE_I2C3 */
|
#endif /* USE_I2C3 */
|
||||||
|
|
||||||
|
|
||||||
|
#if USE_I2C4
|
||||||
|
|
||||||
|
extern struct i2c_periph i2c4;
|
||||||
|
extern void i2c4_init(void);
|
||||||
|
|
||||||
|
#endif /* USE_I2C4 */
|
||||||
|
|
||||||
|
|
||||||
/** Initialize I2C peripheral */
|
/** Initialize I2C peripheral */
|
||||||
extern void i2c_init(struct i2c_periph *p);
|
extern void i2c_init(struct i2c_periph *p);
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,17 @@ void spi3_init(void)
|
|||||||
#endif // USE_SPI3
|
#endif // USE_SPI3
|
||||||
|
|
||||||
|
|
||||||
|
#if USE_SPI4
|
||||||
|
struct spi_periph spi4;
|
||||||
|
|
||||||
|
void spi4_init(void)
|
||||||
|
{
|
||||||
|
spi_init(&spi4);
|
||||||
|
spi4_arch_init();
|
||||||
|
}
|
||||||
|
#endif // USE_SPI4
|
||||||
|
|
||||||
|
|
||||||
void spi_init(struct spi_periph *p)
|
void spi_init(struct spi_periph *p)
|
||||||
{
|
{
|
||||||
p->trans_insert_idx = 0;
|
p->trans_insert_idx = 0;
|
||||||
|
|||||||
@@ -241,6 +241,18 @@ extern void spi3_arch_init(void);
|
|||||||
|
|
||||||
#endif // USE_SPI3
|
#endif // USE_SPI3
|
||||||
|
|
||||||
|
#if USE_SPI4
|
||||||
|
|
||||||
|
extern struct spi_periph spi4;
|
||||||
|
extern void spi4_init(void);
|
||||||
|
|
||||||
|
/** Architecture dependent SPI4 initialization.
|
||||||
|
* Must be implemented by underlying architecture
|
||||||
|
*/
|
||||||
|
extern void spi4_arch_init(void);
|
||||||
|
|
||||||
|
#endif // USE_SPI4
|
||||||
|
|
||||||
/** Initialize a spi peripheral.
|
/** Initialize a spi peripheral.
|
||||||
* @param p spi peripheral to be configured
|
* @param p spi peripheral to be configured
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user