#define IROM_HIGH 0x40400000
#define DROM_LOW 0x3F400000
#define DROM_HIGH 0x3F800000
+#define RTC_IRAM_LOW 0x400C0000
+#define RTC_IRAM_HIGH 0x400C2000
+#define RTC_DATA_LOW 0x50000000
+#define RTC_DATA_HIGH 0x50002000
/*spi mode,saved in third byte in flash */
enum {
#include "rom/ets_sys.h"
#include "rom/spi_flash.h"
#include "rom/crc.h"
+#include "rom/rtc.h"
#include "soc/soc.h"
#include "soc/cpu.h"
uint32_t irom_load_addr = 0;
uint32_t irom_size = 0;
+ /* Reload the RTC memory sections whenever a non-deepsleep reset
+ is occuring */
+ bool load_rtc_memory = rtc_get_reset_reason(0) != DEEPSLEEP_RESET;
+
ESP_LOGD(TAG, "bin_header: %u %u %u %u %08x", image_header.magic,
- image_header.blocks,
- image_header.spi_mode,
- image_header.spi_size,
- (unsigned)image_header.entry_addr);
+ image_header.blocks,
+ image_header.spi_mode,
+ image_header.spi_size,
+ (unsigned)image_header.entry_addr);
for (uint32_t section_index = 0;
section_index < image_header.blocks;
map = true;
}
- ESP_LOGI(TAG, "section %d: paddr=0x%08x vaddr=0x%08x size=0x%05x (%6d) %s", section_index, pos, section_header.load_addr, section_header.data_len, section_header.data_len, (load)?"load":(map)?"map":"");
+ if(!load_rtc_memory && address >= RTC_IRAM_LOW && address < RTC_IRAM_HIGH) {
+ ESP_LOGD(TAG, "Skipping RTC code section at %08x\n", pos);
+ load = false;
+ }
+
+ if(!load_rtc_memory && address >= RTC_DATA_LOW && address < RTC_DATA_HIGH) {
+ ESP_LOGD(TAG, "Skipping RTC data section at %08x\n", pos);
+ load = false;
+ }
+
+ ESP_LOGI(TAG, "section %d: paddr=0x%08x vaddr=0x%08x size=0x%05x (%6d) %s", section_index, pos,
+ section_header.load_addr, section_header.data_len, section_header.data_len, (load)?"load":(map)?"map":"");
if (!load) {
pos += section_header.data_len;
#include "esp_spi_flash.h"
#include "esp_ipc.h"
#include "esp_log.h"
+#include "esp_deepsleep.h"
void start_cpu0(void) __attribute__((weak, alias("start_cpu0_default")));
void start_cpu0_default(void) IRAM_ATTR;
--- /dev/null
+/* Wake from deep sleep stub
+
+ See esp_deepsleep.h esp_wake_deep_sleep() comments for details.
+*/
+#include <stddef.h>
+#include <sys/lock.h>
+#include "rom/cache.h"
+#include "rom/rtc.h"
+#include "soc/rtc_cntl_reg.h"
+#include "esp_attr.h"
+#include "esp_deepsleep.h"
+
+/* Updating RTC_MEMORY_CRC_REG register via set_rtc_memory_crc()
+ is not thread-safe. */
+static _lock_t lock_rtc_memory_crc;
+
+esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void)
+{
+ _lock_acquire(&lock_rtc_memory_crc);
+ uint32_t stored_crc = REG_READ(RTC_MEMORY_CRC_REG);
+ set_rtc_memory_crc();
+ uint32_t calc_crc = REG_READ(RTC_MEMORY_CRC_REG);
+ REG_WRITE(RTC_MEMORY_CRC_REG, stored_crc);
+ _lock_release(&lock_rtc_memory_crc);
+
+ if(stored_crc == calc_crc) {
+ return (esp_deep_sleep_wake_stub_fn_t)REG_READ(RTC_ENTRY_ADDR_REG);
+ } else {
+ return NULL;
+ }
+}
+
+void esp_set_deep_sleep_wake_stub(esp_deep_sleep_wake_stub_fn_t new_stub)
+{
+ _lock_acquire(&lock_rtc_memory_crc);
+ REG_WRITE(RTC_ENTRY_ADDR_REG, (uint32_t)new_stub);
+ set_rtc_memory_crc();
+ _lock_release(&lock_rtc_memory_crc);
+}
+
+void RTC_IRAM_ATTR esp_default_wake_deep_sleep(void) {
+ mmu_init(0);
+}
+
+void __attribute__((weak, alias("esp_default_wake_deep_sleep"))) esp_wake_deep_sleep(void);
#define ROMFN_ATTR
//Normally, the linker script will put all code and rodata in flash,
-//and all variables in shared RAM. This can be redirected to IRAM if
-//needed using these macros.
+//and all variables in shared RAM. These macros can be used to redirect
+//particular functions/variables to other memory regions.
// Forces code into IRAM instead of flash
#define IRAM_ATTR __attribute__((section(".iram1")))
// Forces data into DRAM instead of flash
#define DRAM_ATTR __attribute__((section(".dram1")))
+// Forces code into RTC fast memory
+#define RTC_IRAM_ATTR __attribute__((section(".rtc.text")))
+
+// Forces data into RTC slow memory
+// Any variable marked with this attribute will keep its value
+// during a deep sleep / wake cycle.
+#define RTC_DATA_ATTR __attribute__((section(".rtc.data")))
+
+// Forces read-only data into RTC slow memory
+// Makes constant data available to RTC wake stubs (see esp_deepsleep.h)
+#define RTC_RODATA_ATTR __attribute__((section(".rtc.rodata")))
+
#endif /* __ESP_ATTR_H__ */
--- /dev/null
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef __ESP_DEEPSLEEP_H__
+#define __ESP_DEEPSLEEP_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \defgroup Deep_Sleep_API Deep Sleep API
+ * @brief API for putting device into deep sleep
+ */
+
+/** @addtogroup Deep_Sleep_API
+ * @{
+ */
+
+/**
+ * @brief Set the chip to deep-sleep mode.
+ *
+ * The device will automatically wake up after the deep-sleep time set
+ * by the users. Upon waking up, the device boots up from user_init.
+ *
+ * @attention The parameter time_in_us to be "uint64" is for further development.
+ * Only the low 32 bits of parameter time_in_us are avalable now.
+ *
+ * @param uint64 time_in_us : deep-sleep time, only the low 32bits are avalable now. unit: microsecond
+ *
+ * @return null
+ */
+void system_deep_sleep(uint64_t time_in_us);
+
+/**
+ * @brief Default stub to run on wake from deep sleep.
+ *
+ * Allows for executing code immediately on wake from sleep, before
+ * the software bootloader or esp-idf app has started up.
+ *
+ * This function is weak-linked, so you can implement your own version
+ * to run code immediately when the chip wakes from
+ * sleep.
+ *
+ * For example:
+ * @code
+ * void RTC_IRAM_ATTR esp_wake_deep_sleep(void) {
+ * esp_default_wake_deep_sleep();
+ * // Add additional functionality here
+ * }
+ *
+ * (Implementing this function is not required for normal operation,
+ * in the usual case your app will start normally when waking from
+ * deep sleep.)
+ *
+ * esp_wake_deep_sleep() functionality is limited:
+ *
+ * - Runs immediately on wake, so most of the SoC is freshly reset -
+ * flash is unmapped and hardware is otherwise uninitialised.
+ *
+ * - Can only call functions implemented in ROM, or marked RTC_IRAM_ATTR.
+ *
+ * - Static variables marked RTC_DATA_ATTR will have initial values on
+ * cold boot, and maintain these values between sleep/wake cycles.
+ *
+ * - Read-only data should be marked RTC_RODATA_ATTR. Strings must be
+ * declared as variables also using RTC_RODATA_ATTR, like this:
+ * RTC_RODATA_ATTR const char message[] = "Hello from very early boot!\n";
+ *
+ * - Any other static memory will not be initialised (either to zero,
+ * or to any predefined value).
+ *
+ *
+ * - If you implement your own stub, the first call the stub makes
+ should be to esp_default_wake_deep_sleep().
+ */
+void esp_wake_deep_sleep(void);
+
+/**
+ * @brief Function type for stub to run on wake from sleep.
+ *
+ */
+typedef void (*esp_deep_sleep_wake_stub_fn_t)(void);
+
+/**
+ * @brief Install a new stub at runtime to run on wake from deep sleep
+ *
+ * If implementing esp_wake_deep_sleep() then it is not necessary to
+ * call this function.
+ *
+ * However, it is possible to call this function to substitute a
+ * different deep sleep stub. Any function used as a deep sleep stub
+ * must be marked RTC_IRAM_ATTR, and must obey the same rules given
+ * for esp_wake_deep_sleep().
+ */
+void esp_set_deep_sleep_wake_stub(esp_deep_sleep_wake_stub_fn_t new_stub);
+
+/**
+ * @brief Return current wake from deep sleep stub, or NULL if
+ * no stub is installed.
+ */
+esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void);
+
+/* The default esp-idf-provided esp_wake_deep_sleep() stub.
+
+ If you replace esp_wake_deep_sleep() in your program, or use
+ esp_set_deep_sleep_wake_stub(), then it is recommended you call
+ esp_default_wake_deep_sleep() as the first function in your stub.
+*/
+void esp_default_wake_deep_sleep(void);
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ESP_SYSTEM_H__ */
*/
void system_restart(void);
-/**
- * @brief Set the chip to deep-sleep mode.
- *
- * The device will automatically wake up after the deep-sleep time set
- * by the users. Upon waking up, the device boots up from user_init.
- *
- * @attention The parameter time_in_us to be "uint64" is for further development.
- * Only the low 32 bits of parameter time_in_us are avalable now.
- *
- * @param uint64 time_in_us : deep-sleep time, only the low 32bits are avalable now. unit: microsecond
- *
- * @return null
- */
-void system_deep_sleep(uint64_t time_in_us);
-
/**
* @brief Get system time, unit: microsecond.
*
*
*************************************************************************************
* Rtc store registers usage
- * RTC_STORE0
- * RTC_STORE1
- * RTC_STORE2
- * RTC_STORE3
- * RTC_STORE4 Reserved
- * RTC_STORE5 External Xtal Frequency
- * RTC_STORE6 FAST_RTC_MEMORY_ENTRY
- * RTC_STORE7 FAST_RTC_MEMORY_CRC
+ * RTC_CNTL_STORE0_REG
+ * RTC_CNTL_STORE1_REG
+ * RTC_CNTL_STORE2_REG
+ * RTC_CNTL_STORE3_REG
+ * RTC_CNTL_STORE4_REG Reserved
+ * RTC_CNTL_STORE5_REG External Xtal Frequency
+ * RTC_CNTL_STORE6_REG FAST_RTC_MEMORY_ENTRY
+ * RTC_CNTL_STORE7_REG FAST_RTC_MEMORY_CRC
*************************************************************************************
*/
-#define RTC_ENTRY_ADDR RTC_STORE6
-#define RTC_MEMORY_CRC RTC_STORE7
+#define RTC_ENTRY_ADDR_REG RTC_CNTL_STORE6_REG
+#define RTC_MEMORY_CRC_REG RTC_CNTL_STORE7_REG
typedef enum {
iram0_2_seg (RX) : org = 0x400D0018, len = 0x330000 /* Even though the segment name is iram, it is actually mapped to flash */
dram0_0_seg (RW) : org = 0x3FFC0000, len = 0x40000 /* Shared RAM, minus rom bss/data/stack.*/
drom0_0_seg (R) : org = 0x3F400010, len = 0x800000
+
+ /* RTC fast memory (executable). Persists over deep sleep.
+ */
+ rtc_iram_seg(RWX) : org = 0x400C0000, len = 0x2000
+ /* RTC slow memory (data accessible). Persists over deep sleep. */
+ rtc_slow_seg(RW) : org = 0x50000000, len = 0x2000
}
_heap_end = 0x40000000;
iram0_2_seg (RX) : org = 0x400D0018, len = 0x330000 /* Even though the segment name is iram, it is actually mapped to flash */
dram0_0_seg (RW) : org = 0x3FFC0000, len = 0x38000 /* Shared RAM, minus rom bss/data/stack.*/
drom0_0_seg (R) : org = 0x3F400010, len = 0x800000
+
+ /* RTC fast memory (executable). Persists over deep sleep.
+ */
+ rtc_iram_seg(RWX) : org = 0x400C0000, len = 0x2000
+ /* RTC slow memory (data accessible). Persists over deep sleep. */
+ rtc_slow_seg(RW) : org = 0x50000000, len = 0x2000
}
_heap_end = 0x3FFF8000;
_rodata_start = ABSOLUTE(.);
*(.rodata)
*(.rodata.*)
- *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
+ *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
*(.gnu.linkonce.r.*)
*(.rodata1)
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
*(.dynamic)
*(.gnu.version_d)
_rodata_end = ABSOLUTE(.);
- /* Literals are also RO data. */
+ /* Literals are also RO data. */
_lit4_start = ABSOLUTE(.);
*(*.lit4)
*(.lit4.*)
_text_end = ABSOLUTE(.);
_etext = .;
} >iram0_2_seg
+
+ .rtc.text :
+ {
+ . = ALIGN(4);
+ *(.rtc.literal .rtc.text)
+ } >rtc_iram_seg
+
+ .rtc.data :
+ {
+ *(.rtc.data)
+ *(.rtc.rodata)
+ } > rtc_slow_seg
}
iram0_2_seg (RX) : org = 0x400D0018, len = 0x330000 /* Even though the segment name is iram, it is actually mapped to flash */
dram0_0_seg (RW) : org = 0x3FFB0000, len = 0x50000 /* Shared RAM, minus rom bss/data/stack.*/
drom0_0_seg (R) : org = 0x3F400010, len = 0x800000
+
+ /* RTC fast memory (executable). Persists over deep sleep.
+ */
+ rtc_iram_seg(RWX) : org = 0x400C0000, len = 0x2000
+ /* RTC slow memory (data accessible). Persists over deep sleep. */
+ rtc_slow_seg(RW) : org = 0x50000000, len = 0x2000
}
_heap_end = 0x40000000;