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

📄 os.c

📁 一种适用于单片机上使用的多任务操作系统。在PIC16F877上成功使用。
💻 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 + -