Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Кросс-компиляторный шаблон (EC++, IAR, GCC)
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
uni
Доброго, уважаемый форумчане.

Хочу предложить вашему вниманию пробный проект на C++ для объединения в одно целое процесса проектирования для микроконтроллеров AVR.

Я пытаюсь «подружить»: SVN (VisualSVN для VS2008), Proteus 7.6 (ISIS), Enterprise Architect, VS2008, IAR 5.51, WinAVR-20100110, AVR Studio 4 и AVR Studio 5… ух, короче, всё это в одном проекте.

Думается мне, что если писать на чистом C++, без особых выкрутасов, то можно иметь кросс-компиляторный проект в одном почти флаконе. Конкретно этот у меня компилируется и в IAR 5.51 и в WinAVR-20100110.

Цели:
1. Проектирование сверху (UML2).
2. Использование удобной IDE VS2008.
3. Рабочая виртуальная модель для тестов.

Ссылка на хранилище (svn): https://mysvn.ru/cop/Example/ (доступ: чтение)
Клиент для SVN под Windows: TortoiseSVN

Краткое описание есть там в readme.txt.

Отлаживаю одновременно в: ISIS, IAR и AVR Studio (через ubrof8, который генерится IAR'ом специально для этого).

Я пишу «образ» проекта в EA, используя редактор UML2, потом генерю образ(ы) класса(ов) в виде исходников и подключаю их в VS2008. Там же в студии через Makefile компилирую. Отладку, симуляцию можно делать где угодно.

Переключение компилятора в Defines.h (одном месте).
Моделируемая схема: Example.dsn — Proteus ISIS 7.6.

Вся необходимая инфа по сборке исходника в плане используемых портов и пинов находится в файле: Configuration.h

Хочу собрать вирутальную модель модуля АСУТП, работающего по MODBUS (припомощи com2com или аналога).
После этого:
- найти свободный OPC сервер и установить на компе;
- подключить модель Proteus к OPC серверу через COM-порт и MODBUS;
- взять китайску подделку а-ля iPad с версией Android не менее 1.6;
- найти OPC-клиент на Java для Android;
- написать самопальный HMI, который по WiFi будет подсоединяться через OPC-клиент к OPC-серверу;
- повесить планшетник на стенку, приделать в модели Протеуса 1-Wire термометр и любоваться на планшетнике температуру в модели.

------------------------------------

Кто-нить занимался чем-то подобным? В смысле кросс-компиляторности. Интересует использование строк, которые хранятся в памяти программ, т.е. универсальный подход для IAR и GCC.

Нажмите для просмотра прикрепленного файлаНажмите для просмотра прикрепленного файла
Нажмите для просмотра прикрепленного файлаНажмите для просмотра прикрепленного файла

Просто когда-то я был привлёчён вот к такому проектик для AVR'ки. Мягко говоря, он мне показался слегка запутанным и кроме самого кода никаких больше доков. Эту схемку нарисовала уже студия 2008.
Самый крайний правый класс - это пример того как не надо проектировать классы sm.gif он у меня в несколько экранов даже в таком виде не помещается.

Нажмите для просмотра прикрепленного файлаНажмите для просмотра прикрепленного файла
uni
Пример чуть усложнился. Привык я к винде, поэтому написал небольшой движок с обработкой очереди сообщений. Код по написанию окон интерфейса практически один в один теперь будет. Сейчас у меня только один "поток" (WinMain) и одно окно (hWnd = 100). Функция окна "обрабатывает" два сообщения: SW_SHOW и WM_PAINT. Обработчик второго сообщения и рисует эту картинку.

Хотя проект компилится под IAR и GCC, в GCC я пока не нашёл опции по увеличению стека. Вложенных функций стало больше. С этими очередями есть небольшая проблемка, которую я придумал как решить только одним способом - резервированием под себя внешнего прерывания 0, т.к. оно самое приоритетное. Дело в том, что я пока не понял как добавлять в очередь сообщения из прерываний. Я использую две очереди, которые переключаются время от времени. ISR от EI0 нужно для заполнения второй очереди. Посмотрим как получится это реализовать.

Те, кто программит под винду, найдут много знакомого в коде sm.gif
Я очень расточителен в плане организации очереди, главное - работает, а жирок обрезать всегда успею.

Нажмите для просмотра прикрепленного файла
SasaVitebsk
Цитата(uni @ Jul 18 2011, 00:07) *
ух, короче, всё это в одном проекте.

А это зачем????????
Уж если это - простое решение, то я тогда не знаю.
ReAl
Цитата(uni @ Jul 19 2011, 14:14) *
в GCC я пока не нашёл опции по увеличению стека.
А его в большинстве случаев некуда увеличивать. В avr-gcc стек один, указатель инициализируется верхушкой внутреннего ОЗУ, а все переменные располагаются от начала. Таким образом стек автоматически получается максимально возможного размера.

p.s. с prog_char лучше расстаньтесь, avr-libc и документация нуждаются в правке.
http://savannah.nongnu.org/bugs/?33716
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38342
Для С оно ещё катит, в С++ нет. Когда перестанет проходить в С -- неизвестно.
Лучше сразу привыкать давать PROGMEM переменным :-(
neiver
Цитата(uni @ Jul 18 2011, 01:07) *
Кто-нить занимался чем-то подобным? В смысле кросс-компиляторности. Интересует использование строк, которые хранятся в памяти программ, т.е. универсальный подход для IAR и GCC.

У меня есть статейка на эту тему:
http://we.easyelectronics.ru/Soft/avr-s-i-...-ukazateli.html
ReAl
Цитата(neiver @ Jul 20 2011, 17:15) *
У меня есть статейка на эту тему:

Код
        inline const T operator *()const
        {
                union
                {
                        T value;
                        uint8_t bytes[sizeof(T)];
                }data;

                for(unsigned i = 0; i<sizeof(T); ++i)
                        data.bytes[i] = Accessor::Read(_address + i); // <--------  ??? reinterpret_cast<uint8_t*>(_address) + i
                return data.value;
        }
private:
        T * _address; // указатель-то на тип, _address+i полетит далеко
};
uni
Таак... попробую ответить по-порядку.

Раз уж я объял тему AVR, то классику - нужно знать, т.е. ассемблер и Ассемблер от самой фирмы. Ну, хотя бы в общих чертах, чтобы не спрашивать, а где это в инструкциях там операция XOR и как бы её имитировать? sm.gif

Тут дело вот в чём. Посмотрев кучу разных сайтов около-радиолюбительской тематики, где обсуждают различные подходы к программированию AVR'ок (да и других mcu тоже)... в общем выглядит это всё какий-то стихийным разнобоем. А ведь существуют наработки по красивому написанию кода, по понятному написанию кода, по правильному написанию и т.д.

Вот мне тут про prog_char сказали, что от него нужно уходить. Честно говоря у меня в коде он упоминается только раз 5, наверное. Дело в том, что я ещё не устаканился в выборе define'ов, которые были бы общепринятыми и понятными для обозначения аттрибутов памяти. Нужно сделать так, чтобы было удобно и для IAR и для GCC. В доке к GCC есть макро FLASH_DECLARE() - вполне удобная вещь, я её оставил и использую. Там разница только в очередности: у IAR [ __flash имя ] , а у GCC [ имя __attribute__((...)) ].

Так вот. Я пока использую gcc обозначения для аттрибутов памяти. Все типы, по возможности, обявляют как uintN_t. Кроме аналогов типов из windows.h - это экспериментальная поделка, чтобы можно было народ если что даже к MSDN отсылать для справки. Если Вы посмотрите работу схемы в Proteus, то увидите как работает очередь сообщений и идёт их доставка в окно. Вроде, достаточно понятно. Но не это главное, это больше для красоты и универсальности. Многие знают винду изнутри и код будет как бы знакомым.

Есть ещё такие вещи, как инициализация регистров IO. Я давно искал красивое и понятное решение для этого и лет эдак 5 тому назад нашёл таковое:
Код
    // MCU Control Register
    // [ Регистр управления микроконтроллером ]
    //           00000000 - Initial Value
    MCUCR = BIN8(10000000);
    //           ||||||||
    //           |||||||+- 0, rw, IVCE:   - Interrupt Vector Change Enable
    //           ||||||+-- 1, rw, IVSEL:  - Interrupt Vector Select
    //           |||||+--- 2, rw, SM2: -+ - Interrupt 1 Sense Control
    //           ||||+---- 3, rw, SM0: _|
    //           |||+----- 4, rw, SM1:    - Бит 1 выбора режима сна
    //           ||+------ 5, rw, SE:     - Разрешение режима сна
    //           |+------- 6, rw, SRW10:  - Бит выбора режима ожидания
    //           +-------- 7, rw, SRE:    - Включение внешней SRAM/XMEM
    // Примечание:

Вот так это выглядит. Наверное заметили в коде. Когда у меня был один монитор, мне было в лом постоянно переключаться между доками и кодом. Я бы вообще хотел бы себе 4 монитора: дока, рунет, IDE, симуляция (+ещё один для фильма wink.gif ). А то заколебало уже. Вот и подумал я тогда, что не плохо бы как-то по-умному документировать код вот таким образом. Пошукал и нашё на RSDN. Теперь вовсю пользуюсь. Даже лет через 10, когда я взгляну на такой код, я пойму что он означает, не глядя в даташит.

Вот... А зачем всё вместе столько IDE. На самом деле это не так уж и много. Вот прикиньте, приходит к Вам в отдел новый сотрудник, Вы его сажаете за свой проект какой-нить, чтобы он "втягивался". Вот что Вы ему покажите? Код? Заголовочники? А дока есть на код? С UML2 можно показать "вид сверху", т.к. структуру кода. Это EA, кстати, достаточно удобен. Он поддерживает реверс кода из исходников и генерацию в заголовочники и код (заголовки, без тела функций), а также синхронизацию с кодом.

Я сам прикладник ещё и долго пользовался VS2008. Когда я первый раз сел за IAR, то подумал, что большего убожества ещё не видал. Хотя в плане остального он хорош. Меня его работа с кодом просто достала. Даже 5.51 какая-то глючная в этому смысле. Поэтому я давно уже мечтал от другой среде, но чтобы компилировать можно было в IAR. У меня обычно обе среды открыты, т.к. модификацию они подхватывают сразу, только VS2008 требует подтверждения, а IAR тупо обновляет.

Вообще же, в VS2008 есть много разных фич, которые очень удобны для программера, особенно под C++. Например, fullscreen, разные подсветки, подсказки, деревья кода, классов... куча хрени всякой. или ВОТ - подсветка условной компиляции в коде! Вещь здоровская. Мне уже ещё удобна тем, что я пользую SVN и у меня есть плагин к VS2008 - VisualSVN и я могу коммитить проект в SVN нажатием пары кнопок прямо из VS2008. К EA тоже есть плагин. В общем - must have. Единственно, что плохо - это нету перехода к строкам ошибок после компиляции в avr-gcc, т.к. форматы обозначения у VS2008 и gcc компиляторов отличаются (это можно полечить, но нужно знать как). Зато там есть таблица ошибок и ворнингов в виде окошка, что тоже удобно, там видны строки с ошибками.

Вот и получается такая взаимодополняющся связь. А AVRStudio получается автоматом, т.к. умеет создавать проекты из отладочных файлов IAR. Иногда я их создаю, чтобы посимулировать там, но 5-я версия уж очень тяжела и умна слишком.

Итого: ТЗ -> Enterprise Architect (UML2) <-> VS2008 (C++, SVN) <-> IAR, GCC, Proteus <-> SVN -> ТЗ

Очень не плохо получается. Как-то даже по-другому на весь процесс смотришь. А ведь есть ещё удобные тулзы для VS2008.

А код, что привели, я ещё не ознакомился... буду разбирать. Мне ещё Modbus приделать надо, с COM портами разобраться и написать специальную хрень-переходник для Конфигуратора. Дело в том, что интерфейс Конфигуратора я буду писать на C# (VS2008), а вот Modbus будет в отдельной dll, но поскольку управлять я потоками буду в неуправляемом коде, а отображать в управляемом, то для этих целей существует такая приблуда как C++\CLI - на нём можно писать, как бы это сказать, управляемо-неуправляемый код. Это для того, чтобы обернуть уже имеющийся код Modbus-класса в управляемую обёртку, доступную из C#.

Короче, дело не простое, но и не шибко сложное. Ах, да. Хоть я кое-что и писал на яве под Андроид, то вот OPC как делать пока вообще не в теме. Тут может быть стопор, не искал ещё.

Давно мечтаю что-нить у себя дома довести именно до вот такого вида.
neiver
Цитата(ReAl @ Jul 20 2011, 18:54) *
Код
// <--------  ??? reinterpret_cast<uint8_t*>(_address) + i

Код
pgm_read_byte((const uint8_t*)(_address + i));
MrYuran
Цитата(uni @ Jul 20 2011, 19:41) *
Хоть я кое-что и писал на яве под Андроид, то вот OPC как делать пока вообще не в теме. Тут может быть стопор, не искал ещё.

Смысла в этом нету никакого, поскольку ОРС под андроид нету вообще. Ввиду нахренникомуненужности.
Видал статейку однажды, как в андроид встраивают драйвера FTDI. Вот это ещё можно прикрутить. Либо через ВТ.
Ещё раз повторюсь: смысл ОРС сервера в стандартном сопряжении с ОРС-клиентами. При отсутствии готовых клиентов смысл сервера теряется напрочь.
Или возможно я чего-то недопонял.
ig_z
QUOTE (uni @ Jul 18 2011, 00:07) *
Цели:
1. Проектирование сверху (UML2).
2. Использование удобной IDE VS2008.
3. Рабочая виртуальная модель для тестов.


При таком подходе следовало бы опереться на методологию TDD.
Пунктом 1.а создавать тест, пунктом 1.б создавать тестируемый модуль.
Пунктом 2.а запускать сборку модульных тестов и выполнять их. При успешном прохождении модульных тестов, делать тестовую сборку всего приложения, и опять запускать тесты (или тестера sm.gif).
uni
Цитата(ig_z @ Jul 21 2011, 01:09) *
При таком подходе следовало бы опереться на методологию TDD.
Пунктом 1.а создавать тест, пунктом 1.б создавать тестируемый модуль.
Пунктом 2.а запускать сборку модульных тестов и выполнять их. При успешном прохождении модульных тестов, делать тестовую сборку всего приложения, и опять запускать тесты (или тестера sm.gif).

Принято sm.gif По поводу тестирования. Понятия не имею как писать тесты под МК, но думается мне, что если что-то подобное делать, то можно тестировать ПО через Proteus (эмулируемый COM порт), либо через реальный интерфейс с реальным железом. Не знаю как это будет выглядеть. Не тестировать же классы на ПК - среда не та.

--------------------------------

neiver, я прочитал Вашу статью про указатели. Получается, что перегрузка методов в avr-gcc не пашет именно для такого случая? В IAR'е я могу написать просто дополнительный метод с другим типом параметра для чтения, без использования шаблонов.

Жалко, однако, это больше на костыль похоже для моего случая. Буду думать.

--------------------------------

Что касаемо OPC, то он нужен не для Android, а для Java. Какая разница вообще платформа. Это открытый интерфейс для работы в промышленности. Я потому к нему и веду. Если будет завязка: MODBUS + OPC, то можно будет эту поделку вполне реально применять совместо с огромной кучей имеющегося софта АСУТП верхнего уровня. Вот в чём смысл то. Поделки на AVR типа зажигания светодиодов, чтения температуры и т.д. уже пора оставить в прошлом sm.gif Давай-те чё-нить посерьёзней.

К тому же, если я смогу реализовать эту свою задумку, то применение такого "шаблона" проектирования на C++ можно будет использовать и в простых проектах. Не обязательно совмещать такую кучу всего в одном проекте. Зато, если ты знаешь, что ЭТО работает в сложном проекте, то в малом будет и подавно.

Цитата(MrYuran @ Jul 20 2011, 23:07) *
Смысла в этом нету никакого, поскольку ОРС под андроид нету вообще. Ввиду нахренникомуненужности.
Видал статейку однажды, как в андроид встраивают драйвера FTDI. Вот это ещё можно прикрутить. Либо через ВТ.
Ещё раз повторюсь: смысл ОРС сервера в стандартном сопряжении с ОРС-клиентами. При отсутствии готовых клиентов смысл сервера теряется напрочь.
Или возможно я чего-то недопонял.

Сервер будет не на планшетнике, а на стационарном компе. Смысл в том, чтобы использовать дешёвый ПК с тачскрином (можно КПК, хотя он и есть смартфон на Линуксе) в качестве клиента OPC. Там на борту есть всё: тачскрин, ява, wifi - что ещё нужно для написания юзабельного интерфейса для доступа к промышленной сети? Никто не мешает купить нормальную панель с Windows для тех же целей и писать на WinCC или Intouch. Без разницы будет. Дело в том, что я хочу показать на "простом" примере. А WinCC и Intouch - это не совсем просто sm.gif
demiurg_spb
Мне Ваш подход нравится. Молодчина!
ReAl
Цитата(uni @ Jul 21 2011, 07:03) *
Получается, что перегрузка методов в avr-gcc не пашет именно для такого случая? В IAR'е я могу написать просто дополнительный метод с другим типом параметра для чтения, без использования шаблонов.
В GCC атрибут progmem касается конкретной переменной, а не типа, наравне с attribute(section()) . Поэтому и невозможно сделать перегрузку (как и в IAR для переменных с #pragma section).



Цитата(neiver @ Jul 20 2011, 18:45) *
Код
pgm_read_byte( (const uint8_t*)(_address + i) );
Ну тогда уже
Код
pgm_read_byte( (const uint8_t*)(_address) + i );
И вообще пусть Accessor::Read() сразу принимает указатель на uint8_t, раз уж он по-uint8_t-шно читает.
neiver
Цитата(uni @ Jul 21 2011, 08:03) *
Не тестировать же классы на ПК - среда не та.

Почему нет? БОльшую часть встроенного приложения можно успешно тестировать на ПК - модульные тесты рулят. На целевой платформе нужно тестировать тоько низкоуровневый код, работающий непосредственно с железом. Тестирование на целевой платформе должно быть сведено к разумному минимуму.

По поводу OPC и COM/DCOM в частности, те, кто использовал эти технологии 10 лет назад сейчас активно от них избавляются в пользу веб служб. У DCOM очень большие проблемы обеспечения безопасности в распределённых сетях - админы с него волками воют. COM/DCOM, которые лежат в основе OPC слишком сложные и "замшелые" технологии.
То для чего Вы хотите использовать MODBUS + OPC + Android сейчас обычно делается так:
Промышленное устройство, которым нам надо управлять удалённо, имеет какой либо стандартный сетевой интерфейс (Ethernet, Wi-fi или еще что-нибудь) и подключено к корпоративной сети. На нём работает веб-служба (не путать в веб пользовательским итерфейсом), позволяющая управлять устройством. Далее, имеется большой и масштабируемый веб-сервер, который знает все устройства в сети и умеет с ними работать. Он предоставляет веб пользовательским итерфейс (WEB-UI), которым работают пользователи. Клиент такой системы может быть на любой платформе - главное, чтоб был браузер, а что это будет не важно - ПК, Android, iPhone, что угодно.


Цитата(ReAl @ Jul 21 2011, 10:14) *
И вообще пусть Accessor::Read() сразу принимает указатель на uint8_t, раз уж он по-uint8_t-шно читает.

Согласен.
ReAl
Цитата(uni @ Jul 20 2011, 18:41) *
Вот мне тут про prog_char сказали, что от него нужно уходить. Честно говоря у меня в коде он упоминается только раз 5, наверное. Дело в том, что я ещё не устаканился в выборе define'ов, которые были бы общепринятыми и понятными для обозначения аттрибутов памяти. Нужно сделать так, чтобы было удобно и для IAR и для GCC. В доке к GCC есть макро FLASH_DECLARE() - вполне удобная вещь, я её оставил и использую. Там разница только в очередности: у IAR [ __flash имя ] , а у GCC [ имя __attribute__((...)) ].
В GCC можно и до.
Код
__attribute__((__progmem__)) char foo[] = "foo";



Цитата(neiver @ Jul 20 2011, 17:15) *
У меня есть статейка на эту тему:
http://we.easyelectronics.ru/Soft/avr-s-i-...-ukazateli.html
А вообще надо будет походить на easyelectronics, раз Вы там свои статьи прописали :-)
uni
Читать и писать не успеваю.

Закоммитил новый "слепок". Доделал я очереди как хотел и походу они работают. Точнее как бы одна очередь.

На картинке ниже показан вид экрана в Протеусе для Ревизии 14. Нашёл и исправил досадные баги, из-за которых схема не моделировалась. Ну суть. Правда я беру отладочный образ из IAR, т.к. elf почему-то не хочет работать. Думаю, про большую вложенность функций... пока не знаю точно, поэтому компильте в IARе. (avg-gcc тоже компилится).

Итак. Небольшие пояснения. Прежде чем добраться до MODBUS'а мне нужно было сделать проект "лампочки-кнопочки", чтобы была некая интерактивность и было видно, что что-то работает. Кнопочки я ещё не забацал, а вот "лампочки" вроде пашут. Работает это так:

Представьте, что тут внутри винда в миниатюре. Есть один поток - WinMain(). Есть одно окно (их может быть много). Есть очередь сообщений как в Windows. Вся обработка событий идёт в функции окна в файле Menu.cpp. Я сделал несколько событий: SW_SHOW, WM_PAINT, WM_TIMER. Они почти как настоящие, но не совсем. Структура та же и поля те же. При запуске контроллера я посылаю в очередь сообщения SW_SHOW и WM_PAINT - окно их отрисовывает, как видно на картинке.

При старте контроллера также запускается Таймер 0 на переполнение. Счётчик каждый раз выставляется на 1 мсек. В модуле MCU.cpp я размножаю событие от этого таймера на 4 события: 100мсек, 500 мсек, 1 сек и 5 сек. При этом "рассыльным" служит EI7. Я конфигурирую внешенее прерывание на срабатывание по фронту и программно его эмулирую. Обработчик прерывания проверяет "входящую почту" (это глобальные переменные MSG) и запихивает не пустые в очередь. Дальше всё также - окно получает и отрабатывает.

На картинке видно, что отработали три таймера и через некоторое время отработает 5 сек таймер.

Очередь более менее настроена. Можно приступать к клаве и работе с эмулируемыми COM-портами для взаимодействия модели с реальным миром.
Нажмите для просмотра прикрепленного файла

Цитата
По поводу OPC и COM/DCOM в частности, те, кто использовал эти технологии 10 лет назад сейчас активно от них избавляются в пользу веб служб. У DCOM очень большие проблемы обеспечения безопасности в распределённых сетях - админы с него волками воют. COM/DCOM, которые лежат в основе OPC слишком сложные и "замшелые" технологии.
То для чего Вы хотите использовать MODBUS + OPC + Android сейчас обычно делается так:
Промышленное устройство, которым нам надо управлять удалённо, имеет какой либо стандартный сетевой интерфейс (Ethernet, Wi-fi или еще что-нибудь) и подключено к корпоративной сети. На нём работает веб-служба (не путать в веб пользовательским итерфейсом), позволяющая управлять устройством. Далее, имеется большой и масштабируемый веб-сервер, который знает все устройства в сети и умеет с ними работать. Он предоставляет веб пользовательским итерфейс (WEB-UI), которым работают пользователи. Клиент такой системы может быть на любой платформе - главное, чтоб был браузер, а что это будет не важно - ПК, Android, iPhone, что угодно.


Действительно, может быть так оно где-то сейчас и делается. Я не так давно (пару лет назад) работал автоматчиком в прокатном цехе на недавно построенном заводе по выпуску проволоки-катанки. Там прокатный стан в две линии. Да, контроллеры (сименс) имеют выход в промышленную сеть по Ethernet. Только контролируем мы их не WEB-интерфейсом, конечно, а спец ПО - Step7. Операторы на ПК используют также спец ПО - проекты на WinCC и Intouch. Никаких там масштабируемых веб-сервреров и прочих "служб". Чем их меньше - тем лучше. Если процессы быстро-протекающие - в районе нескольких мсек, то фиг их ты заметишь (зарегишь) такими интерфейсами. Все регистраторы работают напрямую по Profibus и т.д.

Мой пример вполне может пойти под домашнюю (малую) автоматизацию, т.е. коттеджа, квартиры, где можно будет с такими блоками по 485 через modbus управлять. Развел сетку, поставил контроллеры. Они снимают инфу и передают тебе на комп. А комп уже раздаёт её по OPC. Можно, конечно, что-нить помудрёней придумать, но в качестве примера для домашней разработке и применению - самое то. Можно применить все свои более мелкие проекты типа считывания температуры и управления чем-то в этом проекте. Собрать всё воедино и управлять дома: освещением, вентиляцией... ещё чем-то.

Промышленные решения стоят куда дороже, а IDE для разработки под эти решения я вообще молчу.
uni
Ревизия 15.

Совместная работа индикатора и клавиатуры.

Изменения:
В схеме подключена клавиатура (в смысле код обработки написан дополнительно к "железу").
Добавлены сообщения: WM_ACTIVATE, WM_KEYDOWN, WM_KEYUP.
Добавлены 10 окон.
Код, естессно, доработан: старые ошибки убраны, новые добавлены.

Я переход по нажатию делаю. При этом окну посылается сообщение WM_ACTIVATE (см. MSDN). По отпусанию что-то не так работает, хотя событие вроде окну приходит. Надо будет доделать.

Нажмите для просмотра прикрепленного файла Нажмите для просмотра прикрепленного файла
Нажмите для просмотра прикрепленного файла Нажмите для просмотра прикрепленного файла

Приложил отладочный файл для симуляции: Нажмите для просмотра прикрепленного файла
uni
Оказывается китайцы уже давно (года 4, не меньше) ваяют по такой технологии. Нашёл на просторах инета makefile, который я хотел себе тоже сделать.

Ссылка: makefile.old.iar

Жаль, я пока не владею этой скриптовой технологией, чтобы переписать этот шаблон под себя. Оказывается, переключение компилятора в Defines.h нафик не нужно. Просто в настройках конфигурации прописываешь нужные директивы и препроцессор подсвечивается как надо (неактивный) в зависимости от выбранной конфигурации (это я про VS2008). Компилить стало гораздо проще, Alt+TAB и F7 и там и там и готово. Надо будет makefile переделать под себя и вообще в среду IAR'а не лезть, кроме как посимулировать чего. Отстал я от жизни... на много.

Кстати, по поводу Enterprise Architect. Дело в том, что EA помечает каждый свой сформированный заголовочник индивидуальным GUID'ом, что мне стало интересно. Можно с его помощью организовать уникальную базу данных шаблонного кода, где GUID будет ключом к конкретному исходнику. Т.о., если нужно среди коллег обмениваться инфой по каким-то исходникам, то можно было бы отсылать человека к базе данных исходников (шаблонов) с указанием GUID конкретного заголовочника. Самые популярные решения могли бы висеть в топе такой базы данных и т.о. все бы видели примеры интересных и полезных решений.

Пометка GUID'ом выглядит так:
Код
///////////////////////////////////////////////////////////
//  LCD.h
//  Implementation of the Class CLCD
//  Created on:      16-июл-2011 6:53:35
//  Original author: Слава
///////////////////////////////////////////////////////////

#if !defined(EA_1284B123_896C_4fe7_BEC6_A67623960ADF__INCLUDED_)
#define EA_1284B123_896C_4fe7_BEC6_A67623960ADF__INCLUDED_

...

#endif // !defined(EA_1284B123_896C_4fe7_BEC6_A67623960ADF__INCLUDED_)


Теперь этот класс прочно закреплён за мной. Я могу развивать его дальше, оставляя этот GUID. Было бы ещё не плохо вставлять автоматически версию.
uni
Ревизия 16.

Подключена внешняя SRAM на 32К. До этой ревизии всё делалось на ОЗУ, которая есть на борту кристалла. В принципе для этого проекта ATmega128 хватит выше крыши и больше. Но для порядку почему бы не подключить и внешнюю SRAM? Пусть будет. В коде появилась её инициализация. К сожалению, пока только для IAR'а, т.к. я к своему стыду пока не знаю как сделать то же для gcc.

В проекте 10-е окно (клавиша 0) теперь тестирует все 32К байт внешней SRAM, что видно по миганию лампочек в Протеусе.

Отладочный файл для Протеуса: Нажмите для просмотра прикрепленного файла

Нажмите для просмотра прикрепленного файла
uni
Я сначала не обратил внимания, а оказывается, найденный мной сайт является китайским поисковым движком исходников, литературы и пр. для эмбеддеров.

Ещё раз приведу его адрес: http://www.hackchina.com

Блин, они буквально воспроизвели мои мысли в прошлом посте. Там можно вбивать строку поиска прямо в броузере, к примеру:
Код
http://www.hackchina.com/?lang=en&q=modbus

или
Код
http://www.hackchina.com/index.php?lang=en&q=uCOS


и вылазит куча найденных доков по теме.

Самое интересное посмотреть, чем интересуются китайские товарищи нынче. Последние поисковые запросы в виде тегов размещены ниже на страничке, т.о. что часто ищется - всегда на виду. Давно уже хотел изучать китайский вместо англиского. Видимо пора начинать.
uni
Итак, я исправил проект и вернул его в более менее заданное русло. Ошибки были просто тупыми (в GNUC варианте размещал массивы во флеш, а читал как из ОЗУ за что и был наказан).

Ревизия 17.

Я попробовал использовать указанную тут мне шаблонную технологию. Она работает, но не совсем так как я бы хотел. Пришлось ввести одно специальное макро, чтобы проще было всем этим делом пользоваться.

Вот такое макро для GNUC:
Код
    #define FLASHSTR_DECLARE( type, name, init ) \
        PROGMEM type _##name[] = init; \
        FlashPtr<type> name(_##name);


Теперь я задаю вид окошек так:
Код
FLASHSTR_DECLARE( char, Line1, "+------------------+" );
FLASHSTR_DECLARE( char, Line2, "  Версия: 0.0.0.50  " );
FLASHSTR_DECLARE( char, Line3, "  Автор: уни        " );
FLASHSTR_DECLARE( char, Line4, "+------------------+" );


Но пришлось сделать два метода в заголовочнике CLCD.h:
Код
#ifdef __GNUC__
    static void WriteLine(uint8_t Line, FlashPtr<char> pString);
    static void WriteLine(uint8_t Line, char * pString);
#elif defined( __ICCAVR__ )
    static void WriteLine(uint8_t Line, char __flash * pString);
    static void WriteLine(uint8_t Line, char * pString);
#endif


И это мне не нравится. Зато всё компилируется и пашет в обоих вариантах, что не состовляет труда проверить, ибо теперь я предлагаю два файла:
1) Нажмите для просмотра прикрепленного файла (iccout_ubrof8.d90)
2) Нажмите для просмотра прикрепленного файла (gccout.elf)

Можете поиграться. Вот только с тестом памяти я что-то намудрил. Хоть вроде бы от и проходит, на шине есть изменения, но вот если оторвать пару выводов, то всё завершается успешно всё равно. Где-то я ошибся в логике построения теста.
uni
Ревизия 18.

Добавил в шаблон (SmartPtr.h) от neiver дополнительный оператор:
Код
    inline const T operator []( int value ) {
            
        return * Self( _address + value );

    }


Также пришлось ввести ещё один тип:

Для AVR GCC:
Код
#define FLASHSTR_PTR FlashPtr<char>

и для IAR:
Код
#define FLASHSTR_PTR char __flash *


Вот теперь я доволен. Все настройки опять спрятаны в Defines.h. "Типизированные" указатели neiver позволяют делать перегрузку: отдельно для ОЗУ и флеш. А вот про EEPROM я забыл, буду думать как расширить.

Всё компилится, можно ехать дальше. Ах да, поскольку я не спец и вообще не шарю в шаблонах, то хотелось бы услышать от товарищей насколько я правильно записал то, что хотел. Телепатия приветствуется.

Использование этих конструкций см. в LCD.cpp и LCD.h.
Не забываем, что это всё должно одинаково хорошо компилиться в обоих компиляторах.
uni
Ревизия 20.

Версия: 0.0.0.74
Добавлена поддержка автоматического изменения версии программы (класс CVersion и скрипты).

Давно мечтал о такой фиче, но всё никак руки не доходили. Сделано по мотивам вот этой статьи:

IAR EW ARM: автоматическая генерация версии прошивки

Прям скажу, что я написал всё с нуля как всегда. Формат x.x.x.x мне как-то роднее.

Как это работает. Нда... Короче, WSH + пре и пост билды, если в двух словах.

Для VS2008:
Шаг 1. При запуске компиляции отрабатывает команда в Makefile:
Код
genver:
    @echo Generating Version.cpp file ...
    cscript //NoLogo versionfile-gen.js Version version.txt

где:
Version - это имя для формируемого Version.cpp файла, там будет храниться инфа о версии для проекта, а файл version.txt хранит данные о версии:
Код
0
0
0
75


Шаг 2. Скриптом генерится (перезаписывается) файл Version.cpp. Вот он какой:
Код
///////////////////////////////////////////////////////////
//  Version.cpp
//  Implementation of the Class CVersion
//  Created on:      24 июля 2011 г. 20:41:08
//  Original author: Мезенцев В. Н.
///////////////////////////////////////////////////////////

#include "Version.h"


uint8_t CVersion::Major = 0;
uint8_t CVersion::Minor = 0;
uint16_t CVersion::Revision = 0;
uint16_t CVersion::Build = 74;


uint8_t CVersion::GetMajor(){

    return Major;

}


uint8_t CVersion::GetMinor(){

    return Minor;

}


uint16_t CVersion::GetBuild(){

    return Build;
}


uint16_t CVersion::GetRevision(){

    return Revision;
}

Причём дата генерации будет указана свежая sm.gif

Шаг 3. Компилируется всё это дело.

Шаг 4. Если процесс не прервался от досадной ошибки, то выполяется следующая строка Makefile:
Код
updver:
    @echo Updating version ...
    cscript //NoLogo versionfile-update.js version.txt


Тут второй скрипт меняет версию.

Скрипты: versionfile-gen.js и versionfile-update.js.

В коде происходит сборка строки версии следующим образом:
Код
    // Вычисление строки с версией программы
    utoa( CVersion::GetMajor(), buffer, 10 );
    strcat( Version, buffer );
    strcat( Version, "." );

    utoa( CVersion::GetMinor(), buffer, 10 );
    strcat( Version, buffer );
    strcat( Version, "." );

    utoa( CVersion::GetRevision(), buffer, 10 );
    strcat( Version, buffer );
    strcat( Version, "." );

    utoa( CVersion::GetBuild(), buffer, 10 );
    strcat( Version, buffer );


Увы, это не работает в IAR. Пока не придумал как заметить utoa() (sprintf() что-то не пашет).

В остальном, меня это решение очень даже устраивает. На индикаторе теперь выводится истинная версия. После каждого успешного билда счётчик накручивается.

Нда... похоже придётся весь проект переписывать.

После краткого ознакомления с этим ресурсом: KonstantinChizhov / AvrProjects стало как-то уныло от своего стиля кодинга sad.gif .
uni
Вот чего я не видел на многочисленных сайтах, так это Обработка Ошибок (Исключительных ситуаций на МК). Я знаю несколько таких технологий, но применяться они должны во всём проекте единообразно.

Есть одна очень интересная и подробная статья на эту тему, которая мне очень понравилась. Сам я потому и выбрал структуру кода интерфейса в виде сообщений как в Windows, т.к. их HRESULT - это практическо то, что можно было бы применить в МК. Можно разбить всю структуру проекта на модули и сделать соглашения о структуре HRESULT и её использовании.

Вот статья: "ftp://82.193.156.30/Документация/Обработка%20ошибок/" .

Мне хотелось бы организовать в коде понятную логику обработки ошибок. Если их посылать некуда, то они уходили бы в null, если не критические, а если критические, то что-то бы делали. Короче давно хотел разобраться в этом вопросе именно для контроллеров. Как управлять ошибками во время отладки? Что будет в релизе и т.д. Как вести журнал, если есть такая возможность и пр.
uni
Некоторые подвижки в шаблоне на примере отладочной платы Pinboard II (AVR).

Видео:
1. Pinboard II (AVR) Demo (видео)
2. Pinboard II (AVR) плата (видео)

Репозиторий проекта: https://mysvn.ru/schoolbell/pbiidemo/
Для видео: ревизия 11.

Изменений очень много, потому описывать их не буду. Это новый вариант шаблона на основе старого. Вся фишка в событийном управлении а-ля Windows и одинаковости исходников как для IAR, так и для GCC компиляторов. Всё работает.

Вот пример описания отдельных окон интерфейса на основе меню:
1. Основное окно
2. Подсчёт частоты
3. Измерение
4. Малая клавиатура
5. PS/2 клавиатура
uni
Ссылка на svn репозиторий:

Шаблоны: https://mysvn.ru/avr/templates/
Примеры: https://mysvn.ru/avr/examples/

Экспортировать из репозитория к себе можно при помощи плагина к проводнику: TortoiseSVN.

Шаблоны для микроконтроллеров: ATmega48, ATmega16, ATmega32, ATmega128.

Особенности шаблонов:
1. Проекты шаблонов собраны таким образом, что компилируются в двух C++ компиляторах: avr-gcc и iar.
2. Каждый шаблон имеет класс CMCU, который является программной моделью микроконтроллера ATmega.
3. Обработка событий (прерываний) осуществляется через соответствующие методы класса CMCU, которые имеют соответствующие названия.
4. Код максимально самодокументирован, вплоть до отдельных настроечных битов конфигурационных регистров.
5. В каждый проект шаблона включён заголовочный файл с классом CVersion. Этот класс создаётся автоматически перед каждой компиляции проекта (и в iar, и в gcc). Его назначение - автоматически отслеживать номер версии прошивки в стиле: Major.Minor.Revision.Build, где первое число изменяется от 0 до 9, второе от 0 до 99, а последние два от 0 до 9999. Также в классе есть метод, возвращающий дату билда в виде строки. Строка находится во флеш.
6. Первоначально проекты шаблонов настроены для работы с WinAVR-20100110 и IAR 6.10.
7. Каждый шаблон имеет возможность однообразного описания декларации переменных и одномерных массивов, которые должны находится во флеш. При использовании специального C++ шаблона умного указателя (SmartPtr.h) можно забыть про функции типа pgm_read_byte() и eeprom_read_byte(). С++ компилятор автоматически вызовет эти функции для чтения данных из флеш или eeprom.
8. Для тех, кто умеет пользоваться VS2008, в каждой папке есть GCC проект для этой IDE, в котором можно работать над проектом. Сборка идёт через Makefile.

Назначение:
1. Переход на объектный C.
2. Небольшие проекты без сильных требований к быстродействию, т.е. там где не нужны в большом количестве ассемблерные вставки. Их можно подключать и в шаблонах, но только в качестве исключения.
3. Для тех, кому нравится ООП или хочет писать с использованием ООП на AVR.

Ограничения и недостатки:
1. При использовании двумерных массивов, которые должны находится во флеш, теряется кросс-компиляция.
2. Шаблоны пока ещё не готовы на 100%, в них могут быть неточности в плане описания регистров или битов. Нужно быть внимательными.

Пример 1. Проект на основе шаблона ATmega16: freemodbus.
Код
AVR Memory Usage
----------------
Device: atmega16
Program:    6398 bytes (39.1% Full)
(.text + .data + .bootloader)
Data:        421 bytes (41.1% Full)
(.data + .bss + .noinit)
-------- end --------

     IAR Universal Linker V5.2.3.14
     Copyright 1987-2011 IAR Systems AB.

5 778 bytes of CODE memory (+             32 range fill )
   484 bytes of DATA memory (+ 25 absolute )

Настройки адреса и регистров находятся в файле Configuration.h:
Код
#define REG_INPUT_START 1000
#define REG_INPUT_NREGS 4

В проекте определены 4 регистра:
Код
/**
* Главный (основной) поток программы
*/
HRESULT CMCU::MainThreadProcedure(){

    const UCHAR ucSlaveID[] = { 0xAA, 0xBB, 0xCC };
    eMBErrorCode eStatus;

    eStatus = eMBInit( ::MB_RTU, 0x0A, 0, 9600, ::MB_PAR_NONE );

    eStatus = eMBSetSlaveID( 0x34, TRUE, ucSlaveID, 3 );

    __enable_interrupt();

    // Enable the Modbus Protocol Stack
    eStatus = eMBEnable();

    do {

        ( void ) eMBPoll();

        // Here we simply count the number of poll cycles
        usRegInputBuf[0] = Value1;
        usRegInputBuf[1] = Value2;
        usRegInputBuf[2] = ( USHORT ) CVersion::GetRevision();
        usRegInputBuf[3] = ( USHORT ) CVersion::GetBuild();


    } while ( true );

    // Все проверки прошли успешно, объект в рабочем состоянии
    return NO_ERROR;

}

Value1 изменяется с частотой 1 секунда, а Value2 - 5 секунд.
Нажмите для просмотра прикрепленного файла

Пример 2. Проект на основе шаблона ATmega16: uSD с модулем Petit FAT File System.
Код
AVR Memory Usage
----------------
Device: atmega16
Program:   10238 bytes (62.5% Full)
(.text + .data + .bootloader)
Data:        461 bytes (45.0% Full)
(.data + .bss + .noinit)
-------- end --------

     IAR Universal Linker V5.2.3.14
     Copyright 1987-2011 IAR Systems AB.

8 740 bytes of CODE memory (+             36 range fill )
   585 bytes of DATA memory (+ 16 absolute )

Размер кода можно изменять включая и выключая части драйвера Petit FS.

Подключение флешки к ATmega16:
Код
// Definitions for MMC/SDC connection
#define SD_DI   5   // MOSI
#define SD_DO   6   // MISO
#define SD_CLK  7   // CLK
#define SD_CS   4   // SS
#define SD_INS  0   // CD
#define SD_WP   1   // WP

Нажмите для просмотра прикрепленного файла Нажмите для просмотра прикрепленного файла

Пример 3. Пример проекта на основе шаблона ATmega16: MicroVGA conio/user interface library.
Код
AVR Memory Usage
----------------
Device: atmega16
Program:   13874 bytes (84.7% Full)
(.text + .data + .bootloader)
Data:        523 bytes (51.1% Full)
(.data + .bss + .noinit)
-------- end --------

     IAR Universal Linker V5.2.3.14
     Copyright 1987-2011 IAR Systems AB.

12 839 bytes of CODE memory (+             36 range fill )
    625 bytes of DATA memory (+ 19 absolute )

Нажмите для просмотра прикрепленного файла Нажмите для просмотра прикрепленного файла
MrYuran
Цитата(uni @ Jul 20 2011, 19:41) *
форматы обозначения у VS2008 и gcc компиляторов отличаются (это можно полечить, но нужно знать как)

Как-то вот так (ближе к концу приведен скрипт для sed)
Результат - щелкаем по сообщению, перескакивает на строку в окошке вывода компилятора и в исходниках тоже.

За системный подход - респект!
Было дело, тоже хотел что-то подобное, во время переползания с иара на гцц, но потом светлая сторона силы возобладала и потребность исчезла. Вместе с иаром.
uni
MrYuran, это просто клад, как же меня заколебало Gtrl + g делать по номерам строк. Я сам пробовал этот потоковый фильтр, но опыта не хватило довести это дело до ума. Наконец-то, я могу спокойно прыгать по исходникам.
Спасибо! 08.gif
MrYuran
Цитата(uni @ Nov 23 2012, 18:14) *
Спасибо! 08.gif

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

Простейшая фича - автодополнение вводимых идентификаторов после 3-4 символов - фигвам!
Я уж не говорю об элементарнейшем - автоматически парные скобки вставлять..
Может, подскажете, как это настроить, раз апологет студии.
_Артём_
Цитата(MrYuran @ Nov 23 2012, 16:46) *
Простейшая фича - автодополнение вводимых идентификаторов после 3-4 символов - фигвам!
Я уж не говорю об элементарнейшем - автоматически парные скобки вставлять..

Вроде всё с этим нормально в студии...если не хватает функционала попробуйте Visual Assist X поставить.

Цитата(MrYuran @ Nov 23 2012, 16:46) *
Да не за что..
меня вот на студию пересаживают насильственно, так после православных эклипсов/кодеблоксов хочется ругаться матом, причем вслух.

Такие же впечатления после перехода на eclipse: одного нет, другого нет, акронимов не понимает.
SyncLair
Цитата(MrYuran @ Nov 23 2012, 18:46) *
меня вот на студию пересаживают насильственно, так после православных эклипсов/кодеблоксов хочется ругаться матом, причем вслух.

Не пробывали использовать CMAKE ? он вроде гененрирует проекты для студий.
uni
Я не то, чтобы студии апологет, я привык к Windows. Потому и пишу в ней. А вообще, мне без разницы в чём писать, если это что-то не очень большое. Потом встают такие факторы как удобная отладка и вообще сквозное проектирование. Чего-то универсального пока не нашёл. Вот есть плагин EA к студии, я не смотрел подробно для других сред, но у меня есть сомнения, что проектирование классов (через UML) там можно сделать также удобно в обоих направлениях.
Но у студии другой подход к отладке, поэтому приходится использовать AVR Studio или Atmel Studio. Вряд ли какие коде боксы и прочие внешние среды сравняются с оригиналом по визуализации всей периферии мк. Тут, правда, Proteus близко подошёл, но я пока не видел ничего лучше родного софта, что касается отладки по JTAG для AVR. У меня и эклипс настроен, но как-то он не пошёл. Одно дело когда пишешь что-нить на Java, это мне нравится.

А что по теме вопроса, то фич свободных IDE не достаёт, да. Единственно могу подсказать поискать расширения типа DevExpress - это офигенный набор классов для проектирования для .Net и в комплекте в нагрузку идут какие-то дополнительные фичи. Он у меня установлен, но студия из-за этих фичей начала подтормаживать. Уж очень он там пытается всё разукрасить (какого-то особого дополнения я не искал, но через раз расширение это окошки подставляет с различными подсказками типа рефакторинга, назначения быстрых клавиш и прочей ерунды, которая меня пока ещё не очень заинтересовала). Так вот, думаю, надо найти форум продвинутых пользователей подобных дополнений и у них спросить. А вот где я это расширение брал... вот этого не помню. Наверное или на руборде, или на рутрекере, там должны подсказать. DevExpress 12.1.5 у меня.

П. С. Забыл добавить картинку настроек. Никогда почти сюда не заглядывал, лень пока. Может есть что-то полезное. Меня больше библиотека классов интересовала.
uni
6-минутный ролик, демонстрирующий работу простого файлового менеджера на ATmega16 @ 16 МГц. Показана идентичная работа обеих прошивок (iar и avr-gcc):
http://www.youtube.com/watch?v=6OPQV9aZWaE

В качестве отладочной платы используется Pinboard 2. Схема включения типовая. Этот проект можно запустить в Proteus, схема прилагается к исходникам. Правда там будут тормоза, но отлаживать можно.

Исходник: https://mysvn.ru/avr/examples/uSD/

Нажмите для просмотра прикрепленного файла
uni
Обновлены все проекты шаблонов.
Переход всех проектов на MHV AVR Tools 20131017 (avr-gcc (GCC) 4.8.2 20131010 (prerelease)) (замена WinAVR-20100110).

Для GCC:
Путь к сборке выбран: C:\MHVAVRTools\
Для настройки на свои пути нужно изменить их в файлах: build.cmd, buildall.cmd, clean.cmd. В проекте MSVS нужно также изменить пути поиска включаемых файлов, чтобы работал VAssistX и прочие вещи связанные с удобством работы.

В примере работы с EEPROM показано как можно одновременно компилировать исходник в IAR и GCC. Поскольку read_block и write_block у IAR отсутствуют, то пришлось написать их аналоги: _EEGETBLOCK() и _EEPUTBLOCK(). Пример использует микро-файловую систему EFS для работы с EEPROM (взята из openplayer'а).
ar__systems
Цитата(neiver @ Jul 21 2011, 01:18) *
Почему нет? БОльшую часть встроенного приложения можно успешно тестировать на ПК - модульные тесты рулят. На целевой платформе нужно тестировать тоько низкоуровневый код, работающий непосредственно с железом. Тестирование на целевой платформе должно быть сведено к разумному минимуму.

+1. При грамотном проектировании прикладная часть прекрасно отлаживается на компе.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.