diff --git a/conf/messages.xml b/conf/messages.xml index 456a1cd8ab..683bac8e3c 100644 --- a/conf/messages.xml +++ b/conf/messages.xml @@ -2076,6 +2076,7 @@ + diff --git a/sw/airborne/arch/lpc21/mcu_periph/i2c_arch.c b/sw/airborne/arch/lpc21/mcu_periph/i2c_arch.c index 5838dcea14..0f405325d3 100644 --- a/sw/airborne/arch/lpc21/mcu_periph/i2c_arch.c +++ b/sw/airborne/arch/lpc21/mcu_periph/i2c_arch.c @@ -336,8 +336,10 @@ bool_t i2c_submit(struct i2c_periph* p, struct i2c_transaction* t) { idx = p->trans_insert_idx + 1; if (idx >= I2C_TRANSACTION_QUEUE_LEN) idx = 0; if (idx == p->trans_extract_idx) { + /* queue full */ + periph->errors->queue_full_cnt++; t->status = I2CTransFailed; - return FALSE; /* queue full */ + return FALSE; } t->status = I2CTransPending; diff --git a/sw/airborne/arch/stm32/mcu_periph/i2c_arch.c b/sw/airborne/arch/stm32/mcu_periph/i2c_arch.c index 046f0c9441..38e737db23 100644 --- a/sw/airborne/arch/stm32/mcu_periph/i2c_arch.c +++ b/sw/airborne/arch/stm32/mcu_periph/i2c_arch.c @@ -1316,8 +1316,12 @@ bool_t i2c_submit(struct i2c_periph* periph, struct i2c_transaction* t) { uint8_t temp; temp = periph->trans_insert_idx + 1; if (temp >= I2C_TRANSACTION_QUEUE_LEN) temp = 0; - if (temp == periph->trans_extract_idx) - return FALSE; // queue full + if (temp == periph->trans_extract_idx) { + // queue full + periph->errors->queue_full_cnt++; + t->status = I2CTransFailed; + return FALSE; + } t->status = I2CTransPending; diff --git a/sw/airborne/firmwares/fixedwing/ap_downlink.h b/sw/airborne/firmwares/fixedwing/ap_downlink.h index 76bdf38f2b..dc7ede333a 100644 --- a/sw/airborne/firmwares/fixedwing/ap_downlink.h +++ b/sw/airborne/firmwares/fixedwing/ap_downlink.h @@ -47,6 +47,9 @@ #include "messages.h" #include "generated/periodic_telemetry.h" +// I2C Error counters +#include "mcu_periph/i2c.h" + #if defined DOWNLINK #define Downlink(x) x #else @@ -333,4 +336,147 @@ #define PERIODIC_SEND_GX3_INFO(_trans, _dev) {} #endif +#ifdef USE_I2C0 +#define PERIODIC_SEND_I2C0_ERRORS(_trans, _dev) { \ + uint16_t i2c0_queue_full_cnt = i2c0.errors->queue_full_cnt; \ + uint16_t i2c0_ack_fail_cnt = i2c0.errors->ack_fail_cnt; \ + uint16_t i2c0_miss_start_stop_cnt = i2c0.errors->miss_start_stop_cnt; \ + uint16_t i2c0_arb_lost_cnt = i2c0.errors->arb_lost_cnt; \ + uint16_t i2c0_over_under_cnt = i2c0.errors->over_under_cnt; \ + uint16_t i2c0_pec_recep_cnt = i2c0.errors->pec_recep_cnt; \ + uint16_t i2c0_timeout_tlow_cnt = i2c0.errors->timeout_tlow_cnt; \ + uint16_t i2c0_smbus_alert_cnt = i2c0.errors->smbus_alert_cnt; \ + uint16_t i2c0_unexpected_event_cnt = i2c0.errors->unexpected_event_cnt; \ + uint32_t i2c0_last_unexpected_event = i2c0.errors->last_unexpected_event; \ + const uint8_t _bus0 = 0; \ + DOWNLINK_SEND_I2C_ERRORS(_trans, _dev, \ + &i2c0_queue_full_cnt, \ + &i2c0_ack_fail_cnt, \ + &i2c0_miss_start_stop_cnt, \ + &i2c0_arb_lost_cnt, \ + &i2c0_over_under_cnt, \ + &i2c0_pec_recep_cnt, \ + &i2c0_timeout_tlow_cnt, \ + &i2c0_smbus_alert_cnt, \ + &i2c0_unexpected_event_cnt, \ + &i2c0_last_unexpected_event, \ + &_bus0); \ + } +#else +#define PERIODIC_SEND_I2C0_ERRORS(_trans, _dev) {} +#endif + +#ifdef USE_I2C1 +#define PERIODIC_SEND_I2C1_ERRORS(_trans, _dev) { \ + uint16_t i2c1_queue_full_cnt = i2c1.errors->queue_full_cnt; \ + uint16_t i2c1_ack_fail_cnt = i2c1.errors->ack_fail_cnt; \ + uint16_t i2c1_miss_start_stop_cnt = i2c1.errors->miss_start_stop_cnt; \ + uint16_t i2c1_arb_lost_cnt = i2c1.errors->arb_lost_cnt; \ + uint16_t i2c1_over_under_cnt = i2c1.errors->over_under_cnt; \ + uint16_t i2c1_pec_recep_cnt = i2c1.errors->pec_recep_cnt; \ + uint16_t i2c1_timeout_tlow_cnt = i2c1.errors->timeout_tlow_cnt; \ + uint16_t i2c1_smbus_alert_cnt = i2c1.errors->smbus_alert_cnt; \ + uint16_t i2c1_unexpected_event_cnt = i2c1.errors->unexpected_event_cnt; \ + uint32_t i2c1_last_unexpected_event = i2c1.errors->last_unexpected_event; \ + const uint8_t _bus1 = 1; \ + DOWNLINK_SEND_I2C_ERRORS(_trans, _dev, \ + &i2c1_queue_full_cnt, \ + &i2c1_ack_fail_cnt, \ + &i2c1_miss_start_stop_cnt, \ + &i2c1_arb_lost_cnt, \ + &i2c1_over_under_cnt, \ + &i2c1_pec_recep_cnt, \ + &i2c1_timeout_tlow_cnt, \ + &i2c1_smbus_alert_cnt, \ + &i2c1_unexpected_event_cnt, \ + &i2c1_last_unexpected_event, \ + &_bus1); \ + } +#else +#define PERIODIC_SEND_I2C1_ERRORS(_trans, _dev) {} +#endif + +#ifdef USE_I2C2 +#define PERIODIC_SEND_I2C2_ERRORS(_trans, _dev) { \ + uint16_t i2c2_queue_full_cnt = i2c2.errors->queue_full_cnt; \ + uint16_t i2c2_ack_fail_cnt = i2c2.errors->ack_fail_cnt; \ + uint16_t i2c2_miss_start_stop_cnt = i2c2.errors->miss_start_stop_cnt; \ + uint16_t i2c2_arb_lost_cnt = i2c2.errors->arb_lost_cnt; \ + uint16_t i2c2_over_under_cnt = i2c2.errors->over_under_cnt; \ + uint16_t i2c2_pec_recep_cnt = i2c2.errors->pec_recep_cnt; \ + uint16_t i2c2_timeout_tlow_cnt = i2c2.errors->timeout_tlow_cnt; \ + uint16_t i2c2_smbus_alert_cnt = i2c2.errors->smbus_alert_cnt; \ + uint16_t i2c2_unexpected_event_cnt = i2c2.errors->unexpected_event_cnt; \ + uint32_t i2c2_last_unexpected_event = i2c2.errors->last_unexpected_event; \ + const uint8_t _bus2 = 2; \ + DOWNLINK_SEND_I2C_ERRORS(_trans, _dev, \ + &i2c2_queue_full_cnt, \ + &i2c2_ack_fail_cnt, \ + &i2c2_miss_start_stop_cnt, \ + &i2c2_arb_lost_cnt, \ + &i2c2_over_under_cnt, \ + &i2c2_pec_recep_cnt, \ + &i2c2_timeout_tlow_cnt, \ + &i2c2_smbus_alert_cnt, \ + &i2c2_unexpected_event_cnt, \ + &i2c2_last_unexpected_event, \ + &_bus2); \ + } +#else +#define PERIODIC_SEND_I2C2_ERRORS(_trans, _dev) {} +#endif + +#ifdef USE_I2C3 +#define PERIODIC_SEND_I2C3_ERRORS(_trans, _dev) { \ + uint16_t i2c3_queue_full_cnt = i2c3.errors->queue_full_cnt; \ + uint16_t i2c3_ack_fail_cnt = i2c3.errors->ack_fail_cnt; \ + uint16_t i2c3_miss_start_stop_cnt = i2c3.errors->miss_start_stop_cnt; \ + uint16_t i2c3_arb_lost_cnt = i2c3.errors->arb_lost_cnt; \ + uint16_t i2c3_over_under_cnt = i2c3.errors->over_under_cnt; \ + uint16_t i2c3_pec_recep_cnt = i2c3.errors->pec_recep_cnt; \ + uint16_t i2c3_timeout_tlow_cnt = i2c3.errors->timeout_tlow_cnt; \ + uint16_t i2c3_smbus_alert_cnt = i2c3.errors->smbus_alert_cnt; \ + uint16_t i2c3_unexpected_event_cnt = i2c3.errors->unexpected_event_cnt; \ + uint32_t i2c3_last_unexpected_event = i2c3.errors->last_unexpected_event; \ + const uint8_t _bus3 = 3; \ + DOWNLINK_SEND_I2C_ERRORS(_trans, _dev, \ + &i2c3_queue_full_cnt, \ + &i2c3_ack_fail_cnt, \ + &i2c3_miss_start_stop_cnt, \ + &i2c3_arb_lost_cnt, \ + &i2c3_over_under_cnt, \ + &i2c3_pec_recep_cnt, \ + &i2c3_timeout_tlow_cnt, \ + &i2c3_smbus_alert_cnt, \ + &i2c3_unexpected_event_cnt, \ + &i2c3_last_unexpected_event, \ + &_bus3); \ + } +#else +#define PERIODIC_SEND_I2C3_ERRORS(_trans, _dev) {} +#endif + +#ifndef SITL +#define PERIODIC_SEND_I2C_ERRORS(_trans, _dev) { \ + static uint8_t _i2c_nb_cnt = 0; \ + switch (_i2c_nb_cnt) { \ + case 0: \ + PERIODIC_SEND_I2C0_ERRORS(_trans, _dev); break; \ + case 1: \ + PERIODIC_SEND_I2C1_ERRORS(_trans, _dev); break; \ + case 2: \ + PERIODIC_SEND_I2C2_ERRORS(_trans, _dev); break; \ + case 3: \ + PERIODIC_SEND_I2C3_ERRORS(_trans, _dev); break; \ + default: \ + break; \ + } \ + _i2c_nb_cnt++; \ + if (_i2c_nb_cnt == 3) \ + _i2c_nb_cnt = 0; \ + } +#else +#define PERIODIC_SEND_I2C_ERRORS(_trans, _dev) {} +#endif + #endif /* AP_DOWNLINK_H */ diff --git a/sw/airborne/firmwares/rotorcraft/telemetry.h b/sw/airborne/firmwares/rotorcraft/telemetry.h index 4522d049b4..a1b3472812 100644 --- a/sw/airborne/firmwares/rotorcraft/telemetry.h +++ b/sw/airborne/firmwares/rotorcraft/telemetry.h @@ -774,6 +774,7 @@ #ifdef USE_I2C0 #define PERIODIC_SEND_I2C0_ERRORS(_trans, _dev) { \ + uint16_t i2c0_queue_full_cnt = i2c0.errors->queue_full_cnt; \ uint16_t i2c0_ack_fail_cnt = i2c0.errors->ack_fail_cnt; \ uint16_t i2c0_miss_start_stop_cnt = i2c0.errors->miss_start_stop_cnt; \ uint16_t i2c0_arb_lost_cnt = i2c0.errors->arb_lost_cnt; \ @@ -785,6 +786,7 @@ uint32_t i2c0_last_unexpected_event = i2c0.errors->last_unexpected_event; \ const uint8_t _bus0 = 0; \ DOWNLINK_SEND_I2C_ERRORS(_trans, _dev, \ + &i2c0_queue_full_cnt, \ &i2c0_ack_fail_cnt, \ &i2c0_miss_start_stop_cnt, \ &i2c0_arb_lost_cnt, \ @@ -802,6 +804,7 @@ #ifdef USE_I2C1 #define PERIODIC_SEND_I2C1_ERRORS(_trans, _dev) { \ + uint16_t i2c1_queue_full_cnt = i2c1.errors->queue_full_cnt; \ uint16_t i2c1_ack_fail_cnt = i2c1.errors->ack_fail_cnt; \ uint16_t i2c1_miss_start_stop_cnt = i2c1.errors->miss_start_stop_cnt; \ uint16_t i2c1_arb_lost_cnt = i2c1.errors->arb_lost_cnt; \ @@ -813,6 +816,7 @@ uint32_t i2c1_last_unexpected_event = i2c1.errors->last_unexpected_event; \ const uint8_t _bus1 = 1; \ DOWNLINK_SEND_I2C_ERRORS(_trans, _dev, \ + &i2c1_queue_full_cnt, \ &i2c1_ack_fail_cnt, \ &i2c1_miss_start_stop_cnt, \ &i2c1_arb_lost_cnt, \ @@ -830,6 +834,7 @@ #ifdef USE_I2C2 #define PERIODIC_SEND_I2C2_ERRORS(_trans, _dev) { \ + uint16_t i2c2_queue_full_cnt = i2c2.errors->queue_full_cnt; \ uint16_t i2c2_ack_fail_cnt = i2c2.errors->ack_fail_cnt; \ uint16_t i2c2_miss_start_stop_cnt = i2c2.errors->miss_start_stop_cnt; \ uint16_t i2c2_arb_lost_cnt = i2c2.errors->arb_lost_cnt; \ @@ -841,6 +846,7 @@ uint32_t i2c2_last_unexpected_event = i2c2.errors->last_unexpected_event; \ const uint8_t _bus2 = 2; \ DOWNLINK_SEND_I2C_ERRORS(_trans, _dev, \ + &i2c2_queue_full_cnt, \ &i2c2_ack_fail_cnt, \ &i2c2_miss_start_stop_cnt, \ &i2c2_arb_lost_cnt, \ @@ -856,6 +862,36 @@ #define PERIODIC_SEND_I2C2_ERRORS(_trans, _dev) {} #endif +#ifdef USE_I2C3 +#define PERIODIC_SEND_I2C3_ERRORS(_trans, _dev) { \ + uint16_t i2c3_queue_full_cnt = i2c3.errors->queue_full_cnt; \ + uint16_t i2c3_ack_fail_cnt = i2c3.errors->ack_fail_cnt; \ + uint16_t i2c3_miss_start_stop_cnt = i2c3.errors->miss_start_stop_cnt; \ + uint16_t i2c3_arb_lost_cnt = i2c3.errors->arb_lost_cnt; \ + uint16_t i2c3_over_under_cnt = i2c3.errors->over_under_cnt; \ + uint16_t i2c3_pec_recep_cnt = i2c3.errors->pec_recep_cnt; \ + uint16_t i2c3_timeout_tlow_cnt = i2c3.errors->timeout_tlow_cnt; \ + uint16_t i2c3_smbus_alert_cnt = i2c3.errors->smbus_alert_cnt; \ + uint16_t i2c3_unexpected_event_cnt = i2c3.errors->unexpected_event_cnt; \ + uint32_t i2c3_last_unexpected_event = i2c3.errors->last_unexpected_event; \ + const uint8_t _bus3 = 3; \ + DOWNLINK_SEND_I2C_ERRORS(_trans, _dev, \ + &i2c3_queue_full_cnt, \ + &i2c3_ack_fail_cnt, \ + &i2c3_miss_start_stop_cnt, \ + &i2c3_arb_lost_cnt, \ + &i2c3_over_under_cnt, \ + &i2c3_pec_recep_cnt, \ + &i2c3_timeout_tlow_cnt, \ + &i2c3_smbus_alert_cnt, \ + &i2c3_unexpected_event_cnt, \ + &i2c3_last_unexpected_event, \ + &_bus3); \ + } +#else +#define PERIODIC_SEND_I2C3_ERRORS(_trans, _dev) {} +#endif + #ifndef SITL #define PERIODIC_SEND_I2C_ERRORS(_trans, _dev) { \ static uint8_t _i2c_nb_cnt = 0; \ @@ -866,6 +902,8 @@ PERIODIC_SEND_I2C1_ERRORS(_trans, _dev); break; \ case 2: \ PERIODIC_SEND_I2C2_ERRORS(_trans, _dev); break; \ + case 3: \ + PERIODIC_SEND_I2C3_ERRORS(_trans, _dev); break; \ default: \ break; \ } \ diff --git a/sw/airborne/mcu_periph/i2c.h b/sw/airborne/mcu_periph/i2c.h index ac8872bd9c..5d0220ebda 100644 --- a/sw/airborne/mcu_periph/i2c.h +++ b/sw/airborne/mcu_periph/i2c.h @@ -102,6 +102,7 @@ struct i2c_periph { struct i2c_errors { + volatile uint16_t queue_full_cnt; volatile uint16_t ack_fail_cnt; volatile uint16_t miss_start_stop_cnt; volatile uint16_t arb_lost_cnt; @@ -126,6 +127,7 @@ struct i2c_errors { } #define ZEROS_ERR_COUNTER(_i2c_err) { \ + _i2c_err.queue_full_cnt = 0; \ _i2c_err.ack_fail_cnt = 0; \ _i2c_err.miss_start_stop_cnt = 0; \ _i2c_err.arb_lost_cnt = 0; \