📄 os.c
字号:
/*
* Real time operating system for extra small MCU's
* Copyright (C) 2004 UrK
*
* version 1.1
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* UrK
* Ivmuk
* urk1254@hotmail.co.il
* ivmuk-os comes with ABSOLUTELY NO WARRANTY.
* This is free software, and you are welcome to redistribute it
* under certain conditions.
*
*
*
*
*
*
*
*
*
*
* 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.
* Documentation will be released soon.
* For any questions:
* urk1254@hotmail.com
*/
//#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 + -