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

в 17:26, , рубрики: freertos, multiclet мультиклет, операционные системы, Программинг микроконтроллеров, метки: ,

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 способны выполнять программы широко распространенные на других архитектурах, а с учётом низкого энергопотребления и аппаратного распараллеливания ещё и гораздо эффективнее.

Автор: aaefimov

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js