AVED Sensor Control (ASC) Proxy Driver¶
Overview¶
The ASC proxy driver allocates memory and copies all provided sensor data from the appropriate profile (see Profiles and CMake build process#Profiles) in the initialization. ASC uses this to read associated sensor functions, store current values, current statuses and calculates averages for all provided sensors.
Internally, it creates a mutex for protection and a task to handle interaction with the associated sensor functions.
The Task will:
Call the associated read sensor function and store its value.
Signal an event with the EVL core library.
The Proxy API consists of a number of functions to set and get the sensor data that is updated by the proxy task.
API¶
Defines¶
Defines
#define ASC_SENSOR_NAME_MAX ( 20 )
Enums¶
ASC_PROXY_DRIVER_EVENTS
/*
* @enum ASC_PROXY_DRIVER_EVENTS
* @brief Events raised by this proxy driver
*/
typedef enum ASC_PROXY_DRIVER_EVENTS
{
ASC_PROXY_DRIVER_E_SENSOR_UPDATE_COMPLETE = 0,
ASC_PROXY_DRIVER_E_SENSOR_UNAVAILABLE,
ASC_PROXY_DRIVER_E_SENSOR_COMMS_FAILURE,
ASC_PROXY_DRIVER_E_SENSOR_WARNING,
ASC_PROXY_DRIVER_E_SENSOR_CRITICAL,
ASC_PROXY_DRIVER_E_SENSOR_FATAL,
ASC_PROXY_DRIVER_E_SENSOR_LOWER_WARNING,
ASC_PROXY_DRIVER_E_SENSOR_LOWER_CRITICAL,
ASC_PROXY_DRIVER_E_SENSOR_LOWER_FATAL,
ASC_PROXY_DRIVER_E_SENSOR_UPPER_WARNING,
ASC_PROXY_DRIVER_E_SENSOR_UPPER_CRITICAL,
ASC_PROXY_DRIVER_E_SENSOR_UPPER_FATAL,
MAX_ASC_PROXY_DRIVER_EVENTS
} ASC_PROXY_DRIVER_EVENTS;
ASC_PROXY_DRIVER_SENSOR_STATUS
/*
* @enum ASC_PROXY_DRIVER_SENSOR_STATUS
* @brief Status of sensor
*/
typedef enum ASC_PROXY_DRIVER_SENSOR_STATUS
{
ASC_PROXY_DRIVER_SENSOR_STATUS_NOT_PRESENT = 0,
ASC_PROXY_DRIVER_SENSOR_STATUS_PRESENT_AND_VALID,
ASC_PROXY_DRIVER_SENSOR_STATUS_DATA_NOT_AVAILABLE,
ASC_PROXY_DRIVER_SENSOR_STATUS_NOT_AVAILABLE,
MAX_ASC_PROXY_DRIVER_SENSOR_STATUS
} ASC_PROXY_DRIVER_SENSOR_STATUS;
ASC_PROXY_DRIVER_SENSOR_UNIT_MOD
/*
* @enum ASC_PROXY_DRIVER_SENSOR_UNIT_MOD
* @brief Base unit modifiers for sensor readings
*/
typedef enum ASC_PROXY_DRIVER_SENSOR_UNIT_MOD
{
ASC_PROXY_DRIVER_SENSOR_UNIT_MOD_MEGA = 0,
ASC_PROXY_DRIVER_SENSOR_UNIT_MOD_KILO,
ASC_PROXY_DRIVER_SENSOR_UNIT_MOD_NONE,
ASC_PROXY_DRIVER_SENSOR_UNIT_MOD_MILLI,
ASC_PROXY_DRIVER_SENSOR_UNIT_MOD_MICRO,
MAX_ASC_PROXY_DRIVER_SENSOR_UNIT_MOD
} ASC_PROXY_DRIVER_SENSOR_UNIT_MOD;
ASC_PROXY_DRIVER_SENSOR_TYPE
/*
* @enum ASC_PROXY_DRIVER_SENSOR_TYPE
* @brief Type of sensor
*/
typedef enum ASC_PROXY_DRIVER_SENSOR_TYPE
{
ASC_PROXY_DRIVER_SENSOR_TYPE_TEMPERATURE = 0,
ASC_PROXY_DRIVER_SENSOR_TYPE_VOLTAGE,
ASC_PROXY_DRIVER_SENSOR_TYPE_CURRENT,
ASC_PROXY_DRIVER_SENSOR_TYPE_POWER,
MAX_ASC_PROXY_DRIVER_SENSOR_TYPE
} ASC_PROXY_DRIVER_SENSOR_TYPE;
ASC_PROXY_DRIVER_SENSOR_BITFIELD
/*
* @enum ASC_PROXY_DRIVER_SENSOR_BITFIELD
* @brief Bitfield of sensor types
*/
typedef enum ASC_PROXY_DRIVER_SENSOR_BITFIELD
{
ASC_PROXY_DRIVER_SENSOR_BITFIELD_TEMPERATURE = ( 1 << 0 ),
ASC_PROXY_DRIVER_SENSOR_BITFIELD_VOLTAGE = ( 1 << 1 ),
ASC_PROXY_DRIVER_SENSOR_BITFIELD_CURRENT = ( 1 << 2 ),
ASC_PROXY_DRIVER_SENSOR_BITFIELD_POWER = ( 1 << 3 ),
MAX_ASC_PROXY_DRIVER_SENSOR_BITFIELD
} ASC_PROXY_DRIVER_SENSOR_BITFIELD;
Structs¶
ASC_PROXY_DRIVER_SENSOR_READINGS
/*
* @struct ASC_PROXY_DRIVER_SENSOR_READINGS
* @brief Sensor data readings
*/
typedef struct ASC_PROXY_DRIVER_SENSOR_READINGS
{
uint32_t ulSensorValue;
const uint32_t ulLowerWarningLimit;
const uint32_t ulLowerCriticalLimit;
const uint32_t ulLowerFatalLimit;
const uint32_t ulUpperWarningLimit;
const uint32_t ulUpperCriticalLimit;
const uint32_t ulUpperFatalLimit;
uint32_t ulAverageSensorValue;
uint32_t ulMaxSensorValue;
ASC_PROXY_DRIVER_SENSOR_STATUS xSensorStatus;
ASC_PROXY_DRIVER_SENSOR_UNIT_MOD xSensorUnitModifier;
} ASC_PROXY_DRIVER_SENSOR_READINGS;
ASC_PROXY_DRIVER_SENSOR_DATA
/*
* @struct ASC_PROXY_DRIVER_SENSOR_DATA
* @brief Sensor data
*/
typedef struct ASC_PROXY_DRIVER_SENSOR_DATA
{
const char pcSensorName[ ASC_SENSOR_NAME_MAX ];
const uint8_t ucSensorId;
const uint8_t ucSensorType;
const uint8_t ucSensorAddress;
ASC_PROXY_DRIVER_SENSOR_READINGS xReadings[ MAX_ASC_PROXY_DRIVER_SENSOR_TYPE ];
} ASC_PROXY_DRIVER_SENSOR_DATA;
Proxy Driver External APIs¶
Initialise the ASC¶
iASC_Initialise
/*
* @brief Main initialisation point for the ASC Proxy Driver
*
* @param ucProxyId Unique ID for this Proxy driver
* @param pxFwIf Handle to the Firmware Interface to use
* @param ulFwIfPort Port to use on the Firmware Interface
* @param ulTaskPrio Priority of the Proxy driver task (if RR disabled)
* @param ulTaskStack Stack size of the Proxy driver task
* @param pxSensorData Array of sensor data
* @param ucNumSensors Number of sensors to monitor
*
* @return OK Proxy driver initialised correctly
* ERROR Proxy driver not initialised, or was already initialised
*
* @notes Proxy drivers can have 0 or more firmware interfaces
*/
int iASC_Initialise( uint8_t ucProxyId,
FW_IF_CFG *pxFwIf,
uint32_t ulFwIfPort,
uint32_t ulTaskPrio,
uint32_t ulTaskStack,
ASC_PROXY_DRIVER_SENSOR_DATA *pxSensorData,
uint8_t ucNumSensors );
Bind callback¶
iASC_BindCallback
/*
* @brief Bind into this proxy driver
*
* @param pxCallback Callback to bind into the proxy driver
*
* @return OK Callback successfully bound
* ERROR Callback not bound
*
* @notes None
*/
int iASC_BindCallback( AEL_CALLBACK *pxCallback );
Reset all of the transient sensor data¶
iASC_ResetAllSensorData
/*
* @brief Reset current, average, max and status values for all sensors
*
* @param None
*
* @return OK Data reset successfully
* ERROR Data not reset successfully
*
* @notes None
*/
int iASC_ResetAllSensorData( void );
Reset a single sensor’s transient data by ID¶
iASC_ResetSingleSensorDatabyId
/*
* @brief Reset current, average, max and status values for a single sensor by ID
*
* @param ucId Sensor ID
*
* @return OK Data reset successfully
* ERROR Data not reset successfully
*
* @notes None
*/
int iASC_ResetSingleSensorDatabyId( uint8_t ucId );
Reset a single sensor’s transient data by name¶
iASC_ResetSingleSensorDatabyName
/*
* @brief Reset current, average, max and status values for a single sensor by name
*
* @param pcName Sensor Name
*
* @return OK Data reset successfully
* ERROR Data not reset successfully
*
* @notes None
*/
int iASC_ResetSingleSensorDatabyName( const char *pcName );
Get all of the sensor’s data¶
iASC_GetAllSensorData
/*
* @brief Get all sensor data
*
* @param pxData Pointer to data to get
* @param pucNumSensors Pointer to the number of sensors monitored
* Orignally passed in as the maximum number of sensors that can be monitored but will then be
* updated to the actual number of sensors that are monitored
*
* @return OK Data retrieved successfully
* ERROR Data not retrieved successfully
*
* @notes None
*/
int iASC_GetAllSensorData( ASC_PROXY_DRIVER_SENSOR_DATA *pxData, uint8_t *pucNumSensors );
Get a single sensor’s data by ID¶
iASC_GetSingleSensorDataById
/*
* @brief Get single sensor data by ID
*
* @param ucId Sensor ID
* @param pxData Pointer to data to get
*
* @return OK Data retrieved successfully
* ERROR Data not retrieved successfully
*
* @notes None
*/
int iASC_GetSingleSensorDataById( uint8_t ucId, ASC_PROXY_DRIVER_SENSOR_DATA *pxData );
Get a single sensor’s data by name¶
iASC_GetSingleSensorDataByName
/*
* @brief Get single sensor data by name
*
* @param pcName Sensor Name
* @param pxData Pointer to data to get
*
* @return OK Data retrieved successfully
* ERROR Data not retrieved successfully
*
* @notes None
*/
int iASC_GetSingleSensorDataByName( const char *pcName, ASC_PROXY_DRIVER_SENSOR_DATA *pxData );
Display the statistic counters and errors.¶
iASC_PrintStatistics
/**
* @brief Print all of the stats gathered by the application
*
* @return OK Stats retrieved from proxy driver successfully
* ERROR Stats not retrieved successfully
*
*/
int iASC_PrintStatistics( void );
Clear the all statistics counters back to zero.¶
iASC_ClearStatistics
/**
* @brief Clear all of the stats in the application
*
* @return OK Stats cleared successfully
* ERROR Stats not cleared successfully
*
*/
int iASC_ClearStatistics( void );
Sequence Diagrams¶
ASC Proxy Initialization¶
Two ASC API functions are called from the AMC main task (iASC_Initialise and iASC_BindCallback), in order to initialise the proxy.
iASC_Initialise will call into the FAL to open with the provided handle, create a shared proxy mutex, create the proxy task, allocate memory and copy the provided sensor data.
iASC_BindCallback will bind the appropriate top-level callback function.
ASC Proxy Task¶
The task within ASC proxy has 2 main responsibilities:
For each sensor, and for each sensor type (temperature, voltage, current, power, etc), call the associated read sensor function, store its value, calculate average value, and set its status.
Signal an event with EVL core library, if a sensor value exceeds thresholds and when sensor updates have completed.
Examples¶
Initialize Driver¶
This function should only be called once. It requires an unique ID for the proxy, used for signaling new events from the proxy, along with a handle to a FW_IF (already created and initialized), FW_IF port number, proxy driver task priority, stack size, pointer to sensor data array and total number of sensors to be monitored (should match the number of entries in the sensor array).
iASC_Initialise Example
if( OK == iASC_Initialise( AMC_EVENT_UNIQUE_ID_ASC, &xI2cIf, 0, AMC_TASK_PRIO_DEFAULT, AMC_TASK_DEFAULT_STACK, PROFILE_SENSORS_SENSOR_DATA, PROFILE_SENSORS_NUM_SENSORS ) )
{
AMC_PRINTF( "ASC Proxy Driver initialised\r\n" );
}
else
{
AMC_PRINTF( "Error initialising ASC Proxy Driver\r\n" );
}
Register For Callback¶
Define a function based on the function pointer prototype and bind in using the API.
iASC_BindCallback Example
/* Define a callback to handle the events */
static int iAscCallback( EVL_SIGNAL *pxSignal )
{
int iStatus = ERROR;
if( ( NULL != pxSignal ) && ( AMC_EVENT_UNIQUE_ID_ASC == pxSignal->ucModule ) )
{
switch( pxSignal->ucEventType )
{
case ASC_PROXY_DRIVER_E_SENSOR_UPDATE_COMPLETE:
case ASC_PROXY_DRIVER_E_SENSOR_UNAVAILABLE:
case ASC_PROXY_DRIVER_E_SENSOR_COMMS_FAILURE:
case ASC_PROXY_DRIVER_E_SENSOR_WARNING:
case ASC_PROXY_DRIVER_E_SENSOR_CRITICAL:
case ASC_PROXY_DRIVER_E_SENSOR_FATAL:
case ASC_PROXY_DRIVER_E_SENSOR_LOWER_WARNING:
case ASC_PROXY_DRIVER_E_SENSOR_LOWER_CRITICAL:
case ASC_PROXY_DRIVER_E_SENSOR_LOWER_FATAL:
case ASC_PROXY_DRIVER_E_SENSOR_UPPER_WARNING:
case ASC_PROXY_DRIVER_E_SENSOR_UPPER_CRITICAL:
case ASC_PROXY_DRIVER_E_SENSOR_UPPER_FATAL:
/* TODO: handle events */
iStatus = OK;
break;
default:
break;
}
}
return iStatus;
}
/* Bind into the callback during the application initialisation */
if( OK == iASC_BindCallback( &iAscCallback ) )
{
AMC_PRINTF( "ASC Proxy Driver initialised and bound\r\n" );
}
else
{
AMC_PRINTF( "Error binding to ASC Proxy Driver\r\n" );
}
Sets¶
Reset all sensor data¶
Example of re-setting all sensor data. No parameters required, simply call the API.
iASC_ResetAllSensorData Example
if( OK != iASC_ResetAllSensorData() )
{
ASC_DBG_PRINTF( "Error resetting sensors data\r\n" );
}
else
{
ASC_DBG_PRINTF( "All sensor data reset\r\n" );
}
Reset single sensor data (by ID)¶
Example of re-setting single sensor by ID.
iASC_ResetSingleSensorDataById Example
uint8_t iId = 0; /* set to required ID */
if( OK != iASC_ResetSingleSensorDataById( iId )
{
ASC_DBG_PRINTF( "Error resetting sensor %d data\r\n", iId );
}
else
{
ASC_DBG_PRINTF( "Sensor %d data reset\r\n", iId );
}
Reset single sensor data (by name)¶
Example of re-setting single sensor by name.
iASC_ResetSingleSensorDataByName Example
char pcName[ ASC_SENSOR_NAME_MAX ] = { 0 }; /* set to required name */
if( OK != iASC_ResetSingleSensorDataByName( pcName ) )
{
ASC_DBG_PRINTF( "Error resetting sensor %s data\r\n", pcName );
}
else
{
ASC_DBG_PRINTF( "Sensor %s data reset\r\n", pcName );
}
Gets¶
Get all sensor data¶
Example of reading all sensor data, from max number of sensors required.
iASC_GetAllSensorData Example
int iMaxSensors = 15; /* Set to max num of sensors required */
ASC_PROXY_DRIVER_SENSOR_DATA *pxSensors = pvOSAL_MemAlloc( iMaxSensors * sizeof( ASC_PROXY_DRIVER_SENSOR_DATA ) );
if( NULL == pxSensors )
{
ASC_DBG_PRINTF( "Unable to allocate data for %d sensors\r\n", iMaxSensors );
}
else
{
uint8_t uNumSensors = ( uint8_t )iMaxSensors;
if( OK != iASC_GetAllSensorData( pxSensors, &uNumSensors ) )
{
ASC_DBG_PRINTF( "Error retrieving sensor data\r\n" );
}
else
{
ASC_DBG_PRINTF( "Retrieved %d sensors\r\n", uNumSensors );
int i = 0;
for( i = 0; i < uNumSensors; i++ )
{
ASC_DBG_PRINTF( "Sensor %d:\r\n", i );
ASC_DBG_PRINTF( "****************************************************\r\n" );
vPrintSensorData( &pxSensors[ i ] );
}
}
vOSAL_MemFree( ( void** )&pxSensors ); /* free allocated memory */
}
Get single sensor data (by ID)¶
Example of reading sensor data by ID. Also included, an example of printing full data from a single sensor.
iASC_GetSingleSensorDataById Example
int iId = 0; /* set to required ID */
ASC_PROXY_DRIVER_SENSOR_DATA xSensor = { { 0 } };
if( OK != iASC_GetSingleSensorDataById( ( uint8_t )iId, &xSensor ) )
{
ASC_DBG_PRINTF( "Error retrieving sensor %d data\r\n", iId );
}
else
{
vPrintSensorData( &xSensor );
}
/**
* @brief Display the full data of a single sensor
*/
static void vPrintSensorData( ASC_PROXY_DRIVER_SENSOR_DATA *pxSensor )
{
if( NULL != pxSensor )
{
int i = 0;
ASC_DBG_PRINTF( "====================================================\r\n" );
ASC_DBG_PRINTF( "Sensor . . . . . . . . . . . . . . %s\r\n", pxSensor->pcSensorName );
ASC_DBG_PRINTF( "- ID . . . . . . . . . . . . . . . %d\r\n", pxSensor->ucSensorId );
ASC_DBG_PRINTF( "- Type . . . . . . . . . . . . . . 0x%02X\r\n", pxSensor->ucSensorType );
ASC_DBG_PRINTF( "- Address. . . . . . . . . . . . . 0x%02X\r\n", pxSensor->ucSensorAddress );
for( i = 0; i < MAX_ASC_PROXY_DRIVER_SENSOR_TYPE; i++ )
{
ASC_DBG_PRINTF( "----------------------------------------------------\r\n" );
ASC_DBG_PRINTF( "Type: %s\r\n", pcTypeStrings[ i ] );
ASC_DBG_PRINTF( "- Channel number . . . . . . . . . %d\r\n", pxSensor->ucChannelNumber[ i ] );
ASC_DBG_PRINTF( "- Driver callback. . . . . . . . . %s\r\n",
( NULL != pxSensor->pxReadSensorFunc[ i ] ) ? ( "Valid" ):( "NULL" ) );
ASC_DBG_PRINTF( "- reading: value . . . . . . . . . %d\r\n", pxSensor->xReadings[ i ].ulSensorValue );
ASC_DBG_PRINTF( "- reading: lower Warning limit . . %d\r\n", pxSensor->xReadings[ i ].ulLowerWarningLimit );
ASC_DBG_PRINTF( "- reading: lower critical limit. . %d\r\n", pxSensor->xReadings[ i ].ulLowerCriticalLimit );
ASC_DBG_PRINTF( "- reading: lower fatal limit . . . %d\r\n", pxSensor->xReadings[ i ].ulLowerFatalLimit );
ASC_DBG_PRINTF( "- reading: upper Warning limit . . %d\r\n", pxSensor->xReadings[ i ].ulUpperWarningLimit );
ASC_DBG_PRINTF( "- reading: upper critical limit. . %d\r\n", pxSensor->xReadings[ i ].ulUpperCriticalLimit );
ASC_DBG_PRINTF( "- reading: upper fatal limit . . . %d\r\n", pxSensor->xReadings[ i ].ulUpperFatalLimit );
ASC_DBG_PRINTF( "- reading: average sensor value. . %d\r\n", pxSensor->xReadings[ i ].ulAverageSensorValue );
ASC_DBG_PRINTF( "- reading: max sensor value. . . . %d\r\n", pxSensor->xReadings[ i ].ulMaxSensorValue );
ASC_DBG_PRINTF( "- reading: sensor status . . . . . %s\r\n",
pcStatusStrings[ pxSensor->xReadings[ i ].xSensorStatus ] );
ASC_DBG_PRINTF( "- reading: sensor unit modifier. . %s\r\n",
pcModStrings[ pxSensor->xReadings[ i ].xSensorUnitModifier ] );
}
}
else
{
ASC_DBG_PRINTF( "Error - invalid sensor data\r\n" );
}
}
Get single sensor data (by name)¶
Example of reading sensor data by name. Also included, an example of printing full data from a single sensor.
iASC_GetSingleSensorDataByName Example
char pcName[ ASC_SENSOR_NAME_MAX ] = { 0 }; /* set to required name */
ASC_PROXY_DRIVER_SENSOR_DATA xSensor = { { 0 } };
if( OK != iASC_GetSingleSensorDataByName( pcName, &xSensor ) )
{
ASC_DBG_PRINTF( "Error retrieving sensor %s data\r\n", pcName );
}
else
{
vPrintSensorData( &xSensor );
}
/**
* @brief Display the full data of a single sensor
*/
static void vPrintSensorData( ASC_PROXY_DRIVER_SENSOR_DATA *pxSensor )
{
if( NULL != pxSensor )
{
int i = 0;
ASC_DBG_PRINTF( "====================================================\r\n" );
ASC_DBG_PRINTF( "Sensor . . . . . . . . . . . . . . %s\r\n", pxSensor->pcSensorName );
ASC_DBG_PRINTF( "- ID . . . . . . . . . . . . . . . %d\r\n", pxSensor->ucSensorId );
ASC_DBG_PRINTF( "- Type . . . . . . . . . . . . . . 0x%02X\r\n", pxSensor->ucSensorType );
ASC_DBG_PRINTF( "- Address. . . . . . . . . . . . . 0x%02X\r\n", pxSensor->ucSensorAddress );
for( i = 0; i < MAX_ASC_PROXY_DRIVER_SENSOR_TYPE; i++ )
{
ASC_DBG_PRINTF( "----------------------------------------------------\r\n" );
ASC_DBG_PRINTF( "Type: %s\r\n", pcTypeStrings[ i ] );
ASC_DBG_PRINTF( "- Channel number . . . . . . . . . %d\r\n", pxSensor->ucChannelNumber[ i ] );
ASC_DBG_PRINTF( "- Driver callback. . . . . . . . . %s\r\n",
( NULL != pxSensor->pxReadSensorFunc[ i ] ) ? ( "Valid" ):( "NULL" ) );
ASC_DBG_PRINTF( "- reading: value . . . . . . . . . %d\r\n", pxSensor->xReadings[ i ].ulSensorValue );
ASC_DBG_PRINTF( "- reading: lower Warning limit . . %d\r\n", pxSensor->xReadings[ i ].ulLowerWarningLimit );
ASC_DBG_PRINTF( "- reading: lower critical limit. . %d\r\n", pxSensor->xReadings[ i ].ulLowerCriticalLimit );
ASC_DBG_PRINTF( "- reading: lower fatal limit . . . %d\r\n", pxSensor->xReadings[ i ].ulLowerFatalLimit );
ASC_DBG_PRINTF( "- reading: upper Warning limit . . %d\r\n", pxSensor->xReadings[ i ].ulUpperWarningLimit );
ASC_DBG_PRINTF( "- reading: upper critical limit. . %d\r\n", pxSensor->xReadings[ i ].ulUpperCriticalLimit );
ASC_DBG_PRINTF( "- reading: upper fatal limit . . . %d\r\n", pxSensor->xReadings[ i ].ulUpperFatalLimit );
ASC_DBG_PRINTF( "- reading: average sensor value. . %d\r\n", pxSensor->xReadings[ i ].ulAverageSensorValue );
ASC_DBG_PRINTF( "- reading: max sensor value. . . . %d\r\n", pxSensor->xReadings[ i ].ulMaxSensorValue );
ASC_DBG_PRINTF( "- reading: sensor status . . . . . %s\r\n",
pcStatusStrings[ pxSensor->xReadings[ i ].xSensorStatus ] );
ASC_DBG_PRINTF( "- reading: sensor unit modifier. . %s\r\n",
pcModStrings[ pxSensor->xReadings[ i ].xSensorUnitModifier ] );
}
}
else
{
ASC_DBG_PRINTF( "Error - invalid sensor data\r\n" );
}
}
Page Revision: v. 62