⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os.c

📁 mcu 单片机环境的多任务操作系统的例子
💻 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 + -