mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-01-18 03:52:11 +01:00
PiOS/I2C: Lots of small changes. Added a few weird bus events that are
sometimes thrown, and made errors not lock it up by default. It works for me, but since this has historically been associated with lots of lock ups please check your systems carefully. PiOS/I2C: Make the bus by default try to recover from errors instead of locking up PiOS/I2C: After a bus error and clocking all previous data create a STOP condition to make sure bus is released (note, this also requires creating a START condition first) PiOS/I2C: If the same event hits the I2C bus twice in a row then disregard second one, there is no situation where we should get the same event multiple times that matters and this gets us out really quickly to catch the real events. I was seeing this with repeated 0x70084 which means byte transmitted. This is related to STM32 bugs in the IRQ timings I believe. PiOS/I2C: 1) Mask out some bits we don't care about in the event flags 2) Don't lock up if the give semaphore fails, although why it does is strange 3) Recover from bus failure through the "auto" state path instead of just coding state PiOS/I2C: Change the reset bus code to follow http://www.analog.com/static/imported-files/application_notes/54305147357414AN686_0.pdf (thanks for the reference Neontangerine). Although this may actually NOT clear the bus the first time through, subsequent bus errors should eventually clock it out. The up side is it is less likely to clock a bunch of 1s into an ESC and make it run up. PiOS/I2C: Some cleaned up code for getting a snippet of the history when something strange happens PiOS/I2C: Export logging information from I2C through a UAV object PiOS/I2C: Improve the diagnostic information PiOS/I2C: Need to handle the event 0x30084. This seems to happen between a byte transmitted and new byte started PiOS/I2C: Handle the NACK condition by simply going to the stopping state. PiOS/I2C: Add a new NACK state to handle sending the STOP signal after a NACK following the STM documentation. Other error conditions still are not dealt with. PiOS/I2C: Should handle the NACK condition from all the write cases. Need to think about read cases git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@2239 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
parent
c034a35d2c
commit
4b4a66c2d7
@ -167,6 +167,7 @@ SRC += $(OPUAVOBJ)/manualcontrolsettings.c
|
||||
SRC += $(OPUAVOBJ)/attitudedesired.c
|
||||
SRC += $(OPUAVOBJ)/stabilizationsettings.c
|
||||
SRC += $(OPUAVOBJ)/ahrsstatus.c
|
||||
SRC += $(OPUAVOBJ)/i2cstats.c
|
||||
SRC += $(OPUAVOBJ)/baroaltitude.c
|
||||
SRC += $(OPUAVOBJ)/ahrscalibration.c
|
||||
SRC += $(OPUAVOBJ)/attitudeactual.c
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "objectpersistence.h"
|
||||
#include "manualcontrolcommand.h"
|
||||
#include "systemstats.h"
|
||||
#include "i2cstats.h"
|
||||
|
||||
|
||||
// Private constants
|
||||
@ -69,6 +70,7 @@ static int32_t stackOverflow;
|
||||
// Private functions
|
||||
static void objectUpdatedCb(UAVObjEvent * ev);
|
||||
static void updateStats();
|
||||
static void updateI2Cstats();
|
||||
static void updateSystemAlarms();
|
||||
static void systemTask(void *parameters);
|
||||
|
||||
@ -110,7 +112,8 @@ static void systemTask(void *parameters)
|
||||
|
||||
// Update the system alarms
|
||||
updateSystemAlarms();
|
||||
|
||||
updateI2Cstats();
|
||||
|
||||
// Flash the heartbeat LED
|
||||
PIOS_LED_Toggle(LED1);
|
||||
|
||||
@ -199,6 +202,25 @@ static void objectUpdatedCb(UAVObjEvent * ev)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called periodically to update the I2C statistics
|
||||
*/
|
||||
static void updateI2Cstats()
|
||||
{
|
||||
I2CStatsData i2cStats;
|
||||
I2CStatsGet(&i2cStats);
|
||||
|
||||
struct pios_i2c_fault_history history;
|
||||
PIOS_I2C_GetDiagnoistics(&history, &i2cStats.event_errors);
|
||||
|
||||
for(uint8_t i = 0; (i < I2C_LOG_DEPTH) && (i < I2CSTATS_EVENT_LOG_NUMELEM); i++) {
|
||||
i2cStats.event_log[i] = history.event[i];
|
||||
i2cStats.state_log[i] = history.state[i];
|
||||
}
|
||||
i2cStats.last_error_type = history.type;
|
||||
I2CStatsSet(&i2cStats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called periodically to update the system stats
|
||||
*/
|
||||
|
111
flight/OpenPilot/UAVObjects/i2cstats.c
Normal file
111
flight/OpenPilot/UAVObjects/i2cstats.c
Normal file
@ -0,0 +1,111 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup UAVObjects OpenPilot UAVObjects
|
||||
* @{
|
||||
* @addtogroup I2CStats I2CStats
|
||||
* @brief Tracks statistics on the I2C bus.
|
||||
*
|
||||
* Autogenerated files and functions for I2CStats Object
|
||||
* @{
|
||||
*
|
||||
* @file i2cstats.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Implementation of the I2CStats object. This file has been
|
||||
* automatically generated by the UAVObjectGenerator.
|
||||
*
|
||||
* @note Object definition file: i2cstats.xml.
|
||||
* This is an automatically generated file.
|
||||
* DO NOT modify manually.
|
||||
*
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "openpilot.h"
|
||||
#include "i2cstats.h"
|
||||
|
||||
// Private variables
|
||||
static UAVObjHandle handle;
|
||||
|
||||
// Private functions
|
||||
static void setDefaults(UAVObjHandle obj, uint16_t instId);
|
||||
|
||||
/**
|
||||
* Initialize object.
|
||||
* \return 0 Success
|
||||
* \return -1 Failure
|
||||
*/
|
||||
int32_t I2CStatsInitialize()
|
||||
{
|
||||
// Register object with the object manager
|
||||
handle = UAVObjRegister(I2CSTATS_OBJID, I2CSTATS_NAME, I2CSTATS_METANAME, 0,
|
||||
I2CSTATS_ISSINGLEINST, I2CSTATS_ISSETTINGS, I2CSTATS_NUMBYTES, &setDefaults);
|
||||
|
||||
// Done
|
||||
if (handle != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize object fields and metadata with the default values.
|
||||
* If a default value is not specified the object fields
|
||||
* will be initialized to zero.
|
||||
*/
|
||||
static void setDefaults(UAVObjHandle obj, uint16_t instId)
|
||||
{
|
||||
I2CStatsData data;
|
||||
UAVObjMetadata metadata;
|
||||
|
||||
// Initialize object fields to their default values
|
||||
UAVObjGetInstanceData(obj, instId, &data);
|
||||
memset(&data, 0, sizeof(I2CStatsData));
|
||||
|
||||
UAVObjSetInstanceData(obj, instId, &data);
|
||||
|
||||
// Initialize object metadata to their default values
|
||||
metadata.access = ACCESS_READWRITE;
|
||||
metadata.gcsAccess = ACCESS_READWRITE;
|
||||
metadata.telemetryAcked = 0;
|
||||
metadata.telemetryUpdateMode = UPDATEMODE_PERIODIC;
|
||||
metadata.telemetryUpdatePeriod = 10000;
|
||||
metadata.gcsTelemetryAcked = 0;
|
||||
metadata.gcsTelemetryUpdateMode = UPDATEMODE_MANUAL;
|
||||
metadata.gcsTelemetryUpdatePeriod = 0;
|
||||
metadata.loggingUpdateMode = UPDATEMODE_PERIODIC;
|
||||
metadata.loggingUpdatePeriod = 30000;
|
||||
UAVObjSetMetadata(obj, &metadata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get object handle
|
||||
*/
|
||||
UAVObjHandle I2CStatsHandle()
|
||||
{
|
||||
return handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
107
flight/OpenPilot/UAVObjects/inc/i2cstats.h
Normal file
107
flight/OpenPilot/UAVObjects/inc/i2cstats.h
Normal file
@ -0,0 +1,107 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup UAVObjects OpenPilot UAVObjects
|
||||
* @{
|
||||
* @addtogroup I2CStats I2CStats
|
||||
* @brief Tracks statistics on the I2C bus.
|
||||
*
|
||||
* Autogenerated files and functions for I2CStats Object
|
||||
|
||||
* @{
|
||||
*
|
||||
* @file i2cstats.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Implementation of the I2CStats object. This file has been
|
||||
* automatically generated by the UAVObjectGenerator.
|
||||
*
|
||||
* @note Object definition file: i2cstats.xml.
|
||||
* This is an automatically generated file.
|
||||
* DO NOT modify manually.
|
||||
*
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef I2CSTATS_H
|
||||
#define I2CSTATS_H
|
||||
|
||||
// Object constants
|
||||
#define I2CSTATS_OBJID 1063893720U
|
||||
#define I2CSTATS_NAME "I2CStats"
|
||||
#define I2CSTATS_METANAME "I2CStatsMeta"
|
||||
#define I2CSTATS_ISSINGLEINST 1
|
||||
#define I2CSTATS_ISSETTINGS 0
|
||||
#define I2CSTATS_NUMBYTES sizeof(I2CStatsData)
|
||||
|
||||
// Object access macros
|
||||
/**
|
||||
* @function I2CStatsGet(dataOut)
|
||||
* @brief Populate a I2CStatsData object
|
||||
* @param[out] dataOut
|
||||
*/
|
||||
#define I2CStatsGet(dataOut) UAVObjGetData(I2CStatsHandle(), dataOut)
|
||||
#define I2CStatsSet(dataIn) UAVObjSetData(I2CStatsHandle(), dataIn)
|
||||
#define I2CStatsInstGet(instId, dataOut) UAVObjGetInstanceData(I2CStatsHandle(), instId, dataOut)
|
||||
#define I2CStatsInstSet(instId, dataIn) UAVObjSetInstanceData(I2CStatsHandle(), instId, dataIn)
|
||||
#define I2CStatsConnectQueue(queue) UAVObjConnectQueue(I2CStatsHandle(), queue, EV_MASK_ALL_UPDATES)
|
||||
#define I2CStatsConnectCallback(cb) UAVObjConnectCallback(I2CStatsHandle(), cb, EV_MASK_ALL_UPDATES)
|
||||
#define I2CStatsCreateInstance() UAVObjCreateInstance(I2CStatsHandle())
|
||||
#define I2CStatsRequestUpdate() UAVObjRequestUpdate(I2CStatsHandle())
|
||||
#define I2CStatsRequestInstUpdate(instId) UAVObjRequestInstanceUpdate(I2CStatsHandle(), instId)
|
||||
#define I2CStatsUpdated() UAVObjUpdated(I2CStatsHandle())
|
||||
#define I2CStatsInstUpdated(instId) UAVObjUpdated(I2CStatsHandle(), instId)
|
||||
#define I2CStatsGetMetadata(dataOut) UAVObjGetMetadata(I2CStatsHandle(), dataOut)
|
||||
#define I2CStatsSetMetadata(dataIn) UAVObjSetMetadata(I2CStatsHandle(), dataIn)
|
||||
#define I2CStatsReadOnly(dataIn) UAVObjReadOnly(I2CStatsHandle())
|
||||
|
||||
// Object data
|
||||
typedef struct {
|
||||
uint16_t event_errors;
|
||||
uint16_t fsm_errors;
|
||||
uint16_t irq_errors;
|
||||
uint8_t last_error_type;
|
||||
uint32_t event_log[5];
|
||||
uint32_t state_log[5];
|
||||
|
||||
} __attribute__((packed)) I2CStatsData;
|
||||
|
||||
// Field information
|
||||
// Field event_errors information
|
||||
// Field fsm_errors information
|
||||
// Field irq_errors information
|
||||
// Field last_error_type information
|
||||
/* Enumeration options for field last_error_type */
|
||||
typedef enum { I2CSTATS_LAST_ERROR_TYPE_EVENT=0, I2CSTATS_LAST_ERROR_TYPE_FSM=1, I2CSTATS_LAST_ERROR_TYPE_INTERRUPT=2 } I2CStatslast_error_typeOptions;
|
||||
// Field event_log information
|
||||
/* Number of elements for field event_log */
|
||||
#define I2CSTATS_EVENT_LOG_NUMELEM 5
|
||||
// Field state_log information
|
||||
/* Number of elements for field state_log */
|
||||
#define I2CSTATS_STATE_LOG_NUMELEM 5
|
||||
|
||||
|
||||
// Generic interface functions
|
||||
int32_t I2CStatsInitialize();
|
||||
UAVObjHandle I2CStatsHandle();
|
||||
|
||||
#endif // I2CSTATS_H
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
@ -47,6 +47,7 @@
|
||||
#include "gpstime.h"
|
||||
#include "guidancesettings.h"
|
||||
#include "homelocation.h"
|
||||
#include "i2cstats.h"
|
||||
#include "manualcontrolcommand.h"
|
||||
#include "manualcontrolsettings.h"
|
||||
#include "mixersettings.h"
|
||||
@ -91,6 +92,7 @@ void UAVObjectsInitializeAll()
|
||||
GPSTimeInitialize();
|
||||
GuidanceSettingsInitialize();
|
||||
HomeLocationInitialize();
|
||||
I2CStatsInitialize();
|
||||
ManualControlCommandInitialize();
|
||||
ManualControlSettingsInitialize();
|
||||
MixerSettingsInitialize();
|
||||
|
@ -40,6 +40,8 @@
|
||||
|
||||
#include <pios_i2c_priv.h>
|
||||
|
||||
//#define I2C_HALT_ON_ERRORS
|
||||
|
||||
enum i2c_adapter_event {
|
||||
I2C_EVENT_BUS_ERROR,
|
||||
I2C_EVENT_START,
|
||||
@ -55,12 +57,24 @@ enum i2c_adapter_event {
|
||||
I2C_EVENT_TRANSFER_DONE_LEN_EQ_1,
|
||||
I2C_EVENT_TRANSFER_DONE_LEN_EQ_2,
|
||||
I2C_EVENT_TRANSFER_DONE_LEN_GT_2,
|
||||
I2C_EVENT_NACK,
|
||||
I2C_EVENT_STOPPED,
|
||||
I2C_EVENT_AUTO, /* FIXME: remove this */
|
||||
|
||||
I2C_EVENT_NUM_EVENTS /* Must be last */
|
||||
};
|
||||
|
||||
#if defined(PIOS_I2C_DIAGNOSTICS)
|
||||
static struct pios_i2c_fault_history i2c_adapter_fault_history;
|
||||
static uint32_t i2c_event_history[I2C_LOG_DEPTH];
|
||||
static uint8_t i2c_event_history_pointer = 0;
|
||||
static enum i2c_adapter_state i2c_state_history[I2C_LOG_DEPTH];
|
||||
static uint8_t i2c_state_history_pointer = 0;
|
||||
static uint16_t i2c_fsm_fault_count = 0;
|
||||
static uint16_t i2c_bad_event_counter = 0;
|
||||
static uint16_t i2c_error_interrupt_counter = 0;
|
||||
#endif
|
||||
|
||||
static void go_fsm_fault(struct pios_i2c_adapter *i2c_adapter);
|
||||
static void go_bus_error(struct pios_i2c_adapter *i2c_adapter);
|
||||
static void go_stopping(struct pios_i2c_adapter *i2c_adapter);
|
||||
@ -88,6 +102,8 @@ static void go_w_any_txn_addr(struct pios_i2c_adapter *i2c_adapter);
|
||||
static void go_w_any_txn_middle(struct pios_i2c_adapter *i2c_adapter);
|
||||
static void go_w_last_txn_last(struct pios_i2c_adapter *i2c_adapter);
|
||||
|
||||
static void go_nack(struct pios_i2c_adapter *i2c_adapter);
|
||||
|
||||
struct i2c_adapter_transition {
|
||||
void (*entry_fn) (struct pios_i2c_adapter * i2c_adapter);
|
||||
enum i2c_adapter_state next_state[I2C_EVENT_NUM_EVENTS];
|
||||
@ -99,11 +115,15 @@ static void i2c_adapter_fsm_init(struct pios_i2c_adapter *i2c_adapter);
|
||||
static bool i2c_adapter_wait_for_stopped(struct pios_i2c_adapter *i2c_adapter);
|
||||
static void i2c_adapter_reset_bus(struct pios_i2c_adapter *i2c_adapter);
|
||||
|
||||
static void i2c_adapter_log_fault(enum pios_i2c_error_type type);
|
||||
|
||||
const static struct i2c_adapter_transition i2c_adapter_transitions[I2C_STATE_NUM_STATES] = {
|
||||
[I2C_STATE_FSM_FAULT] = {
|
||||
.entry_fn = go_fsm_fault,
|
||||
},
|
||||
|
||||
.next_state = {
|
||||
[I2C_EVENT_AUTO] = I2C_STATE_STOPPING,
|
||||
},
|
||||
},
|
||||
[I2C_STATE_BUS_ERROR] = {
|
||||
.entry_fn = go_bus_error,
|
||||
.next_state = {
|
||||
@ -134,6 +154,7 @@ const static struct i2c_adapter_transition i2c_adapter_transitions[I2C_STATE_NUM
|
||||
[I2C_EVENT_STARTED_MORE_TXN_WRITE] = I2C_STATE_W_MORE_TXN_ADDR,
|
||||
[I2C_EVENT_STARTED_LAST_TXN_READ] = I2C_STATE_R_LAST_TXN_ADDR,
|
||||
[I2C_EVENT_STARTED_LAST_TXN_WRITE] = I2C_STATE_W_LAST_TXN_ADDR,
|
||||
[I2C_EVENT_NACK] = I2C_STATE_STOPPING,
|
||||
[I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
|
||||
},
|
||||
},
|
||||
@ -258,6 +279,7 @@ const static struct i2c_adapter_transition i2c_adapter_transitions[I2C_STATE_NUM
|
||||
[I2C_EVENT_ADDR_SENT_LEN_EQ_1] = I2C_STATE_W_MORE_TXN_LAST,
|
||||
[I2C_EVENT_ADDR_SENT_LEN_EQ_2] = I2C_STATE_W_MORE_TXN_MIDDLE,
|
||||
[I2C_EVENT_ADDR_SENT_LEN_GT_2] = I2C_STATE_W_MORE_TXN_MIDDLE,
|
||||
[I2C_EVENT_NACK] = I2C_STATE_NACK,
|
||||
[I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
|
||||
},
|
||||
},
|
||||
@ -268,6 +290,7 @@ const static struct i2c_adapter_transition i2c_adapter_transitions[I2C_STATE_NUM
|
||||
[I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_W_MORE_TXN_LAST,
|
||||
[I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_W_MORE_TXN_MIDDLE,
|
||||
[I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_W_MORE_TXN_MIDDLE,
|
||||
[I2C_EVENT_NACK] = I2C_STATE_NACK,
|
||||
[I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
|
||||
},
|
||||
},
|
||||
@ -275,7 +298,8 @@ const static struct i2c_adapter_transition i2c_adapter_transitions[I2C_STATE_NUM
|
||||
[I2C_STATE_W_MORE_TXN_LAST] = {
|
||||
.entry_fn = go_w_more_txn_last,
|
||||
.next_state = {
|
||||
[I2C_EVENT_TRANSFER_DONE_LEN_EQ_0] = I2C_STATE_STARTING,
|
||||
[I2C_EVENT_TRANSFER_DONE_LEN_EQ_0] = I2C_STATE_STARTING,
|
||||
[I2C_EVENT_NACK] = I2C_STATE_NACK,
|
||||
[I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
|
||||
},
|
||||
},
|
||||
@ -290,6 +314,7 @@ const static struct i2c_adapter_transition i2c_adapter_transitions[I2C_STATE_NUM
|
||||
[I2C_EVENT_ADDR_SENT_LEN_EQ_1] = I2C_STATE_W_LAST_TXN_LAST,
|
||||
[I2C_EVENT_ADDR_SENT_LEN_EQ_2] = I2C_STATE_W_LAST_TXN_MIDDLE,
|
||||
[I2C_EVENT_ADDR_SENT_LEN_GT_2] = I2C_STATE_W_LAST_TXN_MIDDLE,
|
||||
[I2C_EVENT_NACK] = I2C_STATE_NACK,
|
||||
[I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
|
||||
},
|
||||
},
|
||||
@ -300,6 +325,7 @@ const static struct i2c_adapter_transition i2c_adapter_transitions[I2C_STATE_NUM
|
||||
[I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_W_LAST_TXN_LAST,
|
||||
[I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_W_LAST_TXN_MIDDLE,
|
||||
[I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_W_LAST_TXN_MIDDLE,
|
||||
[I2C_EVENT_NACK] = I2C_STATE_NACK,
|
||||
[I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
|
||||
},
|
||||
},
|
||||
@ -308,14 +334,29 @@ const static struct i2c_adapter_transition i2c_adapter_transitions[I2C_STATE_NUM
|
||||
.entry_fn = go_w_last_txn_last,
|
||||
.next_state = {
|
||||
[I2C_EVENT_TRANSFER_DONE_LEN_EQ_0] = I2C_STATE_STOPPING,
|
||||
[I2C_EVENT_NACK] = I2C_STATE_NACK,
|
||||
[I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
|
||||
},
|
||||
},
|
||||
[I2C_STATE_NACK] = {
|
||||
.entry_fn = go_nack,
|
||||
.next_state = {
|
||||
[I2C_EVENT_AUTO] = I2C_STATE_STOPPING,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static void go_fsm_fault(struct pios_i2c_adapter *i2c_adapter)
|
||||
{
|
||||
#if defined(I2C_HALT_ON_ERRORS)
|
||||
PIOS_DEBUG_Assert(0);
|
||||
#endif
|
||||
/* Note that this transfer has hit a bus error */
|
||||
i2c_adapter->bus_error = true;
|
||||
// i2c_adapter->curr_state = I2C_STATE_STOPPED;
|
||||
|
||||
i2c_adapter_reset_bus(i2c_adapter);
|
||||
|
||||
}
|
||||
|
||||
static void go_bus_error(struct pios_i2c_adapter *i2c_adapter)
|
||||
@ -336,7 +377,9 @@ static void go_stopping(struct pios_i2c_adapter *i2c_adapter)
|
||||
|
||||
#ifdef USE_FREERTOS
|
||||
if (xSemaphoreGiveFromISR(i2c_adapter->sem_ready, &pxHigherPriorityTaskWoken) != pdTRUE) {
|
||||
#if defined(I2C_HALT_ON_ERRORS)
|
||||
PIOS_DEBUG_Assert(0);
|
||||
#endif
|
||||
}
|
||||
portEND_SWITCHING_ISR(pxHigherPriorityTaskWoken); /* FIXME: is this the right place for this? */
|
||||
#endif /* USE_FREERTOS */
|
||||
@ -521,10 +564,23 @@ static void go_w_last_txn_last(struct pios_i2c_adapter *i2c_adapter)
|
||||
i2c_adapter->active_byte++;
|
||||
}
|
||||
|
||||
static void go_nack(struct pios_i2c_adapter *i2c_adapter) {
|
||||
I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_BUF, DISABLE);
|
||||
|
||||
// SHOULD MOVE THIS INTO A STOPPING STATE AND SET IT ONLY AFTER THE BYTE WAS SENT
|
||||
I2C_GenerateSTOP(i2c_adapter->cfg->regs, ENABLE);
|
||||
}
|
||||
|
||||
static void i2c_adapter_inject_event(struct pios_i2c_adapter *i2c_adapter, enum i2c_adapter_event event)
|
||||
{
|
||||
PIOS_IRQ_Disable();
|
||||
|
||||
#if defined(PIOS_I2C_DIAGNOSTICS)
|
||||
i2c_state_history[i2c_state_history_pointer] = i2c_adapter->curr_state;
|
||||
i2c_state_history_pointer = (i2c_state_history_pointer + 1) % I2C_LOG_DEPTH;
|
||||
if(i2c_adapter_transitions[i2c_adapter->curr_state].next_state[event] == I2C_STATE_FSM_FAULT)
|
||||
i2c_adapter_log_fault(PIOS_I2C_ERROR_FSM);
|
||||
#endif
|
||||
/*
|
||||
* Move to the next state
|
||||
*
|
||||
@ -613,15 +669,35 @@ static void i2c_adapter_reset_bus(struct pios_i2c_adapter *i2c_adapter)
|
||||
GPIO_SetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
|
||||
GPIO_Init(i2c_adapter->cfg->sda.gpio, &sda_gpio_init);
|
||||
|
||||
for (uint8_t i = 0; i < 9; i++) {
|
||||
/* Check SDA line to determine if slave is asserting bus and clock out if so, this may */
|
||||
/* have to be repeated (due to futher bus errors) but better than clocking 0xFF into an */
|
||||
/* ESC */
|
||||
bool sda_hung = GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) == Bit_RESET;
|
||||
while(GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) == Bit_RESET) {
|
||||
|
||||
/* Set clock high and wait for any clock stretching to finish. */
|
||||
GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
|
||||
while (GPIO_ReadInputDataBit(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin) == Bit_RESET) ;
|
||||
PIOS_DELAY_WaituS(2);
|
||||
|
||||
|
||||
/* Set clock low */
|
||||
GPIO_ResetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
|
||||
PIOS_DELAY_WaituS(2);
|
||||
|
||||
/* Clock high again */
|
||||
GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
|
||||
PIOS_DELAY_WaituS(2);
|
||||
}
|
||||
if(sda_hung) {
|
||||
|
||||
/* Generate a start then stop condition */
|
||||
GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
|
||||
PIOS_DELAY_WaituS(2);
|
||||
GPIO_ResetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
|
||||
PIOS_DELAY_WaituS(2);
|
||||
GPIO_ResetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
|
||||
PIOS_DELAY_WaituS(2);
|
||||
|
||||
}
|
||||
|
||||
/* Set data and clock high and wait for any clock stretching to finish. */
|
||||
@ -631,6 +707,7 @@ static void i2c_adapter_reset_bus(struct pios_i2c_adapter *i2c_adapter)
|
||||
/* Wait for data to be high */
|
||||
while (GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) != Bit_SET) ;
|
||||
|
||||
|
||||
/* Bus signals are guaranteed to be high (ie. free) after this point */
|
||||
/* Initialize the GPIO pins to the peripheral function */
|
||||
GPIO_Init(i2c_adapter->cfg->scl.gpio, &(i2c_adapter->cfg->scl.init));
|
||||
@ -675,6 +752,53 @@ static bool i2c_adapter_fsm_terminated(struct pios_i2c_adapter *i2c_adapter)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the last N state transitions and N IRQ events due to
|
||||
* an error condition
|
||||
* \param[in] i2c the adapter number to log an event for
|
||||
*/
|
||||
void i2c_adapter_log_fault(enum pios_i2c_error_type type)
|
||||
{
|
||||
#if defined(PIOS_I2C_DIAGNOSTICS)
|
||||
i2c_adapter_fault_history.type = type;
|
||||
for(uint8_t i = 0; i < I2C_LOG_DEPTH; i++) {
|
||||
i2c_adapter_fault_history.event[i] =
|
||||
i2c_event_history[(I2C_LOG_DEPTH + i2c_event_history_pointer - 1 - i) % I2C_LOG_DEPTH];
|
||||
i2c_adapter_fault_history.state[i] =
|
||||
i2c_state_history[(I2C_LOG_DEPTH + i2c_state_history_pointer - 1 - i) % I2C_LOG_DEPTH];
|
||||
}
|
||||
switch(type) {
|
||||
case PIOS_I2C_ERROR_EVENT:
|
||||
i2c_bad_event_counter++;
|
||||
break;
|
||||
case PIOS_I2C_ERROR_FSM:
|
||||
i2c_fsm_fault_count++;
|
||||
break;
|
||||
case PIOS_I2C_ERROR_INTERRUPT:
|
||||
i2c_error_interrupt_counter++;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Logs the last N state transitions and N IRQ events due to
|
||||
* an error condition
|
||||
* \param[out] data address where to copy the pios_i2c_fault_history structure to
|
||||
* \param[out] counts three uint16 that receive the bad event, fsm, and error irq
|
||||
* counts
|
||||
*/
|
||||
void PIOS_I2C_GetDiagnoistics(struct pios_i2c_fault_history * data, uint16_t * counts)
|
||||
{
|
||||
#if defined(PIOS_I2C_DIAGNOSTICS)
|
||||
memcpy(data, &i2c_adapter_fault_history, sizeof(i2c_adapter_fault_history));
|
||||
counts[0] = i2c_bad_event_counter;
|
||||
counts[1] = i2c_fsm_fault_count;
|
||||
counts[2] = i2c_error_interrupt_counter;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes IIC driver
|
||||
* \param[in] mode currently only mode 0 supported
|
||||
@ -779,13 +903,27 @@ bool PIOS_I2C_Transfer(uint8_t i2c, const struct pios_i2c_txn txn_list[], uint32
|
||||
void PIOS_I2C_EV_IRQ_Handler(uint8_t i2c)
|
||||
{
|
||||
struct pios_i2c_adapter *i2c_adapter;
|
||||
|
||||
|
||||
|
||||
i2c_adapter = find_i2c_adapter_by_id(i2c);
|
||||
PIOS_DEBUG_Assert(i2c_adapter);
|
||||
|
||||
|
||||
uint32_t event = I2C_GetLastEvent(i2c_adapter->cfg->regs);
|
||||
|
||||
switch (event) {
|
||||
#if defined(PIOS_I2C_DIAGNOSTICS)
|
||||
/* Store event for diagnostics */
|
||||
i2c_event_history[i2c_event_history_pointer] = event;
|
||||
i2c_event_history_pointer = (i2c_event_history_pointer + 1) % I2C_LOG_DEPTH;
|
||||
#endif
|
||||
|
||||
event &= 0x000700FF;
|
||||
|
||||
static uint32_t prev_event = 0;
|
||||
if((event == prev_event) && (event == 0x70084))
|
||||
return;
|
||||
prev_event = event;
|
||||
|
||||
switch (event) { /* Mask out all the bits we don't care about */
|
||||
case (I2C_EVENT_MASTER_MODE_SELECT | 0x40):
|
||||
/* Unexplained event: EV5 + RxNE : Extraneous Rx. Probably a late NACK from previous read. */
|
||||
/* Clean up the extra Rx until the root cause is identified and just keep going */
|
||||
@ -870,8 +1008,16 @@ void PIOS_I2C_EV_IRQ_Handler(uint8_t i2c)
|
||||
/* Ignore this event and wait for TRANSMITTED in case we can't keep up */
|
||||
goto skip_event;
|
||||
break;
|
||||
case 0x30084: /* Occurs between byte tranmistted and master mode selected */
|
||||
case 0x30000: /* Need to throw away this spurious event */
|
||||
goto skip_event;
|
||||
break;
|
||||
default:
|
||||
i2c_adapter_log_fault(PIOS_I2C_ERROR_EVENT);
|
||||
#if defined(I2C_HALT_ON_ERRORS)
|
||||
PIOS_DEBUG_Assert(0);
|
||||
#endif
|
||||
i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_BUS_ERROR);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -886,8 +1032,23 @@ void PIOS_I2C_ER_IRQ_Handler(uint8_t i2c)
|
||||
i2c_adapter = find_i2c_adapter_by_id(i2c);
|
||||
PIOS_DEBUG_Assert(i2c_adapter);
|
||||
|
||||
/* Fail hard on any errors for now */
|
||||
i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_BUS_ERROR);
|
||||
|
||||
#if defined(PIOS_I2C_DIAGNOSTICS)
|
||||
uint32_t event = I2C_GetLastEvent(i2c_adapter->cfg->regs);
|
||||
|
||||
/* Store event for diagnostics */
|
||||
i2c_event_history[i2c_event_history_pointer] = event;
|
||||
i2c_event_history_pointer = (i2c_event_history_pointer + 1) % I2C_LOG_DEPTH;
|
||||
#endif
|
||||
|
||||
if(I2C_GetFlagStatus(i2c_adapter->cfg->regs, I2C_FLAG_AF)) {
|
||||
i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_NACK);
|
||||
} else {
|
||||
i2c_adapter_log_fault(PIOS_I2C_ERROR_INTERRUPT);
|
||||
|
||||
/* Fail hard on any errors for now */
|
||||
i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_BUS_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,6 +31,8 @@
|
||||
#ifndef PIOS_I2C_H
|
||||
#define PIOS_I2C_H
|
||||
|
||||
//#define PIOS_I2C_DIAGNOSTICS
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Global Types */
|
||||
@ -47,11 +49,25 @@ struct pios_i2c_txn {
|
||||
uint8_t *buf;
|
||||
};
|
||||
|
||||
#define I2C_LOG_DEPTH 5
|
||||
enum pios_i2c_error_type {
|
||||
PIOS_I2C_ERROR_EVENT,
|
||||
PIOS_I2C_ERROR_FSM,
|
||||
PIOS_I2C_ERROR_INTERRUPT
|
||||
};
|
||||
|
||||
struct pios_i2c_fault_history {
|
||||
enum pios_i2c_error_type type;
|
||||
uint32_t event[I2C_LOG_DEPTH];
|
||||
uint32_t state[I2C_LOG_DEPTH];
|
||||
};
|
||||
|
||||
/* Public Functions */
|
||||
extern int32_t PIOS_I2C_Init(void);
|
||||
extern bool PIOS_I2C_Transfer(uint8_t i2c, const struct pios_i2c_txn txn_list[], uint32_t num_txns);
|
||||
extern void PIOS_I2C_EV_IRQ_Handler(uint8_t i2c);
|
||||
extern void PIOS_I2C_ER_IRQ_Handler(uint8_t i2c);
|
||||
extern void PIOS_I2C_GetDiagnoistics(struct pios_i2c_fault_history * data, uint16_t * error_counts);
|
||||
|
||||
#endif /* PIOS_I2C_H */
|
||||
|
||||
|
@ -72,7 +72,9 @@ enum i2c_adapter_state {
|
||||
I2C_STATE_W_LAST_TXN_ADDR,
|
||||
I2C_STATE_W_LAST_TXN_MIDDLE,
|
||||
I2C_STATE_W_LAST_TXN_LAST,
|
||||
|
||||
|
||||
I2C_STATE_NACK,
|
||||
|
||||
I2C_STATE_NUM_STATES /* Must be last */
|
||||
};
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
65322D3B122841F60046CD7C /* gpstime.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = gpstime.xml; sourceTree = "<group>"; };
|
||||
65322D77122897210046CD7C /* MagOrAccelSensorCal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = MagOrAccelSensorCal.c; path = ../../AHRS/MagOrAccelSensorCal.c; sourceTree = SOURCE_ROOT; };
|
||||
65345C871288668B00A5E4E8 /* guidancesettings.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = guidancesettings.xml; sourceTree = "<group>"; };
|
||||
65408AA812BB1648004DACC5 /* i2cstats.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = i2cstats.xml; sourceTree = "<group>"; };
|
||||
654330231218E9780063F913 /* insgps.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = insgps.c; path = ../../AHRS/insgps.c; sourceTree = SOURCE_ROOT; };
|
||||
6543304F121980300063F913 /* insgps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = insgps.h; sourceTree = "<group>"; };
|
||||
654612D812B5E9A900B719D0 /* pios_iap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pios_iap.c; sourceTree = "<group>"; };
|
||||
@ -6799,6 +6800,7 @@
|
||||
65B367FC121C2620003EAD18 /* systemsettings.xml */,
|
||||
65B367FD121C2620003EAD18 /* systemstats.xml */,
|
||||
65B367FE121C2620003EAD18 /* telemetrysettings.xml */,
|
||||
65408AA812BB1648004DACC5 /* i2cstats.xml */,
|
||||
);
|
||||
path = uavobjectdefinition;
|
||||
sourceTree = "<group>";
|
||||
|
@ -200,6 +200,15 @@ function [] = OPLogConvert()
|
||||
HomeLocation(1).RNE = zeros(1,9);
|
||||
HomeLocation(1).Be = zeros(1,3);
|
||||
|
||||
i2cstatsIdx = 1;
|
||||
I2CStats.timestamp = 0;
|
||||
I2CStats(1).event_errors = 0;
|
||||
I2CStats(1).fsm_errors = 0;
|
||||
I2CStats(1).irq_errors = 0;
|
||||
I2CStats(1).last_error_type = 0;
|
||||
I2CStats(1).event_log = zeros(1,5);
|
||||
I2CStats(1).state_log = zeros(1,5);
|
||||
|
||||
manualcontrolcommandIdx = 1;
|
||||
ManualControlCommand.timestamp = 0;
|
||||
ManualControlCommand(1).Connected = 0;
|
||||
@ -459,6 +468,9 @@ function [] = OPLogConvert()
|
||||
case 3590360786
|
||||
HomeLocation(homelocationIdx) = ReadHomeLocationObject(fid, timestamp);
|
||||
homelocationIdx = homelocationIdx + 1;
|
||||
case 1063893720
|
||||
I2CStats(i2cstatsIdx) = ReadI2CStatsObject(fid, timestamp);
|
||||
i2cstatsIdx = i2cstatsIdx + 1;
|
||||
case 2841592332
|
||||
ManualControlCommand(manualcontrolcommandIdx) = ReadManualControlCommandObject(fid, timestamp);
|
||||
manualcontrolcommandIdx = manualcontrolcommandIdx + 1;
|
||||
@ -523,7 +535,7 @@ function [] = OPLogConvert()
|
||||
fclose(fid);
|
||||
|
||||
matfile = strrep(logfile,'opl','mat');
|
||||
save(matfile ,'ActuatorCommand','ActuatorDesired','ActuatorSettings','AHRSCalibration','AHRSSettings','AhrsStatus','AttitudeActual','AttitudeDesired','AttitudeRaw','BaroAltitude','FirmwareIAPObj','FlightBatteryState','FlightTelemetryStats','GCSTelemetryStats','GPSPosition','GPSSatellites','GPSTime','GuidanceSettings','HomeLocation','ManualControlCommand','ManualControlSettings','MixerSettings','MixerStatus','ObjectPersistence','PipXtremeModemSettings','PipXtremeModemStatus','PositionActual','PositionDesired','RateDesired','StabilizationSettings','SystemAlarms','SystemSettings','SystemStats','TelemetrySettings','VelocityActual','VelocityDesired');
|
||||
save(matfile ,'ActuatorCommand','ActuatorDesired','ActuatorSettings','AHRSCalibration','AHRSSettings','AhrsStatus','AttitudeActual','AttitudeDesired','AttitudeRaw','BaroAltitude','FirmwareIAPObj','FlightBatteryState','FlightTelemetryStats','GCSTelemetryStats','GPSPosition','GPSSatellites','GPSTime','GuidanceSettings','HomeLocation','I2CStats','ManualControlCommand','ManualControlSettings','MixerSettings','MixerStatus','ObjectPersistence','PipXtremeModemSettings','PipXtremeModemStatus','PositionActual','PositionDesired','RateDesired','StabilizationSettings','SystemAlarms','SystemSettings','SystemStats','TelemetrySettings','VelocityActual','VelocityDesired');
|
||||
|
||||
end
|
||||
|
||||
@ -918,6 +930,25 @@ function [HomeLocation] = ReadHomeLocationObject(fid, timestamp)
|
||||
fread(fid, 1, 'uint8');
|
||||
end
|
||||
|
||||
function [I2CStats] = ReadI2CStatsObject(fid, timestamp)
|
||||
if 1
|
||||
headerSize = 8;
|
||||
else
|
||||
I2CStats.instanceID = fread(fid, 1, 'uint16');
|
||||
headerSize = 10;
|
||||
end
|
||||
|
||||
I2CStats.timestamp = timestamp;
|
||||
I2CStats.event_errors = double(fread(fid, 1, 'uint16'));
|
||||
I2CStats.fsm_errors = double(fread(fid, 1, 'uint16'));
|
||||
I2CStats.irq_errors = double(fread(fid, 1, 'uint16'));
|
||||
I2CStats.last_error_type = double(fread(fid, 1, 'uint8'));
|
||||
I2CStats.event_log = double(fread(fid, 5, 'uint32'));
|
||||
I2CStats.state_log = double(fread(fid, 5, 'uint32'));
|
||||
% read CRC
|
||||
fread(fid, 1, 'uint8');
|
||||
end
|
||||
|
||||
function [ManualControlCommand] = ReadManualControlCommandObject(fid, timestamp)
|
||||
if 1
|
||||
headerSize = 8;
|
||||
|
155
ground/src/plugins/uavobjects/i2cstats.cpp
Normal file
155
ground/src/plugins/uavobjects/i2cstats.cpp
Normal file
@ -0,0 +1,155 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file i2cstats.cpp
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup UAVObjectsPlugin UAVObjects Plugin
|
||||
* @{
|
||||
*
|
||||
* @note Object definition file: i2cstats.xml.
|
||||
* This is an automatically generated file.
|
||||
* DO NOT modify manually.
|
||||
*
|
||||
* @brief The UAVUObjects GCS plugin
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "i2cstats.h"
|
||||
#include "uavobjectfield.h"
|
||||
|
||||
const QString I2CStats::NAME = QString("I2CStats");
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
I2CStats::I2CStats(): UAVDataObject(OBJID, ISSINGLEINST, ISSETTINGS, NAME)
|
||||
{
|
||||
// Create fields
|
||||
QList<UAVObjectField*> fields;
|
||||
QStringList event_errorsElemNames;
|
||||
event_errorsElemNames.append("0");
|
||||
fields.append( new UAVObjectField(QString("event_errors"), QString(""), UAVObjectField::UINT16, event_errorsElemNames, QStringList()) );
|
||||
QStringList fsm_errorsElemNames;
|
||||
fsm_errorsElemNames.append("0");
|
||||
fields.append( new UAVObjectField(QString("fsm_errors"), QString(""), UAVObjectField::UINT16, fsm_errorsElemNames, QStringList()) );
|
||||
QStringList irq_errorsElemNames;
|
||||
irq_errorsElemNames.append("0");
|
||||
fields.append( new UAVObjectField(QString("irq_errors"), QString(""), UAVObjectField::UINT16, irq_errorsElemNames, QStringList()) );
|
||||
QStringList last_error_typeElemNames;
|
||||
last_error_typeElemNames.append("0");
|
||||
QStringList last_error_typeEnumOptions;
|
||||
last_error_typeEnumOptions.append("EVENT");
|
||||
last_error_typeEnumOptions.append("FSM");
|
||||
last_error_typeEnumOptions.append("INTERRUPT");
|
||||
fields.append( new UAVObjectField(QString("last_error_type"), QString(""), UAVObjectField::ENUM, last_error_typeElemNames, last_error_typeEnumOptions) );
|
||||
QStringList event_logElemNames;
|
||||
event_logElemNames.append("0");
|
||||
event_logElemNames.append("1");
|
||||
event_logElemNames.append("2");
|
||||
event_logElemNames.append("3");
|
||||
event_logElemNames.append("4");
|
||||
fields.append( new UAVObjectField(QString("event_log"), QString(""), UAVObjectField::UINT32, event_logElemNames, QStringList()) );
|
||||
QStringList state_logElemNames;
|
||||
state_logElemNames.append("0");
|
||||
state_logElemNames.append("1");
|
||||
state_logElemNames.append("2");
|
||||
state_logElemNames.append("3");
|
||||
state_logElemNames.append("4");
|
||||
fields.append( new UAVObjectField(QString("state_log"), QString(""), UAVObjectField::UINT32, state_logElemNames, QStringList()) );
|
||||
|
||||
// Initialize object
|
||||
initializeFields(fields, (quint8*)&data, NUMBYTES);
|
||||
// Set the default field values
|
||||
setDefaultFieldValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default metadata for this object
|
||||
*/
|
||||
UAVObject::Metadata I2CStats::getDefaultMetadata()
|
||||
{
|
||||
UAVObject::Metadata metadata;
|
||||
metadata.flightAccess = ACCESS_READWRITE;
|
||||
metadata.gcsAccess = ACCESS_READWRITE;
|
||||
metadata.gcsTelemetryAcked = 0;
|
||||
metadata.gcsTelemetryUpdateMode = UAVObject::UPDATEMODE_MANUAL;
|
||||
metadata.gcsTelemetryUpdatePeriod = 0;
|
||||
metadata.flightTelemetryAcked = 0;
|
||||
metadata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC;
|
||||
metadata.flightTelemetryUpdatePeriod = 10000;
|
||||
metadata.loggingUpdateMode = UAVObject::UPDATEMODE_PERIODIC;
|
||||
metadata.loggingUpdatePeriod = 30000;
|
||||
return metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize object fields with the default values.
|
||||
* If a default value is not specified the object fields
|
||||
* will be initialized to zero.
|
||||
*/
|
||||
void I2CStats::setDefaultFieldValues()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object data fields
|
||||
*/
|
||||
I2CStats::DataFields I2CStats::getData()
|
||||
{
|
||||
QMutexLocker locker(mutex);
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the object data fields
|
||||
*/
|
||||
void I2CStats::setData(const DataFields& data)
|
||||
{
|
||||
QMutexLocker locker(mutex);
|
||||
// Get metadata
|
||||
Metadata mdata = getMetadata();
|
||||
// Update object if the access mode permits
|
||||
if ( mdata.gcsAccess == ACCESS_READWRITE )
|
||||
{
|
||||
this->data = data;
|
||||
emit objectUpdatedAuto(this); // trigger object updated event
|
||||
emit objectUpdated(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a clone of this object, a new instance ID must be specified.
|
||||
* Do not use this function directly to create new instances, the
|
||||
* UAVObjectManager should be used instead.
|
||||
*/
|
||||
UAVDataObject* I2CStats::clone(quint32 instID)
|
||||
{
|
||||
I2CStats* obj = new I2CStats();
|
||||
obj->initialize(instID, this->getMetaObject());
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static function to retrieve an instance of the object.
|
||||
*/
|
||||
I2CStats* I2CStats::GetInstance(UAVObjectManager* objMngr, quint32 instID)
|
||||
{
|
||||
return dynamic_cast<I2CStats*>(objMngr->getObject(I2CStats::OBJID, instID));
|
||||
}
|
94
ground/src/plugins/uavobjects/i2cstats.h
Normal file
94
ground/src/plugins/uavobjects/i2cstats.h
Normal file
@ -0,0 +1,94 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file i2cstats.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup UAVObjectsPlugin UAVObjects Plugin
|
||||
* @{
|
||||
*
|
||||
* @note Object definition file: i2cstats.xml.
|
||||
* This is an automatically generated file.
|
||||
* DO NOT modify manually.
|
||||
*
|
||||
* @brief The UAVUObjects GCS plugin
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef I2CSTATS_H
|
||||
#define I2CSTATS_H
|
||||
|
||||
#include "uavdataobject.h"
|
||||
#include "uavobjectmanager.h"
|
||||
|
||||
class UAVOBJECTS_EXPORT I2CStats: public UAVDataObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
// Field structure
|
||||
typedef struct {
|
||||
quint16 event_errors;
|
||||
quint16 fsm_errors;
|
||||
quint16 irq_errors;
|
||||
quint8 last_error_type;
|
||||
quint32 event_log[5];
|
||||
quint32 state_log[5];
|
||||
|
||||
} __attribute__((packed)) DataFields;
|
||||
|
||||
// Field information
|
||||
// Field event_errors information
|
||||
// Field fsm_errors information
|
||||
// Field irq_errors information
|
||||
// Field last_error_type information
|
||||
/* Enumeration options for field last_error_type */
|
||||
typedef enum { LAST_ERROR_TYPE_EVENT=0, LAST_ERROR_TYPE_FSM=1, LAST_ERROR_TYPE_INTERRUPT=2 } last_error_typeOptions;
|
||||
// Field event_log information
|
||||
/* Number of elements for field event_log */
|
||||
static const quint32 EVENT_LOG_NUMELEM = 5;
|
||||
// Field state_log information
|
||||
/* Number of elements for field state_log */
|
||||
static const quint32 STATE_LOG_NUMELEM = 5;
|
||||
|
||||
|
||||
// Constants
|
||||
static const quint32 OBJID = 1063893720U;
|
||||
static const QString NAME;
|
||||
static const bool ISSINGLEINST = 1;
|
||||
static const bool ISSETTINGS = 0;
|
||||
static const quint32 NUMBYTES = sizeof(DataFields);
|
||||
|
||||
// Functions
|
||||
I2CStats();
|
||||
|
||||
DataFields getData();
|
||||
void setData(const DataFields& data);
|
||||
Metadata getDefaultMetadata();
|
||||
UAVDataObject* clone(quint32 instID);
|
||||
|
||||
static I2CStats* GetInstance(UAVObjectManager* objMngr, quint32 instID = 0);
|
||||
|
||||
private:
|
||||
DataFields data;
|
||||
|
||||
void setDefaultFieldValues();
|
||||
|
||||
};
|
||||
|
||||
#endif // I2CSTATS_H
|
147
ground/src/plugins/uavobjects/i2cstats.py
Normal file
147
ground/src/plugins/uavobjects/i2cstats.py
Normal file
@ -0,0 +1,147 @@
|
||||
##
|
||||
##############################################################################
|
||||
#
|
||||
# @file i2cstats.py
|
||||
# @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
# @brief Implementation of the I2CStats object. This file has been
|
||||
# automatically generated by the UAVObjectGenerator.
|
||||
#
|
||||
# @note Object definition file: i2cstats.xml.
|
||||
# This is an automatically generated file.
|
||||
# DO NOT modify manually.
|
||||
#
|
||||
# @see The GNU Public License (GPL) Version 3
|
||||
#
|
||||
#############################################################################/
|
||||
#
|
||||
# This program 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 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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 this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
|
||||
import uavobject
|
||||
|
||||
import struct
|
||||
from collections import namedtuple
|
||||
|
||||
# This is a list of instances of the data fields contained in this object
|
||||
_fields = [ \
|
||||
uavobject.UAVObjectField(
|
||||
'event_errors',
|
||||
'H',
|
||||
1,
|
||||
[
|
||||
'0',
|
||||
],
|
||||
{
|
||||
}
|
||||
),
|
||||
uavobject.UAVObjectField(
|
||||
'fsm_errors',
|
||||
'H',
|
||||
1,
|
||||
[
|
||||
'0',
|
||||
],
|
||||
{
|
||||
}
|
||||
),
|
||||
uavobject.UAVObjectField(
|
||||
'irq_errors',
|
||||
'H',
|
||||
1,
|
||||
[
|
||||
'0',
|
||||
],
|
||||
{
|
||||
}
|
||||
),
|
||||
uavobject.UAVObjectField(
|
||||
'last_error_type',
|
||||
'b',
|
||||
1,
|
||||
[
|
||||
'0',
|
||||
],
|
||||
{
|
||||
'0' : 'EVENT',
|
||||
'1' : 'FSM',
|
||||
'2' : 'INTERRUPT',
|
||||
}
|
||||
),
|
||||
uavobject.UAVObjectField(
|
||||
'event_log',
|
||||
'I',
|
||||
5,
|
||||
[
|
||||
'0',
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
],
|
||||
{
|
||||
}
|
||||
),
|
||||
uavobject.UAVObjectField(
|
||||
'state_log',
|
||||
'I',
|
||||
5,
|
||||
[
|
||||
'0',
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
],
|
||||
{
|
||||
}
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
class I2CStats(uavobject.UAVObject):
|
||||
## Object constants
|
||||
OBJID = 1063893720
|
||||
NAME = "I2CStats"
|
||||
METANAME = "I2CStatsMeta"
|
||||
ISSINGLEINST = 1
|
||||
ISSETTINGS = 0
|
||||
|
||||
def __init__(self):
|
||||
uavobject.UAVObject.__init__(self,
|
||||
self.OBJID,
|
||||
self.NAME,
|
||||
self.METANAME,
|
||||
0,
|
||||
self.ISSINGLEINST)
|
||||
|
||||
for f in _fields:
|
||||
self.add_field(f)
|
||||
|
||||
def __str__(self):
|
||||
s = ("0x%08X (%10u) %-30s %3u bytes format '%s'\n"
|
||||
% (self.OBJID, self.OBJID, self.NAME, self.get_struct().size, self.get_struct().format))
|
||||
for f in self.get_tuple()._fields:
|
||||
s += ("\t%s\n" % f)
|
||||
return (s)
|
||||
|
||||
def main():
|
||||
# Instantiate the object and dump out some interesting info
|
||||
x = I2CStats()
|
||||
print (x)
|
||||
|
||||
if __name__ == "__main__":
|
||||
#import pdb ; pdb.run('main()')
|
||||
main()
|
@ -46,7 +46,8 @@ HEADERS += uavobjects_global.h \
|
||||
ratedesired.h \
|
||||
firmwareiapobj.h \
|
||||
pipxtrememodemsettings.h \
|
||||
pipxtrememodemstatus.h
|
||||
pipxtrememodemstatus.h \
|
||||
i2cstats.h
|
||||
|
||||
SOURCES += uavobject.cpp \
|
||||
uavmetaobject.cpp \
|
||||
@ -90,5 +91,6 @@ SOURCES += uavobject.cpp \
|
||||
ratedesired.cpp \
|
||||
firmwareiapobj.cpp \
|
||||
pipxtrememodemsettings.cpp \
|
||||
pipxtrememodemstatus.cpp
|
||||
pipxtrememodemstatus.cpp \
|
||||
i2cstats.cpp
|
||||
OTHER_FILES += UAVObjects.pluginspec
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "gpstime.h"
|
||||
#include "guidancesettings.h"
|
||||
#include "homelocation.h"
|
||||
#include "i2cstats.h"
|
||||
#include "manualcontrolcommand.h"
|
||||
#include "manualcontrolsettings.h"
|
||||
#include "mixersettings.h"
|
||||
@ -93,6 +94,7 @@ void UAVObjectsInitialize(UAVObjectManager* objMngr)
|
||||
objMngr->registerObject( new GPSTime() );
|
||||
objMngr->registerObject( new GuidanceSettings() );
|
||||
objMngr->registerObject( new HomeLocation() );
|
||||
objMngr->registerObject( new I2CStats() );
|
||||
objMngr->registerObject( new ManualControlCommand() );
|
||||
objMngr->registerObject( new ManualControlSettings() );
|
||||
objMngr->registerObject( new MixerSettings() );
|
||||
|
15
ground/src/shared/uavobjectdefinition/i2cstats.xml
Normal file
15
ground/src/shared/uavobjectdefinition/i2cstats.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<xml>
|
||||
<object name="I2CStats" singleinstance="true" settings="false">
|
||||
<description>Tracks statistics on the I2C bus.</description>
|
||||
<field name="event_errors" units="" type="uint16" elements="1"/>
|
||||
<field name="fsm_errors" units="" type="uint16" elements="1"/>
|
||||
<field name="irq_errors" units="" type="uint16" elements="1"/>
|
||||
<field name="last_error_type" units="" type="enum" elements="1" options="EVENT,FSM,INTERRUPT"/>
|
||||
<field name="event_log" units="" type="uint32" elements="5"/>
|
||||
<field name="state_log" units="" type="uint32" elements="5"/>
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="false" updatemode="manual" period="0"/>
|
||||
<telemetryflight acked="false" updatemode="periodic" period="10000"/>
|
||||
<logging updatemode="periodic" period="30000"/>
|
||||
</object>
|
||||
</xml>
|
Loading…
x
Reference in New Issue
Block a user