Skip to content

Commit

Permalink
Fix nasa#385, adds generic driver interface and Linux sysmon module
Browse files Browse the repository at this point in the history
Defines an "iodriver" interface with a simple module id + opcode +
argument interface, which can be extended as necessary for different
purposes.

Also adds a "linux_sysmon" module that implements this interface to
provide system monitoring capabilities.  This includes, but is not
limited to, the CPU utilization that HS needs.
  • Loading branch information
jphickey committed Apr 6, 2023
1 parent 6fceb13 commit 54bed51
Show file tree
Hide file tree
Showing 16 changed files with 1,465 additions and 1 deletion.
9 changes: 9 additions & 0 deletions fsw/modules/iodriver/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

# Generic I/O device driver interface module
add_psp_module(iodriver src/iodriver.c)

target_include_directories(iodriver PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/inc)

if (ENABLE_UNIT_TESTS)
add_subdirectory(ut-stubs)
endif (ENABLE_UNIT_TESTS)
73 changes: 73 additions & 0 deletions fsw/modules/iodriver/inc/iodriver_analog_io.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (c) 2015, United States government as represented by the
* administrator of the National Aeronautics Space Administration.
* All rights reserved. This software was created at NASA Glenn
* Research Center pursuant to government contracts.
*/

/**
* \file iodriver_analog_io.h
*
* Created on: Sep 30, 2015
* Created by: [email protected]
*
*/

#ifndef CFE_PSP_IODriver_ANALOG_IO_H_
#define CFE_PSP_IODriver_ANALOG_IO_H_

/* Include all base definitions */
#include "iodriver_base.h"

/**
* Standardized width of ADC/DAC codes.
*
* This should reflect the highest-precision ADC that the system is expected to use. ADC inputs
* that are less precise than this will be bit-expanded in software such that all processing
* in the upper layers receives consistent data no matter what the actual hardware implements.
* This permits easier swapping between different phsyical hardware types, including those with
* potentially less ADC/DAC precision, while presenting similar values to application code.
*/
#define CFE_PSP_IODriver_ADC_BITWIDTH 24

/**
* Type abstraction for expressing analog ADC codes.
*
* This type is an integer type of at least CFE_PSP_IODriver_ADC_BITWIDTH in length. It is used
* as a parameter for the Read/Write opcodes on ADC/DAC channels. Normalized (fixed-width) ADC
* codes are used at this layer rather than floating point due to the fact that floats involve a
* lot of extra overhead and some CPUs do not have FP units at all.
*
* If desired on CPUs that are capable of good-performance floating point operations, another
* module/CFS application can convert the ADC codes to real-word floats. This would be done
* outside the I/O driver layer.
*/
typedef int32 CFE_PSP_IODriver_AdcCode_t;

/**
* Complete API container for analog read/write commands.
* This allows reading/writing multiple channels at once with a single entry into the API.
* As each entry into the API needs to acquire a mutex for serialization, this can be much
* more efficient to read channels through this means rather than single channel read/write.
* Set NumChannels to 1 to perform single channel read/write
*/
typedef struct
{
uint16 NumChannels; /**< Number of channels in the i/o structure (length of "samples" array) */
CFE_PSP_IODriver_AdcCode_t *Samples; /**< Array for ADC/DAC samples */
} CFE_PSP_IODriver_AnalogRdWr_t;

/**
* Opcodes specific to analog io (ADC/DAC) devices
*/
enum
{
CFE_PSP_IODriver_ANALOG_IO_NOOP = CFE_PSP_IODriver_ANALOG_IO_CLASS_BASE,

CFE_PSP_IODriver_ANALOG_IO_READ_CHANNELS, /**< CFE_PSP_IODriver_AnalogRdWr_t argument */
CFE_PSP_IODriver_ANALOG_IO_WRITE_CHANNELS, /**< CFE_PSP_IODriver_AnalogRdWr_t argument */

CFE_PSP_IODriver_ANALOG_IO_MAX
};

#endif /* CFE_PSP_IODriver_ANALOG_IO_H_ */
157 changes: 157 additions & 0 deletions fsw/modules/iodriver/inc/iodriver_base.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*
* Copyright (c) 2015, United States government as represented by the
* administrator of the National Aeronautics Space Administration.
* All rights reserved. This software was created at NASA Glenn
* Research Center pursuant to government contracts.
*/

/**
* \file
*
* I/O Driver base header file
*/

#ifndef IODRIVER_BASE_H
#define IODRIVER_BASE_H

#include <common_types.h>

/**
* Physical channel location descriptor.
*
* See the CFE_PSP_IODriver_LOOKUP_SUBCHANNEL opcode to determine channel number to set in here,
* as each board may have their own unique channel naming conventions. The integer value that
* goes in this structure may or may not correlate to the physical device labeling.
*/
typedef struct
{
uint32 PspModuleId; /**< Device selection */
uint16 SubsystemId; /**< Instance or subsystem number */
uint16 SubchannelId; /**< Subchannel number - optional, set to 0 for devices that do not have multiple channels */
} CFE_PSP_IODriver_Location_t;

/**
* Wrapper for constant arguments, to avoid a compiler warning
* about arguments differing in const-ness. Use the inline functions to
* pass in an immediate/constant value.
*/
typedef union
{
void * Vptr;
const void *ConstVptr;
const char *ConstStr;
uint32 U32;
} CFE_PSP_IODriver_Arg_t;

static inline CFE_PSP_IODriver_Arg_t CFE_PSP_IODriver_VPARG(void *x)
{
CFE_PSP_IODriver_Arg_t a;
a.Vptr = x;
return a;
}
static inline CFE_PSP_IODriver_Arg_t CFE_PSP_IODriver_CONST_VPARG(const void *x)
{
CFE_PSP_IODriver_Arg_t a;
a.ConstVptr = x;
return a;
}
static inline CFE_PSP_IODriver_Arg_t CFE_PSP_IODriver_CONST_STR(const char *x)
{
CFE_PSP_IODriver_Arg_t a;
a.ConstStr = x;
return a;
}
static inline CFE_PSP_IODriver_Arg_t CFE_PSP_IODriver_U32ARG(uint32 x)
{
CFE_PSP_IODriver_Arg_t a;
a.U32 = x;
return a;
}

/**
* Standardized concept of directionality for any device
*
* Some code may use these enumeration values as a bitmask -
* use care when updating to ensure that the values may be used as bitmasks.
* Specific hardware drivers may or may not implement all modes depending on capabilities.
*/
typedef enum
{
CFE_PSP_IODriver_Direction_DISABLED = 0, /**< Disabled (inactive, tri-state if possible) */
CFE_PSP_IODriver_Direction_INPUT_ONLY = 0x01, /**< Device/channel is configured for input */
CFE_PSP_IODriver_Direction_OUTPUT_ONLY = 0x02, /**< Device/channel is configured for output */
CFE_PSP_IODriver_Direction_INPUT_OUTPUT = 0x03 /**< Input/Output (some HW supports this) */
} CFE_PSP_IODriver_Direction_t;

/**
* Some common values for the device command codes
* These are some VERY basic ops that many devices may support in some way.
* Any opcode that is not implemented should return CFE_PSP_ERROR_NOT_IMPLEMENTED
*
* Negative return values indicate an error of some type, while return values >= 0 indicate success
*/
enum
{
CFE_PSP_IODriver_NOOP = 0, /**< Reserved, do nothing */

/* Start/stop opcodes */
CFE_PSP_IODriver_SET_RUNNING, /**< uint32 argument, 0=stop 1=start device */
CFE_PSP_IODriver_GET_RUNNING, /**< no argument, returns positive nonzero (true) if running and zero (false) if
stopped, negative on error */

/* Configuration opcodes */
CFE_PSP_IODriver_SET_CONFIGURATION, /**< const string argument (device-dependent content) */
CFE_PSP_IODriver_GET_CONFIGURATION, /**< void * argument (device-dependent content) */

/* Sub-channel configuration/mapping opcodes */
CFE_PSP_IODriver_LOOKUP_SUBSYSTEM, /**< const char * argument, looks up ChannelName and returns positive value for
subsystem ID, negative value for error */
CFE_PSP_IODriver_LOOKUP_SUBCHANNEL, /**< const char * argument, looks up ChannelName and returns positive value for
subchannel ID, negative value for error */
CFE_PSP_IODriver_SET_DIRECTION, /**< U32 (CFE_PSP_IODriver_Direction_t) argument as input */
CFE_PSP_IODriver_QUERY_DIRECTION, /**< U32 (CFE_PSP_IODriver_Direction_t) argument as output */

/*
* Placeholders for opcodes that could be implemented across a class of devices.
* For instance, all ADC/DAC devices should implement a common set of read/write opcodes
* so that devices can be interchanged without affecting higher-level software
*/
CFE_PSP_IODriver_ANALOG_IO_CLASS_BASE = 0x00010000, /**< Opcodes for typical adc/dac devices */
CFE_PSP_IODriver_DISCRETE_IO_CLASS_BASE = 0x00020000, /**< Opcodes for discrete IO (digital logic) devices */
CFE_PSP_IODriver_PACKET_IO_CLASS_BASE = 0x00030000, /**< Opcodes for packet/datagram-oriented devices */
CFE_PSP_IODriver_MEMORY_IO_CLASS_BASE = 0x00040000, /**< Opcodes for memory/register oriented devices */
CFE_PSP_IODriver_STREAM_IO_CLASS_BASE = 0x00050000, /**< Opcodes for data stream oriented devices */

/**
* Placeholder for extended opcodes that may be very specific to a single device/device type.
* This allows the same API call (CFE_PSP_DeviceCommandFunc_t) but
*/
CFE_PSP_IODriver_EXTENDED_BASE = 0x7FFF0000

};

/* ------------------------------------------------------------- */
/**
* @brief Find an IO device module ID by name
*
* @param DriverName the device name to find
* @param PspModuleId location to store the module ID, if found
*
* @retval #CFE_PSP_SUCCESS if found, or error code if not found
*/
int32 CFE_PSP_IODriver_FindByName(const char *DriverName, uint32 *PspModuleId);

/* ------------------------------------------------------------- */
/**
* @brief Issue a request to an IO device module
*
* @param Location Aggregate location identifier
* @param CommandCode Request identifier
* @param Arg Request Argument
*
* @retval #CFE_PSP_SUCCESS if successful, or error code if not successful
*/
int32 CFE_PSP_IODriver_Command(const CFE_PSP_IODriver_Location_t *Location, uint32 CommandCode,
CFE_PSP_IODriver_Arg_t Arg);

#endif /* IODRIVER_BASE_H */
93 changes: 93 additions & 0 deletions fsw/modules/iodriver/inc/iodriver_digital_gpio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright (c) 2015, United States government as represented by the
* administrator of the National Aeronautics Space Administration.
* All rights reserved. This software was created at NASA Glenn
* Research Center pursuant to government contracts.
*/

/**
* \file iodriver_digital_gpio.h
*
* Created on: Sep 30, 2015
* Created by: [email protected]
*
*/

#ifndef CFE_PSP_IODriver_DISCRETE_GPIO_H_
#define CFE_PSP_IODriver_DISCRETE_GPIO_H_

/**
* Type abstraction for expressing digital logic levels.
*
* This value will be filled starting with the LSB. A typical GPIO logic channel is 1 bit, so
* only the LSB is signficiant and the other bits are not used.
*
* This allows single channels up to 8 bits wide, but multiple "channels" could be concatenated
* using a multi-read/write opcode to allow atomic access to any number of bits.
*/
typedef uint8 CFE_PSP_IODriver_GpioLevel_t;

/**
* Enumerated names for typical digital 1-bit logic channel states.
*
* For convenience / code readability.
*/
enum
{
CFE_PSP_IODriver_GPIO_LOGIC_LOW = 0,
CFE_PSP_IODriver_GPIO_LOGIC_HIGH = 1
};

#ifdef JPHFIX
/**
* Overall Configuration structure for channel configuration commands.
*
* This describes both ADC/DAC (analog) and GPIO (digital logic)
* channels. It is returned from the "Get Status" command.
*/
typedef struct
{
CFE_PSP_IODriver_ChannelType_t ChannelType; /**< Define the type of channel */
CFE_PSP_IODriver_Direction_t Direction; /**< Define whether GPIO is input or output */
} CFE_PSP_IODriver_ChannelStatus_t;

/**
* Sample container for multi-channel read/write commands.
*
* This is just a pointer to an array, but the array could be ADC codes
* or digital logic levels. This allows the same API to be used for both.
*/
typedef union
{
void * VoidPtr;
CFE_PSP_IODriver_GpioLevel_t *GpioLev;
} CFE_PSP_IODriver_Sample_t;

#endif

/**
* Complete API container for gpio read/write commands.
* This allows reading/writing multiple channels at once with a single entry into the API.
* As each entry into the API needs to acquire a mutex for serialization, this can be much
* more efficient to read channels through this means rather than single channel read/write.
*/
typedef struct
{
uint16 NumChannels; /**< Number of channels in the i/o structure (length of "samples" array) */
CFE_PSP_IODriver_GpioLevel_t *Samples; /**< Array for digital logic levels */
} CFE_PSP_IODriver_GpioRdWr_t;

/**
* Opcodes specific to digital GPIO devices
*/
enum
{
CFE_PSP_IODriver_DISCRETE_IO_NOOP = CFE_PSP_IODriver_DISCRETE_IO_CLASS_BASE,

CFE_PSP_IODriver_DISCRETE_IO_READ_CHANNELS, /**< CFE_PSP_IODriver_GpioRdWr_t argument */
CFE_PSP_IODriver_DISCRETE_IO_WRITE_CHANNELS, /**< CFE_PSP_IODriver_GpioRdWr_t argument */

CFE_PSP_IODriver_DISCRETE_IO_MAX
};

#endif /* CFE_PSP_IODriver_DISCRETE_GPIO_H_ */
55 changes: 55 additions & 0 deletions fsw/modules/iodriver/inc/iodriver_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2015, United States government as represented by the
* administrator of the National Aeronautics Space Administration.
* All rights reserved. This software was created at NASA Glenn
* Research Center pursuant to government contracts.
*/

/**
* \file iodriver_impl.h
*
* Created on: Oct 5, 2015
* Created by: [email protected]
*
*/

#ifndef IODRIVER_IMPL_H
#define IODRIVER_IMPL_H

#ifndef _CFE_PSP_MODULE_
#error "Do not include this file from outside the PSP"
#endif

#include "cfe_psp_module.h"
#include "iodriver_base.h"

/**
* Macro to declare the global object for an IO device driver
*/
#define CFE_PSP_MODULE_DECLARE_IODEVICEDRIVER(name) \
static void name##_Init(uint32 PspModuleId); \
CFE_PSP_ModuleApi_t CFE_PSP_##name##_API = { \
.ModuleType = CFE_PSP_MODULE_TYPE_DEVICEDRIVER, \
.OperationFlags = 0, \
.Init = name##_Init, \
.ExtendedApi = &name##_DevApi, \
}

/**
* Prototype for a basic device command function
* Implemented as a single API call with an extendible command code for device-specific ops. This allows
* a common API to be used while still allowing full freedom to handle many different device types.
*/
typedef int32 (*CFE_PSP_IODriver_ApiFunc_t)(uint32 CommandCode, uint16 Instance, uint16 SubChannel,
CFE_PSP_IODriver_Arg_t arg);

typedef const struct
{
CFE_PSP_IODriver_ApiFunc_t DeviceCommand;
CFE_PSP_IODriver_ApiFunc_t DeviceMutex;
} CFE_PSP_IODriver_API_t;

osal_id_t CFE_PSP_IODriver_GetMutex(uint32 PspModuleId, int32 DeviceHash);
int32 CFE_PSP_IODriver_HashMutex(int32 StartHash, int32 Datum);

#endif /* IODRIVER_IMPL_H */
Loading

0 comments on commit 54bed51

Please sign in to comment.