реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Sleep mode и внешние прерывания, sam3s
xelax
сообщение Jul 4 2012, 15:12
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035



Всем здравствуйте ))

Столкнулся с проблемой. Курил доки на mcu, искал в инете, но ответа на свой вопрос не смог найти.
Суть собственно вот в чем:
Есть желание во время простоя микроконтроллера переводить его в sleep mode, что собственно получается успешно делать. Также на плате есть чип, который может сгенерировать внешнее для mcu прерывание в любой момент времени. То есть оно может случиться например в момент выполнения процедуры ухода в сон.
Код
void IdleMode(void)
{
  SCB->SCR &= ~SCR_SLEEPDEEP;
  
  //  например прерывание происходит вот здесь

  PMC->PMC_FSMR &= ~PMC_FSMR_LPM;
  __WFE();
}

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

Например я знаю как такая ситуация обходится в avr. Там разрешают прерывания sei перед инструкцией sleep, а согласно доке на ядро, следующая инструкция после sei выполнится гарантированно.

Есть ли здесь подобные механизмы? Кто-нибудь сталкивался такой проблемой и как обходил её?
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Jul 4 2012, 15:48
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(xelax @ Jul 4 2012, 18:12) *
Есть ли здесь подобные механизмы? Кто-нибудь сталкивался такой проблемой и как обходил её?

Вот такой пример попадался (Cortex-M3).
CODE
volatile bool lfrcoReady = false
void CMU_IRQHandler(void)
{
/* Clear interrupt flag */
CMU_IntClear(CMU_IF_LFRCORDY);

/* Indicate that LFRCO is ready */
lfrcoReady = true;
}


/***************************************************************************//**
* @brief Main function. Enables LFRCO and waits in EM1 until it is ready
******************************************************************************/
int main(void)
{
/* Chip revision alignment and errata fixes */
CHIP_Init();

/* Enable CMU IRQ when LFRCO is ready */
CMU_IntEnable(CMU_IF_LFRCORDY);

/* Enable CMU interrupt vector in NVIC */
NVIC_EnableIRQ(CMU_IRQn);

/* Enable LFRCO but do not wait until it is ready */
CMU_OscillatorEnable(cmuOsc_LFRCO, true, false);

/* Wait in EM1 until LFRCO is ready.
* Disable interrupts first to avoid interrupt executing between lfrcoReady
* check and _WFI(); This would have caused the program to get stuck! */
__disable_irq();
while(!lfrcoReady)
{
__WFI(); /* Pending and enabled IRQs will wake up the CPU, but not go to ISR */
__enable_irq(); /* ISR for any pending and enabled IRQs will be executed after this */
}

/* Wait here at the end */
while(1);
}

Тут правда не внешние прерывания, а прерывание по готовности осцилятора, но разница невелика.

Сообщение отредактировал IgorKossak - Jul 4 2012, 16:48
Причина редактирования: [codebox] для длинного кода!!!
Go to the top of the page
 
+Quote Post
xelax
сообщение Jul 5 2012, 06:32
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035



Что-то я не совсем понимаю. Мы запрещая прерывания, запрещаем контроллеру прыгать на их обработчики, но при это даже в запрещенном сотоянии это прерывание способно пробудить микроконтроллер?
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Jul 5 2012, 07:09
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(xelax @ Jul 5 2012, 09:32) *
Что-то я не совсем понимаю. Мы запрещая прерывания, запрещаем контроллеру прыгать на их обработчики, но при это даже в запрещенном сотоянии это прерывание способно пробудить микроконтроллер?

Так получается.
Попробуйте.
Go to the top of the page
 
+Quote Post
xelax
сообщение Jul 5 2012, 09:28
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035



Метод проб и ошибок конечно тоже вариант, но вот я к стати вроде как нашел теоретическое подтверждение такому поведению.

Книжка называется "The definitive guide to the arm cortex-M3" second edition by Joseph Yiu

На 234 странице приведено "The rules of waking the Cortex-M3 processor from sleep modes"

Код
Table 14.2 WFI and WFE Wakeup Behavior
WFI Behavior                                       Wake Up               IRQ Execution
IRQ with BASEPRI
IRQ priority > BASEPRIv                            Y                           Y
IRQ priority =< BASEPRI                           N                          N
IRQ with BASEPRI and PRIMASK
IRQ priority > BASEPRI                              Y                           N
IRQ priority =< BASEPRI                            N                          N
WFE Behavior
IRQ with BASEPRI, SEVONPEND = 0
IRQ priority > BASEPRI                               Y                           Y
IRQ priority =< BASEPRI                             N                           N
IRQ with BASEPRI, SEVONPEND = 1
IRQ priority > BASEPRI                               Y                           Y
IRQ priority =< BASEPRI                             Y                           N
IRQ with BASEPRI and PRIMASK, SEVONPEND = 0
IRQ priority > BASEPRI                               N                           N
IRQ priority =< BASEPRI                             N                           N
IRQ with BASEPRI & PRIMASK, SEVONPEND = 1
IRQ priority > BASEPRI                                Y                          N
IRQ priority =< BASEPRI                              Y                          N


То есть запрещая прерывание через cpsid i, мы устанавливаем PRIMASK, то есть попадаем в вариант 3, когда все прерывания приоритета выше чем BASEPRI будут будить ядро ноне будут инициировать прыжка на вектор. Но это только если уснуть через WFI. При засыпании через WFE эффекта не будет никакого, только если предварительно event не сгенерируется.

Спасибо за то что идею подсказали, а то бы я долго лопатил все эти доки пока не наткнулся бы на эту таблицу.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Jul 5 2012, 09:39
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(xelax @ Jul 5 2012, 12:28) *
Метод проб и ошибок конечно тоже вариант, но вот я к стати вроде как нашел теоретическое подтверждение такому поведению.

Значит можно пользоваться.
P.S. Нашёл откуда исходник "моего" примера:AppNota - это не sam3, но тоже Cortex-M3, поэтому в основном одинаково будет.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Oct 23 2013, 09:42
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Вопрос : Правильно ли я понимаю смысл бита SLEEPONEXIT ? Когда бит стоит и команда WFI стоит внутри прерывания, процессор сначала выходит из прерывания, а уже потом засыпает. А если бит сброшен, то процессор засыпает сразу после команды WFI , даже если он внутри прерывания.


Sleep-now: if the SLEEPONEXIT bit is cleared, the MCU enters Sleep mode as soon
as WFI or WFE instruction is executed.
Sleep-on-exit: if the SLEEPONEXIT bit is set, the MCU enters Sleep mode as soon as
it exits the lowest priority ISR.


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 03:07
Рейтинг@Mail.ru


Страница сгенерированна за 0.02378 секунд с 7
ELECTRONIX ©2004-2016