Цитата(SasaVitebsk @ Feb 11 2016, 13:29)

Например. Спим в LPM3.5. Приходит прерывание от RTC, обрабатывается и, например раз в сутки надо замерить текущую температуру.
Для этого надо выйти из прерывания со сбросом режима сна подать питание на датчик температуры, зарядить таймаут на таймер 0 и заснуть уже в режиме LPM3.
Если у Вас МК вошёл в ISR, то естественно он уже не режиме сна, а в run-mode находится. Как это может быть непонятно??
Как всегда - у вопрошающего каша в голове...
И по выходу из ISR, можно вернуться в сон или продолжить выполнение фонового процесса с инструкции, следующей после той инструкции, что погрузила в сон.
Т.е. - именно инструкция выхода из прерывания, загружает значение в статусный регистр МК, содержащий биты сна.
Атомарный вход в сон:
Код
__bic_SR_register(GIE);
if (!(mainFL & (1 << MAIN_F_TASK_MEASURE | 1 << MAIN_F_TASK_RX)))
if (keyboard == KBD_NONE) {
mainFL |= 1 << MAIN_F_SLEEP;
__bis_SR_register(LPM3 | GIE);
__bic_SR_register(GIE);
}
mainFL &= ~(1 << MAIN_F_SLEEP);
__bis_SR_register(GIE);
В
mainFL содержатся флаги-требования обработки некоторых событий (MAIN_F_TASK_RX, MAIN_F_TASK_MEASURE). Эти флаги выставляются в ISR-ах (которые могут срабатывать в режимах сна, пробуждая МК, или в run-mode, если уже идёт какая-то обработка одного из событий).
После этого участка идёт код проверяющий эти флаги и обслуживающий их.
Есть также флаг MAIN_F_SLEEP - по нему ISR-ы определяют из какого режима они вызвались (если им это нужно).
Цитата(SasaVitebsk @ Feb 11 2016, 17:04)

То есть получается в голове совсем проги не должно быть. Как у них в примерах.
Неправильно. Основную обработку лучше располагать в фоновом процессе.
Активация фонового процесса: срабатывает ISR, выставляет флаг в переменной запросов сервисов фонового процесса, выходит из ISR в run-mode.
Фоновый процесс построен в виде большого цикла - просматривает поочередно флаги в переменной запросов, если какой-то установлен - сбрасывает его и выполняет сервис, дальше - опять анализ переменной запросов.
Если переменная запросов ==0 - вход в сон.
Весь цикл:
Код
enum {MAIN_F_SLEEP, MAIN_F_TASK_MEASURE, MAIN_F_TASK_RX, ...};
while (1) {
__bic_SR_register(GIE);
if (!(mainFL & (1 << MAIN_F_TASK_MEASURE | 1 << MAIN_F_TASK_RX | ...))) {
mainFL |= 1 << MAIN_F_SLEEP;
__bis_SR_register(LPM3 | GIE);
__bic_SR_register(GIE);
}
mainFL &= ~(1 << MAIN_F_SLEEP);
__bis_SR_register(GIE);
do {
if (mainFL & 1 << MAIN_F_TASK_MEASURE) {
__bic_SR_register(GIE);
mainFL &= ~(1 << MAIN_F_TASK_MEASURE);
__bis_SR_register(GIE);
... //сервис MAIN_F_TASK_MEASURE
}
if (mainFL & 1 << MAIN_F_TASK_RX) {
__bic_SR_register(GIE);
mainFL &= ~(1 << MAIN_F_TASK_RX);
__bis_SR_register(GIE);
... //сервис MAIN_F_TASK_RX
}
... //другие сервисы
} while (mainFL & (1 << MAIN_F_TASK_MEASURE | 1 << MAIN_F_TASK_RX | ...));
}
В принципе, возможно запреты прерываний при модификации флагов
mainFL возможно излишни, так как IAR эти операции генерит в виде одной инструкции чтения-модификации-записи (которая атомарна, как я понимаю, для контроллера прерываний).