Портирование FreeRTOS на процессор от «Мультиклет»

от автора

Multiclet & FreeRTOS На Хабре уже было много статей, в которых описывалось применение FreeRTOS или портирование на широко распространенные архитектуры процессоров. В этой статье я хочу поделиться опытом портирования FreeRTOS на российскую архитектуру «Мультиклет» и показать как справляется процессор Multiclet P1 с несколькими параллельными задачами. В качестве примера будет создан GPS трекер с возможностью записи координат на SD, оболочкой через UART, небольшим текстовым редактором и возможностью работы с файловой системой FAT32.

Шаг 1. Портирование.

В качестве примера был использован порт FreeRTOS для ATMega323, т. к. с архитектурой данного процессора я был давно знаком. После изучения файлов стало понятно, что в лоб эту задачу не решить, т. к. для FreeRTOS рекомендуется использовать набор компиляторов GCC (для конкретной архитектуры) с его __attribute__ и asm вставками, а в текущем компиляторе LCC от Multiclet данная возможность отсутствует. Это не стало большой проблемой, единственный атрибут, который был использован в порте для ATMega323, это __attribute__ ((naked)), который говорит компилятору не создавать пролог и эпилог функции. Этот атрибут приписан к функции, которая отвечает за смену контекста задачи и уход на выполнение новой, поэтому важно, чтобы при её вызове не создавался пролог и эпилог (иначе стек\память быстро закончится). Данную функцию и все функции с asm вставками пришлось писать на ассемблере Multiclet.

Следующая проблема, с которой я столкнулся, портируя ОС, это стек. Дело в том, что в процессорах Multiclet нет команд push и pop из-за особенностей архитектуры. Архитектура порта получилась, возможно, слегка мудрёной, но на данный момент я не вижу более
элегантного решения. Идея заключается в следующем: у каждой задачи в ОС своя область памяти, в которой располагаются значения её регистров и стек вызовов, и имеется общий стек ОС, в котором располагаются вызовы функций во время обработки прерываний. Подмена значений регистров #SP и #BP (указатели на базу и фрейм функции) осуществляется в первичном обработчике прерываний (файл crt0.s).

Пример смены задачи в момент прерывания.

Имеются 2 задачи с одинаковым приоритетом. После того, как задачи созданы и добавлены ядром ОС в очередь, будет вызвана функция xPortStartScheduler(void), которая запустит системный таймер и вызовет функцию первичной смены контекста PRS(). В функции PRS() через указатель pxCurrentTCB (pxCurrentTCB — указатель ОС на контекст задачи) устанавливаются значение всех регистров, в том числе #SP и #BP (значение глобальных #SP и #BP сохраняются в переменных gSP и gBP соответственно), отвечающих за стек текущей задачи и переход на её выполнение.

PRS:  	jmp PRS_fin  	PXCTCB:= rdl pxCurrentTCB  	pxTopOfStack:= rdl @PXCTCB  	setl #DI, @pxTopOfStack  complete   PRS_fin:  	reg7 := rdl #DI, pStack  	reg6 := rdl #DI, pStack + 4  	reg5 := rdl #DI, pStack + 8  	reg4 := rdl #DI, pStack + 12  	reg3 := rdl #DI, pStack + 16  	reg2 := rdl #DI, pStack + 20  	reg1 := rdl #DI, pStack + 24  	reg0:= rdl #DI, pStack + 28  	pvp := rdl #DI, pStack + 32  	pxCode := rdl #DI, pStack + 36  	taskSP := rdl #DI, pStack + 40  	taskBP := rdl #DI, pStack + 44  	saveSP := getl #SP  	saveBP := getl #BP  	setl #R7,@reg7  	setl #R6,@reg6  	setl #R5,@reg5  	setl #R4,@reg4  	setl #R3,@reg3  	setl #R2,@reg2  	setl #R1,@reg1  	setl #R0,@reg0  	wrl @saveSP, gSP  	wrl @saveBP, gBP  	setl #SP, @taskSP  	setl #BP, @taskBP  	jmp @pxCode  complete 

В момент возникновения прерывания от системного таймера происходит передача управления на первичный обработчик прерываний.

master.isr:  	jmp mi.hendler  	saveSP := getl #SP  	saveBP := getl #BP  	loadSP := rdl gSP  	loadBP := rdl gBP  	reta := getl #IRETADDR  	wrl @saveSP, iSP </code>  	wrl @saveBP, iBP  	setl #SP, @loadSP  	setl #BP, @loadBP  	wrl @reta, master.isr.retaddr  complete 

В первичном обработчике прерываний (master.isr) заменяются указатели на стек и сохраняется адрес возврата из прерывания, затем вызывается функция смены контекста RTOS.

mi.hendler:  	getl #SP  	getl mi.stop  	getl #INTNUMR  	getl irq.desc.tbl  	mull @2, sizeof.I</code> DT.item  	addl @1, @2  	rdl @1  	jmp @1  	subl @8, sizeof.ptr  	wrl @8, @1  	setl #SP, @2  complete  

Во время смены контекста вызывается функция сохранения контекста текущей задачи, затем планировщик OC установит указатель pxCurrentTCB на задачу, которую необходимо восстановить, и вызывается функция восстановления контекста с передачей управления на эпилог первичного обработчика прерываний.

mi.stop:  	jmp mi.PF  	getl #SP  	addl @1, sizeof.ptr  	setl #SP, @1  complete   mi.PF:  	rdl master.isr.retaddr  	jmp @1  	getq #PSW  	or @1, PSW.ONIRQS  	setq #PSW, @1  	saveSP := getl #SP  	saveBP := getl #BP  	loadSP := rdl iSP  	loadBP := rdl iBP  	wrl @saveSP, gSP  	wrl @saveBP, gBP  	setl #SP, @loadSP  	setl #BP, @loadBP  complete  

Так работает смена задач и стеков FreeRTOS Multiclet P1.

Шаг 2. Пример использования.

В качестве примера реального использования ОС на демонстрационной плате был собран небольшой макет GPS трекера.

Демонстрационная плата

Плата сверху это Pinboard II. Она была использована только в качестве разъёма для SD карты.
Основной задачей с наивысшим приоритетом был эмулятор терминала, реализованный через COM порт.
Терминал
Параллельно выполняемые задачи: запись на SD карту, чтение SD карты, получение данных c GPS приёмника, запись и чтение координатного трека в\из файл(а).
Запись трека
Чтение трека из файла
Полученные данные не достоверны (т. к. GPS приёмник лежал на столе) и демонстрируют только работу с файловой системой. Поместив демонстрационную плату на окно получаем почти верные результаты.
Реальные координаты
Работа ОС с картой памяти осуществлялась при помощи библиотеки FatFS товарища Сhan’a [ elm-chan.org/fsw/ff/00index_e.html ].

Заключение

В данной статье я хотел показать, что процессоры Multiclet способны выполнять программы широко распространенные на других архитектурах, а с учётом низкого энергопотребления и аппаратного распараллеливания ещё и гораздо эффективнее.

ссылка на оригинал статьи http://habrahabr.ru/post/209732/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *