• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Deep-Sleep и Sleep режимы в RTL серии “A”.

pvvx

Активный участник сообщества
В SDK имеем более пяти методов для обеспечения экономии энергии.

Сам чип имеет 3 аппаратных расширенных конфигурации для разных режимов – work, sleep и dsleep.

Испытания и сравнения произведем на SDK4.0, модуле RTL00 (RTL8710AF) c частотой 83MHz.

Для начала посмотрим, что предлагается пользователю в качестве драйвера PMU в wakelock.

После старта имеем потребление примерно до 13 мА, включение release_wakelock(WAKELOCK_OS) или pmu_release_wakelock(PMU_OS) понижает его до средних к 1.2 мА с “просыпанием” на обработку всех событий:
atsp.gif
Ввод в RX LogUART при этом отключается. Он будет активирован при активности. Видим обработку прерывания таймера RTOS...


Теперь сравним со sleep без отключения внутреннего питания.
В данном режиме активация возможна по GPIO, IRQ (разным таймерам и от разных устройств).
[inline]HalDeinitLogUart();
sleep_ex_selective(wakeup_event, sleep_ms, clk_source_en, 0);
HalInitLogUart();
[/inline]
atdss.gif
Понижает ток потребления примерно на уровень до 1 мА (SPI Flash не переключена в режим sleep).


Ну и deep-sleep, как вариант отключения с полной перезагрузкой при просыпании, к примеру, по заданному уровню на PA_5:
[inline]standby_wakeup_event_add(STANDBY_WAKEUP_BY_PA5, 0, level);
deepstandby_ex();
[/inline]
atdsa.gif
Понижает ток потребления примерно на уровень до утечек схемы включения модуля. (на диаграмме рестарт производится с активацией WiFi и соединением в внешней AP).

Итого: в принципе, для пользовательских устройств с малым потреблением, ожидающих какое-то событие, типа нажатия кнопок, вполне достаточно использование переключения pmu wakelock. При этом уровень потребления будет не сильно отличаться от активации sleep режимов, но программно это реализуется сложнее и необходимо учитывать множество фактов... А в режимах работы с процедурами pmu думать не требуется, кроме как о их активации :)

Есть ещё множественные модификации sleep/dsleep с перезагрузкой прошивки и без. Флагов, как и аппаратных регистров в чипе для этого делу, очень много, а если ещё дописывать самим примеры, то вариантов уже не счесть... По этому, если есть вопросы или ещё чаго, то уточняем конкретику.
 
Последнее редактирование:

Pavel_x

New member
Есть ещё множественные модификации sleep/dsleep с перезагрузкой прошивки и без. Флагов, как и аппаратных регистров в чипе для этого делу, очень много, а если ещё дописывать самим примеры, то вариантов уже не счесть... По этому, если есть вопросы или ещё чаго, то уточняем конкретику.
А не подскажете как организовать dsleep без перезагрузки?
Мне требуется организовать RTC в режиме dsleep (с минимальным потреблением) и например, чтобы по нажатию кнопки MK просыпался, выполнял определенные задачи, и опять уходил в dsleep.
Я организовал RTC с использованием Gtimer, и объединил это с примером для ARDUINO "DeepSleepBasic",
но в данном примере, после выхода из DeepSleep МК сбрасывается, следовательно сбрасываются и переменные счетчика RTC. Используя пример "SleepBasic" всё работает, но потребление в таком режиме около 1,2mA ,
что слишком много для меня.
 

pvvx

Активный участник сообщества
Код:
//------------------------------------------------------------------------------
// Deep sleep PB_1
//------------------------------------------------------------------------------
LOCAL void fATDSB(int argc, char *argv[]) {
    uint32 sleep_ms = 7000;
    if (argc > 1)
        sleep_ms = atoi(argv[1]);
    printf("%u ms waiting low level on PB_1 before launching Deep-Sleep...\n",
            sleep_ms);
    // turn off log uart
    HalDeinitLogUart(); // sys_log_uart_off();

    // initialize wakeup pin
    gpio_t gpio_wake;
    gpio_init(&gpio_wake, PB_1);
    gpio_dir(&gpio_wake, PIN_INPUT);
    gpio_mode(&gpio_wake, PullDown);
    TickType_t sttime = xTaskGetTickCount();

    do {
        if (gpio_read(&gpio_wake) == 0) {
            // Enter deep sleep... Wait give rising edge at PB_1 to wakeup system.
            deepsleep_ex(DSLEEP_WAKEUP_BY_GPIO, 0); // 0 mA
        };
        vTaskDelay(1);
    } while (xTaskGetTickCount() - sttime < sleep_ms);
    HalInitLogUart(); // sys_log_uart_on();
    printf("No set pin low in deep sleep!\n");
}
 

Pavel_x

New member
@pvvx Большое спасибо за пример, но я пробую в среде ARDUINO.
Я конечно добавил функцию deepsleep_ex(DSLEEP_WAKEUP_BY_GPIO, 0)
в библиотеку, но при пробуждении по PB1 всё равно происходит перезагрузка модуля,
т.е он стартует с вектора сброса, а не с того места где остановилась программа после входа в DSLEEP.
Так-же не совсем разобрался как в ARDUINO при таком режиме организовать таймер RTC?
 

pvvx

Активный участник сообщества
но при пробуждении по PB1 всё равно происходит перезагрузка модуля
Вы же писали что хотите Deep_sleep. А это всегда связано с перезагрузкой.
Другие sleep режимы не очень развиты у серии "A" RTL и кушают к пару mA.
В SDK от Ameba не дописан и режим почти аналогичный deep_sleep с отключением всего, кроме питания на SRAM. Ветка в и старт из этого режима в ROM есть, в загрузчике boot есть 4-ре указателя для старта из него. В нем можно не перезагружать коды из Flash в SRAM, но Arduino для этого не приспособлена, т.к. надо менять многое там...
Я тоже для него не писал готовых для выкладывания примеров.
Частичная и старая инфа про это тут:
https://esp8266.ru/forum/threads/rtl8710af-zagruzchik-v-rom-bios.1602/
Описываемый режим deep_sleep "без полной перезагрузки, со стартом в SRAM" включается так:
SleepPwrGatted(sleep_tik); // перезагрука через RamWakeupFun

При этом используется:
PRAM_FUNCTION_START_TABLE pRamStartFun = (PRAM_FUNCTION_START_TABLE) __ram_start_table_start__;
pRamStartFun->RamWakeupFun = new_start;
И далее вам надо правильно восстановить все CLK (на всякие UART, Flash и т.д.) и учесть отличие стартовой частоты задаваемой в ROM для RTL8710AF...

Остальные sleep в RTL серии "A", после вызова имеющихся в SDK функций вода в них, продолжают работу далее, в коде после этого вызова. Но там не отключаются многие клоки и потребление в sleep не падает ниже 1 mA.
Если нужно что-то менее "жручие" в разных sleep, то используйте серию "B" RTL. Там достаточно развитый PMU и получите средние потребление не более 200 мкА в требуемой вашей задаче, с активацией и счетам по пинам, включая активное время работы CPU на 125 МГц (для счета и поддержки RTOS).
 
Последнее редактирование:

Pavel_x

New member
Вы же писали что хотите Deep_sleep. А это всегда связано с перезагрузкой.
В принципе Deep_sleep с перезагрузкой меня бы тоже устроил, но мне нужно организовать часы реального времени и чтобы в режиме Deep_sleep они шли. В ARDUINO я так и не смог разобраться как это реализовать, т.к после перезагрузки все переменные сбрасываются. Не могли бы Вы подсказать как это сделать?
В других sleep режимах у меня получилось, но потребление в mA меня не устроило.
 

pvvx

Активный участник сообщества
В принципе Deep_sleep с перезагрузкой меня бы тоже устроил, но мне нужно организовать часы реального времени и чтобы в режиме Deep_sleep они шли. В ARDUINO я так и не смог разобраться как это реализовать, т.к после перезагрузки все переменные сбрасываются. Не могли бы Вы подсказать как это сделать?
В других sleep режимах у меня получилось, но потребление в mA меня не устроило.
Оставляйте активным таймер с RC (и активным событием при его переполнении) и при перезагрузке в SRAM (указанному выше) считывайте его значение. Всё это в Arduino сделать сложно, т.к. её концепция не имеет и не предполагает методов восстановления "прерванных" процессов, без полного переписывания SDK в части процедур инициализации и дополнений RTOS... Видимо, по этим причинам и малым ресурсам самого чипа по RAM, писатели Ameba и бросили эту ветку sleep "в начальной стадии" (оставив часть каких-то процедур чисто для примера, что оно есть ...).
 

Pavel_x

New member
Оставляйте активным таймер с RC (и активным событием при его переполнении) и при перезагрузке в SRAM (указанному выше) считывайте его значение.
Но ведь RC не обеспечивает достаточную точность хода, нельзя ли тоже самое сделать при тактировании от кварца.
На счет ARDUINO я понял, что нужно перейти на Eclipse и SDK, тогда реализовать подобный пример с использованием тактирования от кварца возможно?
Вот в ESP8266_Specifications увидел, что есть режим Deep sleep (RTC) с потреблением 60uA,
на RTL нет ничего подобного?
 

pvvx

Активный участник сообщества
Но ведь RC не обеспечивает достаточную точность хода, нельзя ли тоже самое сделать при тактировании от кварца.
На счет ARDUINO я понял, что нужно перейти на Eclipse и SDK, тогда реализовать подобный пример с использованием тактирования от кварца возможно?
Тактовый генератор от кварца на MHz-ы и жрет эти 1 mA.
Вот в ESP8266_Specifications увидел, что есть режим Deep sleep (RTC) с потреблением 60uA,
на RTL нет ничего подобного?
Оно и есть с рабочим от RC генератором для таймера якобы RTC. Но у ESP нет активации из deep_sleep по пинам.
Низкочастотный RC генератор нестабилен по температуре и напряжению питания. Перед входом в deep_sleep его калибруют к кварцевому генератору, что у ESP, что у RTL серии "A". На "B" серии есть возможность включения ext_32K (32768 Гц)...
При включенном кварце CPU с PLL у ESP8266 есть возможность только поставить CPU на команду типа Halt (ожидания прерываний) в которой он жрет достаточно много. У RTL можно отключить CPU, PLL, клоки и питание на выбранные потроха. У ESP8266 можно отключить только блок WiFi и некоторые CLK на другие потроха, но и этого нет в Arduino и даже описания бит в регистрах, кроме моих ковыряний :) ... Вход подпитки RTC у ESP8266 с браком, но можно кое как задействовать (Потребление по питанию часов (по ноге RTC_VDD)). У серии "B" в PMU предусмотрено даже отключение питания на раздельные сегменты SRAM, для минимизации статических утечек уровней uA и сделан специальный блок в несколько байт со своим питанием именно для сохранения флагов перезапука в режимах типа deep_sleep...
Как это всё вы представляете использовать в Arduino, если примеры в SDK и готовый HAL на RTL используют только половину возможностей чипа? :)
На все случаи примеров даже не описать...
 
Последнее редактирование:

Pavel_x

New member
Как это всё вы представляете использовать в Arduino, если примеры в SDK и готовый HAL на RTL используют только половину возможностей чипа?
@pvvx, большое спасибо за разъяснения!
В Ардуино я не собираюсь всё это использовать, пора слезать с него.
Просто попробовал несколько примеров в Ардуино, для быстрой реализации.
 

Pavel_x

New member
Оно и есть с рабочим от RC генератором для таймера якобы RTC. Но у ESP нет активации из deep_sleep по пинам.
Низкочастотный RC генератор нестабилен по температуре и напряжению питания. Перед входом в deep_sleep его калибруют к кварцевому генератору, что у ESP, что у RTL серии "A"
@pvvx, извините за назойливость, а вас не имеется случайно примера на "си" с RC генератором, с последующей его
калибровкой и вход в режим deep_sleep, чтобы RTC осуществлял счет в этом режиме.
Если есть что-то подобное, я бы попробовал скомпилировать данный код в Eclipse.
Заранее спасибо.
 

pvvx

Активный участник сообщества
примера на "си" с RC генератором, с последующей его
калибровкой и вход в режим deep_sleep, чтобы RTC осуществлял счет в этом режиме.
Если есть что-то подобное, я бы попробовал скомпилировать данный код в Eclipse.
Примеров нет, т.к. это всего пару команд для серии "A":
Код:
VOID HalLogUartWaitTxFifoEmpty(VOID) {
    int x = 16384;
    while((!(HAL_READ8(LOG_UART_REG_BASE, 0x14) & BIT6)) && x--);
}
....
    uint32 sleep_ms = 5000; // Предел 8355 ms!
    printf("Sleep Timer %u tik\n", sleep_ms);
    HalLogUartWaitTxFifoEmpty();
    DSleep_Timer(sleep_ms);
И общие для DeepSleep c просыпанием по таймеру или GPIO:
Код:
VOID DeepSleep(IN  u8  Option,  IN  u32 SDuration)
или
/**
  * @brief  To make the system entering the Deep Sleep power saving mode.
  *         The CPU, memory and peripheral power is off when entering
  *         deep sleep power saving mode. The program needs to be reload
  *         and all peripheral needs be re-configure when system resume.
  *
  * @param  wakeup_event: A bit map of wake up event. Available event:
  *                         DSLEEP_WAKEUP_BY_TIMER
  *                         DSLEEP_WAKEUP_BY_GPIO
  *         sleep_duration: the system sleep duration in ms, only valid
  *         for DSLEEP_WAKEUP_BY_TIMER wake up event.
  *
  * @retval None
  */
void deepsleep_ex(uint32_t wakeup_event, uint32_t sleep_duration)
Когда вы даете команду DSleep_Timer(SDuration) или DeepSleep...(), то калибровка RC таймера производится в ней автоматически - Calibration A33 CLK
 
Сверху Снизу