Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: scmRTOS - первые шаги - II
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > scmRTOS
MrYuran
Вчера запустил scmRTOS на mspgcc (Thanks to AHTOXA)
Поигрался светодиодиками, пищалкой, буковки повыводил на экранчик.
Теперь такой вопрос:
Насколько я понял, при передаче управления через программные прерывания используется аналоговый компаратор. А мне он, к примеру, бывает нужен.
Если использовать прямую передачу управления, то (цитирую руководство, стр.47)
Цитата
Представим, что МК участвует в обмене данными через UART. Обмен
производится пакетами, состоящими из заголовка, «тела» пакета, где заключена
собственно передаваемая информация, и трейлера, содержащего контрольную
сумму. Логика работы такова, что сначала принимается весь пакет, а затем управ-
ление получает процесс, ожидающий пакет и обрабатывающий заключенную в
нем информацию. Совершенно очевидно, что при приеме заголовка и «тела» па-
кета нет никакой необходимости в передаче управления процессу, т.е. никакого
перепланирования реально происходить не будет – перепланирование с после-
дующей передачей управления процессу, ожидающему пакет, будет иметь место
только после приема трейлера, проверки контрольной суммы и в случае отсутст-
вия ошибок. Таким образом, реально полное сохранение контекста требуется
только один раз на весь пакет, но при рассматриваемом подходе будет происхо-
дить каждый раз при приеме очередного символа приемником UART. Т.е. налицо
очень значительный оверхед, который весьма снижает производительность сис-
темы и очень ограничивает скорость передачи по UART’у.
Еще одним недостатком является то, что каждый ISR включает в себя код
по полному сохранению и восстановлению контекста, что влечет за собой на-
кладные расходы по размеру кода программы.

А у меня как раз желание работать с UARTом на 115200, то есть каждые 100мкс будет приходить байт и вызывать вышеописанные неудобства.
Можно ли всё-таки использовать прямую передачу управления, а если нельзя, то как сохранить компаратор для собственных нужд?
Сергей Борщ
Цитата(MrYuran @ Apr 17 2008, 12:29) *
Насколько я понял, при передаче управления через программные прерывания используется аналоговый компаратор. А мне он, к примеру, бывает нужен.
Там используется любое ненужное прерывание. Например в последних правках порта под AVR будет прерывание готовности флеша, которое нужно только в загрузчике, а писать загрузчик под ОС несколько... необычно. Выбирайте любое прерывание (желательно самое низкоприоритетное из доступных), которое вы можете вызвать программно (т.е. установить его флаг) и поправьте под него scmRTOS_TARGET_CFG.h
Цитата(MrYuran @ Apr 17 2008, 12:29) *
Можно ли всё-таки использовать прямую передачу управления
Можно, если программа будет успевать и вам не жалко потребляемого тока на лишние действия. Поэтому вариант с прерыванием лучше.
dxp
Цитата(MrYuran @ Apr 17 2008, 16:29) *
Насколько я понял, при передаче управления через программные прерывания используется аналоговый компаратор. А мне он, к примеру, бывает нужен.

Можно использовать любое свободное прерывание. Для этого надо просто этот кусок, где задействован компаратор, переписать под выбранное прерывание - там буквально несколько строк. Нужно переопределить вектор прерывания, функцию RaiseContextSwitch() и еще кое-что по мелочи. Все это вынесено на уровень проекта и задается в файле scmRTOS_TARGET_CFG.h. Файл небольшой, там все увидете.
MrYuran
Цитата(Сергей Борщ @ Apr 17 2008, 14:00) *
Можно, если программа будет успевать и вам не жалко потребляемого тока на лишние действия. Поэтому вариант с прерыванием лучше.

Нее, тока не жалко! biggrin.gif
24В/2А - все мои! (хотя нет, немного ТЭНу надо оставить)
Спасибо за совет, сделал прерывание от PORT1
Код
#if CONTEXT_SWITCH_ISR_VECTOR == PORT1_VECTOR
#define NON_USED_PIN    1
    INLINE inline void RaiseContextSwitch() { P1IE |= (NON_USED_PIN);
                                              P1IFG |= (NON_USED_PIN);
                                            } // set flag and enable interrupt

        class TNestedISRW
        {
        public:
            TNestedISRW() : State(P1IE) { P1IE &= ~(NON_USED_PIN);
                                          P1IFG &= ~(NON_USED_PIN);
                                          __enable_interrupt(); }
            ~TNestedISRW() { __disable_interrupt(); P1IE = State; }

        private:
            byte State;
        };

        #define ENABLE_NESTED_INTERRUPTS() OS::TNestedISRW NestedISRW
#endif

Сам не понял чё сваял, но главное работает

bb-offtopic.gif
Всё, теперь товарища снабженца с евоными х135 будем гнать поганой метлой, пусть в другом месте экономит. Лучше б 169 закупил, там DMA и DAC есть всего за 1 лишний бакс...
Сергей Борщ
Цитата(MrYuran @ Apr 17 2008, 15:35) *
Сам не понял чё сваял, но главное работает
Мне кажется, P1IFG можно устанавливать только однажды, в процессе инициализации - он ведь не сбрасывается автоматически при переходе по вектору. А дальше рулить только P1IE. Мелочь, но несколько тактов и байтов экономится.
MrYuran
Цитата
P1IFG можно устанавливать только однажды, в процессе инициализации

Точно, так и сделал.

Ещё маленький вопросец.
Я в операционках полный чяйнег, как и в плюсах.
Введение классов как-нибудь сказывается на размере кода?
Преобразовал модуль вывода на экранчик в класс TIndicator, и чё-то такое ощущение, что размер на килобайт увеличился. Может, конечно, оптический обман зрения...
Зато какая красота...
Нажмите для просмотра прикрепленного файла
Не надо лазить по исходникам, вспоминать как функция называется, какие аргументы...
dxp
Цитата(MrYuran @ Apr 17 2008, 20:32) *
Введение классов как-нибудь сказывается на размере кода?
Преобразовал модуль вывода на экранчик в класс TIndicator, и чё-то такое ощущение, что размер на килобайт увеличился.

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

Смотрите по листингам и мап файлу, на что размер ушел. Обратите внимание, не вызывается ли в конструкторе функция new - выделение памяти из кучи. Эта штука вполне может сожрать килобайт. И был такой косяк на старых версиях IAR, но уже давно пофиксили.
MrYuran
Такой ещё вопросик. Пара.
Вызов метода OS::WakeUpProcess вызывает немедленную перепланировку процессов или только по системному таймеру?
Можно ли его применять внутри прерываний
Можно ли сбрасывать WDT c целью немедленной перепланировки, чем это может быть чревато или как сделать по-другому
Чем отличается WakeUpProcess от ForceWakeUpProcess

И ещё:
Может есть какой аналог Sleep(), но который не системные тики считает, а к примеру, микросекунды (загнул конечно, ну хоть десятки).
В смысле не в штатных средствах операционки, а у кого-нибудь из сообщества.
Какой-нибудь класс виртуального таймера
Самому лень писать, а Pause(mks){while(mks--)_NOP();} как-то уже не катит...
dxp
Цитата(MrYuran @ Apr 18 2008, 13:52) *
Вызов метода OS::WakeUpProcess вызывает немедленную перепланировку процессов или только по системному таймеру?
Можно ли его применять внутри прерываний
Можно ли сбрасывать WDT c целью немедленной перепланировки, чем это может быть чревато или как сделать по-другому
Чем отличается WakeUpProcess от ForceWakeUpProcess

Цитата из доки:

Цитата
• WakeUpProcess(TBaseProcess& p); Выводит процесс из состояния «спячки». Процесс переводится в состояние готового к выполнению, только если он находился в состоянии ожидания с таймаутом события; при этом, если этот процесс имеет приоритет выше текущего, то он сразу получает управление;

• ForceWakeUpProcess(TBaseProcess& p); Выводит процесс из со-стояния «спячки». Процесс переводится в состояние готового к выполне-нию всегда. при этом, если этот процесс имеет приоритет выше текуще-го, то он сразу получает управление; Этой функцией нужно пользоваться с особой осторожностью, т.к. некорректное использование может привес-ти к неправильной (непредсказуемой) работе программы;


Из прерываний, оформленных соответствующим образом, вызывать можно. Но зачем? Обе эти функции служат для аварийных целей - когда надо разбудить процесс нештатным образом. Для штатной работы надо пользоваться средствами межпроцессного взаимодействия. Лично я не помню случая, когда бы эти функции мне пригодились. Она там присутствуют скорее для комплекта. smile.gif

WDT сбрасывать не пробовал, не понял, чего вы хотите этим добиться.

Цитата(MrYuran @ Apr 18 2008, 13:52) *
Может есть какой аналог Sleep(), но который не системные тики считает, а к примеру, микросекунды (загнул конечно, ну хоть десятки).
В смысле не в штатных средствах операционки, а у кого-нибудь из сообщества.
Какой-нибудь класс виртуального таймера
Самому лень писать, а Pause(mks){while(mks--)_NOP();} как-то уже не катит...

Нет, такой вещи нет - сложновато привязывать абсолютные единицы времени ко всем возможным ситуациям (платформам, периферии). То, что вам нужно, реализуется на таймере и OS::TEventFlag'е.
MrYuran
Ну чё, в целом вроде разобрался, поигрался немного, перенёс рабочий проект (non-OS) на scmRTOS, вроде всё работает. (Правда, иногда "залипает" и сбрасывается, но это пока мелочи)

Вопрос теперь такой: как максимально эффективно работать с УАРТом?
Я хочу работать на 115200, то есть между символами будет 100мкс.
Схема передачи управления - программное прерывание.
Я планирую в прерывании читать буфер УАРТ и кидать байт в глобальный буфер.
А потом по таймауту приёма потихоньку этот буфер разгребать.
Какие-нибудь подводные грабли могут быть?

И ещё:
OS::TISRW ISRW;
вот эту штуку обязательно писать в прерывании?
Что будет, если её не поставить?
Сергей Борщ
Цитата(MrYuran @ Apr 24 2008, 12:05) *
И ещё:
OS::TISRW ISRW;
вот эту штуку обязательно писать в прерывании?
Что будет, если её не поставить?
Если прерывание не использует сервисы ОС и в нем не разрешаются вложенные прерывания - то все нормально. А если использует или разрешаются - то перепланировка может быть выполнена внутри прерывания с разрушением стекового фрейма. Результат, сами понимаете, любой отличный от нормальной работы.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.