Миро Самек "Использование режимов малого энергопотребления в простых программных архитектурах" (перевод)


AVR

AVR - малопотребляющий 8-разрядный RISC контроллер фирмы Atmel - также предоставляет возможность атомарного перехода в режим сна, хотя он и не столь очевиден, как в случае HC08 или MSP430. В AVR есть инструкция "SLEEP", которая останавливает тактирование ядра, но она не влияет на прерывания и поэтому должна выполняться уже после их разрешения. Это могло бы стать проблемой, если бы не следующее неприметное примечание в техническом описании [3]:

/" 4.7 Обработка режимов сброса и прерывания
<..>
Если для разрешения прерываний используется инструкция "SEI", то инструкция, следующая сразу за "SEI", будет выполнена до передачи управления ожидающим прерываниям, как показано в этом примера:

    SEI   ;     установить Global Interrupt Enable
    SLEEP ;     перейти в режим сна с ожиданием прерываний
          ;     примечание: переход произойдёт до передачи управления
          ;     ожидающим прерываниям
    ...   ;
				
"/

 

Другими словами, пара инструкций "SEI-SLEEP" будет выполняться атомарно, вероятнее всего, из-за конвейерной архитектуры AVR. Будьте внимательны и всегда используйте "SEI-SLEEP" только вместе, никогда не разбивая их какой-либо иной инструкцией.

В листинге 4 приведён пример, показывающий переход в режим сна из фонового цикла, для компилятора IAR AVR. В листинге 5 показан тот же пример для компилятора GNU AVR (WinAVR).

Листинг 4. Пример для компилятора IAR AVR показывает как переходить в режим сна из фонового цикла

    __disable_interrupt();          /*  __asm ("CLI");              */
    if (idle_condition()) {         /*  Состояние простоя ?         */
        SMCR=...;                   /*  Да: Проводим изменение режима тактирования  */
        __enable_interrupt();       /*  __asm ("SEI");              */
        __sleep();                  /*  __asm ("SLEEP");            */
    }
    else {
        __enable_interrupt();       /*  Нет: __asm ("SEI");         */
    }

				

 

Листинг 5. Пример для компилятора GNU AVR (WinAVR) показывает как переходить в режим сна из фонового цикла

    __asm__ __volatile__ ("CLI" "\n\t" ;; );
    if (idle_condition()) {         /*  Состояние простоя ?         */
                                    /*  Да: ..                      */
        SMCR=...;                   /*  .. Проводим изменение режима тактирования  */    
        __asm__ __volatile__ ("SEI" "\n\t" ;; );
        __asm__ __volatile__ ("SLEEP" "\n\t" ;; );
    }
    else {                          /*  Нет: ..                     */
                                    /*  .. разрешаем прерывания     */
        __asm__ __volatile__ ("SEI" "\n\t" ;; );
    }

				

 

ПредпросмотрAttachmentSize
low_power_modes_in_background.zip27.87 КБ