Перейти к содержанию
    

Здравствуйте!

 

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?

 

Благодарю заранее!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1. В примерах T0 - системный таймер. Почему инициализация и запуск системного таймера производится не средствами ОС (допустим, в Run), а пользователем ОС вручную?

 

Потому что системным таймером может быть не только Т0, но и любой другой таймер - это отдано на откуп пользователю, он может сам выбрать и настроить. Поэтому и вынесено с уровня ОС на уровень прикладного проекта.

 

2. Почему при использовании передачи управления на основе программного прерывания инициализация компаратора производится не средствами ОС, а пользователем ОС вручную?

 

Ровно по той же причине, что и п.1. Поскольку нет у процессора отдельного прерывания, предназначенного для этих дел, то приходится использовать какое-либо из свободных. А это тоже дело такое - в одном случае одно лучше подходит, в другом это занято. Вот чтобы ось не привязывать к выбору источника прерываний для переключения контекстов, это тоже вынесено но уровень проекта.

 

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

 

3. Один тик системного таймера - одно его переполнение?

 

Это одно его прерывание. :) А уж по переполнению оно сделано или по Compare Match - это особенности конкретного проекта. Все в руках юзера. :)

 

4. Рекомендуемое значение системного тика 1-10 мс. Т. е., мы должны настраивать системный таймер, на переполнение его в пределах этого времени?

 

Да, вы можете выбрать таймер, настроить его так, чтобы получить нужное вам значение системного тика. Оно может быть любым - какое сделаете, такое и будет.

 

5. Каковы будут дополнительные опции компилятора для моей связки ОС + компилятор + IDE?

Не понял вопроса. ОС требует только чтобы для компилятора была включена поддержка С++ и (если надо) расширения языка. Если для целей проекта надо еще что-то, ну добавьте.

 

Если ответ не удовлетворил, уточните, что конкретно нужно. Либо дождемся ответа от автора порта. :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По вопросам 1 и 2 понятно.

Т. е., для того, чтобы ОС работала, выбираем, настраиваем, запускаем системный таймер в main.

Если используем конфигурацию ОС с передачей управления по программному прерыванию, то "настраиваем" соответствующее прерывание в main.

 

По вопросу 3.

Compare Match - для более точного подбора длительности тика?

А нужно ли это? :)

 

Не понял вопроса. ОС требует только чтобы для компилятора была включена поддержка С++ и (если надо) расширения языка. Если для целей проекта надо еще что-то, ну добавьте.

 

Если ответ не удовлетворил, уточните, что конкретно нужно. Либо дождемся ответа от автора порта. :)

 

Понятно :)

 

6. При описании типа процесса размер двух стеков указывать или одного?

 

7. Как "прикинуть" размер требуемых стеков таким образом, чтобы взять его с запасом?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Там есть 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 плюс ожидаемые размеры локальных переменных на стеке (обычно бывает когда есть массивчики или переменные, адрес которых передаётся куда-то).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У нас на форуме уже рассказывалось, как можно ввести контроль за объемом стека в scmRTOS. Методика простая. Выделяем поболее, смотрим за реальной работой процессора, анализируем сколько было использовано. Есть возможность - ужимаем, оставив еще немного про запас.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот и ещё вопросы подоспели :)

 

8. Для чего функция процесса Exec() - статическая?

9. Почему функции WakeUpProcess() и ForceWakeUpProcess() следует использовать с осторожностью? В каких случаях?

10. Какую оптимизацию задавать при компиляции?

 

У нас на форуме уже рассказывалось, как можно ввести контроль за объемом стека в scmRTOS. Методика простая. Выделяем поболее, смотрим за реальной работой процессора, анализируем сколько было использовано. Есть возможность - ужимаем, оставив еще немного про запас.

 

Я читал :)

Но мне как новичку пока сложновато это...

 

TOGGLE(LED_R);

 

Что это?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8. Для чего функция процесса Exec() - статическая?

 

А как иначе? Эта функция должна быть в единственном экземпляре всегда. Кроме того, хотя эта функция и объявлена, как функция процесса, на самом деле к ресурсам процесса она отношения не имеет и служит исключительно для нужд пользовательского кода. Поэтому делать ее нестатической - это передача ненужного this, а учитывая, что эта фукнция нормально не вызывается, то и this нее передать невозможно. Вот такие логические и технические посылы.

 

9. Почему функции WakeUpProcess() и ForceWakeUpProcess() следует использовать с осторожностью? В каких случаях?

Потому, что их использование нарушает обычную логику работы программы. Например, какой-то процесс ожидает события, а тут его в другом месте выдергивают - это как бы нештатная ситуация. Поэтому тут надо действовать внимательно. К слову сказать, функции эти сделаны там скорее на всякий случай, лично я уже и не помню, когда их применял (и применял ли вообще). При правильно организованной программе необходимость в их использовании стемится к нулю. Это как с оператором goto.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А как иначе? Эта функция должна быть в единственном экземпляре всегда.

 

Каждый процесс - объект типа полученного с помощью шаблона process, наследник TBaseProcess.

Каждый процесс существует в единственном экземпляре.

Значит функция будет и так в единственном экземпляре...

Или я не понимаю что такое статическая функция :(

 

Потому, что их использование нарушает обычную логику работы программы. Например, какой-то процесс ожидает события, а тут его в другом месте выдергивают - это как бы нештатная ситуация. Поэтому тут надо действовать внимательно. К слову сказать, функции эти сделаны там скорее на всякий случай, лично я уже и не помню, когда их применял (и применял ли вообще). При правильно организованной программе необходимость в их использовании стемится к нулю. Это как с оператором goto.

 

А что может произойти? Система "упадёт"?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Каждый процесс - объект типа полученного с помощью шаблона process, наследник TBaseProcess.

Каждый процесс существует в единственном экземпляре.

Значит функция будет и так в единственном экземпляре...

Или я не понимаю что такое статическая функция :(

 

Никто не мешает завести больше одного объекта-процесса. Хотя это, конечно, неправильно. Я же ясно, вроде, пояснил, что:

  1. хотя эта функция и объявлена, как функция процесса, на самом деле к ресурсам процесса она отношения не имеет и служит исключительно для нужд пользовательского кода. Это логический довод.
  2. делать ее нестатической - это передача ненужного this, а учитывая, что эта фукнция нормально не вызывается, то и this нее передать невозможно. Это технический довод.
Как бы вы передали в нее указатель this? А без этого она может работать некорректно, и там можно получить очень хорошие грабли.

 

 

 

 

А что может произойти? Система "упадёт"?

 

Можно получить неожиданное поведение. И удивляться. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Раз пошел процесс обсуждения scmRTOS, хочу воспользоваться активным присутствием DXP на форуме.

 

Очень хотелось бы сделать так, чтобы первый объявленный процесс получал высший приоритет, следующий процесс - приоритет на 1 ниже и т.д.

Тогда, объявив в самой ОС число возможных процессов по максимуму всю ОС оформить в виде отдельной библиотеки и пользователям в своей организации раздать, чтобы они "грязными ногами" в ее "чистом теле" не натоптали. Сколько не думал, пока ничего не придумалось. Может есть какие соображения на сей счет?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как бы вы передали в нее указатель this?
Если постараться - можно.

В конструкторе TBaseProcess после Kernel.RegisterProcess(this), там, где формируется начальный стековый кадр, затолкать этот же this в такое место, чтобы после восстановления контекста он оказался в нужных регистрах. Только, насколько я понимаю, тип параметра exec у конструктора для этого должен быть другой - указатель на функцию-член.

 

Топикстартеру:

 

Таким же образом можно было бы передать в функцию процесса указатель на некую структуру/класс, с которыми процесс должен работать, но для этого надо конструктору добавить соответствующий аргумент. Но это имело бы смысл при одновремённом переводе Exec() в нестатическую - чтобы создавать два экземпляра процесса (с разными приоритетами, но это в конечном счёте не важно), работающие одинаковым образом с разными однотипными сущностями и разделяющими код.

 

Но это же делается просто созданием двух процессов, из Exec() которых вызывается одна и та же функция с разными указателями на рабочий объект. Несколько накладнее, пожалуй. И не так красиво.

Но у меня пока такие желания не возникали - ну пусть два UART - ну всё равно у них разное назначение в системе и они обрабатываются по разному.

А ради просто красоты до/пере-делывать структуру ОС особого смысла не вижу.

 

 

 

Очень хотелось бы сделать так, чтобы первый объявленный процесс получал высший приоритет, следующий процесс - приоритет на 1 ниже и т.д.

Тогда, объявив в самой ОС число возможных процессов по максимуму всю ОС оформить в виде отдельной библиотеки и пользователям в своей организации раздать, чтобы они "грязными ногами" в ее "чистом теле" не натоптали. Сколько не думал, пока ничего не придумалось. Может есть какие соображения на сей счет?

Чтобы процессов было "по максимуму" их и задать бы надо. Ну там размер таблиц вырастет, это ладно, но между низшим по приоритету из созданных и Idle заполнено всё должно быть, она же их вызывать попытается.

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

 

Главное - "а зачем"?

Удобство "объектных", а не "исходниковых" библиотек в embeded обсуждалось неоднократно и практически для всего, кроме стандартной библиотеки языка оно для меня сомнительно. А уж scmRTOS, в которой ещё некоторые вещи конфигурируются попроектно - не только число процессов, и компилируется потом с inline-подстановками оптимально под проект - так и подавно.

 

Так то, что должно решаться административными методами, ими и решайте.

Пусть проверка результата работы производится компиляцией со свежевыдернутыми из недоступного по правам записи хранилища, а кто в рабочей копии наменял что-то - сам себе враг. Или ещё что-то придумайте.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вопросы далее :)

 

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(;;)
    {
    }
}

}

Изменено пользователем n_bogoyavlensky

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Скопировал исходники в отдельную папку, прописал пути.

Но компилятор жалуется на отсутствие файлов scmRTOS_CONFIG.h и scmRTOS_TARGET_CFG.h - лежат в папке с проектом (это ведь файлы конфигурации ОС для конкретного проекта и по идее должны храниться в папке проекта). Переместил эти файлы в папку AVR ОС - компилятор перестал ругаться...

Текущая папка проекта должна быть прописана в ключах компилятора в -I иначе файлы из другой папки (из ОС) не видят .h из текущей.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вообще непонятны следующие конструкции в примерах, я запутался...

 

namespace OS {

template<> OS_PROCESS void TProc1::Exec()
{
...

 

В руководстве этого нет...

 

Текущая папка проекта должна быть прописана в ключах компилятора в -I иначе файлы из другой папки (из ОС) не видят .h из текущей.

 

Получилось. Спасибо :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...