104 lines
3.5 KiB
C++
104 lines
3.5 KiB
C++
/**
|
|
* \file OPUSPollingTask.cpp
|
|
*
|
|
* \brief This file contains the implementation for the OPUSPollingTask class.
|
|
*
|
|
* \author Bastian Baetz
|
|
*
|
|
* \date 17.03.2011
|
|
*
|
|
*/
|
|
|
|
#include <framework/devicehandlers/PollingTask.h>
|
|
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
|
|
|
uint32_t PollingTask::deadlineMissedCount = 0;
|
|
|
|
PollingTask::PollingTask( const char *name, TaskPriority_t setPriority, size_t setStack, void (*setDeadlineMissedFunc)(), object_id_t getPst ) :
|
|
TaskBase( setPriority, setStack, name ), periodId(0) {
|
|
// All additional attributes are applied to the object.
|
|
this->deadlineMissedFunc = setDeadlineMissedFunc;
|
|
this->pst = objectManager->get<PollingSequence>( getPst );
|
|
}
|
|
|
|
PollingTask::~PollingTask() {
|
|
// The PollingSequence destructor is called, if a sequence is announced.
|
|
if ( this->pst != NULL ) {
|
|
this->pst->~PollingSequence();
|
|
} else {
|
|
// There was no memory allocation, so there's nothing to do.
|
|
}
|
|
}
|
|
|
|
TaskReturn_t PollingTask::taskEntryPoint( TaskArgument_t argument ) {
|
|
|
|
//The argument is re-interpreted as PollingTask.
|
|
PollingTask *originalTask( reinterpret_cast<PollingTask*>( argument ) );
|
|
if ( originalTask->pst != NULL ) {
|
|
//The task's functionality is called.
|
|
originalTask->taskFunctionality();
|
|
} else {
|
|
|
|
}
|
|
debug << "Polling task " << originalTask->getId() << " returned from taskFunctionality." << std::endl;
|
|
}
|
|
|
|
void PollingTask::missedDeadlineCounter() {
|
|
PollingTask::deadlineMissedCount++;
|
|
if (PollingTask::deadlineMissedCount%10 == 0) {
|
|
error << "PST missed " << PollingTask::deadlineMissedCount << " deadlines." << std::endl;
|
|
}
|
|
}
|
|
|
|
ReturnValue_t PollingTask::startTask() {
|
|
this->setRunning( true );
|
|
ReturnValue_t status;
|
|
status = OSAL::startTask( &( this->id ), PollingTask::taskEntryPoint, TaskArgument_t( ( void *)this ) );
|
|
if( status != RETURN_OK ) {
|
|
//TODO: Call any FDIR routine?
|
|
error << "PollingTask::startTask for " << std::hex << this->getId() << std::dec << " failed." << std::endl;
|
|
} else {
|
|
// debug << "PollingTask::startTask for " << std::hex << this->getId() << std::dec << " successful" << std::endl;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
void PollingTask::taskFunctionality() {
|
|
ReturnValue_t status = OSAL::TIMEOUT;
|
|
Interval_t interval;
|
|
// A local iterator for the Polling Sequence Table is created to find the start time for the first entry.
|
|
std::list<PollingSlot*>::iterator it;
|
|
|
|
it = this->pst->current;
|
|
//The start time for the first entry is read.
|
|
interval = ( *it )->pollingTime;
|
|
//The period is set up and started with the system call.
|
|
status = OSAL::setAndStartPeriod( interval, &( this->periodId ) );
|
|
if( status == RETURN_OK ) {
|
|
//The task's "infinite" inner loop is entered.
|
|
while( this->isRunning ) {
|
|
if ( pst->slotFollowsImmediately() ) {
|
|
//Do nothing
|
|
} else {
|
|
//The interval for the next polling slot is selected.
|
|
interval = this->pst->getInterval();
|
|
//The period is checked and restarted with the new interval.
|
|
//If the deadline was missed, the deadlineMissedFunc is called.
|
|
status = OSAL::checkAndRestartPeriod( this->periodId, interval );
|
|
if( status == OSAL::TIMEOUT ) {
|
|
if( this->deadlineMissedFunc != NULL ) {
|
|
this->deadlineMissedFunc();
|
|
}
|
|
}
|
|
}
|
|
//The device handler for this slot is executed and the next one is chosen.
|
|
this->pst->pollAndAdvance();
|
|
}
|
|
} else {
|
|
error << "PollingTask::setAndStartPeriod failed with status "<< status << std::endl;
|
|
}
|
|
//Any operating system object for periodic execution is deleted.
|
|
debug << "Deleting the PollingTask's period." << std::endl;
|
|
OSAL::deletePeriod( &(this->id) );
|
|
}
|