Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate timers and pended functions #596

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/FreeRTOS.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,10 @@
#define INCLUDE_vTaskSuspend 0
#endif

#ifndef configUSE_WORKQUEUE
#define configUSE_WORKQUEUE 1
#endif

#ifdef INCLUDE_xTaskDelayUntil
#ifdef INCLUDE_vTaskDelayUntil

Expand Down
43 changes: 43 additions & 0 deletions include/workqueue.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@

#ifndef WORKQUEUE_H
#define WORKQUEUE_H


#include "FreeRTOS.h"
#include <stdbool.h>
#include "task.h"

/*-----------------------------------------------------------
* MACROS AND DEFINITIONS
*----------------------------------------------------------*/

#if configUSE_WORKQUEUE == 1

#ifndef configWORK_TASK_QUEUE_LENGTH
#error If configUSE_WORKQUEUE is set to 1 then configWORK_TASK_QUEUE_LENGTH must also be defined.
#endif

// TODO: use a default stack size or print a warning instead?
#ifndef configWORK_TASK_STACK_SIZE
#define configWORK_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE*2 )
#endif

#ifndef configWORK_TASK_PRIORITY
#define configWORK_TASK_PRIORITY ( tskIDLE_PRIORITY+1 )
#endif

typedef void (*WorkerFunction_t)(void* pvParam);

extern BaseType_t xWorkerQueueSendFromISR(WorkerFunction_t xFunctionToCall, void* pvParam, BaseType_t * pxHigherPriorityTaskWoken);
extern BaseType_t xWorkerQueueSend(WorkerFunction_t xFunctionToCall, void* pvParam, TickType_t xTicksToWait);


/*
* Functions beyond this part are not part of the public API and are intended
* for use by the kernel only.
*/
BaseType_t xWorkerCreateWorkerTask( void ) PRIVILEGED_FUNCTION;

#endif /* configUSE_WORKQUEUE */

#endif
120 changes: 120 additions & 0 deletions workqueue.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#include "workqueue.h"
#include "FreeRTOS.h"
#include "queue.h"

#if ( configUSE_WORKQUEUE == 1 )

#ifndef configWORK_TASK_NAME
#define configWORK_TASK_NAME "WORKER"
#endif


/* The definition of "work tasks" that can be put on the work queue. */
typedef struct
{
WorkerFunction_t pxCallbackFunction;
void* pvParam;
} CallbackParameters_t;


/*
* The worker task. This task performs low-priority or lengthy operations that
* are defered to it by application software. Other tasks communicate with the
* worker task via the xWorkerQueueSend and xWorkerQueueSendFromISR calls. */
static portTASK_FUNCTION_PROTO( prvWorkerTask, pvParameters ) PRIVILEGED_FUNCTION;


/* the actual queue which holds the tasks that have to be performed. */
PRIVILEGED_DATA static QueueHandle_t xWorkQueue = NULL;

/* the handle to the worker task, in case it will be needed later. */
PRIVILEGED_DATA static TaskHandle_t xWorkTaskHandle = NULL;


/* creates the actual worker task and the associated work queue. */
BaseType_t xWorkerCreateWorkerTask(void)
{
BaseType_t xReturn = pdFAIL;

#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
// TODO: implement static allocation too.
#else

/* create the queue which the work tasks are posted to. If queue creation fails, abort and don't start the worker task. */
xWorkQueue = xQueueCreate(configWORK_TASK_QUEUE_LENGTH, sizeof(CallbackParameters_t));
if(xWorkQueue == NULL)
{
return pdFAIL;
}

/* if the queue creation is successful, create the worker task. If this fails for some reason, the queue is also not needed
* anymore and should be deleted. */
xReturn = xTaskCreate(prvWorkerTask,
configWORK_TASK_NAME,
configWORK_TASK_STACK_SIZE,
NULL,
configWORK_TASK_PRIORITY,
&xWorkTaskHandle);
if(xReturn != pdPASS)
{
vQueueDelete(xWorkQueue);
xWorkQueue = NULL;
return pdFAIL;
}

#endif

return pdPASS;
}



BaseType_t xWorkerQueueSend(WorkerFunction_t xFunctionToCall, void* pvParam, TickType_t xTicksToWait)
{
CallbackParameters_t xCallback;
xCallback.pxCallbackFunction = xFunctionToCall;
xCallback.pvParam = pvParam;
return xQueueSendToBack(xWorkQueue, &xCallback, xTicksToWait);
}



BaseType_t xWorkerQueueSendFromISR(WorkerFunction_t xFunctionToCall, void* pvParam, BaseType_t * pxHigherPriorityTaskWoken)
{
CallbackParameters_t xCallback;
xCallback.pxCallbackFunction = xFunctionToCall;
xCallback.pvParam = pvParam;
return xQueueSendToBackFromISR(xWorkQueue, &xCallback, pxHigherPriorityTaskWoken);
}



static portTASK_FUNCTION( prvWorkerTask, pvParameters )
{
/* parameter is unused. avoid compiler warning. */
(void)pvParameters;

for( ; ; )
{
/* wait on the work queue until actual work tasks are sent to it.
* as long as the queue is empty, there is nothing to do and the worker
* task should stay blocked such that no CPU cycles are wasted to it. */
CallbackParameters_t xCallback;
if(xQueueReceive(xWorkQueue, &xCallback, portMAX_DELAY))
{

/* at least one work task has been sent to the queue. We should determine the
* callback function and its parameter, check the callback function for validity and
* then actually call it. */
WorkerFunction_t pxCallbackFunction = xCallback.pxCallbackFunction;
void* pvParam = xCallback.pvParam;
if(pxCallbackFunction != NULL)
{
pxCallbackFunction(pvParam);
}
}
}
}

#endif