MrYuran 16 17 апреля, 2008 Опубликовано 17 апреля, 2008 (изменено) · Жалоба Вчера запустил scmRTOS на mspgcc (Thanks to AHTOXA) Поигрался светодиодиками, пищалкой, буковки повыводил на экранчик. Теперь такой вопрос: Насколько я понял, при передаче управления через программные прерывания используется аналоговый компаратор. А мне он, к примеру, бывает нужен. Если использовать прямую передачу управления, то (цитирую руководство, стр.47) Представим, что МК участвует в обмене данными через UART. Обмен производится пакетами, состоящими из заголовка, «тела» пакета, где заключена собственно передаваемая информация, и трейлера, содержащего контрольную сумму. Логика работы такова, что сначала принимается весь пакет, а затем управ- ление получает процесс, ожидающий пакет и обрабатывающий заключенную в нем информацию. Совершенно очевидно, что при приеме заголовка и «тела» па- кета нет никакой необходимости в передаче управления процессу, т.е. никакого перепланирования реально происходить не будет – перепланирование с после- дующей передачей управления процессу, ожидающему пакет, будет иметь место только после приема трейлера, проверки контрольной суммы и в случае отсутст- вия ошибок. Таким образом, реально полное сохранение контекста требуется только один раз на весь пакет, но при рассматриваемом подходе будет происхо- дить каждый раз при приеме очередного символа приемником UART. Т.е. налицо очень значительный оверхед, который весьма снижает производительность сис- темы и очень ограничивает скорость передачи по UART’у. Еще одним недостатком является то, что каждый ISR включает в себя код по полному сохранению и восстановлению контекста, что влечет за собой на- кладные расходы по размеру кода программы. А у меня как раз желание работать с UARTом на 115200, то есть каждые 100мкс будет приходить байт и вызывать вышеописанные неудобства. Можно ли всё-таки использовать прямую передачу управления, а если нельзя, то как сохранить компаратор для собственных нужд? Изменено 17 апреля, 2008 пользователем MrYuran Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 17 апреля, 2008 Опубликовано 17 апреля, 2008 · Жалоба Насколько я понял, при передаче управления через программные прерывания используется аналоговый компаратор. А мне он, к примеру, бывает нужен.Там используется любое ненужное прерывание. Например в последних правках порта под AVR будет прерывание готовности флеша, которое нужно только в загрузчике, а писать загрузчик под ОС несколько... необычно. Выбирайте любое прерывание (желательно самое низкоприоритетное из доступных), которое вы можете вызвать программно (т.е. установить его флаг) и поправьте под него scmRTOS_TARGET_CFG.h Можно ли всё-таки использовать прямую передачу управленияМожно, если программа будет успевать и вам не жалко потребляемого тока на лишние действия. Поэтому вариант с прерыванием лучше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 34 17 апреля, 2008 Опубликовано 17 апреля, 2008 · Жалоба Насколько я понял, при передаче управления через программные прерывания используется аналоговый компаратор. А мне он, к примеру, бывает нужен. Можно использовать любое свободное прерывание. Для этого надо просто этот кусок, где задействован компаратор, переписать под выбранное прерывание - там буквально несколько строк. Нужно переопределить вектор прерывания, функцию RaiseContextSwitch() и еще кое-что по мелочи. Все это вынесено на уровень проекта и задается в файле scmRTOS_TARGET_CFG.h. Файл небольшой, там все увидете. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 16 17 апреля, 2008 Опубликовано 17 апреля, 2008 · Жалоба Можно, если программа будет успевать и вам не жалко потребляемого тока на лишние действия. Поэтому вариант с прерыванием лучше. Нее, тока не жалко! 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: Всё, теперь товарища снабженца с евоными х135 будем гнать поганой метлой, пусть в другом месте экономит. Лучше б 169 закупил, там DMA и DAC есть всего за 1 лишний бакс... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 17 апреля, 2008 Опубликовано 17 апреля, 2008 · Жалоба Сам не понял чё сваял, но главное работаетМне кажется, P1IFG можно устанавливать только однажды, в процессе инициализации - он ведь не сбрасывается автоматически при переходе по вектору. А дальше рулить только P1IE. Мелочь, но несколько тактов и байтов экономится. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 16 17 апреля, 2008 Опубликовано 17 апреля, 2008 · Жалоба P1IFG можно устанавливать только однажды, в процессе инициализации Точно, так и сделал. Ещё маленький вопросец. Я в операционках полный чяйнег, как и в плюсах. Введение классов как-нибудь сказывается на размере кода? Преобразовал модуль вывода на экранчик в класс TIndicator, и чё-то такое ощущение, что размер на килобайт увеличился. Может, конечно, оптический обман зрения... Зато какая красота... Не надо лазить по исходникам, вспоминать как функция называется, какие аргументы... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 34 17 апреля, 2008 Опубликовано 17 апреля, 2008 · Жалоба Введение классов как-нибудь сказывается на размере кода? Преобразовал модуль вывода на экранчик в класс TIndicator, и чё-то такое ощущение, что размер на килобайт увеличился. Небольшой оверхед по размеру кода есть в некоторых случаях - связано с тем, что инициализация делается с помощью конструктора, т.к. отдельная функция вызывается для инициализации, это, конечно, толще, вариант со статической инициализацией (которая имеет место для объектов встроенных типов). Но и гибкости больше. И, разумеется, в килобайт оно выливаться не должно. Смотрите по листингам и мап файлу, на что размер ушел. Обратите внимание, не вызывается ли в конструкторе функция new - выделение памяти из кучи. Эта штука вполне может сожрать килобайт. И был такой косяк на старых версиях IAR, но уже давно пофиксили. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 16 18 апреля, 2008 Опубликовано 18 апреля, 2008 (изменено) · Жалоба Такой ещё вопросик. Пара. Вызов метода OS::WakeUpProcess вызывает немедленную перепланировку процессов или только по системному таймеру? Можно ли его применять внутри прерываний Можно ли сбрасывать WDT c целью немедленной перепланировки, чем это может быть чревато или как сделать по-другому Чем отличается WakeUpProcess от ForceWakeUpProcess И ещё: Может есть какой аналог Sleep(), но который не системные тики считает, а к примеру, микросекунды (загнул конечно, ну хоть десятки). В смысле не в штатных средствах операционки, а у кого-нибудь из сообщества. Какой-нибудь класс виртуального таймера Самому лень писать, а Pause(mks){while(mks--)_NOP();} как-то уже не катит... Изменено 18 апреля, 2008 пользователем MrYuran Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 34 18 апреля, 2008 Опубликовано 18 апреля, 2008 · Жалоба Вызов метода OS::WakeUpProcess вызывает немедленную перепланировку процессов или только по системному таймеру? Можно ли его применять внутри прерываний Можно ли сбрасывать WDT c целью немедленной перепланировки, чем это может быть чревато или как сделать по-другому Чем отличается WakeUpProcess от ForceWakeUpProcess Цитата из доки: • WakeUpProcess(TBaseProcess& p); Выводит процесс из состояния «спячки». Процесс переводится в состояние готового к выполнению, только если он находился в состоянии ожидания с таймаутом события; при этом, если этот процесс имеет приоритет выше текущего, то он сразу получает управление; • ForceWakeUpProcess(TBaseProcess& p); Выводит процесс из со-стояния «спячки». Процесс переводится в состояние готового к выполне-нию всегда. при этом, если этот процесс имеет приоритет выше текуще-го, то он сразу получает управление; Этой функцией нужно пользоваться с особой осторожностью, т.к. некорректное использование может привес-ти к неправильной (непредсказуемой) работе программы; Из прерываний, оформленных соответствующим образом, вызывать можно. Но зачем? Обе эти функции служат для аварийных целей - когда надо разбудить процесс нештатным образом. Для штатной работы надо пользоваться средствами межпроцессного взаимодействия. Лично я не помню случая, когда бы эти функции мне пригодились. Она там присутствуют скорее для комплекта. :) WDT сбрасывать не пробовал, не понял, чего вы хотите этим добиться. Может есть какой аналог Sleep(), но который не системные тики считает, а к примеру, микросекунды (загнул конечно, ну хоть десятки). В смысле не в штатных средствах операционки, а у кого-нибудь из сообщества. Какой-нибудь класс виртуального таймера Самому лень писать, а Pause(mks){while(mks--)_NOP();} как-то уже не катит... Нет, такой вещи нет - сложновато привязывать абсолютные единицы времени ко всем возможным ситуациям (платформам, периферии). То, что вам нужно, реализуется на таймере и OS::TEventFlag'е. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 16 24 апреля, 2008 Опубликовано 24 апреля, 2008 · Жалоба Ну чё, в целом вроде разобрался, поигрался немного, перенёс рабочий проект (non-OS) на scmRTOS, вроде всё работает. (Правда, иногда "залипает" и сбрасывается, но это пока мелочи) Вопрос теперь такой: как максимально эффективно работать с УАРТом? Я хочу работать на 115200, то есть между символами будет 100мкс. Схема передачи управления - программное прерывание. Я планирую в прерывании читать буфер УАРТ и кидать байт в глобальный буфер. А потом по таймауту приёма потихоньку этот буфер разгребать. Какие-нибудь подводные грабли могут быть? И ещё: OS::TISRW ISRW; вот эту штуку обязательно писать в прерывании? Что будет, если её не поставить? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 24 апреля, 2008 Опубликовано 24 апреля, 2008 · Жалоба И ещё: OS::TISRW ISRW; вот эту штуку обязательно писать в прерывании? Что будет, если её не поставить? Если прерывание не использует сервисы ОС и в нем не разрешаются вложенные прерывания - то все нормально. А если использует или разрешаются - то перепланировка может быть выполнена внутри прерывания с разрушением стекового фрейма. Результат, сами понимаете, любой отличный от нормальной работы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться