Merge branch 'mueller_framework' into front_branch
This commit is contained in:
commit
aea18c423e
@ -12,6 +12,8 @@
|
|||||||
#include <framework/ipc/QueueFactory.h>
|
#include <framework/ipc/QueueFactory.h>
|
||||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
object_id_t DeviceHandlerBase::powerSwitcherId = 0;
|
object_id_t DeviceHandlerBase::powerSwitcherId = 0;
|
||||||
object_id_t DeviceHandlerBase::rawDataReceiverId = 0;
|
object_id_t DeviceHandlerBase::rawDataReceiverId = 0;
|
||||||
object_id_t DeviceHandlerBase::defaultFDIRParentId = 0;
|
object_id_t DeviceHandlerBase::defaultFDIRParentId = 0;
|
||||||
@ -37,6 +39,12 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId,
|
|||||||
CommandMessage::MAX_MESSAGE_SIZE);
|
CommandMessage::MAX_MESSAGE_SIZE);
|
||||||
cookieInfo.state = COOKIE_UNUSED;
|
cookieInfo.state = COOKIE_UNUSED;
|
||||||
insertInCommandMap(RAW_COMMAND_ID);
|
insertInCommandMap(RAW_COMMAND_ID);
|
||||||
|
if (comCookie == nullptr) {
|
||||||
|
sif::error << "DeviceHandlerBase: ObjectID 0x" << std::hex <<
|
||||||
|
std::setw(8) << std::setfill('0') << this->getObjectId() <<
|
||||||
|
std::dec << ": Do not pass nullptr as a cookie, consider "
|
||||||
|
"passing a dummy cookie instead!" << std::endl;
|
||||||
|
}
|
||||||
if (this->fdirInstance == nullptr) {
|
if (this->fdirInstance == nullptr) {
|
||||||
this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId,
|
this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId,
|
||||||
defaultFDIRParentId);
|
defaultFDIRParentId);
|
||||||
@ -44,7 +52,6 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DeviceHandlerBase::~DeviceHandlerBase() {
|
DeviceHandlerBase::~DeviceHandlerBase() {
|
||||||
//communicationInterface->close(cookie);
|
|
||||||
delete comCookie;
|
delete comCookie;
|
||||||
if (defaultFDIRUsed) {
|
if (defaultFDIRUsed) {
|
||||||
delete fdirInstance;
|
delete fdirInstance;
|
||||||
@ -646,8 +653,8 @@ ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress,
|
|||||||
uint8_t * *data, uint32_t * len) {
|
uint8_t * *data, uint32_t * len) {
|
||||||
size_t lenTmp;
|
size_t lenTmp;
|
||||||
|
|
||||||
if (IPCStore == NULL) {
|
if (IPCStore == nullptr) {
|
||||||
*data = NULL;
|
*data = nullptr;
|
||||||
*len = 0;
|
*len = 0;
|
||||||
return RETURN_FAILED;
|
return RETURN_FAILED;
|
||||||
}
|
}
|
||||||
@ -658,7 +665,7 @@ ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress,
|
|||||||
} else {
|
} else {
|
||||||
triggerEvent(StorageManagerIF::GET_DATA_FAILED, result,
|
triggerEvent(StorageManagerIF::GET_DATA_FAILED, result,
|
||||||
storageAddress.raw);
|
storageAddress.raw);
|
||||||
*data = NULL;
|
*data = nullptr;
|
||||||
*len = 0;
|
*len = 0;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1,36 +1,61 @@
|
|||||||
#include <framework/globalfunctions/printer.h>
|
#include <framework/globalfunctions/printer.h>
|
||||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||||
|
#include <bitset>
|
||||||
|
|
||||||
void printer::print(uint8_t *data, size_t size, OutputType type) {
|
void printer::print(const uint8_t *data, size_t size, OutputType type,
|
||||||
sif::info << "Printing data with size " << size << ": [";
|
bool printInfo, size_t maxCharPerLine) {
|
||||||
if(type == OutputType::HEX) {
|
if(printInfo) {
|
||||||
printer::printHex(data, size);
|
sif::info << "Printing data with size " << size << ": ";
|
||||||
}
|
}
|
||||||
else {
|
sif::info << "[";
|
||||||
printer::printDec(data, size);
|
if(type == OutputType::HEX) {
|
||||||
|
printer::printHex(data, size, maxCharPerLine);
|
||||||
|
}
|
||||||
|
else if (type == OutputType::DEC) {
|
||||||
|
printer::printDec(data, size, maxCharPerLine);
|
||||||
|
}
|
||||||
|
else if(type == OutputType::BIN) {
|
||||||
|
printer::printBin(data, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void printer::printHex(uint8_t *data, size_t size) {
|
void printer::printHex(const uint8_t *data, size_t size,
|
||||||
|
size_t maxCharPerLine) {
|
||||||
sif::info << std::hex;
|
sif::info << std::hex;
|
||||||
for(size_t i = 0; i < size; i++) {
|
for(size_t i = 0; i < size; i++) {
|
||||||
sif::info << "0x" << static_cast<int>(data[i]);
|
sif::info << "0x" << static_cast<int>(data[i]);
|
||||||
if(i < size - 1){
|
if(i < size - 1){
|
||||||
sif::info << " , ";
|
sif::info << " , ";
|
||||||
|
if(i > 0 and i % maxCharPerLine == 0) {
|
||||||
|
sif::info << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
sif::info << std::dec;
|
sif::info << std::dec;
|
||||||
sif::info << "]" << std::endl;
|
sif::info << "]" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void printer::printDec(uint8_t *data, size_t size) {
|
void printer::printDec(const uint8_t *data, size_t size,
|
||||||
|
size_t maxCharPerLine) {
|
||||||
sif::info << std::dec;
|
sif::info << std::dec;
|
||||||
for(size_t i = 0; i < size; i++) {
|
for(size_t i = 0; i < size; i++) {
|
||||||
sif::info << "0x" << static_cast<int>(data[i]);
|
sif::info << static_cast<int>(data[i]);
|
||||||
if(i < size - 1){
|
if(i < size - 1){
|
||||||
sif::info << " , ";
|
sif::info << " , ";
|
||||||
|
if(i > 0 and i % maxCharPerLine == 0) {
|
||||||
|
sif::info << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sif::info << "]" << std::endl;
|
sif::info << "]" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void printer::printBin(const uint8_t *data, size_t size) {
|
||||||
|
sif::info << "\n" << std::flush;
|
||||||
|
for(size_t i = 0; i < size; i++) {
|
||||||
|
sif::info << "Byte " << i + 1 << ": 0b"<<
|
||||||
|
std::bitset<8>(data[i]) << ",\n" << std::flush;
|
||||||
|
}
|
||||||
|
sif::info << "]" << std::endl;
|
||||||
|
}
|
||||||
|
@ -7,12 +7,15 @@ namespace printer {
|
|||||||
|
|
||||||
enum class OutputType {
|
enum class OutputType {
|
||||||
DEC,
|
DEC,
|
||||||
HEX
|
HEX,
|
||||||
|
BIN
|
||||||
};
|
};
|
||||||
|
|
||||||
void print(uint8_t* data, size_t size, OutputType type = OutputType::HEX);
|
void print(const uint8_t* data, size_t size, OutputType type = OutputType::HEX,
|
||||||
void printHex(uint8_t* data, size_t size);
|
bool printInfo = true, size_t maxCharPerLine = 12);
|
||||||
void printDec(uint8_t* data, size_t size);
|
void printHex(const uint8_t* data, size_t size, size_t maxCharPerLine = 12);
|
||||||
|
void printDec(const uint8_t* data, size_t size, size_t maxCharPerLine = 12);
|
||||||
|
void printBin(const uint8_t* data, size_t size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* FRAMEWORK_GLOBALFUNCTIONS_PRINTER_H_ */
|
#endif /* FRAMEWORK_GLOBALFUNCTIONS_PRINTER_H_ */
|
||||||
|
@ -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>
|
||||||
|
|
||||||
@ -10,9 +5,8 @@
|
|||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
@ -21,27 +15,6 @@ BinarySemaphore::~BinarySemaphore() {
|
|||||||
vSemaphoreDelete(handle);
|
vSemaphoreDelete(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This copy ctor is important as it prevents the assignment to a ressource
|
|
||||||
// (other.handle) variable which is later deleted!
|
|
||||||
BinarySemaphore::BinarySemaphore(const BinarySemaphore& other) {
|
|
||||||
handle = xSemaphoreCreateBinary();
|
|
||||||
if(handle == nullptr) {
|
|
||||||
sif::error << "Binary semaphore creation failure" << std::endl;
|
|
||||||
}
|
|
||||||
xSemaphoreGive(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
BinarySemaphore& BinarySemaphore::operator =(const BinarySemaphore& s) {
|
|
||||||
if(this != &s) {
|
|
||||||
handle = xSemaphoreCreateBinary();
|
|
||||||
if(handle == nullptr) {
|
|
||||||
sif::error << "Binary semaphore creation failure" << std::endl;
|
|
||||||
}
|
|
||||||
xSemaphoreGive(handle);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) {
|
BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) {
|
||||||
handle = xSemaphoreCreateBinary();
|
handle = xSemaphoreCreateBinary();
|
||||||
if(handle == nullptr) {
|
if(handle == nullptr) {
|
||||||
@ -132,7 +105,18 @@ void BinarySemaphore::resetSemaphore() {
|
|||||||
xSemaphoreGive(handle);
|
xSemaphoreGive(handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
@ -151,4 +135,4 @@ ReturnValue_t BinarySemaphore::giveBinarySemaphoreFromISR(SemaphoreHandle_t sema
|
|||||||
} else {
|
} else {
|
||||||
return SEMAPHORE_NOT_OWNED;
|
return SEMAPHORE_NOT_OWNED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
@ -36,40 +36,25 @@ public:
|
|||||||
//! Can be passed as tick type and ms value.
|
//! Can be passed as tick type and ms value.
|
||||||
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, deleted explicitely.
|
||||||
/**
|
BinarySemaphore(const BinarySemaphore&) = delete;
|
||||||
* @brief Copy ctor
|
//! @brief Copy assignment, deleted explicitely.
|
||||||
*/
|
BinarySemaphore& operator=(const BinarySemaphore&) = delete;
|
||||||
BinarySemaphore(const BinarySemaphore&);
|
//! @brief Move ctor
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Copy assignment
|
|
||||||
*/
|
|
||||||
BinarySemaphore& operator=(const BinarySemaphore&);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
28
osal/FreeRTOS/CountingSemaphore.cpp
Normal file
28
osal/FreeRTOS/CountingSemaphore.cpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include <framework/osal/FreeRTOS/CountingSemaphore.h>
|
||||||
|
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||||
|
|
||||||
|
// Make sure #define configUSE_COUNTING_SEMAPHORES 1 is set in
|
||||||
|
// free FreeRTOSConfig.h file.
|
||||||
|
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,55 +12,71 @@ 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.
|
||||||
|
* 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.
|
||||||
*
|
*
|
||||||
* @details Message queues are used to pass asynchronous messages between processes.
|
* The MessageQueue should be used as "post box" for a single owning object.
|
||||||
* They work like post boxes, where all incoming messages are stored in FIFO
|
* So all message queue communication is "n-to-one".
|
||||||
* order. This class creates a new receiving queue and provides methods to fetch
|
* For creating the queue, as well as sending and receiving messages, the class
|
||||||
* received messages. Being a child of MessageQueueSender, this class also provides
|
* makes use of the operating system calls provided.
|
||||||
* 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
|
* Please keep in mind that FreeRTOS offers different calls for message queue
|
||||||
* message queue communication is "n-to-one".
|
* operations if called from an ISR.
|
||||||
* For creating the queue, as well as sending and receiving messages, the class makes
|
* For now, the system context needs to be switched manually.
|
||||||
* use of the operating system calls provided.
|
* @ingroup osal
|
||||||
*
|
* @ingroup message_queue
|
||||||
* Please keep in mind that FreeRTOS offers
|
|
||||||
* different calls for message queue operations if called from an ISR.
|
|
||||||
* For now, the system context needs to be switched manually.
|
|
||||||
* @ingroup osal
|
|
||||||
* @ingroup message_queue
|
|
||||||
*/
|
*/
|
||||||
class MessageQueue : public MessageQueueIF {
|
class MessageQueue : public MessageQueueIF {
|
||||||
friend class MessageQueueSenderIF;
|
friend class MessageQueueSenderIF;
|
||||||
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
|
||||||
* and initialized. The message depth - the maximum number of messages to be
|
* By making use of the according operating system call, a message queue is created
|
||||||
* buffered - may be set with the help of a parameter, whereas the message size is
|
* and initialized. The message depth - the maximum number of messages to be
|
||||||
* automatically set to the maximum message queue message size. The operating system
|
* buffered - may be set with the help of a parameter, whereas the message size is
|
||||||
* sets the message queue id, or i case of failure, it is set to zero.
|
* automatically set to the maximum message queue message size. The operating system
|
||||||
* @param message_depth The number of messages to be buffered before passing an error to the
|
* sets the message queue id, or i case of failure, it is set to zero.
|
||||||
* sender. Default is three.
|
* @param message_depth
|
||||||
* @param max_message_size With this parameter, the maximum message size can be adjusted.
|
* The number of messages to be buffered before passing an error to the
|
||||||
* This should be left default.
|
* 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 );
|
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;
|
||||||
|
}
|
@ -1,10 +1,11 @@
|
|||||||
#include <framework/osal/FreeRTOS/TaskManagement.h>
|
#include <framework/osal/FreeRTOS/TaskManagement.h>
|
||||||
|
|
||||||
void TaskManagement::requestContextSwitchFromTask() {
|
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();
|
||||||
@ -12,13 +13,11 @@ void TaskManagement::requestContextSwitch(CallContext callContext = CallContext:
|
|||||||
requestContextSwitchFromTask();
|
requestContextSwitchFromTask();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskHandle_t TaskManagement::getCurrentTaskHandle() {
|
TaskHandle_t TaskManagement::getCurrentTaskHandle() {
|
||||||
return xTaskGetCurrentTaskHandle();
|
return xTaskGetCurrentTaskHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
configSTACK_DEPTH_TYPE TaskManagement::getTaskStackHighWatermark() {
|
configSTACK_DEPTH_TYPE TaskManagement::getTaskStackHighWatermark() {
|
||||||
return uxTaskGetStackHighWaterMark(TaskManagement::getCurrentTaskHandle());
|
return uxTaskGetStackHighWaterMark(TaskManagement::getCurrentTaskHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ extern "C" {
|
|||||||
#include <freertos/task.h>
|
#include <freertos/task.h>
|
||||||
}
|
}
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Architecture dependant portmacro.h function call.
|
* Architecture dependant portmacro.h function call.
|
||||||
* Should be implemented in bsp.
|
* Should be implemented in bsp.
|
||||||
@ -17,10 +17,10 @@ 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
|
||||||
@ -29,19 +29,19 @@ 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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If task preemption in FreeRTOS is disabled, a context switch
|
* If task preemption in FreeRTOS is disabled, a context switch
|
||||||
* can be requested manually by calling this function.
|
* can be requested manually by calling this function.
|
||||||
*/
|
*/
|
||||||
static void requestContextSwitchFromTask(void);
|
static void requestContextSwitchFromTask(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The current task handle
|
* @return The current task handle
|
||||||
@ -56,8 +56,8 @@ public:
|
|||||||
* E.g. on a 32 bit machine, a value of 200 means 800 bytes.
|
* E.g. on a 32 bit machine, a value of 200 means 800 bytes.
|
||||||
* @return Smallest value of stack remaining since the task was started in
|
* @return Smallest value of stack remaining since the task was started in
|
||||||
* words.
|
* words.
|
||||||
*/
|
*/
|
||||||
static configSTACK_DEPTH_TYPE getTaskStackHighWatermark();
|
static configSTACK_DEPTH_TYPE getTaskStackHighWatermark();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ */
|
#endif /* FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ */
|
||||||
|
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_ */
|
@ -13,28 +13,28 @@ TcPacketBase::~TcPacketBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t TcPacketBase::getService() {
|
uint8_t TcPacketBase::getService() {
|
||||||
return tcData->data_field.service_type;
|
return tcData->dataField.service_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t TcPacketBase::getSubService() {
|
uint8_t TcPacketBase::getSubService() {
|
||||||
return tcData->data_field.service_subtype;
|
return tcData->dataField.service_subtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t TcPacketBase::getAcknowledgeFlags() {
|
uint8_t TcPacketBase::getAcknowledgeFlags() {
|
||||||
return tcData->data_field.version_type_ack & 0b00001111;
|
return tcData->dataField.version_type_ack & 0b00001111;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t* TcPacketBase::getApplicationData() const {
|
const uint8_t* TcPacketBase::getApplicationData() const {
|
||||||
return &tcData->data;
|
return &tcData->appData;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t TcPacketBase::getApplicationDataSize() {
|
uint16_t TcPacketBase::getApplicationDataSize() {
|
||||||
return getPacketDataLength() - sizeof(tcData->data_field) - CRC_SIZE + 1;
|
return getPacketDataLength() - sizeof(tcData->dataField) - CRC_SIZE + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t TcPacketBase::getErrorControl() {
|
uint16_t TcPacketBase::getErrorControl() {
|
||||||
uint16_t size = getApplicationDataSize() + CRC_SIZE;
|
uint16_t size = getApplicationDataSize() + CRC_SIZE;
|
||||||
uint8_t* p_to_buffer = &tcData->data;
|
uint8_t* p_to_buffer = &tcData->appData;
|
||||||
return (p_to_buffer[size - 2] << 8) + p_to_buffer[size - 1];
|
return (p_to_buffer[size - 2] << 8) + p_to_buffer[size - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,8 +42,8 @@ void TcPacketBase::setErrorControl() {
|
|||||||
uint32_t full_size = getFullSize();
|
uint32_t full_size = getFullSize();
|
||||||
uint16_t crc = CRC::crc16ccitt(getWholeData(), full_size - CRC_SIZE);
|
uint16_t crc = CRC::crc16ccitt(getWholeData(), full_size - CRC_SIZE);
|
||||||
uint32_t size = getApplicationDataSize();
|
uint32_t size = getApplicationDataSize();
|
||||||
(&tcData->data)[size] = (crc & 0XFF00) >> 8; // CRCH
|
(&tcData->appData)[size] = (crc & 0XFF00) >> 8; // CRCH
|
||||||
(&tcData->data)[size + 1] = (crc) & 0X00FF; // CRCL
|
(&tcData->appData)[size + 1] = (crc) & 0X00FF; // CRCL
|
||||||
}
|
}
|
||||||
|
|
||||||
void TcPacketBase::setData(const uint8_t* pData) {
|
void TcPacketBase::setData(const uint8_t* pData) {
|
||||||
@ -51,19 +51,18 @@ void TcPacketBase::setData(const uint8_t* pData) {
|
|||||||
tcData = (TcPacketPointer*) pData;
|
tcData = (TcPacketPointer*) pData;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TcPacketBase::setApplicationData(const uint8_t * pData, uint16_t dataLen) {
|
void TcPacketBase::setAppData(uint8_t * appData, uint16_t dataLen) {
|
||||||
setData(pData);
|
memcpy(&tcData->appData, appData, dataLen);
|
||||||
// packet data length is actual size of data field minus 1
|
|
||||||
SpacePacketBase::setPacketDataLength(dataLen +
|
SpacePacketBase::setPacketDataLength(dataLen +
|
||||||
sizeof(PUSTcDataFieldHeader) + TcPacketBase::CRC_SIZE - 1);
|
sizeof(PUSTcDataFieldHeader) + TcPacketBase::CRC_SIZE - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t TcPacketBase::getSecondaryHeaderFlag() {
|
uint8_t TcPacketBase::getSecondaryHeaderFlag() {
|
||||||
return (tcData->data_field.version_type_ack & 0b10000000) >> 7;
|
return (tcData->dataField.version_type_ack & 0b10000000) >> 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t TcPacketBase::getPusVersionNumber() {
|
uint8_t TcPacketBase::getPusVersionNumber() {
|
||||||
return (tcData->data_field.version_type_ack & 0b01110000) >> 4;
|
return (tcData->dataField.version_type_ack & 0b01110000) >> 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TcPacketBase::print() {
|
void TcPacketBase::print() {
|
||||||
@ -78,14 +77,14 @@ void TcPacketBase::print() {
|
|||||||
void TcPacketBase::initializeTcPacket(uint16_t apid, uint16_t sequenceCount,
|
void TcPacketBase::initializeTcPacket(uint16_t apid, uint16_t sequenceCount,
|
||||||
uint8_t ack, uint8_t service, uint8_t subservice) {
|
uint8_t ack, uint8_t service, uint8_t subservice) {
|
||||||
initSpacePacketHeader(true, true, apid, sequenceCount);
|
initSpacePacketHeader(true, true, apid, sequenceCount);
|
||||||
memset(&tcData->data_field, 0, sizeof(tcData->data_field));
|
memset(&tcData->dataField, 0, sizeof(tcData->dataField));
|
||||||
setPacketDataLength(sizeof(PUSTcDataFieldHeader) + CRC_SIZE - 1);
|
setPacketDataLength(sizeof(PUSTcDataFieldHeader) + CRC_SIZE - 1);
|
||||||
//Data Field Header:
|
//Data Field Header:
|
||||||
//Set CCSDS_secondary_header_flag to 0, version number to 001 and ack to 0000
|
//Set CCSDS_secondary_header_flag to 0, version number to 001 and ack to 0000
|
||||||
tcData->data_field.version_type_ack = 0b00010000;
|
tcData->dataField.version_type_ack = 0b00010000;
|
||||||
tcData->data_field.version_type_ack |= (ack & 0x0F);
|
tcData->dataField.version_type_ack |= (ack & 0x0F);
|
||||||
tcData->data_field.service_type = service;
|
tcData->dataField.service_type = service;
|
||||||
tcData->data_field.service_subtype = subservice;
|
tcData->dataField.service_subtype = subservice;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t TcPacketBase::calculateFullPacketLength(size_t appDataLen) {
|
size_t TcPacketBase::calculateFullPacketLength(size_t appDataLen) {
|
||||||
|
@ -24,8 +24,8 @@ struct PUSTcDataFieldHeader {
|
|||||||
*/
|
*/
|
||||||
struct TcPacketPointer {
|
struct TcPacketPointer {
|
||||||
CCSDSPrimaryHeader primary;
|
CCSDSPrimaryHeader primary;
|
||||||
PUSTcDataFieldHeader data_field;
|
PUSTcDataFieldHeader dataField;
|
||||||
uint8_t data;
|
uint8_t appData;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -168,6 +168,14 @@ public:
|
|||||||
* current content of the packet.
|
* current content of the packet.
|
||||||
*/
|
*/
|
||||||
void setErrorControl();
|
void setErrorControl();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies the supplied data to the internal TC application data field.
|
||||||
|
* @param pData
|
||||||
|
* @param dataLen
|
||||||
|
*/
|
||||||
|
void setAppData(uint8_t * appData, uint16_t dataLen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* With this method, the packet data pointer can be redirected to another
|
* With this method, the packet data pointer can be redirected to another
|
||||||
* location.
|
* location.
|
||||||
@ -178,12 +186,7 @@ public:
|
|||||||
* @param p_data A pointer to another PUS Telecommand Packet.
|
* @param p_data A pointer to another PUS Telecommand Packet.
|
||||||
*/
|
*/
|
||||||
void setData( const uint8_t* pData );
|
void setData( const uint8_t* pData );
|
||||||
/**
|
|
||||||
* Set application data and corresponding length field.
|
|
||||||
* @param pData
|
|
||||||
* @param dataLen
|
|
||||||
*/
|
|
||||||
void setApplicationData(const uint8_t * pData, uint16_t dataLen);
|
|
||||||
/**
|
/**
|
||||||
* This is a debugging helper method that prints the whole packet content
|
* This is a debugging helper method that prints the whole packet content
|
||||||
* to the screen.
|
* to the screen.
|
||||||
|
@ -1,35 +1,47 @@
|
|||||||
#include <framework/objectmanager/ObjectManagerIF.h>
|
#include <framework/objectmanager/ObjectManagerIF.h>
|
||||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||||
#include <framework/tmtcpacket/pus/TcPacketStored.h>
|
#include <framework/tmtcpacket/pus/TcPacketStored.h>
|
||||||
#include <string.h>
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
TcPacketStored::TcPacketStored(store_address_t setAddress) :
|
TcPacketStored::TcPacketStored(store_address_t setAddress) :
|
||||||
TcPacketBase(NULL), storeAddress(setAddress) {
|
TcPacketBase(nullptr), storeAddress(setAddress) {
|
||||||
this->setStoreAddress(this->storeAddress);
|
this->setStoreAddress(this->storeAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
TcPacketStored::TcPacketStored(uint16_t apid, uint8_t ack, uint8_t service,
|
TcPacketStored::TcPacketStored(uint8_t service, uint8_t subservice,
|
||||||
uint8_t subservice, uint8_t sequence_count, const uint8_t* data,
|
uint16_t apid, uint8_t sequence_count, const uint8_t* data,
|
||||||
uint32_t size) :
|
size_t size, uint8_t ack ) :
|
||||||
TcPacketBase(NULL) {
|
TcPacketBase(nullptr) {
|
||||||
this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
|
this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
|
||||||
if (!this->checkAndSetStore()) {
|
if (!this->checkAndSetStore()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint8_t* p_data = NULL;
|
uint8_t* p_data = nullptr;
|
||||||
ReturnValue_t returnValue = this->store->getFreeElement(&this->storeAddress,
|
ReturnValue_t returnValue = this->store->getFreeElement(&this->storeAddress,
|
||||||
(TC_PACKET_MIN_SIZE + size), &p_data);
|
(TC_PACKET_MIN_SIZE + size), &p_data);
|
||||||
if (returnValue != this->store->RETURN_OK) {
|
if (returnValue != this->store->RETURN_OK) {
|
||||||
|
sif::warning << "TcPacketStored: Could not get free element from store!"
|
||||||
|
<< std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->setData(p_data);
|
this->setData(p_data);
|
||||||
initializeTcPacket(apid, sequence_count, ack, service, subservice);
|
initializeTcPacket(apid, sequence_count, ack, service, subservice);
|
||||||
memcpy(&tcData->data, data, size);
|
memcpy(&tcData->appData, data, size);
|
||||||
this->setPacketDataLength(
|
this->setPacketDataLength(
|
||||||
size + sizeof(PUSTcDataFieldHeader) + CRC_SIZE - 1);
|
size + sizeof(PUSTcDataFieldHeader) + CRC_SIZE - 1);
|
||||||
this->setErrorControl();
|
this->setErrorControl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t TcPacketStored::getData(const uint8_t ** dataPtr,
|
||||||
|
size_t* dataSize) {
|
||||||
|
auto result = this->store->getData(storeAddress, dataPtr, dataSize);
|
||||||
|
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
sif::warning << "TcPacketStored: Could not get data!" << std::endl;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
TcPacketStored::TcPacketStored() :
|
TcPacketStored::TcPacketStored() :
|
||||||
TcPacketBase(NULL) {
|
TcPacketBase(NULL) {
|
||||||
this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
|
this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
|
||||||
|
@ -64,7 +64,9 @@ public:
|
|||||||
* @param data The data to be copied to the Application Data Field.
|
* @param data The data to be copied to the Application Data Field.
|
||||||
* @param size The amount of data to be copied.
|
* @param size The amount of data to be copied.
|
||||||
*/
|
*/
|
||||||
TcPacketStored( uint16_t apid, uint8_t ack, uint8_t service, uint8_t subservice, uint8_t sequence_count = 0, const uint8_t* data = NULL, uint32_t size = 0 );
|
TcPacketStored( uint8_t service, uint8_t subservice, uint16_t apid,
|
||||||
|
uint8_t sequence_count = 0, const uint8_t* data = nullptr,
|
||||||
|
size_t size = 0, uint8_t ack = TcPacketBase::ACK_ALL );
|
||||||
/**
|
/**
|
||||||
* Another constructor to create a TcPacket from a raw packet stream.
|
* Another constructor to create a TcPacket from a raw packet stream.
|
||||||
* Takes the data and adds it unchecked to the TcStore.
|
* Takes the data and adds it unchecked to the TcStore.
|
||||||
@ -72,6 +74,9 @@ public:
|
|||||||
* @param Size size of the packet.
|
* @param Size size of the packet.
|
||||||
*/
|
*/
|
||||||
TcPacketStored( const uint8_t* data, uint32_t size);
|
TcPacketStored( const uint8_t* data, uint32_t size);
|
||||||
|
|
||||||
|
ReturnValue_t getData(const uint8_t ** dataPtr,
|
||||||
|
size_t* dataSize);
|
||||||
/**
|
/**
|
||||||
* This is a getter for the current store address of the packet.
|
* This is a getter for the current store address of the packet.
|
||||||
* @return The current store address. The (raw) value is \c StorageManagerIF::INVALID_ADDRESS if
|
* @return The current store address. The (raw) value is \c StorageManagerIF::INVALID_ADDRESS if
|
||||||
|
@ -102,6 +102,11 @@ void TmPacketBase::initializeTmPacket(uint16_t apid, uint8_t service, uint8_t su
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TmPacketBase::setSourceData(uint8_t* sourceData, size_t sourceSize) {
|
||||||
|
memcpy(getSourceData(), sourceData, sourceSize);
|
||||||
|
setSourceDataSize(sourceSize);
|
||||||
|
}
|
||||||
|
|
||||||
void TmPacketBase::setSourceDataSize(uint16_t size) {
|
void TmPacketBase::setSourceDataSize(uint16_t size) {
|
||||||
setPacketDataLength(size + sizeof(PUSTmDataFieldHeader) + CRC_SIZE - 1);
|
setPacketDataLength(size + sizeof(PUSTmDataFieldHeader) + CRC_SIZE - 1);
|
||||||
}
|
}
|
||||||
|
@ -125,6 +125,13 @@ public:
|
|||||||
* current content of the packet.
|
* current content of the packet.
|
||||||
*/
|
*/
|
||||||
void setErrorControl();
|
void setErrorControl();
|
||||||
|
/**
|
||||||
|
* This sets the source data. It copies the provided data to
|
||||||
|
* the internal TmPacketPointer source data location.
|
||||||
|
* @param sourceData
|
||||||
|
* @param sourceSize
|
||||||
|
*/
|
||||||
|
void setSourceData(uint8_t* sourceData, size_t sourceSize);
|
||||||
/**
|
/**
|
||||||
* With this method, the packet data pointer can be redirected to another
|
* With this method, the packet data pointer can be redirected to another
|
||||||
* location.
|
* location.
|
||||||
|
Loading…
Reference in New Issue
Block a user