📄 os.c
字号:
/*
* Real time operating system for extra small MCU's
* Sorry, there's no real documentation yet, so here the basic example of usage:
* #include "os.h"
*
* void main() {
* osInit();
* for (;;) { osSched();}
* }
* once in a while you should call also osTimer() function (in this case it is a macro function.
*/
//#define _OS_COUNT_TASKS_
#include <stdlib.h>
#include "os.h"
_OSBANK unsigned int osTicksCounter;
_OSBANK osTaskType osTasks[OS_TASKS];
_OSBANK osMessageType osMessages[OS_EVENTS];
_OSBANK unsigned char osCurrentTask;
_OSBANK unsigned char taskState;
_OSBANK unsigned char osCount;
#ifdef _OS_COUNT_TASKS_
_OSBANK unsigned char osMaxTasks;
#endif//_OS_COUNT_TASKS_
/** scheduler of the OS
* Actions taken here are:
* Parameters: none; Returns: nothing */
void osSched() {
unsigned char i;unsigned char j; unsigned char nextPrio;
_OSBANK static unsigned int oldTicksCounter;
#ifdef _OS_COUNT_TASKS_
unsigned char taskCount;
#endif//_OS_COUNT_TASKS_
osProfilerEnterOsFunction();
/* wake up delayed tasks and find maximal dynamic task priority */
nextPrio = OS_MIN_PRIORITY;
#ifdef _OS_COUNT_TASKS_
taskCount = 0;
#endif//_OS_COUNT_TASKS_
for (i = 0; i < OS_TASKS; i++) {
taskState = osTasks[i].state;
if (oldTicksCounter < osTicksCounter) {
osTasks[i].counterOverflow = false;
}
oldTicksCounter = osTicksCounter;
if (taskState != OS_TASK_STATE_DESTROYED
&& taskState != OS_TASK_STATE_UNDEFINED) {
#ifdef _OS_COUNT_TASKS_
/* if this task exists */
taskCount++;
#endif//_OS_COUNT_TASKS_
if (taskState == OS_TASK_STATE_DELAYED) {
/* delayed tasks handling */
if (osTicksCounter >= osTasks[i].data.delayTicks) {
if (!osTasks[i].counterOverflow) {
/* delay had ended if the ticks counter passed the time
* needed for task resuming. */
osTasks[i].state = OS_TASK_STATE_RUNNING; }
}
} else if (taskState == OS_TASK_STATE_WAITING) {
/* check all messages */
for (j = 0; j < OS_EVENTS; j++) {
/* if this task is waiting for current message and
* its type matches current message type: we have
* a match, transfer the task into running state */
if (osMessages[j].state == OS_MESSAGE_STATE_WAITING &&
osMessages[j].type == osTasks[i].data.msgWaiting) {
osTasks[i].state = OS_TASK_STATE_RUNNING;
osMessages[j].state = OS_MESSAGE_STATE_ANSWERED;
/* if there are two messages of the same type waiting, next
* "break" will keep next message for the next round */
break;
}
}
} else if (taskState == OS_TASK_STATE_RUNNING) {
if (osTasks[i].priority <= nextPrio) {
nextPrio = osTasks[i].priority; }
}
}
}
/* find first task with maximal priority and activate it */
for (i = 0; i < OS_TASKS; i++) {
if (osTasks[i].state == OS_TASK_STATE_RUNNING
&& osTasks[i].priority == nextPrio) {
osCurrentTask = i;
osProfilerExitOsFunction();
(osTasks[i].task)();
osProfilerEnterOsFunction();
osCurrentTask = OS_TASKS; break;
}
}
#ifdef _OS_COUNT_TASKS_
if (osMaxTasks < taskCount) { osMaxTasks = taskCount; }
#endif//_OS_COUNT_TASKS_
osProfilerExitOsFunction();
}
/** creates task
* Parameters: void * - pointer to task function
* char - task initial priority
* Returns: OS_TASKS on failure task id on success */
unsigned char osCreateTask(void *taskPtr, unsigned char prio) {
char i, j;
osProfilerEnterOsFunction();
for (i = 0; i < OS_TASKS; i++) {
j = osTasks[i].state;
if (j == OS_TASK_STATE_DESTROYED || j == OS_TASK_STATE_UNDEFINED) {
osTasks[i].task = taskPtr;
osTasks[i].state = OS_TASK_STATE_ELIGIBLE;
osTasks[i].priority = prio;
osProfilerExitOsFunction(); return i;
}
}
osProfilerExitOsFunction();return OS_TASKS;
}
/** stops current task
* Parameters: id of the tast to stop
* Returns: operation result */
osErrorType osStopTask(unsigned char id) {
osProfilerEnterOsFunction();
if (id >= OS_TASKS) {
osProfilerExitOsFunction();
return OS_ERROR_INVALID_TASK; }
osTasks[id].state = OS_TASK_STATE_STOPPED;
osProfilerExitOsFunction(); return OS_ERROR_NO_ERROR;
}
/** intializes os by undefining all tasks */
void osInit() {
unsigned char i;
osProfilerEnterOsFunction();
/* reset all tasks */
for (i = 0; i < OS_TASKS; i++) {osTasks[i].state = OS_TASK_STATE_UNDEFINED;}
/* reset all messages */
for (i = 0; i < OS_EVENTS; i++) {osMessages[i].type = OS_MESSAGE_STATE_UNDEFINED;}
/* reset ticks counter */
osTicksCounter = 0;
#ifdef _OS_COUNT_TASKS_
/* reset maximal number of tasks counter */
osMaxTasks = 0;
#endif//_OS_COUNT_TASKS_
osProfilerExitOsFunction();
}
/** starts the specified task
* Parameters: task id
* Returns: status success */
osErrorType osStartTask(unsigned char id) {
osProfilerEnterOsFunction();
if (id >= OS_TASKS) {osProfilerExitOsFunction();return OS_ERROR_INVALID_TASK; }
osTasks[id].state = OS_TASK_STATE_RUNNING;
osProfilerExitOsFunction(); return OS_ERROR_NO_ERROR;
}
/** schedules execution of specified task to specified number of clock ticks after current time
* Parameters: number of counter ticks to delay
* Returns: operation result */
osErrorType osDelayTask(unsigned char id, unsigned int ticks) {
unsigned int dt;
osProfilerEnterOsFunction();
/* check that task id is legal */
if (id >= OS_TASKS) {
osProfilerExitOsFunction(); return OS_ERROR_INVALID_TASK; }
/* remember the time after which the task should be activated */
dt = osTicksCounter + ticks;
/* if the time has overflowed, remember it */
if (dt < osTicksCounter) { osTasks[id].counterOverflow = true;
} else { osTasks[id].counterOverflow = false; }
/* set new task state */
osTasks[id].state = OS_TASK_STATE_DELAYED;
osTasks[id].data.delayTicks = dt;
osProfilerExitOsFunction(); return OS_ERROR_NO_ERROR;
}
/** destroys specified task.
* Parameters: id of the tast to destroy
* Returns: OS_ERROR_NO_ERROR on success
* OS_ERROR_INVALID_TASK if the specified task doesn't exist */
osErrorType osDestroyTask(unsigned char id) {
osProfilerEnterOsFunction();
if (id >= OS_TASKS) {
osProfilerExitOsFunction(); return OS_ERROR_INVALID_TASK; }
osTasks[id].state = OS_TASK_STATE_DESTROYED;
osProfilerExitOsFunction(); return OS_ERROR_NO_ERROR;
}
/** creates and sends message
* Parameters: type - type of the message
* void - additional data
* Return: OS_ERROR_NO_ERROR on success
* OS_ERROR_QUEUE_FULL when there's no more space for messages left */
osErrorType osSendMessage(unsigned char type, void * data) {
char i, j;
osProfilerEnterOsFunction();
for (i = 0; i < OS_EVENTS; i++) {
j = osMessages[i].state;
if (j == OS_MESSAGE_STATE_UNDEFINED || j == OS_MESSAGE_STATE_DESTROYED) {
osMessages[i].type = type;
osMessages[i].state = OS_MESSAGE_STATE_WAITING;
osMessages[i].data = data;
osProfilerExitOsFunction();
return OS_ERROR_NO_ERROR; }
}
osProfilerExitOsFunction(); return OS_ERROR_QUEUE_FULL;
}
/** starts waiting for message using specified task, i.e. the task is placed
* into waiting state and awekened when specified message type is received
* Parameters: id - id of the task to use
* type - type of the message to wait for
* Returns: OS_ERROR_INVALID_TASK if the task received is invalide
*/
osErrorType osWaitMessage(unsigned char id, unsigned char type) {
osProfilerEnterOsFunction();
if (id >= OS_TASKS) { osProfilerExitOsFunction();
return OS_ERROR_INVALID_TASK; }
osTasks[id].state = OS_TASK_STATE_WAITING;
osTasks[id].data.msgWaiting = type;
osProfilerExitOsFunction(); return OS_ERROR_NO_ERROR;
}
/** returns message data and erases this message from the queue of messages
* Parameter: type - type of the message
* Returns:
* NULL if the there's no answered message with specified type, otherwise
* returns pointer to data in the message
* Notes:Pay attention!!! In both cases: error or empty data field, this function will return NULL.
* There's no way to tell if the returned value is real or an error occured */
void * osReadMessage(unsigned char type) {
char i, j;
osProfilerEnterOsFunction();
for (i = 0; i < OS_EVENTS; i++) {
j = osMessages[i].state;
if ((j == OS_MESSAGE_STATE_ANSWERED || j == OS_MESSAGE_STATE_WAITING)
&& osMessages[i].type == type) {
osMessages[i].state = OS_MESSAGE_STATE_DESTROYED;
osProfilerExitOsFunction();
return osMessages[i].data; }
}
osProfilerExitOsFunction(); return NULL;
}
/** checks whether message of specified type awaits for answering
* Parameters: message type
* Returns: true - at leas one message of specified type awaits for answering
* false - no unanswered messages of specified exist currently in the system */
unsigned char osCheckMessage(unsigned char type) {
unsigned char i;
osProfilerEnterOsFunction();
for (i = 0; i < OS_EVENTS; i++) {
if (osMessages[i].type == type
&& osMessages[i].state == OS_MESSAGE_STATE_WAITING) {
osProfilerExitOsFunction(); return true; }
}
osProfilerExitOsFunction(); return false;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -