AVR-GCC предава аргументи на main() и използва неговата върната стойност, Embedder - s life
AVR-GCC: предаване на аргументи на main() и използване на неговата върната стойност
За всеки здравомислещ човек е ясно, че при писане на фърмуер за контролер без ОС използването на main() запис с параметри и връщана стойност е напълно безсмислено - няма операционна система, няма откъде да дойдат параметрите и няма откъде да се върне резултатът от изпълнението. Въпреки това, ако не можете, но наистина искате, тогава можете. Как - сега ще ви покажа.
И така, като за начало, малко философия - откъде можете да намерите аргументите за main () във фърмуера? Ако имате ОС, всичко е ясно - това е анализиран команден ред. Нямаме команден ред. Единственото нещо, което изглежда логично, е те да бъдат извлечени отвън, от пристанища. Е, например, свържете DIP превключватели към порта и предадете тяхното състояние с помощта на argv[]. Или получавайте данни чрез UART. По принцип можете да съхранявате аргументите във FLASH, но това е някак безинтересно.
Разбира се, можете също да проверите DIP превключвателите в тялото на main(), но ние не търсим лесни начини, нали? 🙂
Сега, всъщност, за това как да предадете параметри на main (), ако на теория, при липса на операционна система, контролът веднага се прехвърля там. Факт е, че в действителност всичко не е съвсем така - преди main() все още се изпълнява достатъчно служебен код - аз го анализирах подробно в една от предишните статии. Освен това, след main(), линкерът винаги поставя мъниче. И се оказва, че има начин да го помолите учтиво да включи произволен код в секциите за услуги.
Всъщност самите параметри се предават точно по същия начин, както във всяка друга функция.
Така че, за да постигнете целта, просто трябва да напишете код, който поставя параметрите на договорените места, и да помолите линкера да го постави, преди да извикате main (). Е, в същото време (също съгласувано с линкера)напишете нещо, което ще улови върнатата стойност на main() и ще го покаже по някакъв начин.
Ще напишем споменатите части от кода в asma в отделен файл, тъй като изисква активна работа с регистри с общо предназначение, което е трудно да се направи в C, а форматът на вмъкване в AVR-GCC е болезнено объркан. Но по принцип можете да посочите местоположението на кода в секциите за услуги в C.
За да може линкерът да постави кода в желания раздел, той трябва да бъде предшестван от следната директива:
Интересуваме се от секции .init8 (код точно преди main() ) и .fini1 (точно след main() ).
Самите параметри се предават в регистри. Конкретно за нашия случай R25:R24 трябва да съдържа argc, R23:R22 трябва да съдържа указател към argv[], т.е. указател към началото на масив от указатели към байтове.
Реших да спра на два параметъра: първият е стойността на порт B, вторият е стойността на порт D.
Следователно, за да изпълните плана, трябва да направите следното:
1. Създайте променливи в паметта за стойностите PINB и PIND и ги попълнете със съответните стойности, прочетени от портовете (чрез задаване на портовете, разбира се).
2. Създайте масив в паметта под argv[] и поставете указатели към горните променливи в него.
4. Поставете в R25:R24 стойността на argv, броя на аргументите. За нашия случай те са две.
5. Помолете линкера да постави всичко в паметта, преди да извика main().
Така че нека настроим променливи:
И тогава всичко е написано:
Улавянето на върнатата стойност е още по-лесно - реших да я изведа към C порта (по същия начин молим линкера да постави този код след main()):
Експериментите са проведени в Proteus на модела ATmega8515:
Два протейски седемсегментни примитива на дисплея са свързани към порт C, получавайки данни в BCD, програмата C е написана, като се вземе предвидтова.
Основната програма работи по следния алгоритъм: сравнява стойностите на аргументите, след което показва последователно числата от най-малкото до най-голямото; в края показва буквите (всъщност шестнадесетично число) AE - Край на алгоритъма. Ако числата са равни, тогава се извежда EE. Това се прави, за да се покаже как работи връщането.
Основен източник на програмата:
Леле, като това. Архивът съдържа изходни кодове и модел в Proteus за тези, които искат да видят всичко със собствените си очи.
Защо ви трябва такава екзотика? не знам Но работи.