Adding Code for Linux
This commit is contained in:
parent
db1f93a155
commit
fd782b20c0
@ -20,11 +20,13 @@ ReturnValue_t ActionHelper::handleActionMessage(CommandMessage* command) {
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t ActionHelper::initialize() {
|
||||
ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) {
|
||||
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if (ipcStore == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
setQueueToUse(queueToUse_);
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
@ -100,3 +102,6 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t rep
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ActionHelper::resetHelper() {
|
||||
}
|
||||
|
@ -4,26 +4,90 @@
|
||||
#include <framework/action/ActionMessage.h>
|
||||
#include <framework/serialize/SerializeIF.h>
|
||||
#include <framework/ipc/MessageQueueIF.h>
|
||||
|
||||
/**
|
||||
* \brief Action Helper is a helper class which handles action messages
|
||||
*
|
||||
* Components which use the HasActionIF this helper can be used to handle the action messages.
|
||||
* It does handle step messages as well as other answers to action calls. It uses the executeAction function
|
||||
* of its owner as callback. The call of the initialize function is mandatory and it needs a valid messageQueueIF pointer!
|
||||
*/
|
||||
class HasActionsIF;
|
||||
|
||||
class ActionHelper {
|
||||
public:
|
||||
/**
|
||||
* Constructor of the action helper
|
||||
* @param setOwner Pointer to the owner of the interface
|
||||
* @param useThisQueue messageQueue to be used, can be set during initialize function as well.
|
||||
*/
|
||||
ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
||||
|
||||
virtual ~ActionHelper();
|
||||
/**
|
||||
* Function to be called from the owner with a new command message
|
||||
*
|
||||
* If the message is a valid action message the helper will use the executeAction function from HasActionsIF.
|
||||
* If the message is invalid or the callback fails a message reply will be send to the sender of the message automatically.
|
||||
*
|
||||
* @param command Pointer to a command message received by the owner
|
||||
* @return HasReturnvaluesIF::RETURN_OK if the message is a action message, CommandMessage::UNKNOW_COMMAND if this message ID is unkown
|
||||
*/
|
||||
ReturnValue_t handleActionMessage(CommandMessage* command);
|
||||
ReturnValue_t initialize();
|
||||
/**
|
||||
* Helper initialize function. Must be called before use of any other helper function
|
||||
* @param queueToUse_ Pointer to the messageQueue to be used
|
||||
* @return Returns RETURN_OK if successful
|
||||
*/
|
||||
ReturnValue_t initialize(MessageQueueIF* queueToUse_);
|
||||
/**
|
||||
* Function to be called from the owner to send a step message. Success or failure will be determined by the result value.
|
||||
*
|
||||
* @param step Number of steps already done
|
||||
* @param reportTo The messageQueueId to report the step message to
|
||||
* @param commandId ID of the executed command
|
||||
* @param result Result of the execution
|
||||
*/
|
||||
void step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
/**
|
||||
* Function to be called by the owner to send a action completion message
|
||||
*
|
||||
* @param reportTo MessageQueueId_t to report the action completion message to
|
||||
* @param commandId ID of the executed command
|
||||
* @param result Result of the execution
|
||||
*/
|
||||
void finish(MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
/**
|
||||
* Function to be called by the owner if an action does report data
|
||||
*
|
||||
* @param reportTo MessageQueueId_t to report the action completion message to
|
||||
* @param replyId ID of the executed command
|
||||
* @param data Pointer to the data
|
||||
* @return Returns RETURN_OK if successful, otherwise failure code
|
||||
*/
|
||||
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data, bool hideSender = false);
|
||||
/**
|
||||
* Function to setup the MessageQueueIF* of the helper. Can be used to set the messageQueueIF* if
|
||||
* message queue is unavailable at construction and initialize but must be setup before first call of other functions.
|
||||
* @param queue Queue to be used by the helper
|
||||
*/
|
||||
void setQueueToUse(MessageQueueIF *queue);
|
||||
protected:
|
||||
static const uint8_t STEP_OFFSET = 1;
|
||||
HasActionsIF* owner;
|
||||
MessageQueueIF* queueToUse;
|
||||
StorageManagerIF* ipcStore;
|
||||
static const uint8_t STEP_OFFSET = 1;//!< Increase of value of this per step
|
||||
HasActionsIF* owner;//!< Pointer to the owner
|
||||
MessageQueueIF* queueToUse;//!< Queue to be used as response sender, has to be set with
|
||||
StorageManagerIF* ipcStore;//!< Pointer to an IPC Store, initialized during construction or initialize(MessageQueueIF* queueToUse_) or with setQueueToUse(MessageQueueIF *queue)
|
||||
/**
|
||||
*Internal function called by handleActionMessage(CommandMessage* command)
|
||||
*
|
||||
* @param commandedBy MessageQueueID of Commander
|
||||
* @param actionId ID of action to be done
|
||||
* @param dataAddress Address of additional data in IPC Store
|
||||
*/
|
||||
virtual void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress);
|
||||
void resetHelper();
|
||||
/**
|
||||
*
|
||||
*/
|
||||
virtual void resetHelper();
|
||||
};
|
||||
|
||||
#endif /* ACTIONHELPER_H_ */
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <framework/objectmanager/ObjectManagerIF.h>
|
||||
|
||||
CommandActionHelper::CommandActionHelper(CommandsActionsIF* setOwner) :
|
||||
owner(setOwner), queueToUse(setOwner->getCommandQueuePtr()), ipcStore(
|
||||
owner(setOwner), queueToUse(NULL), ipcStore(
|
||||
NULL), commandCount(0), lastTarget(0) {
|
||||
}
|
||||
|
||||
@ -66,11 +66,15 @@ ReturnValue_t CommandActionHelper::sendCommand(MessageQueueId_t queueId,
|
||||
|
||||
ReturnValue_t CommandActionHelper::initialize() {
|
||||
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if (ipcStore != NULL) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
if (ipcStore == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
queueToUse = owner->getCommandQueuePtr();
|
||||
if(queueToUse == NULL){
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t CommandActionHelper::handleReply(CommandMessage* reply) {
|
||||
|
@ -6,14 +6,36 @@
|
||||
#include <framework/action/SimpleActionHelper.h>
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <framework/ipc/MessageQueueIF.h>
|
||||
/**
|
||||
* \brief Interface for component which uses actions
|
||||
*
|
||||
* This interface is used to execute actions in the component. Actions, in the sense of this interface, are activities with a well-defined beginning and
|
||||
* end in time. They may adjust sub-states of components, but are not supposed to change
|
||||
* the main mode of operation, which is handled with the HasModesIF described below.
|
||||
*
|
||||
* The HasActionsIF allows components to define such actions and make them available
|
||||
* for other components to use. Implementing the interface is straightforward: There’s a
|
||||
* single executeAction call, which provides an identifier for the action to execute, as well
|
||||
* as arbitrary parameters for input. Aside from direct, software-based
|
||||
* actions, it is used in device handler components as an interface to forward commands to
|
||||
* devices.
|
||||
* Implementing components of the interface are supposed to check identifier (ID) and
|
||||
* parameters and immediately start execution of the action. It is, however, not required to
|
||||
* immediately finish execution. Instead, this may be deferred to a later point in time, at
|
||||
* which the component needs to inform the caller about finished or failed execution.
|
||||
*/
|
||||
class HasActionsIF {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_ACTIONS_IF;
|
||||
static const ReturnValue_t IS_BUSY = MAKE_RETURN_CODE(1);
|
||||
static const ReturnValue_t IS_BUSY = MAKE_RETURN_CODE(1);//!<
|
||||
static const ReturnValue_t INVALID_PARAMETERS = MAKE_RETURN_CODE(2);
|
||||
static const ReturnValue_t EXECUTION_FINISHED = MAKE_RETURN_CODE(3);
|
||||
static const ReturnValue_t INVALID_ACTION_ID = MAKE_RETURN_CODE(4);
|
||||
virtual ~HasActionsIF() { }
|
||||
/**
|
||||
* Function to get the MessageQueueId_t of the implementing object
|
||||
* @return MessageQueueId_t of the object
|
||||
*/
|
||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||
/**
|
||||
* Execute or initialize the execution of a certain function.
|
||||
|
@ -10,9 +10,10 @@ public:
|
||||
void step(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
void finish(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
ReturnValue_t reportData(SerializeIF* data);
|
||||
void resetHelper();
|
||||
|
||||
protected:
|
||||
void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress);
|
||||
virtual void resetHelper();
|
||||
private:
|
||||
bool isExecuting;
|
||||
MessageQueueId_t lastCommander;
|
||||
|
@ -8,7 +8,7 @@ ControllerBase::ControllerBase(uint32_t setObjectId, uint32_t parentId,
|
||||
size_t commandQueueDepth) :
|
||||
SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF), submode(
|
||||
SUBMODE_NONE), commandQueue(NULL), modeHelper(
|
||||
this), healthHelper(this, setObjectId),hkSwitcher(this) {
|
||||
this), healthHelper(this, setObjectId),hkSwitcher(this),executingTask(NULL) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
|
||||
|
||||
}
|
||||
@ -129,6 +129,9 @@ ReturnValue_t ControllerBase::setHealth(HealthState health) {
|
||||
HasHealthIF::HealthState ControllerBase::getHealth() {
|
||||
return healthHelper.getHealth();
|
||||
}
|
||||
void ControllerBase::setTaskIF(PeriodicTaskIF* task_){
|
||||
executingTask = task_;
|
||||
}
|
||||
|
||||
void ControllerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
|
||||
}
|
||||
|
@ -32,6 +32,16 @@ public:
|
||||
virtual ReturnValue_t setHealth(HealthState health);
|
||||
|
||||
virtual HasHealthIF::HealthState getHealth();
|
||||
|
||||
/**
|
||||
* Implementation of ExecutableObjectIF function
|
||||
*
|
||||
* Used to setup the reference of the task, that executes this component
|
||||
* @param task_ Pointer to the taskIF of this task
|
||||
*/
|
||||
virtual void setTaskIF(PeriodicTaskIF* task_);
|
||||
|
||||
|
||||
protected:
|
||||
const uint32_t parentId;
|
||||
|
||||
@ -47,6 +57,11 @@ protected:
|
||||
|
||||
HkSwitchHelper hkSwitcher;
|
||||
|
||||
/**
|
||||
* Pointer to the task which executes this component, is invalid before setTaskIF was called.
|
||||
*/
|
||||
PeriodicTaskIF* executingTask;
|
||||
|
||||
void handleQueue();
|
||||
|
||||
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0;
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define COORDINATETRANSFORMATIONS_H_
|
||||
|
||||
#include <framework/timemanager/Clock.h>
|
||||
#include <cstring>
|
||||
|
||||
class CoordinateTransformations {
|
||||
public:
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
DataPoolAdmin::DataPoolAdmin(object_id_t objectId) :
|
||||
SystemObject(objectId), storage(NULL), commandQueue(NULL), memoryHelper(
|
||||
this, commandQueue), actionHelper(this, commandQueue) {
|
||||
this, NULL), actionHelper(this, NULL) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue();
|
||||
}
|
||||
|
||||
@ -171,7 +171,7 @@ ReturnValue_t DataPoolAdmin::initialize() {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = memoryHelper.initialize();
|
||||
result = memoryHelper.initialize(commandQueue);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
@ -181,7 +181,7 @@ ReturnValue_t DataPoolAdmin::initialize() {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
result = actionHelper.initialize();
|
||||
result = actionHelper.initialize(commandQueue);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -24,6 +24,8 @@ public:
|
||||
|
||||
ReturnValue_t switchHK(SerializeIF *sids, bool enable);
|
||||
|
||||
virtual void setTaskIF(PeriodicTaskIF* task_){};
|
||||
|
||||
protected:
|
||||
virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step);
|
||||
virtual void stepFailedReceived(ActionId_t actionId, uint8_t step,
|
||||
|
@ -76,13 +76,13 @@ ReturnValue_t PoolRawAccess::getEntryEndianSafe(uint8_t* buffer,
|
||||
return DATA_POOL_ACCESS_FAILED;
|
||||
if (typeSize > max_size)
|
||||
return INCORRECT_SIZE;
|
||||
#ifndef BYTE_ORDER
|
||||
#error BYTE_ORDER not defined
|
||||
#elif BYTE_ORDER == LITTLE_ENDIAN
|
||||
#ifndef BYTE_ORDER_SYSTEM
|
||||
#error BYTE_ORDER_SYSTEM not defined
|
||||
#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
|
||||
for (uint8_t count = 0; count < typeSize; count++) {
|
||||
buffer[count] = data_ptr[typeSize - count - 1];
|
||||
}
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
|
||||
memcpy(buffer, data_ptr, typeSize);
|
||||
#endif
|
||||
*writtenBytes = typeSize;
|
||||
@ -112,13 +112,13 @@ PoolVariableIF::ReadWriteMode_t PoolRawAccess::getReadWriteMode() const {
|
||||
ReturnValue_t PoolRawAccess::setEntryFromBigEndian(const uint8_t* buffer,
|
||||
uint32_t setSize) {
|
||||
if (typeSize == setSize) {
|
||||
#ifndef BYTE_ORDER
|
||||
#error BYTE_ORDER not defined
|
||||
#elif BYTE_ORDER == LITTLE_ENDIAN
|
||||
#ifndef BYTE_ORDER_SYSTEM
|
||||
#error BYTE_ORDER_SYSTEM not defined
|
||||
#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
|
||||
for (uint8_t count = 0; count < typeSize; count++) {
|
||||
value[count] = buffer[typeSize - count - 1];
|
||||
}
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
|
||||
memcpy(value, buffer, typeSize);
|
||||
#endif
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
@ -149,13 +149,13 @@ ReturnValue_t PoolRawAccess::serialize(uint8_t** buffer, uint32_t* size,
|
||||
const uint32_t max_size, bool bigEndian) const {
|
||||
if (typeSize + *size <= max_size) {
|
||||
if (bigEndian) {
|
||||
#ifndef BYTE_ORDER
|
||||
#error BYTE_ORDER not defined
|
||||
#elif BYTE_ORDER == LITTLE_ENDIAN
|
||||
#ifndef BYTE_ORDER_SYSTEM
|
||||
#error BYTE_ORDER_SYSTEM not defined
|
||||
#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
|
||||
for (uint8_t count = 0; count < typeSize; count++) {
|
||||
(*buffer)[count] = value[typeSize - count - 1];
|
||||
}
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
|
||||
memcpy(*buffer, value, typeSize);
|
||||
#endif
|
||||
} else {
|
||||
@ -179,13 +179,13 @@ ReturnValue_t PoolRawAccess::deSerialize(const uint8_t** buffer, int32_t* size,
|
||||
if (*size >= 0) {
|
||||
|
||||
if (bigEndian) {
|
||||
#ifndef BYTE_ORDER
|
||||
#error BYTE_ORDER not defined
|
||||
#elif BYTE_ORDER == LITTLE_ENDIAN
|
||||
#ifndef BYTE_ORDER_SYSTEM
|
||||
#error BYTE_ORDER_SYSTEM not defined
|
||||
#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
|
||||
for (uint8_t count = 0; count < typeSize; count++) {
|
||||
value[count] = (*buffer)[typeSize - count - 1];
|
||||
}
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
|
||||
memcpy(value, *buffer, typeSize);
|
||||
#endif
|
||||
} else {
|
||||
|
@ -30,19 +30,7 @@ DeviceHandlerBase::DeviceHandlerBase(uint32_t ioBoardAddress,
|
||||
thermalRequestPoolId), healthHelper(this, setObjectId), modeHelper(
|
||||
this), parameterHelper(this), childTransitionFailure(RETURN_OK), ignoreMissedRepliesCount(
|
||||
0), fdirInstance(fdirInstance), hkSwitcher(this), defaultFDIRUsed(
|
||||
fdirInstance == NULL), switchOffWasReported(false), executingTask(
|
||||
NULL), actionHelper(this, commandQueue), cookieInfo(), ioBoardAddress(
|
||||
//=======
|
||||
// NULL), IPCStore(NULL), deviceCommunicationId(deviceCommunication), communicationInterface(
|
||||
// NULL), cookie(
|
||||
// NULL), commandQueue(cmdQueueSize, CommandMessage::MAX_MESSAGE_SIZE), deviceThermalStatePoolId(
|
||||
// thermalStatePoolId), deviceThermalRequestPoolId(
|
||||
// thermalRequestPoolId), healthHelper(this, setObjectId), modeHelper(
|
||||
// this), parameterHelper(this), childTransitionFailure(RETURN_OK), ignoreMissedRepliesCount(
|
||||
// 0), fdirInstance(fdirInstance), defaultFDIRUsed(
|
||||
// fdirInstance == NULL), switchOffWasReported(false), actionHelper(
|
||||
// this, &commandQueue), cookieInfo(), ioBoardAddress(
|
||||
//>>>>>>> makefile
|
||||
fdirInstance == NULL), switchOffWasReported(false),executingTask(NULL), actionHelper(this, NULL), cookieInfo(), ioBoardAddress(
|
||||
ioBoardAddress), timeoutStart(0), childTransitionDelay(5000), transitionSourceMode(
|
||||
_MODE_POWER_DOWN), transitionSourceSubMode(SUBMODE_NONE), deviceSwitch(
|
||||
setDeviceSwitch) {
|
||||
@ -636,7 +624,7 @@ ReturnValue_t DeviceHandlerBase::initialize() {
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = actionHelper.initialize();
|
||||
result = actionHelper.initialize(commandQueue);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
@ -1021,10 +1009,6 @@ ReturnValue_t DeviceHandlerBase::acceptExternalDeviceCommands() {
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* interface) {
|
||||
executingTask = interface;
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::replyRawReplyIfnotWiretapped(const uint8_t* data,
|
||||
size_t len) {
|
||||
if ((wiretappingMode == RAW)
|
||||
@ -1281,3 +1265,7 @@ bool DeviceHandlerBase::commandIsExecuting(DeviceCommandId_t commandId) {
|
||||
|
||||
void DeviceHandlerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task_){
|
||||
executingTask = task_;
|
||||
}
|
||||
|
@ -92,8 +92,13 @@ public:
|
||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||
|
||||
void setTaskIF(PeriodicTaskIF* interface);
|
||||
/**
|
||||
* Implementation of ExecutableObjectIF function
|
||||
*
|
||||
* Used to setup the reference of the task, that executes this component
|
||||
* @param task_ Pointer to the taskIF of this task
|
||||
*/
|
||||
virtual void setTaskIF(PeriodicTaskIF* task_);
|
||||
protected:
|
||||
/**
|
||||
* The Returnvalues id of this class, required by HasReturnvaluesIF
|
||||
@ -248,13 +253,13 @@ protected:
|
||||
|
||||
bool switchOffWasReported; //!< Indicates if SWITCH_WENT_OFF was already thrown.
|
||||
|
||||
PeriodicTaskIF* executingTask;//!< Pointer to the task which executes this component, is invalid before setTaskIF was called.
|
||||
|
||||
static object_id_t powerSwitcherId; //!< Object which switches power on and off.
|
||||
|
||||
static object_id_t rawDataReceiverId; //!< Object which receives RAW data by default.
|
||||
|
||||
static object_id_t defaultFDIRParentId; //!< Object which may be the root cause of an identified fault.
|
||||
|
||||
PeriodicTaskIF* executingTask;
|
||||
/**
|
||||
* Helper function to report a missed reply
|
||||
*
|
||||
@ -787,7 +792,6 @@ protected:
|
||||
DeviceCommandMap deviceCommandMap;
|
||||
|
||||
ActionHelper actionHelper;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
|
@ -17,7 +17,6 @@ FixedSlotSequence::~FixedSlotSequence() {
|
||||
}
|
||||
|
||||
void FixedSlotSequence::executeAndAdvance() {
|
||||
// (*this->current)->print();
|
||||
(*this->current)->handler->performOperation((*this->current)->opcode);
|
||||
// if (returnValue != RETURN_OK) {
|
||||
// this->sendErrorMessage( returnValue );
|
||||
|
@ -34,7 +34,6 @@ public:
|
||||
object_id_t reporterFrom = 0, object_id_t reporterTo = 0,
|
||||
bool reporterInverted = false);
|
||||
ReturnValue_t performOperation(uint8_t opCode);
|
||||
|
||||
protected:
|
||||
|
||||
MessageQueueIF* eventReportQueue;
|
||||
|
@ -39,10 +39,7 @@ endif
|
||||
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/parameters/*.cpp)
|
||||
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/power/*.cpp)
|
||||
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/returnvalues/*.cpp)
|
||||
|
||||
# easier without it for now
|
||||
#CXXSRC += $(wildcard $(FRAMEWORK_PATH)/rmap/*.cpp)
|
||||
|
||||
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/rmap/*.cpp)
|
||||
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/serialize/*.cpp)
|
||||
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/serviceinterface/*.cpp)
|
||||
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/storagemanager/*.cpp)
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include <framework/globalfunctions/conversion.h>
|
||||
//TODO REMOVE. Needed because of BYTE_ORDER
|
||||
#include <framework/osal/Endiness.h>
|
||||
#include <cstring>
|
||||
|
||||
@ -59,9 +58,9 @@ void convertToByteStream( int32_t value, uint8_t* buffer, uint32_t* size ) {
|
||||
//}
|
||||
|
||||
void convertToByteStream( float in_value, uint8_t* buffer, uint32_t* size ) {
|
||||
#ifndef BYTE_ORDER
|
||||
#error BYTE_ORDER not defined
|
||||
#elif BYTE_ORDER == LITTLE_ENDIAN
|
||||
#ifndef BYTE_ORDER_SYSTEM
|
||||
#error BYTE_ORDER_SYSTEM not defined
|
||||
#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
|
||||
union float_union {
|
||||
float value;
|
||||
uint8_t chars[4];
|
||||
@ -73,16 +72,16 @@ void convertToByteStream( float in_value, uint8_t* buffer, uint32_t* size ) {
|
||||
buffer[2] = temp.chars[1];
|
||||
buffer[3] = temp.chars[0];
|
||||
*size += 4;
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
|
||||
memcpy(buffer, &in_value, sizeof(in_value));
|
||||
*size += sizeof(in_value);
|
||||
#endif
|
||||
}
|
||||
|
||||
void convertToByteStream( double in_value, uint8_t* buffer, uint32_t* size ) {
|
||||
#ifndef BYTE_ORDER
|
||||
#error Endianess not defined
|
||||
#elif BYTE_ORDER == LITTLE_ENDIAN
|
||||
#ifndef BYTE_ORDER_SYSTEM
|
||||
#error BYTE_ORDER_SYSTEM not defined
|
||||
#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
|
||||
union double_union {
|
||||
double value;
|
||||
uint8_t chars[8];
|
||||
@ -98,7 +97,7 @@ void convertToByteStream( double in_value, uint8_t* buffer, uint32_t* size ) {
|
||||
buffer[6] = temp.chars[1];
|
||||
buffer[7] = temp.chars[0];
|
||||
*size += 8;
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
|
||||
memcpy(buffer, &in_value, sizeof(in_value));
|
||||
*size += sizeof(in_value);
|
||||
#endif
|
||||
|
@ -22,7 +22,6 @@ public:
|
||||
virtual void lostTm();
|
||||
|
||||
virtual void storeFull();
|
||||
|
||||
protected:
|
||||
MutexIF* mutex;
|
||||
|
||||
|
@ -5,11 +5,22 @@
|
||||
|
||||
#include <framework/ipc/MessageQueueMessage.h>
|
||||
#include <framework/ipc/MessageQueueSenderIF.h>
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
class MessageQueueIF {
|
||||
public:
|
||||
|
||||
static const MessageQueueId_t NO_QUEUE = MessageQueueSenderIF::NO_QUEUE; //!< Ugly hack.
|
||||
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::MESSAGE_QUEUE_IF;
|
||||
/**
|
||||
* No new messages on the queue
|
||||
*/
|
||||
static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(1);
|
||||
/**
|
||||
* No space left for more messages
|
||||
*/
|
||||
static const ReturnValue_t FULL = MAKE_RETURN_CODE(2);
|
||||
|
||||
virtual ~MessageQueueIF() {}
|
||||
/**
|
||||
* @brief This operation sends a message to the last communication partner.
|
||||
@ -65,16 +76,32 @@ public:
|
||||
* This variable is set to zero by default.
|
||||
* \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full (if implemented).
|
||||
*/
|
||||
virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ) = 0;
|
||||
virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0;
|
||||
/**
|
||||
* @brief This operation sends a message to the given destination.
|
||||
* @details It directly uses the sendMessage call of the MessageQueueSender parent, but passes its
|
||||
* queue id as "sentFrom" parameter.
|
||||
* @param sendTo This parameter specifies the message queue id of the destination message queue.
|
||||
* @param message A pointer to a previously created message, which is sent.
|
||||
* @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
|
||||
*/
|
||||
virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo, MessageQueueMessage* message, bool ignoreFault = false ) = 0;
|
||||
|
||||
/**
|
||||
* \brief The sendToDefault method sends a queue message to the default destination.
|
||||
* \brief The sendToDefaultFrom method sends a queue message to the default destination.
|
||||
* \details In all other aspects, it works identical to the sendMessage method.
|
||||
* \param message This is a pointer to a previously created message, which is sent.
|
||||
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
|
||||
* This variable is set to zero by default.
|
||||
*/
|
||||
virtual ReturnValue_t sendToDefault( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ) = 0;
|
||||
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0;
|
||||
/**
|
||||
* @brief This operation sends a message to the default destination.
|
||||
* @details As in the sendMessage method, this function uses the sendToDefault call of the
|
||||
* Implementation class and adds its queue id as "sentFrom" information.
|
||||
* @param message A pointer to a previously created message, which is sent.
|
||||
*/
|
||||
virtual ReturnValue_t sendToDefault( MessageQueueMessage* message ) = 0;
|
||||
/**
|
||||
* \brief This method is a simple setter for the default destination.
|
||||
*/
|
||||
|
24
ipc/MutexHelper.h
Normal file
24
ipc/MutexHelper.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef FRAMEWORK_IPC_MUTEXHELPER_H_
|
||||
#define FRAMEWORK_IPC_MUTEXHELPER_H_
|
||||
|
||||
#include <framework/ipc/MutexFactory.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
|
||||
class MutexHelper {
|
||||
public:
|
||||
MutexHelper(MutexIF* mutex, uint32_t timeoutMs) :
|
||||
internalMutex(mutex) {
|
||||
ReturnValue_t status = mutex->lockMutex(timeoutMs);
|
||||
if(status != HasReturnvaluesIF::RETURN_OK){
|
||||
error << "MutexHelper: Lock of Mutex failed " << status << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
~MutexHelper() {
|
||||
internalMutex->unlockMutex();
|
||||
}
|
||||
private:
|
||||
MutexIF* internalMutex;
|
||||
};
|
||||
#endif /* FRAMEWORK_IPC_MUTEXHELPER_H_ */
|
@ -6,6 +6,57 @@
|
||||
class MutexIF {
|
||||
public:
|
||||
static const uint32_t NO_TIMEOUT; //!< Needs to be defined in implementation.
|
||||
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::MUTEX_IF;
|
||||
/**
|
||||
* The system lacked the necessary resources (other than memory) to initialize another mutex.
|
||||
*/
|
||||
static const ReturnValue_t NOT_ENOUGH_RESOURCES = MAKE_RETURN_CODE(1);
|
||||
/**
|
||||
* Insufficient memory to create or init Mutex
|
||||
*/
|
||||
static const ReturnValue_t INSUFFICIENT_MEMORY = MAKE_RETURN_CODE(2);
|
||||
/**
|
||||
* Caller does not have enough or right privilege
|
||||
*/
|
||||
static const ReturnValue_t NO_PRIVILEGE = MAKE_RETURN_CODE(3);
|
||||
/**
|
||||
* Wrong Attribute Setting
|
||||
*/
|
||||
static const ReturnValue_t WRONG_ATTRIBUTE_SETTING = MAKE_RETURN_CODE(4);
|
||||
/**
|
||||
* The mutex is already locked
|
||||
*/
|
||||
static const ReturnValue_t MUTEX_ALREADY_LOCKED = MAKE_RETURN_CODE(5);
|
||||
/**
|
||||
* Mutex object not found
|
||||
*/
|
||||
static const ReturnValue_t MUTEX_NOT_FOUND = MAKE_RETURN_CODE(6);
|
||||
/**
|
||||
* Mutex could not be locked because max amount of recursive locks
|
||||
*/
|
||||
static const ReturnValue_t MUTEX_MAX_LOCKS = MAKE_RETURN_CODE(7);
|
||||
/**
|
||||
* The current thread already owns this mutex
|
||||
*/
|
||||
static const ReturnValue_t CURR_THREAD_ALREADY_OWNS_MUTEX = MAKE_RETURN_CODE(8);
|
||||
/**
|
||||
* Current thread does not own this mutex
|
||||
*/
|
||||
static const ReturnValue_t CURR_THREAD_DOES_NOT_OWN_MUTEX = MAKE_RETURN_CODE(9);
|
||||
/**
|
||||
* The Mutex could not be blocked before timeout
|
||||
*/
|
||||
static const ReturnValue_t MUTEX_TIMEOUT = MAKE_RETURN_CODE(10);
|
||||
/**
|
||||
* Invalid Mutex ID
|
||||
*/
|
||||
static const ReturnValue_t MUTEX_INVALID_ID = MAKE_RETURN_CODE(11);
|
||||
/**
|
||||
* Mutex destroyed while waiting
|
||||
*/
|
||||
static const ReturnValue_t MUTEX_DESTROYED_WHILE_WAITING = MAKE_RETURN_CODE(12);
|
||||
|
||||
virtual ~MutexIF() {}
|
||||
virtual ReturnValue_t lockMutex(uint32_t timeoutMs) = 0;
|
||||
virtual ReturnValue_t unlockMutex() = 0;
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
LocalMemory::LocalMemory(object_id_t setObjectId) :
|
||||
SystemObject(setObjectId), commandQueue(NULL), memoryHelper(this,
|
||||
commandQueue) {
|
||||
NULL) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue();
|
||||
}
|
||||
|
||||
@ -52,7 +52,7 @@ ReturnValue_t LocalMemory::handleMemoryDump(uint32_t address, uint32_t size,
|
||||
}
|
||||
|
||||
ReturnValue_t LocalMemory::initialize() {
|
||||
return memoryHelper.initialize();
|
||||
return memoryHelper.initialize(commandQueue);
|
||||
}
|
||||
|
||||
MessageQueueId_t LocalMemory::getCommandQueue() const {
|
||||
|
@ -183,3 +183,13 @@ void MemoryHelper::handleMemoryCheckOrDump(CommandMessage* message) {
|
||||
queueToUse->sendMessage(lastSender, &reply);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t MemoryHelper::initialize(MessageQueueIF* queueToUse_) {
|
||||
if(queueToUse_!=NULL){
|
||||
this->queueToUse = queueToUse_;
|
||||
}else{
|
||||
return MessageQueueIF::NO_QUEUE;
|
||||
}
|
||||
|
||||
return initialize();
|
||||
}
|
||||
|
@ -24,12 +24,13 @@ private:
|
||||
bool busy;
|
||||
void handleMemoryLoad(CommandMessage* message);
|
||||
void handleMemoryCheckOrDump(CommandMessage* message);
|
||||
ReturnValue_t initialize();
|
||||
public:
|
||||
ReturnValue_t handleMemoryCommand(CommandMessage* message);
|
||||
void completeLoad( ReturnValue_t errorCode, const uint8_t* dataToCopy = NULL, const uint32_t size = 0, uint8_t* copyHere = NULL );
|
||||
void completeDump( ReturnValue_t errorCode, const uint8_t* dataToCopy = NULL, const uint32_t size = 0);
|
||||
void swapMatrixCopy( uint8_t *out, const uint8_t *in, uint32_t totalSize, uint8_t datatypeSize);
|
||||
ReturnValue_t initialize();
|
||||
ReturnValue_t initialize(MessageQueueIF* queueToUse_);
|
||||
MemoryHelper( HasMemoryIF* workOnThis, MessageQueueIF* useThisQueue );
|
||||
~MemoryHelper();
|
||||
};
|
||||
|
@ -19,11 +19,11 @@ public:
|
||||
}
|
||||
ReturnValue_t doCheck(T lowSample, T highSample) {
|
||||
T crossedLimit;
|
||||
ReturnValue_t currentState = checkSample(lowSample, &crossedLimit);
|
||||
ReturnValue_t currentState = this->checkSample(lowSample, &crossedLimit);
|
||||
if (currentState != HasReturnvaluesIF::RETURN_OK) {
|
||||
return this->monitorStateIs(currentState, lowSample, crossedLimit);
|
||||
}
|
||||
currentState = checkSample(highSample, &crossedLimit);
|
||||
currentState = this->checkSample(highSample, &crossedLimit);
|
||||
return this->monitorStateIs(currentState, highSample, crossedLimit);
|
||||
}
|
||||
protected:
|
||||
|
@ -12,16 +12,19 @@
|
||||
#define LITTLE_ENDIAN 1234
|
||||
#endif
|
||||
|
||||
|
||||
// This is a GCC C extension
|
||||
#ifndef BYTE_ORDER
|
||||
#ifndef BYTE_ORDER_SYSTEM
|
||||
#ifdef __BYTE_ORDER__
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define BYTE_ORDER BIG_ENDIAN
|
||||
#define BYTE_ORDER_SYSTEM LITTLE_ENDIAN
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
#define BYTE_ORDER_SYSTEM BIG_ENDIAN
|
||||
#else
|
||||
#error "Can't decide which end is which!"
|
||||
#endif
|
||||
#else
|
||||
#error __BYTE_ORDER__ not defined
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -21,16 +21,16 @@ MessageQueue::~MessageQueue() {
|
||||
|
||||
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
|
||||
MessageQueueMessage* message, bool ignoreFault) {
|
||||
return sendMessage(sendTo, message, this->getId(), ignoreFault);
|
||||
return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message) {
|
||||
return sendToDefault(message, this->getId());
|
||||
return sendToDefaultFrom(message, this->getId());
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) {
|
||||
if (this->lastPartner != 0) {
|
||||
return sendMessage(this->lastPartner, message, this->getId());
|
||||
return sendMessageFrom(this->lastPartner, message, this->getId());
|
||||
} else {
|
||||
//TODO: Good returnCode
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
@ -49,8 +49,7 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) {
|
||||
if (result == pdPASS){
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
//TODO Queue Empty
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return MessageQueueIF::EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +72,7 @@ void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
|
||||
this->defaultDestination = defaultDestination;
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
|
||||
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
|
||||
MessageQueueMessage* message, MessageQueueId_t sentFrom,
|
||||
bool ignoreFault) {
|
||||
message->setSender(sentFrom);
|
||||
@ -83,15 +82,14 @@ ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
|
||||
if (!ignoreFault) {
|
||||
//TODO errr reporter
|
||||
}
|
||||
//TODO queue is full
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return MessageQueueIF::FULL;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message,
|
||||
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessage* message,
|
||||
MessageQueueId_t sentFrom, bool ignoreFault) {
|
||||
return 0;
|
||||
return sendMessageFrom(defaultDestination,message,sentFrom,ignoreFault);
|
||||
}
|
||||
|
||||
MessageQueueId_t MessageQueue::getDefaultDestination() const {
|
||||
|
@ -117,7 +117,7 @@ public:
|
||||
* This variable is set to zero by default.
|
||||
* \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
|
||||
*/
|
||||
virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
|
||||
virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
|
||||
/**
|
||||
* \brief The sendToDefault method sends a queue message to the default destination.
|
||||
* \details In all other aspects, it works identical to the sendMessage method.
|
||||
@ -125,7 +125,7 @@ public:
|
||||
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
|
||||
* This variable is set to zero by default.
|
||||
*/
|
||||
virtual ReturnValue_t sendToDefault( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
|
||||
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
|
||||
/**
|
||||
* \brief This method is a simple setter for the default destination.
|
||||
*/
|
||||
|
@ -1,31 +1,32 @@
|
||||
//entry point into "bsp"
|
||||
void init(void);
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <FreeRTOSConfig.h>
|
||||
#include "task.h"
|
||||
|
||||
|
||||
void initTask(void *parameters) {
|
||||
init();
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
|
||||
if ( pdPASS
|
||||
!= xTaskCreate(initTask, "init", 512, NULL,
|
||||
configMAX_PRIORITIES - 1, NULL)) {
|
||||
//print_uart0("Could not create task1\r\n");
|
||||
}
|
||||
|
||||
vTaskStartScheduler();
|
||||
|
||||
//Scheduler should never return
|
||||
|
||||
//print_uart0("This is bad\n");
|
||||
|
||||
for (;;)
|
||||
;
|
||||
|
||||
return 0;
|
||||
}
|
||||
//TODO This can be done mission dependent and some low level calls before vTaskStartScheduler might be important
|
||||
//void init(void);
|
||||
//
|
||||
//#include <FreeRTOS.h>
|
||||
//#include <FreeRTOSConfig.h>
|
||||
//#include "task.h"
|
||||
//
|
||||
//
|
||||
//void initTask(void *parameters) {
|
||||
// init();
|
||||
//}
|
||||
//
|
||||
//int main(void) {
|
||||
//
|
||||
// if ( pdPASS
|
||||
// != xTaskCreate(initTask, "init", 512, NULL,
|
||||
// configMAX_PRIORITIES - 1, NULL)) {
|
||||
// //print_uart0("Could not create task1\r\n");
|
||||
// }
|
||||
//
|
||||
// vTaskStartScheduler();
|
||||
//
|
||||
// //Scheduler should never return
|
||||
//
|
||||
// //print_uart0("This is bad\n");
|
||||
//
|
||||
// for (;;)
|
||||
// ;
|
||||
//
|
||||
// return 0;
|
||||
//}
|
||||
|
@ -1,144 +0,0 @@
|
||||
#ifndef FRAMEWORK_OSAL_OPERATINGSYSTEMIF_H_
|
||||
#define FRAMEWORK_OSAL_OPERATINGSYSTEMIF_H_
|
||||
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
|
||||
class OperatingSystemIF {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::OPERATING_SYSTEM_ABSTRACTION;
|
||||
|
||||
//API Status codes, must be implemented by the Operating System (TODO comments based on rtems status.h):
|
||||
|
||||
/**
|
||||
* This is the status to indicate successful completion.
|
||||
*/
|
||||
static const ReturnValue_t SUCCESSFUL = MAKE_RETURN_CODE(0);
|
||||
/**
|
||||
* This is the status to indicate that a thread exited.
|
||||
*/
|
||||
static const ReturnValue_t TASK_EXITTED = MAKE_RETURN_CODE(1);
|
||||
/**
|
||||
* This is the status to indicate multiprocessing is not configured.
|
||||
*/
|
||||
static const ReturnValue_t MP_NOT_CONFIGURED = MAKE_RETURN_CODE(2);
|
||||
/**
|
||||
* This is the status to indicate that the object name was invalid.
|
||||
*/
|
||||
static const ReturnValue_t INVALID_NAME = MAKE_RETURN_CODE(3);
|
||||
/**
|
||||
* This is the status to indicate that the object Id was invalid.
|
||||
*/
|
||||
static const ReturnValue_t INVALID_ID = MAKE_RETURN_CODE(4);
|
||||
/**
|
||||
* This is the status to indicate you have attempted to create too many
|
||||
* instances of a particular object class.
|
||||
*
|
||||
* Used for full messages Queues as well
|
||||
*/
|
||||
static const ReturnValue_t TOO_MANY = MAKE_RETURN_CODE(5);
|
||||
/**
|
||||
* This is the status to indicate that a blocking directive timed out.
|
||||
*/
|
||||
static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(6);
|
||||
/**
|
||||
* This is the status to indicate the the object was deleted
|
||||
* while the task was blocked waiting.
|
||||
*/
|
||||
static const ReturnValue_t OBJECT_WAS_DELETED = MAKE_RETURN_CODE(7);
|
||||
/**
|
||||
* This is the status to indicate that the specified size was invalid.
|
||||
*/
|
||||
static const ReturnValue_t INVALID_SIZE = MAKE_RETURN_CODE(8);
|
||||
/**
|
||||
* This is the status to indicate that the specified address is invalid.
|
||||
*/
|
||||
static const ReturnValue_t INVALID_ADDRESS = MAKE_RETURN_CODE(9);
|
||||
/**
|
||||
* This is the status to indicate that the specified number was invalid.
|
||||
*/
|
||||
static const ReturnValue_t INVALID_NUMBER = MAKE_RETURN_CODE(10);
|
||||
/**
|
||||
* This is the status to indicate that the item has not been initialized.
|
||||
*/
|
||||
static const ReturnValue_t NOT_DEFINED =MAKE_RETURN_CODE(11);
|
||||
/**
|
||||
* This is the status to indicate that the object still has
|
||||
* resources in use.
|
||||
*/
|
||||
static const ReturnValue_t RESOURCE_IN_USE =MAKE_RETURN_CODE(12);
|
||||
/**
|
||||
* This is the status to indicate that the request was not satisfied.
|
||||
*/
|
||||
static const ReturnValue_t UNSATISFIED =MAKE_RETURN_CODE(13);
|
||||
/**
|
||||
* Indicates that a Message Queue is empty (unable to allocate it)
|
||||
*/
|
||||
static const ReturnValue_t QUEUE_EMPTY =MAKE_RETURN_CODE(14);
|
||||
/**
|
||||
* This is the status to indicate that a thread is in wrong state
|
||||
* was in the wrong execution state for the requested operation.
|
||||
*/
|
||||
static const ReturnValue_t INCORRECT_STATE =MAKE_RETURN_CODE(15);
|
||||
/**
|
||||
* This is the status to indicate thread was already suspended.
|
||||
*/
|
||||
static const ReturnValue_t ALREADY_SUSPENDED = MAKE_RETURN_CODE(16);
|
||||
/**
|
||||
* This is the status to indicate that the operation is illegal
|
||||
* on calling thread.
|
||||
*/
|
||||
static const ReturnValue_t ILLEGAL_ON_SELF =MAKE_RETURN_CODE(17);
|
||||
/**
|
||||
* This is the status to indicate illegal for remote object.
|
||||
*/
|
||||
static const ReturnValue_t ILLEGAL_ON_REMOTE_OBJECT=MAKE_RETURN_CODE(18);
|
||||
/**
|
||||
* This is the status to indicate that the operation should not be
|
||||
* called from from this excecution environment.
|
||||
*/
|
||||
static const ReturnValue_t CALLED_FROM_ISR=MAKE_RETURN_CODE(19);
|
||||
/**
|
||||
* This is the status to indicate that an invalid thread priority
|
||||
* was provided.
|
||||
*/
|
||||
static const ReturnValue_t INVALID_PRIORITY=MAKE_RETURN_CODE(20);
|
||||
/**
|
||||
* This is the status to indicate that the specified date/time was invalid.
|
||||
*/
|
||||
static const ReturnValue_t INVALID_CLOCK=MAKE_RETURN_CODE(21);
|
||||
/**
|
||||
* This is the status to indicate that the specified node Id was invalid.
|
||||
*/
|
||||
static const ReturnValue_t INVALID_NODE=MAKE_RETURN_CODE(22);
|
||||
/**
|
||||
* This is the status to indicate that the directive was not configured.
|
||||
*/
|
||||
static const ReturnValue_t NOT_CONFIGURED=MAKE_RETURN_CODE(23);
|
||||
/**
|
||||
* This is the status to indicate that the caller is not the
|
||||
* owner of the resource.
|
||||
*/
|
||||
static const ReturnValue_t NOT_OWNER_OF_RESOURCE=MAKE_RETURN_CODE(24);
|
||||
/**
|
||||
* This is the status to indicate the the directive or requested
|
||||
* portion of the directive is not implemented.
|
||||
*/
|
||||
static const ReturnValue_t NOT_IMPLEMENTED=MAKE_RETURN_CODE(25);
|
||||
/**
|
||||
* This is the status to indicate that an internal RTEMS inconsistency
|
||||
* was detected.
|
||||
*/
|
||||
static const ReturnValue_t INTERNAL_ERROR=MAKE_RETURN_CODE(26);
|
||||
/**
|
||||
* This is the status to indicate that the directive attempted to allocate
|
||||
* memory but was unable to do so.
|
||||
*/
|
||||
static const ReturnValue_t NO_MEMORY=MAKE_RETURN_CODE(27);
|
||||
/**
|
||||
* This is the status to indicate an driver IO error.
|
||||
*/
|
||||
static const ReturnValue_t IO_ERROR=MAKE_RETURN_CODE(28);
|
||||
|
||||
virtual ~OperatingSystemIF() {};
|
||||
};
|
||||
#endif /* FRAMEWORK_OSAL_OPERATINGSYSTEMIF_H_ */
|
@ -8,25 +8,21 @@
|
||||
#include <unistd.h>
|
||||
|
||||
//#include <fstream>
|
||||
|
||||
uint16_t Clock::leapSeconds = 0;
|
||||
MutexIF* Clock::timeMutex = NULL;
|
||||
|
||||
uint32_t Clock::getTicksPerSecond(void){
|
||||
//TODO This function returns the ticks per second for thread ticks not clock ticks
|
||||
// timespec ticks;
|
||||
// int status = clock_getres(CLOCK_REALTIME,&ticks);
|
||||
//
|
||||
// if(status!=0){
|
||||
// //TODO errno
|
||||
// return 0xFFFFFFFF;
|
||||
// }
|
||||
// uint32_t resolution = 1e9 / ticks.tv_nsec;
|
||||
uint32_t resolution = sysconf(_SC_CLK_TCK);
|
||||
return resolution;
|
||||
uint32_t ticks = sysconf(_SC_CLK_TCK);
|
||||
return ticks;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
|
||||
//TODO timeOfDay conversion
|
||||
timespec timeUnix;
|
||||
timeval timeTimeval;
|
||||
convertTimeOfDayToTimeval(time,&timeTimeval);
|
||||
timeUnix.tv_sec = timeTimeval.tv_sec;
|
||||
timeUnix.tv_nsec = (__syscall_slong_t) timeTimeval.tv_usec * 1000;
|
||||
|
||||
int status = clock_settime(CLOCK_REALTIME,&timeUnix);
|
||||
if(status!=0){
|
||||
//TODO errno
|
||||
@ -109,14 +105,6 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
||||
//TODO errno
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
timespec ticks;
|
||||
status = clock_getres(CLOCK_REALTIME,&ticks);
|
||||
if(status!=0){
|
||||
//TODO errno
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
uint32_t resolution = 1e9 / ticks.tv_nsec;
|
||||
|
||||
|
||||
struct tm* timeInfo;
|
||||
timeInfo = gmtime(&timeUnix.tv_sec);
|
||||
@ -126,7 +114,7 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
||||
time->hour = timeInfo->tm_hour;
|
||||
time->minute = timeInfo->tm_min;
|
||||
time->second = timeInfo->tm_sec;
|
||||
time->ticks = (timeUnix.tv_nsec / (double) 1e9) * resolution;
|
||||
time->usecond = timeUnix.tv_nsec / 1000.0;
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
@ -143,34 +131,81 @@ ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from,
|
||||
fromTm.tm_min = from->minute;
|
||||
fromTm.tm_sec = from->second;
|
||||
|
||||
timespec ticks;
|
||||
uint32_t status = clock_getres(CLOCK_REALTIME,&ticks);
|
||||
if(status!=0){
|
||||
//TODO errno
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
uint32_t resolution = 1e9 / ticks.tv_nsec;
|
||||
|
||||
to->tv_sec = mktime(&fromTm);
|
||||
to->tv_usec = (from->ticks /(double) resolution) * 1e6;
|
||||
|
||||
|
||||
|
||||
to->tv_usec = from->usecond;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24.
|
||||
/ 3600.;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) {
|
||||
//SHOULDDO: works not for dates in the past (might have less leap seconds)
|
||||
if (timeMutex == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
uint16_t leapSeconds;
|
||||
ReturnValue_t result = getLeapSeconds(&leapSeconds);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
timeval leapSeconds_timeval = { 0, 0 };
|
||||
leapSeconds_timeval.tv_sec = leapSeconds;
|
||||
|
||||
//initial offset between UTC and TAI
|
||||
timeval UTCtoTAI1972 = { 10, 0 };
|
||||
|
||||
timeval TAItoTT = { 32, 184000 };
|
||||
|
||||
*tt = utc + leapSeconds_timeval + UTCtoTAI1972 + TAItoTT;
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) {
|
||||
if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
ReturnValue_t result = timeMutex->lockMutex(MutexIF::NO_TIMEOUT);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
leapSeconds = leapSeconds_;
|
||||
|
||||
result = timeMutex->unlockMutex();
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
|
||||
if(timeMutex==NULL){
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
ReturnValue_t result = timeMutex->lockMutex(MutexIF::NO_TIMEOUT);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
*leapSeconds_ = leapSeconds;
|
||||
|
||||
result = timeMutex->unlockMutex();
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::checkOrCreateClockMutex(){
|
||||
if(timeMutex==NULL){
|
||||
MutexFactory* mutexFactory = MutexFactory::instance();
|
||||
if (mutexFactory == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
timeMutex = mutexFactory->createMutex();
|
||||
if (timeMutex == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
89
osal/linux/FixedTimeslotTask.cpp
Normal file
89
osal/linux/FixedTimeslotTask.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <framework/osal/linux/FixedTimeslotTask.h>
|
||||
|
||||
|
||||
uint32_t FixedTimeslotTask::deadlineMissedCount = 0;
|
||||
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = PTHREAD_STACK_MIN;
|
||||
|
||||
FixedTimeslotTask::FixedTimeslotTask(const char* name_, int priority_, size_t stackSize_, uint32_t periodMs_):PosixThread(name_,priority_,stackSize_),pst(periodMs_),started(false) {
|
||||
}
|
||||
|
||||
FixedTimeslotTask::~FixedTimeslotTask() {
|
||||
|
||||
}
|
||||
|
||||
void* FixedTimeslotTask::taskEntryPoint(void* arg) {
|
||||
//The argument is re-interpreted as PollingTask.
|
||||
FixedTimeslotTask *originalTask(reinterpret_cast<FixedTimeslotTask*>(arg));
|
||||
//The task's functionality is called.
|
||||
originalTask->taskFunctionality();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ReturnValue_t FixedTimeslotTask::startTask() {
|
||||
started = true;
|
||||
createTask(&taskEntryPoint,this);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) {
|
||||
return PosixThread::sleep((uint64_t)ms*1000000);
|
||||
}
|
||||
|
||||
uint32_t FixedTimeslotTask::getPeriodMs() const {
|
||||
return pst.getLengthMs();
|
||||
}
|
||||
|
||||
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId,
|
||||
uint32_t slotTimeMs, int8_t executionStep) {
|
||||
pst.addSlot(componentId, slotTimeMs, executionStep, this);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FixedTimeslotTask::checkSequence() const {
|
||||
return pst.checkSequence();
|
||||
}
|
||||
|
||||
void FixedTimeslotTask::taskFunctionality() {
|
||||
//Like FreeRTOS pthreads are running as soon as they are created
|
||||
if (!started) {
|
||||
suspend();
|
||||
}
|
||||
// A local iterator for the Polling Sequence Table is created to find the start time for the first entry.
|
||||
std::list<FixedSequenceSlot*>::iterator it = pst.current;
|
||||
|
||||
//The start time for the first entry is read.
|
||||
uint64_t lastWakeTime = getCurrentMonotonicTimeMs();
|
||||
uint64_t interval = pst.getIntervalToNextSlotMs();
|
||||
|
||||
|
||||
//The task's "infinite" inner loop is entered.
|
||||
while (1) {
|
||||
if (pst.slotFollowsImmediately()) {
|
||||
//Do nothing
|
||||
} else {
|
||||
//The interval for the next polling slot is selected.
|
||||
interval = this->pst.getIntervalToPreviousSlotMs();
|
||||
//The period is checked and restarted with the new interval.
|
||||
//If the deadline was missed, the deadlineMissedFunc is called.
|
||||
if(!PosixThread::delayUntil(&lastWakeTime,interval)) {
|
||||
//No time left on timer -> we missed the deadline
|
||||
missedDeadlineCounter();
|
||||
}
|
||||
}
|
||||
//The device handler for this slot is executed and the next one is chosen.
|
||||
this->pst.executeAndAdvance();
|
||||
}
|
||||
}
|
||||
|
||||
void FixedTimeslotTask::missedDeadlineCounter() {
|
||||
FixedTimeslotTask::deadlineMissedCount++;
|
||||
if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) {
|
||||
error << "PST missed " << FixedTimeslotTask::deadlineMissedCount
|
||||
<< " deadlines." << std::endl;
|
||||
}
|
||||
}
|
58
osal/linux/FixedTimeslotTask.h
Normal file
58
osal/linux/FixedTimeslotTask.h
Normal file
@ -0,0 +1,58 @@
|
||||
#ifndef FRAMEWORK_OSAL_LINUX_FIXEDTIMESLOTTASK_H_
|
||||
#define FRAMEWORK_OSAL_LINUX_FIXEDTIMESLOTTASK_H_
|
||||
|
||||
#include <framework/tasks/FixedTimeslotTaskIF.h>
|
||||
#include <framework/devicehandlers/FixedSlotSequence.h>
|
||||
#include <framework/osal/linux/PosixThread.h>
|
||||
#include <pthread.h>
|
||||
|
||||
class FixedTimeslotTask: public FixedTimeslotTaskIF, public PosixThread {
|
||||
public:
|
||||
FixedTimeslotTask(const char* name_, int priority_, size_t stackSize_, uint32_t periodMs_);
|
||||
virtual ~FixedTimeslotTask();
|
||||
|
||||
virtual ReturnValue_t startTask();
|
||||
|
||||
virtual ReturnValue_t sleepFor(uint32_t ms);
|
||||
|
||||
virtual uint32_t getPeriodMs() const;
|
||||
|
||||
virtual ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep);
|
||||
virtual ReturnValue_t checkSequence() const;
|
||||
|
||||
/**
|
||||
* This static function can be used as #deadlineMissedFunc.
|
||||
* It counts missedDeadlines and prints the number of missed deadlines every 10th time.
|
||||
*/
|
||||
static void missedDeadlineCounter();
|
||||
|
||||
/**
|
||||
* A helper variable to count missed deadlines.
|
||||
*/
|
||||
static uint32_t deadlineMissedCount;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief This function holds the main functionality of the thread.
|
||||
*
|
||||
*
|
||||
* @details Holding the main functionality of the task, this method is most important.
|
||||
* It links the functionalities provided by FixedSlotSequence with the OS's System Calls
|
||||
* to keep the timing of the periods.
|
||||
*/
|
||||
virtual void taskFunctionality();
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief This is the entry point in a new thread.
|
||||
*
|
||||
* @details This method, that is the entry point in the new thread and calls taskFunctionality of the child class.
|
||||
* Needs a valid pointer to the derived class.
|
||||
*/
|
||||
static void* taskEntryPoint(void* arg);
|
||||
FixedSlotSequence pst;
|
||||
|
||||
bool started;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ */
|
14
osal/linux/InternalErrorCodes.cpp
Normal file
14
osal/linux/InternalErrorCodes.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
#include <framework/osal/InternalErrorCodes.h>
|
||||
|
||||
ReturnValue_t InternalErrorCodes::translate(uint8_t code) {
|
||||
//TODO This class can be removed
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
InternalErrorCodes::InternalErrorCodes() {
|
||||
}
|
||||
|
||||
InternalErrorCodes::~InternalErrorCodes() {
|
||||
|
||||
}
|
||||
|
258
osal/linux/MessageQueue.cpp
Normal file
258
osal/linux/MessageQueue.cpp
Normal file
@ -0,0 +1,258 @@
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <fcntl.h> /* For O_* constants */
|
||||
#include <sys/stat.h> /* For mode constants */
|
||||
#include <mqueue.h>
|
||||
#include <cstring>
|
||||
#include <errno.h>
|
||||
#include <framework/osal/linux/MessageQueue.h>
|
||||
|
||||
|
||||
MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size) :
|
||||
id(0), lastPartner(0), defaultDestination(NO_QUEUE), internalErrorReporter(
|
||||
NULL) {
|
||||
//debug << "MessageQueue::MessageQueue: Creating a queue" << std::endl;
|
||||
mq_attr attributes;
|
||||
this->id = 0;
|
||||
//Set attributes
|
||||
attributes.mq_curmsgs = 0;
|
||||
attributes.mq_maxmsg = message_depth;
|
||||
attributes.mq_msgsize = max_message_size;
|
||||
attributes.mq_flags = 0; //Flags are ignored on Linux during mq_open
|
||||
|
||||
//Set the name of the queue
|
||||
sprintf(name, "/Q%u\n", queueCounter++);
|
||||
|
||||
//Create a nonblocking queue if the name is available (the queue is Read and writable for the owner as well as the group)
|
||||
mqd_t tempId = mq_open(name, O_NONBLOCK | O_RDWR | O_CREAT | O_EXCL,
|
||||
S_IWUSR | S_IREAD | S_IWGRP | S_IRGRP | S_IROTH | S_IWOTH, &attributes);
|
||||
if (tempId == -1) {
|
||||
//An error occured during open
|
||||
//We need to distinguish if it is caused by an already created queue
|
||||
if (errno == EEXIST) {
|
||||
//There's another queue with the same name
|
||||
//We unlink the other queue
|
||||
int status = mq_unlink(name);
|
||||
if (status != 0) {
|
||||
error << "mq_unlink Failed with status: " << strerror(errno)
|
||||
<< std::endl;
|
||||
} else {
|
||||
//Successful unlinking, try to open again
|
||||
mqd_t tempId = mq_open(name,
|
||||
O_NONBLOCK | O_RDWR | O_CREAT | O_EXCL,
|
||||
S_IWUSR | S_IREAD | S_IWGRP | S_IRGRP, &attributes);
|
||||
if (tempId != -1) {
|
||||
//Successful mq_open
|
||||
this->id = tempId;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Failed either the first time or the second time
|
||||
error << "MessageQueue::MessageQueue: Creating Queue " << std::hex
|
||||
<< name << std::dec << " failed with status: "
|
||||
<< strerror(errno) << std::endl;
|
||||
} else {
|
||||
//Successful mq_open call
|
||||
this->id = tempId;
|
||||
}
|
||||
}
|
||||
|
||||
MessageQueue::~MessageQueue() {
|
||||
int status = mq_close(this->id);
|
||||
if(status != 0){
|
||||
error << "MessageQueue::Destructor: mq_close Failed with status: " << strerror(errno) <<std::endl;
|
||||
}
|
||||
status = mq_unlink(name);
|
||||
if(status != 0){
|
||||
error << "MessageQueue::Destructor: mq_unlink Failed with status: " << strerror(errno) <<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
|
||||
MessageQueueMessage* message, bool ignoreFault) {
|
||||
return sendMessageFrom(sendTo, message, this->getId(), false);
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message) {
|
||||
return sendToDefaultFrom(message, this->getId());
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) {
|
||||
if (this->lastPartner != 0) {
|
||||
return sendMessageFrom(this->lastPartner, message, this->getId());
|
||||
} else {
|
||||
//TODO: Good returnCode
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message,
|
||||
MessageQueueId_t* receivedFrom) {
|
||||
ReturnValue_t status = this->receiveMessage(message);
|
||||
*receivedFrom = this->lastPartner;
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) {
|
||||
unsigned int messagePriority = 0;
|
||||
int status = mq_receive(id,reinterpret_cast<char*>(message->getBuffer()),message->MAX_MESSAGE_SIZE,&messagePriority);
|
||||
if (status > 0) {
|
||||
this->lastPartner = message->getSender();
|
||||
//Check size of incoming message.
|
||||
if (message->messageSize < message->getMinimumMessageSize()) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}else if(status==0){
|
||||
//Success but no message received
|
||||
return MessageQueueIF::EMPTY;
|
||||
} else {
|
||||
//No message was received. Keep lastPartner anyway, I might send something later.
|
||||
//But still, delete packet content.
|
||||
memset(message->getData(), 0, message->MAX_DATA_SIZE);
|
||||
switch(errno){
|
||||
case EAGAIN:
|
||||
//O_NONBLOCK or MQ_NONBLOCK was set and there are no messages currently on the specified queue.
|
||||
return MessageQueueIF::EMPTY;
|
||||
case EBADF:
|
||||
//mqdes doesn't represent a valid queue open for reading.
|
||||
error << "MessageQueue::receive: configuration error " << strerror(errno) << std::endl;
|
||||
/*NO BREAK*/
|
||||
case EINVAL:
|
||||
/*
|
||||
* This value indicates one of the following:
|
||||
* * The pointer to the buffer for storing the received message, msg_ptr, is NULL.
|
||||
* * The number of bytes requested, msg_len is less than zero.
|
||||
* * msg_len is anything other than the mq_msgsize of the specified queue, and the QNX extended option MQ_READBUF_DYNAMIC hasn't been set in the queue's mq_flags.
|
||||
*/
|
||||
error << "MessageQueue::receive: configuration error " << strerror(errno) << std::endl;
|
||||
/*NO BREAK*/
|
||||
case EMSGSIZE:
|
||||
/*
|
||||
* This value indicates one of the following:
|
||||
* * the QNX extended option MQ_READBUF_DYNAMIC hasn't been set, and the given msg_len is shorter than the mq_msgsize for the given queue.
|
||||
* * the extended option MQ_READBUF_DYNAMIC has been set, but the given msg_len is too short for the message that would have been received.
|
||||
*/
|
||||
error << "MessageQueue::receive: configuration error " << strerror(errno) << std::endl;
|
||||
/*NO BREAK*/
|
||||
case EINTR:
|
||||
//The operation was interrupted by a signal.
|
||||
default:
|
||||
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
MessageQueueId_t MessageQueue::getLastPartner() const {
|
||||
return this->lastPartner;
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
||||
mq_attr attrib;
|
||||
int status = mq_getattr(id,&attrib);
|
||||
if(status != 0){
|
||||
switch(errno){
|
||||
case EBADF:
|
||||
//mqdes doesn't represent a valid message queue.
|
||||
error << "MessageQueue::flush configuration error, called flush with an invalid queue ID" << std::endl;
|
||||
/*NO BREAK*/
|
||||
case EINVAL:
|
||||
//mq_attr is NULL
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
*count = attrib.mq_curmsgs;
|
||||
attrib.mq_curmsgs = 0;
|
||||
status = mq_setattr(id,&attrib,NULL);
|
||||
if(status != 0){
|
||||
switch(errno){
|
||||
case EBADF:
|
||||
//mqdes doesn't represent a valid message queue.
|
||||
error << "MessageQueue::flush configuration error, called flush with an invalid queue ID" << std::endl;
|
||||
/*NO BREAK*/
|
||||
case EINVAL:
|
||||
/*
|
||||
* This value indicates one of the following:
|
||||
* * mq_attr is NULL.
|
||||
* * MQ_MULT_NOTIFY had been set for this queue, and the given mq_flags includes a 0 in the MQ_MULT_NOTIFY bit. Once MQ_MULT_NOTIFY has been turned on, it may never be turned off.
|
||||
*
|
||||
*/
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
MessageQueueId_t MessageQueue::getId() const {
|
||||
return this->id;
|
||||
}
|
||||
|
||||
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
|
||||
this->defaultDestination = defaultDestination;
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
|
||||
MessageQueueMessage* message, MessageQueueId_t sentFrom,
|
||||
bool ignoreFault) {
|
||||
|
||||
message->setSender(sentFrom);
|
||||
int result = mq_send(sendTo,
|
||||
reinterpret_cast<const char*>(message->getBuffer()), message->messageSize,0);
|
||||
|
||||
//TODO: Check if we're in ISR.
|
||||
if (result != 0 && !ignoreFault) {
|
||||
if (internalErrorReporter == NULL) {
|
||||
internalErrorReporter = objectManager->get<InternalErrorReporterIF>(
|
||||
objects::INTERNAL_ERROR_REPORTER);
|
||||
}
|
||||
if (internalErrorReporter != NULL) {
|
||||
internalErrorReporter->queueMessageNotSent();
|
||||
}
|
||||
switch(errno){
|
||||
case EAGAIN:
|
||||
//The O_NONBLOCK flag was set when opening the queue, or the MQ_NONBLOCK flag was set in its attributes, and the specified queue is full.
|
||||
return MessageQueueIF::FULL;
|
||||
case EBADF:
|
||||
//mq_des doesn't represent a valid message queue descriptor, or mq_des wasn't opened for writing.
|
||||
error << "MessageQueue::sendMessage: Configuration error " << strerror(errno) << " in mq_send mqSendTo: " << sendTo << " sent from " << sentFrom << std::endl;
|
||||
/*NO BREAK*/
|
||||
case EINTR:
|
||||
//The call was interrupted by a signal.
|
||||
case EINVAL:
|
||||
/*
|
||||
* This value indicates one of the following:
|
||||
* * msg_ptr is NULL.
|
||||
* * msg_len is negative.
|
||||
* * msg_prio is greater than MQ_PRIO_MAX.
|
||||
* * msg_prio is less than 0.
|
||||
* * MQ_PRIO_RESTRICT is set in the mq_attr of mq_des, and msg_prio is greater than the priority of the calling process.
|
||||
* */
|
||||
error << "MessageQueue::sendMessage: Configuration error " << strerror(errno) << " in mq_send" << std::endl;
|
||||
/*NO BREAK*/
|
||||
case EMSGSIZE:
|
||||
//The msg_len is greater than the msgsize associated with the specified queue.
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessage* message,
|
||||
MessageQueueId_t sentFrom, bool ignoreFault) {
|
||||
return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault);
|
||||
}
|
||||
|
||||
MessageQueueId_t MessageQueue::getDefaultDestination() const {
|
||||
return this->defaultDestination;
|
||||
}
|
||||
|
||||
bool MessageQueue::isDefaultDestinationSet() const {
|
||||
return (defaultDestination != NO_QUEUE);
|
||||
}
|
||||
|
||||
uint16_t MessageQueue::queueCounter = 0;
|
169
osal/linux/MessageQueue.h
Normal file
169
osal/linux/MessageQueue.h
Normal file
@ -0,0 +1,169 @@
|
||||
#ifndef MESSAGEQUEUE_H_
|
||||
#define MESSAGEQUEUE_H_
|
||||
|
||||
#include <framework/internalError/InternalErrorReporterIF.h>
|
||||
#include <framework/ipc/MessageQueueIF.h>
|
||||
#include <framework/ipc/MessageQueueMessage.h>
|
||||
/**
|
||||
* @brief This class manages sending and receiving of message queue messages.
|
||||
*
|
||||
* @details Message queues are used to pass asynchronous messages between processes.
|
||||
* They work like post boxes, where all incoming messages are stored in FIFO
|
||||
* order. This class creates a new receiving queue and provides methods to fetch
|
||||
* received messages. Being a child of MessageQueueSender, this class also provides
|
||||
* methods to send a message to a user-defined or a default destination. In addition
|
||||
* it also provides a reply method to answer to the queue it received its last message
|
||||
* from.
|
||||
* The MessageQueue should be used as "post box" for a single owning object. So all
|
||||
* message queue communication is "n-to-one".
|
||||
* For creating the queue, as well as sending and receiving messages, the class makes
|
||||
* use of the operating system calls provided.
|
||||
* \ingroup message_queue
|
||||
*/
|
||||
class MessageQueue : public MessageQueueIF {
|
||||
public:
|
||||
/**
|
||||
* @brief The constructor initializes and configures the message queue.
|
||||
* @details By making use of the according operating system call, a message queue is created
|
||||
* and initialized. The message depth - the maximum number of messages to be
|
||||
* buffered - may be set with the help of a parameter, whereas the message size is
|
||||
* automatically set to the maximum message queue message size. The operating system
|
||||
* sets the message queue id, or i case of failure, it is set to zero.
|
||||
* @param message_depth The number of messages to be buffered before passing an error to the
|
||||
* sender. Default is three.
|
||||
* @param max_message_size With this parameter, the maximum message size can be adjusted.
|
||||
* This should be left default.
|
||||
*/
|
||||
MessageQueue( size_t message_depth = 3, size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE );
|
||||
/**
|
||||
* @brief The destructor deletes the formerly created message queue.
|
||||
* @details This is accomplished by using the delete call provided by the operating system.
|
||||
*/
|
||||
virtual ~MessageQueue();
|
||||
/**
|
||||
* @brief This operation sends a message to the given destination.
|
||||
* @details It directly uses the sendMessage call of the MessageQueueSender parent, but passes its
|
||||
* queue id as "sentFrom" parameter.
|
||||
* @param sendTo This parameter specifies the message queue id of the destination message queue.
|
||||
* @param message A pointer to a previously created message, which is sent.
|
||||
* @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
|
||||
*/
|
||||
virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo,
|
||||
MessageQueueMessage* message, bool ignoreFault = false );
|
||||
/**
|
||||
* @brief This operation sends a message to the default destination.
|
||||
* @details As in the sendMessage method, this function uses the sendToDefault call of the
|
||||
* MessageQueueSender parent class and adds its queue id as "sentFrom" information.
|
||||
* @param message A pointer to a previously created message, which is sent.
|
||||
*/
|
||||
virtual ReturnValue_t sendToDefault( MessageQueueMessage* message );
|
||||
/**
|
||||
* @brief This operation sends a message to the last communication partner.
|
||||
* @details This operation simplifies answering an incoming message by using the stored
|
||||
* lastParnter information as destination. If there was no message received yet
|
||||
* (i.e. lastPartner is zero), an error code is returned.
|
||||
* @param message A pointer to a previously created message, which is sent.
|
||||
*/
|
||||
ReturnValue_t reply( MessageQueueMessage* message );
|
||||
|
||||
/**
|
||||
* @brief This function reads available messages from the message queue and returns the sender.
|
||||
* @details It works identically to the other receiveMessage call, but in addition returns the
|
||||
* sender's queue id.
|
||||
* @param message A pointer to a message in which the received data is stored.
|
||||
* @param receivedFrom A pointer to a queue id in which the sender's id is stored.
|
||||
*/
|
||||
ReturnValue_t receiveMessage(MessageQueueMessage* message,
|
||||
MessageQueueId_t *receivedFrom);
|
||||
|
||||
/**
|
||||
* @brief This function reads available messages from the message queue.
|
||||
* @details If data is available it is stored in the passed message pointer. The message's
|
||||
* original content is overwritten and the sendFrom information is stored in the
|
||||
* lastPartner attribute. Else, the lastPartner information remains untouched, the
|
||||
* message's content is cleared and the function returns immediately.
|
||||
* @param message A pointer to a message in which the received data is stored.
|
||||
*/
|
||||
ReturnValue_t receiveMessage(MessageQueueMessage* message);
|
||||
/**
|
||||
* Deletes all pending messages in the queue.
|
||||
* @param count The number of flushed messages.
|
||||
* @return RETURN_OK on success.
|
||||
*/
|
||||
ReturnValue_t flush(uint32_t* count);
|
||||
/**
|
||||
* @brief This method returns the message queue id of the last communication partner.
|
||||
*/
|
||||
MessageQueueId_t getLastPartner() const;
|
||||
/**
|
||||
* @brief This method returns the message queue id of this class's message queue.
|
||||
*/
|
||||
MessageQueueId_t getId() const;
|
||||
/**
|
||||
* \brief With the sendMessage call, a queue message is sent to a receiving queue.
|
||||
* \details This method takes the message provided, adds the sentFrom information and passes
|
||||
* it on to the destination provided with an operating system call. The OS's return
|
||||
* value is returned.
|
||||
* \param sendTo This parameter specifies the message queue id to send the message to.
|
||||
* \param message This is a pointer to a previously created message, which is sent.
|
||||
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
|
||||
* This variable is set to zero by default.
|
||||
* \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
|
||||
*/
|
||||
virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault = false );
|
||||
/**
|
||||
* \brief The sendToDefault method sends a queue message to the default destination.
|
||||
* \details In all other aspects, it works identical to the sendMessage method.
|
||||
* \param message This is a pointer to a previously created message, which is sent.
|
||||
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
|
||||
* This variable is set to zero by default.
|
||||
*/
|
||||
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
|
||||
/**
|
||||
* \brief This method is a simple setter for the default destination.
|
||||
*/
|
||||
void setDefaultDestination(MessageQueueId_t defaultDestination);
|
||||
/**
|
||||
* \brief This method is a simple getter for the default destination.
|
||||
*/
|
||||
MessageQueueId_t getDefaultDestination() const;
|
||||
|
||||
bool isDefaultDestinationSet() const;
|
||||
private:
|
||||
/**
|
||||
* @brief The class stores the queue id it got assigned from the operating system in this attribute.
|
||||
* If initialization fails, the queue id is set to zero.
|
||||
*/
|
||||
MessageQueueId_t id;
|
||||
/**
|
||||
* @brief In this attribute, the queue id of the last communication partner is stored
|
||||
* to allow for replying.
|
||||
*/
|
||||
MessageQueueId_t lastPartner;
|
||||
/**
|
||||
* @brief The message queue's name -a user specific information for the operating system- is
|
||||
* generated automatically with the help of this static counter.
|
||||
*/
|
||||
/**
|
||||
* \brief This attribute stores a default destination to send messages to.
|
||||
* \details It is stored to simplify sending to always-the-same receiver. The attribute may
|
||||
* be set in the constructor or by a setter call to setDefaultDestination.
|
||||
*/
|
||||
MessageQueueId_t defaultDestination;
|
||||
|
||||
/**
|
||||
* \brief This attribute stores a reference to the internal error reporter for reporting full queues.
|
||||
* \details In the event of a full destination queue, the reporter will be notified. The reference is set
|
||||
* by lazy loading
|
||||
*/
|
||||
InternalErrorReporterIF *internalErrorReporter;
|
||||
|
||||
/**
|
||||
* The name of the message queue, stored for unlinking
|
||||
*/
|
||||
char name[5];
|
||||
|
||||
static uint16_t queueCounter;
|
||||
};
|
||||
|
||||
#endif /* MESSAGEQUEUE_H_ */
|
98
osal/linux/Mutex.cpp
Normal file
98
osal/linux/Mutex.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
#include <framework/osal/linux/Mutex.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <framework/timemanager/Clock.h>
|
||||
|
||||
const uint32_t MutexIF::NO_TIMEOUT = 0;
|
||||
uint8_t Mutex::count = 0;
|
||||
|
||||
|
||||
#include <cstring>
|
||||
#include <errno.h>
|
||||
|
||||
Mutex::Mutex() {
|
||||
pthread_mutexattr_t mutexAttr;
|
||||
int status = pthread_mutexattr_init(&mutexAttr);
|
||||
if (status != 0) {
|
||||
error << "Mutex: Attribute init failed with: " << strerror(status) << std::endl;
|
||||
}
|
||||
status = pthread_mutexattr_setprotocol(&mutexAttr, PTHREAD_PRIO_INHERIT);
|
||||
if (status != 0) {
|
||||
error << "Mutex: Attribute set PRIO_INHERIT failed with: " << strerror(status)
|
||||
<< std::endl;
|
||||
}
|
||||
status = pthread_mutex_init(&mutex, &mutexAttr);
|
||||
if (status != 0) {
|
||||
error << "Mutex: creation with name, id " << mutex.__data.__count
|
||||
<< ", " << " failed with " << strerror(status) << std::endl;
|
||||
}
|
||||
//After a mutex attributes object has been used to initialize one or more mutexes, any function affecting the attributes object (including destruction) shall not affect any previously initialized mutexes.
|
||||
status = pthread_mutexattr_destroy(&mutexAttr);
|
||||
if (status != 0) {
|
||||
error << "Mutex: Attribute destroy failed with " << strerror(status) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
Mutex::~Mutex() {
|
||||
//No Status check yet
|
||||
pthread_mutex_destroy(&mutex);
|
||||
}
|
||||
|
||||
ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) {
|
||||
int status = 0;
|
||||
if (timeoutMs != MutexIF::NO_TIMEOUT) {
|
||||
timespec timeOut;
|
||||
clock_gettime(CLOCK_REALTIME, &timeOut);
|
||||
uint64_t nseconds = timeOut.tv_sec * 1000000000 + timeOut.tv_nsec;
|
||||
nseconds += timeoutMs * 1000000;
|
||||
timeOut.tv_sec = nseconds / 1000000000;
|
||||
timeOut.tv_nsec = nseconds - timeOut.tv_sec * 1000000000;
|
||||
status = pthread_mutex_timedlock(&mutex, &timeOut);
|
||||
} else {
|
||||
status = pthread_mutex_lock(&mutex);
|
||||
}
|
||||
switch (status) {
|
||||
case EINVAL:
|
||||
//The mutex was created with the protocol attribute having the value PTHREAD_PRIO_PROTECT and the calling thread's priority is higher than the mutex's current priority ceiling.
|
||||
return WRONG_ATTRIBUTE_SETTING;
|
||||
//The process or thread would have blocked, and the abs_timeout parameter specified a nanoseconds field value less than zero or greater than or equal to 1000 million.
|
||||
//The value specified by mutex does not refer to an initialized mutex object.
|
||||
//return MUTEX_NOT_FOUND;
|
||||
case EBUSY:
|
||||
//The mutex could not be acquired because it was already locked.
|
||||
return MUTEX_ALREADY_LOCKED;
|
||||
case ETIMEDOUT:
|
||||
//The mutex could not be locked before the specified timeout expired.
|
||||
return MUTEX_TIMEOUT;
|
||||
case EAGAIN:
|
||||
//The mutex could not be acquired because the maximum number of recursive locks for mutex has been exceeded.
|
||||
return MUTEX_MAX_LOCKS;
|
||||
case EDEADLK:
|
||||
//A deadlock condition was detected or the current thread already owns the mutex.
|
||||
return CURR_THREAD_ALREADY_OWNS_MUTEX;
|
||||
case 0:
|
||||
//Success
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
};
|
||||
}
|
||||
|
||||
ReturnValue_t Mutex::unlockMutex() {
|
||||
int status = pthread_mutex_unlock(&mutex);
|
||||
switch (status) {
|
||||
case EINVAL:
|
||||
//The value specified by mutex does not refer to an initialized mutex object.
|
||||
return MUTEX_NOT_FOUND;
|
||||
case EAGAIN:
|
||||
//The mutex could not be acquired because the maximum number of recursive locks for mutex has been exceeded.
|
||||
return MUTEX_MAX_LOCKS;
|
||||
case EPERM:
|
||||
//The current thread does not own the mutex.
|
||||
return CURR_THREAD_DOES_NOT_OWN_MUTEX;
|
||||
case 0:
|
||||
//Success
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
};
|
||||
}
|
18
osal/linux/Mutex.h
Normal file
18
osal/linux/Mutex.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef OS_RTEMS_MUTEX_H_
|
||||
#define OS_RTEMS_MUTEX_H_
|
||||
|
||||
#include <framework/ipc/MutexIF.h>
|
||||
#include <pthread.h>
|
||||
|
||||
class Mutex : public MutexIF {
|
||||
public:
|
||||
Mutex();
|
||||
virtual ~Mutex();
|
||||
virtual ReturnValue_t lockMutex(uint32_t timeoutMs);
|
||||
virtual ReturnValue_t unlockMutex();
|
||||
private:
|
||||
pthread_mutex_t mutex;
|
||||
static uint8_t count;
|
||||
};
|
||||
|
||||
#endif /* OS_RTEMS_MUTEX_H_ */
|
23
osal/linux/MutexFactory.cpp
Normal file
23
osal/linux/MutexFactory.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include <framework/ipc/MutexFactory.h>
|
||||
#include <framework/osal/linux/Mutex.h>
|
||||
|
||||
//TODO: Different variant than the lazy loading in QueueFactory. What's better and why?
|
||||
MutexFactory* MutexFactory::factoryInstance = new MutexFactory();
|
||||
|
||||
MutexFactory::MutexFactory() {
|
||||
}
|
||||
|
||||
MutexFactory::~MutexFactory() {
|
||||
}
|
||||
|
||||
MutexFactory* MutexFactory::instance() {
|
||||
return MutexFactory::factoryInstance;
|
||||
}
|
||||
|
||||
MutexIF* MutexFactory::createMutex() {
|
||||
return new Mutex();
|
||||
}
|
||||
|
||||
void MutexFactory::deleteMutex(MutexIF* mutex) {
|
||||
delete mutex;
|
||||
}
|
72
osal/linux/PeriodicPosixTask.cpp
Normal file
72
osal/linux/PeriodicPosixTask.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
#include <framework/tasks/ExecutableObjectIF.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <errno.h>
|
||||
#include <framework/osal/linux/PeriodicPosixTask.h>
|
||||
|
||||
PeriodicPosixTask::PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, uint32_t period_, void(deadlineMissedFunc_)()):PosixThread(name_,priority_,stackSize_),objectList(),started(false),periodMs(period_),deadlineMissedFunc(
|
||||
deadlineMissedFunc_) {
|
||||
|
||||
}
|
||||
|
||||
PeriodicPosixTask::~PeriodicPosixTask() {
|
||||
//Not Implemented
|
||||
}
|
||||
|
||||
void* PeriodicPosixTask::taskEntryPoint(void* arg) {
|
||||
//The argument is re-interpreted as PollingTask.
|
||||
PeriodicPosixTask *originalTask(reinterpret_cast<PeriodicPosixTask*>(arg));
|
||||
//The task's functionality is called.
|
||||
originalTask->taskFunctionality();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object) {
|
||||
ExecutableObjectIF* newObject = objectManager->get<ExecutableObjectIF>(
|
||||
object);
|
||||
if (newObject == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
objectList.push_back(newObject);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PeriodicPosixTask::sleepFor(uint32_t ms) {
|
||||
return PosixThread::sleep((uint64_t)ms*1000000);
|
||||
}
|
||||
|
||||
|
||||
ReturnValue_t PeriodicPosixTask::startTask(void){
|
||||
started = true;
|
||||
createTask(&taskEntryPoint,this);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void PeriodicPosixTask::taskFunctionality(void){
|
||||
if(!started){
|
||||
suspend();
|
||||
}
|
||||
uint64_t lastWakeTime = getCurrentMonotonicTimeMs();
|
||||
//The task's "infinite" inner loop is entered.
|
||||
while (1) {
|
||||
for (ObjectList::iterator it = objectList.begin();
|
||||
it != objectList.end(); ++it) {
|
||||
(*it)->performOperation();
|
||||
}
|
||||
if(!PosixThread::delayUntil(&lastWakeTime,periodMs)){
|
||||
char name[20] = {0};
|
||||
int status = pthread_getname_np(pthread_self(),name,sizeof(name));
|
||||
if(status==0){
|
||||
error << "ObjectTask: " << name << " Deadline missed." << std::endl;
|
||||
}else{
|
||||
error << "ObjectTask: X Deadline missed. " << status << std::endl;
|
||||
}
|
||||
if (this->deadlineMissedFunc != NULL) {
|
||||
this->deadlineMissedFunc();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t PeriodicPosixTask::getPeriodMs() const {
|
||||
return periodMs;
|
||||
}
|
76
osal/linux/PeriodicPosixTask.h
Normal file
76
osal/linux/PeriodicPosixTask.h
Normal file
@ -0,0 +1,76 @@
|
||||
#ifndef FRAMEWORK_OSAL_LINUX_PERIODICPOSIXTASK_H_
|
||||
#define FRAMEWORK_OSAL_LINUX_PERIODICPOSIXTASK_H_
|
||||
|
||||
#include <framework/tasks/PeriodicTaskIF.h>
|
||||
#include <framework/objectmanager/ObjectManagerIF.h>
|
||||
#include <framework/osal/linux/PosixThread.h>
|
||||
#include <framework/tasks/ExecutableObjectIF.h>
|
||||
#include <vector>
|
||||
|
||||
class PeriodicPosixTask: public PosixThread, public PeriodicTaskIF {
|
||||
public:
|
||||
PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, uint32_t period_, void(*deadlineMissedFunc_)());
|
||||
virtual ~PeriodicPosixTask();
|
||||
/**
|
||||
* @brief The method to start the task.
|
||||
* @details The method starts the task with the respective system call.
|
||||
* Entry point is the taskEntryPoint method described below.
|
||||
* The address of the task object is passed as an argument
|
||||
* to the system call.
|
||||
*/
|
||||
ReturnValue_t startTask(void);
|
||||
/**
|
||||
* Adds an object to the list of objects to be executed.
|
||||
* The objects are executed in the order added.
|
||||
* @param object Id of the object to add.
|
||||
* @return RETURN_OK on success, RETURN_FAILED if the object could not be added.
|
||||
*/
|
||||
ReturnValue_t addComponent(object_id_t object);
|
||||
|
||||
uint32_t getPeriodMs() const;
|
||||
|
||||
ReturnValue_t sleepFor(uint32_t ms);
|
||||
|
||||
private:
|
||||
typedef std::vector<ExecutableObjectIF*> ObjectList; //!< Typedef for the List of objects.
|
||||
/**
|
||||
* @brief This attribute holds a list of objects to be executed.
|
||||
*/
|
||||
ObjectList objectList;
|
||||
|
||||
/**
|
||||
* @brief Flag to indicate that the task was started and is allowed to run
|
||||
*/
|
||||
bool started;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Period of the task in milliseconds
|
||||
*/
|
||||
uint32_t periodMs;
|
||||
/**
|
||||
* @brief The function containing the actual functionality of the task.
|
||||
* @details The method sets and starts
|
||||
* the task's period, then enters a loop that is repeated indefinitely. Within the loop, all performOperation methods of the added
|
||||
* objects are called. Afterwards the task will be blocked until the next period.
|
||||
* On missing the deadline, the deadlineMissedFunction is executed.
|
||||
*/
|
||||
virtual void taskFunctionality(void);
|
||||
/**
|
||||
* @brief This is the entry point in a new thread.
|
||||
*
|
||||
* @details This method, that is the entry point in the new thread and calls taskFunctionality of the child class.
|
||||
* Needs a valid pointer to the derived class.
|
||||
*/
|
||||
static void* taskEntryPoint(void* arg);
|
||||
/**
|
||||
* @brief The pointer to the deadline-missed function.
|
||||
* @details This pointer stores the function that is executed if the task's deadline is missed.
|
||||
* So, each may react individually on a timing failure. The pointer may be NULL,
|
||||
* then nothing happens on missing the deadline. The deadline is equal to the next execution
|
||||
* of the periodic task.
|
||||
*/
|
||||
void (*deadlineMissedFunc)();
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_OSAL_LINUX_PERIODICPOSIXTASK_H_ */
|
188
osal/linux/PosixThread.cpp
Normal file
188
osal/linux/PosixThread.cpp
Normal file
@ -0,0 +1,188 @@
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <cstring>
|
||||
#include <errno.h>
|
||||
#include <framework/osal/linux/PosixThread.h>
|
||||
|
||||
|
||||
PosixThread::~PosixThread() {
|
||||
//No deletion and no free of Stack Pointer
|
||||
}
|
||||
|
||||
ReturnValue_t PosixThread::sleep(uint64_t ns) {
|
||||
//TODO sleep might be better with timer instead of sleep()
|
||||
timespec time;
|
||||
time.tv_sec = ns/1000000000;
|
||||
time.tv_nsec = ns - time.tv_sec*1e9;
|
||||
|
||||
//Remaining Time is not set here
|
||||
int status = nanosleep(&time,NULL);
|
||||
if(status != 0){
|
||||
switch(errno){
|
||||
case EINTR:
|
||||
//The nanosleep() function was interrupted by a signal.
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
case EINVAL:
|
||||
//The rqtp argument specified a nanosecond value less than zero or greater than or equal to 1000 million.
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void PosixThread::suspend() {
|
||||
//Wait for SIGUSR1
|
||||
int caughtSig = 0;
|
||||
sigset_t waitSignal;
|
||||
sigemptyset(&waitSignal);
|
||||
sigaddset(&waitSignal, SIGUSR1);
|
||||
sigwait(&waitSignal, &caughtSig);
|
||||
if (caughtSig != SIGUSR1) {
|
||||
error << "FixedTimeslotTask: Unknown Signal received: " << caughtSig
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void PosixThread::resume(){
|
||||
/* Signal the thread to start. Makes sense to call kill to start or? ;)
|
||||
*
|
||||
* According to Posix raise(signal) will call pthread_kill(pthread_self(), sig),
|
||||
* but as the call must be done from the thread itsself this is not possible here
|
||||
*/
|
||||
pthread_kill(thread,SIGUSR1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool PosixThread::delayUntil(uint64_t* const prevoiusWakeTime_ms,
|
||||
const uint64_t delayTime_ms) {
|
||||
uint64_t nextTimeToWake_ms;
|
||||
bool shouldDelay = false;
|
||||
//Get current Time
|
||||
const uint64_t currentTime_ms = getCurrentMonotonicTimeMs();
|
||||
/* Generate the tick time at which the task wants to wake. */
|
||||
nextTimeToWake_ms = (*prevoiusWakeTime_ms) + delayTime_ms;
|
||||
|
||||
if (currentTime_ms < *prevoiusWakeTime_ms) {
|
||||
/* The tick count has overflowed since this function was
|
||||
lasted called. In this case the only time we should ever
|
||||
actually delay is if the wake time has also overflowed,
|
||||
and the wake time is greater than the tick time. When this
|
||||
is the case it is as if neither time had overflowed. */
|
||||
if ((nextTimeToWake_ms < *prevoiusWakeTime_ms)
|
||||
&& (nextTimeToWake_ms > currentTime_ms)) {
|
||||
shouldDelay = true;
|
||||
}
|
||||
} else {
|
||||
/* The tick time has not overflowed. In this case we will
|
||||
delay if either the wake time has overflowed, and/or the
|
||||
tick time is less than the wake time. */
|
||||
if ((nextTimeToWake_ms < *prevoiusWakeTime_ms)
|
||||
|| (nextTimeToWake_ms > currentTime_ms)) {
|
||||
shouldDelay = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the wake time ready for the next call. */
|
||||
|
||||
(*prevoiusWakeTime_ms) = nextTimeToWake_ms;
|
||||
|
||||
if (shouldDelay) {
|
||||
uint64_t sleepTime = nextTimeToWake_ms - currentTime_ms;
|
||||
PosixThread::sleep(sleepTime * 1000000ull);
|
||||
return true;
|
||||
}
|
||||
//We are shifting the time in case the deadline was missed like rtems
|
||||
(*prevoiusWakeTime_ms) = currentTime_ms;
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
uint64_t PosixThread::getCurrentMonotonicTimeMs(){
|
||||
timespec timeNow;
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &timeNow);
|
||||
uint64_t currentTime_ms = (uint64_t) timeNow.tv_sec * 1000
|
||||
+ timeNow.tv_nsec / 1000000;
|
||||
|
||||
return currentTime_ms;
|
||||
}
|
||||
|
||||
PosixThread::PosixThread(const char* name_, int priority_, size_t stackSize_):thread(0),priority(priority_),stackSize(stackSize_) {
|
||||
strcpy(name,name_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PosixThread::createTask(void* (*fnc_)(void*), void* arg_) {
|
||||
debug << "PosixThread::createTask" << std::endl;
|
||||
/*
|
||||
* The attr argument points to a pthread_attr_t structure whose contents
|
||||
are used at thread creation time to determine attributes for the new
|
||||
thread; this structure is initialized using pthread_attr_init(3) and
|
||||
related functions. If attr is NULL, then the thread is created with
|
||||
default attributes.
|
||||
*/
|
||||
pthread_attr_t attributes;
|
||||
int status = pthread_attr_init(&attributes);
|
||||
if(status != 0){
|
||||
error << "Posix Thread attribute init failed with: " << strerror(status) << std::endl;
|
||||
}
|
||||
void* sp;
|
||||
status = posix_memalign(&sp, sysconf(_SC_PAGESIZE), stackSize);
|
||||
if(status != 0){
|
||||
error << "Posix Thread stack init failed with: " << strerror(status) << std::endl;
|
||||
}
|
||||
|
||||
status = pthread_attr_setstack(&attributes, sp, stackSize);
|
||||
if(status != 0){
|
||||
error << "Posix Thread attribute setStack failed with: " << strerror(status) << std::endl;
|
||||
}
|
||||
|
||||
status = pthread_attr_setinheritsched(&attributes, PTHREAD_EXPLICIT_SCHED);
|
||||
if(status != 0){
|
||||
error << "Posix Thread attribute setinheritsched failed with: " << strerror(status) << std::endl;
|
||||
}
|
||||
|
||||
//TODO FIFO -> This needs root privileges for the process
|
||||
status = pthread_attr_setschedpolicy(&attributes,SCHED_FIFO);
|
||||
if(status != 0){
|
||||
error << "Posix Thread attribute schedule policy failed with: " << strerror(status) << std::endl;
|
||||
}
|
||||
|
||||
sched_param scheduleParams;
|
||||
scheduleParams.__sched_priority = priority;
|
||||
status = pthread_attr_setschedparam(&attributes, &scheduleParams);
|
||||
if(status != 0){
|
||||
error << "Posix Thread attribute schedule params failed with: " << strerror(status) << std::endl;
|
||||
}
|
||||
|
||||
//Set Signal Mask for suspend until startTask is called
|
||||
sigset_t waitSignal;
|
||||
sigemptyset(&waitSignal);
|
||||
sigaddset(&waitSignal, SIGUSR1);
|
||||
status = pthread_sigmask(SIG_BLOCK, &waitSignal, NULL);
|
||||
if(status != 0){
|
||||
error << "Posix Thread sigmask failed failed with: " << strerror(status) << " errno: " << strerror(errno) << std::endl;
|
||||
}
|
||||
|
||||
|
||||
status = pthread_create(&thread,&attributes,fnc_,arg_);
|
||||
if(status != 0){
|
||||
error << "Posix Thread create failed with: " << strerror(status) << std::endl;
|
||||
}
|
||||
|
||||
status = pthread_setname_np(thread,name);
|
||||
if(status != 0){
|
||||
error << "Posix Thread setname failed with: " << strerror(status) << std::endl;
|
||||
}
|
||||
|
||||
status = pthread_attr_destroy(&attributes);
|
||||
if(status!=0){
|
||||
error << "Posix Thread attribute destroy failed with: " << strerror(status) << std::endl;
|
||||
}
|
||||
}
|
74
osal/linux/PosixThread.h
Normal file
74
osal/linux/PosixThread.h
Normal file
@ -0,0 +1,74 @@
|
||||
#ifndef FRAMEWORK_OSAL_LINUX_POSIXTHREAD_H_
|
||||
#define FRAMEWORK_OSAL_LINUX_POSIXTHREAD_H_
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
|
||||
class PosixThread {
|
||||
public:
|
||||
PosixThread(const char* name_, int priority_, size_t stackSize_);
|
||||
virtual ~PosixThread();
|
||||
/**
|
||||
* Set the Thread to sleep state
|
||||
* @param ns Nanosecond sleep time
|
||||
* @return Returns Failed if sleep fails
|
||||
*/
|
||||
static ReturnValue_t sleep(uint64_t ns);
|
||||
/**
|
||||
* @brief Function to suspend the task until SIGUSR1 was received
|
||||
*
|
||||
* @details Will be called in the beginning to suspend execution until startTask() is called explicitly.
|
||||
*/
|
||||
void suspend();
|
||||
|
||||
/**
|
||||
* @brief Function to allow a other thread to start the thread again from suspend state
|
||||
*
|
||||
* @details Restarts the Thread after suspend call
|
||||
*/
|
||||
void resume();
|
||||
|
||||
|
||||
/**
|
||||
* Delay function similar to FreeRtos delayUntil function
|
||||
*
|
||||
* @param prevoiusWakeTime_ms Needs the previous wake time and returns the next wakeup time
|
||||
* @param delayTime_ms Time period to delay
|
||||
*
|
||||
* @return False If deadline was missed; True if task was delayed
|
||||
*/
|
||||
static bool delayUntil(uint64_t* const prevoiusWakeTime_ms, const uint64_t delayTime_ms);
|
||||
|
||||
/**
|
||||
* Returns the current time in milliseconds from CLOCK_MONOTONIC
|
||||
*
|
||||
* @return current time in milliseconds from CLOCK_MONOTONIC
|
||||
*/
|
||||
static uint64_t getCurrentMonotonicTimeMs();
|
||||
|
||||
protected:
|
||||
pthread_t thread;
|
||||
|
||||
/**
|
||||
* @brief Function that has to be called by derived class because the derived class pointer has to be valid as argument
|
||||
* @details This function creates a pthread with the given parameters. As the function requires a pointer to the derived object
|
||||
* it has to be called after the this pointer of the derived object is valid. Sets the taskEntryPoint as
|
||||
* function to be called by new a thread.
|
||||
* @param name_ Name of the task
|
||||
* @param priority_ Priority of the task according to POSIX
|
||||
* @param stackSize_ Size of the stack attached to that task
|
||||
* @param arg_ argument of the taskEntryPoint function, needs to be this pointer of derived class
|
||||
*/
|
||||
void createTask(void* (*fnc_)(void*),void* arg_);
|
||||
|
||||
private:
|
||||
char name[10];
|
||||
int priority;
|
||||
size_t stackSize;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_OSAL_LINUX_POSIXTHREAD_H_ */
|
68
osal/linux/QueueFactory.cpp
Normal file
68
osal/linux/QueueFactory.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
#include <framework/ipc/QueueFactory.h>
|
||||
#include <mqueue.h>
|
||||
#include <errno.h>
|
||||
#include <framework/osal/linux/MessageQueue.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <cstring>
|
||||
|
||||
QueueFactory* QueueFactory::factoryInstance = NULL;
|
||||
|
||||
|
||||
ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo,
|
||||
MessageQueueMessage* message, MessageQueueId_t sentFrom) {
|
||||
message->setSender(sentFrom);
|
||||
int result = mq_send(sendTo,
|
||||
reinterpret_cast<const char*>(message->getBuffer()), message->messageSize,0);
|
||||
|
||||
//TODO: Check if we're in ISR.
|
||||
if (result != 0) {
|
||||
//TODO Translate error
|
||||
switch(errno){
|
||||
case EAGAIN:
|
||||
//The O_NONBLOCK flag was set when opening the queue, or the MQ_NONBLOCK flag was set in its attributes, and the specified queue is full.
|
||||
return MessageQueueIF::FULL;
|
||||
case EBADF:
|
||||
//mq_des doesn't represent a valid message queue descriptor, or mq_des wasn't opened for writing.
|
||||
error << "MessageQueueSenderIF::sendMessage: Configuration error " << strerror(errno) << " in mq_send mqSendTo: " << sendTo << " sent from " << sentFrom << std::endl;
|
||||
/*NO BREAK*/
|
||||
case EINTR:
|
||||
//The call was interrupted by a signal.
|
||||
case EINVAL:
|
||||
/*
|
||||
* This value indicates one of the following:
|
||||
* * msg_ptr is NULL.
|
||||
* * msg_len is negative.
|
||||
* * msg_prio is greater than MQ_PRIO_MAX.
|
||||
* * msg_prio is less than 0.
|
||||
* * MQ_PRIO_RESTRICT is set in the mq_attr of mq_des, and msg_prio is greater than the priority of the calling process.
|
||||
* */
|
||||
case EMSGSIZE:
|
||||
//The msg_len is greater than the msgsize associated with the specified queue.
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
QueueFactory* QueueFactory::instance() {
|
||||
if (factoryInstance == NULL) {
|
||||
factoryInstance = new QueueFactory;
|
||||
}
|
||||
return factoryInstance;
|
||||
}
|
||||
|
||||
QueueFactory::QueueFactory() {
|
||||
}
|
||||
|
||||
QueueFactory::~QueueFactory() {
|
||||
}
|
||||
|
||||
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t message_depth,
|
||||
uint32_t max_message_size) {
|
||||
return new MessageQueue(message_depth, max_message_size);
|
||||
}
|
||||
|
||||
void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) {
|
||||
delete queue;
|
||||
}
|
34
osal/linux/TaskFactory.cpp
Normal file
34
osal/linux/TaskFactory.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
#include <framework/osal/linux/FixedTimeslotTask.h>
|
||||
#include <framework/osal/linux/PeriodicPosixTask.h>
|
||||
#include <framework/tasks/TaskFactory.h>
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
|
||||
//TODO: Different variant than the lazy loading in QueueFactory. What's better and why?
|
||||
TaskFactory* TaskFactory::factoryInstance = new TaskFactory();
|
||||
|
||||
TaskFactory::~TaskFactory() {
|
||||
}
|
||||
|
||||
TaskFactory* TaskFactory::instance() {
|
||||
return TaskFactory::factoryInstance;
|
||||
}
|
||||
|
||||
PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_,TaskPriority taskPriority_,TaskStackSize stackSize_,TaskPeriod periodInSeconds_,TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
||||
return static_cast<PeriodicTaskIF*>(new PeriodicPosixTask(name_, taskPriority_,stackSize_,periodInSeconds_ * 1000,deadLineMissedFunction_));
|
||||
}
|
||||
|
||||
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(TaskName name_,TaskPriority taskPriority_,TaskStackSize stackSize_,TaskPeriod periodInSeconds_,TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
||||
return static_cast<FixedTimeslotTaskIF*>(new FixedTimeslotTask(name_, taskPriority_,stackSize_,periodInSeconds_*1000));
|
||||
}
|
||||
|
||||
ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) {
|
||||
//TODO not implemented
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
ReturnValue_t TaskFactory::delayTask(uint32_t delayMs){
|
||||
return PosixThread::sleep(delayMs*1000000ull);
|
||||
}
|
||||
|
||||
TaskFactory::TaskFactory() {
|
||||
}
|
41
osal/linux/Timer.cpp
Normal file
41
osal/linux/Timer.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <errno.h>
|
||||
#include <framework/osal/linux/Timer.h>
|
||||
|
||||
Timer::Timer() {
|
||||
sigevent sigEvent;
|
||||
sigEvent.sigev_notify = SIGEV_NONE;
|
||||
sigEvent.sigev_signo = 0;
|
||||
sigEvent.sigev_value.sival_ptr = &timerId;
|
||||
int status = timer_create(CLOCK_MONOTONIC, &sigEvent, &timerId);
|
||||
if(status!=0){
|
||||
error << "Timer creation failed with: " << status << " errno: " << errno << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
Timer::~Timer() {
|
||||
timer_delete(timerId);
|
||||
}
|
||||
|
||||
int Timer::setTimer(uint32_t intervalMs) {
|
||||
itimerspec timer;
|
||||
timer.it_value.tv_sec = intervalMs / 1000;
|
||||
timer.it_value.tv_nsec = (intervalMs * 1000000) % (1000000000);
|
||||
timer.it_interval.tv_sec = 0;
|
||||
timer.it_interval.tv_nsec = 0;
|
||||
return timer_settime(timerId, 0, &timer, NULL);
|
||||
}
|
||||
|
||||
|
||||
int Timer::getTimer(uint32_t* remainingTimeMs){
|
||||
itimerspec timer;
|
||||
timer.it_value.tv_sec = 0;
|
||||
timer.it_value.tv_nsec = 0;
|
||||
timer.it_interval.tv_sec = 0;
|
||||
timer.it_interval.tv_nsec = 0;
|
||||
int status = timer_gettime(timerId, &timer);
|
||||
|
||||
*remainingTimeMs = timer.it_value.tv_sec * 1000 + timer.it_value.tv_nsec / 1000000;
|
||||
|
||||
return status;
|
||||
}
|
45
osal/linux/Timer.h
Normal file
45
osal/linux/Timer.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef FRAMEWORK_OSAL_LINUX_TIMER_H_
|
||||
#define FRAMEWORK_OSAL_LINUX_TIMER_H_
|
||||
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* This class is a helper for the creation of a Clock Monotonic timer which does not trigger a signal
|
||||
*/
|
||||
class Timer {
|
||||
public:
|
||||
/**
|
||||
* Creates the Timer sets the timerId Member
|
||||
*/
|
||||
Timer();
|
||||
/**
|
||||
* Deletes the timer
|
||||
*
|
||||
* Careful! According to POSIX documentation:
|
||||
* The treatment of any pending signal generated by the deleted timer is unspecified.
|
||||
*/
|
||||
virtual ~Timer();
|
||||
|
||||
/**
|
||||
* Set the timer given in timerId to the given interval
|
||||
*
|
||||
* @param intervalMs Interval in ms to be set
|
||||
* @return 0 on Success 1 else
|
||||
*/
|
||||
int setTimer(uint32_t intervalMs);
|
||||
|
||||
/**
|
||||
* Get the remaining time of the timer
|
||||
*
|
||||
* @param remainingTimeMs Pointer to integer value which is used to return the remaining time
|
||||
* @return 0 on Success 1 else (see timer_getime documentation of posix function)
|
||||
*/
|
||||
int getTimer(uint32_t* remainingTimeMs);
|
||||
|
||||
private:
|
||||
timer_t timerId;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_OSAL_LINUX_TIMER_H_ */
|
@ -1,72 +1,125 @@
|
||||
#include <framework/timemanager/Clock.h>
|
||||
#include "RtemsBasic.h"
|
||||
#include <rtems/score/todimpl.h>
|
||||
|
||||
uint16_t Clock::leapSeconds = 0;
|
||||
MutexIF* Clock::timeMutex = NULL;
|
||||
|
||||
uint32_t Clock::getTicksPerSecond(void){
|
||||
rtems_interval ticks_per_second;
|
||||
(void) rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second);
|
||||
return ticks_per_second;
|
||||
rtems_interval ticks_per_second = rtems_clock_get_ticks_per_second();
|
||||
return static_cast<uint32_t>(ticks_per_second);
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
|
||||
//We need to cast to rtems internal time of day type here. Both structs have the same structure
|
||||
//rtems provides no const guarantee, so we need to cast the const away
|
||||
//TODO Check if this can be done safely
|
||||
rtems_time_of_day* timeRtems = reinterpret_cast<rtems_time_of_day*>(const_cast<TimeOfDay_t*>(time));
|
||||
rtems_status_code status = rtems_clock_set(timeRtems);
|
||||
return RtemsBasic::convertReturnCode(status);
|
||||
rtems_time_of_day timeRtems;
|
||||
timeRtems.year = time->year;
|
||||
timeRtems.month = time->month;
|
||||
timeRtems.day = time->day;
|
||||
timeRtems.hour = time->hour;
|
||||
timeRtems.minute = time->minute;
|
||||
timeRtems.second = time->second;
|
||||
timeRtems.ticks = time->usecond * getTicksPerSecond() / 1e6;
|
||||
rtems_status_code status = rtems_clock_set(&timeRtems);
|
||||
switch(status){
|
||||
case RTEMS_SUCCESSFUL:
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case RTEMS_INVALID_ADDRESS:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
case RTEMS_INVALID_CLOCK:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::setClock(const timeval* time) {
|
||||
//TODO This routine uses _TOD_Set which is not
|
||||
timespec newTime;
|
||||
newTime.tv_sec = time->tv_sec;
|
||||
newTime.tv_nsec = time->tv_usec * TOD_NANOSECONDS_PER_MICROSECOND;
|
||||
//SHOULDDO: Not sure if we need to protect this call somehow (by thread lock or something).
|
||||
//Uli: rtems docu says you can call this from an ISR, not sure if this means no protetion needed
|
||||
_TOD_Set(&newTime);
|
||||
//TODO Second parameter is ISR_lock_Context
|
||||
_TOD_Set(&newTime,NULL);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
||||
//Callable from ISR
|
||||
rtems_status_code status = rtems_clock_get_tod_timeval(time);
|
||||
return RtemsBasic::convertReturnCode(status);
|
||||
switch(status){
|
||||
case RTEMS_SUCCESSFUL:
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case RTEMS_NOT_DEFINED:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getUptime(timeval* uptime) {
|
||||
//According to docs.rtems.org for rtems 5 this method is more accurate than rtems_clock_get_ticks_since_boot
|
||||
timespec time;
|
||||
rtems_status_code status = rtems_clock_get_uptime(&time);
|
||||
uptime->tv_sec = time.tv_sec;
|
||||
time.tv_nsec = time.tv_nsec / 1000;
|
||||
uptime->tv_usec = time.tv_nsec;
|
||||
return RtemsBasic::convertReturnCode(status);
|
||||
switch(status){
|
||||
case RTEMS_SUCCESSFUL:
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
|
||||
//This counter overflows after 50 days
|
||||
*uptimeMs = rtems_clock_get_ticks_since_boot();
|
||||
return RtemsBasic::convertReturnCode(RTEMS_SUCCESSFUL);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
||||
timeval temp_time;
|
||||
rtems_status_code returnValue = rtems_clock_get_tod_timeval(&temp_time);
|
||||
*time = ((uint64_t) temp_time.tv_sec * 1000000) + temp_time.tv_usec;
|
||||
return RtemsBasic::convertReturnCode(returnValue);
|
||||
switch(returnValue){
|
||||
case RTEMS_SUCCESSFUL:
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
||||
rtems_time_of_day* timeRtems = reinterpret_cast<rtems_time_of_day*>(time);
|
||||
rtems_status_code status = rtems_clock_get_tod(timeRtems);
|
||||
return RtemsBasic::convertReturnCode(status);
|
||||
switch (status) {
|
||||
case RTEMS_SUCCESSFUL:
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case RTEMS_NOT_DEFINED:
|
||||
//system date and time is not set
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
case RTEMS_INVALID_ADDRESS:
|
||||
//time_buffer is NULL
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from,
|
||||
timeval* to) {
|
||||
//Fails in 2038..
|
||||
const rtems_time_of_day* timeRtems = reinterpret_cast<const rtems_time_of_day*>(from);
|
||||
to->tv_sec = _TOD_To_seconds(timeRtems);
|
||||
to->tv_usec = timeRtems->ticks * 1000;
|
||||
rtems_time_of_day timeRtems;
|
||||
timeRtems.year = from->year;
|
||||
timeRtems.month = from->month;
|
||||
timeRtems.day = from->day;
|
||||
timeRtems.hour = from->hour;
|
||||
timeRtems.minute = from->minute;
|
||||
timeRtems.second = from->second;
|
||||
timeRtems.ticks = from->usecond * getTicksPerSecond() / 1e6;
|
||||
to->tv_sec = _TOD_To_seconds(&timeRtems);
|
||||
to->tv_usec = from->usecond;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <framework/osal/CpuUsage.h>
|
||||
#include "CpuUsage.h"
|
||||
#include <framework/serialize/SerialArrayListAdapter.h>
|
||||
#include <framework/serialize/SerializeAdapter.h>
|
||||
#include <string.h>
|
||||
@ -80,7 +80,7 @@ void CpuUsage::resetCpuUsage() {
|
||||
}
|
||||
|
||||
void CpuUsage::read() {
|
||||
rtems_cpu_usage_report_with_plugin(this, &handlePrint);
|
||||
//rtems_cpu_usage_report_with_plugin(this, &handlePrint);
|
||||
}
|
||||
|
||||
void CpuUsage::clear() {
|
||||
|
@ -7,21 +7,5 @@ InitTask::InitTask() {
|
||||
}
|
||||
|
||||
InitTask::~InitTask() {
|
||||
}
|
||||
|
||||
void InitTask::deleteTask(){
|
||||
rtems_task_delete(RTEMS_SELF);
|
||||
}
|
||||
|
||||
ReturnValue_t InitTask::startTask() {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t InitTask::sleepFor(uint32_t ms) {
|
||||
rtems_status_code status = rtems_task_wake_after(RtemsBasic::convertMsToTicks(ms));
|
||||
return RtemsBasic::convertReturnCode(status);
|
||||
}
|
||||
|
||||
uint32_t InitTask::getPeriodMs() const {
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
#ifndef OS_RTEMS_INITTASK_H_
|
||||
#define OS_RTEMS_INITTASK_H_
|
||||
|
||||
#include <framework/tasks/PeriodicTaskIF.h>
|
||||
|
||||
//TODO move into static function in TaskIF
|
||||
|
||||
/**
|
||||
@ -12,17 +10,10 @@
|
||||
* Warning: The init task is deleted with this stub, i.e. the destructor
|
||||
* calls rtems_task_delete(RTEMS_SELF)
|
||||
*/
|
||||
class InitTask: public PeriodicTaskIF {
|
||||
class InitTask {
|
||||
public:
|
||||
InitTask();
|
||||
virtual ~InitTask();
|
||||
ReturnValue_t startTask();
|
||||
|
||||
ReturnValue_t sleepFor(uint32_t ms);
|
||||
|
||||
uint32_t getPeriodMs() const;
|
||||
|
||||
void deleteTask();
|
||||
};
|
||||
|
||||
#endif /* OS_RTEMS_INITTASK_H_ */
|
||||
|
@ -3,12 +3,13 @@
|
||||
|
||||
ReturnValue_t InternalErrorCodes::translate(uint8_t code) {
|
||||
switch (code) {
|
||||
case INTERNAL_ERROR_NO_CONFIGURATION_TABLE:
|
||||
return NO_CONFIGURATION_TABLE;
|
||||
case INTERNAL_ERROR_NO_CPU_TABLE:
|
||||
return NO_CPU_TABLE;
|
||||
case INTERNAL_ERROR_INVALID_WORKSPACE_ADDRESS:
|
||||
return INVALID_WORKSPACE_ADDRESS;
|
||||
//TODO It looks like RTEMS-5 does not provide the same error codes
|
||||
// case INTERNAL_ERROR_NO_CONFIGURATION_TABLE:
|
||||
// return NO_CONFIGURATION_TABLE;
|
||||
// case INTERNAL_ERROR_NO_CPU_TABLE:
|
||||
// return NO_CPU_TABLE;
|
||||
// case INTERNAL_ERROR_INVALID_WORKSPACE_ADDRESS:
|
||||
// return INVALID_WORKSPACE_ADDRESS;
|
||||
case INTERNAL_ERROR_TOO_LITTLE_WORKSPACE:
|
||||
return TOO_LITTLE_WORKSPACE;
|
||||
case INTERNAL_ERROR_WORKSPACE_ALLOCATION:
|
||||
@ -35,16 +36,16 @@ ReturnValue_t InternalErrorCodes::translate(uint8_t code) {
|
||||
return INVALID_GLOBAL_ID;
|
||||
case INTERNAL_ERROR_BAD_STACK_HOOK:
|
||||
return BAD_STACK_HOOK;
|
||||
case INTERNAL_ERROR_BAD_ATTRIBUTES:
|
||||
return BAD_ATTRIBUTES;
|
||||
case INTERNAL_ERROR_IMPLEMENTATION_KEY_CREATE_INCONSISTENCY:
|
||||
return IMPLEMENTATION_KEY_CREATE_INCONSISTENCY;
|
||||
case INTERNAL_ERROR_IMPLEMENTATION_BLOCKING_OPERATION_CANCEL:
|
||||
return IMPLEMENTATION_BLOCKING_OPERATION_CANCEL;
|
||||
case INTERNAL_ERROR_MUTEX_OBTAIN_FROM_BAD_STATE:
|
||||
return MUTEX_OBTAIN_FROM_BAD_STATE;
|
||||
case INTERNAL_ERROR_UNLIMITED_AND_MAXIMUM_IS_0:
|
||||
return UNLIMITED_AND_MAXIMUM_IS_0;
|
||||
// case INTERNAL_ERROR_BAD_ATTRIBUTES:
|
||||
// return BAD_ATTRIBUTES;
|
||||
// case INTERNAL_ERROR_IMPLEMENTATION_KEY_CREATE_INCONSISTENCY:
|
||||
// return IMPLEMENTATION_KEY_CREATE_INCONSISTENCY;
|
||||
// case INTERNAL_ERROR_IMPLEMENTATION_BLOCKING_OPERATION_CANCEL:
|
||||
// return IMPLEMENTATION_BLOCKING_OPERATION_CANCEL;
|
||||
// case INTERNAL_ERROR_MUTEX_OBTAIN_FROM_BAD_STATE:
|
||||
// return MUTEX_OBTAIN_FROM_BAD_STATE;
|
||||
// case INTERNAL_ERROR_UNLIMITED_AND_MAXIMUM_IS_0:
|
||||
// return UNLIMITED_AND_MAXIMUM_IS_0;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
#include "Interrupt.h"
|
||||
#include <bsp_flp/bsp_flp.h>
|
||||
extern "C" {
|
||||
#include <bsp_flp/hw_timer/hw_timer.h>
|
||||
#include <bsp_flp/hw_uart/hw_uart.h>
|
||||
}
|
||||
#include "RtemsBasic.h"
|
||||
|
||||
|
||||
@ -24,7 +27,20 @@ ReturnValue_t Interrupt::setInterruptServiceRoutine(IsrHandler_t handler,
|
||||
//+ 0x10 comes because of trap type assignment to IRQs in UT699 processor
|
||||
rtems_status_code status = rtems_interrupt_catch(handler, interrupt + 0x10,
|
||||
oldHandler);
|
||||
return RtemsBasic::convertReturnCode(status);
|
||||
switch(status){
|
||||
case RTEMS_SUCCESSFUL:
|
||||
//ISR established successfully
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case RTEMS_INVALID_NUMBER:
|
||||
//illegal vector number
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
case RTEMS_INVALID_ADDRESS:
|
||||
//illegal ISR entry point or invalid old_isr_handler
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t Interrupt::disableInterrupt(InterruptNumber_t interruptNumber) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include "MessageQueue.h"
|
||||
#include "RtemsBasic.h"
|
||||
|
||||
#include <cstring>
|
||||
MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size) :
|
||||
id(0), lastPartner(0), defaultDestination(NO_QUEUE), internalErrorReporter(NULL) {
|
||||
rtems_name name = ('Q' << 24) + (queueCounter++ << 8);
|
||||
@ -21,11 +21,11 @@ MessageQueue::~MessageQueue() {
|
||||
|
||||
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
|
||||
MessageQueueMessage* message, bool ignoreFault) {
|
||||
return sendMessage(sendTo, message, this->getId(), ignoreFault);
|
||||
return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message) {
|
||||
return sendToDefault(message, this->getId());
|
||||
return sendToDefaultFrom(message, this->getId());
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) {
|
||||
@ -59,7 +59,7 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) {
|
||||
//But still, delete packet content.
|
||||
memset(message->getData(), 0, message->MAX_DATA_SIZE);
|
||||
}
|
||||
return RtemsBasic::convertReturnCode(status);
|
||||
return convertReturnCode(status);
|
||||
}
|
||||
|
||||
MessageQueueId_t MessageQueue::getLastPartner() const {
|
||||
@ -68,7 +68,7 @@ MessageQueueId_t MessageQueue::getLastPartner() const {
|
||||
|
||||
ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
||||
rtems_status_code status = rtems_message_queue_flush(id, count);
|
||||
return RtemsBasic::convertReturnCode(status);
|
||||
return convertReturnCode(status);
|
||||
}
|
||||
|
||||
MessageQueueId_t MessageQueue::getId() const {
|
||||
@ -79,7 +79,7 @@ void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
|
||||
this->defaultDestination = defaultDestination;
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
|
||||
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
|
||||
MessageQueueMessage* message, MessageQueueId_t sentFrom,
|
||||
bool ignoreFault) {
|
||||
|
||||
@ -97,12 +97,18 @@ ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
|
||||
internalErrorReporter->queueMessageNotSent();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
ReturnValue_t returnCode = convertReturnCode(result);
|
||||
if(result == MessageQueueIF::EMPTY){
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message,
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessage* message,
|
||||
MessageQueueId_t sentFrom, bool ignoreFault) {
|
||||
return sendMessage(defaultDestination, message, sentFrom, ignoreFault);
|
||||
return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault);
|
||||
}
|
||||
|
||||
MessageQueueId_t MessageQueue::getDefaultDestination() const {
|
||||
@ -113,4 +119,30 @@ bool MessageQueue::isDefaultDestinationSet() const {
|
||||
return (defaultDestination != NO_QUEUE);
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::convertReturnCode(rtems_status_code inValue){
|
||||
switch(inValue){
|
||||
case RTEMS_SUCCESSFUL:
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case RTEMS_INVALID_ID:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
case RTEMS_TIMEOUT:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
case RTEMS_OBJECT_WAS_DELETED:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
case RTEMS_INVALID_ADDRESS:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
case RTEMS_INVALID_SIZE:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
case RTEMS_TOO_MANY:
|
||||
return MessageQueueIF::FULL;
|
||||
case RTEMS_UNSATISFIED:
|
||||
return MessageQueueIF::EMPTY;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint16_t MessageQueue::queueCounter = 0;
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <framework/internalError/InternalErrorReporterIF.h>
|
||||
#include <framework/ipc/MessageQueueIF.h>
|
||||
#include <framework/ipc/MessageQueueMessage.h>
|
||||
#include "RtemsBasic.h"
|
||||
|
||||
/**
|
||||
* @brief This class manages sending and receiving of message queue messages.
|
||||
@ -120,7 +121,7 @@ public:
|
||||
* This variable is set to zero by default.
|
||||
* \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
|
||||
*/
|
||||
virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
|
||||
virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
|
||||
/**
|
||||
* \brief The sendToDefault method sends a queue message to the default destination.
|
||||
* \details In all other aspects, it works identical to the sendMessage method.
|
||||
@ -128,7 +129,7 @@ public:
|
||||
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
|
||||
* This variable is set to zero by default.
|
||||
*/
|
||||
virtual ReturnValue_t sendToDefault( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
|
||||
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
|
||||
/**
|
||||
* \brief This method is a simple setter for the default destination.
|
||||
*/
|
||||
@ -169,6 +170,12 @@ private:
|
||||
InternalErrorReporterIF *internalErrorReporter;
|
||||
|
||||
static uint16_t queueCounter;
|
||||
/**
|
||||
* A method to convert an OS-specific return code to the frameworks return value concept.
|
||||
* @param inValue The return code coming from the OS.
|
||||
* @return The converted return value.
|
||||
*/
|
||||
static ReturnValue_t convertReturnCode(rtems_status_code inValue);
|
||||
};
|
||||
|
||||
#endif /* MESSAGEQUEUE_H_ */
|
||||
|
@ -14,13 +14,6 @@ MultiObjectTask::MultiObjectTask(const char *name, rtems_task_priority setPriori
|
||||
TaskBase(setPriority, setStack, name), periodTicks(
|
||||
RtemsBasic::convertMsToTicks(setPeriod)), periodId(0), deadlineMissedFunc(
|
||||
setDeadlineMissedFunc) {
|
||||
rtems_name periodName = (('P' << 24) + ('e' << 16) + ('r' << 8) + 'd');
|
||||
rtems_status_code status = rtems_rate_monotonic_create(periodName,
|
||||
&periodId);
|
||||
if (status != RTEMS_SUCCESSFUL) {
|
||||
error << "ObjectTask::period create failed with status " << status
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
MultiObjectTask::~MultiObjectTask(void) {
|
||||
@ -40,7 +33,17 @@ ReturnValue_t MultiObjectTask::startTask() {
|
||||
error << "ObjectTask::startTask for " << std::hex << this->getId()
|
||||
<< std::dec << " failed." << std::endl;
|
||||
}
|
||||
return RtemsBasic::convertReturnCode(status);
|
||||
switch(status){
|
||||
case RTEMS_SUCCESSFUL:
|
||||
//ask started successfully
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
default:
|
||||
/* RTEMS_INVALID_ADDRESS - invalid task entry point
|
||||
RTEMS_INVALID_ID - invalid task id
|
||||
RTEMS_INCORRECT_STATE - task not in the dormant state
|
||||
RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task */
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t MultiObjectTask::sleepFor(uint32_t ms) {
|
||||
@ -48,21 +51,14 @@ ReturnValue_t MultiObjectTask::sleepFor(uint32_t ms) {
|
||||
}
|
||||
|
||||
void MultiObjectTask::taskFunctionality() {
|
||||
//The +1 is necessary to avoid a call with period = 0, which does not start the period.
|
||||
rtems_status_code status = rtems_rate_monotonic_period(periodId,
|
||||
periodTicks + 1);
|
||||
if (status != RTEMS_SUCCESSFUL) {
|
||||
error << "ObjectTask::period start failed with status " << status
|
||||
<< std::endl;
|
||||
return;
|
||||
}
|
||||
TaskBase::setAndStartPeriod(periodTicks,&periodId);
|
||||
//The task's "infinite" inner loop is entered.
|
||||
while (1) {
|
||||
for (ObjectList::iterator it = objectList.begin();
|
||||
it != objectList.end(); ++it) {
|
||||
(*it)->performOperation();
|
||||
}
|
||||
status = rtems_rate_monotonic_period(periodId, periodTicks + 1);
|
||||
rtems_status_code status = TaskBase::restartPeriod(periodTicks,periodId);
|
||||
if (status == RTEMS_TIMEOUT) {
|
||||
char nameSpace[8] = { 0 };
|
||||
char* ptr = rtems_object_get_name(getId(), sizeof(nameSpace),
|
||||
|
@ -26,10 +26,40 @@ Mutex::~Mutex() {
|
||||
|
||||
ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) {
|
||||
rtems_status_code status = rtems_semaphore_obtain(mutexId, RTEMS_WAIT, timeoutMs);
|
||||
return RtemsBasic::convertReturnCode(status);
|
||||
switch(status){
|
||||
case RTEMS_SUCCESSFUL:
|
||||
//semaphore obtained successfully
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case RTEMS_UNSATISFIED:
|
||||
//semaphore not available
|
||||
return MUTEX_NOT_FOUND;
|
||||
case RTEMS_TIMEOUT:
|
||||
//timed out waiting for semaphore
|
||||
return MUTEX_TIMEOUT;
|
||||
case RTEMS_OBJECT_WAS_DELETED:
|
||||
//semaphore deleted while waiting
|
||||
return MUTEX_DESTROYED_WHILE_WAITING;
|
||||
case RTEMS_INVALID_ID:
|
||||
//invalid semaphore id
|
||||
return MUTEX_INVALID_ID;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t Mutex::unlockMutex() {
|
||||
rtems_status_code status = rtems_semaphore_release(mutexId);
|
||||
return RtemsBasic::convertReturnCode(status);
|
||||
switch(status){
|
||||
case RTEMS_SUCCESSFUL:
|
||||
//semaphore obtained successfully
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case RTEMS_NOT_OWNER_OF_RESOURCE:
|
||||
//semaphore not available
|
||||
return CURR_THREAD_DOES_NOT_OWN_MUTEX;
|
||||
case RTEMS_INVALID_ID:
|
||||
//invalid semaphore id
|
||||
return MUTEX_INVALID_ID;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,18 @@
|
||||
#include <framework/devicehandlers/FixedSequenceSlot.h>
|
||||
#include <framework/objectmanager/SystemObjectIF.h>
|
||||
#include <framework/osal/rtems/PollingTask.h>
|
||||
#include <framework/osal/rtems/RtemsBasic.h>
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include "PollingTask.h"
|
||||
#include <rtems/bspIo.h>
|
||||
#include <rtems/rtems/ratemon.h>
|
||||
#include <rtems/rtems/status.h>
|
||||
#include <rtems/rtems/tasks.h>
|
||||
#include <rtems/rtems/types.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/_stdint.h>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
|
||||
uint32_t PollingTask::deadlineMissedCount = 0;
|
||||
|
||||
@ -10,13 +23,6 @@ PollingTask::PollingTask(const char *name, rtems_task_priority setPriority,
|
||||
setOverallPeriod) {
|
||||
// All additional attributes are applied to the object.
|
||||
this->deadlineMissedFunc = setDeadlineMissedFunc;
|
||||
rtems_name periodName = (('P' << 24) + ('e' << 16) + ('r' << 8) + 'd');
|
||||
rtems_status_code status = rtems_rate_monotonic_create(periodName,
|
||||
&periodId);
|
||||
if (status != RTEMS_SUCCESSFUL) {
|
||||
error << "PollingTask::period create failed with status " << status
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
PollingTask::~PollingTask() {
|
||||
@ -47,7 +53,17 @@ ReturnValue_t PollingTask::startTask() {
|
||||
error << "PollingTask::startTask for " << std::hex << this->getId()
|
||||
<< std::dec << " failed." << std::endl;
|
||||
}
|
||||
return RtemsBasic::convertReturnCode(status);
|
||||
switch(status){
|
||||
case RTEMS_SUCCESSFUL:
|
||||
//ask started successfully
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
default:
|
||||
/* RTEMS_INVALID_ADDRESS - invalid task entry point
|
||||
RTEMS_INVALID_ID - invalid task id
|
||||
RTEMS_INCORRECT_STATE - task not in the dormant state
|
||||
RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task */
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t PollingTask::addSlot(object_id_t componentId, uint32_t slotTimeMs,
|
||||
@ -64,6 +80,8 @@ ReturnValue_t PollingTask::checkSequence() const {
|
||||
return pst.checkSequence();
|
||||
}
|
||||
|
||||
#include <rtems/io.h>
|
||||
|
||||
void PollingTask::taskFunctionality() {
|
||||
// A local iterator for the Polling Sequence Table is created to find the start time for the first entry.
|
||||
std::list<FixedSequenceSlot*>::iterator it = pst.current;
|
||||
@ -71,15 +89,7 @@ void PollingTask::taskFunctionality() {
|
||||
//The start time for the first entry is read.
|
||||
rtems_interval interval = RtemsBasic::convertMsToTicks(
|
||||
(*it)->pollingTimeMs);
|
||||
//The period is set up and started with the system call.
|
||||
//The +1 is necessary to avoid a call with period = 0, which does not start the period.
|
||||
rtems_status_code status = rtems_rate_monotonic_period(periodId,
|
||||
interval + 1);
|
||||
if (status != RTEMS_SUCCESSFUL) {
|
||||
error << "PollingTask::period start failed with status " << status
|
||||
<< std::endl;
|
||||
return;
|
||||
}
|
||||
TaskBase::setAndStartPeriod(interval,&periodId);
|
||||
//The task's "infinite" inner loop is entered.
|
||||
while (1) {
|
||||
if (pst.slotFollowsImmediately()) {
|
||||
@ -89,7 +99,7 @@ void PollingTask::taskFunctionality() {
|
||||
interval = RtemsBasic::convertMsToTicks(this->pst.getIntervalToNextSlotMs());
|
||||
//The period is checked and restarted with the new interval.
|
||||
//If the deadline was missed, the deadlineMissedFunc is called.
|
||||
status = rtems_rate_monotonic_period(periodId, interval);
|
||||
rtems_status_code status = TaskBase::restartPeriod(interval,periodId);
|
||||
if (status == RTEMS_TIMEOUT) {
|
||||
if (this->deadlineMissedFunc != NULL) {
|
||||
this->deadlineMissedFunc();
|
||||
|
@ -10,7 +10,29 @@ ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo,
|
||||
message->setSender(sentFrom);
|
||||
rtems_status_code result = rtems_message_queue_send(sendTo, message->getBuffer(),
|
||||
message->messageSize);
|
||||
return RtemsBasic::convertReturnCode(result);
|
||||
switch(result){
|
||||
case RTEMS_SUCCESSFUL:
|
||||
//message sent successfully
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case RTEMS_INVALID_ID:
|
||||
//invalid queue id
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
case RTEMS_INVALID_SIZE:
|
||||
// invalid message size
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
case RTEMS_INVALID_ADDRESS:
|
||||
//buffer is NULL
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
case RTEMS_UNSATISFIED:
|
||||
//out of message buffers
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
case RTEMS_TOO_MANY:
|
||||
//queue's limit has been reached
|
||||
return MessageQueueIF::FULL;
|
||||
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
QueueFactory* QueueFactory::instance() {
|
||||
|
@ -1,70 +1,70 @@
|
||||
#include "RtemsBasic.h"
|
||||
|
||||
|
||||
ReturnValue_t RtemsBasic::convertReturnCode(rtems_status_code inValue) {
|
||||
if (inValue == RTEMS_SUCCESSFUL) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
switch(inValue){
|
||||
case RTEMS_SUCCESSFUL:
|
||||
return OperatingSystemIF::SUCCESSFUL;
|
||||
case RTEMS_TASK_EXITTED:
|
||||
return OperatingSystemIF::TASK_EXITTED;
|
||||
case RTEMS_MP_NOT_CONFIGURED:
|
||||
return OperatingSystemIF::MP_NOT_CONFIGURED;
|
||||
case RTEMS_INVALID_NAME:
|
||||
return OperatingSystemIF::INVALID_NAME;
|
||||
case RTEMS_INVALID_ID:
|
||||
return OperatingSystemIF::INVALID_ID;
|
||||
case RTEMS_TOO_MANY:
|
||||
return OperatingSystemIF::TOO_MANY;
|
||||
case RTEMS_TIMEOUT:
|
||||
return OperatingSystemIF::TIMEOUT;
|
||||
case RTEMS_OBJECT_WAS_DELETED:
|
||||
return OperatingSystemIF::OBJECT_WAS_DELETED;
|
||||
case RTEMS_INVALID_SIZE:
|
||||
return OperatingSystemIF::INVALID_SIZE;
|
||||
case RTEMS_INVALID_ADDRESS:
|
||||
return OperatingSystemIF::INVALID_ADDRESS;
|
||||
case RTEMS_INVALID_NUMBER:
|
||||
return OperatingSystemIF::INVALID_NUMBER;
|
||||
case RTEMS_NOT_DEFINED:
|
||||
return OperatingSystemIF::NOT_DEFINED;
|
||||
case RTEMS_RESOURCE_IN_USE:
|
||||
return OperatingSystemIF::RESOURCE_IN_USE;
|
||||
//TODO RTEMS_UNSATISFIED is double mapped for FLP so it will only return Queue_empty and not unsatisfied
|
||||
case RTEMS_UNSATISFIED:
|
||||
return OperatingSystemIF::QUEUE_EMPTY;
|
||||
case RTEMS_INCORRECT_STATE:
|
||||
return OperatingSystemIF::INCORRECT_STATE;
|
||||
case RTEMS_ALREADY_SUSPENDED:
|
||||
return OperatingSystemIF::ALREADY_SUSPENDED;
|
||||
case RTEMS_ILLEGAL_ON_SELF:
|
||||
return OperatingSystemIF::ILLEGAL_ON_SELF;
|
||||
case RTEMS_ILLEGAL_ON_REMOTE_OBJECT:
|
||||
return OperatingSystemIF::ILLEGAL_ON_REMOTE_OBJECT;
|
||||
case RTEMS_CALLED_FROM_ISR:
|
||||
return OperatingSystemIF::CALLED_FROM_ISR;
|
||||
case RTEMS_INVALID_PRIORITY:
|
||||
return OperatingSystemIF::INVALID_PRIORITY;
|
||||
case RTEMS_INVALID_CLOCK:
|
||||
return OperatingSystemIF::INVALID_CLOCK;
|
||||
case RTEMS_INVALID_NODE:
|
||||
return OperatingSystemIF::INVALID_NODE;
|
||||
case RTEMS_NOT_CONFIGURED:
|
||||
return OperatingSystemIF::NOT_CONFIGURED;
|
||||
case RTEMS_NOT_OWNER_OF_RESOURCE:
|
||||
return OperatingSystemIF::NOT_OWNER_OF_RESOURCE;
|
||||
case RTEMS_NOT_IMPLEMENTED:
|
||||
return OperatingSystemIF::NOT_IMPLEMENTED;
|
||||
case RTEMS_INTERNAL_ERROR:
|
||||
return OperatingSystemIF::INTERNAL_ERROR;
|
||||
case RTEMS_NO_MEMORY:
|
||||
return OperatingSystemIF::NO_MEMORY;
|
||||
case RTEMS_IO_ERROR:
|
||||
return OperatingSystemIF::IO_ERROR;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
//ReturnValue_t RtemsBasic::convertReturnCode(rtems_status_code inValue) {
|
||||
// if (inValue == RTEMS_SUCCESSFUL) {
|
||||
// return HasReturnvaluesIF::RETURN_OK;
|
||||
// } else {
|
||||
// switch(inValue){
|
||||
// case RTEMS_SUCCESSFUL:
|
||||
// return OperatingSystemIF::SUCCESSFUL;
|
||||
// case RTEMS_TASK_EXITTED:
|
||||
// return OperatingSystemIF::TASK_EXITTED;
|
||||
// case RTEMS_MP_NOT_CONFIGURED:
|
||||
// return OperatingSystemIF::MP_NOT_CONFIGURED;
|
||||
// case RTEMS_INVALID_NAME:
|
||||
// return OperatingSystemIF::INVALID_NAME;
|
||||
// case RTEMS_INVALID_ID:
|
||||
// return OperatingSystemIF::INVALID_ID;
|
||||
// case RTEMS_TOO_MANY:
|
||||
// return OperatingSystemIF::TOO_MANY;
|
||||
// case RTEMS_TIMEOUT:
|
||||
// return OperatingSystemIF::TIMEOUT;
|
||||
// case RTEMS_OBJECT_WAS_DELETED:
|
||||
// return OperatingSystemIF::OBJECT_WAS_DELETED;
|
||||
// case RTEMS_INVALID_SIZE:
|
||||
// return OperatingSystemIF::INVALID_SIZE;
|
||||
// case RTEMS_INVALID_ADDRESS:
|
||||
// return OperatingSystemIF::INVALID_ADDRESS;
|
||||
// case RTEMS_INVALID_NUMBER:
|
||||
// return OperatingSystemIF::INVALID_NUMBER;
|
||||
// case RTEMS_NOT_DEFINED:
|
||||
// return OperatingSystemIF::NOT_DEFINED;
|
||||
// case RTEMS_RESOURCE_IN_USE:
|
||||
// return OperatingSystemIF::RESOURCE_IN_USE;
|
||||
// //TODO RTEMS_UNSATISFIED is double mapped for FLP so it will only return Queue_empty and not unsatisfied
|
||||
// case RTEMS_UNSATISFIED:
|
||||
// return OperatingSystemIF::QUEUE_EMPTY;
|
||||
// case RTEMS_INCORRECT_STATE:
|
||||
// return OperatingSystemIF::INCORRECT_STATE;
|
||||
// case RTEMS_ALREADY_SUSPENDED:
|
||||
// return OperatingSystemIF::ALREADY_SUSPENDED;
|
||||
// case RTEMS_ILLEGAL_ON_SELF:
|
||||
// return OperatingSystemIF::ILLEGAL_ON_SELF;
|
||||
// case RTEMS_ILLEGAL_ON_REMOTE_OBJECT:
|
||||
// return OperatingSystemIF::ILLEGAL_ON_REMOTE_OBJECT;
|
||||
// case RTEMS_CALLED_FROM_ISR:
|
||||
// return OperatingSystemIF::CALLED_FROM_ISR;
|
||||
// case RTEMS_INVALID_PRIORITY:
|
||||
// return OperatingSystemIF::INVALID_PRIORITY;
|
||||
// case RTEMS_INVALID_CLOCK:
|
||||
// return OperatingSystemIF::INVALID_CLOCK;
|
||||
// case RTEMS_INVALID_NODE:
|
||||
// return OperatingSystemIF::INVALID_NODE;
|
||||
// case RTEMS_NOT_CONFIGURED:
|
||||
// return OperatingSystemIF::NOT_CONFIGURED;
|
||||
// case RTEMS_NOT_OWNER_OF_RESOURCE:
|
||||
// return OperatingSystemIF::NOT_OWNER_OF_RESOURCE;
|
||||
// case RTEMS_NOT_IMPLEMENTED:
|
||||
// return OperatingSystemIF::NOT_IMPLEMENTED;
|
||||
// case RTEMS_INTERNAL_ERROR:
|
||||
// return OperatingSystemIF::INTERNAL_ERROR;
|
||||
// case RTEMS_NO_MEMORY:
|
||||
// return OperatingSystemIF::NO_MEMORY;
|
||||
// case RTEMS_IO_ERROR:
|
||||
// return OperatingSystemIF::IO_ERROR;
|
||||
// default:
|
||||
// return HasReturnvaluesIF::RETURN_FAILED;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
@ -2,11 +2,6 @@
|
||||
#define OS_RTEMS_RTEMSBASIC_H_
|
||||
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <framework/osal/OperatingSystemIF.h>
|
||||
extern "C" {
|
||||
#include <bsp_flp/rtems_config.h>
|
||||
}
|
||||
#include <rtems/endian.h>
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <rtems/error.h>
|
||||
@ -14,24 +9,15 @@ extern "C" {
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
class RtemsBasic: public OperatingSystemIF {
|
||||
class RtemsBasic {
|
||||
public:
|
||||
/**
|
||||
* A method to convert an OS-specific return code to the frameworks return value concept.
|
||||
* @param inValue The return code coming from the OS.
|
||||
* @return The converted return value.
|
||||
*/
|
||||
static ReturnValue_t convertReturnCode(rtems_status_code inValue);
|
||||
|
||||
static rtems_interval convertMsToTicks(uint32_t msIn) {
|
||||
rtems_interval ticks_per_second;
|
||||
rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second);
|
||||
rtems_interval ticks_per_second = rtems_clock_get_ticks_per_second();
|
||||
return (ticks_per_second * msIn) / 1000;
|
||||
}
|
||||
|
||||
static rtems_interval convertTicksToMs(rtems_interval ticksIn) {
|
||||
rtems_interval ticks_per_second;
|
||||
rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second);
|
||||
rtems_interval ticks_per_second = rtems_clock_get_ticks_per_second();
|
||||
return (ticksIn * 1000) / ticks_per_second;
|
||||
}
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include "TaskBase.h"
|
||||
|
||||
const uint64_t PeriodicTaskIF::MINIMUM_STACK_SIZE=RTEMS_MINIMUM_STACK_SIZE;
|
||||
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE=RTEMS_MINIMUM_STACK_SIZE;
|
||||
|
||||
TaskBase::TaskBase(rtems_task_priority set_priority, size_t stack_size,
|
||||
const char *name) {
|
||||
@ -20,7 +20,7 @@ TaskBase::TaskBase(rtems_task_priority set_priority, size_t stack_size,
|
||||
RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR,
|
||||
RTEMS_FLOATING_POINT, &id);
|
||||
}
|
||||
ReturnValue_t result = RtemsBasic::convertReturnCode(status);
|
||||
ReturnValue_t result = convertReturnCode(status);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
error << "TaskBase::TaskBase: createTask with name " << std::hex
|
||||
<< osalName << std::dec << " failed with return code "
|
||||
@ -39,5 +39,44 @@ rtems_id TaskBase::getId() {
|
||||
|
||||
ReturnValue_t TaskBase::sleepFor(uint32_t ms) {
|
||||
rtems_status_code status = rtems_task_wake_after(RtemsBasic::convertMsToTicks(ms));
|
||||
return RtemsBasic::convertReturnCode(status);
|
||||
return convertReturnCode(status);
|
||||
}
|
||||
|
||||
|
||||
ReturnValue_t TaskBase::convertReturnCode(rtems_status_code inValue) {
|
||||
switch (inValue) {
|
||||
case RTEMS_SUCCESSFUL:
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case RTEMS_MP_NOT_CONFIGURED:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
case RTEMS_INVALID_NAME:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
case RTEMS_TOO_MANY:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
case RTEMS_INVALID_ADDRESS:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
case RTEMS_UNSATISFIED:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
case RTEMS_INVALID_PRIORITY:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
ReturnValue_t TaskBase::setAndStartPeriod(rtems_interval period, rtems_id *periodId) {
|
||||
rtems_name periodName = (('P' << 24) + ('e' << 16) + ('r' << 8) + 'd');
|
||||
rtems_status_code status = rtems_rate_monotonic_create(periodName, periodId);
|
||||
if (status == RTEMS_SUCCESSFUL) {
|
||||
status = restartPeriod(period,*periodId);
|
||||
}
|
||||
return convertReturnCode(status);
|
||||
}
|
||||
|
||||
rtems_status_code TaskBase::restartPeriod(rtems_interval period, rtems_id periodId){
|
||||
//This is necessary to avoid a call with period = 0, which does not start the period.
|
||||
rtems_status_code status = rtems_rate_monotonic_period(periodId, period + 1);
|
||||
return status;
|
||||
}
|
||||
|
@ -37,6 +37,10 @@ public:
|
||||
rtems_id getId();
|
||||
|
||||
ReturnValue_t sleepFor(uint32_t ms);
|
||||
static ReturnValue_t setAndStartPeriod(rtems_interval period, rtems_id *periodId);
|
||||
static rtems_status_code restartPeriod(rtems_interval period, rtems_id periodId);
|
||||
private:
|
||||
static ReturnValue_t convertReturnCode(rtems_status_code inValue);
|
||||
};
|
||||
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "MultiObjectTask.h"
|
||||
#include "PollingTask.h"
|
||||
#include "InitTask.h"
|
||||
#include "RtemsBasic.h"
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
|
||||
//TODO: Different variant than the lazy loading in QueueFactory. What's better and why?
|
||||
@ -14,13 +15,13 @@ TaskFactory* TaskFactory::instance() {
|
||||
return TaskFactory::factoryInstance;
|
||||
}
|
||||
|
||||
PeriodicTaskIF* TaskFactory::createPeriodicTask(OSAL::TaskName name_,OSAL::TaskPriority taskPriority_,OSAL::TaskStackSize stackSize_,OSAL::TaskPeriod periodInSeconds_,OSAL::TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
||||
PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_,TaskPriority taskPriority_,TaskStackSize stackSize_,TaskPeriod periodInSeconds_,TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
||||
rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond();
|
||||
|
||||
return static_cast<PeriodicTaskIF*>(new MultiObjectTask(name_,taskPriority_,stackSize_,taskPeriod,deadLineMissedFunction_));
|
||||
}
|
||||
|
||||
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(OSAL::TaskName name_,OSAL::TaskPriority taskPriority_,OSAL::TaskStackSize stackSize_,OSAL::TaskPeriod periodInSeconds_,OSAL::TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
||||
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(TaskName name_,TaskPriority taskPriority_,TaskStackSize stackSize_,TaskPeriod periodInSeconds_,TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
||||
rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond();
|
||||
return static_cast<FixedTimeslotTaskIF*>(new PollingTask(name_,taskPriority_,stackSize_,taskPeriod,deadLineMissedFunction_));
|
||||
}
|
||||
@ -30,5 +31,11 @@ ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
ReturnValue_t TaskFactory::delayTask(uint32_t delayMs){
|
||||
rtems_task_wake_after(RtemsBasic::convertMsToTicks(delayMs));
|
||||
//Only return value is "RTEMS_SUCCESSFUL - always successful" so it has been neglected
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
TaskFactory::TaskFactory() {
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
ParameterHelper::ParameterHelper(ReceivesParameterMessagesIF* owner) :
|
||||
owner(owner), storage(NULL) {
|
||||
ownerQueueId = owner->getCommandQueue();
|
||||
|
||||
}
|
||||
|
||||
ParameterHelper::~ParameterHelper() {
|
||||
@ -114,6 +114,9 @@ ReturnValue_t ParameterHelper::sendParameter(MessageQueueId_t to, uint32_t id,
|
||||
}
|
||||
|
||||
ReturnValue_t ParameterHelper::initialize() {
|
||||
ownerQueueId = owner->getCommandQueue();
|
||||
|
||||
|
||||
storage = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if (storage == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
|
@ -55,7 +55,10 @@ enum {
|
||||
DEVICE_COMMUNICATION_IF, //DC
|
||||
BSP, //BSP
|
||||
TIME_STAMPER_IF, //TSI 52
|
||||
//TODO This will shift all IDs for FLP
|
||||
SGP4PROPAGATOR_CLASS, //SGP4 53
|
||||
MUTEX_IF, //MUX 54
|
||||
MESSAGE_QUEUE_IF,//MQI 55
|
||||
FW_CLASS_ID_COUNT //is actually count + 1 !
|
||||
|
||||
};
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <stddef.h>
|
||||
|
||||
ReturnValue_t RMAP::reset(RMAPCookie* cookie) {
|
||||
return cookie->channel->reset();
|
||||
return cookie->getChannel()->reset();
|
||||
}
|
||||
|
||||
RMAP::RMAP(){
|
||||
@ -22,7 +22,7 @@ ReturnValue_t RMAP::sendWriteCommand(RMAPCookie *cookie, uint8_t* buffer,
|
||||
if (cookie->getChannel() == NULL) {
|
||||
return COMMAND_NO_CHANNEL;
|
||||
}
|
||||
instruction = RMAP_COMMAND_WRITE | cookie->command_mask;
|
||||
instruction = RMAPIds::RMAP_COMMAND_WRITE | cookie->getCommandMask();
|
||||
return cookie->getChannel()->sendCommand(cookie, instruction, buffer,
|
||||
length);
|
||||
|
||||
@ -32,7 +32,7 @@ ReturnValue_t RMAP::getWriteReply(RMAPCookie *cookie) {
|
||||
if (cookie->getChannel() == NULL) {
|
||||
return COMMAND_NO_CHANNEL;
|
||||
}
|
||||
if (cookie->header.instruction & (1 << RMAP_COMMAND_BIT_WRITE)) {
|
||||
if (cookie->getHeader()->instruction & (1 << RMAPIds::RMAP_COMMAND_BIT_WRITE)) {
|
||||
return cookie->getChannel()->getReply(cookie, NULL, NULL);
|
||||
} else {
|
||||
return REPLY_MISSMATCH;
|
||||
@ -53,8 +53,8 @@ ReturnValue_t RMAP::sendReadCommand(RMAPCookie *cookie, uint32_t expLength) {
|
||||
if (cookie->getChannel() == NULL) {
|
||||
return COMMAND_NO_CHANNEL;
|
||||
}
|
||||
command = RMAP_COMMAND_READ
|
||||
| (cookie->command_mask & ~(1 << RMAP_COMMAND_BIT_VERIFY));
|
||||
command = RMAPIds::RMAP_COMMAND_READ
|
||||
| (cookie->getCommandMask() & ~(1 << RMAPIds::RMAP_COMMAND_BIT_VERIFY));
|
||||
|
||||
return cookie->getChannel()->sendCommand(cookie, command, NULL, expLength);
|
||||
|
||||
@ -68,7 +68,7 @@ ReturnValue_t RMAP::getReadReply(RMAPCookie *cookie, uint8_t **buffer,
|
||||
if (buffer == NULL || size == NULL) {
|
||||
return DeviceCommunicationIF::NULLPOINTER;
|
||||
}
|
||||
if (cookie->header.instruction & (1 << RMAP_COMMAND_BIT_WRITE)) {
|
||||
if (cookie->getHeader()->instruction & (1 << RMAPIds::RMAP_COMMAND_BIT_WRITE)) {
|
||||
return REPLY_MISSMATCH;
|
||||
} else {
|
||||
return cookie->getChannel()->getReply(cookie, buffer, size);
|
||||
|
@ -1,11 +1,12 @@
|
||||
#ifndef RMAPCHANNELIF_H_
|
||||
#define RMAPCHANNELIF_H_
|
||||
|
||||
#include <framework/rmap/RMAP.h>
|
||||
#include <framework/tasks/PeriodicTaskIF.h>
|
||||
#include <framework/rmap/RMAPCookie.h>
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
|
||||
class RMAPChannelIF: public RMAP {
|
||||
class RMAPChannelIF {
|
||||
public:
|
||||
virtual ~RMAPChannelIF(){};
|
||||
/**
|
||||
* Reset an RMAP channel
|
||||
*
|
||||
@ -42,7 +43,7 @@ public:
|
||||
* - @c COMMAND_PORT_OUT_OF_RANGE if the port is invalid
|
||||
*/
|
||||
virtual ReturnValue_t setPort(int8_t port, uint8_t dest_addr,
|
||||
uint8_t src_addr, PeriodicTaskIF* currentTask)=0;
|
||||
uint8_t src_addr)=0;
|
||||
|
||||
/**
|
||||
* Assign a SpaceWire port to the Channel
|
||||
@ -54,7 +55,7 @@ public:
|
||||
* - @c COMMAND_OK if port was changed
|
||||
* - @c COMMAND_PORT_OUT_OF_RANGE if the port is invalid
|
||||
*/
|
||||
virtual ReturnValue_t setPort(int8_t port, PeriodicTaskIF* currentTask)=0;
|
||||
virtual ReturnValue_t setPort(int8_t port)=0;
|
||||
|
||||
/**
|
||||
* Send an RMAP command
|
||||
|
@ -20,13 +20,11 @@ RMAPCookie::RMAPCookie() {
|
||||
this->header.datalen_m = 0;
|
||||
this->header.datalen_l = 0;
|
||||
this->header.header_crc = 0;
|
||||
|
||||
|
||||
this->txdesc = NULL;
|
||||
this->rxdesc_index = 0;
|
||||
this->channel = NULL;
|
||||
this->command_mask = 0;
|
||||
|
||||
this->dataCRC = 0;
|
||||
|
||||
this->maxReplyLen = 0;
|
||||
}
|
||||
|
||||
@ -47,11 +45,9 @@ RMAPCookie::RMAPCookie(uint32_t set_address, uint8_t set_extended_address,
|
||||
this->header.datalen_m = 0;
|
||||
this->header.datalen_l = 0;
|
||||
this->header.header_crc = 0;
|
||||
|
||||
this->txdesc = NULL;
|
||||
this->rxdesc_index = 0;
|
||||
this->channel = set_channel;
|
||||
this->command_mask = set_command_mask;
|
||||
this->dataCRC = 0;
|
||||
|
||||
this->maxReplyLen = maxReplyLen;
|
||||
}
|
||||
@ -104,3 +100,25 @@ uint32_t RMAPCookie::getMaxReplyLen() const {
|
||||
void RMAPCookie::setMaxReplyLen(uint32_t maxReplyLen) {
|
||||
this->maxReplyLen = maxReplyLen;
|
||||
}
|
||||
|
||||
RMAPStructs::rmap_cmd_header* RMAPCookie::getHeader(){
|
||||
return &this->header;
|
||||
}
|
||||
|
||||
uint16_t RMAPCookie::getTransactionIdentifier() const {
|
||||
return static_cast<uint16_t>((header.tid_h << 8) | (header.tid_l));
|
||||
}
|
||||
|
||||
void RMAPCookie::setTransactionIdentifier(uint16_t id_) {
|
||||
header.tid_l = id_ & 0xFF;
|
||||
header.tid_h = (id_ >> 8 ) & 0xFF;
|
||||
}
|
||||
|
||||
uint32_t RMAPCookie::getDataLength() const {
|
||||
return static_cast<uint32_t>(header.datalen_h << 16 | header.datalen_m << 8 | header.datalen_l);
|
||||
}
|
||||
void RMAPCookie::setDataLength(uint32_t length_) {
|
||||
header.datalen_l = length_ & 0xff;
|
||||
header.datalen_m = (length_ >> 8) & 0xff;
|
||||
header.datalen_h = (length_ >> 16) & 0xff;
|
||||
}
|
||||
|
@ -7,8 +7,6 @@
|
||||
class RMAPChannelIF;
|
||||
|
||||
class RMAPCookie : public Cookie{
|
||||
friend class RMAP;
|
||||
friend class RmapSPWChannel;
|
||||
public:
|
||||
//To Uli: Sorry, I need an empty ctor to initialize an array of cookies.
|
||||
RMAPCookie();
|
||||
@ -20,24 +18,41 @@ public:
|
||||
|
||||
void setAddress(uint32_t address);
|
||||
uint32_t getAddress();
|
||||
|
||||
void setExtendedAddress(uint8_t);
|
||||
uint8_t getExtendedAddress();
|
||||
|
||||
void setChannel(RMAPChannelIF *channel);
|
||||
RMAPChannelIF *getChannel();
|
||||
|
||||
void setCommandMask(uint8_t commandMask);
|
||||
uint8_t getCommandMask();
|
||||
|
||||
uint32_t getMaxReplyLen() const;
|
||||
void setMaxReplyLen(uint32_t maxReplyLen);
|
||||
|
||||
//rmap_cookie* getDeviceDescriptor();
|
||||
uint16_t getTransactionIdentifier() const;
|
||||
void setTransactionIdentifier(uint16_t id_);
|
||||
|
||||
RMAPStructs::rmap_cmd_header* getHeader();
|
||||
|
||||
uint32_t getDataLength() const;
|
||||
void setDataLength(uint32_t lenght_);
|
||||
|
||||
uint8_t getDataCrc() const {
|
||||
return dataCRC;
|
||||
}
|
||||
|
||||
void setDataCrc(uint8_t dataCrc) {
|
||||
dataCRC = dataCrc;
|
||||
}
|
||||
|
||||
protected:
|
||||
RMAPStructs::rmap_cmd_header header;
|
||||
void *txdesc;
|
||||
uint8_t rxdesc_index;
|
||||
RMAPChannelIF *channel;
|
||||
uint8_t command_mask;
|
||||
uint32_t maxReplyLen;
|
||||
uint8_t dataCRC;
|
||||
};
|
||||
|
||||
#endif /* RMAPCOOKIE_H_ */
|
||||
|
47
rmap/RmapDeviceCommunicationIF.cpp
Normal file
47
rmap/RmapDeviceCommunicationIF.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
#include <framework/rmap/RmapDeviceCommunicationIF.h>
|
||||
#include <framework/rmap/RMAP.h>
|
||||
|
||||
//TODO Cast here are all potential bugs
|
||||
RmapDeviceCommunicationIF::~RmapDeviceCommunicationIF() {
|
||||
}
|
||||
|
||||
ReturnValue_t RmapDeviceCommunicationIF::sendMessage(Cookie* cookie,
|
||||
uint8_t* data, uint32_t len) {
|
||||
return RMAP::sendWriteCommand((RMAPCookie *) cookie, data, len);
|
||||
}
|
||||
|
||||
ReturnValue_t RmapDeviceCommunicationIF::getSendSuccess(Cookie* cookie) {
|
||||
return RMAP::getWriteReply((RMAPCookie *) cookie);
|
||||
}
|
||||
|
||||
ReturnValue_t RmapDeviceCommunicationIF::requestReceiveMessage(
|
||||
Cookie* cookie) {
|
||||
return RMAP::sendReadCommand((RMAPCookie *) cookie,
|
||||
((RMAPCookie *) cookie)->getMaxReplyLen());
|
||||
}
|
||||
|
||||
ReturnValue_t RmapDeviceCommunicationIF::readReceivedMessage(Cookie* cookie,
|
||||
uint8_t** buffer, uint32_t* size) {
|
||||
return RMAP::getReadReply((RMAPCookie *) cookie, buffer, size);
|
||||
}
|
||||
|
||||
ReturnValue_t RmapDeviceCommunicationIF::setAddress(Cookie* cookie,
|
||||
uint32_t address) {
|
||||
|
||||
((RMAPCookie *) cookie)->setAddress(address);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
uint32_t RmapDeviceCommunicationIF::getAddress(Cookie* cookie) {
|
||||
return ((RMAPCookie *) cookie)->getAddress();
|
||||
}
|
||||
|
||||
ReturnValue_t RmapDeviceCommunicationIF::setParameter(Cookie* cookie,
|
||||
uint32_t parameter) {
|
||||
//TODO Empty?
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
uint32_t RmapDeviceCommunicationIF::getParameter(Cookie* cookie) {
|
||||
return 0;
|
||||
}
|
80
rmap/RmapDeviceCommunicationIF.h
Normal file
80
rmap/RmapDeviceCommunicationIF.h
Normal file
@ -0,0 +1,80 @@
|
||||
#ifndef MISSION_RMAP_RMAPDEVICECOMMUNICATIONINTERFACE_H_
|
||||
#define MISSION_RMAP_RMAPDEVICECOMMUNICATIONINTERFACE_H_
|
||||
|
||||
#include <framework/devicehandlers/DeviceCommunicationIF.h>
|
||||
|
||||
/**
|
||||
* @brief This class is a implementation of a DeviceCommunicationIF for RMAP calls. It expects RMAPCookies or a derived class of RMAPCookies
|
||||
*
|
||||
* @details The open, close and reOpen calls are mission specific
|
||||
* The open call might return any child of RMAPCookies
|
||||
*
|
||||
* \ingroup rmap
|
||||
*/
|
||||
class RmapDeviceCommunicationIF: public DeviceCommunicationIF {
|
||||
|
||||
public:
|
||||
virtual ~RmapDeviceCommunicationIF();
|
||||
|
||||
|
||||
/**
|
||||
* This method is mission specific as the open call will return a mission specific cookie
|
||||
*
|
||||
* @param cookie A cookie, can be mission specific subclass of RMAP Cookie
|
||||
* @param address The address of the RMAP Cookie
|
||||
* @param maxReplyLen Maximum length of expected reply
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t open(Cookie **cookie, uint32_t address,
|
||||
uint32_t maxReplyLen) = 0;
|
||||
|
||||
/**
|
||||
* Use an existing cookie to open a connection to a new DeviceCommunication.
|
||||
* The previous connection must not be closed.
|
||||
* If the returnvalue is not RETURN_OK, the cookie is unchanged and
|
||||
* can be used with the previous connection.
|
||||
*
|
||||
* @param cookie
|
||||
* @param address
|
||||
* @param maxReplyLen
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t reOpen(Cookie *cookie, uint32_t address,
|
||||
uint32_t maxReplyLen) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Closing call of connection and memory free of cookie. Mission dependent call
|
||||
* @param cookie
|
||||
*/
|
||||
virtual void close(Cookie *cookie) = 0;
|
||||
|
||||
//SHOULDDO can data be const?
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param cookie Expects an RMAPCookie or derived from RMAPCookie Class
|
||||
* @param data Data to be send
|
||||
* @param len Length of the data to be send
|
||||
* @return - Return codes of RMAP::sendWriteCommand()
|
||||
*/
|
||||
virtual ReturnValue_t sendMessage(Cookie *cookie, uint8_t *data,
|
||||
uint32_t len);
|
||||
|
||||
virtual ReturnValue_t getSendSuccess(Cookie *cookie);
|
||||
|
||||
virtual ReturnValue_t requestReceiveMessage(Cookie *cookie);
|
||||
|
||||
virtual ReturnValue_t readReceivedMessage(Cookie *cookie, uint8_t **buffer,
|
||||
uint32_t *size);
|
||||
|
||||
virtual ReturnValue_t setAddress(Cookie *cookie, uint32_t address);
|
||||
|
||||
virtual uint32_t getAddress(Cookie *cookie);
|
||||
|
||||
virtual ReturnValue_t setParameter(Cookie *cookie, uint32_t parameter);
|
||||
|
||||
virtual uint32_t getParameter(Cookie *cookie);
|
||||
};
|
||||
|
||||
#endif /* MISSION_RMAP_RMAPDEVICECOMMUNICATIONINTERFACE_H_ */
|
@ -1,744 +0,0 @@
|
||||
#include <framework/rmap/RmapSPWChannel.h>
|
||||
extern "C" {
|
||||
#include <bsp_flp/hw_timer/hw_timer.h>
|
||||
#include <bsp_flp/crc/crc.h>
|
||||
}
|
||||
|
||||
#include <framework/datapool/DataSet.h>
|
||||
#include <framework/datapool/PoolVariable.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//bits for the failure table
|
||||
#define RMAP_RX_FAIL_CHECKED 0
|
||||
#define RMAP_RX_FAIL_EEP 1
|
||||
#define RMAP_RX_FAIL_TRUNC 2
|
||||
#define RMAP_RX_FAIL_LEN 3
|
||||
#define RMAP_RX_FAIL_CRC 4
|
||||
#define RMAP_RX_FAIL_DST_ADDR 5
|
||||
#define RMAP_RX_FAIL_PROTO 6
|
||||
#define RMAP_RX_FAIL_INSTR_TYPE 7 //this is when the instruction byte is really wrong (must be caused by device)
|
||||
#define RMAP_RX_FAIL_INSTR 8 //this is when a wrong instruction byte was caused by a wrong instruction sent by the host and detected by the device
|
||||
#define RMAP_RX_FAIL_SRC_ADDR 9
|
||||
#define RMAP_RX_FAIL_LEN_MISSMATCH 10
|
||||
#define RMAP_RX_FAIL_WRONG_REPLY 11 //a read command was answered by a write reply or the other way round
|
||||
//pad a number so it is word aligned (32bit)
|
||||
#define BYTES2WORDS(number) (((number) +3)/4)
|
||||
|
||||
RmapSPWChannel::RmapSPWChannel(object_id_t setObjectId,
|
||||
uint16_t buffersize_words, uint32_t maxPacketSize, int8_t portNr,
|
||||
uint8_t dest_addr, uint8_t src_addr, PeriodicTaskIF* currentTask,
|
||||
datapool::opus_variable_id portVariable) :
|
||||
SystemObject(setObjectId), port(NULL), rx_index(0), max_rx(128), tx_index(
|
||||
0), max_tx(64), src_addr(src_addr), dest_addr(dest_addr), portPoolId(
|
||||
portVariable) {
|
||||
buffer = new uint32_t[buffersize_words];
|
||||
buffer_pointer = buffer;
|
||||
end_of_buffer = &buffer[buffersize_words];
|
||||
max_packet_len = maxPacketSize & 0x1FFFFFC;
|
||||
tid = 0;
|
||||
failure_table = new uint16_t[128];
|
||||
setPort(portNr, dest_addr, src_addr, currentTask);
|
||||
}
|
||||
|
||||
RmapSPWChannel::~RmapSPWChannel() {
|
||||
delete[] buffer;
|
||||
delete[] failure_table;
|
||||
}
|
||||
|
||||
ReturnValue_t RmapSPWChannel::reset() {
|
||||
uint8_t link_down = 0;
|
||||
uint8_t missed, i;
|
||||
uint32_t state;
|
||||
|
||||
//check if channel has a port
|
||||
if (port == NULL) {
|
||||
return COMMAND_CHANNEL_DEACTIVATED;
|
||||
}
|
||||
|
||||
//check state of SPW
|
||||
state = spw_get_state(port);
|
||||
if (state != SPW_STATE_RUN) {
|
||||
triggerEvent(SPW_LINK_DOWN, getCurrentPortNr());
|
||||
link_down++;
|
||||
}
|
||||
//SPW link errors
|
||||
if ((state = (port->SPWSTR & 0x1de)) != 0) {
|
||||
reportSpwstr(state);
|
||||
}
|
||||
//check DMA errors
|
||||
if ((state = (port->SPWCHN & 0x180)) != 0) {
|
||||
triggerEvent(SPW_ERROR, SPW_DMA, state);
|
||||
}
|
||||
|
||||
//hard reset spw
|
||||
//only safe way to reset the descriptors
|
||||
|
||||
spw_reset(port);
|
||||
|
||||
spw_reset_rxdesc_table(port);
|
||||
spw_reset_txdesc_table(port);
|
||||
|
||||
//reset internal buffer
|
||||
buffer_pointer = buffer;
|
||||
|
||||
#ifdef LEON
|
||||
asm("flush");
|
||||
#endif
|
||||
|
||||
//check how many packets were received
|
||||
missed = 0;
|
||||
|
||||
if ((rx_index != 0)
|
||||
&& (rx_descriptor_table[rx_index - 1].word0
|
||||
& (1 << SPW_DESC_RX_ENABLE))) {
|
||||
// printf("word 0 = %08lx\n",
|
||||
// rx_descriptor_table[rx_index - 1].word0);
|
||||
for (missed = 1; missed < rx_index; missed++) {
|
||||
if (!(rx_descriptor_table[rx_index - 1 - missed].word0
|
||||
& (1 << SPW_DESC_RX_ENABLE)))
|
||||
break;
|
||||
}
|
||||
triggerEvent(RMAP_MISSED_REPLIES, missed);
|
||||
//missed is number of missed replies
|
||||
|
||||
}
|
||||
if (missed == rx_index) {
|
||||
link_down++;
|
||||
}
|
||||
|
||||
for (i = rx_index - missed; i > 0; i--) {
|
||||
if (!(failure_table[i - 1] & 1)) {
|
||||
checkRxDescPacket(&(rx_descriptor_table[i - 1]),
|
||||
&(failure_table[i - 1]));
|
||||
}
|
||||
if (failure_table[i - 1] & 0xFFFE) {
|
||||
reportFailures(failure_table[i - 1], i - 1);
|
||||
}
|
||||
}
|
||||
|
||||
//reset descriptor counter
|
||||
rx_index = 0;
|
||||
tx_index = 0;
|
||||
|
||||
//clear all descriptors to get rid of unused ones
|
||||
spw_rx_desc *rx_desc;
|
||||
i = 0;
|
||||
for (rx_desc = rx_descriptor_table; rx_desc < &rx_descriptor_table[max_rx];
|
||||
rx_desc++) {
|
||||
rx_desc->word0 = 0;
|
||||
failure_table[i++] = 0;
|
||||
}
|
||||
spw_tx_desc *tx_desc;
|
||||
for (tx_desc = tx_descriptor_table; tx_desc < &tx_descriptor_table[max_tx];
|
||||
tx_desc++) {
|
||||
tx_desc->word0 = 0;
|
||||
}
|
||||
|
||||
//restart spw
|
||||
spw_start(port);
|
||||
|
||||
if (link_down > 1) {
|
||||
return LINK_DOWN;
|
||||
}
|
||||
return RETURN_OK;
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t RmapSPWChannel::isActive() {
|
||||
if (port == NULL) {
|
||||
return COMMAND_CHANNEL_DEACTIVATED;
|
||||
}
|
||||
uint32_t state = spw_get_state(port);
|
||||
if (state != SPW_STATE_RUN) {
|
||||
return LINK_DOWN;
|
||||
}
|
||||
return RETURN_OK;
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t RmapSPWChannel::setPort(int8_t portNr, uint8_t dest_addr,
|
||||
uint8_t src_addr, PeriodicTaskIF* currentTask) {
|
||||
|
||||
SPW_dev *new_port;
|
||||
|
||||
//only accept ports from a list or -1, which disables channel
|
||||
if (portNr >= SPW_devices.len && portNr < -1) {
|
||||
return COMMAND_PORT_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
//check if crc is enabled
|
||||
|
||||
if (portNr != -1) {
|
||||
new_port = SPW_devices.devices[portNr];
|
||||
if (!spw_crc_enabled(new_port)) {
|
||||
return NO_HW_CRC;
|
||||
}
|
||||
} else {
|
||||
new_port = NULL;
|
||||
}
|
||||
|
||||
//anounce change
|
||||
triggerEvent(RMAP_SWITCHED_PORT, portNr, getCurrentPortNr());
|
||||
if (portPoolId != 0) {
|
||||
DataSet mySet;
|
||||
PoolVariable<int8_t> channel(portPoolId, &mySet,
|
||||
PoolVariableIF::VAR_WRITE);
|
||||
mySet.read();
|
||||
channel = portNr;
|
||||
mySet.commit(PoolVariableIF::VALID);
|
||||
}
|
||||
|
||||
//reset the old port to clear pending errors etc
|
||||
reset();
|
||||
//assign new port
|
||||
this->port = new_port;
|
||||
|
||||
if (new_port == NULL) {
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
//stop the new port
|
||||
spw_stop(new_port);
|
||||
//make sure the new port has the max len set
|
||||
new_port->SPWRXL = max_packet_len;
|
||||
//set the addresses
|
||||
this->dest_addr = dest_addr;
|
||||
this->src_addr = src_addr;
|
||||
new_port->SPWNDR = src_addr;
|
||||
//set descriptor table
|
||||
tx_descriptor_table = spw_get_tx_descriptor_table(new_port);
|
||||
rx_descriptor_table = spw_get_rx_descriptor_table(new_port);
|
||||
spw_reset_rxdesc_table(new_port);
|
||||
spw_reset_txdesc_table(new_port);
|
||||
//reset the channel
|
||||
spw_start(new_port);
|
||||
currentTask->sleepFor(10);
|
||||
reset();
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t RmapSPWChannel::setPort(int8_t port, PeriodicTaskIF* currentTask) {
|
||||
return setPort(port, this->dest_addr, this->src_addr, currentTask);
|
||||
}
|
||||
|
||||
spw_rx_desc* RmapSPWChannel::findReply(RMAPCookie* cookie) {
|
||||
spw_rx_desc *rxdesc;
|
||||
uint8_t i;
|
||||
|
||||
//look downwards
|
||||
for (i = cookie->rxdesc_index; i < 200; i--) {
|
||||
if ((rxdesc = checkRxDesc(cookie, i)) != NULL) {
|
||||
return rxdesc;
|
||||
}
|
||||
}
|
||||
//look upwards
|
||||
for (i = cookie->rxdesc_index + 1; i < max_rx; i++) {
|
||||
if ((rxdesc = checkRxDesc(cookie, i)) != NULL) {
|
||||
return rxdesc;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t RmapSPWChannel::sendCommand(RMAPCookie* cookie,
|
||||
uint8_t instruction, uint8_t* data, uint32_t datalen) {
|
||||
|
||||
uint8_t headerlen = RMAP_COMMAND_HEADER_LEN - 1;
|
||||
|
||||
//check if channel has a port
|
||||
if (port == NULL) {
|
||||
return COMMAND_CHANNEL_DEACTIVATED;
|
||||
}
|
||||
|
||||
//max send limit
|
||||
if ((instruction & (1 << RMAP_COMMAND_BIT_WRITE))
|
||||
&& (datalen & ~0xFFFFFF)) {
|
||||
printf("application wants to send to much data with cookie at %p\n",
|
||||
cookie);
|
||||
return TOO_MUCH_DATA;
|
||||
}
|
||||
//max receive limit
|
||||
if ((!(instruction & (1 << RMAP_COMMAND_BIT_WRITE)))
|
||||
&& (datalen + 1 + RMAP_READ_REPLY_HEADER_LEN > max_packet_len)) {
|
||||
printf("application wants to read too much data with cookie at %p\n",
|
||||
cookie);
|
||||
return TOO_MUCH_DATA;
|
||||
}
|
||||
|
||||
//check if enough space is left in the buffer
|
||||
//must be checked against max_packet_len, as you can not tell what hw will do,
|
||||
//except that it will write this number at most
|
||||
if ((buffer_pointer + BYTES2WORDS(max_packet_len))
|
||||
> end_of_buffer) {
|
||||
printf("buffer is full, cookie is %p\n", cookie);
|
||||
return COMMAND_BUFFER_FULL;
|
||||
}
|
||||
|
||||
//we allow tx descriptor wrap at user discretion, but check we have rx descriptors available
|
||||
//as we dont wrap them
|
||||
//note: [tr]x_index will be incremented when done
|
||||
if (rx_index >= max_rx) {
|
||||
triggerEvent(RMAP_NO_RX_DESCRIPTORS, 0);
|
||||
return COMMAND_NO_DESCRIPTORS_AVAILABLE;
|
||||
}
|
||||
if (tx_index >= max_tx) {
|
||||
if (max_tx == 64) {
|
||||
tx_index = 0;
|
||||
} else {
|
||||
triggerEvent(RMAP_NO_TX_DESCRIPTORS, 0);
|
||||
return COMMAND_NO_DESCRIPTORS_AVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
//check if tx descriptor is activated, which means we wrapped the table
|
||||
//and came to a descriptor not yet sent
|
||||
#ifdef LEON
|
||||
asm("flush");
|
||||
#endif
|
||||
if (tx_descriptor_table[tx_index].word0 & (1 << SPW_DESC_TX_ENABLE)) {
|
||||
return COMMAND_NO_DESCRIPTORS_AVAILABLE;
|
||||
}
|
||||
|
||||
//prepare header
|
||||
//set addresses
|
||||
cookie->header.source_address = src_addr;
|
||||
cookie->header.dest_address = dest_addr;
|
||||
//set instruction
|
||||
cookie->header.instruction = instruction;
|
||||
//set the tid
|
||||
cookie->header.tid_l = tid & 0xff;
|
||||
cookie->header.tid_h = (tid >> 8) & 0xff;
|
||||
tid++;
|
||||
//set datalen
|
||||
cookie->header.datalen_l = datalen & 0xff;
|
||||
cookie->header.datalen_m = (datalen >> 8) & 0xff;
|
||||
cookie->header.datalen_h = (datalen >> 16) & 0xff;
|
||||
|
||||
//configure rx_descriptor
|
||||
rx_descriptor_table[rx_index].word1 = (uint32_t) buffer_pointer;
|
||||
rx_descriptor_table[rx_index].word0 = (1 << SPW_DESC_RX_ENABLE);
|
||||
|
||||
//inc buffer
|
||||
if (instruction & (1 << RMAP_COMMAND_BIT_WRITE)) {
|
||||
buffer_pointer += BYTES2WORDS(RMAP_WRITE_REPLY_HEADER_LEN);
|
||||
} else {
|
||||
buffer_pointer += BYTES2WORDS(RMAP_READ_REPLY_HEADER_LEN + datalen + 1); //+1 for crc
|
||||
}
|
||||
|
||||
//configure tx_descriptor
|
||||
tx_descriptor_table[tx_index].word1 = (uint32_t) &cookie->header;
|
||||
if (instruction & (1 << RMAP_COMMAND_BIT_WRITE)) {
|
||||
tx_descriptor_table[tx_index].word2 = datalen & 0xFFFFFF;
|
||||
} else {
|
||||
tx_descriptor_table[tx_index].word2 = 0;
|
||||
}
|
||||
tx_descriptor_table[tx_index].word3 = (uint32_t) data;
|
||||
|
||||
if (instruction & (1 << RMAP_COMMAND_BIT_WRITE)) {
|
||||
tx_descriptor_table[tx_index].word0 = headerlen
|
||||
| (1 << SPW_DESC_TX_ENABLE) | (1 << SPW_DESC_TX_CRC_DATA)
|
||||
| (1 << SPW_DESC_TX_CRC_HEADER);
|
||||
} else {
|
||||
tx_descriptor_table[tx_index].word0 = headerlen
|
||||
| (1 << SPW_DESC_TX_ENABLE) | (1 << SPW_DESC_TX_CRC_HEADER);
|
||||
}
|
||||
|
||||
//remember descriptors to find them faster when looking for the reply
|
||||
cookie->txdesc = &(tx_descriptor_table[tx_index]);
|
||||
cookie->rxdesc_index = rx_index;
|
||||
|
||||
tx_index++;
|
||||
rx_index++;
|
||||
|
||||
//inform the hw about the new descriptors
|
||||
spw_new_rxdesc(port);
|
||||
spw_new_txdesc(port);
|
||||
|
||||
return RETURN_OK;
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t RmapSPWChannel::getReply(RMAPCookie* cookie, uint8_t** databuffer,
|
||||
uint32_t* len) {
|
||||
spw_rx_desc *rxdesc;
|
||||
ReturnValue_t result;
|
||||
uint32_t packetlen;
|
||||
//was the command sent right
|
||||
result = checkTxDesc(cookie);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
//command was sent
|
||||
//find the rx descriptor
|
||||
if ((rxdesc = findReply(cookie)) == NULL) {
|
||||
return REPLY_NO_REPLY;
|
||||
}
|
||||
//reply_header = (rmap_write_reply_header *) rxdesc->word1;
|
||||
if (databuffer != NULL) {
|
||||
packetlen = (rxdesc->word0 & 0x1FFFFFF);
|
||||
*databuffer = ((uint8_t *) rxdesc->word1) + RMAP_READ_REPLY_HEADER_LEN;
|
||||
*len = packetlen - RMAP_READ_REPLY_HEADER_LEN - 1;
|
||||
}
|
||||
result = ((RMAPStructs::rmap_write_reply_header *) (rxdesc->word1))->status;
|
||||
//result is an RMAP standard return code, not a ReturnValue_t, thus we check against 0
|
||||
//and do MAKE_RETURN_CODE(), or set to RETURN_OK respectively
|
||||
//if RETURN_OK == 0, this is not neccessary, but we should not make assumptions on the
|
||||
//value of ReturnValues
|
||||
if (result != 0) {
|
||||
result = ((RMAP::INTERFACE_ID << 8) + (result));
|
||||
} else {
|
||||
result = RETURN_OK;
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t RmapSPWChannel::checkTxDesc(RMAPCookie* cookie) {
|
||||
RMAPStructs::rmap_cmd_header *header_desc;
|
||||
uint16_t tid_desc, tid_cookie;
|
||||
uint32_t status;
|
||||
#ifdef LEON
|
||||
asm("flush");
|
||||
#endif
|
||||
if (cookie->txdesc == NULL) {
|
||||
return REPLY_NOT_SENT;
|
||||
}
|
||||
header_desc =
|
||||
(RMAPStructs::rmap_cmd_header *) ((spw_tx_desc *) cookie->txdesc)->word1;
|
||||
status = ((spw_tx_desc *) cookie->txdesc)->word0
|
||||
& ((1 << SPW_DESC_TX_ENABLE) | (1 << SPW_DESC_TX_LINK_ERROR));
|
||||
tid_cookie = (cookie->header.tid_l) | (cookie->header.tid_h << 8);
|
||||
tid_desc = (header_desc->tid_l) | (header_desc->tid_h << 8);
|
||||
if (tid_cookie != tid_desc) {
|
||||
//tx descriptor was reused, we have no info so let's assume the best
|
||||
return RETURN_OK;
|
||||
}
|
||||
//was command sent or an error seen?
|
||||
if (status == (1 << SPW_DESC_TX_ENABLE)) {
|
||||
return REPLY_NOT_YET_SENT;
|
||||
}
|
||||
if (status & (1 << SPW_DESC_TX_LINK_ERROR)) {
|
||||
triggerEvent(SPW_ERROR, SPW_LINK_ERROR, 0);
|
||||
return REPLY_NOT_SENT;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
spw_rx_desc* RmapSPWChannel::checkRxDesc(RMAPCookie* cookie,
|
||||
uint8_t rxdesc_index) {
|
||||
uint16_t *failureEntry, tid_desc, tid_cookie;
|
||||
spw_rx_desc *rxdesc;
|
||||
RMAPStructs::rmap_read_reply_header *reply_header;
|
||||
|
||||
rxdesc = &rx_descriptor_table[rxdesc_index];
|
||||
failureEntry = &failure_table[rxdesc_index];
|
||||
|
||||
if (!(*failureEntry)) {
|
||||
checkRxDescPacket(rxdesc, failureEntry);
|
||||
}
|
||||
if (*failureEntry != 1 << RMAP_RX_FAIL_CHECKED) {
|
||||
return NULL;
|
||||
}
|
||||
//the packet has been checked and is formally correct
|
||||
//only thing left is to check tid and instruction:
|
||||
|
||||
reply_header = (RMAPStructs::rmap_read_reply_header *) rxdesc->word1;
|
||||
|
||||
tid_cookie = cookie->header.tid_l | (cookie->header.tid_h << 8);
|
||||
tid_desc = reply_header->tid_l | (reply_header->tid_h << 8);
|
||||
if (tid_desc != tid_cookie) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((cookie->header.instruction & 0x3F) != reply_header->instruction) {
|
||||
*failureEntry |= (1 << RMAP_RX_FAIL_WRONG_REPLY);
|
||||
return NULL;
|
||||
}
|
||||
return rxdesc;
|
||||
|
||||
}
|
||||
|
||||
void RmapSPWChannel::checkRxDescPacket(spw_rx_desc* rxdesc,
|
||||
uint16_t* failureEntry) {
|
||||
uint32_t statusword, len;
|
||||
|
||||
#ifdef LEON
|
||||
asm("flush");
|
||||
#endif
|
||||
|
||||
statusword = rxdesc->word0;
|
||||
|
||||
if ((statusword & (1 << SPW_DESC_RX_ENABLE)) || (statusword == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
*failureEntry = 1 << RMAP_RX_FAIL_CHECKED;
|
||||
|
||||
if (statusword & (1 << SPW_DESC_RX_EEP)) {
|
||||
*failureEntry |= (1 << RMAP_RX_FAIL_EEP);
|
||||
return;
|
||||
}
|
||||
|
||||
if (statusword & (1 << SPW_DESC_RX_TRUNCATED)) {
|
||||
*failureEntry |= (1 << RMAP_RX_FAIL_TRUNC);
|
||||
return;
|
||||
}
|
||||
|
||||
len = statusword & 0x1FFFFFF;
|
||||
if (!(len >= 13 || len == 8)) {
|
||||
*failureEntry |= (1 << RMAP_RX_FAIL_LEN);
|
||||
return;
|
||||
}
|
||||
if (checkCrc((uint8_t*) rxdesc->word1, len) != RETURN_OK) {
|
||||
*failureEntry |= (1 << RMAP_RX_FAIL_CRC);
|
||||
return;
|
||||
}
|
||||
|
||||
checkRmapHeader((void *) rxdesc->word1, len, failureEntry);
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t RmapSPWChannel::checkCrc(uint8_t* packet, uint32_t len) {
|
||||
if (len == 8) {
|
||||
if (crc_calculate(packet, len) == 0) {
|
||||
return RETURN_OK;
|
||||
} else {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
} else {
|
||||
if ((crc_calculate(packet, RMAP_READ_REPLY_HEADER_LEN) == 0)
|
||||
&& (crc_calculate(packet, len) == 0)) {
|
||||
return RETURN_OK;
|
||||
} else {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RmapSPWChannel::checkRmapHeader(void* _header, uint32_t len,
|
||||
uint16_t* failureEntry) {
|
||||
RMAPStructs::rmap_read_reply_header *header =
|
||||
(RMAPStructs::rmap_read_reply_header *) _header;
|
||||
uint32_t datalen;
|
||||
|
||||
if (header->dest_address != src_addr) {
|
||||
*failureEntry |= (1 << RMAP_RX_FAIL_DST_ADDR);
|
||||
}
|
||||
|
||||
if (header->protocol != 0x01) {
|
||||
*failureEntry |= (1 << RMAP_RX_FAIL_PROTO);
|
||||
}
|
||||
|
||||
if (header->instruction & 0xC0) {
|
||||
*failureEntry |= (1 << RMAP_RX_FAIL_INSTR_TYPE);
|
||||
} else { //hope that works...
|
||||
if ((!(header->instruction & (1 << RMAP_COMMAND_BIT_REPLY)))
|
||||
|| ((header->instruction & (1 << RMAP_COMMAND_BIT_VERIFY))
|
||||
&& (!(header->instruction
|
||||
& (1 << RMAP_COMMAND_BIT_WRITE))))
|
||||
|| (header->instruction & 3)) {
|
||||
if (header->status == REPLY_UNUSED_PACKET_TYPE_OR_COMMAND_CODE) {
|
||||
*failureEntry |= (1 << RMAP_RX_FAIL_INSTR);
|
||||
} else {
|
||||
*failureEntry |= (1 << RMAP_RX_FAIL_INSTR_TYPE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (header->instruction & (1 << RMAP_COMMAND_BIT_WRITE)) {
|
||||
if (len != 8) {
|
||||
*failureEntry |= (1 << RMAP_RX_FAIL_INSTR_TYPE);
|
||||
}
|
||||
} else {
|
||||
if (len == 8) {
|
||||
*failureEntry |= (1 << RMAP_RX_FAIL_INSTR_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
if (header->source_address != dest_addr) {
|
||||
*failureEntry |= (1 << RMAP_RX_FAIL_SRC_ADDR);
|
||||
}
|
||||
|
||||
if (len != 8) {
|
||||
datalen = header->datalen_l | (header->datalen_m << 8)
|
||||
| (header->datalen_h << 16);
|
||||
if (datalen + RMAP_READ_REPLY_HEADER_LEN + 1 != len) {
|
||||
*failureEntry |= (1 << RMAP_RX_FAIL_LEN_MISSMATCH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t RmapSPWChannel::sendCommandBlocking(RMAPCookie *cookie,
|
||||
uint8_t *data, uint32_t datalen, uint8_t **databuffer, uint32_t *len,
|
||||
uint32_t timeout_us) {
|
||||
uint32_t time;
|
||||
ReturnValue_t result;
|
||||
if (databuffer != NULL) {
|
||||
result = sendReadCommand(cookie, datalen);
|
||||
} else {
|
||||
result = sendWriteCommand(cookie, data, datalen);
|
||||
}
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
time = hw_timer_get_us();
|
||||
while (time - hw_timer_get_us() < timeout_us) {
|
||||
result = getReply(cookie, databuffer, len);
|
||||
if (!((result == REPLY_NOT_YET_SENT) || (result == REPLY_NO_REPLY))) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (result == REPLY_NOT_YET_SENT) {
|
||||
return result;
|
||||
}
|
||||
return REPLY_TIMEOUT;
|
||||
}
|
||||
|
||||
//SHOULDDO find a better way to inject the Extended address
|
||||
#include <config/hardware/IoBoardAddresses.h>
|
||||
ReturnValue_t RmapSPWChannel::open(Cookie **cookie, uint32_t address,
|
||||
uint32_t maxReplyLen) {
|
||||
*cookie = new RMAPCookie(address, IoBoardExtendedAddresses::DEVICE_BUFFER,
|
||||
this, 0, maxReplyLen);
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t RmapSPWChannel::reOpen(Cookie* cookie, uint32_t address,
|
||||
uint32_t maxReplyLen) {
|
||||
ReturnValue_t result = isActive();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
RMAPCookie *rCookie = dynamic_cast<RMAPCookie *>(cookie);
|
||||
if (rCookie == NULL) {
|
||||
return INVALID_COOKIE_TYPE;
|
||||
}
|
||||
rCookie->setAddress(address);
|
||||
rCookie->setChannel(this);
|
||||
rCookie->setCommandMask(0);
|
||||
rCookie->setExtendedAddress(IoBoardExtendedAddresses::DEVICE_BUFFER);
|
||||
rCookie->setMaxReplyLen(maxReplyLen);
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void RmapSPWChannel::close(Cookie* cookie) {
|
||||
delete cookie;
|
||||
}
|
||||
|
||||
ReturnValue_t RmapSPWChannel::sendMessage(Cookie* cookie, uint8_t* data,
|
||||
uint32_t len) {
|
||||
return sendWriteCommand((RMAPCookie *) cookie, data, len);
|
||||
}
|
||||
|
||||
ReturnValue_t RmapSPWChannel::getSendSuccess(Cookie* cookie) {
|
||||
return getWriteReply((RMAPCookie *) cookie);
|
||||
}
|
||||
|
||||
ReturnValue_t RmapSPWChannel::requestReceiveMessage(Cookie* cookie) {
|
||||
return sendReadCommand((RMAPCookie *) cookie,
|
||||
((RMAPCookie *) cookie)->getMaxReplyLen());
|
||||
}
|
||||
|
||||
ReturnValue_t RmapSPWChannel::readReceivedMessage(Cookie* cookie,
|
||||
uint8_t** buffer, uint32_t* size) {
|
||||
return getReadReply((RMAPCookie *) cookie, buffer, size);
|
||||
}
|
||||
|
||||
ReturnValue_t RmapSPWChannel::setAddress(Cookie* cookie, uint32_t address) {
|
||||
((RMAPCookie *) cookie)->setAddress(address);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
uint32_t RmapSPWChannel::getAddress(Cookie* cookie) {
|
||||
return ((RMAPCookie *) cookie)->getAddress();
|
||||
}
|
||||
|
||||
ReturnValue_t RmapSPWChannel::setParameter(Cookie* cookie, uint32_t parameter) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
uint32_t RmapSPWChannel::getParameter(Cookie* cookie) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RmapSPWChannel::reportFailures(uint16_t failureEntry,
|
||||
uint8_t descriptorNr) {
|
||||
if (failureEntry & (1 << RMAP_RX_FAIL_CRC)) {
|
||||
triggerEvent(RMAP_PROTOCOL_ERROR, REPLY_INVALID_DATA_CRC, descriptorNr);
|
||||
}
|
||||
if (failureEntry & (1 << RMAP_RX_FAIL_DST_ADDR)) {
|
||||
triggerEvent(RMAP_PROTOCOL_ERROR, REPLY_INVALID_TARGET_LOGICAL_ADDRESS,
|
||||
descriptorNr);
|
||||
}
|
||||
if (failureEntry & (1 << RMAP_RX_FAIL_EEP)) {
|
||||
triggerEvent(RMAP_PROTOCOL_ERROR, REPLY_EEP, descriptorNr);
|
||||
}
|
||||
if (failureEntry & (1 << RMAP_RX_FAIL_INSTR)) {
|
||||
triggerEvent(RMAP_PROTOCOL_ERROR,
|
||||
REPLY_COMMAND_NOT_IMPLEMENTED_OR_NOT_AUTHORISED, descriptorNr);
|
||||
}
|
||||
if (failureEntry & (1 << RMAP_RX_FAIL_INSTR_TYPE)) {
|
||||
triggerEvent(RMAP_PROTOCOL_ERROR, REPLY_RESERVED, descriptorNr);
|
||||
}
|
||||
if (failureEntry & (1 << RMAP_RX_FAIL_LEN)) {
|
||||
triggerEvent(RMAP_PROTOCOL_ERROR, REPLY_TOO_MUCH_DATA, descriptorNr);
|
||||
}
|
||||
if (failureEntry & (1 << RMAP_RX_FAIL_LEN_MISSMATCH)) {
|
||||
triggerEvent(RMAP_PROTOCOL_ERROR, REPLY_INVALID_DATA, descriptorNr);
|
||||
}
|
||||
if (failureEntry & (1 << RMAP_RX_FAIL_PROTO)) {
|
||||
triggerEvent(RMAP_PROTOCOL_ERROR, REPLY_GENERAL_ERROR_CODE,
|
||||
descriptorNr);
|
||||
}
|
||||
if (failureEntry & (1 << RMAP_RX_FAIL_SRC_ADDR)) {
|
||||
triggerEvent(RMAP_PROTOCOL_ERROR, REPLY_GENERAL_ERROR_CODE,
|
||||
descriptorNr);
|
||||
}
|
||||
if (failureEntry & (1 << RMAP_RX_FAIL_TRUNC)) {
|
||||
triggerEvent(RMAP_PROTOCOL_ERROR, REPLY_TRANSMISSION_ERROR,
|
||||
descriptorNr);
|
||||
}
|
||||
if (failureEntry & (1 << RMAP_RX_FAIL_WRONG_REPLY)) {
|
||||
triggerEvent(RMAP_PROTOCOL_ERROR, REPLY_INVALID_KEY, descriptorNr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RmapSPWChannel::reportSpwstr(uint32_t spwstr) {
|
||||
if (spwstr & (1 << SPW_SPWSTR_CE)) {
|
||||
triggerEvent(SPW_ERROR, SPW_CREDIT);
|
||||
}
|
||||
if (spwstr & (1 << SPW_SPWSTR_ER)) {
|
||||
triggerEvent(SPW_ERROR, SPW_ESCAPE);
|
||||
}
|
||||
if (spwstr & (1 << SPW_SPWSTR_DE)) {
|
||||
triggerEvent(SPW_ERROR, SPW_DISCONNECT);
|
||||
}
|
||||
if (spwstr & (1 << SPW_SPWSTR_PE)) {
|
||||
triggerEvent(SPW_ERROR, SPW_PARITY);
|
||||
}
|
||||
if (spwstr & (1 << SPW_SPWSTR_WE)) {
|
||||
triggerEvent(SPW_ERROR, SPW_WRITE_SYNC);
|
||||
}
|
||||
if (spwstr & (1 << SPW_SPWSTR_IA)) {
|
||||
triggerEvent(SPW_ERROR, SPW_INVALID_ADDRESS);
|
||||
}
|
||||
if (spwstr & (1 << SPW_SPWSTR_EE)) {
|
||||
triggerEvent(SPW_ERROR, SPW_EARLY_EOP);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t RmapSPWChannel::null_crc = 0;
|
||||
|
||||
int8_t RmapSPWChannel::getCurrentPortNr() {
|
||||
uint8_t i;
|
||||
int8_t oldport = -1;
|
||||
for (i = 0; i < SPW_devices.len; ++i) {
|
||||
if (SPW_devices.devices[i] == this->port) {
|
||||
oldport = i;
|
||||
}
|
||||
}
|
||||
return oldport;
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
#ifndef RMAPCHANNEL_H_
|
||||
#define RMAPCHANNEL_H_
|
||||
|
||||
#include <framework/objectmanager/SystemObject.h>
|
||||
#include <framework/rmap/RMAPChannelIF.h>
|
||||
extern "C" {
|
||||
#include <bsp_flp/spw/spw.h>
|
||||
}
|
||||
#include <config/datapool/dataPoolInit.h>
|
||||
#include <framework/devicehandlers/DeviceCommunicationIF.h>
|
||||
#include <framework/events/Event.h>
|
||||
#include <framework/tasks/PeriodicTaskIF.h>
|
||||
|
||||
class RmapSPWChannel: public SystemObject,
|
||||
public RMAPChannelIF,
|
||||
public DeviceCommunicationIF {
|
||||
public:
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CDH_1;
|
||||
static const Event SPW_ERROR = MAKE_EVENT(0, SEVERITY::LOW);
|
||||
static const Event SPW_LINK_DOWN = MAKE_EVENT(1, SEVERITY::LOW);
|
||||
// static const Event SPW_CREDIT = MAKE_EVENT(1, SEVERITY::LOW);
|
||||
// static const Event SPW_ESCAPE = MAKE_EVENT(2, SEVERITY::LOW);
|
||||
// static const Event SPW_DISCONNECT = MAKE_EVENT(3, SEVERITY::LOW);
|
||||
// static const Event SPW_PARITY = MAKE_EVENT(4, SEVERITY::LOW);
|
||||
// static const Event SPW_WRITE_SYNC = MAKE_EVENT(5, SEVERITY::LOW);
|
||||
// static const Event SPW_INVALID_ADDRESS = MAKE_EVENT(6, SEVERITY::LOW);
|
||||
// static const Event SPW_EARLY_EOP = MAKE_EVENT(7, SEVERITY::LOW);
|
||||
// static const Event SPW_DMA = MAKE_EVENT(8, SEVERITY::LOW);
|
||||
// static const Event SPW_LINK_ERROR = MAKE_EVENT(9, SEVERITY::LOW);
|
||||
static const Event RMAP_PROTOCOL_ERROR = MAKE_EVENT(10, SEVERITY::LOW);
|
||||
// static const Event RMAP_CRC = MAKE_EVENT(10, SEVERITY::LOW);
|
||||
// static const Event RMAP_DST_ADDR = MAKE_EVENT(11, SEVERITY::LOW);
|
||||
// static const Event RMAP_EEP = MAKE_EVENT(12, SEVERITY::LOW);
|
||||
// static const Event RMAP_INSTR = MAKE_EVENT(13, SEVERITY::LOW);
|
||||
// static const Event RMAP_INSTR_TYPE = MAKE_EVENT(14, SEVERITY::LOW);
|
||||
// static const Event RMAP_LEN = MAKE_EVENT(15, SEVERITY::LOW);
|
||||
// static const Event RMAP_LEN_MISSMATCH = MAKE_EVENT(16, SEVERITY::LOW);
|
||||
// static const Event RMAP_PROTO = MAKE_EVENT(17, SEVERITY::LOW);
|
||||
// static const Event RMAP_SRC_ADDR = MAKE_EVENT(18, SEVERITY::LOW);
|
||||
// static const Event RMAP_TRUNC = MAKE_EVENT(19, SEVERITY::LOW);
|
||||
// static const Event RMAP_WRONG_REPLY = MAKE_EVENT(20, SEVERITY::LOW);
|
||||
static const Event RMAP_MISSED_REPLIES = MAKE_EVENT(21, SEVERITY::LOW);
|
||||
static const Event RMAP_NO_RX_DESCRIPTORS = MAKE_EVENT(22, SEVERITY::LOW);
|
||||
static const Event RMAP_NO_TX_DESCRIPTORS = MAKE_EVENT(23, SEVERITY::LOW);
|
||||
static const Event RMAP_SWITCHED_PORT = MAKE_EVENT(24, SEVERITY::INFO);
|
||||
|
||||
RmapSPWChannel(object_id_t setObjectId, uint16_t buffersize_words,
|
||||
uint32_t maxPacketSize, int8_t portNr, uint8_t dest_addr,
|
||||
uint8_t src_addr, PeriodicTaskIF* currentTask, datapool::opus_variable_id portVariable =
|
||||
datapool::NO_PARAMETER);
|
||||
|
||||
virtual ~RmapSPWChannel();
|
||||
|
||||
virtual ReturnValue_t reset();
|
||||
|
||||
virtual ReturnValue_t isActive();
|
||||
|
||||
virtual ReturnValue_t setPort(int8_t port, uint8_t dest_addr,
|
||||
uint8_t src_addr, PeriodicTaskIF* currentTask);
|
||||
|
||||
virtual ReturnValue_t setPort(int8_t port, PeriodicTaskIF* currentTask);
|
||||
|
||||
virtual ReturnValue_t sendCommand(RMAPCookie *cookie, uint8_t instruction,
|
||||
uint8_t *data, uint32_t datalen);
|
||||
virtual ReturnValue_t getReply(RMAPCookie *cookie, uint8_t **databuffer,
|
||||
uint32_t *len);
|
||||
virtual ReturnValue_t sendCommandBlocking(RMAPCookie *cookie, uint8_t *data,
|
||||
uint32_t datalen, uint8_t **databuffer, uint32_t *len,
|
||||
uint32_t timeout_us);
|
||||
|
||||
virtual ReturnValue_t open(Cookie **cookie, uint32_t address,
|
||||
uint32_t maxReplyLen);
|
||||
|
||||
virtual ReturnValue_t reOpen(Cookie *cookie, uint32_t address,
|
||||
uint32_t maxReplyLen);
|
||||
|
||||
virtual void close(Cookie *cookie);
|
||||
|
||||
virtual ReturnValue_t sendMessage(Cookie *cookie, uint8_t *data,
|
||||
uint32_t len);
|
||||
|
||||
virtual ReturnValue_t getSendSuccess(Cookie *cookie);
|
||||
|
||||
virtual ReturnValue_t requestReceiveMessage(Cookie *cookie);
|
||||
|
||||
virtual ReturnValue_t readReceivedMessage(Cookie *cookie, uint8_t **buffer,
|
||||
uint32_t *size);
|
||||
|
||||
virtual ReturnValue_t setAddress(Cookie *cookie, uint32_t address);
|
||||
|
||||
virtual uint32_t getAddress(Cookie *cookie);
|
||||
|
||||
virtual ReturnValue_t setParameter(Cookie *cookie, uint32_t parameter);
|
||||
|
||||
virtual uint32_t getParameter(Cookie *cookie);
|
||||
|
||||
private:
|
||||
|
||||
SPW_dev *port;
|
||||
uint32_t *buffer;
|
||||
uint32_t *buffer_pointer; //points to the next free space in the buffer
|
||||
uint32_t *end_of_buffer; //points to the word AFTER the buffer
|
||||
spw_tx_desc *tx_descriptor_table;
|
||||
spw_rx_desc *rx_descriptor_table;
|
||||
uint16_t *failure_table;
|
||||
uint32_t max_packet_len;
|
||||
uint16_t tid;
|
||||
// uint8_t port_has_crc;
|
||||
uint8_t rx_index; //index of the next unused rx descriptor
|
||||
uint8_t max_rx;
|
||||
uint8_t tx_index; //index of the next unused tx descriptor
|
||||
uint8_t max_tx;
|
||||
uint8_t src_addr;
|
||||
uint8_t dest_addr;
|
||||
|
||||
datapool::opus_variable_id portPoolId;
|
||||
|
||||
static uint8_t null_crc;
|
||||
|
||||
spw_rx_desc *findReply(RMAPCookie *cookie);
|
||||
ReturnValue_t checkTxDesc(RMAPCookie *cookie);
|
||||
spw_rx_desc *checkRxDesc(RMAPCookie *cookie, uint8_t rxdesc_index);
|
||||
void checkRxDescPacket(spw_rx_desc *rxdesc, uint16_t *failureEntry);
|
||||
|
||||
ReturnValue_t checkCrc(uint8_t *packet, uint32_t len);
|
||||
|
||||
void checkRmapHeader(void *_header, uint32_t len, uint16_t *failureEntry);
|
||||
|
||||
void reportFailures(uint16_t failureEntry, uint8_t descriptorNr);
|
||||
void reportSpwstr(uint32_t spwstr);
|
||||
int8_t getCurrentPortNr();
|
||||
|
||||
};
|
||||
|
||||
#endif /* RMAPCHANNEL_H_ */
|
@ -7,28 +7,45 @@
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// RMAP command bits
|
||||
#define RMAP_COMMAND_BIT_INCREMENT 2
|
||||
#define RMAP_COMMAND_BIT_REPLY 3
|
||||
#define RMAP_COMMAND_BIT_WRITE 5
|
||||
#define RMAP_COMMAND_BIT_VERIFY 4
|
||||
#define RMAP_COMMAND_BIT 6
|
||||
//#define RMAP_COMMAND_BIT_INCREMENT 2
|
||||
//#define RMAP_COMMAND_BIT_REPLY 3
|
||||
//#define RMAP_COMMAND_BIT_WRITE 5
|
||||
//#define RMAP_COMMAND_BIT_VERIFY 4
|
||||
//#define RMAP_COMMAND_BIT 6
|
||||
|
||||
namespace RMAPIds{
|
||||
|
||||
static const uint8_t RMAP_COMMAND_BIT_INCREMENT = 2;
|
||||
static const uint8_t RMAP_COMMAND_BIT_REPLY = 3;
|
||||
static const uint8_t RMAP_COMMAND_BIT_WRITE = 5;
|
||||
static const uint8_t RMAP_COMMAND_BIT_VERIFY = 4;
|
||||
static const uint8_t RMAP_COMMAND_BIT = 6;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// RMAP commands
|
||||
|
||||
#define RMAP_COMMAND_WRITE ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY))
|
||||
static const uint8_t RMAP_COMMAND_WRITE = ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY));
|
||||
static const uint8_t RMAP_COMMAND_READ = ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_REPLY));
|
||||
static const uint8_t RMAP_REPLY_WRITE = ((1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY));
|
||||
static const uint8_t RMAP_REPLY_READ = ((1<<RMAP_COMMAND_BIT_REPLY));
|
||||
//#define RMAP_COMMAND_WRITE ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY))
|
||||
//#define RMAP_COMMAND_WRITE_VERIFY ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY) | (1<<RMAP_COMMAND_BIT_VERIFY))
|
||||
#define RMAP_COMMAND_READ ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_REPLY))
|
||||
//#define RMAP_COMMAND_READ ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_REPLY))
|
||||
|
||||
#define RMAP_REPLY_WRITE ((1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY))
|
||||
//#define RMAP_REPLY_WRITE ((1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY))
|
||||
//#define RMAP_REPLY_WRITE_VERIFY ((1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY) | (1<<RMAP_COMMAND_BIT_VERIFY))
|
||||
#define RMAP_REPLY_READ ((1<<RMAP_COMMAND_BIT_REPLY))
|
||||
//#define RMAP_REPLY_READ ((1<<RMAP_COMMAND_BIT_REPLY))
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// useful info
|
||||
#define RMAP_COMMAND_HEADER_LEN 16
|
||||
#define RMAP_WRITE_REPLY_HEADER_LEN 8
|
||||
#define RMAP_READ_REPLY_HEADER_LEN 12
|
||||
static const uint8_t RMAP_COMMAND_HEADER_LEN = 16;
|
||||
static const uint8_t RMAP_WRITE_REPLY_HEADER_LEN = 8;
|
||||
static const uint8_t RMAP_READ_REPLY_HEADER_LEN = 12;
|
||||
static const uint8_t RMAP_DATA_FOOTER_SIZE = 1; //SIZE OF CRC
|
||||
//#define RMAP_COMMAND_HEADER_LEN 16
|
||||
//#define RMAP_WRITE_REPLY_HEADER_LEN 8
|
||||
//#define RMAP_READ_REPLY_HEADER_LEN 12
|
||||
|
||||
}
|
||||
|
||||
namespace RMAPStructs {
|
||||
struct rmap_cmd_header {
|
||||
|
@ -1,9 +1,9 @@
|
||||
#ifndef ENDIANSWAPPER_H_
|
||||
#define ENDIANSWAPPER_H_
|
||||
|
||||
//#include <endian.h> //for testing on x86
|
||||
#include <framework/osal/Endiness.h>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
class EndianSwapper {
|
||||
private:
|
||||
@ -13,9 +13,9 @@ private:
|
||||
public:
|
||||
template<typename T>
|
||||
static T swap(T in) {
|
||||
#ifndef BYTE_ORDER
|
||||
#error BYTE_ORDER not defined
|
||||
#elif BYTE_ORDER == LITTLE_ENDIAN
|
||||
#ifndef BYTE_ORDER_SYSTEM
|
||||
#error BYTE_ORDER_SYSTEM not defined
|
||||
#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
|
||||
T tmp;
|
||||
uint8_t *pointerOut = (uint8_t *) &tmp;
|
||||
uint8_t *pointerIn = (uint8_t *) ∈
|
||||
@ -23,21 +23,21 @@ public:
|
||||
pointerOut[sizeof(T) - count - 1] = pointerIn[count];
|
||||
}
|
||||
return tmp;
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
|
||||
return in;
|
||||
#else
|
||||
#error Unknown Byte Order
|
||||
#endif
|
||||
}
|
||||
static void swap(uint8_t* out, const uint8_t* in, uint32_t size) {
|
||||
#ifndef BYTE_ORDER
|
||||
#error BYTE_ORDER not defined
|
||||
#elif BYTE_ORDER == LITTLE_ENDIAN
|
||||
#ifndef BYTE_ORDER_SYSTEM
|
||||
#error BYTE_ORDER_SYSTEM not defined
|
||||
#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
|
||||
for (uint8_t count = 0; count < size; count++) {
|
||||
out[size - count - 1] = in[count];
|
||||
}
|
||||
return;
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
|
||||
memcpy(out, in, size);
|
||||
return;
|
||||
#endif
|
||||
|
@ -39,6 +39,7 @@ int ServiceInterfaceBuffer::sync(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef UT699
|
||||
|
||||
ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port) {
|
||||
this->log_message = set_message;
|
||||
@ -59,8 +60,11 @@ void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) {
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UT699
|
||||
#include <framework/osal/rtems/Interrupt.h>
|
||||
|
||||
ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port) {
|
||||
this->log_message = set_message;
|
||||
this->isActive = true;
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <sstream>
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
#ifndef UT699
|
||||
class ServiceInterfaceBuffer: public std::basic_streambuf<char,
|
||||
std::char_traits<char> > {
|
||||
friend class ServiceInterfaceStream;
|
||||
@ -36,7 +36,7 @@ private:
|
||||
// In this function, the characters are parsed.
|
||||
void putChars(char const* begin, char const* end);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
@ -12,8 +12,7 @@
|
||||
|
||||
|
||||
#include <framework/storagemanager/LocalPool.h>
|
||||
#include <framework/ipc/MutexIF.h>
|
||||
#include <framework/ipc/MutexFactory.h>
|
||||
#include <framework/ipc/MutexHelper.h>
|
||||
|
||||
/**
|
||||
* @brief The PoolManager class provides an intermediate data storage with
|
||||
@ -50,20 +49,10 @@ public:
|
||||
|
||||
template<uint8_t NUMBER_OF_POOLS>
|
||||
inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::reserveSpace(const uint32_t size, store_address_t* address, bool ignoreFault) {
|
||||
ReturnValue_t mutexStatus = mutex->lockMutex(MutexIF::NO_TIMEOUT);
|
||||
ReturnValue_t status = this->DATA_STORAGE_FULL;
|
||||
if ( mutexStatus == this->RETURN_OK ) {
|
||||
status = LocalPool<NUMBER_OF_POOLS>::reserveSpace(size,address,ignoreFault);
|
||||
} else {
|
||||
error << "PoolManager::findEmpty: Mutex could not be acquired. Error code: " << mutexStatus << std::endl;
|
||||
}
|
||||
mutexStatus = mutex->lockMutex(MutexIF::NO_TIMEOUT);
|
||||
if (mutexStatus != this->RETURN_OK) {
|
||||
return mutexStatus;
|
||||
} else {
|
||||
MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT);
|
||||
ReturnValue_t status = LocalPool<NUMBER_OF_POOLS>::reserveSpace(size,address,ignoreFault);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
template<uint8_t NUMBER_OF_POOLS>
|
||||
inline PoolManager<NUMBER_OF_POOLS>::PoolManager(object_id_t setObjectId,
|
||||
@ -81,37 +70,17 @@ template<uint8_t NUMBER_OF_POOLS>
|
||||
inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::deleteData(
|
||||
store_address_t packet_id) {
|
||||
// debug << "PoolManager( " << translateObject(getObjectId()) << " )::deleteData from store " << packet_id.pool_index << ". id is " << packet_id.packet_index << std::endl;
|
||||
ReturnValue_t mutexStatus = mutex->lockMutex(MutexIF::NO_TIMEOUT);
|
||||
ReturnValue_t status = this->RETURN_OK;
|
||||
if ( mutexStatus == this->RETURN_OK ) {
|
||||
LocalPool<NUMBER_OF_POOLS>::deleteData(packet_id);
|
||||
} else {
|
||||
error << "PoolManager:deleteData: Mutex could not be acquired. Error code: " << status << std::endl;
|
||||
}
|
||||
mutexStatus = mutex->lockMutex(MutexIF::NO_TIMEOUT);
|
||||
if (mutexStatus != this->RETURN_OK) {
|
||||
return mutexStatus;
|
||||
} else {
|
||||
MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT);
|
||||
ReturnValue_t status = LocalPool<NUMBER_OF_POOLS>::deleteData(packet_id);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
template<uint8_t NUMBER_OF_POOLS>
|
||||
inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::deleteData(uint8_t* buffer, uint32_t size,
|
||||
store_address_t* storeId) {
|
||||
ReturnValue_t mutexStatus = mutex->lockMutex(MutexIF::NO_TIMEOUT);
|
||||
ReturnValue_t status = this->RETURN_OK;
|
||||
if ( mutexStatus == this->RETURN_OK ) {
|
||||
LocalPool<NUMBER_OF_POOLS>::deleteData(buffer, size, storeId);
|
||||
} else {
|
||||
error << "PoolManager:deleteData: Mutex could not be acquired. Error code: " << status << std::endl;
|
||||
}
|
||||
mutexStatus = mutex->lockMutex(MutexIF::NO_TIMEOUT);
|
||||
if (mutexStatus != this->RETURN_OK) {
|
||||
return mutexStatus;
|
||||
} else {
|
||||
MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT);
|
||||
ReturnValue_t status = LocalPool<NUMBER_OF_POOLS>::deleteData(buffer, size, storeId);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* POOLMANAGER_H_ */
|
||||
|
@ -8,7 +8,7 @@ SubsystemBase::SubsystemBase(object_id_t setObjectId, object_id_t parent,
|
||||
SystemObject(setObjectId), mode(initialMode), submode(SUBMODE_NONE), childrenChangedMode(
|
||||
false), commandsOutstanding(0), commandQueue(NULL), healthHelper(this,
|
||||
setObjectId), modeHelper(this), parentId(parent) {
|
||||
QueueFactory::instance()->createMessageQueue(commandQueueDepth,
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth,
|
||||
CommandMessage::MAX_MESSAGE_SIZE);
|
||||
}
|
||||
|
||||
|
@ -11,10 +11,11 @@
|
||||
#ifndef EXECUTABLEOBJECTIF_H_
|
||||
#define EXECUTABLEOBJECTIF_H_
|
||||
|
||||
|
||||
#include <framework/osal/OperatingSystemIF.h>
|
||||
class PeriodicTaskIF;
|
||||
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
|
||||
#include <cstring>
|
||||
/**
|
||||
* @brief The interface provides a method to execute objects within a task.
|
||||
* @details The performOperation method, that is required by the interface is
|
||||
@ -34,7 +35,15 @@ public:
|
||||
*/
|
||||
virtual ReturnValue_t performOperation(uint8_t operationCode = 0) = 0;
|
||||
|
||||
virtual void setTaskIF(PeriodicTaskIF* interface) {};
|
||||
/**
|
||||
* @brief Function called during setup assignment of object to task
|
||||
* @details Has to be called from the function that assigns the object to a task and
|
||||
* enables the object implementation to overwrite this function and get a reference to the executing task
|
||||
* @param task_ Pointer to the taskIF of this task
|
||||
*/
|
||||
virtual void setTaskIF(PeriodicTaskIF* task_) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* EXECUTABLEOBJECTIF_H_ */
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define PERIODICTASKIF_H_
|
||||
|
||||
#include <framework/objectmanager/SystemObjectIF.h>
|
||||
#include <cstddef>
|
||||
class ExecutableObjectIF;
|
||||
/**
|
||||
* New version of TaskIF
|
||||
@ -10,7 +11,7 @@ class ExecutableObjectIF;
|
||||
*/
|
||||
class PeriodicTaskIF {
|
||||
public:
|
||||
static const uint64_t MINIMUM_STACK_SIZE;
|
||||
static const size_t MINIMUM_STACK_SIZE;
|
||||
/**
|
||||
* @brief A virtual destructor as it is mandatory for interfaces.
|
||||
*/
|
||||
@ -20,7 +21,7 @@ public:
|
||||
*/
|
||||
virtual ReturnValue_t startTask() = 0;
|
||||
|
||||
virtual ReturnValue_t addComponent(object_id_t) {return HasReturnvaluesIF::RETURN_FAILED;};
|
||||
virtual ReturnValue_t addComponent(object_id_t object) {return HasReturnvaluesIF::RETURN_FAILED;};
|
||||
|
||||
virtual ReturnValue_t sleepFor(uint32_t ms) = 0;
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
//TODO more generic?
|
||||
typedef const char* TaskName;
|
||||
typedef uint8_t TaskPriority;
|
||||
typedef uint16_t TaskStackSize;
|
||||
typedef size_t TaskStackSize;
|
||||
typedef double TaskPeriod;
|
||||
typedef void (*TaskDeadlineMissedFunction)();
|
||||
|
||||
|
@ -52,7 +52,8 @@ ReturnValue_t PUSDistributor::registerService(AcceptsTelecommandsIF* service) {
|
||||
errorCode = this->queueMap.insert(
|
||||
std::pair<uint32_t, MessageQueueId_t>(serviceId, queue)).second;
|
||||
if (errorCode == false) {
|
||||
returnValue = OperatingSystemIF::RESOURCE_IN_USE;
|
||||
//TODO Return Code
|
||||
returnValue = MessageQueueIF::NO_QUEUE;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ ReturnValue_t TcDistributor::performOperation(uint8_t opCode) {
|
||||
status = tcQueue->receiveMessage(¤tMessage)) {
|
||||
status = handlePacket();
|
||||
}
|
||||
if (status == OperatingSystemIF::QUEUE_EMPTY) {
|
||||
if (status == MessageQueueIF::EMPTY) {
|
||||
return RETURN_OK;
|
||||
} else {
|
||||
return status;
|
||||
|
@ -2,7 +2,6 @@
|
||||
#define TCDISTRIBUTOR_H_
|
||||
#include <framework/objectmanager/ObjectManagerIF.h>
|
||||
#include <framework/objectmanager/SystemObject.h>
|
||||
#include <framework/osal/OperatingSystemIF.h>
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <framework/storagemanager/StorageManagerIF.h>
|
||||
#include <framework/tasks/ExecutableObjectIF.h>
|
||||
|
@ -45,7 +45,7 @@ ReturnValue_t CCSDSTime::convertToCcsds(Ccs_mseconds* to,
|
||||
to->minute = from->minute;
|
||||
to->second = from->second;
|
||||
to->secondEminus2 = from->usecond / 10000;
|
||||
to->secondEminus4 = (from->usecond % 10) * 10 / 1000;
|
||||
to->secondEminus4 = (from->usecond % 10000) / 100;
|
||||
|
||||
return RETURN_OK;
|
||||
}
|
||||
@ -142,7 +142,7 @@ ReturnValue_t CCSDSTime::convertFromCCS(Clock::TimeOfDay_t* to, const uint8_t* f
|
||||
if (temp->secondEminus4 >= 100) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
}
|
||||
to->usecond += temp->secondEminus4 / 10 * 1000;
|
||||
to->usecond += temp->secondEminus4 * 100;
|
||||
}
|
||||
|
||||
return RETURN_OK;
|
||||
|
@ -49,6 +49,16 @@ public:
|
||||
|
||||
virtual ReturnValue_t initialize();
|
||||
|
||||
/**
|
||||
* Implementation of ExecutableObjectIF function
|
||||
*
|
||||
* Used to setup the reference of the task, that executes this component
|
||||
* @param task_ Pointer to the taskIF of this task
|
||||
*/
|
||||
virtual void setTaskIF(PeriodicTaskIF* task_){
|
||||
executingTask = task_;
|
||||
};
|
||||
|
||||
protected:
|
||||
struct CommandInfo {
|
||||
struct tcInfo {
|
||||
@ -92,6 +102,11 @@ protected:
|
||||
|
||||
object_id_t packetDestination;
|
||||
|
||||
/**
|
||||
* Pointer to the task which executes this component, is invalid before setTaskIF was called.
|
||||
*/
|
||||
PeriodicTaskIF* executingTask;
|
||||
|
||||
void sendTmPacket(uint8_t subservice, const uint8_t *data, uint32_t dataLen,
|
||||
const uint8_t* headerData = NULL, uint32_t headerSize = 0);
|
||||
void sendTmPacket(uint8_t subservice, object_id_t objectId,
|
||||
@ -147,7 +162,7 @@ CommandingServiceBase<STATE_T>::CommandingServiceBase(object_id_t setObjectId,
|
||||
NULL), commandQueue(NULL), requestQueue(NULL), commandMap(
|
||||
numberOfParallelCommands), failureParameter1(0), failureParameter2(
|
||||
0), packetSource(setPacketSource), packetDestination(
|
||||
setPacketDestination) {
|
||||
setPacketDestination),executingTask(NULL) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(queueDepth);
|
||||
requestQueue = QueueFactory::instance()->createMessageQueue(20); //TODO: Funny magic number.
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ ReturnValue_t PusServiceBase::performOperation(uint8_t opCode) {
|
||||
this->currentPacket.deletePacket();
|
||||
errorParameter1 = 0;
|
||||
errorParameter2 = 0;
|
||||
} else if (status == OperatingSystemIF::QUEUE_EMPTY) {
|
||||
} else if (status == MessageQueueIF::EMPTY) {
|
||||
status = RETURN_OK;
|
||||
// debug << "PusService " << (uint16_t)this->serviceId << ": no new packet." << std::endl;
|
||||
break;
|
||||
|
@ -15,10 +15,10 @@ private:
|
||||
public:
|
||||
SourceSequenceCounter() : sequenceCount(0) {}
|
||||
void increment() {
|
||||
this->sequenceCount = (++this->sequenceCount) % (SpacePacketBase::LIMIT_SEQUENCE_COUNT);
|
||||
sequenceCount = (sequenceCount+1) % (SpacePacketBase::LIMIT_SEQUENCE_COUNT);
|
||||
}
|
||||
void decrement() {
|
||||
this->sequenceCount = (--this->sequenceCount) % (SpacePacketBase::LIMIT_SEQUENCE_COUNT);
|
||||
sequenceCount = (sequenceCount-1) % (SpacePacketBase::LIMIT_SEQUENCE_COUNT);
|
||||
}
|
||||
uint16_t get() { return this->sequenceCount; }
|
||||
void reset(uint16_t toValue = 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user