Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: scmRTOS и MSP430 low power mode
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
Dr.NoA
Использую операционную систему scmRTOS на микроконтроллерах MSP430 (в основном F169 и F1611), все замечательно, но есть одна проблема.
Хотелось бы переводить МК в режим пониженного энергопотребления (например, LPM3), когда ему нечем заняться. Насколько я понимаю, для этого достаточно в теле функции void OS::IdleProcessUserHook() выполнить команду _BIS_SR(LPM3_bits). В результате МК "заснет" до следующего прерывания от сторожевого таймера, от которого тактируется планировчик задач ОС. В обработчике прерывания нужно выполнить _BIC_SR_IRQ(LPM3_bits), чтобы МК нормально вернулся в активный режим. Но проблема в том, что код обработчика прерывания от сторожевого таймера является частью scmRTOS, а добавление одной строчки "_BIC_SR_IRQ(LPM3_bits)" приведет к нарушению условий лицензии на scmRTOS.
В общем вопрос в следующем. Решал ли кто-нибудь эту задачу без внесения изменений в исходники операционки? Если да, то поделитесь рецептом.

P.S.
Я, конечно, понимаю, что проблема несколько надуманная, но все таки хочется хоть что-то использовать без нарушения лицензии.
dxp
Цитата(Dr.NoA @ Sep 7 2006, 17:07) *
Использую операционную систему scmRTOS на микроконтроллерах MSP430 (в основном F169 и F1611), все замечательно, но есть одна проблема.
Хотелось бы переводить МК в режим пониженного энергопотребления (например, LPM3), когда ему нечем заняться. Насколько я понимаю, для этого достаточно в теле функции void OS::IdleProcessUserHook() выполнить команду _BIS_SR(LPM3_bits). В результате МК "заснет" до следующего прерывания от сторожевого таймера, от которого тактируется планировчик задач ОС. В обработчике прерывания нужно выполнить _BIC_SR_IRQ(LPM3_bits), чтобы МК нормально вернулся в активный режим. Но проблема в том, что код обработчика прерывания от сторожевого таймера является частью scmRTOS, а добавление одной строчки "_BIC_SR_IRQ(LPM3_bits)" приведет к нарушению условий лицензии на scmRTOS.
В общем вопрос в следующем. Решал ли кто-нибудь эту задачу без внесения изменений в исходники операционки? Если да, то поделитесь рецептом.

Там для системного таймера есть тоже соответсвующий хук. Его нужно разрешить в конфигурации и определить его потроха.

Цитата(Dr.NoA @ Sep 7 2006, 17:07) *
Я, конечно, понимаю, что проблема несколько надуманная, но все таки хочется хоть что-то использовать без нарушения лицензии.

Вы как будто не в России. smile.gif
Dr.NoA
Цитата(dxp @ Sep 7 2006, 15:24) *
Там для системного таймера есть тоже соответсвующий хук. Его нужно разрешить в конфигурации и определить его потроха.

Это я знаю, но как-то не подумал его использовать для сброса флагов LPM-режима. Надо будет попробовать. Спасибо.
Цитата
Вы как будто не в России. smile.gif

В России, но я же говорю, что хочу хотя бы что-то честно использоватьsmile.gif Тем более что автор scmRTOS денег за нее не хочет, а просит просто не курочить.
dxp
Цитата(Dr.NoA @ Sep 7 2006, 19:38) *
Цитата

Вы как будто не в России. smile.gif

Тем более что автор scmRTOS денег за нее не хочет, а просит просто не курочить.

Ну, думается, что сломать Вы там ничего не сломаете так, чтоб нанести ущерб автору. smile.gif И потом, я знаю, что народ рихтует под себя, не боится. Никто еще не пострадал от гнева автора. biggrin.gif

Самым негативным моментом (для Вас опять же, не для автора) того, что залезете руками, будет то, что когда (если вдруг) выйдет новая версия, и Вы захотите ее использовать, то придется опять лезть руками и править. Не лучше ли обратиться к автору с предложением внести ту или иную фичу - если в ней есть рациональное зерно, то оно наверняка будет принято к рассмотрению.
Dr.NoA
Цитата(dxp @ Sep 7 2006, 17:11) *
Цитата(Dr.NoA @ Sep 7 2006, 19:38) *

Цитата

Вы как будто не в России. smile.gif

Тем более что автор scmRTOS денег за нее не хочет, а просит просто не курочить.

Ну, думается, что сломать Вы там ничего не сломаете так, чтоб нанести ущерб автору. smile.gif И потом, я знаю, что народ рихтует под себя, не боится. Никто еще не пострадал от гнева автора. biggrin.gif

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

Да, проблема с совместимостью тоже является одной из причин нежелания делать "тюнинг" операционки.
Но думаю, что в данном случае можно обойдись штатными средствами, воспользовавшись вашим советом. Правда пока не проверял.

Кстати, по поводу "рихтования". Вы случайно не встречали порта scmRTOS на 51-семейство?
dxp
Цитата(Dr.NoA @ Sep 7 2006, 23:36) *
Но думаю, что в данном случае можно обойдись штатными средствами, воспользовавшись вашим советом. Правда пока не проверял.

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

Цитата(Dr.NoA @ Sep 7 2006, 23:36) *
Кстати, по поводу "рихтования". Вы случайно не встречали порта scmRTOS на 51-семейство?

Нет, все порты лежат вместе. Для 51-го оно врядли появится по причине того, что на оный МК даже С ложится плохо, а уж С++... К тому же, не помню, чтобы для 51-го вообще был С++, может быть ошибаюсь.
yornik
Поправьте меня, если ошибаюсь: в изначальном виде порт scmRTOS для MSP430 заточен под использование сторожевого таймера в режиме источника периодических прерываний => точности по времени в вызовах типа OS::Sleep( MY_FAVORITE_PROTOCOL_TIMEOUT ) - никакой => править надо по-любому?
Dr.NoA
Цитата(yornik @ Sep 8 2006, 16:30) *
Поправьте меня, если ошибаюсь: в изначальном виде порт scmRTOS для MSP430 заточен под использование сторожевого таймера в режиме источника периодических прерываний => точности по времени в вызовах типа OS::Sleep( MY_FAVORITE_PROTOCOL_TIMEOUT ) - никакой => править надо по-любому?

А что вы хотите править?
Просто по умолчанию сторожевой таймер тактируется внутренним генератором DCO, у которого действительно частота "гуляет". Если вам нужно точнее, то можете при загрузке ОС перенастроить сторожевой таймер на внешний тактовый сигнал, например, часовой кварц. Сделать это можно в функции OS::SystemStartUserHook(). То есть штатные средства вам позволяют это сделать и править исходники нет необходимости.
Hamster1979
Цитата(dxp @ Sep 8 2006, 08:31) *
Должно работать - этот хук там для того и предназначен, чтобы пользователь мог выполнить какие-то действия внутри обработчика прерывания от системного таймера, не модифицируя исходный код.

Задача переходит в режим пониженного потребления функцией _BIS_SR (LPM3_bits+GIE).
Попробовал выйти из пониженного режима энергопотребления, используя вызов функции _BIC_SR_IRQ (LPM3_bits) в хуке системного таймера ОС. При компиляции выдает ошибку This intrinsic function can only be used in interrupt or monitor function. Посмотрел в исходники операционки - действительно хук не имеет модификатора __inline или __monitor. Как тогда выйти из режима power down?
dxp
Цитата(Hamster1979 @ Jan 16 2010, 00:14) *
Задача переходит в режим пониженного потребления функцией _BIS_SR (LPM3_bits+GIE).
Попробовал выйти из пониженного режима энергопотребления, используя вызов функции _BIC_SR_IRQ (LPM3_bits) в хуке системного таймера ОС. При компиляции выдает ошибку This intrinsic function can only be used in interrupt or monitor function. Посмотрел в исходники операционки - действительно хук не имеет модификатора __inline или __monitor. Как тогда выйти из режима power down?

А если написать свою __inline __monitor функцию, из которой звать означенный интринсик, а вызов самой этой функции поместить в хук?
Hamster1979
Цитата(dxp @ Jan 16 2010, 14:05) *
А если написать свою __inline __monitor функцию, из которой звать означенный интринсик, а вызов самой этой функции поместить в хук?

Пробовал. Не помагает. Восстанавливается контекс задачи и вместе с ним состояние бита CPUOFF....

Дело в том что насколько я понимаю BIC_SR_IRQ функция меняет состояние битов не в самом теле функции а на выходе из нее ... Если не использовать операционную систему то применяют BIC_SR_IRQ в обработчике прерывания ... вызываемого при необходимости выхода из режима power down. Если использовать функцию BIC_SR_IRQ во вложенной в вызываемой из прерывания функции пусть даже __inerrupt и __monitor, модификация бита CPUOFF произойдет не на выходе из прерывания а внутри него..поправьте если я не прав.
dxp
Цитата(Hamster1979 @ Jan 16 2010, 17:23) *
Пробовал. Не помагает. Восстанавливается контекс задачи и вместе с ним состояние бита CPUOFF....

Дело в том что насколько я понимаю BIC_SR_IRQ функция меняет состояние битов не в самом теле функции а на выходе из нее ... Если не использовать операционную систему то применяют BIC_SR_IRQ в обработчике прерывания ... вызываемого при необходимости выхода из режима power down. Если использовать функцию BIC_SR_IRQ во вложенной в вызываемой из прерывания функции пусть даже __inerrupt и __monitor, модификация бита CPUOFF произойдет не на выходе из прерывания а внутри него..поправьте если я не прав.

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

Исходя из вышесказанного, применять этот интринсик всегда нужно только в прерывании безотносительно к тому, используется ОС или нет. ОС - это обычная программа, на логику применения обсуждаемого интринсика это влияния оказывать не должно.

И к хуку IdleProcess'а все это отношения не имеет.
Hamster1979
Даже не так. При применении _Pragma ("inline = forced") выдало warning что не может встроить мою функцию (которая с модификатором __monitor, внтури содержит _BIC_SR_IRQ(LPM3bits)).
Вот отрывок заголовочного файла power.h:
Код
#define INLINE _Pragma("inline = forced")
. . .
class PWR
{
    public:
        static void init(void);
        static void off(void);
. . .
        INLINE static inline __monitor void wakeUp(void)
        {
               _BIC_SR_IRQ(LPM3bits);
        };
};


отрывок main.cpp:

Код
void OS::SystemTimerUserHook(void)
{
       adc.read();
       adc.start();
       if(adc.reault[2] < 900)
       {
              PwrOffFlag.SignalISR();
       }
       else
       {
              wakeUp();
       }
}


Код
OS_PROCESS void TPWRProc(void)
{
       for(;;)
       {
             pwr.off();
       }
}


Код
//-------------------------------------------
// Реакция на пропадание уровня питания
//-------------------------------------------
void PWR::off(void)
{
    PowerOffFlag.Wait();
    ...
    //Выключение переферии
    ...
    BIS_SR(LPM3_bits +GIE);
}

Warning:[G004]: Could not inline function "PWR::wakeUp"
... на всякий случай, чтобы понятно было - у меня проект написан на С под msp430f449 без опреционной системы...я его переписываю с применением ОС(так как его очень трудно стало сопровождать, необходимы стали средства межпроцессоного взаимодействия, оптимизировать ресурсы и логику работы)..scmRTOS очень понравилась, перерписал почти все драйвера на ней,демку для проверки наваял все работает.. кроме power down.

Цитата(dxp @ Jan 16 2010, 16:47) *
Исходя из вышесказанного, применять этот интринсик всегда нужно только в прерывании безотносительно к тому, используется ОС или нет. ОС - это обычная программа, на логику применения обсуждаемого интринсика это влияния оказывать не должно.

И к хуку IdleProcess'а все это отношения не имеет.

Естественно не имеет . я ведь написал выше что использую хук системного таймера .А он работает по прерыванию. Устройство выключается пользователем, отключается основное питание . Устройство должно выключить узлы периферии (которые потребляют очень много, ток несколько ампер может быть) на плате, узлы перифери процессора и перейти в режим power down и работу от литиевой батареии. при этом отсаются рабочими только прерывания... гарантированным включенным прерыванием на этот момент может только системный таймер ОС . Вот я его хук и пользую.
dxp
Цитата(Hamster1979 @ Jan 16 2010, 20:34) *
Даже не так. При применении _Pragma ("inline = forced") выдало warning что не может встроить мою функцию (которая с модификатором __monitor, внтури содержит _BIC_SR_IRQ(LPM3bits)).

smile.gif Стало еще понятнее.

А зачем вам в прерывании фукнция __monitor? Только если разрешены вложенные прерывания. И, имхо, в при использовании ОС логично применять для этого критические секции (и без ОС тоже лучше не использовать эти непереносимые расширения конкретного компилятора, а лучше написать что-нибудь свое вроде критической секции). Без нее со встроенной _BIC_SR_IRQ должно работать. Насколько понимаю, этот интринсик важно вызывать с уровня самого прерывания, чтобы компилятор правильно нашел копию SR в стеке. Поэтому если интринсик "обернут" другой функцией, то эта функция должна быть встраиваемой. Таким образом, у вас и хук таймера должен быть встроенным, и wakeUp тоже. Попробуйте без __monitor. Не вижу тут никаких противоречий, связанных с использованием ОС.
Hamster1979
Цитата(dxp @ Jan 17 2010, 16:52) *
А зачем вам в прерывании фукнция __monitor?
...
Попробуйте без __monitor. Не вижу тут никаких противоречий, связанных с использованием ОС.

biggrin.gif ну мы так опять покругу пойдем. __monitor - потому что просто вставить _BIC_SR_IRQ компилятор в хук системного таймера не даст (см мои посты выше), в том то и проблема что хук не ВСТРОЕННАЯ функция! Ладно я пошел дальше вкорячил этот интринсик, вызываемый тупо по глобальному флагу, непосредственно в обработчик прерывания системного таймера (это уже не хук а исходы ОС, чтобы не городить встраивание inline и _monitor)- не помогло. Потом сделал голое (без всяких оберток и т.п.)аппаратное прерывание вызываемое только когда нужно выйти из режима спячки, в обработчике - интринсик - - не работает!!! бит CPUoff всегда в еденице при возврате из прерывания .. у меня впечатление что интринсик некорректно находит копию регистра в стеке либо регистр восстанавливается для задачи из другого места(не там где интринсик правит). Причем без ОС все работает как должно.
Вобщем буду рад примеру работаещему с low power и scmRTOS (в любом виде хоть с правками исходов ОС, хоть с вставками на асме) ))) оч надо!
dxp
Цитата(Hamster1979 @ Jan 18 2010, 02:38) *
Вобщем буду рад примеру работаещему с low power и scmRTOS (в любом виде хоть с правками исходов ОС, хоть с вставками на асме) ))) оч надо!

А у вас там, часом, нет ли переключения на стек прерываний в прерывании от системного таймера? Если оно есть, то все эти потуги с SR в прерывании идут лесом. Посмотрите на конфигурацию - определение макроса:

#define scmRTOS_ISRW_TYPE TISRW_SS // это из примера - тут оно как раз есть

Ну, и на симуляторе можно по шагам это место пройти - где интринсик копию в стеке изменяет и потом посмотреть, что стек не переключен.
ReAl
Цитата(dxp @ Jan 18 2010, 06:16) *
#define scmRTOS_ISRW_TYPE TISRW_SS // это из примера - тут оно как раз есть

Я поначалу тоже об этом подумал, но увидел
Цитата
Потом сделал голое (без всяких оберток и т.п.)аппаратное прерывание вызываемое только когда нужно выйти из режима спячки,
и понял так, что это было "внеосевое" прерывание без TISRW* вообще.
dxp
Цитата(ReAl @ Jan 18 2010, 14:26) *
и понял так, что это было "внеосевое" прерывание без TISRW* вообще.

Если "внеосевое", то тогда вообще разницы быть не должно. В каком-то процессе "заснули", в прерывании "проснулись" и при выходе оказались в том же процессе (с тем же стеком, никаких перепланирований не производилось). Т.е. ситуация ровно такая, как без ОС.
SSerge
Я тут подумал...
Когда процессор должен уходить в спячку? Когда ему нечем заняться.
При очередной перепланировке выясняется что других готовых к исполнению процессов нет и управление получает IdleProcess, а уже в нём процессор усыпляют. Тут всё правильно.

А вот в обратную сторону логично было бы что процессор пробуждается когда планировщик обнаружил готовый к исполнению процесс и передал управление ему. Заметим, что прерывание от системного таймера не единственное такое событие, другие прерывания также могут привести к перепланировке.

Получается, что попытка выходить из спячки в обработчике прерывания от таймера есть подход идеологически неправильный.
dxp
Цитата(SSerge @ Jan 18 2010, 17:36) *
Получается, что попытка выходить из спячки в обработчике прерывания от таймера есть подход идеологически неправильный.

А тут мы не знаем, как у автора задумано - может, ему надо именно так, и все остальные источники событий принудительно заблокированы. Кстати, я тоже в свое время делал так, когда работал с АЦП - лочил все источники событий, чтобы ничего не пробуждало процессор во время АЦ преобразования, и АЦП спокойно работал в тишине, загружая регистры данных результатами преобразований (до 16 штук). Иначе, когда работает ядро, сложно было получить результат, близкий к 12 битам. Вроде, этот режим (многократное АЦ преобразование с усыплением процессора и пробуждением по окончании) - штатная задумка TI.

Правда, в том случае пробуждение делалось в прерывании от АЦП, что логично. А системный таймер наоборот блокировался. Дождемся автора темы, может он объяснит. smile.gif
Dr.NoA
Цитата(SSerge @ Jan 18 2010, 14:36) *
Получается, что попытка выходить из спячки в обработчике прерывания от таймера есть подход идеологически неправильный.

Цитата(dxp @ Jan 18 2010, 15:00) *
Дождемся автора темы, может он объяснит. smile.gif

Если вы ждете меня, то могу пояснить.

Рассуждения SSerge совершенно верные. Переход в спящий режим выполняется в функции IdleProcessUserHook(), если выясняется, что процессору делать нечего. В частности, при переходе в спящий режим MCLK переключается на DCO, а высокочастотный генератор выключается, при выходе из спящего режима мы опять переключаемся на XT2. Естественно, было бы глупо выполнять выход из спящего режима при каждом прерывании от системного таймера, так как накладные расходы на переключение нивелировали бы всю экономию от спящего режима, поэтому для выхода из спящего режима пришлось завести еще одну функцию - IdleProcessExitUserHook(), которая вызывается планировщиком перед тем, как передать управление от Idle-процесса к какому-либо нормальному процессу. Именно в IdleProcessExitUserHook() выполняется восстановление системы тактирования и прочие действия для перехода в активный режим работы.
Hamster1979
Цитата(dxp @ Jan 18 2010, 07:16) *
А у вас там, часом, нет ли переключения на стек прерываний в прерывании от системного таймера? Если оно есть, то все эти потуги с SR в прерывании идут лесом. ...

laughing.gif опс!... вы совершенно правы! в этом и был у меня косяк..я то читал описание на на версию операционки 2.0 там такой фичи небыло...вот и накосячил...щас поставил TISRW вместо TISRW_SS , запретил NESTED_INTERRUPTS и все заработало... dxp большое спасибо.

Цитата(Dr.NoA @ Jan 18 2010, 16:58) *
Если вы ждете меня, то могу пояснить....

а у меня ситуация не такая. я перехожу в спячку не от нечего делать (Idle процесс)а по показаниям АЦП который меряетнапряжуху на присобаченом источнике питания, т.е. когда питание отключается впадаю в спячку с выключением всего и вся(не только в процессоре но и на плате, иначе резервное питалово просядет и разрядится). Так как проверяю результаты измерения АЦП в хуке системного таймера (он достаточно часто тикает для этого ), то логично что и будиться буду в нем же (накладные расходы - один оператор сравнения if и интринсик)..
Сделано на самом деле так - процесс с навивысшим приоритетом ждет Event(событие) об отсутсвии основного питания...когда ивент получит выключает все в т.ч. и CPU (это значит что останавливается и сам процесс!! в этом месте)... дальше если питание появилось снова запускаем CPU и выполнение процесса с наивысшим приоритетом продолжится..а там дальше вся переферия включается заново и потом по циклу ..опять засыпаем до получения EVENT... оч просто.
dxp
Цитата(Dr.NoA @ Jan 18 2010, 19:58) *
Если вы ждете меня, то могу пояснить.

Прошу прощения, это я внес путаницу. Я имел в виду автора обсуждаемого вопроса, а не темы, конечно. smile.gif
jorikdima
В качестве результата обсуждения, как в итоге-то надо организовывать low power mode в случаях, когда нечего делать?
Я вообще рассуждал, что единственное, что требуется, это написать одну строчку в OS::IdleProcessUserHook() , а именно _BIS_SR(LPM3_bits).
Зачем где-то вызывать _BIC_SR_IRQ(LPM3_bits)? Ведь войдя в обработчик прерывания от системного таймера, в случае если надо будет переключить задачу, то восстановится полностью контекст этой задачи, в том числе и регистр SR, в котором не будет уже стоять битов CPUOFF и пр., соответственно таск продолжит выполняться. Как только шедулер решит, что ни один таск не готов, то включится опять IDLE и восстановится его контекст, вместе с CPUOFF, контроллер опять заснет. Я правильно понимаю все?
Спасибо.
dxp
Цитата(jorikdima @ Feb 5 2010, 15:39) *
Как только шедулер решит, что ни один таск не готов, то включится опять IDLE и восстановится его контекст, вместе с CPUOFF, контроллер опять заснет. Я правильно понимаю все?

Вроде правильно. Но лучше попробовать. smile.gif Точнее, я даже пробовал (был один проект давно), но уже забыл. Точнее, не помню, чтобы были проблемы, все, вроде, работало, как задумывалось.

_BIC_SR_IRQ(LPM3_bits) может потребоваться вызывать там, где хочется все-таки перевести спящий в IdleProcess процессор в активное состояние.
Dr.NoA
Цитата(jorikdima @ Feb 5 2010, 12:39) *
Я вообще рассуждал, что единственное, что требуется, это написать одну строчку в OS::IdleProcessUserHook() , а именно _BIS_SR(LPM3_bits).

Дело было давно и я уже не помню деталей, но, кажется, что с _BIS_SR(LPM3_bits) и _BIC_SR(LPM3_bits) все не так просто как вы описали. Но даже если и так, что все равно остается вопрос, например, с включением/отключением высокочастотного кварца или какой-то другой периферии для минимизации потребления.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.