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

Заставить MSP430 спать все свободное время

Добрый день.

Вопрос собственно в заголовке. Надо чтобы контроллер MSP430F149 все свободное время спал. Достаточно ли будет написать так:

void OS::IdleProcessUserHook() 
{ 
    LPM0;
}

PS использую IAR

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


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

Наверное вопрос сочли слишком глупым чтобы на него отвечать... :05:

Все же господа хорошие, объясните пожалуйста новичку премудрости вытесняющего планирования. :)

 

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

 

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

 

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

 

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

 

Заранее большое спасибо за помощь!

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


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

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

Тут уже было обсуждение похожей темы: http://electronix.ru/forum/index.php?showt...=20811&st=0

пришли к такому же выводу.

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

Ну надо же что-то делать когда совсем нечего делать :)

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

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

А это зависит от дефайна scmRTOS_ISRW_TYPE

 

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


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

Тут уже было обсуждение похожей темы: http://electronix.ru/forum/index.php?showt...=20811&st=0

пришли к такому же выводу.

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

 

Ну надо же что-то делать когда совсем нечего делать :)

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

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

 

А это зависит от дефайна scmRTOS_ISRW_TYPE

значение этого дефайна выставил в TISRW. Правильно ли я понимаю что теперь стек выделяемый IAR (тот что задается в конфигурации проекта) будет использоваться прерываниями?

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


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

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

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

 

значение этого дефайна выставил в TISRW. Правильно ли я понимаю что теперь стек выделяемый IAR (тот что задается в конфигурации проекта) будет использоваться прерываниями?

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

 

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

 

 

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


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

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

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

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

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

 

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

Если уложусь в 1 Кб смогу использовать более дешевый и доступный МК. Более того всегда есть куда с пользой потратить свободную память - на буферы для более быстрого обмена по UART и на структуры данных с диагностикой... Да и вообще надо же во всем до конца разобраться иначе как же выпускать продукт не понимая во всех деталях как он работает....

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


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

IdleProcess со своим стеком и постоянно переключать на него контекст лишь для того чтобы в нем спать несколько накладно...

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

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

Вот примерчик более утилитарного использования Idle (операционка похожая на FreeRTOS и ARM, но не суть важно):

/
void idle_system( void )
{
.........

    if( xQueueReceiveFromIdle( idle_queue, &imsg ) )
    {    
.......
    }
    else
    {    // CPU Idle
        PCON |= PCON_IDL;
    }
}

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


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

Если уложусь в 1 Кб смогу использовать более дешевый и доступный МК.

Более дешёвый и доступный, чем 149, трудно найти.

Разве что 135, но там памяти всего 512.

И упихивать под завязку - в корне неправильно. Всегда надо иметь хотя бы 30% запас на будущее.

Чтобы не было мучительно больно ©

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


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

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

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

 

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

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

 

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


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

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

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

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

 

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

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

 

Более дешёвый и доступный, чем 149, трудно найти.

Разве что 135, но там памяти всего 512.

И упихивать под завязку - в корне неправильно. Всегда надо иметь хотя бы 30% запас на будущее.

Чтобы не было мучительно больно ©

Прошу прощения, я хотел сказать уложиться в 2 Кб. Да и вообще неприятно когда несколько десятков байт, а то и сотни тратятся впустую. Ведь если даже спать в Idle всеравно нужно выделить ему стек для всех регистров + под прерывания оставить не забыть...

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


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

Как-то все слишком сложно выходит...(

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

 

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

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

 

Если вам так надо эту память, но и юзайте её под свои нужды - размещайте в ней переменные, буфера или что хотите. :)

 

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


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

Ещё вопрос на засыпку: а оно обязательно, вытесняющее планирование?

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

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


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

Ещё вопрос на засыпку: а оно обязательно, вытесняющее планирование?

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

Наверное вы правы для случая работы от батарейки. В моем же случае есть хоть и очень маленькое но постоянное питание, так что вполне можно себе позволить переключение контекста, тем более занимает оно < 50 мкс...

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


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

Ещё вопрос на засыпку: а оно обязательно, вытесняющее планирование?

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

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

 

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

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


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

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

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

 

 

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

Однажды, выжимая все и вся пришлось :) написать такой вот:

__noreturn void main(void)
{
      for(;; )
        __sleep();
}

 

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


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

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

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

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

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

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

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

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

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

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