Adding Code for Linux

This commit is contained in:
Steffen Gaisser 2018-07-13 18:28:26 +02:00
parent db1f93a155
commit fd782b20c0
90 changed files with 2411 additions and 1497 deletions

View File

@ -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); ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
if (ipcStore == NULL) { if (ipcStore == NULL) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
setQueueToUse(queueToUse_);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
@ -100,3 +102,6 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t rep
} }
return result; return result;
} }
void ActionHelper::resetHelper() {
}

View File

@ -4,26 +4,90 @@
#include <framework/action/ActionMessage.h> #include <framework/action/ActionMessage.h>
#include <framework/serialize/SerializeIF.h> #include <framework/serialize/SerializeIF.h>
#include <framework/ipc/MessageQueueIF.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 HasActionsIF;
class ActionHelper { class ActionHelper {
public: 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); ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
virtual ~ActionHelper(); 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 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); 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); 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); 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); void setQueueToUse(MessageQueueIF *queue);
protected: protected:
static const uint8_t STEP_OFFSET = 1; static const uint8_t STEP_OFFSET = 1;//!< Increase of value of this per step
HasActionsIF* owner; HasActionsIF* owner;//!< Pointer to the owner
MessageQueueIF* queueToUse; MessageQueueIF* queueToUse;//!< Queue to be used as response sender, has to be set with
StorageManagerIF* ipcStore; 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); virtual void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress);
void resetHelper(); /**
*
*/
virtual void resetHelper();
}; };
#endif /* ACTIONHELPER_H_ */ #endif /* ACTIONHELPER_H_ */

View File

@ -5,7 +5,7 @@
#include <framework/objectmanager/ObjectManagerIF.h> #include <framework/objectmanager/ObjectManagerIF.h>
CommandActionHelper::CommandActionHelper(CommandsActionsIF* setOwner) : CommandActionHelper::CommandActionHelper(CommandsActionsIF* setOwner) :
owner(setOwner), queueToUse(setOwner->getCommandQueuePtr()), ipcStore( owner(setOwner), queueToUse(NULL), ipcStore(
NULL), commandCount(0), lastTarget(0) { NULL), commandCount(0), lastTarget(0) {
} }
@ -66,11 +66,15 @@ ReturnValue_t CommandActionHelper::sendCommand(MessageQueueId_t queueId,
ReturnValue_t CommandActionHelper::initialize() { ReturnValue_t CommandActionHelper::initialize() {
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE); ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
if (ipcStore != NULL) { if (ipcStore == NULL) {
return HasReturnvaluesIF::RETURN_OK;
} else {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
queueToUse = owner->getCommandQueuePtr();
if(queueToUse == NULL){
return HasReturnvaluesIF::RETURN_FAILED;
}
return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t CommandActionHelper::handleReply(CommandMessage* reply) { ReturnValue_t CommandActionHelper::handleReply(CommandMessage* reply) {

View File

@ -6,14 +6,36 @@
#include <framework/action/SimpleActionHelper.h> #include <framework/action/SimpleActionHelper.h>
#include <framework/returnvalues/HasReturnvaluesIF.h> #include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/ipc/MessageQueueIF.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: Theres 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 { class HasActionsIF {
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_ACTIONS_IF; 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 INVALID_PARAMETERS = MAKE_RETURN_CODE(2);
static const ReturnValue_t EXECUTION_FINISHED = MAKE_RETURN_CODE(3); static const ReturnValue_t EXECUTION_FINISHED = MAKE_RETURN_CODE(3);
static const ReturnValue_t INVALID_ACTION_ID = MAKE_RETURN_CODE(4); static const ReturnValue_t INVALID_ACTION_ID = MAKE_RETURN_CODE(4);
virtual ~HasActionsIF() { } virtual ~HasActionsIF() { }
/**
* Function to get the MessageQueueId_t of the implementing object
* @return MessageQueueId_t of the object
*/
virtual MessageQueueId_t getCommandQueue() const = 0; virtual MessageQueueId_t getCommandQueue() const = 0;
/** /**
* Execute or initialize the execution of a certain function. * Execute or initialize the execution of a certain function.

View File

@ -10,9 +10,10 @@ public:
void step(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); void step(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
void finish(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); void finish(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
ReturnValue_t reportData(SerializeIF* data); ReturnValue_t reportData(SerializeIF* data);
void resetHelper();
protected: protected:
void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress); void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress);
virtual void resetHelper();
private: private:
bool isExecuting; bool isExecuting;
MessageQueueId_t lastCommander; MessageQueueId_t lastCommander;

View File

@ -8,7 +8,7 @@ ControllerBase::ControllerBase(uint32_t setObjectId, uint32_t parentId,
size_t commandQueueDepth) : size_t commandQueueDepth) :
SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF), submode( SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF), submode(
SUBMODE_NONE), commandQueue(NULL), modeHelper( SUBMODE_NONE), commandQueue(NULL), modeHelper(
this), healthHelper(this, setObjectId),hkSwitcher(this) { this), healthHelper(this, setObjectId),hkSwitcher(this),executingTask(NULL) {
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth); commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
} }
@ -129,6 +129,9 @@ ReturnValue_t ControllerBase::setHealth(HealthState health) {
HasHealthIF::HealthState ControllerBase::getHealth() { HasHealthIF::HealthState ControllerBase::getHealth() {
return healthHelper.getHealth(); return healthHelper.getHealth();
} }
void ControllerBase::setTaskIF(PeriodicTaskIF* task_){
executingTask = task_;
}
void ControllerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) { void ControllerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
} }

View File

@ -32,6 +32,16 @@ public:
virtual ReturnValue_t setHealth(HealthState health); virtual ReturnValue_t setHealth(HealthState health);
virtual HasHealthIF::HealthState getHealth(); 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: protected:
const uint32_t parentId; const uint32_t parentId;
@ -47,6 +57,11 @@ protected:
HkSwitchHelper hkSwitcher; HkSwitchHelper hkSwitcher;
/**
* Pointer to the task which executes this component, is invalid before setTaskIF was called.
*/
PeriodicTaskIF* executingTask;
void handleQueue(); void handleQueue();
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0; virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0;

View File

@ -2,6 +2,7 @@
#define COORDINATETRANSFORMATIONS_H_ #define COORDINATETRANSFORMATIONS_H_
#include <framework/timemanager/Clock.h> #include <framework/timemanager/Clock.h>
#include <cstring>
class CoordinateTransformations { class CoordinateTransformations {
public: public:

View File

@ -8,7 +8,7 @@
DataPoolAdmin::DataPoolAdmin(object_id_t objectId) : DataPoolAdmin::DataPoolAdmin(object_id_t objectId) :
SystemObject(objectId), storage(NULL), commandQueue(NULL), memoryHelper( SystemObject(objectId), storage(NULL), commandQueue(NULL), memoryHelper(
this, commandQueue), actionHelper(this, commandQueue) { this, NULL), actionHelper(this, NULL) {
commandQueue = QueueFactory::instance()->createMessageQueue(); commandQueue = QueueFactory::instance()->createMessageQueue();
} }
@ -171,7 +171,7 @@ ReturnValue_t DataPoolAdmin::initialize() {
return result; return result;
} }
result = memoryHelper.initialize(); result = memoryHelper.initialize(commandQueue);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
@ -181,7 +181,7 @@ ReturnValue_t DataPoolAdmin::initialize() {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
result = actionHelper.initialize(); result = actionHelper.initialize(commandQueue);
return result; return result;
} }

View File

@ -24,6 +24,8 @@ public:
ReturnValue_t switchHK(SerializeIF *sids, bool enable); ReturnValue_t switchHK(SerializeIF *sids, bool enable);
virtual void setTaskIF(PeriodicTaskIF* task_){};
protected: protected:
virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step); virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step);
virtual void stepFailedReceived(ActionId_t actionId, uint8_t step, virtual void stepFailedReceived(ActionId_t actionId, uint8_t step,

View File

@ -76,13 +76,13 @@ ReturnValue_t PoolRawAccess::getEntryEndianSafe(uint8_t* buffer,
return DATA_POOL_ACCESS_FAILED; return DATA_POOL_ACCESS_FAILED;
if (typeSize > max_size) if (typeSize > max_size)
return INCORRECT_SIZE; return INCORRECT_SIZE;
#ifndef BYTE_ORDER #ifndef BYTE_ORDER_SYSTEM
#error BYTE_ORDER not defined #error BYTE_ORDER_SYSTEM not defined
#elif BYTE_ORDER == LITTLE_ENDIAN #elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
for (uint8_t count = 0; count < typeSize; count++) { for (uint8_t count = 0; count < typeSize; count++) {
buffer[count] = data_ptr[typeSize - count - 1]; buffer[count] = data_ptr[typeSize - count - 1];
} }
#elif BYTE_ORDER == BIG_ENDIAN #elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
memcpy(buffer, data_ptr, typeSize); memcpy(buffer, data_ptr, typeSize);
#endif #endif
*writtenBytes = typeSize; *writtenBytes = typeSize;
@ -112,13 +112,13 @@ PoolVariableIF::ReadWriteMode_t PoolRawAccess::getReadWriteMode() const {
ReturnValue_t PoolRawAccess::setEntryFromBigEndian(const uint8_t* buffer, ReturnValue_t PoolRawAccess::setEntryFromBigEndian(const uint8_t* buffer,
uint32_t setSize) { uint32_t setSize) {
if (typeSize == setSize) { if (typeSize == setSize) {
#ifndef BYTE_ORDER #ifndef BYTE_ORDER_SYSTEM
#error BYTE_ORDER not defined #error BYTE_ORDER_SYSTEM not defined
#elif BYTE_ORDER == LITTLE_ENDIAN #elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
for (uint8_t count = 0; count < typeSize; count++) { for (uint8_t count = 0; count < typeSize; count++) {
value[count] = buffer[typeSize - count - 1]; value[count] = buffer[typeSize - count - 1];
} }
#elif BYTE_ORDER == BIG_ENDIAN #elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
memcpy(value, buffer, typeSize); memcpy(value, buffer, typeSize);
#endif #endif
return HasReturnvaluesIF::RETURN_OK; 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 { const uint32_t max_size, bool bigEndian) const {
if (typeSize + *size <= max_size) { if (typeSize + *size <= max_size) {
if (bigEndian) { if (bigEndian) {
#ifndef BYTE_ORDER #ifndef BYTE_ORDER_SYSTEM
#error BYTE_ORDER not defined #error BYTE_ORDER_SYSTEM not defined
#elif BYTE_ORDER == LITTLE_ENDIAN #elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
for (uint8_t count = 0; count < typeSize; count++) { for (uint8_t count = 0; count < typeSize; count++) {
(*buffer)[count] = value[typeSize - count - 1]; (*buffer)[count] = value[typeSize - count - 1];
} }
#elif BYTE_ORDER == BIG_ENDIAN #elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
memcpy(*buffer, value, typeSize); memcpy(*buffer, value, typeSize);
#endif #endif
} else { } else {
@ -179,13 +179,13 @@ ReturnValue_t PoolRawAccess::deSerialize(const uint8_t** buffer, int32_t* size,
if (*size >= 0) { if (*size >= 0) {
if (bigEndian) { if (bigEndian) {
#ifndef BYTE_ORDER #ifndef BYTE_ORDER_SYSTEM
#error BYTE_ORDER not defined #error BYTE_ORDER_SYSTEM not defined
#elif BYTE_ORDER == LITTLE_ENDIAN #elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
for (uint8_t count = 0; count < typeSize; count++) { for (uint8_t count = 0; count < typeSize; count++) {
value[count] = (*buffer)[typeSize - count - 1]; value[count] = (*buffer)[typeSize - count - 1];
} }
#elif BYTE_ORDER == BIG_ENDIAN #elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
memcpy(value, *buffer, typeSize); memcpy(value, *buffer, typeSize);
#endif #endif
} else { } else {

View File

@ -30,19 +30,7 @@ DeviceHandlerBase::DeviceHandlerBase(uint32_t ioBoardAddress,
thermalRequestPoolId), healthHelper(this, setObjectId), modeHelper( thermalRequestPoolId), healthHelper(this, setObjectId), modeHelper(
this), parameterHelper(this), childTransitionFailure(RETURN_OK), ignoreMissedRepliesCount( this), parameterHelper(this), childTransitionFailure(RETURN_OK), ignoreMissedRepliesCount(
0), fdirInstance(fdirInstance), hkSwitcher(this), defaultFDIRUsed( 0), fdirInstance(fdirInstance), hkSwitcher(this), defaultFDIRUsed(
fdirInstance == NULL), switchOffWasReported(false), executingTask( fdirInstance == NULL), switchOffWasReported(false),executingTask(NULL), actionHelper(this, NULL), cookieInfo(), ioBoardAddress(
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
ioBoardAddress), timeoutStart(0), childTransitionDelay(5000), transitionSourceMode( ioBoardAddress), timeoutStart(0), childTransitionDelay(5000), transitionSourceMode(
_MODE_POWER_DOWN), transitionSourceSubMode(SUBMODE_NONE), deviceSwitch( _MODE_POWER_DOWN), transitionSourceSubMode(SUBMODE_NONE), deviceSwitch(
setDeviceSwitch) { setDeviceSwitch) {
@ -636,7 +624,7 @@ ReturnValue_t DeviceHandlerBase::initialize() {
if (result != RETURN_OK) { if (result != RETURN_OK) {
return result; return result;
} }
result = actionHelper.initialize(); result = actionHelper.initialize(commandQueue);
if (result != RETURN_OK) { if (result != RETURN_OK) {
return result; return result;
} }
@ -1021,10 +1009,6 @@ ReturnValue_t DeviceHandlerBase::acceptExternalDeviceCommands() {
return RETURN_OK; return RETURN_OK;
} }
void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* interface) {
executingTask = interface;
}
void DeviceHandlerBase::replyRawReplyIfnotWiretapped(const uint8_t* data, void DeviceHandlerBase::replyRawReplyIfnotWiretapped(const uint8_t* data,
size_t len) { size_t len) {
if ((wiretappingMode == RAW) 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::changeHK(Mode_t mode, Submode_t submode, bool enable) {
} }
void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task_){
executingTask = task_;
}

View File

@ -92,8 +92,13 @@ public:
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper *parameterWrapper, ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex); 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: protected:
/** /**
* The Returnvalues id of this class, required by HasReturnvaluesIF * The Returnvalues id of this class, required by HasReturnvaluesIF
@ -248,13 +253,13 @@ protected:
bool switchOffWasReported; //!< Indicates if SWITCH_WENT_OFF was already thrown. 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 powerSwitcherId; //!< Object which switches power on and off.
static object_id_t rawDataReceiverId; //!< Object which receives RAW data by default. 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. 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 * Helper function to report a missed reply
* *
@ -787,7 +792,6 @@ protected:
DeviceCommandMap deviceCommandMap; DeviceCommandMap deviceCommandMap;
ActionHelper actionHelper; ActionHelper actionHelper;
private: private:
/** /**

View File

@ -17,7 +17,6 @@ FixedSlotSequence::~FixedSlotSequence() {
} }
void FixedSlotSequence::executeAndAdvance() { void FixedSlotSequence::executeAndAdvance() {
// (*this->current)->print();
(*this->current)->handler->performOperation((*this->current)->opcode); (*this->current)->handler->performOperation((*this->current)->opcode);
// if (returnValue != RETURN_OK) { // if (returnValue != RETURN_OK) {
// this->sendErrorMessage( returnValue ); // this->sendErrorMessage( returnValue );

View File

@ -34,7 +34,6 @@ public:
object_id_t reporterFrom = 0, object_id_t reporterTo = 0, object_id_t reporterFrom = 0, object_id_t reporterTo = 0,
bool reporterInverted = false); bool reporterInverted = false);
ReturnValue_t performOperation(uint8_t opCode); ReturnValue_t performOperation(uint8_t opCode);
protected: protected:
MessageQueueIF* eventReportQueue; MessageQueueIF* eventReportQueue;

View File

@ -39,10 +39,7 @@ endif
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/parameters/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/parameters/*.cpp)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/power/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/power/*.cpp)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/returnvalues/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/returnvalues/*.cpp)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/rmap/*.cpp)
# easier without it for now
#CXXSRC += $(wildcard $(FRAMEWORK_PATH)/rmap/*.cpp)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/serialize/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/serialize/*.cpp)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/serviceinterface/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/serviceinterface/*.cpp)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/storagemanager/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/storagemanager/*.cpp)

View File

@ -1,5 +1,4 @@
#include <framework/globalfunctions/conversion.h> #include <framework/globalfunctions/conversion.h>
//TODO REMOVE. Needed because of BYTE_ORDER
#include <framework/osal/Endiness.h> #include <framework/osal/Endiness.h>
#include <cstring> #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 ) { void convertToByteStream( float in_value, uint8_t* buffer, uint32_t* size ) {
#ifndef BYTE_ORDER #ifndef BYTE_ORDER_SYSTEM
#error BYTE_ORDER not defined #error BYTE_ORDER_SYSTEM not defined
#elif BYTE_ORDER == LITTLE_ENDIAN #elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
union float_union { union float_union {
float value; float value;
uint8_t chars[4]; 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[2] = temp.chars[1];
buffer[3] = temp.chars[0]; buffer[3] = temp.chars[0];
*size += 4; *size += 4;
#elif BYTE_ORDER == BIG_ENDIAN #elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
memcpy(buffer, &in_value, sizeof(in_value)); memcpy(buffer, &in_value, sizeof(in_value));
*size += sizeof(in_value); *size += sizeof(in_value);
#endif #endif
} }
void convertToByteStream( double in_value, uint8_t* buffer, uint32_t* size ) { void convertToByteStream( double in_value, uint8_t* buffer, uint32_t* size ) {
#ifndef BYTE_ORDER #ifndef BYTE_ORDER_SYSTEM
#error Endianess not defined #error BYTE_ORDER_SYSTEM not defined
#elif BYTE_ORDER == LITTLE_ENDIAN #elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
union double_union { union double_union {
double value; double value;
uint8_t chars[8]; 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[6] = temp.chars[1];
buffer[7] = temp.chars[0]; buffer[7] = temp.chars[0];
*size += 8; *size += 8;
#elif BYTE_ORDER == BIG_ENDIAN #elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
memcpy(buffer, &in_value, sizeof(in_value)); memcpy(buffer, &in_value, sizeof(in_value));
*size += sizeof(in_value); *size += sizeof(in_value);
#endif #endif

View File

@ -22,7 +22,6 @@ public:
virtual void lostTm(); virtual void lostTm();
virtual void storeFull(); virtual void storeFull();
protected: protected:
MutexIF* mutex; MutexIF* mutex;

View File

@ -5,11 +5,22 @@
#include <framework/ipc/MessageQueueMessage.h> #include <framework/ipc/MessageQueueMessage.h>
#include <framework/ipc/MessageQueueSenderIF.h> #include <framework/ipc/MessageQueueSenderIF.h>
#include <framework/returnvalues/HasReturnvaluesIF.h>
class MessageQueueIF { class MessageQueueIF {
public: public:
static const MessageQueueId_t NO_QUEUE = MessageQueueSenderIF::NO_QUEUE; //!< Ugly hack. 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() {} virtual ~MessageQueueIF() {}
/** /**
* @brief This operation sends a message to the last communication partner. * @brief This operation sends a message to the last communication partner.
@ -65,16 +76,32 @@ public:
* This variable is set to zero by default. * 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). * \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. * \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 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. * \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. * 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. * \brief This method is a simple setter for the default destination.
*/ */

24
ipc/MutexHelper.h Normal file
View 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_ */

View File

@ -6,6 +6,57 @@
class MutexIF { class MutexIF {
public: public:
static const uint32_t NO_TIMEOUT; //!< Needs to be defined in implementation. 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 ~MutexIF() {}
virtual ReturnValue_t lockMutex(uint32_t timeoutMs) = 0; virtual ReturnValue_t lockMutex(uint32_t timeoutMs) = 0;
virtual ReturnValue_t unlockMutex() = 0; virtual ReturnValue_t unlockMutex() = 0;

View File

@ -8,7 +8,7 @@
LocalMemory::LocalMemory(object_id_t setObjectId) : LocalMemory::LocalMemory(object_id_t setObjectId) :
SystemObject(setObjectId), commandQueue(NULL), memoryHelper(this, SystemObject(setObjectId), commandQueue(NULL), memoryHelper(this,
commandQueue) { NULL) {
commandQueue = QueueFactory::instance()->createMessageQueue(); commandQueue = QueueFactory::instance()->createMessageQueue();
} }
@ -52,7 +52,7 @@ ReturnValue_t LocalMemory::handleMemoryDump(uint32_t address, uint32_t size,
} }
ReturnValue_t LocalMemory::initialize() { ReturnValue_t LocalMemory::initialize() {
return memoryHelper.initialize(); return memoryHelper.initialize(commandQueue);
} }
MessageQueueId_t LocalMemory::getCommandQueue() const { MessageQueueId_t LocalMemory::getCommandQueue() const {

View File

@ -183,3 +183,13 @@ void MemoryHelper::handleMemoryCheckOrDump(CommandMessage* message) {
queueToUse->sendMessage(lastSender, &reply); queueToUse->sendMessage(lastSender, &reply);
} }
} }
ReturnValue_t MemoryHelper::initialize(MessageQueueIF* queueToUse_) {
if(queueToUse_!=NULL){
this->queueToUse = queueToUse_;
}else{
return MessageQueueIF::NO_QUEUE;
}
return initialize();
}

View File

@ -24,12 +24,13 @@ private:
bool busy; bool busy;
void handleMemoryLoad(CommandMessage* message); void handleMemoryLoad(CommandMessage* message);
void handleMemoryCheckOrDump(CommandMessage* message); void handleMemoryCheckOrDump(CommandMessage* message);
ReturnValue_t initialize();
public: public:
ReturnValue_t handleMemoryCommand(CommandMessage* message); 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 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 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); 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( HasMemoryIF* workOnThis, MessageQueueIF* useThisQueue );
~MemoryHelper(); ~MemoryHelper();
}; };

View File

@ -19,11 +19,11 @@ public:
} }
ReturnValue_t doCheck(T lowSample, T highSample) { ReturnValue_t doCheck(T lowSample, T highSample) {
T crossedLimit; T crossedLimit;
ReturnValue_t currentState = checkSample(lowSample, &crossedLimit); ReturnValue_t currentState = this->checkSample(lowSample, &crossedLimit);
if (currentState != HasReturnvaluesIF::RETURN_OK) { if (currentState != HasReturnvaluesIF::RETURN_OK) {
return this->monitorStateIs(currentState, lowSample, crossedLimit); return this->monitorStateIs(currentState, lowSample, crossedLimit);
} }
currentState = checkSample(highSample, &crossedLimit); currentState = this->checkSample(highSample, &crossedLimit);
return this->monitorStateIs(currentState, highSample, crossedLimit); return this->monitorStateIs(currentState, highSample, crossedLimit);
} }
protected: protected:

View File

@ -12,16 +12,19 @@
#define LITTLE_ENDIAN 1234 #define LITTLE_ENDIAN 1234
#endif #endif
// This is a GCC C extension // This is a GCC C extension
#ifndef BYTE_ORDER #ifndef BYTE_ORDER_SYSTEM
#ifdef __BYTE_ORDER__
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define BYTE_ORDER BIG_ENDIAN #define BYTE_ORDER_SYSTEM LITTLE_ENDIAN
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define BYTE_ORDER LITTLE_ENDIAN #define BYTE_ORDER_SYSTEM BIG_ENDIAN
#else #else
#error "Can't decide which end is which!" #error "Can't decide which end is which!"
#endif #endif
#else
#error __BYTE_ORDER__ not defined
#endif
#endif #endif

View File

@ -21,16 +21,16 @@ MessageQueue::~MessageQueue() {
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
MessageQueueMessage* message, bool ignoreFault) { MessageQueueMessage* message, bool ignoreFault) {
return sendMessage(sendTo, message, this->getId(), ignoreFault); return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
} }
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message) { ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message) {
return sendToDefault(message, this->getId()); return sendToDefaultFrom(message, this->getId());
} }
ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) { ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) {
if (this->lastPartner != 0) { if (this->lastPartner != 0) {
return sendMessage(this->lastPartner, message, this->getId()); return sendMessageFrom(this->lastPartner, message, this->getId());
} else { } else {
//TODO: Good returnCode //TODO: Good returnCode
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
@ -49,8 +49,7 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) {
if (result == pdPASS){ if (result == pdPASS){
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} else { } else {
//TODO Queue Empty return MessageQueueIF::EMPTY;
return HasReturnvaluesIF::RETURN_FAILED;
} }
} }
@ -73,7 +72,7 @@ void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
this->defaultDestination = defaultDestination; this->defaultDestination = defaultDestination;
} }
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
MessageQueueMessage* message, MessageQueueId_t sentFrom, MessageQueueMessage* message, MessageQueueId_t sentFrom,
bool ignoreFault) { bool ignoreFault) {
message->setSender(sentFrom); message->setSender(sentFrom);
@ -83,15 +82,14 @@ ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
if (!ignoreFault) { if (!ignoreFault) {
//TODO errr reporter //TODO errr reporter
} }
//TODO queue is full return MessageQueueIF::FULL;
return HasReturnvaluesIF::RETURN_FAILED;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message, ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessage* message,
MessageQueueId_t sentFrom, bool ignoreFault) { MessageQueueId_t sentFrom, bool ignoreFault) {
return 0; return sendMessageFrom(defaultDestination,message,sentFrom,ignoreFault);
} }
MessageQueueId_t MessageQueue::getDefaultDestination() const { MessageQueueId_t MessageQueue::getDefaultDestination() const {

View File

@ -117,7 +117,7 @@ public:
* This variable is set to zero by default. * 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. * \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. * \brief The sendToDefault method sends a queue message to the default destination.
* \details In all other aspects, it works identical to the sendMessage method. * \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. * \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. * 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. * \brief This method is a simple setter for the default destination.
*/ */

View File

@ -1,31 +1,32 @@
//entry point into "bsp" //entry point into "bsp"
void init(void); //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 <FreeRTOS.h>
#include "task.h" //#include <FreeRTOSConfig.h>
//#include "task.h"
//
void initTask(void *parameters) { //
init(); //void initTask(void *parameters) {
} // init();
//}
int main(void) { //
//int main(void) {
if ( pdPASS //
!= xTaskCreate(initTask, "init", 512, NULL, // if ( pdPASS
configMAX_PRIORITIES - 1, NULL)) { // != xTaskCreate(initTask, "init", 512, NULL,
//print_uart0("Could not create task1\r\n"); // configMAX_PRIORITIES - 1, NULL)) {
} // //print_uart0("Could not create task1\r\n");
// }
vTaskStartScheduler(); //
// vTaskStartScheduler();
//Scheduler should never return //
// //Scheduler should never return
//print_uart0("This is bad\n"); //
// //print_uart0("This is bad\n");
for (;;) //
; // for (;;)
// ;
return 0; //
} // return 0;
//}

View File

@ -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_ */

View File

@ -8,25 +8,21 @@
#include <unistd.h> #include <unistd.h>
//#include <fstream> //#include <fstream>
uint16_t Clock::leapSeconds = 0;
MutexIF* Clock::timeMutex = NULL;
uint32_t Clock::getTicksPerSecond(void){ uint32_t Clock::getTicksPerSecond(void){
//TODO This function returns the ticks per second for thread ticks not clock ticks uint32_t ticks = sysconf(_SC_CLK_TCK);
// timespec ticks; return 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;
} }
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
//TODO timeOfDay conversion
timespec timeUnix; 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); int status = clock_settime(CLOCK_REALTIME,&timeUnix);
if(status!=0){ if(status!=0){
//TODO errno //TODO errno
@ -109,14 +105,6 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
//TODO errno //TODO errno
return HasReturnvaluesIF::RETURN_FAILED; 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; struct tm* timeInfo;
timeInfo = gmtime(&timeUnix.tv_sec); timeInfo = gmtime(&timeUnix.tv_sec);
@ -126,7 +114,7 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
time->hour = timeInfo->tm_hour; time->hour = timeInfo->tm_hour;
time->minute = timeInfo->tm_min; time->minute = timeInfo->tm_min;
time->second = timeInfo->tm_sec; time->second = timeInfo->tm_sec;
time->ticks = (timeUnix.tv_nsec / (double) 1e9) * resolution; time->usecond = timeUnix.tv_nsec / 1000.0;
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
@ -143,34 +131,81 @@ ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from,
fromTm.tm_min = from->minute; fromTm.tm_min = from->minute;
fromTm.tm_sec = from->second; 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_sec = mktime(&fromTm);
to->tv_usec = (from->ticks /(double) resolution) * 1e6; to->tv_usec = from->usecond;
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) { 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) { 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; 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_) { ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) {
if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){
return HasReturnvaluesIF::RETURN_FAILED; 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_) { ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
if(timeMutex==NULL){
return HasReturnvaluesIF::RETURN_FAILED; 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;
}

View 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;
}
}

View 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_ */

View 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
View 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
View 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
View 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
View 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_ */

View 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;
}

View 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;
}

View 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
View 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
View 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_ */

View 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;
}

View 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
View 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
View 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_ */

View File

@ -1,72 +1,125 @@
#include <framework/timemanager/Clock.h> #include <framework/timemanager/Clock.h>
#include "RtemsBasic.h" #include "RtemsBasic.h"
#include <rtems/score/todimpl.h>
uint16_t Clock::leapSeconds = 0; uint16_t Clock::leapSeconds = 0;
MutexIF* Clock::timeMutex = NULL; MutexIF* Clock::timeMutex = NULL;
uint32_t Clock::getTicksPerSecond(void){ uint32_t Clock::getTicksPerSecond(void){
rtems_interval ticks_per_second; rtems_interval ticks_per_second = rtems_clock_get_ticks_per_second();
(void) rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second); return static_cast<uint32_t>(ticks_per_second);
return ticks_per_second;
} }
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { 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_time_of_day timeRtems;
//rtems provides no const guarantee, so we need to cast the const away timeRtems.year = time->year;
//TODO Check if this can be done safely timeRtems.month = time->month;
rtems_time_of_day* timeRtems = reinterpret_cast<rtems_time_of_day*>(const_cast<TimeOfDay_t*>(time)); timeRtems.day = time->day;
rtems_status_code status = rtems_clock_set(timeRtems); timeRtems.hour = time->hour;
return RtemsBasic::convertReturnCode(status); 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) { ReturnValue_t Clock::setClock(const timeval* time) {
//TODO This routine uses _TOD_Set which is not
timespec newTime; timespec newTime;
newTime.tv_sec = time->tv_sec; newTime.tv_sec = time->tv_sec;
newTime.tv_nsec = time->tv_usec * TOD_NANOSECONDS_PER_MICROSECOND; 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). //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 //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; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t Clock::getClock_timeval(timeval* time) { ReturnValue_t Clock::getClock_timeval(timeval* time) {
//Callable from ISR
rtems_status_code status = rtems_clock_get_tod_timeval(time); 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) { 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; timespec time;
rtems_status_code status = rtems_clock_get_uptime(&time); rtems_status_code status = rtems_clock_get_uptime(&time);
uptime->tv_sec = time.tv_sec; uptime->tv_sec = time.tv_sec;
time.tv_nsec = time.tv_nsec / 1000; time.tv_nsec = time.tv_nsec / 1000;
uptime->tv_usec = time.tv_nsec; 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) { ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
//This counter overflows after 50 days
*uptimeMs = rtems_clock_get_ticks_since_boot(); *uptimeMs = rtems_clock_get_ticks_since_boot();
return RtemsBasic::convertReturnCode(RTEMS_SUCCESSFUL); return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t Clock::getClock_usecs(uint64_t* time) { ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
timeval temp_time; timeval temp_time;
rtems_status_code returnValue = rtems_clock_get_tod_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; *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) { ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
rtems_time_of_day* timeRtems = reinterpret_cast<rtems_time_of_day*>(time); rtems_time_of_day* timeRtems = reinterpret_cast<rtems_time_of_day*>(time);
rtems_status_code status = rtems_clock_get_tod(timeRtems); 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, ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from,
timeval* to) { timeval* to) {
//Fails in 2038.. //Fails in 2038..
const rtems_time_of_day* timeRtems = reinterpret_cast<const rtems_time_of_day*>(from); rtems_time_of_day timeRtems;
to->tv_sec = _TOD_To_seconds(timeRtems); timeRtems.year = from->year;
to->tv_usec = timeRtems->ticks * 1000; 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; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -1,4 +1,4 @@
#include <framework/osal/CpuUsage.h> #include "CpuUsage.h"
#include <framework/serialize/SerialArrayListAdapter.h> #include <framework/serialize/SerialArrayListAdapter.h>
#include <framework/serialize/SerializeAdapter.h> #include <framework/serialize/SerializeAdapter.h>
#include <string.h> #include <string.h>
@ -80,7 +80,7 @@ void CpuUsage::resetCpuUsage() {
} }
void CpuUsage::read() { void CpuUsage::read() {
rtems_cpu_usage_report_with_plugin(this, &handlePrint); //rtems_cpu_usage_report_with_plugin(this, &handlePrint);
} }
void CpuUsage::clear() { void CpuUsage::clear() {

View File

@ -7,21 +7,5 @@ InitTask::InitTask() {
} }
InitTask::~InitTask() { InitTask::~InitTask() {
}
void InitTask::deleteTask(){
rtems_task_delete(RTEMS_SELF); 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;
}

View File

@ -1,8 +1,6 @@
#ifndef OS_RTEMS_INITTASK_H_ #ifndef OS_RTEMS_INITTASK_H_
#define OS_RTEMS_INITTASK_H_ #define OS_RTEMS_INITTASK_H_
#include <framework/tasks/PeriodicTaskIF.h>
//TODO move into static function in TaskIF //TODO move into static function in TaskIF
/** /**
@ -12,17 +10,10 @@
* Warning: The init task is deleted with this stub, i.e. the destructor * Warning: The init task is deleted with this stub, i.e. the destructor
* calls rtems_task_delete(RTEMS_SELF) * calls rtems_task_delete(RTEMS_SELF)
*/ */
class InitTask: public PeriodicTaskIF { class InitTask {
public: public:
InitTask(); InitTask();
virtual ~InitTask(); virtual ~InitTask();
ReturnValue_t startTask();
ReturnValue_t sleepFor(uint32_t ms);
uint32_t getPeriodMs() const;
void deleteTask();
}; };
#endif /* OS_RTEMS_INITTASK_H_ */ #endif /* OS_RTEMS_INITTASK_H_ */

View File

@ -3,12 +3,13 @@
ReturnValue_t InternalErrorCodes::translate(uint8_t code) { ReturnValue_t InternalErrorCodes::translate(uint8_t code) {
switch (code) { switch (code) {
case INTERNAL_ERROR_NO_CONFIGURATION_TABLE: //TODO It looks like RTEMS-5 does not provide the same error codes
return NO_CONFIGURATION_TABLE; // case INTERNAL_ERROR_NO_CONFIGURATION_TABLE:
case INTERNAL_ERROR_NO_CPU_TABLE: // return NO_CONFIGURATION_TABLE;
return NO_CPU_TABLE; // case INTERNAL_ERROR_NO_CPU_TABLE:
case INTERNAL_ERROR_INVALID_WORKSPACE_ADDRESS: // return NO_CPU_TABLE;
return INVALID_WORKSPACE_ADDRESS; // case INTERNAL_ERROR_INVALID_WORKSPACE_ADDRESS:
// return INVALID_WORKSPACE_ADDRESS;
case INTERNAL_ERROR_TOO_LITTLE_WORKSPACE: case INTERNAL_ERROR_TOO_LITTLE_WORKSPACE:
return TOO_LITTLE_WORKSPACE; return TOO_LITTLE_WORKSPACE;
case INTERNAL_ERROR_WORKSPACE_ALLOCATION: case INTERNAL_ERROR_WORKSPACE_ALLOCATION:
@ -35,16 +36,16 @@ ReturnValue_t InternalErrorCodes::translate(uint8_t code) {
return INVALID_GLOBAL_ID; return INVALID_GLOBAL_ID;
case INTERNAL_ERROR_BAD_STACK_HOOK: case INTERNAL_ERROR_BAD_STACK_HOOK:
return BAD_STACK_HOOK; return BAD_STACK_HOOK;
case INTERNAL_ERROR_BAD_ATTRIBUTES: // case INTERNAL_ERROR_BAD_ATTRIBUTES:
return BAD_ATTRIBUTES; // return BAD_ATTRIBUTES;
case INTERNAL_ERROR_IMPLEMENTATION_KEY_CREATE_INCONSISTENCY: // case INTERNAL_ERROR_IMPLEMENTATION_KEY_CREATE_INCONSISTENCY:
return IMPLEMENTATION_KEY_CREATE_INCONSISTENCY; // return IMPLEMENTATION_KEY_CREATE_INCONSISTENCY;
case INTERNAL_ERROR_IMPLEMENTATION_BLOCKING_OPERATION_CANCEL: // case INTERNAL_ERROR_IMPLEMENTATION_BLOCKING_OPERATION_CANCEL:
return IMPLEMENTATION_BLOCKING_OPERATION_CANCEL; // return IMPLEMENTATION_BLOCKING_OPERATION_CANCEL;
case INTERNAL_ERROR_MUTEX_OBTAIN_FROM_BAD_STATE: // case INTERNAL_ERROR_MUTEX_OBTAIN_FROM_BAD_STATE:
return MUTEX_OBTAIN_FROM_BAD_STATE; // return MUTEX_OBTAIN_FROM_BAD_STATE;
case INTERNAL_ERROR_UNLIMITED_AND_MAXIMUM_IS_0: // case INTERNAL_ERROR_UNLIMITED_AND_MAXIMUM_IS_0:
return UNLIMITED_AND_MAXIMUM_IS_0; // return UNLIMITED_AND_MAXIMUM_IS_0;
default: default:
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }

View File

@ -1,5 +1,8 @@
#include "Interrupt.h" #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" #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 //+ 0x10 comes because of trap type assignment to IRQs in UT699 processor
rtems_status_code status = rtems_interrupt_catch(handler, interrupt + 0x10, rtems_status_code status = rtems_interrupt_catch(handler, interrupt + 0x10,
oldHandler); 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) { ReturnValue_t Interrupt::disableInterrupt(InterruptNumber_t interruptNumber) {

View File

@ -1,7 +1,7 @@
#include <framework/serviceinterface/ServiceInterfaceStream.h> #include <framework/serviceinterface/ServiceInterfaceStream.h>
#include "MessageQueue.h" #include "MessageQueue.h"
#include "RtemsBasic.h" #include "RtemsBasic.h"
#include <cstring>
MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size) : MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size) :
id(0), lastPartner(0), defaultDestination(NO_QUEUE), internalErrorReporter(NULL) { id(0), lastPartner(0), defaultDestination(NO_QUEUE), internalErrorReporter(NULL) {
rtems_name name = ('Q' << 24) + (queueCounter++ << 8); rtems_name name = ('Q' << 24) + (queueCounter++ << 8);
@ -21,11 +21,11 @@ MessageQueue::~MessageQueue() {
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
MessageQueueMessage* message, bool ignoreFault) { MessageQueueMessage* message, bool ignoreFault) {
return sendMessage(sendTo, message, this->getId(), ignoreFault); return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
} }
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message) { ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message) {
return sendToDefault(message, this->getId()); return sendToDefaultFrom(message, this->getId());
} }
ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) { ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) {
@ -59,7 +59,7 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) {
//But still, delete packet content. //But still, delete packet content.
memset(message->getData(), 0, message->MAX_DATA_SIZE); memset(message->getData(), 0, message->MAX_DATA_SIZE);
} }
return RtemsBasic::convertReturnCode(status); return convertReturnCode(status);
} }
MessageQueueId_t MessageQueue::getLastPartner() const { MessageQueueId_t MessageQueue::getLastPartner() const {
@ -68,7 +68,7 @@ MessageQueueId_t MessageQueue::getLastPartner() const {
ReturnValue_t MessageQueue::flush(uint32_t* count) { ReturnValue_t MessageQueue::flush(uint32_t* count) {
rtems_status_code status = rtems_message_queue_flush(id, count); rtems_status_code status = rtems_message_queue_flush(id, count);
return RtemsBasic::convertReturnCode(status); return convertReturnCode(status);
} }
MessageQueueId_t MessageQueue::getId() const { MessageQueueId_t MessageQueue::getId() const {
@ -79,7 +79,7 @@ void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
this->defaultDestination = defaultDestination; this->defaultDestination = defaultDestination;
} }
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
MessageQueueMessage* message, MessageQueueId_t sentFrom, MessageQueueMessage* message, MessageQueueId_t sentFrom,
bool ignoreFault) { bool ignoreFault) {
@ -97,12 +97,18 @@ ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
internalErrorReporter->queueMessageNotSent(); 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) { MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessage(defaultDestination, message, sentFrom, ignoreFault); return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault);
} }
MessageQueueId_t MessageQueue::getDefaultDestination() const { MessageQueueId_t MessageQueue::getDefaultDestination() const {
@ -113,4 +119,30 @@ bool MessageQueue::isDefaultDestinationSet() const {
return (defaultDestination != NO_QUEUE); 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; uint16_t MessageQueue::queueCounter = 0;

View File

@ -13,6 +13,7 @@
#include <framework/internalError/InternalErrorReporterIF.h> #include <framework/internalError/InternalErrorReporterIF.h>
#include <framework/ipc/MessageQueueIF.h> #include <framework/ipc/MessageQueueIF.h>
#include <framework/ipc/MessageQueueMessage.h> #include <framework/ipc/MessageQueueMessage.h>
#include "RtemsBasic.h"
/** /**
* @brief This class manages sending and receiving of message queue messages. * @brief This class manages sending and receiving of message queue messages.
@ -120,7 +121,7 @@ public:
* This variable is set to zero by default. * 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. * \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. * \brief The sendToDefault method sends a queue message to the default destination.
* \details In all other aspects, it works identical to the sendMessage method. * \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. * \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. * 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. * \brief This method is a simple setter for the default destination.
*/ */
@ -169,6 +170,12 @@ private:
InternalErrorReporterIF *internalErrorReporter; InternalErrorReporterIF *internalErrorReporter;
static uint16_t queueCounter; 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_ */ #endif /* MESSAGEQUEUE_H_ */

View File

@ -14,13 +14,6 @@ MultiObjectTask::MultiObjectTask(const char *name, rtems_task_priority setPriori
TaskBase(setPriority, setStack, name), periodTicks( TaskBase(setPriority, setStack, name), periodTicks(
RtemsBasic::convertMsToTicks(setPeriod)), periodId(0), deadlineMissedFunc( RtemsBasic::convertMsToTicks(setPeriod)), periodId(0), deadlineMissedFunc(
setDeadlineMissedFunc) { 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) { MultiObjectTask::~MultiObjectTask(void) {
@ -40,7 +33,17 @@ ReturnValue_t MultiObjectTask::startTask() {
error << "ObjectTask::startTask for " << std::hex << this->getId() error << "ObjectTask::startTask for " << std::hex << this->getId()
<< std::dec << " failed." << std::endl; << 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) { ReturnValue_t MultiObjectTask::sleepFor(uint32_t ms) {
@ -48,21 +51,14 @@ ReturnValue_t MultiObjectTask::sleepFor(uint32_t ms) {
} }
void MultiObjectTask::taskFunctionality() { void MultiObjectTask::taskFunctionality() {
//The +1 is necessary to avoid a call with period = 0, which does not start the period. TaskBase::setAndStartPeriod(periodTicks,&periodId);
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;
}
//The task's "infinite" inner loop is entered. //The task's "infinite" inner loop is entered.
while (1) { while (1) {
for (ObjectList::iterator it = objectList.begin(); for (ObjectList::iterator it = objectList.begin();
it != objectList.end(); ++it) { it != objectList.end(); ++it) {
(*it)->performOperation(); (*it)->performOperation();
} }
status = rtems_rate_monotonic_period(periodId, periodTicks + 1); rtems_status_code status = TaskBase::restartPeriod(periodTicks,periodId);
if (status == RTEMS_TIMEOUT) { if (status == RTEMS_TIMEOUT) {
char nameSpace[8] = { 0 }; char nameSpace[8] = { 0 };
char* ptr = rtems_object_get_name(getId(), sizeof(nameSpace), char* ptr = rtems_object_get_name(getId(), sizeof(nameSpace),

View File

@ -26,10 +26,40 @@ Mutex::~Mutex() {
ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) {
rtems_status_code status = rtems_semaphore_obtain(mutexId, RTEMS_WAIT, 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() { ReturnValue_t Mutex::unlockMutex() {
rtems_status_code status = rtems_semaphore_release(mutexId); 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;
}
} }

View File

@ -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 <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; uint32_t PollingTask::deadlineMissedCount = 0;
@ -10,13 +23,6 @@ PollingTask::PollingTask(const char *name, rtems_task_priority setPriority,
setOverallPeriod) { setOverallPeriod) {
// All additional attributes are applied to the object. // All additional attributes are applied to the object.
this->deadlineMissedFunc = setDeadlineMissedFunc; 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() { PollingTask::~PollingTask() {
@ -47,7 +53,17 @@ ReturnValue_t PollingTask::startTask() {
error << "PollingTask::startTask for " << std::hex << this->getId() error << "PollingTask::startTask for " << std::hex << this->getId()
<< std::dec << " failed." << std::endl; << 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, ReturnValue_t PollingTask::addSlot(object_id_t componentId, uint32_t slotTimeMs,
@ -64,6 +80,8 @@ ReturnValue_t PollingTask::checkSequence() const {
return pst.checkSequence(); return pst.checkSequence();
} }
#include <rtems/io.h>
void PollingTask::taskFunctionality() { void PollingTask::taskFunctionality() {
// A local iterator for the Polling Sequence Table is created to find the start time for the first entry. // 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; std::list<FixedSequenceSlot*>::iterator it = pst.current;
@ -71,15 +89,7 @@ void PollingTask::taskFunctionality() {
//The start time for the first entry is read. //The start time for the first entry is read.
rtems_interval interval = RtemsBasic::convertMsToTicks( rtems_interval interval = RtemsBasic::convertMsToTicks(
(*it)->pollingTimeMs); (*it)->pollingTimeMs);
//The period is set up and started with the system call. TaskBase::setAndStartPeriod(interval,&periodId);
//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;
}
//The task's "infinite" inner loop is entered. //The task's "infinite" inner loop is entered.
while (1) { while (1) {
if (pst.slotFollowsImmediately()) { if (pst.slotFollowsImmediately()) {
@ -89,7 +99,7 @@ void PollingTask::taskFunctionality() {
interval = RtemsBasic::convertMsToTicks(this->pst.getIntervalToNextSlotMs()); interval = RtemsBasic::convertMsToTicks(this->pst.getIntervalToNextSlotMs());
//The period is checked and restarted with the new interval. //The period is checked and restarted with the new interval.
//If the deadline was missed, the deadlineMissedFunc is called. //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 (status == RTEMS_TIMEOUT) {
if (this->deadlineMissedFunc != NULL) { if (this->deadlineMissedFunc != NULL) {
this->deadlineMissedFunc(); this->deadlineMissedFunc();

View File

@ -10,7 +10,29 @@ ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo,
message->setSender(sentFrom); message->setSender(sentFrom);
rtems_status_code result = rtems_message_queue_send(sendTo, message->getBuffer(), rtems_status_code result = rtems_message_queue_send(sendTo, message->getBuffer(),
message->messageSize); 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() { QueueFactory* QueueFactory::instance() {

View File

@ -1,70 +1,70 @@
#include "RtemsBasic.h" #include "RtemsBasic.h"
ReturnValue_t RtemsBasic::convertReturnCode(rtems_status_code inValue) { //ReturnValue_t RtemsBasic::convertReturnCode(rtems_status_code inValue) {
if (inValue == RTEMS_SUCCESSFUL) { // if (inValue == RTEMS_SUCCESSFUL) {
return HasReturnvaluesIF::RETURN_OK; // return HasReturnvaluesIF::RETURN_OK;
} else { // } else {
switch(inValue){ // switch(inValue){
case RTEMS_SUCCESSFUL: // case RTEMS_SUCCESSFUL:
return OperatingSystemIF::SUCCESSFUL; // return OperatingSystemIF::SUCCESSFUL;
case RTEMS_TASK_EXITTED: // case RTEMS_TASK_EXITTED:
return OperatingSystemIF::TASK_EXITTED; // return OperatingSystemIF::TASK_EXITTED;
case RTEMS_MP_NOT_CONFIGURED: // case RTEMS_MP_NOT_CONFIGURED:
return OperatingSystemIF::MP_NOT_CONFIGURED; // return OperatingSystemIF::MP_NOT_CONFIGURED;
case RTEMS_INVALID_NAME: // case RTEMS_INVALID_NAME:
return OperatingSystemIF::INVALID_NAME; // return OperatingSystemIF::INVALID_NAME;
case RTEMS_INVALID_ID: // case RTEMS_INVALID_ID:
return OperatingSystemIF::INVALID_ID; // return OperatingSystemIF::INVALID_ID;
case RTEMS_TOO_MANY: // case RTEMS_TOO_MANY:
return OperatingSystemIF::TOO_MANY; // return OperatingSystemIF::TOO_MANY;
case RTEMS_TIMEOUT: // case RTEMS_TIMEOUT:
return OperatingSystemIF::TIMEOUT; // return OperatingSystemIF::TIMEOUT;
case RTEMS_OBJECT_WAS_DELETED: // case RTEMS_OBJECT_WAS_DELETED:
return OperatingSystemIF::OBJECT_WAS_DELETED; // return OperatingSystemIF::OBJECT_WAS_DELETED;
case RTEMS_INVALID_SIZE: // case RTEMS_INVALID_SIZE:
return OperatingSystemIF::INVALID_SIZE; // return OperatingSystemIF::INVALID_SIZE;
case RTEMS_INVALID_ADDRESS: // case RTEMS_INVALID_ADDRESS:
return OperatingSystemIF::INVALID_ADDRESS; // return OperatingSystemIF::INVALID_ADDRESS;
case RTEMS_INVALID_NUMBER: // case RTEMS_INVALID_NUMBER:
return OperatingSystemIF::INVALID_NUMBER; // return OperatingSystemIF::INVALID_NUMBER;
case RTEMS_NOT_DEFINED: // case RTEMS_NOT_DEFINED:
return OperatingSystemIF::NOT_DEFINED; // return OperatingSystemIF::NOT_DEFINED;
case RTEMS_RESOURCE_IN_USE: // case RTEMS_RESOURCE_IN_USE:
return OperatingSystemIF::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 // //TODO RTEMS_UNSATISFIED is double mapped for FLP so it will only return Queue_empty and not unsatisfied
case RTEMS_UNSATISFIED: // case RTEMS_UNSATISFIED:
return OperatingSystemIF::QUEUE_EMPTY; // return OperatingSystemIF::QUEUE_EMPTY;
case RTEMS_INCORRECT_STATE: // case RTEMS_INCORRECT_STATE:
return OperatingSystemIF::INCORRECT_STATE; // return OperatingSystemIF::INCORRECT_STATE;
case RTEMS_ALREADY_SUSPENDED: // case RTEMS_ALREADY_SUSPENDED:
return OperatingSystemIF::ALREADY_SUSPENDED; // return OperatingSystemIF::ALREADY_SUSPENDED;
case RTEMS_ILLEGAL_ON_SELF: // case RTEMS_ILLEGAL_ON_SELF:
return OperatingSystemIF::ILLEGAL_ON_SELF; // return OperatingSystemIF::ILLEGAL_ON_SELF;
case RTEMS_ILLEGAL_ON_REMOTE_OBJECT: // case RTEMS_ILLEGAL_ON_REMOTE_OBJECT:
return OperatingSystemIF::ILLEGAL_ON_REMOTE_OBJECT; // return OperatingSystemIF::ILLEGAL_ON_REMOTE_OBJECT;
case RTEMS_CALLED_FROM_ISR: // case RTEMS_CALLED_FROM_ISR:
return OperatingSystemIF::CALLED_FROM_ISR; // return OperatingSystemIF::CALLED_FROM_ISR;
case RTEMS_INVALID_PRIORITY: // case RTEMS_INVALID_PRIORITY:
return OperatingSystemIF::INVALID_PRIORITY; // return OperatingSystemIF::INVALID_PRIORITY;
case RTEMS_INVALID_CLOCK: // case RTEMS_INVALID_CLOCK:
return OperatingSystemIF::INVALID_CLOCK; // return OperatingSystemIF::INVALID_CLOCK;
case RTEMS_INVALID_NODE: // case RTEMS_INVALID_NODE:
return OperatingSystemIF::INVALID_NODE; // return OperatingSystemIF::INVALID_NODE;
case RTEMS_NOT_CONFIGURED: // case RTEMS_NOT_CONFIGURED:
return OperatingSystemIF::NOT_CONFIGURED; // return OperatingSystemIF::NOT_CONFIGURED;
case RTEMS_NOT_OWNER_OF_RESOURCE: // case RTEMS_NOT_OWNER_OF_RESOURCE:
return OperatingSystemIF::NOT_OWNER_OF_RESOURCE; // return OperatingSystemIF::NOT_OWNER_OF_RESOURCE;
case RTEMS_NOT_IMPLEMENTED: // case RTEMS_NOT_IMPLEMENTED:
return OperatingSystemIF::NOT_IMPLEMENTED; // return OperatingSystemIF::NOT_IMPLEMENTED;
case RTEMS_INTERNAL_ERROR: // case RTEMS_INTERNAL_ERROR:
return OperatingSystemIF::INTERNAL_ERROR; // return OperatingSystemIF::INTERNAL_ERROR;
case RTEMS_NO_MEMORY: // case RTEMS_NO_MEMORY:
return OperatingSystemIF::NO_MEMORY; // return OperatingSystemIF::NO_MEMORY;
case RTEMS_IO_ERROR: // case RTEMS_IO_ERROR:
return OperatingSystemIF::IO_ERROR; // return OperatingSystemIF::IO_ERROR;
default: // default:
return HasReturnvaluesIF::RETURN_FAILED; // return HasReturnvaluesIF::RETURN_FAILED;
} // }
} // }
} //}

View File

@ -2,11 +2,6 @@
#define OS_RTEMS_RTEMSBASIC_H_ #define OS_RTEMS_RTEMSBASIC_H_
#include <framework/returnvalues/HasReturnvaluesIF.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.h>
#include <rtems/libio.h> #include <rtems/libio.h>
#include <rtems/error.h> #include <rtems/error.h>
@ -14,24 +9,15 @@ extern "C" {
#include <stddef.h> #include <stddef.h>
class RtemsBasic: public OperatingSystemIF { class RtemsBasic {
public: 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) { static rtems_interval convertMsToTicks(uint32_t msIn) {
rtems_interval ticks_per_second; rtems_interval ticks_per_second = rtems_clock_get_ticks_per_second();
rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second);
return (ticks_per_second * msIn) / 1000; return (ticks_per_second * msIn) / 1000;
} }
static rtems_interval convertTicksToMs(rtems_interval ticksIn) { static rtems_interval convertTicksToMs(rtems_interval ticksIn) {
rtems_interval ticks_per_second; rtems_interval ticks_per_second = rtems_clock_get_ticks_per_second();
rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second);
return (ticksIn * 1000) / ticks_per_second; return (ticksIn * 1000) / ticks_per_second;
} }
}; };

View File

@ -1,7 +1,7 @@
#include <framework/serviceinterface/ServiceInterfaceStream.h> #include <framework/serviceinterface/ServiceInterfaceStream.h>
#include "TaskBase.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, TaskBase::TaskBase(rtems_task_priority set_priority, size_t stack_size,
const char *name) { 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_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR,
RTEMS_FLOATING_POINT, &id); RTEMS_FLOATING_POINT, &id);
} }
ReturnValue_t result = RtemsBasic::convertReturnCode(status); ReturnValue_t result = convertReturnCode(status);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
error << "TaskBase::TaskBase: createTask with name " << std::hex error << "TaskBase::TaskBase: createTask with name " << std::hex
<< osalName << std::dec << " failed with return code " << osalName << std::dec << " failed with return code "
@ -39,5 +39,44 @@ rtems_id TaskBase::getId() {
ReturnValue_t TaskBase::sleepFor(uint32_t ms) { ReturnValue_t TaskBase::sleepFor(uint32_t ms) {
rtems_status_code status = rtems_task_wake_after(RtemsBasic::convertMsToTicks(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;
} }

View File

@ -37,6 +37,10 @@ public:
rtems_id getId(); rtems_id getId();
ReturnValue_t sleepFor(uint32_t ms); 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);
}; };

View File

@ -2,6 +2,7 @@
#include "MultiObjectTask.h" #include "MultiObjectTask.h"
#include "PollingTask.h" #include "PollingTask.h"
#include "InitTask.h" #include "InitTask.h"
#include "RtemsBasic.h"
#include <framework/returnvalues/HasReturnvaluesIF.h> #include <framework/returnvalues/HasReturnvaluesIF.h>
//TODO: Different variant than the lazy loading in QueueFactory. What's better and why? //TODO: Different variant than the lazy loading in QueueFactory. What's better and why?
@ -14,13 +15,13 @@ TaskFactory* TaskFactory::instance() {
return TaskFactory::factoryInstance; 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(); rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond();
return static_cast<PeriodicTaskIF*>(new MultiObjectTask(name_,taskPriority_,stackSize_,taskPeriod,deadLineMissedFunction_)); 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(); rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond();
return static_cast<FixedTimeslotTaskIF*>(new PollingTask(name_,taskPriority_,stackSize_,taskPeriod,deadLineMissedFunction_)); 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; 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() { TaskFactory::TaskFactory() {
} }

View File

@ -4,7 +4,7 @@
ParameterHelper::ParameterHelper(ReceivesParameterMessagesIF* owner) : ParameterHelper::ParameterHelper(ReceivesParameterMessagesIF* owner) :
owner(owner), storage(NULL) { owner(owner), storage(NULL) {
ownerQueueId = owner->getCommandQueue();
} }
ParameterHelper::~ParameterHelper() { ParameterHelper::~ParameterHelper() {
@ -114,6 +114,9 @@ ReturnValue_t ParameterHelper::sendParameter(MessageQueueId_t to, uint32_t id,
} }
ReturnValue_t ParameterHelper::initialize() { ReturnValue_t ParameterHelper::initialize() {
ownerQueueId = owner->getCommandQueue();
storage = objectManager->get<StorageManagerIF>(objects::IPC_STORE); storage = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
if (storage == NULL) { if (storage == NULL) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;

View File

@ -55,7 +55,10 @@ enum {
DEVICE_COMMUNICATION_IF, //DC DEVICE_COMMUNICATION_IF, //DC
BSP, //BSP BSP, //BSP
TIME_STAMPER_IF, //TSI 52 TIME_STAMPER_IF, //TSI 52
//TODO This will shift all IDs for FLP
SGP4PROPAGATOR_CLASS, //SGP4 53 SGP4PROPAGATOR_CLASS, //SGP4 53
MUTEX_IF, //MUX 54
MESSAGE_QUEUE_IF,//MQI 55
FW_CLASS_ID_COUNT //is actually count + 1 ! FW_CLASS_ID_COUNT //is actually count + 1 !
}; };

View File

@ -5,7 +5,7 @@
#include <stddef.h> #include <stddef.h>
ReturnValue_t RMAP::reset(RMAPCookie* cookie) { ReturnValue_t RMAP::reset(RMAPCookie* cookie) {
return cookie->channel->reset(); return cookie->getChannel()->reset();
} }
RMAP::RMAP(){ RMAP::RMAP(){
@ -22,7 +22,7 @@ ReturnValue_t RMAP::sendWriteCommand(RMAPCookie *cookie, uint8_t* buffer,
if (cookie->getChannel() == NULL) { if (cookie->getChannel() == NULL) {
return COMMAND_NO_CHANNEL; 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, return cookie->getChannel()->sendCommand(cookie, instruction, buffer,
length); length);
@ -32,7 +32,7 @@ ReturnValue_t RMAP::getWriteReply(RMAPCookie *cookie) {
if (cookie->getChannel() == NULL) { if (cookie->getChannel() == NULL) {
return COMMAND_NO_CHANNEL; 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); return cookie->getChannel()->getReply(cookie, NULL, NULL);
} else { } else {
return REPLY_MISSMATCH; return REPLY_MISSMATCH;
@ -53,8 +53,8 @@ ReturnValue_t RMAP::sendReadCommand(RMAPCookie *cookie, uint32_t expLength) {
if (cookie->getChannel() == NULL) { if (cookie->getChannel() == NULL) {
return COMMAND_NO_CHANNEL; return COMMAND_NO_CHANNEL;
} }
command = RMAP_COMMAND_READ command = RMAPIds::RMAP_COMMAND_READ
| (cookie->command_mask & ~(1 << RMAP_COMMAND_BIT_VERIFY)); | (cookie->getCommandMask() & ~(1 << RMAPIds::RMAP_COMMAND_BIT_VERIFY));
return cookie->getChannel()->sendCommand(cookie, command, NULL, expLength); 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) { if (buffer == NULL || size == NULL) {
return DeviceCommunicationIF::NULLPOINTER; 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; return REPLY_MISSMATCH;
} else { } else {
return cookie->getChannel()->getReply(cookie, buffer, size); return cookie->getChannel()->getReply(cookie, buffer, size);

View File

@ -1,11 +1,12 @@
#ifndef RMAPCHANNELIF_H_ #ifndef RMAPCHANNELIF_H_
#define RMAPCHANNELIF_H_ #define RMAPCHANNELIF_H_
#include <framework/rmap/RMAP.h> #include <framework/rmap/RMAPCookie.h>
#include <framework/tasks/PeriodicTaskIF.h> #include <framework/returnvalues/HasReturnvaluesIF.h>
class RMAPChannelIF: public RMAP { class RMAPChannelIF {
public: public:
virtual ~RMAPChannelIF(){};
/** /**
* Reset an RMAP channel * Reset an RMAP channel
* *
@ -42,7 +43,7 @@ public:
* - @c COMMAND_PORT_OUT_OF_RANGE if the port is invalid * - @c COMMAND_PORT_OUT_OF_RANGE if the port is invalid
*/ */
virtual ReturnValue_t setPort(int8_t port, uint8_t dest_addr, 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 * Assign a SpaceWire port to the Channel
@ -54,7 +55,7 @@ public:
* - @c COMMAND_OK if port was changed * - @c COMMAND_OK if port was changed
* - @c COMMAND_PORT_OUT_OF_RANGE if the port is invalid * - @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 * Send an RMAP command

View File

@ -20,13 +20,11 @@ RMAPCookie::RMAPCookie() {
this->header.datalen_m = 0; this->header.datalen_m = 0;
this->header.datalen_l = 0; this->header.datalen_l = 0;
this->header.header_crc = 0; this->header.header_crc = 0;
this->txdesc = NULL;
this->rxdesc_index = 0;
this->channel = NULL; this->channel = NULL;
this->command_mask = 0; this->command_mask = 0;
this->dataCRC = 0;
this->maxReplyLen = 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_m = 0;
this->header.datalen_l = 0; this->header.datalen_l = 0;
this->header.header_crc = 0; this->header.header_crc = 0;
this->txdesc = NULL;
this->rxdesc_index = 0;
this->channel = set_channel; this->channel = set_channel;
this->command_mask = set_command_mask; this->command_mask = set_command_mask;
this->dataCRC = 0;
this->maxReplyLen = maxReplyLen; this->maxReplyLen = maxReplyLen;
} }
@ -104,3 +100,25 @@ uint32_t RMAPCookie::getMaxReplyLen() const {
void RMAPCookie::setMaxReplyLen(uint32_t maxReplyLen) { void RMAPCookie::setMaxReplyLen(uint32_t maxReplyLen) {
this->maxReplyLen = 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;
}

View File

@ -7,8 +7,6 @@
class RMAPChannelIF; class RMAPChannelIF;
class RMAPCookie : public Cookie{ class RMAPCookie : public Cookie{
friend class RMAP;
friend class RmapSPWChannel;
public: public:
//To Uli: Sorry, I need an empty ctor to initialize an array of cookies. //To Uli: Sorry, I need an empty ctor to initialize an array of cookies.
RMAPCookie(); RMAPCookie();
@ -20,24 +18,41 @@ public:
void setAddress(uint32_t address); void setAddress(uint32_t address);
uint32_t getAddress(); uint32_t getAddress();
void setExtendedAddress(uint8_t); void setExtendedAddress(uint8_t);
uint8_t getExtendedAddress(); uint8_t getExtendedAddress();
void setChannel(RMAPChannelIF *channel); void setChannel(RMAPChannelIF *channel);
RMAPChannelIF *getChannel(); RMAPChannelIF *getChannel();
void setCommandMask(uint8_t commandMask); void setCommandMask(uint8_t commandMask);
uint8_t getCommandMask(); uint8_t getCommandMask();
uint32_t getMaxReplyLen() const; uint32_t getMaxReplyLen() const;
void setMaxReplyLen(uint32_t maxReplyLen); 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: protected:
RMAPStructs::rmap_cmd_header header; RMAPStructs::rmap_cmd_header header;
void *txdesc;
uint8_t rxdesc_index;
RMAPChannelIF *channel; RMAPChannelIF *channel;
uint8_t command_mask; uint8_t command_mask;
uint32_t maxReplyLen; uint32_t maxReplyLen;
uint8_t dataCRC;
}; };
#endif /* RMAPCOOKIE_H_ */ #endif /* RMAPCOOKIE_H_ */

View 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;
}

View 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_ */

View File

@ -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;
}

View File

@ -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_ */

View File

@ -7,28 +7,45 @@
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////
// RMAP command bits // RMAP command bits
#define RMAP_COMMAND_BIT_INCREMENT 2 //#define RMAP_COMMAND_BIT_INCREMENT 2
#define RMAP_COMMAND_BIT_REPLY 3 //#define RMAP_COMMAND_BIT_REPLY 3
#define RMAP_COMMAND_BIT_WRITE 5 //#define RMAP_COMMAND_BIT_WRITE 5
#define RMAP_COMMAND_BIT_VERIFY 4 //#define RMAP_COMMAND_BIT_VERIFY 4
#define RMAP_COMMAND_BIT 6 //#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 // RMAP commands
static const uint8_t RMAP_COMMAND_WRITE = ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY));
#define 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_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_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 // useful info
#define RMAP_COMMAND_HEADER_LEN 16 static const uint8_t RMAP_COMMAND_HEADER_LEN = 16;
#define RMAP_WRITE_REPLY_HEADER_LEN 8 static const uint8_t RMAP_WRITE_REPLY_HEADER_LEN = 8;
#define RMAP_READ_REPLY_HEADER_LEN 12 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 { namespace RMAPStructs {
struct rmap_cmd_header { struct rmap_cmd_header {

View File

@ -1,9 +1,9 @@
#ifndef ENDIANSWAPPER_H_ #ifndef ENDIANSWAPPER_H_
#define ENDIANSWAPPER_H_ #define ENDIANSWAPPER_H_
//#include <endian.h> //for testing on x86
#include <framework/osal/Endiness.h> #include <framework/osal/Endiness.h>
#include <cstring> #include <cstring>
#include <iostream>
class EndianSwapper { class EndianSwapper {
private: private:
@ -13,9 +13,9 @@ private:
public: public:
template<typename T> template<typename T>
static T swap(T in) { static T swap(T in) {
#ifndef BYTE_ORDER #ifndef BYTE_ORDER_SYSTEM
#error BYTE_ORDER not defined #error BYTE_ORDER_SYSTEM not defined
#elif BYTE_ORDER == LITTLE_ENDIAN #elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
T tmp; T tmp;
uint8_t *pointerOut = (uint8_t *) &tmp; uint8_t *pointerOut = (uint8_t *) &tmp;
uint8_t *pointerIn = (uint8_t *) &in; uint8_t *pointerIn = (uint8_t *) &in;
@ -23,21 +23,21 @@ public:
pointerOut[sizeof(T) - count - 1] = pointerIn[count]; pointerOut[sizeof(T) - count - 1] = pointerIn[count];
} }
return tmp; return tmp;
#elif BYTE_ORDER == BIG_ENDIAN #elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
return in; return in;
#else #else
#error Unknown Byte Order #error Unknown Byte Order
#endif #endif
} }
static void swap(uint8_t* out, const uint8_t* in, uint32_t size) { static void swap(uint8_t* out, const uint8_t* in, uint32_t size) {
#ifndef BYTE_ORDER #ifndef BYTE_ORDER_SYSTEM
#error BYTE_ORDER not defined #error BYTE_ORDER_SYSTEM not defined
#elif BYTE_ORDER == LITTLE_ENDIAN #elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
for (uint8_t count = 0; count < size; count++) { for (uint8_t count = 0; count < size; count++) {
out[size - count - 1] = in[count]; out[size - count - 1] = in[count];
} }
return; return;
#elif BYTE_ORDER == BIG_ENDIAN #elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
memcpy(out, in, size); memcpy(out, in, size);
return; return;
#endif #endif

View File

@ -39,6 +39,7 @@ int ServiceInterfaceBuffer::sync(void) {
return 0; return 0;
} }
#ifndef UT699
ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port) { ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port) {
this->log_message = set_message; this->log_message = set_message;
@ -59,8 +60,11 @@ void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) {
} }
} }
#endif
#ifdef UT699 #ifdef UT699
#include <framework/osal/rtems/Interrupt.h>
ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port) { ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port) {
this->log_message = set_message; this->log_message = set_message;
this->isActive = true; this->isActive = true;

View File

@ -6,7 +6,7 @@
#include <sstream> #include <sstream>
#include <cstdio> #include <cstdio>
#ifndef UT699
class ServiceInterfaceBuffer: public std::basic_streambuf<char, class ServiceInterfaceBuffer: public std::basic_streambuf<char,
std::char_traits<char> > { std::char_traits<char> > {
friend class ServiceInterfaceStream; friend class ServiceInterfaceStream;
@ -36,7 +36,7 @@ private:
// In this function, the characters are parsed. // In this function, the characters are parsed.
void putChars(char const* begin, char const* end); void putChars(char const* begin, char const* end);
}; };
#endif

View File

@ -12,8 +12,7 @@
#include <framework/storagemanager/LocalPool.h> #include <framework/storagemanager/LocalPool.h>
#include <framework/ipc/MutexIF.h> #include <framework/ipc/MutexHelper.h>
#include <framework/ipc/MutexFactory.h>
/** /**
* @brief The PoolManager class provides an intermediate data storage with * @brief The PoolManager class provides an intermediate data storage with
@ -50,20 +49,10 @@ public:
template<uint8_t NUMBER_OF_POOLS> template<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::reserveSpace(const uint32_t size, store_address_t* address, bool ignoreFault) { 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); MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT);
ReturnValue_t status = this->DATA_STORAGE_FULL; ReturnValue_t status = LocalPool<NUMBER_OF_POOLS>::reserveSpace(size,address,ignoreFault);
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 {
return status; return status;
} }
}
template<uint8_t NUMBER_OF_POOLS> template<uint8_t NUMBER_OF_POOLS>
inline PoolManager<NUMBER_OF_POOLS>::PoolManager(object_id_t setObjectId, 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( inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::deleteData(
store_address_t packet_id) { store_address_t packet_id) {
// debug << "PoolManager( " << translateObject(getObjectId()) << " )::deleteData from store " << packet_id.pool_index << ". id is " << packet_id.packet_index << std::endl; // 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); MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT);
ReturnValue_t status = this->RETURN_OK; ReturnValue_t status = LocalPool<NUMBER_OF_POOLS>::deleteData(packet_id);
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 {
return status; return status;
} }
}
template<uint8_t NUMBER_OF_POOLS> template<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::deleteData(uint8_t* buffer, uint32_t size, inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::deleteData(uint8_t* buffer, uint32_t size,
store_address_t* storeId) { store_address_t* storeId) {
ReturnValue_t mutexStatus = mutex->lockMutex(MutexIF::NO_TIMEOUT); MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT);
ReturnValue_t status = this->RETURN_OK; ReturnValue_t status = LocalPool<NUMBER_OF_POOLS>::deleteData(buffer, size, storeId);
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 {
return status; return status;
} }
}
#endif /* POOLMANAGER_H_ */ #endif /* POOLMANAGER_H_ */

View File

@ -8,7 +8,7 @@ SubsystemBase::SubsystemBase(object_id_t setObjectId, object_id_t parent,
SystemObject(setObjectId), mode(initialMode), submode(SUBMODE_NONE), childrenChangedMode( SystemObject(setObjectId), mode(initialMode), submode(SUBMODE_NONE), childrenChangedMode(
false), commandsOutstanding(0), commandQueue(NULL), healthHelper(this, false), commandsOutstanding(0), commandQueue(NULL), healthHelper(this,
setObjectId), modeHelper(this), parentId(parent) { setObjectId), modeHelper(this), parentId(parent) {
QueueFactory::instance()->createMessageQueue(commandQueueDepth, commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth,
CommandMessage::MAX_MESSAGE_SIZE); CommandMessage::MAX_MESSAGE_SIZE);
} }

View File

@ -11,10 +11,11 @@
#ifndef EXECUTABLEOBJECTIF_H_ #ifndef EXECUTABLEOBJECTIF_H_
#define EXECUTABLEOBJECTIF_H_ #define EXECUTABLEOBJECTIF_H_
#include <framework/osal/OperatingSystemIF.h>
class PeriodicTaskIF; class PeriodicTaskIF;
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <cstring>
/** /**
* @brief The interface provides a method to execute objects within a task. * @brief The interface provides a method to execute objects within a task.
* @details The performOperation method, that is required by the interface is * @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 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_ */ #endif /* EXECUTABLEOBJECTIF_H_ */

View File

@ -2,6 +2,7 @@
#define PERIODICTASKIF_H_ #define PERIODICTASKIF_H_
#include <framework/objectmanager/SystemObjectIF.h> #include <framework/objectmanager/SystemObjectIF.h>
#include <cstddef>
class ExecutableObjectIF; class ExecutableObjectIF;
/** /**
* New version of TaskIF * New version of TaskIF
@ -10,7 +11,7 @@ class ExecutableObjectIF;
*/ */
class PeriodicTaskIF { class PeriodicTaskIF {
public: 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. * @brief A virtual destructor as it is mandatory for interfaces.
*/ */
@ -20,7 +21,7 @@ public:
*/ */
virtual ReturnValue_t startTask() = 0; 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; virtual ReturnValue_t sleepFor(uint32_t ms) = 0;

View File

@ -4,7 +4,7 @@
//TODO more generic? //TODO more generic?
typedef const char* TaskName; typedef const char* TaskName;
typedef uint8_t TaskPriority; typedef uint8_t TaskPriority;
typedef uint16_t TaskStackSize; typedef size_t TaskStackSize;
typedef double TaskPeriod; typedef double TaskPeriod;
typedef void (*TaskDeadlineMissedFunction)(); typedef void (*TaskDeadlineMissedFunction)();

View File

@ -52,7 +52,8 @@ ReturnValue_t PUSDistributor::registerService(AcceptsTelecommandsIF* service) {
errorCode = this->queueMap.insert( errorCode = this->queueMap.insert(
std::pair<uint32_t, MessageQueueId_t>(serviceId, queue)).second; std::pair<uint32_t, MessageQueueId_t>(serviceId, queue)).second;
if (errorCode == false) { if (errorCode == false) {
returnValue = OperatingSystemIF::RESOURCE_IN_USE; //TODO Return Code
returnValue = MessageQueueIF::NO_QUEUE;
} }
return returnValue; return returnValue;
} }

View File

@ -20,7 +20,7 @@ ReturnValue_t TcDistributor::performOperation(uint8_t opCode) {
status = tcQueue->receiveMessage(&currentMessage)) { status = tcQueue->receiveMessage(&currentMessage)) {
status = handlePacket(); status = handlePacket();
} }
if (status == OperatingSystemIF::QUEUE_EMPTY) { if (status == MessageQueueIF::EMPTY) {
return RETURN_OK; return RETURN_OK;
} else { } else {
return status; return status;

View File

@ -2,7 +2,6 @@
#define TCDISTRIBUTOR_H_ #define TCDISTRIBUTOR_H_
#include <framework/objectmanager/ObjectManagerIF.h> #include <framework/objectmanager/ObjectManagerIF.h>
#include <framework/objectmanager/SystemObject.h> #include <framework/objectmanager/SystemObject.h>
#include <framework/osal/OperatingSystemIF.h>
#include <framework/returnvalues/HasReturnvaluesIF.h> #include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/storagemanager/StorageManagerIF.h> #include <framework/storagemanager/StorageManagerIF.h>
#include <framework/tasks/ExecutableObjectIF.h> #include <framework/tasks/ExecutableObjectIF.h>

View File

@ -45,7 +45,7 @@ ReturnValue_t CCSDSTime::convertToCcsds(Ccs_mseconds* to,
to->minute = from->minute; to->minute = from->minute;
to->second = from->second; to->second = from->second;
to->secondEminus2 = from->usecond / 10000; to->secondEminus2 = from->usecond / 10000;
to->secondEminus4 = (from->usecond % 10) * 10 / 1000; to->secondEminus4 = (from->usecond % 10000) / 100;
return RETURN_OK; return RETURN_OK;
} }
@ -142,7 +142,7 @@ ReturnValue_t CCSDSTime::convertFromCCS(Clock::TimeOfDay_t* to, const uint8_t* f
if (temp->secondEminus4 >= 100) { if (temp->secondEminus4 >= 100) {
return INVALID_TIME_FORMAT; return INVALID_TIME_FORMAT;
} }
to->usecond += temp->secondEminus4 / 10 * 1000; to->usecond += temp->secondEminus4 * 100;
} }
return RETURN_OK; return RETURN_OK;

View File

@ -49,6 +49,16 @@ public:
virtual ReturnValue_t initialize(); 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: protected:
struct CommandInfo { struct CommandInfo {
struct tcInfo { struct tcInfo {
@ -92,6 +102,11 @@ protected:
object_id_t packetDestination; 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, void sendTmPacket(uint8_t subservice, const uint8_t *data, uint32_t dataLen,
const uint8_t* headerData = NULL, uint32_t headerSize = 0); const uint8_t* headerData = NULL, uint32_t headerSize = 0);
void sendTmPacket(uint8_t subservice, object_id_t objectId, 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( NULL), commandQueue(NULL), requestQueue(NULL), commandMap(
numberOfParallelCommands), failureParameter1(0), failureParameter2( numberOfParallelCommands), failureParameter1(0), failureParameter2(
0), packetSource(setPacketSource), packetDestination( 0), packetSource(setPacketSource), packetDestination(
setPacketDestination) { setPacketDestination),executingTask(NULL) {
commandQueue = QueueFactory::instance()->createMessageQueue(queueDepth); commandQueue = QueueFactory::instance()->createMessageQueue(queueDepth);
requestQueue = QueueFactory::instance()->createMessageQueue(20); //TODO: Funny magic number. requestQueue = QueueFactory::instance()->createMessageQueue(20); //TODO: Funny magic number.
} }

View File

@ -42,7 +42,7 @@ ReturnValue_t PusServiceBase::performOperation(uint8_t opCode) {
this->currentPacket.deletePacket(); this->currentPacket.deletePacket();
errorParameter1 = 0; errorParameter1 = 0;
errorParameter2 = 0; errorParameter2 = 0;
} else if (status == OperatingSystemIF::QUEUE_EMPTY) { } else if (status == MessageQueueIF::EMPTY) {
status = RETURN_OK; status = RETURN_OK;
// debug << "PusService " << (uint16_t)this->serviceId << ": no new packet." << std::endl; // debug << "PusService " << (uint16_t)this->serviceId << ": no new packet." << std::endl;
break; break;

View File

@ -15,10 +15,10 @@ private:
public: public:
SourceSequenceCounter() : sequenceCount(0) {} SourceSequenceCounter() : sequenceCount(0) {}
void increment() { void increment() {
this->sequenceCount = (++this->sequenceCount) % (SpacePacketBase::LIMIT_SEQUENCE_COUNT); sequenceCount = (sequenceCount+1) % (SpacePacketBase::LIMIT_SEQUENCE_COUNT);
} }
void decrement() { void decrement() {
this->sequenceCount = (--this->sequenceCount) % (SpacePacketBase::LIMIT_SEQUENCE_COUNT); sequenceCount = (sequenceCount-1) % (SpacePacketBase::LIMIT_SEQUENCE_COUNT);
} }
uint16_t get() { return this->sequenceCount; } uint16_t get() { return this->sequenceCount; }
void reset(uint16_t toValue = 0) { void reset(uint16_t toValue = 0) {