Merge branch 'mueller_BinSempahInterface' into mueller_framework
This commit is contained in:
commit
3c7e2c7cff
@ -1,8 +1,3 @@
|
|||||||
/**
|
|
||||||
* @file BinarySemaphore.cpp
|
|
||||||
*
|
|
||||||
* @date 25.02.2020
|
|
||||||
*/
|
|
||||||
#include <framework/osal/FreeRTOS/BinarySemaphore.h>
|
#include <framework/osal/FreeRTOS/BinarySemaphore.h>
|
||||||
#include <framework/osal/FreeRTOS/TaskManagement.h>
|
#include <framework/osal/FreeRTOS/TaskManagement.h>
|
||||||
|
|
||||||
@ -11,8 +6,7 @@
|
|||||||
BinarySemaphore::BinarySemaphore() {
|
BinarySemaphore::BinarySemaphore() {
|
||||||
handle = xSemaphoreCreateBinary();
|
handle = xSemaphoreCreateBinary();
|
||||||
if(handle == nullptr) {
|
if(handle == nullptr) {
|
||||||
|
sif::error << "Semaphore: Binary semaph creation failure" << std::endl;
|
||||||
sif::error << "Binary semaphore creation failure" << std::endl;
|
|
||||||
}
|
}
|
||||||
xSemaphoreGive(handle);
|
xSemaphoreGive(handle);
|
||||||
}
|
}
|
||||||
@ -133,6 +127,17 @@ void BinarySemaphore::resetSemaphore() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t BinarySemaphore::acquire(uint32_t timeoutMs) {
|
||||||
|
return takeBinarySemaphore(timeoutMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t BinarySemaphore::release() {
|
||||||
|
return giveBinarySemaphore();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t BinarySemaphore::getSemaphoreCounter() {
|
||||||
|
return uxSemaphoreGetCount(handle);
|
||||||
|
}
|
||||||
|
|
||||||
// Be careful with the stack size here. This is called from an ISR!
|
// Be careful with the stack size here. This is called from an ISR!
|
||||||
ReturnValue_t BinarySemaphore::giveBinarySemaphoreFromISR(SemaphoreHandle_t semaphore,
|
ReturnValue_t BinarySemaphore::giveBinarySemaphoreFromISR(SemaphoreHandle_t semaphore,
|
||||||
|
@ -1,30 +1,30 @@
|
|||||||
/**
|
|
||||||
* @file BinarySempahore.h
|
|
||||||
*
|
|
||||||
* @date 25.02.2020
|
|
||||||
*/
|
|
||||||
#ifndef FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_
|
#ifndef FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_
|
||||||
#define FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_
|
#define FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_
|
||||||
|
|
||||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||||
|
#include <framework/tasks/SemaphoreIF.h>
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "FreeRTOS.h"
|
#include <freertos/FreeRTOS.h>
|
||||||
#include "semphr.h"
|
#include <freertos/semphr.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Counting semaphores and implement the new (better)
|
||||||
|
// task notifications. However, those use task notifications require
|
||||||
|
// the task handle. Maybe it would be better to make a separate class
|
||||||
|
// and switch between the classes with #ifdefs.
|
||||||
|
// Task Notifications require FreeRTOS V8.2 something..
|
||||||
/**
|
/**
|
||||||
* @brief OS Tool to achieve synchronization of between tasks or between task and ISR
|
* @brief OS Tool to achieve synchronization of between tasks or between
|
||||||
|
* task and ISR. The default semaphore implementation creates a
|
||||||
|
* binary semaphore, which can only be taken once.
|
||||||
* @details
|
* @details
|
||||||
* Documentation: https://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html
|
* Documentation: https://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html
|
||||||
*
|
*
|
||||||
* SHOULDDO: check freeRTOS version and use new task notifications,
|
* @author R. Mueller
|
||||||
* if non-ancient freeRTOS version is used.
|
|
||||||
*
|
|
||||||
* @ingroup osal
|
* @ingroup osal
|
||||||
*/
|
*/
|
||||||
class BinarySemaphore: public HasReturnvaluesIF {
|
class BinarySemaphore: public SemaphoreIF,
|
||||||
|
public HasReturnvaluesIF {
|
||||||
public:
|
public:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF;
|
static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF;
|
||||||
|
|
||||||
@ -37,39 +37,24 @@ public:
|
|||||||
static constexpr TickType_t BLOCK_TIMEOUT_TICKS = portMAX_DELAY;
|
static constexpr TickType_t BLOCK_TIMEOUT_TICKS = portMAX_DELAY;
|
||||||
static constexpr uint32_t BLOCK_TIMEOUT = portMAX_DELAY;
|
static constexpr uint32_t BLOCK_TIMEOUT = portMAX_DELAY;
|
||||||
|
|
||||||
//! Semaphore timeout
|
//! @brief Default ctor
|
||||||
static constexpr ReturnValue_t SEMAPHORE_TIMEOUT = MAKE_RETURN_CODE(1);
|
|
||||||
/** The current semaphore can not be given, because it is not owned */
|
|
||||||
static constexpr ReturnValue_t SEMAPHORE_NOT_OWNED = MAKE_RETURN_CODE(2);
|
|
||||||
static constexpr ReturnValue_t SEMAPHORE_NULLPOINTER = MAKE_RETURN_CODE(3);
|
|
||||||
|
|
||||||
BinarySemaphore();
|
BinarySemaphore();
|
||||||
|
//! @brief Copy ctor
|
||||||
/**
|
|
||||||
* @brief Copy ctor
|
|
||||||
*/
|
|
||||||
BinarySemaphore(const BinarySemaphore&);
|
BinarySemaphore(const BinarySemaphore&);
|
||||||
|
//! @brief Copy assignment
|
||||||
/**
|
|
||||||
* @brief Copy assignment
|
|
||||||
*/
|
|
||||||
BinarySemaphore& operator=(const BinarySemaphore&);
|
BinarySemaphore& operator=(const BinarySemaphore&);
|
||||||
|
//! @brief Move ctor
|
||||||
/**
|
|
||||||
* @brief Move constructor
|
|
||||||
*/
|
|
||||||
BinarySemaphore (BinarySemaphore &&);
|
BinarySemaphore (BinarySemaphore &&);
|
||||||
|
//! @brief Move assignment
|
||||||
/**
|
|
||||||
* Move assignment
|
|
||||||
*/
|
|
||||||
BinarySemaphore & operator=(BinarySemaphore &&);
|
BinarySemaphore & operator=(BinarySemaphore &&);
|
||||||
|
//! @brief Destructor
|
||||||
/**
|
|
||||||
* Delete the binary semaphore to prevent a memory leak
|
|
||||||
*/
|
|
||||||
virtual ~BinarySemaphore();
|
virtual ~BinarySemaphore();
|
||||||
|
|
||||||
|
ReturnValue_t acquire(uint32_t timeoutMs =
|
||||||
|
BinarySemaphore::NO_BLOCK_TIMEOUT) override;
|
||||||
|
ReturnValue_t release() override;
|
||||||
|
uint8_t getSemaphoreCounter() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Take the binary semaphore.
|
* Take the binary semaphore.
|
||||||
* If the semaphore has already been taken, the task will be blocked
|
* If the semaphore has already been taken, the task will be blocked
|
||||||
@ -127,7 +112,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
static ReturnValue_t giveBinarySemaphoreFromISR(SemaphoreHandle_t semaphore,
|
static ReturnValue_t giveBinarySemaphoreFromISR(SemaphoreHandle_t semaphore,
|
||||||
BaseType_t * higherPriorityTaskWoken);
|
BaseType_t * higherPriorityTaskWoken);
|
||||||
private:
|
|
||||||
|
protected:
|
||||||
SemaphoreHandle_t handle;
|
SemaphoreHandle_t handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
26
osal/FreeRTOS/CountingSemaphore.cpp
Normal file
26
osal/FreeRTOS/CountingSemaphore.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#include <framework/osal/FreeRTOS/CountingSemaphore.h>
|
||||||
|
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||||
|
|
||||||
|
CountingSemaphore::CountingSemaphore(uint8_t count, uint8_t initCount):
|
||||||
|
count(count), initCount(initCount) {
|
||||||
|
handle = xSemaphoreCreateCounting(count, initCount);
|
||||||
|
if(handle == nullptr) {
|
||||||
|
sif::error << "CountingSemaphore: Creation failure" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CountingSemaphore::CountingSemaphore(CountingSemaphore&& other) {
|
||||||
|
handle = xSemaphoreCreateCounting(other.count, other.initCount);
|
||||||
|
if(handle == nullptr) {
|
||||||
|
sif::error << "CountingSemaphore: Creation failure" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CountingSemaphore& CountingSemaphore::operator =(
|
||||||
|
CountingSemaphore&& other) {
|
||||||
|
handle = xSemaphoreCreateCounting(other.count, other.initCount);
|
||||||
|
if(handle == nullptr) {
|
||||||
|
sif::error << "CountingSemaphore: Creation failure" << std::endl;
|
||||||
|
}
|
||||||
|
return * this;
|
||||||
|
}
|
29
osal/FreeRTOS/CountingSemaphore.h
Normal file
29
osal/FreeRTOS/CountingSemaphore.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_
|
||||||
|
#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_
|
||||||
|
#include <framework/osal/FreeRTOS/BinarySemaphore.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Counting semaphores, which can be acquire more than once.
|
||||||
|
* @details
|
||||||
|
* See: https://www.freertos.org/CreateCounting.html
|
||||||
|
* API of counting semaphores is almost identical to binary semaphores,
|
||||||
|
* so we just inherit from binary semaphore and provide the respective
|
||||||
|
* constructors.
|
||||||
|
*/
|
||||||
|
class CountingSemaphore: public BinarySemaphore {
|
||||||
|
public:
|
||||||
|
CountingSemaphore(uint8_t count, uint8_t initCount);
|
||||||
|
//! @brief Copy ctor, disabled
|
||||||
|
CountingSemaphore(const CountingSemaphore&) = delete;
|
||||||
|
//! @brief Copy assignment, disabled
|
||||||
|
CountingSemaphore& operator=(const CountingSemaphore&) = delete;
|
||||||
|
//! @brief Move ctor
|
||||||
|
CountingSemaphore (CountingSemaphore &&);
|
||||||
|
//! @brief Move assignment
|
||||||
|
CountingSemaphore & operator=(CountingSemaphore &&);
|
||||||
|
private:
|
||||||
|
uint8_t count = 0;
|
||||||
|
uint8_t initCount = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ */
|
@ -7,11 +7,10 @@
|
|||||||
// As a first step towards this, introduces system context variable which needs
|
// As a first step towards this, introduces system context variable which needs
|
||||||
// to be switched manually
|
// to be switched manually
|
||||||
// Haven't found function to find system context.
|
// Haven't found function to find system context.
|
||||||
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize) :
|
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize) {
|
||||||
defaultDestination(0),lastPartner(0), callContext(CallContext::task) {
|
|
||||||
handle = xQueueCreate(messageDepth, maxMessageSize);
|
handle = xQueueCreate(messageDepth, maxMessageSize);
|
||||||
if (handle == NULL) {
|
if (handle == NULL) {
|
||||||
sif::error << "MessageQueue creation failed" << std::endl;
|
sif::error << "MessageQueue: Creation failed" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,16 +49,18 @@ ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) {
|
|||||||
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
|
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
|
||||||
MessageQueueMessage* message, MessageQueueId_t sentFrom,
|
MessageQueueMessage* message, MessageQueueId_t sentFrom,
|
||||||
bool ignoreFault) {
|
bool ignoreFault) {
|
||||||
return sendMessageFromMessageQueue(sendTo,message,sentFrom,ignoreFault, callContext);
|
return sendMessageFromMessageQueue(sendTo, message, sentFrom,
|
||||||
|
ignoreFault, callContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::handleSendResult(BaseType_t result, bool ignoreFault) {
|
ReturnValue_t MessageQueue::handleSendResult(BaseType_t result, bool ignoreFault) {
|
||||||
if (result != pdPASS) {
|
if (result != pdPASS) {
|
||||||
if (!ignoreFault) {
|
if (not ignoreFault) {
|
||||||
InternalErrorReporterIF* internalErrorReporter = objectManager->get<InternalErrorReporterIF>(
|
InternalErrorReporterIF* internalErrorReporter =
|
||||||
|
objectManager->get<InternalErrorReporterIF>(
|
||||||
objects::INTERNAL_ERROR_REPORTER);
|
objects::INTERNAL_ERROR_REPORTER);
|
||||||
if (internalErrorReporter != NULL) {
|
if (internalErrorReporter != nullptr) {
|
||||||
internalErrorReporter->queueMessageNotSent();
|
internalErrorReporter->queueMessageNotSent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,7 +79,8 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) {
|
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) {
|
||||||
BaseType_t result = xQueueReceive(handle,reinterpret_cast<void*>(message->getBuffer()), 0);
|
BaseType_t result = xQueueReceive(handle,reinterpret_cast<void*>(
|
||||||
|
message->getBuffer()), 0);
|
||||||
if (result == pdPASS){
|
if (result == pdPASS){
|
||||||
this->lastPartner = message->getSender();
|
this->lastPartner = message->getSender();
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
@ -103,6 +105,7 @@ MessageQueueId_t MessageQueue::getId() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
|
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
|
||||||
|
defaultDestinationSet = true;
|
||||||
this->defaultDestination = defaultDestination;
|
this->defaultDestination = defaultDestination;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +114,7 @@ MessageQueueId_t MessageQueue::getDefaultDestination() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool MessageQueue::isDefaultDestinationSet() const {
|
bool MessageQueue::isDefaultDestinationSet() const {
|
||||||
return 0;
|
return defaultDestinationSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -126,9 +129,9 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
|||||||
static_cast<const void*>(message->getBuffer()), 0);
|
static_cast<const void*>(message->getBuffer()), 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// If the call context is from an interrupt,
|
/* If the call context is from an interrupt,
|
||||||
// request a context switch if a higher priority task
|
* request a context switch if a higher priority task
|
||||||
// was blocked by the interrupt.
|
* was blocked by the interrupt. */
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||||
result = xQueueSendFromISR(reinterpret_cast<QueueHandle_t>(sendTo),
|
result = xQueueSendFromISR(reinterpret_cast<QueueHandle_t>(sendTo),
|
||||||
static_cast<const void*>(message->getBuffer()),
|
static_cast<const void*>(message->getBuffer()),
|
||||||
|
@ -12,28 +12,30 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: this class assumes that MessageQueueId_t is the same size as void*
|
||||||
//TODO this class assumes that MessageQueueId_t is the same size as void* (the FreeRTOS handle type), compiler will catch this but it might be nice to have something checking or even an always working solution
|
// (the FreeRTOS handle type), compiler will catch this but it might be nice
|
||||||
|
// to have something checking or even an always working solution
|
||||||
// https://scaryreasoner.wordpress.com/2009/02/28/checking-sizeof-at-compile-time/
|
// https://scaryreasoner.wordpress.com/2009/02/28/checking-sizeof-at-compile-time/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This class manages sending and receiving of message queue messages.
|
* @brief This class manages sending and receiving of
|
||||||
*
|
* message queue messages.
|
||||||
* @details Message queues are used to pass asynchronous messages between processes.
|
* @details
|
||||||
|
* Message queues are used to pass asynchronous messages between processes.
|
||||||
* They work like post boxes, where all incoming messages are stored in FIFO
|
* 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
|
* order. This class creates a new receiving queue and provides methods to fetch
|
||||||
* received messages. Being a child of MessageQueueSender, this class also provides
|
* received messages. Being a child of MessageQueueSender, this class also
|
||||||
* methods to send a message to a user-defined or a default destination. In addition
|
* provides methods to send a message to a user-defined or a default destination.
|
||||||
* it also provides a reply method to answer to the queue it received its last message
|
* In addition it also provides a reply method to answer to the queue it
|
||||||
* from.
|
* received its last message from.
|
||||||
*
|
*
|
||||||
* The MessageQueue should be used as "post box" for a single owning object. So all
|
* The MessageQueue should be used as "post box" for a single owning object.
|
||||||
* message queue communication is "n-to-one".
|
* So all message queue communication is "n-to-one".
|
||||||
* For creating the queue, as well as sending and receiving messages, the class makes
|
* For creating the queue, as well as sending and receiving messages, the class
|
||||||
* use of the operating system calls provided.
|
* makes use of the operating system calls provided.
|
||||||
*
|
*
|
||||||
* Please keep in mind that FreeRTOS offers
|
* Please keep in mind that FreeRTOS offers different calls for message queue
|
||||||
* different calls for message queue operations if called from an ISR.
|
* operations if called from an ISR.
|
||||||
* For now, the system context needs to be switched manually.
|
* For now, the system context needs to be switched manually.
|
||||||
* @ingroup osal
|
* @ingroup osal
|
||||||
* @ingroup message_queue
|
* @ingroup message_queue
|
||||||
@ -43,24 +45,38 @@ class MessageQueue : public MessageQueueIF {
|
|||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief The constructor initializes and configures the message queue.
|
* @brief The constructor initializes and configures the message queue.
|
||||||
* @details By making use of the according operating system call, a message queue is created
|
* @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
|
* 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
|
* 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
|
* 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.
|
* 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
|
* @param message_depth
|
||||||
|
* The number of messages to be buffered before passing an error to the
|
||||||
* sender. Default is three.
|
* sender. Default is three.
|
||||||
* @param max_message_size With this parameter, the maximum message size can be adjusted.
|
* @param max_message_size
|
||||||
|
* With this parameter, the maximum message size can be adjusted.
|
||||||
* This should be left default.
|
* This should be left default.
|
||||||
*/
|
*/
|
||||||
MessageQueue( size_t message_depth = 3, size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE );
|
MessageQueue( size_t messageDepth = 3,
|
||||||
|
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE );
|
||||||
|
|
||||||
|
/** Copying message queues forbidden */
|
||||||
|
MessageQueue(const MessageQueue&) = delete;
|
||||||
|
MessageQueue& operator=(const MessageQueue&) = delete;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The destructor deletes the formerly created message queue.
|
* @brief The destructor deletes the formerly created message queue.
|
||||||
* @details This is accomplished by using the delete call provided by the operating system.
|
* @details This is accomplished by using the delete call provided
|
||||||
|
* by the operating system.
|
||||||
*/
|
*/
|
||||||
virtual ~MessageQueue();
|
virtual ~MessageQueue();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is used to switch the call context. This has to be called
|
||||||
|
* if a message is sent or received from an ISR!
|
||||||
|
* @param callContext
|
||||||
|
*/
|
||||||
void switchSystemContext(CallContext callContext);
|
void switchSystemContext(CallContext callContext);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -90,27 +106,28 @@ public:
|
|||||||
ReturnValue_t reply( MessageQueueMessage* message );
|
ReturnValue_t reply( MessageQueueMessage* message );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief With the sendMessage call, a queue message is sent to a receiving queue.
|
* @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
|
* @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
|
* it on to the destination provided with an operating system call. The OS's return
|
||||||
* value is returned.
|
* value is returned.
|
||||||
* \param sendTo This parameter specifies the message queue id to send the message to.
|
* @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 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.
|
||||||
* \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 sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message,
|
virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message,
|
||||||
MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
|
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.
|
||||||
* \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 sendToDefaultFrom( 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 function reads available messages from the message queue and returns the sender.
|
* @brief This function reads available messages from the message queue and returns the sender.
|
||||||
@ -147,27 +164,38 @@ public:
|
|||||||
MessageQueueId_t getId() const;
|
MessageQueueId_t getId() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
<<<<<<< HEAD
|
||||||
* \brief This method is a simple setter for the default destination.
|
* \brief This method is a simple setter for the default destination.
|
||||||
|
=======
|
||||||
|
* @brief This method is a simple setter for the default destination.
|
||||||
|
>>>>>>> mueller_BinSempahInterface
|
||||||
*/
|
*/
|
||||||
void setDefaultDestination(MessageQueueId_t defaultDestination);
|
void setDefaultDestination(MessageQueueId_t defaultDestination);
|
||||||
/**
|
/**
|
||||||
* \brief This method is a simple getter for the default destination.
|
* @brief This method is a simple getter for the default destination.
|
||||||
*/
|
*/
|
||||||
MessageQueueId_t getDefaultDestination() const;
|
MessageQueueId_t getDefaultDestination() const;
|
||||||
|
|
||||||
bool isDefaultDestinationSet() const;
|
bool isDefaultDestinationSet() const;
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Implementation to be called from any send Call within MessageQueue and MessageQueueSenderIF
|
* @brief Implementation to be called from any send Call within
|
||||||
* \details This method takes the message provided, adds the sentFrom information and passes
|
* MessageQueue and MessageQueueSenderIF.
|
||||||
* it on to the destination provided with an operating system call. The OS's return
|
* @details
|
||||||
* value is returned.
|
* This method takes the message provided, adds the sentFrom information and
|
||||||
* \param sendTo This parameter specifies the message queue id to send the message to.
|
* passes it on to the destination provided with an operating system call.
|
||||||
* \param message This is a pointer to a previously created message, which is sent.
|
* The OS's return value is returned.
|
||||||
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
|
* @param sendTo
|
||||||
* This variable is set to zero by default.
|
* This parameter specifies the message queue id to send the message to.
|
||||||
* \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
|
* @param message
|
||||||
* \param context
|
* 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.
|
||||||
|
* @param context Specify whether call is made from task or from an ISR.
|
||||||
*/
|
*/
|
||||||
static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
||||||
MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE,
|
MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE,
|
||||||
@ -175,12 +203,13 @@ protected:
|
|||||||
|
|
||||||
static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault);
|
static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool defaultDestinationSet = false;
|
||||||
QueueHandle_t handle;
|
QueueHandle_t handle;
|
||||||
MessageQueueId_t defaultDestination;
|
MessageQueueId_t defaultDestination = 0;
|
||||||
MessageQueueId_t lastPartner;
|
MessageQueueId_t lastPartner = 0;
|
||||||
CallContext callContext; //!< Stores the current system context
|
//!< Stores the current system context
|
||||||
|
CallContext callContext = CallContext::task;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* MESSAGEQUEUE_H_ */
|
#endif /* MESSAGEQUEUE_H_ */
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
#include <framework/ipc/MutexFactory.h>
|
#include <framework/ipc/MutexFactory.h>
|
||||||
#include <framework/osal/FreeRTOS/Mutex.h>
|
#include <framework/osal/FreeRTOS/Mutex.h>
|
||||||
|
|
||||||
//TODO: Different variant than the lazy loading in QueueFactory. What's better and why? -> one is on heap the other on bss/data
|
//TODO: Different variant than the lazy loading in QueueFactory.
|
||||||
|
//What's better and why? -> one is on heap the other on bss/data
|
||||||
//MutexFactory* MutexFactory::factoryInstance = new MutexFactory();
|
//MutexFactory* MutexFactory::factoryInstance = new MutexFactory();
|
||||||
MutexFactory* MutexFactory::factoryInstance = NULL;
|
MutexFactory* MutexFactory::factoryInstance = nullptr;
|
||||||
|
|
||||||
MutexFactory::MutexFactory() {
|
MutexFactory::MutexFactory() {
|
||||||
}
|
}
|
||||||
@ -12,7 +13,7 @@ MutexFactory::~MutexFactory() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MutexFactory* MutexFactory::instance() {
|
MutexFactory* MutexFactory::instance() {
|
||||||
if (factoryInstance == NULL){
|
if (factoryInstance == nullptr){
|
||||||
factoryInstance = new MutexFactory();
|
factoryInstance = new MutexFactory();
|
||||||
}
|
}
|
||||||
return MutexFactory::factoryInstance;
|
return MutexFactory::factoryInstance;
|
||||||
|
33
osal/FreeRTOS/SemaphoreFactory.cpp
Normal file
33
osal/FreeRTOS/SemaphoreFactory.cpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#include <framework/osal/FreeRTOS/BinarySemaphore.h>
|
||||||
|
#include <framework/osal/FreeRTOS/CountingSemaphore.h>
|
||||||
|
#include <framework/tasks/SemaphoreFactory.h>
|
||||||
|
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||||
|
|
||||||
|
SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr;
|
||||||
|
|
||||||
|
SemaphoreFactory::SemaphoreFactory() {
|
||||||
|
}
|
||||||
|
|
||||||
|
SemaphoreFactory::~SemaphoreFactory() {
|
||||||
|
delete factoryInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
SemaphoreFactory* SemaphoreFactory::instance() {
|
||||||
|
if (factoryInstance == nullptr){
|
||||||
|
factoryInstance = new SemaphoreFactory();
|
||||||
|
}
|
||||||
|
return SemaphoreFactory::factoryInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
SemaphoreIF* SemaphoreFactory::createBinarySemaphore() {
|
||||||
|
return new BinarySemaphore();
|
||||||
|
}
|
||||||
|
|
||||||
|
SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t count,
|
||||||
|
uint8_t initCount) {
|
||||||
|
return new CountingSemaphore(count, initCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SemaphoreFactory::deleteMutex(SemaphoreIF* semaphore) {
|
||||||
|
delete semaphore;
|
||||||
|
}
|
@ -4,7 +4,8 @@ void TaskManagement::requestContextSwitchFromTask() {
|
|||||||
vTaskDelay(0);
|
vTaskDelay(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskManagement::requestContextSwitch(CallContext callContext = CallContext::task) {
|
void TaskManagement::requestContextSwitch(
|
||||||
|
CallContext callContext = CallContext::task) {
|
||||||
if(callContext == CallContext::isr) {
|
if(callContext == CallContext::isr) {
|
||||||
// This function depends on the partmacro.h definition for the specific device
|
// This function depends on the partmacro.h definition for the specific device
|
||||||
requestContextSwitchFromISR();
|
requestContextSwitchFromISR();
|
||||||
@ -20,5 +21,3 @@ TaskHandle_t TaskManagement::getCurrentTaskHandle() {
|
|||||||
configSTACK_DEPTH_TYPE TaskManagement::getTaskStackHighWatermark() {
|
configSTACK_DEPTH_TYPE TaskManagement::getTaskStackHighWatermark() {
|
||||||
return uxTaskGetStackHighWaterMark(TaskManagement::getCurrentTaskHandle());
|
return uxTaskGetStackHighWaterMark(TaskManagement::getCurrentTaskHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,9 +18,9 @@ extern "C" void requestContextSwitchFromISR();
|
|||||||
/*!
|
/*!
|
||||||
* Used by functions to tell if they are being called from
|
* Used by functions to tell if they are being called from
|
||||||
* within an ISR or from a regular task. This is required because FreeRTOS
|
* within an ISR or from a regular task. This is required because FreeRTOS
|
||||||
* has different functions for handling semaphores and messages from within an ISR and task.
|
* has different functions for handling semaphores and messages from within
|
||||||
|
* an ISR and task.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum CallContext {
|
enum CallContext {
|
||||||
task = 0x00,//!< task_context
|
task = 0x00,//!< task_context
|
||||||
isr = 0xFF //!< isr_context
|
isr = 0xFF //!< isr_context
|
||||||
@ -30,10 +30,10 @@ enum CallContext {
|
|||||||
class TaskManagement {
|
class TaskManagement {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* In this function, a function dependant on the portmacro.h header function calls
|
* @brief In this function, a function dependant on the portmacro.h header
|
||||||
* to request a context switch can be specified.
|
* function calls to request a context switch can be specified.
|
||||||
* This can be used if sending to the queue from an ISR caused a task to unblock
|
* This can be used if sending to the queue from an ISR caused a task
|
||||||
* and a context switch is required.
|
* to unblock and a context switch is required.
|
||||||
*/
|
*/
|
||||||
static void requestContextSwitch(CallContext callContext);
|
static void requestContextSwitch(CallContext callContext);
|
||||||
|
|
||||||
|
45
tasks/SemaphoreFactory.h
Normal file
45
tasks/SemaphoreFactory.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#ifndef FRAMEWORK_TASKS_SEMAPHOREFACTORY_H_
|
||||||
|
#define FRAMEWORK_TASKS_SEMAPHOREFACTORY_H_
|
||||||
|
#include <framework/tasks/SemaphoreIF.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates Semaphore.
|
||||||
|
* This class is a "singleton" interface, i.e. it provides an
|
||||||
|
* interface, but also is the base class for a singleton.
|
||||||
|
*/
|
||||||
|
class SemaphoreFactory {
|
||||||
|
public:
|
||||||
|
virtual ~SemaphoreFactory();
|
||||||
|
/**
|
||||||
|
* Returns the single instance of SemaphoreFactory.
|
||||||
|
* The implementation of #instance is found in its subclasses.
|
||||||
|
* Thus, we choose link-time variability of the instance.
|
||||||
|
*/
|
||||||
|
static SemaphoreFactory* instance();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a binary semaphore.
|
||||||
|
* Creator function for a binary semaphore which may only be acquired once
|
||||||
|
* @return Pointer to newly created semaphore class instance.
|
||||||
|
*/
|
||||||
|
SemaphoreIF* createBinarySemaphore();
|
||||||
|
/**
|
||||||
|
* Create a counting semaphore.
|
||||||
|
* Creator functons for a counting semaphore which may be acquired multiple
|
||||||
|
* times.
|
||||||
|
* @param count Semaphore can be taken count times.
|
||||||
|
* @param initCount Initial count value.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
SemaphoreIF* createCountingSemaphore(uint8_t count, uint8_t initCount);
|
||||||
|
void deleteMutex(SemaphoreIF* mutex);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* External instantiation is not allowed.
|
||||||
|
*/
|
||||||
|
SemaphoreFactory();
|
||||||
|
static SemaphoreFactory* factoryInstance;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FRAMEWORK_TASKS_SEMAPHOREFACTORY_H_ */
|
58
tasks/SemaphoreIF.h
Normal file
58
tasks/SemaphoreIF.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#ifndef FRAMEWORK_TASKS_SEMAPHOREIF_H_
|
||||||
|
#define FRAMEWORK_TASKS_SEMAPHOREIF_H_
|
||||||
|
#include <framework/returnvalues/FwClassIds.h>
|
||||||
|
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generic interface for semaphores, which can be used to achieve
|
||||||
|
* task synchronization. This is a generic interface which can be
|
||||||
|
* used for both binary semaphores and counting semaphores.
|
||||||
|
* @details
|
||||||
|
* A semaphore is a synchronization primitive.
|
||||||
|
* See: https://en.wikipedia.org/wiki/Semaphore_(programming)
|
||||||
|
* A semaphore can be used to achieve task synchonization and track the
|
||||||
|
* availability of resources.
|
||||||
|
*
|
||||||
|
* If mutual exlcusion of a resource is desired, a mutex should be used,
|
||||||
|
* which is a special form of a semaphore and has an own interface.
|
||||||
|
*/
|
||||||
|
class SemaphoreIF {
|
||||||
|
public:
|
||||||
|
virtual~ SemaphoreIF() {};
|
||||||
|
//!< Needs to be defined in implementation.
|
||||||
|
static const uint32_t NO_TIMEOUT;
|
||||||
|
static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF;
|
||||||
|
//! Semaphore timeout
|
||||||
|
static constexpr ReturnValue_t SEMAPHORE_TIMEOUT = MAKE_RETURN_CODE(1);
|
||||||
|
//! The current semaphore can not be given, because it is not owned
|
||||||
|
static constexpr ReturnValue_t SEMAPHORE_NOT_OWNED = MAKE_RETURN_CODE(2);
|
||||||
|
static constexpr ReturnValue_t SEMAPHORE_NULLPOINTER = MAKE_RETURN_CODE(3);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic call to acquire a semaphore.
|
||||||
|
* If there are no more semaphores to be taken (for a counting semaphore,
|
||||||
|
* a semaphore may be taken more than once), the taks will block
|
||||||
|
* for a maximum of timeoutMs while trying to acquire the semaphore.
|
||||||
|
* This can be used to achieve task synchrnization.
|
||||||
|
* @param timeoutMs
|
||||||
|
* @return - c RETURN_OK for successfull acquisition
|
||||||
|
*/
|
||||||
|
virtual ReturnValue_t acquire(uint32_t timeoutMs) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Corrensponding call to release a semaphore.
|
||||||
|
* @return -@c RETURN_OK for successfull release
|
||||||
|
*/
|
||||||
|
virtual ReturnValue_t release() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the semaphore is a counting semaphore then the semaphores current
|
||||||
|
* count value is returned. If the semaphore is a binary semaphore then 1
|
||||||
|
* is returned if the semaphore is available, and 0 is returned if the
|
||||||
|
* semaphore is not available.
|
||||||
|
*/
|
||||||
|
virtual uint8_t getSemaphoreCounter() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FRAMEWORK_TASKS_SEMAPHOREIF_H_ */
|
Loading…
Reference in New Issue
Block a user