STM8–Выполнение кода из ОЗУ

23 Июня 2011 К комментариям

Рассмотрим как реализовать выполнение программного кода из ОЗУ работая с компилятором Cosmic.

Пример

Самый простой способ выделить область памяти и объявить её отдельной секцией.

Для этого правим файл компоновщика (*.lkf).

Вот типичный пример распределения памяти в простом проекте:

# ОЗУ
+seg .bsct -b 0x0 -m 0x100  -n .bsct
+seg .ubsct -a .bsct  -n .ubsct
+seg .bit -a .ubsct  -n .bit -id

+seg .data -b 0x100 -m 0x4ff  -n .data
+seg .bss -a .data -n .bss

Что есть что:

секция назначение
bsct так называемая “нулевая страница”, предназначена для инициализируемых переменных. Переменные значение которых требуется инициализировать до запуска основного кода. “Нулевая страница” вероятно из-за расположения в памяти, всегда должна быть первой.
ubsct предназначена для переменных не требующих начальной инициализации.
bit предназначенная для переменных размеров в один бит.
data предназначена для инициализируемых переменных.
bss предназначена для переменных не требующих начальной инициализации.

Как видим у последних двух секций назначение совпадает с предыдущими, это связанно с различием в адресации. Для адресации всех данных в нулевой странице достаточно одного байта (short range), для секций data и bss, требуется уже два байта (long range).

Размер секции, начальный адрес и прочие опции определяется с помощью ключей:

+seg добавляем секцию
.bsct имя секции (точка в начале имени обязательна)
-b 0х00 начальный адрес секции
-m 0x100 размер секции
-n .bsct имя секции (как я понял по этому имени секция доступна извне)

Так как нам заранее не известен размер секций (bsct, ubsct, bit), самым простым способом оказалось объявление размера у одной (bsct) и добавление последующих двух (ubsct, bit) в неё. (ключ -a).

Аналогично для секций data и bss.

Код предпочтительно размещать за пределами нулевой секции.

Выделим кусочек для нашего кода:

+seg .data -b 0x100 -m 0x4ff  -n .data
+seg .in_ram -a .data -n .in_ram -ic
+seg .bss -a .erase_in_ram  -n .bss

Для экономии места я просто добавил секцию in_ram без жесткой привязки к памяти.

Ключик –ic помечает указывает что сегмент предназначен для перемещаемого кода, т.е. после компиляции мы будем иметь нужный нам код во флеш-памяти, который нужно будет скопировать в ОЗУ перед использованием.

Для тех кто работает с STVD, все ещё проще нужно просто прописать секцию в настройках проекта:

image

Место выделено, теперь нужно “обрамить” требуемые функции следующим образом:

#pragma section (in_ram)
void run_in_ram(void)
{
}
#pragma section ()

и перед вызовом скопировать код из флеш-памяти в ОЗУ:

_fctcpy('i'); // перед именем подчерк, мой подсветчик кода глючит ;(

Это библиотечная функция предназначена специально для перемещаемого кода, в качестве её аргумента необходимо указать первую букву от названия секции, в данном случае это буква “i” от имени in_ram.

Для использования библиотечной функции нужно сделать её объявление в проекте:

extern int _fctcpy(char name_section);

Функция возвращает ноль при успешном копировании, и не нулевое значение при ошибке.

Ну вот собственно и все.

Как видим все очень просто, если вы свободно владеете английским, к сожалению я такими способностями не обладаю ;( поэтому возможно ошибаюсь в некоторых моментах.

Алгоритм работы описан в документации к компилятору:

C Cross Compiler User’s Guide for ST Microelectronics STM8

в разделе “Перемещаемый код” (Moveable Code).

Стоит заметить что нужно быть внимательным при выполнении кода из ОЗУ, так как если в коде используются библиотечные функции, то будем иметь смешанный код. При чем сами того не замечая мы очень часто используем библиотечные коды, например работа с переменными размером 32 бита требует библиотечные функции (сложение, вычитание и т.п.).

Аналогичным образом реализована работа с кодом в ОЗУ у GCC, используемого мной в работе с микроконтроллерами STM32.

При выполнении кода из ОЗУ как правильно микроконтроллер потребляет меньший ток. Так же при некоторых операциях с памятью (флеш, EEPROM) необходимо выполнение кода из ОЗУ.



comments powered by Disqus