Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Заставить MSP430 спать все свободное время
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > scmRTOS
aliko
Добрый день.
Вопрос собственно в заголовке. Надо чтобы контроллер MSP430F149 все свободное время спал. Достаточно ли будет написать так:
Код
void OS::IdleProcessUserHook()
{
    LPM0;
}

PS использую IAR
aliko
Наверное вопрос сочли слишком глупым чтобы на него отвечать... 05.gif
Все же господа хорошие, объясните пожалуйста новичку премудрости вытесняющего планирования. sm.gif

Я постараюсь более подробно изложить свои вопросы:

1) Я так понимаю IdleProcess такой же процесс как и все остальные. Разве что не надо его оборачивать в бесконечный цикл, так как это уже сделано в коде ОС. Значит если я усыплю МК в этом процессе то всякий раз возвращаясь в него планировщик будет восстанавливать SR, а значит впадать в спячку. Так ли это?

2) Если IdleProcess нужен лишь для усыпления контроллера, не слишком ли жирным будет выделять для таких целей отдельный процесс со своим стеком? Можно ли вообще отказаться от этого процесса? Как в таком случае реализовать спящий режим при простое МК?

3) Этот вопрос наверное уже больше завязан на конкретную среду IAR. В настройках проекта в среде IAR указывается величина выделяемого стека и кучи. Кто будет пользоваться этим стеком? Какие значения лучше указывать?

Заранее большое спасибо за помощь!
SSerge
Цитата(aliko @ Jun 21 2011, 17:46) *
1) Я так понимаю IdleProcess такой же процесс как и все остальные. Разве что не надо его оборачивать в бесконечный цикл, так как это уже сделано в коде ОС. Значит если я усыплю МК в этом процессе то всякий раз возвращаясь в него планировщик будет восстанавливать SR, а значит впадать в спячку. Так ли это?

Тут уже было обсуждение похожей темы: http://electronix.ru/forum/index.php?showt...=20811&st=0
пришли к такому же выводу.
Цитата
2) Если IdleProcess нужен лишь для усыпления контроллера, не слишком ли жирным будет выделять для таких целей отдельный процесс со своим стеком? Можно ли вообще отказаться от этого процесса? Как в таком случае реализовать спящий режим при простое МК?

Ну надо же что-то делать когда совсем нечего делать sm.gif
В принципе можно что-то и там делать, но далеко не что угодно, так как усыплять этот процесс нельзя. С другой стороны, накладные расходы на ещё один процесс минимальны.
Цитата
3) Этот вопрос наверное уже больше завязан на конкретную среду IAR. В настройках проекта в среде IAR указывается величина выделяемого стека и кучи. Кто будет пользоваться этим стеком? Какие значения лучше указывать?

А это зависит от дефайна scmRTOS_ISRW_TYPE
aliko
Цитата(SSerge @ Jun 21 2011, 16:26) *
Тут уже было обсуждение похожей темы: http://electronix.ru/forum/index.php?showt...=20811&st=0
пришли к такому же выводу.

Большое спасибо за эту ссылку, я рад что оказался не одинок в своих поисках решения)

Цитата(SSerge @ Jun 21 2011, 16:26) *
Ну надо же что-то делать когда совсем нечего делать sm.gif
В принципе можно что-то и там делать, но далеко не что угодно, так как усыплять этот процесс нельзя. С другой стороны, накладные расходы на ещё один процесс минимальны.

Ну вобщем-то делать мне там совершенно нечего и хотелось бы сэкономить побольше оперативки так что держать отдельный IdleProcess со своим стеком и постоянно переключать на него контекст лишь для того чтобы в нем спать несколько накладно...

Цитата(SSerge @ Jun 21 2011, 16:26) *
А это зависит от дефайна scmRTOS_ISRW_TYPE

значение этого дефайна выставил в TISRW. Правильно ли я понимаю что теперь стек выделяемый IAR (тот что задается в конфигурации проекта) будет использоваться прерываниями?
dxp
Цитата(aliko @ Jun 22 2011, 15:11) *
Ну вобщем-то делать мне там совершенно нечего и хотелось бы сэкономить побольше оперативки так что держать отдельный IdleProcess со своим стеком и постоянно переключать на него контекст лишь для того чтобы в нем спать несколько накладно...

Что вы предлагаете делать, когда все ваши процессы упали в ожидание и отдали управление? Куда оно должно пойти?

Цитата(aliko @ Jun 22 2011, 15:11) *
значение этого дефайна выставил в TISRW. Правильно ли я понимаю что теперь стек выделяемый IAR (тот что задается в конфигурации проекта) будет использоваться прерываниями?

Нет. Этот стек используется для стека прерываний только при схеме с включенным отдельным стеком прерываний (TISRW_SS), но использовать его на MSP430 очень не рекомендуется. Т.ч. оставьте как есть.

P.S. У вас проблемы с объёмом памяти, что вы так упорно хотите её сэкономить?

aliko
Цитата
Что вы предлагаете делать, когда все ваши процессы упали в ожидание и отдали управление? Куда оно должно пойти?

Ну в общем-то когда ресурсы МК никому не нужны, МК должен спать. Сейчас это реализовано вызовом LPM0 в IdleProcess. Однако что-то мне говорит что должно быть более красивое решение чем тратить отдельный процесс со своим стеком и регулярным переключением контекста на него для того чтобы в нем просто спать.
Цитата
Нет. Этот стек используется для стека прерываний только при схеме с включенным отдельным стеком прерываний (TISRW_SS), но использовать его на MSP430 очень не рекомендуется. Т.ч. оставьте как есть.

Не совсем понятно... Каждый процесс имеет свой стек, IdleProcess также имеет свой стек. В какой стек кладут данные тогда прерывания? В стек IdleProcess-a? И кто пользуется тогда стеком по-умолчанию размер которого задается в настройках ИАР? Я наверное задаю не самые умные вопросы, так что сильно не пинайте, хочу понять как че же это все работает...

Цитата
P.S. У вас проблемы с объёмом памяти, что вы так упорно хотите её сэкономить?

Если уложусь в 1 Кб смогу использовать более дешевый и доступный МК. Более того всегда есть куда с пользой потратить свободную память - на буферы для более быстрого обмена по UART и на структуры данных с диагностикой... Да и вообще надо же во всем до конца разобраться иначе как же выпускать продукт не понимая во всех деталях как он работает....
zltigo
QUOTE (aliko @ Jun 22 2011, 11:11) *
IdleProcess со своим стеком и постоянно переключать на него контекст лишь для того чтобы в нем спать несколько накладно...

Ну зачем это только для... Считайте, что это самый низкоприоритетный процесс, который по завершению того, что ему положено переводит не процесс а контроллер в спячку.
Единственно, что время спячки Вы для него задать не сможете. Ну и если вдруг, будут нужны какие-то системные вызовы, то придется сделать их варианты для Idle.
Вот примерчик более утилитарного использования Idle (операционка похожая на FreeRTOS и ARM, но не суть важно):
CODE
/
void idle_system( void )
{
.........

    if( xQueueReceiveFromIdle( idle_queue, &imsg ) )
    {    
.......
    }
    else
    {    // CPU Idle
        PCON |= PCON_IDL;
    }
}
MrYuran
Цитата(aliko @ Jun 22 2011, 16:02) *
Если уложусь в 1 Кб смогу использовать более дешевый и доступный МК.

Более дешёвый и доступный, чем 149, трудно найти.
Разве что 135, но там памяти всего 512.
И упихивать под завязку - в корне неправильно. Всегда надо иметь хотя бы 30% запас на будущее.
Чтобы не было мучительно больно ©
dxp
Цитата(aliko @ Jun 22 2011, 19:02) *
Ну в общем-то когда ресурсы МК никому не нужны, МК должен спать. Сейчас это реализовано вызовом LPM0 в IdleProcess. Однако что-то мне говорит что должно быть более красивое решение чем тратить отдельный процесс со своим стеком и регулярным переключением контекста на него для того чтобы в нем просто спать.

Мне было бы тоже очень интересно узнать про такую реализацию. Предлагайте?

Цитата(aliko @ Jun 22 2011, 19:02) *
Не совсем понятно... Каждый процесс имеет свой стек, IdleProcess также имеет свой стек. В какой стек кладут данные тогда прерывания? В стек IdleProcess-a? И кто пользуется тогда стеком по-умолчанию размер которого задается в настройках ИАР? Я наверное задаю не самые умные вопросы, так что сильно не пинайте, хочу понять как че же это все работает...

Прерывания работают в стеке прерванного процесса, если при переходе к обработчику прерываний не происходит переключения на специальный стек прерываний, это очевидно. Вообще-то, этот момент достаточно подробно рассмотрен в документации.
aliko
Цитата
Мне было бы тоже очень интересно узнать про такую реализацию. Предлагайте?

Пока что придумал лишь такой вариант: Перенести функционал одного из процессов (самого низкоприоритетного) в IdleProcess. Но тут возникают сложности с отсутствием всех плюшек которые есть у обычного процесса - это возможность вызывать sleep() а также прочие варианты передачи управления и работы с разделяемыми ресурсами. Я так понимаю это все не будет работать в Idle.
Также опять же вопрос спячки контроллера еще более усложняется. Представим что я выполнил цикл подпрограмм в IdleProcess после которого надо уснуть на какое-то время. Я вызываю LPM0 и засыпаю. Кто же меня теперь разбудит??? Планировщик восстанавливая контекст IdleProcess всякий раз будет восстанавливать SR и сразу засыпать. Получается кто-то извне должен залезть в стек процесса IdleProcess и в его стеке исправить значение SR. Как-то все слишком сложно выходит...(

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

В том-то и дело. У каждого процесса свой стек и у IdleProcess тоже свой. Кто же пользуется стеком по-умолчанию (тот размер которого задается в настройках проекта ИАР в General Options). Получается им пользуется только все то что идет до вызова os_start? Выходит если я все правильно понимаю его можно сделать минимальным, так как из os_start мы никогда уже не выйдем?

Цитата(MrYuran @ Jun 22 2011, 16:33) *
Более дешёвый и доступный, чем 149, трудно найти.
Разве что 135, но там памяти всего 512.
И упихивать под завязку - в корне неправильно. Всегда надо иметь хотя бы 30% запас на будущее.
Чтобы не было мучительно больно ©

Прошу прощения, я хотел сказать уложиться в 2 Кб. Да и вообще неприятно когда несколько десятков байт, а то и сотни тратятся впустую. Ведь если даже спать в Idle всеравно нужно выделить ему стек для всех регистров + под прерывания оставить не забыть...
dxp
Цитата(aliko @ Jun 22 2011, 20:19) *
Как-то все слишком сложно выходит...(

В том-то и дело, что не всё там так просто и за всё надо платить.

Цитата(aliko @ Jun 22 2011, 20:19) *
В том-то и дело. У каждого процесса свой стек и у IdleProcess тоже свой. Кто же пользуется стеком по-умолчанию (тот размер которого задается в настройках проекта ИАР в General Options). Получается им пользуется только все то что идет до вызова os_start? Выходит если я все правильно понимаю его можно сделать минимальным, так как из os_start мы никогда уже не выйдем?

Когда-то был вариант (ещё в версиях 2.хх), когда системный стек использовался в качестве стека IdleProcess, но потом от этого отказались по какой-то причине, уже не помню. Вроде, гемора много, а толку мало.

Если вам так надо эту память, но и юзайте её под свои нужды - размещайте в ней переменные, буфера или что хотите. sm.gif
MrYuran
Ещё вопрос на засыпку: а оно обязательно, вытесняющее планирование?
Как-то у меня в голове энергосбережение и постоянный запуск планировщика вместе не вяжутся...
aliko
Цитата
Ещё вопрос на засыпку: а оно обязательно, вытесняющее планирование?
Как-то у меня в голове энергосбережение и постоянный запуск планировщика вместе не вяжутся...

Наверное вы правы для случая работы от батарейки. В моем же случае есть хоть и очень маленькое но постоянное питание, так что вполне можно себе позволить переключение контекста, тем более занимает оно < 50 мкс...
dxp
Цитата(MrYuran @ Jun 22 2011, 20:45) *
Ещё вопрос на засыпку: а оно обязательно, вытесняющее планирование?
Как-то у меня в голове энергосбережение и постоянный запуск планировщика вместе не вяжутся...

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

А без этого придётся заниматься поллингом тех или иных событий с каким-то периодом - это и есть непроизводительный расход энергии. Можно и без оси делать всё по событиям, но тут придётся всю обработку городить в обработчиках прерываний, а это не очень-то красиво и функционально, и всё равно похоже на работу ос с event-driven управлением, особенно, если контроллер прерываний многоуровневый приоритетный.
zltigo
QUOTE (dxp @ Jun 22 2011, 17:55) *
Как раз-таки очень вяжется - когда все процессы работу сделали и ждут своих событий, то процессор спокойно падает в спячку, из....

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


QUOTE (dxp @ Jun 22 2011, 17:55) *
Можно и без оси делать всё по событиям, но тут придётся всю обработку городить в обработчиках прерываний...

Однажды, выжимая все и вся пришлось sm.gif написать такой вот:
CODE
__noreturn void main(void)
{
      for(;; )
        __sleep();
}

dxp
Цитата(zltigo @ Jun 23 2011, 00:37) *
Я думаю, что тут народ волнуется о том, что системный таймер будет периодически будить и система будет считать время, даже если кто-то захочет поспать интервал времени много превышающий тик системного таймера.

Ну, дык, заблокировать и его, ежели он не нужен и мешает.


Цитата(zltigo @ Jun 23 2011, 00:37) *
Однажды, выжимая все и вся пришлось sm.gif написать такой вот:
Код
__noreturn void main(void)
{
      for(;; )
        __sleep();
}

biggrin.gif
zltigo
QUOTE (dxp @ Jun 23 2011, 05:56) *
Ну, дык, заблокировать и его, ежели он не нужен и мешает.

Это понятно, когда будить можно по внешнему событию, но кому тогда сказать разбудить, например, через сутки sm.gif? Придется делать нечто софтовое или аппаратное позволяющее формировать большие временные интервалы с минимальными затратами энергии.




MrYuran
Цитата(zltigo @ Jun 23 2011, 14:42) *
Это понятно, когда будить можно по внешнему событию, но кому тогда сказать разбудить, например, через сутки sm.gif? Придется делать нечто софтовое или аппаратное позволяющее формировать большие временные интервалы с минимальными затратами энергии.

А динамически период системного тика нельзя менять?
zltigo
QUOTE (MrYuran @ Jun 23 2011, 13:46) *
А динамически период системного тика нельзя менять?

Естественно можно, еще можно его обработчик (если формируемого интервала не хватит) на максимально короткий на время сна заменить. Это то, что я имел ввиду под софтовым решением. Можно добавить RTC c будильником и к режимам сна подвязать....
jorikdima
Приветствую.
Не буду создавать отдельную тему, тут напишу. Читал обе темы про слип режим в контексте МСП430 и даже вроде поучаствовал как-то, но появился новый ракурс проблемы.
Все понятно если тип слип режима один, например LPM0. Но что делать, если в зависимости от ситуации тип режима должен меняться?
Например, мой случай. Прибор работает условно в двух режимах, покоя и работы. В покое прибор ничего не делает, просто ждет нажатия кнопки. Его задача потреблять как можно меньше. В режиме работы есть обмен по УАРТ, запись на СД карту и пр. дела, в перерывах между которыми неплохо бы поспать.
Однако, реализовать сон можно тут по-разному. В первом случае можно делать LPM3, и тактироваться от часового кварца. Для периодического опроса кнопки 32 кГц хватит, а периферия не нужна. В режиме работы LPM3 не годится ибо нельзя снимать клоки с УАРТ и пр. поэтому только LPM0.
Проблема вот в чем. Просто поставить if в зависимости от режима в IdleProcessUserHook нельзя. Ведь в каждой из задач ОС при восстановлении контекста восстанавливается и статусный регистр, а в нем информация о работе/не работе FLL. Соответственно при смене режима с покоя на рабочий и включив FLL сей факт запишется только в статусный регистр контекста текущего процесса, а в другие процессы как??? Хакерскими способами не очень хорошо. Кто-нибудь сталкивался с подобной проблемой? Как решали?
Спасибо.
MrYuran
Цитата(jorikdima @ Jun 26 2011, 21:50) *
В покое прибор ничего не делает, просто ждет нажатия кнопки. Его задача потреблять как можно меньше.

Тогда можно загнать в LPM4, а нажатие любой кнопки перенаправить на RST, с последующим запуском рабочего режима (естественно, обработчик вектора сброса должен уметь отличать горячий запуск от холодного)
jorikdima
Цитата(MrYuran @ Jun 27 2011, 10:31) *
Тогда можно загнать в LPM4, а нажатие любой кнопки перенаправить на RST, с последующим запуском рабочего режима (естественно, обработчик вектора сброса должен уметь отличать горячий запуск от холодного)

Спасибо. Но хотелось бы менее хакерского способа sm.gif Ресет контроллера идеологически вещь, которая не должна использоваться для перехода из режима в режим.
jorikdima
Не появилось ни у кого идей по моему вопросу? sm.gif
dxp
Цитата(jorikdima @ Sep 12 2011, 23:17) *
Не появилось ни у кого идей по моему вопросу? sm.gif

Разослать широковещательное сообщение всем процессам о смене режима? И пусть они сами рулят своим статусным регистром.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.