На повороты проект предыдущий реагирует - это круто. Но чисто внешне реагирует невнятно, да и все переменные хранит в регистрах. Это не круто - регистров мало.
Для этого надо бы использовать память, наконец-таки. Объявим секцию переменных:
Название можно любое в пределах допустимого ассемблером. Оно создаёт секцию в объектном файле, но на результат не влияет. Все секции, объявленные с атрибутом READWRITE получают адреса начиная с 0x20000000 (выставляется в настройках проекта).
читать дальшеПеременные объявляются примерно так:
Ключевое слово DCD означает, что переменная занимает 4 байта. DCW - 2 байта. DCB - 1 байт.
Если бы эти объявления были в секции READONLY, то это были бы константы заданного размера и содержания.
В NOINIT секции в качестве инициализирующего числа не может быть иного, чем ноль. Инициализируется секция всё той же библиотекой, так что если вы не успели её вернуть, а инициализация нужна - самое время это сделать.
Доступ к переменным осуществляется точно так же, как и к регистрам, с помощью команд LDR, STR. Пример:
LDR R0, =rAccelX ; Загрузить в R0 адрес rAccelX
LDR R1, [R0] ; Загрузить в R1 содержимое памяти по адресу R0 размером в 4 байта.
LDRH R1, [R0] ; Загрузить в R1 содержимое памяти по адресу R0 размером в 2 байта.
LDRB R1, [R0] ; Загрузить в R1 содержимое памяти по адресу R0 размером в 1 байт.
Запись осуществляется аналогичными командами. Причём, модификаторов к командам чтения/записи куда как больше, чем H и B. Есть модификаторы загрузки знаковых данных (SH, SB), где при чтении осуществляется знаковое расширение числа до 32 бит. По сути, если там выставлен знаковый бит в исходных данных (7 для SB и 15 для SH), то все старшие разряды заполнятся единицами.
Сам проект претерпел некоторые структурные изменения в главном файле: весь нечитабельный код из главного цикла был удалён и заменён на вызов более понятных процедур WriteAccel и PWMAccel.
Таким образом, теперь на светодиодах можно контролировать наклон относительно поверхности земли: светодиоды светятся с той стороны, которая ниже. И чем ниже больше наклон, тем больше светится. Аналогичный код уже можно пихать в игрушки: шарик, светящийся с одной стороны всегда, как его ни клади. Ну и могущий моргать при перегрузках =D
Ещё одно замечание относительно оформления кода по сохранению регистров в процедурах. Желательно очень, чтоб единовременно сохранялось чётное число регистров, так как ядро любит, чтоб адрес указателя стека всегда был кратен 8 байтам (три нулевых бита в конце указателя). И при наличии вызовов функций, которым это требуется, из ассемблерного кода, где это дело не выполняется, приведёт к ошибке:
Error: L6238E: <модуль>(<секция>) contains invalid call from '~PRES8 (The user did not require code to preserve 8-byte aligment of 8-byte data objects)' function to 'REQ8 (Code was permitted to depend on the 8-byte aligment of 8-byte data items)' function <функция>
Требование на такой режим выравнивания по умолчанию есть у всех функций, написанных на Си. У Ассемблера это можно затребовать директивой PRESERVE8 в начале файла. То есть требование относится ко всем функциям модуля и к их вызовам.
Причём, даже наличие одной функции в модуле, где нечётное количество регистров пихается в стек, приведёт к этой ошибке.
PUSH {R4-R5,LR} ; Может быть причиной ошибки L6238E
PUSH {R4-R6,LR} ; Это ошибки вызвать не может.
И последнее замечание на этот раз про локальные метки.
Сначала необходимо объявить область действия локальных меток с помощью ключевого слова ROUT (routine).
nameofscope ROUT ; Область действия меток с названием nameofscope
Область действует до следующего объявления области. Внутри этой области можно объявлять метки вида <номер от 1 до 99><название области>. Например:
3nameofscope
Переход по таким меткам записывается: B %3nameofscope
Более просто можно записывать только числа:
3 ;Локальная метка 3
B %3 ; Переход на локальную метку 3
Но с названием области более надёжно. Почему метки сделаны так странно - я не знаю, лично мне не нравится.
Хотелось бы пользоваться локальными метками осмысленными и полезными в каждой почти функции: exit, skip и т.д. Но нельзя. Либо добавлять префиксы или по-другому модифицировать название метки, делая её глобальной для модуля, либо использовать числа.
В этот раз изменился только один файл: main.s.
Проект целиком.<< Предыдущее Следующее >>
@темы:
arm,
программизмы,
электроника,
ассемблер,
stm32f4discovery,
stm32