uOS
uOS - операционная система реального времени.
Автор - Сергей Вакуленко
Авторский сайт - www.vak.ru
Архив исходников также можно взять тут (500 KB)
Для компиляции нужно сделать следующее :
1 Войдите в каталог /targets/i386-dbg
Запустите команду make
Будет сгенерированы 2 обьектных файла :
рантайм-библиотека libuos.a и startup.o.
2 Войдите в каталог /tests/i386
Запустите команду make
Будут сгенерированы несколько бинарных файлов с расширением .out
Фактически это загрузчики , которые запускаются из-под grub .
Например , при запуске t_tcl.out открывается терминал .
В нем можно набрать команду help , которая распечатает список команд .
Запуская эти команды , можно получить информацию о железе и т.д.
А вот тут лежит обрезанная версия.
Она короче на 5 модулей , и все собирается с помощью одного Makefile.
Библиотека libuos.a состоит из набора модулей :
runtime
kernel
stream
random
regexp
mem
tcl
timer
buf
net
crc
snmp
vesa
i8042
input
pci
Модуль runtime : работа с памятью - поиск и копирование , набор символьных функций ,
Модуль kernel : управление задачами , прерываниями , сигналами , наконец главная
задача - main() :
int main (void)
{
/* Create the idle task.
* Align stack on long word boundary. */
task_idle = (task_t*) (((int) task_idle_data + sizeof (long) - 1) &
~(sizeof (long) - 1));
task_idle->stack[0] = STACK_MAGIC;
task_idle->name = CONST("idle");
task_current = task_idle;
task_enqueue (&task_active, task_idle);
/* тут можно создавать пользовательские процессы */
uos_init ();
/* установка приоритета */
MACHDEP_TASK_SWITCH ();
}
Модуль mem : выделение - освобождение памяти
Модуль tcl : интерпретатор языка
uOS представляет собой переносимую масштабируемую операционную систему реального времени
с вытесняющей многозадачностью.
Система uOS построена по модульному принципу . Базовый модуль ядра занимает около
2 килобайт ПЗУ и 200 байт ОЗУ . Набор модулей может наращиваться . В перечень модулей
входят драйверы устройств , диспетчер памяти , сетевые протоколы .
Ядро системы оперирует обьектами 2-х типов - "задача" и "ресурс".
Задача представляет собой поток управления (thread) . Каждая задача имеет отдельный стек .
В процессе выполнения задача может захватывать необходимые ресурсы . При попытке захватить
ресурс , занятый другой задачей , задача блокируется до момента освобождения ресурса .
Т.о каждая задача может находиться в одном из 2-х состояний - выполнения или блокировки .
Каждая задача имеет приоритет , при этом будет выполняться задача с наибольшим приоритетом.
Приоритет создается при создании задачи и по ходу может меняться .
Для отладки каждая задача имеет имя - текстовую строку .
Задачи могут обмениваться сообщениями . Если задача ожидает сообщения от ресурса ,
она блокируется .
При захвате ресурса задача може присвоить ему номер аппаратного прерывания ,
и ожидать сообщения . Для каждого аппаратного прерывания следует создать отдельную задачу,
которая в цикле будет ожидать от прерывания сообщения .
При старте системы вызывается функция пользователя uos_init() , которая посредством
task_create() создает необходимое количество задач . После завершения функции uos_init()
запускается планировщик задач , открываются прерывания и самая приоритетная задача получает управление .
Ниже показана стартовая точка работы загрузчика t_tcl.out :
...
void task_tcl (void *arg)
{
char *cmd;
unsigned char result, got_partial, quit_flag;
Tcl_Interp *interp;
Tcl_CmdBuf buffer;
mem_init (&pool, (mem_size_t) 0x200000, (mem_size_t) 0x400000);
again:
printf ("\nEmbedded TCL\n\n");
printf ("Enter \"help\" for a list of commands\n\n");
interp = Tcl_CreateInterp (&pool);
Tcl_CreateCommand (interp, "loop", loop_cmd, 0, 0);
...
buffer = Tcl_CreateCmdBuf (&pool);
got_partial = 0;
quit_flag = 0;
while (! quit_flag) {
/* clearerr (stdin);*/
if (! got_partial) {
debug_puts ("% ");
}
if (! debug_gets (line, sizeof (line))) {
if (! got_partial)
break;
line[0] = 0;
}
cmd = Tcl_AssembleCmd (buffer, line);
if (! cmd) {
got_partial = 1;
continue;
}
got_partial = 0;
result = Tcl_Eval (interp, cmd, 0, 0);
if (result != TCL_OK) {
debug_puts ("Error");
if (result != TCL_ERROR)
printf (" %d", result);
if (*interp->result != 0)
printf (": %s", interp->result);
debug_putchar (0, '\n');
continue;
}
if (*interp->result != 0)
printf ("%s\n", interp->result);
}
Tcl_DeleteInterp (interp);
Tcl_DeleteCmdBuf (buffer);
goto again;
}
void uos_init (void)
{
task_create (task_tcl, 0, "tcl", 1, task, sizeof (task));
}
Функция uos_halt() - завершает работу системы , используется при отладке .
Задача - представляет собой поток управления (thread) . У каждой задачи свой стек .
Тип task_t :
#include < kernel/uos.h>
typedef struct task_t {
...
}task_t;
task_t *task_create(void (*func)(void*),
void *arg,
char *name,
int priority,
char *stack,
int stacksz);
Это структура , описывающая задачу . ОС производит переключение между задачами .
Для работы с задачами применяются следующие функции :
'task_create'
'task_exit'
'task_delete'
'task_wait'
'task_stack_avail'
'task_name'
'task_priority'
'task_set_priority'
Тип lock_t применяется для работы с ресурсами :
#include < kernel/uos.h>
typedef struct _lock_t {
...
}lock_t;
Применяются следующие функции :
'lock_take' - захват ресурса
'lock_release' - освобождение ресурса
'lock_try' - попытка захвата ресурса
'lock_signal' - посылка сообщения
'lock_wait' - ожидание сообщения
Ниже показана схема работы функции lock_release :
Для обработки аппаратных прерываний применяется механизм сообщений .
При захвате ресурса задача может присвоить ему номер аппаратного прерывания ,
и ожидать сообщения .
После вызова lock_take_irq() аппаратное прерывание считается связанным
с указанным ресурсом . Для каждого аппаратного прерывания , требующего обслуживания ,
следует создать отдельную задачу .
У этого метода обработки прерываний есть недостаток - требуется переключение задач
на каждое прерывание . Если нужна более быстрая реакция на прерывания , применяется механизм
быстрой обработки .
Быстрый обработчик - это функция , которая регистрируется рои захвате ресурса прерывания ,
и вызывается ядром при наступлении прерывания . Обслужив прерывание , такой обработчик принимает
решение - стоит ли основной задаче посылать сообщение о прерывании .
Если ресурс захвачен с помощью lock_take , он может быть освобожден после
lock_release или lock_wait .
Следующая диаграмма показывает работу функции lock_take_irq() , которая захватывает ресурс
и привязывает его к аппаратному прерывани/ю с указанным номером :
|
Roman | Как создать процесс. можно пример простейший, например моргание светодиодом через определенное время. и как скомпилировать под AVR? 2009-09-05 16:20:31 | |
|