koluna 0 15 мая, 2009 Опубликовано 15 мая, 2009 · Жалоба Здравствуйте! scmRTOS v3 AVR/GCC. Компилятор - WinAVR 20080610. IDE - Code::Blocks 8.02. Простую тестовую программу буду пробовать на ATmega88. Приступил к изучению. Читаю scmRTOS_v2.pdf, смотрю исходники примеров релиза. Возникло несколько вопросов. Прошу помочь разобраться. Буду очень благодарен за какие-нибудь шаблоны программ (без лишнего кода), практические рекомендации и ссылки! Первые два вопроса - функции main примеров. 1. В примерах T0 - системный таймер. Почему инициализация и запуск системного таймера производится не средствами ОС (допустим, в Run), а пользователем ОС вручную? 2. Почему при использовании передачи управления на основе программного прерывания инициализация компаратора производится не средствами ОС, а пользователем ОС вручную? 3. Один тик системного таймера - одно его переполнение? 4. Рекомендуемое значение системного тика 1-10 мс. Т. е., мы должны настраивать системный таймер, на переполнение его в пределах этого времени? 5. Каковы будут дополнительные опции компилятора для моей связки ОС + компилятор + IDE? Благодарю заранее! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 34 15 мая, 2009 Опубликовано 15 мая, 2009 · Жалоба 1. В примерах T0 - системный таймер. Почему инициализация и запуск системного таймера производится не средствами ОС (допустим, в Run), а пользователем ОС вручную? Потому что системным таймером может быть не только Т0, но и любой другой таймер - это отдано на откуп пользователю, он может сам выбрать и настроить. Поэтому и вынесено с уровня ОС на уровень прикладного проекта. 2. Почему при использовании передачи управления на основе программного прерывания инициализация компаратора производится не средствами ОС, а пользователем ОС вручную? Ровно по той же причине, что и п.1. Поскольку нет у процессора отдельного прерывания, предназначенного для этих дел, то приходится использовать какое-либо из свободных. А это тоже дело такое - в одном случае одно лучше подходит, в другом это занято. Вот чтобы ось не привязывать к выбору источника прерываний для переключения контекстов, это тоже вынесено но уровень проекта. В предыдущих версиях, кстати, оба прерывания были описаны внутри ОС, но это, как показала практика, оказалось негибко. Поэтому они сейчас и вынесены. 3. Один тик системного таймера - одно его переполнение? Это одно его прерывание. :) А уж по переполнению оно сделано или по Compare Match - это особенности конкретного проекта. Все в руках юзера. :) 4. Рекомендуемое значение системного тика 1-10 мс. Т. е., мы должны настраивать системный таймер, на переполнение его в пределах этого времени? Да, вы можете выбрать таймер, настроить его так, чтобы получить нужное вам значение системного тика. Оно может быть любым - какое сделаете, такое и будет. 5. Каковы будут дополнительные опции компилятора для моей связки ОС + компилятор + IDE? Не понял вопроса. ОС требует только чтобы для компилятора была включена поддержка С++ и (если надо) расширения языка. Если для целей проекта надо еще что-то, ну добавьте. Если ответ не удовлетворил, уточните, что конкретно нужно. Либо дождемся ответа от автора порта. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
koluna 0 15 мая, 2009 Опубликовано 15 мая, 2009 · Жалоба По вопросам 1 и 2 понятно. Т. е., для того, чтобы ОС работала, выбираем, настраиваем, запускаем системный таймер в main. Если используем конфигурацию ОС с передачей управления по программному прерыванию, то "настраиваем" соответствующее прерывание в main. По вопросу 3. Compare Match - для более точного подбора длительности тика? А нужно ли это? :) Не понял вопроса. ОС требует только чтобы для компилятора была включена поддержка С++ и (если надо) расширения языка. Если для целей проекта надо еще что-то, ну добавьте. Если ответ не удовлетворил, уточните, что конкретно нужно. Либо дождемся ответа от автора порта. :) Понятно :) 6. При описании типа процесса размер двух стеков указывать или одного? 7. Как "прикинуть" размер требуемых стеков таким образом, чтобы взять его с запасом? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 15 мая, 2009 Опубликовано 15 мая, 2009 · Жалоба Там есть makefile с ключами компилятора. Если Code::Blocks позволяет создать проект "на всём готовом" (у NetBeans это называется С/С++ project from existing code - он тогда только подхватывает исходники в среду, а для компиляции в свой makefile подставляет вызов make с готовым makefile из проекта), то можно воспользоваться этим управляющим файлом. Если нет - то просто придётся посмотреть опции в makefile проекта и перенести их в IDE. Собственно, там каких-то специфических опций именно для scmRTOS действительно и не нужно. По вопросу 3. Compare Match - для более точного подбора длительности тика? А нужно ли это? :) А это вопрос вкусовой. Если речь именно о точности. А так - частота тактирования процессора и прескалер могут дать, к примеру, переполнение в 2,2мс, а хочется иметь тик в 1мс. Или таймер 0 занят чем-то другим, а есть свободный канал сравнения на таймере 3. 6. При описании типа процесса размер двух стеков указывать или одного? 7. Как "прикинуть" размер требуемых стеков таким образом, чтобы взять его с запасом? Для avr-gcc, как оно видно в примерах, стек один. Размер стека зависит от того, в какую глубину идут вызовы функций (в том числе сервисов ОС) и могут ли накладываться прерывания. Сколь-нибудь серьёзного исследования я не проводил, но так навскидку - висящему в for (;;) { Sleep(500); TOGGLE(LED_R); } достаточно 45-50 байт стека (без наложения прерываний) Вызывающему пару-тройку функций (без использования стека для локальных переменных), которые где-то там обращаются к Mutex да Event - уже нужно, скажем, 75-80. Для спокойствия можно начать где-то со 120 плюс ожидаемые размеры локальных переменных на стеке (обычно бывает когда есть массивчики или переменные, адрес которых передаётся куда-то). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergeeff 1 15 мая, 2009 Опубликовано 15 мая, 2009 · Жалоба У нас на форуме уже рассказывалось, как можно ввести контроль за объемом стека в scmRTOS. Методика простая. Выделяем поболее, смотрим за реальной работой процессора, анализируем сколько было использовано. Есть возможность - ужимаем, оставив еще немного про запас. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
koluna 0 15 мая, 2009 Опубликовано 15 мая, 2009 · Жалоба Вот и ещё вопросы подоспели :) 8. Для чего функция процесса Exec() - статическая? 9. Почему функции WakeUpProcess() и ForceWakeUpProcess() следует использовать с осторожностью? В каких случаях? 10. Какую оптимизацию задавать при компиляции? У нас на форуме уже рассказывалось, как можно ввести контроль за объемом стека в scmRTOS. Методика простая. Выделяем поболее, смотрим за реальной работой процессора, анализируем сколько было использовано. Есть возможность - ужимаем, оставив еще немного про запас. Я читал :) Но мне как новичку пока сложновато это... TOGGLE(LED_R); Что это? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 15 мая, 2009 Опубликовано 15 мая, 2009 · Жалоба 10. Какую оптимизацию задавать при компиляции?По вкусу. Я ставлю -Os и выбрасывание неиспользуемого кода/данных (-ffunction-sections -fdata-sections для компилятора и --gc-sections для линкера) а также --relax линкеру для замен длинных вызовов/переходов на короткие там, где это возможно и замен комбинаций call+ret на jump. В общем, те же, что и для С-шных проектов. Что это?Макрос инверсии вывода (в данном случае - выхода светодиода), развитие "классики от Аскольда Волкова" http://electronix.ru/forum/index.php?showt...mp;#entry199555 Включено в примеры к порту scmRTOS для avr-gcc - файл pin_macros.h Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 34 16 мая, 2009 Опубликовано 16 мая, 2009 · Жалоба 8. Для чего функция процесса Exec() - статическая? А как иначе? Эта функция должна быть в единственном экземпляре всегда. Кроме того, хотя эта функция и объявлена, как функция процесса, на самом деле к ресурсам процесса она отношения не имеет и служит исключительно для нужд пользовательского кода. Поэтому делать ее нестатической - это передача ненужного this, а учитывая, что эта фукнция нормально не вызывается, то и this нее передать невозможно. Вот такие логические и технические посылы. 9. Почему функции WakeUpProcess() и ForceWakeUpProcess() следует использовать с осторожностью? В каких случаях? Потому, что их использование нарушает обычную логику работы программы. Например, какой-то процесс ожидает события, а тут его в другом месте выдергивают - это как бы нештатная ситуация. Поэтому тут надо действовать внимательно. К слову сказать, функции эти сделаны там скорее на всякий случай, лично я уже и не помню, когда их применял (и применял ли вообще). При правильно организованной программе необходимость в их использовании стемится к нулю. Это как с оператором goto. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
koluna 0 16 мая, 2009 Опубликовано 16 мая, 2009 · Жалоба А как иначе? Эта функция должна быть в единственном экземпляре всегда. Каждый процесс - объект типа полученного с помощью шаблона process, наследник TBaseProcess. Каждый процесс существует в единственном экземпляре. Значит функция будет и так в единственном экземпляре... Или я не понимаю что такое статическая функция :( Потому, что их использование нарушает обычную логику работы программы. Например, какой-то процесс ожидает события, а тут его в другом месте выдергивают - это как бы нештатная ситуация. Поэтому тут надо действовать внимательно. К слову сказать, функции эти сделаны там скорее на всякий случай, лично я уже и не помню, когда их применял (и применял ли вообще). При правильно организованной программе необходимость в их использовании стемится к нулю. Это как с оператором goto. А что может произойти? Система "упадёт"? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 34 16 мая, 2009 Опубликовано 16 мая, 2009 · Жалоба Каждый процесс - объект типа полученного с помощью шаблона process, наследник TBaseProcess. Каждый процесс существует в единственном экземпляре. Значит функция будет и так в единственном экземпляре... Или я не понимаю что такое статическая функция :( Никто не мешает завести больше одного объекта-процесса. Хотя это, конечно, неправильно. Я же ясно, вроде, пояснил, что: хотя эта функция и объявлена, как функция процесса, на самом деле к ресурсам процесса она отношения не имеет и служит исключительно для нужд пользовательского кода. Это логический довод. делать ее нестатической - это передача ненужного this, а учитывая, что эта фукнция нормально не вызывается, то и this нее передать невозможно. Это технический довод. Как бы вы передали в нее указатель this? А без этого она может работать некорректно, и там можно получить очень хорошие грабли. А что может произойти? Система "упадёт"? Можно получить неожиданное поведение. И удивляться. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergeeff 1 16 мая, 2009 Опубликовано 16 мая, 2009 · Жалоба Раз пошел процесс обсуждения scmRTOS, хочу воспользоваться активным присутствием DXP на форуме. Очень хотелось бы сделать так, чтобы первый объявленный процесс получал высший приоритет, следующий процесс - приоритет на 1 ниже и т.д. Тогда, объявив в самой ОС число возможных процессов по максимуму всю ОС оформить в виде отдельной библиотеки и пользователям в своей организации раздать, чтобы они "грязными ногами" в ее "чистом теле" не натоптали. Сколько не думал, пока ничего не придумалось. Может есть какие соображения на сей счет? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 16 мая, 2009 Опубликовано 16 мая, 2009 · Жалоба Как бы вы передали в нее указатель this?Если постараться - можно. В конструкторе TBaseProcess после Kernel.RegisterProcess(this), там, где формируется начальный стековый кадр, затолкать этот же this в такое место, чтобы после восстановления контекста он оказался в нужных регистрах. Только, насколько я понимаю, тип параметра exec у конструктора для этого должен быть другой - указатель на функцию-член. Топикстартеру: Таким же образом можно было бы передать в функцию процесса указатель на некую структуру/класс, с которыми процесс должен работать, но для этого надо конструктору добавить соответствующий аргумент. Но это имело бы смысл при одновремённом переводе Exec() в нестатическую - чтобы создавать два экземпляра процесса (с разными приоритетами, но это в конечном счёте не важно), работающие одинаковым образом с разными однотипными сущностями и разделяющими код. Но это же делается просто созданием двух процессов, из Exec() которых вызывается одна и та же функция с разными указателями на рабочий объект. Несколько накладнее, пожалуй. И не так красиво. Но у меня пока такие желания не возникали - ну пусть два UART - ну всё равно у них разное назначение в системе и они обрабатываются по разному. А ради просто красоты до/пере-делывать структуру ОС особого смысла не вижу. Очень хотелось бы сделать так, чтобы первый объявленный процесс получал высший приоритет, следующий процесс - приоритет на 1 ниже и т.д. Тогда, объявив в самой ОС число возможных процессов по максимуму всю ОС оформить в виде отдельной библиотеки и пользователям в своей организации раздать, чтобы они "грязными ногами" в ее "чистом теле" не натоптали. Сколько не думал, пока ничего не придумалось. Может есть какие соображения на сей счет? Чтобы процессов было "по максимуму" их и задать бы надо. Ну там размер таблиц вырастет, это ладно, но между низшим по приоритету из созданных и Idle заполнено всё должно быть, она же их вызывать попытается. Можно наоборот - с низшего начинать. Ну, если выйдет, так как я тоже чисто языковыми средствами не могу придумать как это сделать - в разных файлах, независимо. Но тогда начинаться непонятно с чего выполнение будет - до наивысшего таблицы пусты. Главное - "а зачем"? Удобство "объектных", а не "исходниковых" библиотек в embeded обсуждалось неоднократно и практически для всего, кроме стандартной библиотеки языка оно для меня сомнительно. А уж scmRTOS, в которой ещё некоторые вещи конфигурируются попроектно - не только число процессов, и компилируется потом с inline-подстановками оптимально под проект - так и подавно. Так то, что должно решаться административными методами, ими и решайте. Пусть проверка результата работы производится компиляцией со свежевыдернутыми из недоступного по правам записи хранилища, а кто в рабочей копии наменял что-то - сам себе враг. Или ещё что-то придумайте. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
koluna 0 16 мая, 2009 Опубликовано 16 мая, 2009 (изменено) · Жалоба Вопросы далее :) 11. Как лучше поступить с исходниками scmRTOS? Отвести для них отдельную папку и использовать для всех проектов сразу, как-то прописал пути в каждом проекте, или копировать в папку с каждым проектом? Скопировал исходники в отдельную папку, прописал пути. Но компилятор жалуется на отсутствие файлов scmRTOS_CONFIG.h и scmRTOS_TARGET_CFG.h - лежат в папке с проектом (это ведь файлы конфигурации ОС для конкретного проекта и по идее должны храниться в папке проекта). Переместил эти файлы в папку AVR ОС - компилятор перестал ругаться... 12. Сейчас при компиляции имею 5 ошибок. Скриншоты ниже (выбрана каждая из ошибок). http://file.qip.ru/file/87782953/9829dcad/e1_online.html http://file.qip.ru/file/87782958/ffb0525/e2_online.html http://file.qip.ru/file/87782964/2d601acd/e3_online.html http://file.qip.ru/file/87782966/c36e7be1/e4_online.html http://file.qip.ru/file/87782969/53d16670/e5_online.html Код main.cpp: #include <avr/io.h> #include "scmRTOS.h" typedef OS::process<OS::pr0, 120> TProc1; typedef OS::process<OS::pr1, 160> TProc2; TProc1 Proc1; TProc2 Proc2; int main(void) { TCCR0B = (1 << CS01) | (1 << CS00); TIMSK0 |= (1 << TOIE0); OS::Run(); return 0; }; namespace OS { template<> OS_PROCESS void TProc1::Exec() { for(;;) { } } } namespace OS { template<> OS_PROCESS void TProc2::Exec() { for(;;) { } } } Изменено 16 мая, 2009 пользователем n_bogoyavlensky Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 16 мая, 2009 Опубликовано 16 мая, 2009 · Жалоба Скопировал исходники в отдельную папку, прописал пути. Но компилятор жалуется на отсутствие файлов scmRTOS_CONFIG.h и scmRTOS_TARGET_CFG.h - лежат в папке с проектом (это ведь файлы конфигурации ОС для конкретного проекта и по идее должны храниться в папке проекта). Переместил эти файлы в папку AVR ОС - компилятор перестал ругаться... Текущая папка проекта должна быть прописана в ключах компилятора в -I иначе файлы из другой папки (из ОС) не видят .h из текущей. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
koluna 0 16 мая, 2009 Опубликовано 16 мая, 2009 · Жалоба Вообще непонятны следующие конструкции в примерах, я запутался... namespace OS { template<> OS_PROCESS void TProc1::Exec() { ... В руководстве этого нет... Текущая папка проекта должна быть прописана в ключах компилятора в -I иначе файлы из другой папки (из ОС) не видят .h из текущей. Получилось. Спасибо :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться