mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-31 19:24:33 +02:00
esp_hw_support: Add initial ESP32-C3 support
From internal commit 7761d6e8
This commit is contained in:
@@ -77,8 +77,10 @@ void IRAM_ATTR esp_clear_watchpoint(int no)
|
||||
|
||||
bool IRAM_ATTR esp_cpu_in_ocd_debug_mode(void)
|
||||
{
|
||||
#if (CONFIG_ESP32_DEBUG_OCDAWARE == 1) || \
|
||||
(CONFIG_ESP32S2_DEBUG_OCDAWARE == 1)
|
||||
#if CONFIG_ESP32_DEBUG_OCDAWARE || \
|
||||
CONFIG_ESP32S2_DEBUG_OCDAWARE || \
|
||||
CONFIG_ESP32S3_DEBUG_OCDAWARE || \
|
||||
CONFIG_ESP32C3_DEBUG_OCDAWARE
|
||||
return cpu_ll_is_debugger_attached();
|
||||
#else
|
||||
return false; // Always return false if "OCD aware" is disabled
|
||||
|
@@ -39,6 +39,8 @@
|
||||
#include "esp32s2/rom/ets_sys.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/rom/ets_sys.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#include "esp32c3/rom/ets_sys.h"
|
||||
#endif
|
||||
|
||||
#define SOC_LOGE(tag, fmt, ...) esp_rom_printf("%s(err): " fmt, tag, ##__VA_ARGS__)
|
||||
|
20
components/esp_hw_support/port/esp32c3/CMakeLists.txt
Normal file
20
components/esp_hw_support/port/esp32c3/CMakeLists.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
set(srcs "cpu_util_esp32c3.c"
|
||||
"rtc_clk_init.c"
|
||||
"rtc_clk.c"
|
||||
"rtc_init.c"
|
||||
"rtc_pm.c"
|
||||
"rtc_sleep.c"
|
||||
"rtc_time.c"
|
||||
"soc_memory_layout.c"
|
||||
)
|
||||
|
||||
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")
|
||||
|
||||
target_sources(${COMPONENT_LIB} PRIVATE "${srcs}")
|
||||
target_include_directories(${COMPONENT_LIB} PUBLIC . include)
|
||||
target_include_directories(${COMPONENT_LIB} PRIVATE ../hal)
|
||||
|
||||
if(NOT CMAKE_BUILD_EARLY_EXPANSION)
|
||||
set_source_files_properties("${CMAKE_CURRENT_LIST_DIR}/rtc_clk.c" PROPERTIES
|
||||
COMPILE_FLAGS "-fno-jump-tables -fno-tree-switch-conversion")
|
||||
endif()
|
112
components/esp_hw_support/port/esp32c3/cpu_util_esp32c3.c
Normal file
112
components/esp_hw_support/port/esp32c3/cpu_util_esp32c3.c
Normal file
@@ -0,0 +1,112 @@
|
||||
// Copyright 2020 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.
|
||||
#include <assert.h>
|
||||
#include "soc/cpu.h"
|
||||
|
||||
void esp_cpu_configure_region_protection(void)
|
||||
{
|
||||
/* Notes on implementation:
|
||||
*
|
||||
* 1) Note: ESP32-C3 CPU doesn't support overlapping PMP regions
|
||||
*
|
||||
* 2) Therefore, we use TOR (top of range) entries to map the whole address
|
||||
* space, bottom to top.
|
||||
*
|
||||
* 3) There are not enough entries to describe all the memory regions 100% accurately.
|
||||
*
|
||||
* 4) This means some gaps (invalid memory) are accessible. Priority for extending regions
|
||||
* to cover gaps is to extend read-only or read-execute regions or read-only regions only
|
||||
* (executing unmapped addresses should always fault with invalid instruction, read-only means
|
||||
* stores will correctly fault even if reads may return some invalid value.)
|
||||
*
|
||||
* 5) Entries are grouped in order with some static asserts to try and verify everything is
|
||||
* correct.
|
||||
*/
|
||||
const unsigned NONE = PMP_L | PMP_TOR;
|
||||
const unsigned R = PMP_L | PMP_TOR | PMP_R;
|
||||
const unsigned RW = PMP_L | PMP_TOR | PMP_R | PMP_W;
|
||||
const unsigned RX = PMP_L | PMP_TOR | PMP_R | PMP_X;
|
||||
const unsigned RWX = PMP_L | PMP_TOR | PMP_R | PMP_W | PMP_X;
|
||||
|
||||
// 1. Gap at bottom of address space
|
||||
PMP_ENTRY_SET(0, SOC_DEBUG_LOW, NONE);
|
||||
|
||||
// 2. Debug region
|
||||
PMP_ENTRY_SET(1, SOC_DEBUG_HIGH, RWX);
|
||||
_Static_assert(SOC_DEBUG_LOW < SOC_DEBUG_HIGH, "Invalid CPU debug region");
|
||||
|
||||
// 3. Gap between debug region & DROM (flash cache)
|
||||
PMP_ENTRY_SET(2, SOC_DROM_LOW, NONE);
|
||||
_Static_assert(SOC_DEBUG_HIGH < SOC_DROM_LOW, "Invalid PMP entry order");
|
||||
|
||||
// 4. DROM (flash cache)
|
||||
// 5. Gap between DROM & DRAM
|
||||
// (Note: To save PMP entries these two are merged into one read-only region)
|
||||
PMP_ENTRY_SET(3, SOC_DRAM_LOW, R);
|
||||
_Static_assert(SOC_DROM_LOW < SOC_DROM_HIGH, "Invalid DROM region");
|
||||
_Static_assert(SOC_DROM_HIGH < SOC_DRAM_LOW, "Invalid PMP entry order");
|
||||
|
||||
// 6. DRAM
|
||||
PMP_ENTRY_SET(4, SOC_DRAM_HIGH, RW);
|
||||
_Static_assert(SOC_DRAM_LOW < SOC_DRAM_HIGH, "Invalid DRAM region");
|
||||
|
||||
// 7. Gap between DRAM and Mask DROM
|
||||
// 8. Mask DROM
|
||||
// (Note: to save PMP entries these two are merged into one read-only region)
|
||||
PMP_ENTRY_SET(5, SOC_DROM_MASK_HIGH, R);
|
||||
_Static_assert(SOC_DRAM_HIGH < SOC_DROM_MASK_LOW, "Invalid PMP entry order");
|
||||
_Static_assert(SOC_DROM_MASK_LOW < SOC_DROM_MASK_HIGH, "Invalid mask DROM region");
|
||||
|
||||
// 9. Gap between mask DROM and mask IROM
|
||||
// 10. Mask IROM
|
||||
// (Note: to save PMP entries these two are merged into one RX region)
|
||||
PMP_ENTRY_SET(6, SOC_IROM_MASK_HIGH, RX);
|
||||
_Static_assert(SOC_DROM_MASK_HIGH < SOC_IROM_MASK_LOW, "Invalid PMP entry order");
|
||||
_Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid mask IROM region");
|
||||
|
||||
// 11. Gap between mask IROM & IRAM
|
||||
PMP_ENTRY_SET(7, SOC_IRAM_LOW, NONE);
|
||||
_Static_assert(SOC_IROM_MASK_HIGH < SOC_IRAM_LOW, "Invalid PMP entry order");
|
||||
|
||||
// 12. IRAM
|
||||
PMP_ENTRY_SET(8, SOC_IRAM_HIGH, RWX);
|
||||
_Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid IRAM region");
|
||||
|
||||
// 13. Gap between IRAM and IROM
|
||||
// 14. IROM (flash cache)
|
||||
// (Note: to save PMP entries these two are merged into one RX region)
|
||||
PMP_ENTRY_SET(9, SOC_IROM_HIGH, RX);
|
||||
_Static_assert(SOC_IRAM_HIGH < SOC_IROM_LOW, "Invalid PMP entry order");
|
||||
_Static_assert(SOC_IROM_LOW < SOC_IROM_HIGH, "Invalid IROM region");
|
||||
|
||||
// 15. Gap between IROM & RTC slow memory
|
||||
PMP_ENTRY_SET(10, SOC_RTC_IRAM_LOW, NONE);
|
||||
_Static_assert(SOC_IROM_HIGH < SOC_RTC_IRAM_LOW, "Invalid PMP entry order");
|
||||
|
||||
// 16. RTC fast memory
|
||||
PMP_ENTRY_SET(11, SOC_RTC_IRAM_HIGH, RWX);
|
||||
_Static_assert(SOC_RTC_IRAM_LOW < SOC_RTC_IRAM_HIGH, "Invalid RTC IRAM region");
|
||||
|
||||
// 17. Gap between RTC fast memory & peripheral addresses
|
||||
PMP_ENTRY_SET(12, SOC_PERIPHERAL_LOW, NONE);
|
||||
_Static_assert(SOC_RTC_IRAM_HIGH < SOC_PERIPHERAL_LOW, "Invalid PMP entry order");
|
||||
|
||||
// 18. Peripheral addresses
|
||||
PMP_ENTRY_SET(13, SOC_PERIPHERAL_HIGH, RW);
|
||||
_Static_assert(SOC_PERIPHERAL_LOW < SOC_PERIPHERAL_HIGH, "Invalid peripheral region");
|
||||
|
||||
// 19. End of address space
|
||||
PMP_ENTRY_SET(14, UINT32_MAX, NONE); // all but last 4 bytes
|
||||
PMP_ENTRY_SET(15, UINT32_MAX, PMP_L | PMP_NA4); // last 4 bytes
|
||||
}
|
30
components/esp_hw_support/port/esp32c3/i2c_brownout.h
Normal file
30
components/esp_hw_support/port/esp32c3/i2c_brownout.h
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright 2020 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* @file i2c_brownout.h
|
||||
* @brief Register definitions for brownout detector
|
||||
*
|
||||
* This file lists register fields of the brownout detector, located on an internal configuration
|
||||
* bus. These definitions are used via macros defined in i2c_rtc_clk.h.
|
||||
*/
|
||||
|
||||
#define I2C_BOD 0x61
|
||||
#define I2C_BOD_HOSTID 1
|
||||
|
||||
#define I2C_BOD_THRESHOLD 0x5
|
||||
#define I2C_BOD_THRESHOLD_MSB 2
|
||||
#define I2C_BOD_THRESHOLD_LSB 0
|
49
components/esp_hw_support/port/esp32c3/i2c_rtc_clk.h
Normal file
49
components/esp_hw_support/port/esp32c3/i2c_rtc_clk.h
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright 2020 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "i2c_apll.h"
|
||||
#include "i2c_bbpll.h"
|
||||
|
||||
/* Analog function control register */
|
||||
#define ANA_CONFIG_REG 0x6000E044
|
||||
#define ANA_CONFIG_S (8)
|
||||
#define ANA_CONFIG_M (0x3FF)
|
||||
/* Clear to enable APLL */
|
||||
#define I2C_APLL_M (BIT(14))
|
||||
/* Clear to enable BBPLL */
|
||||
#define I2C_BBPLL_M (BIT(17))
|
||||
|
||||
/* ROM functions which read/write internal control bus */
|
||||
uint8_t rom_i2c_readReg(uint8_t block, uint8_t host_id, uint8_t reg_add);
|
||||
uint8_t rom_i2c_readReg_Mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb);
|
||||
void rom_i2c_writeReg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data);
|
||||
void rom_i2c_writeReg_Mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb, uint8_t data);
|
||||
|
||||
/* Convenience macros for the above functions, these use register definitions
|
||||
* from i2c_apll.h/i2c_bbpll.h header files.
|
||||
*/
|
||||
#define I2C_WRITEREG_MASK_RTC(block, reg_add, indata) \
|
||||
rom_i2c_writeReg_Mask(block, block##_HOSTID, reg_add, reg_add##_MSB, reg_add##_LSB, indata)
|
||||
|
||||
#define I2C_READREG_MASK_RTC(block, reg_add) \
|
||||
rom_i2c_readReg_Mask(block, block##_HOSTID, reg_add, reg_add##_MSB, reg_add##_LSB)
|
||||
|
||||
#define I2C_WRITEREG_RTC(block, reg_add, indata) \
|
||||
rom_i2c_writeReg(block, block##_HOSTID, reg_add, indata)
|
||||
|
||||
#define I2C_READREG_RTC(block, reg_add) \
|
||||
rom_i2c_readReg(block, block##_HOSTID, reg_add)
|
565
components/esp_hw_support/port/esp32c3/rtc_clk.c
Normal file
565
components/esp_hw_support/port/esp32c3/rtc_clk.c
Normal file
@@ -0,0 +1,565 @@
|
||||
// Copyright 2020 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.
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp32c3/rom/ets_sys.h"
|
||||
#include "esp32c3/rom/rtc.h"
|
||||
#include "esp32c3/rom/uart.h"
|
||||
#include "esp32c3/rom/gpio.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/sens_reg.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/syscon_reg.h"
|
||||
#include "soc/system_reg.h"
|
||||
#include "i2c_rtc_clk.h"
|
||||
#include "soc_log.h"
|
||||
#include "rtc_clk_common.h"
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
static const char *TAG = "rtc_clk";
|
||||
|
||||
#define RTC_PLL_FREQ_320M 320
|
||||
#define RTC_PLL_FREQ_480M 480
|
||||
|
||||
// Current PLL frequency, in MHZ (320 or 480). Zero if PLL is not enabled.
|
||||
static int s_cur_pll_freq;
|
||||
|
||||
static void rtc_clk_cpu_freq_to_8m(void);
|
||||
|
||||
void rtc_clk_32k_enable_internal(x32k_config_t cfg)
|
||||
{
|
||||
REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DAC_XTAL_32K, cfg.dac);
|
||||
REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DRES_XTAL_32K, cfg.dres);
|
||||
REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DGM_XTAL_32K, cfg.dgm);
|
||||
REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DBUF_XTAL_32K, cfg.dbuf);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K);
|
||||
}
|
||||
|
||||
void rtc_clk_32k_enable(bool enable)
|
||||
{
|
||||
abort(); // TODO ESP32-C3 IDF-2408
|
||||
}
|
||||
|
||||
void rtc_clk_32k_enable_external(void)
|
||||
{
|
||||
abort(); // TODO ESP32-C3 IDF-2408
|
||||
}
|
||||
|
||||
void rtc_clk_32k_bootstrap(uint32_t cycle)
|
||||
{
|
||||
/* No special bootstrapping needed. Just enable the XTAL here. */
|
||||
(void) cycle;
|
||||
rtc_clk_32k_enable(true);
|
||||
}
|
||||
|
||||
bool rtc_clk_32k_enabled(void)
|
||||
{
|
||||
uint32_t xtal_conf = READ_PERI_REG(RTC_CNTL_EXT_XTL_CONF_REG);
|
||||
/* If xtal xpd is controlled by software */
|
||||
bool xtal_xpd_sw = (xtal_conf & RTC_CNTL_XTAL32K_XPD_FORCE) >> RTC_CNTL_XTAL32K_XPD_FORCE_S;
|
||||
/* If xtal xpd software control is on */
|
||||
bool xtal_xpd_st = (xtal_conf & RTC_CNTL_XPD_XTAL_32K) >> RTC_CNTL_XPD_XTAL_32K_S;
|
||||
bool disabled = xtal_xpd_sw && !xtal_xpd_st;
|
||||
return !disabled;
|
||||
}
|
||||
|
||||
void rtc_clk_8m_enable(bool clk_8m_en, bool d256_en)
|
||||
{
|
||||
if (clk_8m_en) {
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M);
|
||||
/* no need to wait once enabled by software */
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CK8M_ENABLE_WAIT_DEFAULT);
|
||||
esp_rom_delay_us(DELAY_8M_ENABLE);
|
||||
} else {
|
||||
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M);
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_DEFAULT);
|
||||
}
|
||||
/* d256 should be independent configured with 8M
|
||||
* Maybe we can split this function into 8m and dmd256
|
||||
*/
|
||||
if (d256_en) {
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV);
|
||||
} else {
|
||||
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV);
|
||||
}
|
||||
}
|
||||
|
||||
bool rtc_clk_8m_enabled(void)
|
||||
{
|
||||
return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M) == 0;
|
||||
}
|
||||
|
||||
bool rtc_clk_8md256_enabled(void)
|
||||
{
|
||||
return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV) == 0;
|
||||
}
|
||||
|
||||
void rtc_clk_apll_enable(bool enable, uint32_t sdm0, uint32_t sdm1, uint32_t sdm2, uint32_t o_div)
|
||||
{
|
||||
REG_SET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD, enable ? 0 : 1);
|
||||
REG_SET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU, enable ? 1 : 0);
|
||||
|
||||
if (enable) {
|
||||
I2C_WRITEREG_MASK_RTC(I2C_APLL, I2C_APLL_DSDM2, sdm2);
|
||||
I2C_WRITEREG_MASK_RTC(I2C_APLL, I2C_APLL_DSDM0, sdm0);
|
||||
I2C_WRITEREG_MASK_RTC(I2C_APLL, I2C_APLL_DSDM1, sdm1);
|
||||
I2C_WRITEREG_RTC(I2C_APLL, I2C_APLL_SDM_STOP, APLL_SDM_STOP_VAL_1);
|
||||
I2C_WRITEREG_RTC(I2C_APLL, I2C_APLL_SDM_STOP, APLL_SDM_STOP_VAL_2_REV1);
|
||||
I2C_WRITEREG_MASK_RTC(I2C_APLL, I2C_APLL_OR_OUTPUT_DIV, o_div);
|
||||
|
||||
/* calibration */
|
||||
I2C_WRITEREG_RTC(I2C_APLL, I2C_APLL_IR_CAL_DELAY, APLL_CAL_DELAY_1);
|
||||
I2C_WRITEREG_RTC(I2C_APLL, I2C_APLL_IR_CAL_DELAY, APLL_CAL_DELAY_2);
|
||||
I2C_WRITEREG_RTC(I2C_APLL, I2C_APLL_IR_CAL_DELAY, APLL_CAL_DELAY_3);
|
||||
|
||||
/* wait for calibration end */
|
||||
while (!(I2C_READREG_MASK_RTC(I2C_APLL, I2C_APLL_OR_CAL_END))) {
|
||||
/* use esp_rom_delay_us so the RTC bus doesn't get flooded */
|
||||
esp_rom_delay_us(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_clk_set_xtal_wait(void)
|
||||
{
|
||||
/*
|
||||
the `xtal_wait` time need 1ms, so we need calibrate slow clk period,
|
||||
and `RTC_CNTL_XTL_BUF_WAIT` depend on it.
|
||||
*/
|
||||
rtc_slow_freq_t slow_clk_freq = rtc_clk_slow_freq_get();
|
||||
rtc_slow_freq_t rtc_slow_freq_x32k = RTC_SLOW_FREQ_32K_XTAL;
|
||||
rtc_slow_freq_t rtc_slow_freq_8MD256 = RTC_SLOW_FREQ_8MD256;
|
||||
rtc_cal_sel_t cal_clk = RTC_CAL_RTC_MUX;
|
||||
if (slow_clk_freq == (rtc_slow_freq_x32k)) {
|
||||
cal_clk = RTC_CAL_32K_XTAL;
|
||||
} else if (slow_clk_freq == rtc_slow_freq_8MD256) {
|
||||
cal_clk = RTC_CAL_8MD256;
|
||||
}
|
||||
uint32_t slow_clk_period = rtc_clk_cal(cal_clk, 2000);
|
||||
uint32_t xtal_wait_1ms = 100;
|
||||
if (slow_clk_period) {
|
||||
xtal_wait_1ms = (1000 << RTC_CLK_CAL_FRACT) / slow_clk_period;
|
||||
}
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_XTL_BUF_WAIT, xtal_wait_1ms);
|
||||
}
|
||||
|
||||
void rtc_clk_slow_freq_set(rtc_slow_freq_t slow_freq)
|
||||
{
|
||||
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, slow_freq);
|
||||
|
||||
/* Why we need to connect this clock to digital?
|
||||
* Or maybe this clock should be connected to digital when xtal 32k clock is enabled instead?
|
||||
*/
|
||||
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN,
|
||||
(slow_freq == RTC_SLOW_FREQ_32K_XTAL) ? 1 : 0);
|
||||
|
||||
/* The clk_8m_d256 will be closed when rtc_state in SLEEP,
|
||||
so if the slow_clk is 8md256, clk_8m must be force power on
|
||||
*/
|
||||
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU, (slow_freq == RTC_SLOW_FREQ_8MD256) ? 1 : 0);
|
||||
rtc_clk_set_xtal_wait();
|
||||
esp_rom_delay_us(DELAY_SLOW_CLK_SWITCH);
|
||||
}
|
||||
|
||||
rtc_slow_freq_t rtc_clk_slow_freq_get(void)
|
||||
{
|
||||
return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL);
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_slow_freq_get_hz(void)
|
||||
{
|
||||
switch (rtc_clk_slow_freq_get()) {
|
||||
case RTC_SLOW_FREQ_RTC: return RTC_SLOW_CLK_FREQ_90K;
|
||||
case RTC_SLOW_FREQ_32K_XTAL: return RTC_SLOW_CLK_FREQ_32K;
|
||||
case RTC_SLOW_FREQ_8MD256: return RTC_SLOW_CLK_FREQ_8MD256;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rtc_clk_fast_freq_set(rtc_fast_freq_t fast_freq)
|
||||
{
|
||||
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, fast_freq);
|
||||
esp_rom_delay_us(DELAY_FAST_CLK_SWITCH);
|
||||
}
|
||||
|
||||
rtc_fast_freq_t rtc_clk_fast_freq_get(void)
|
||||
{
|
||||
return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL);
|
||||
}
|
||||
|
||||
static void rtc_clk_bbpll_disable(void)
|
||||
{
|
||||
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD |
|
||||
RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD);
|
||||
s_cur_pll_freq = 0;
|
||||
}
|
||||
|
||||
static void rtc_clk_bbpll_enable(void)
|
||||
{
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD |
|
||||
RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD);
|
||||
}
|
||||
|
||||
void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq)
|
||||
{
|
||||
uint8_t div_ref;
|
||||
uint8_t div7_0;
|
||||
uint8_t dr1;
|
||||
uint8_t dr3;
|
||||
uint8_t dchgp;
|
||||
uint8_t dcur;
|
||||
|
||||
assert(xtal_freq == RTC_XTAL_FREQ_40M);
|
||||
|
||||
if (pll_freq == RTC_PLL_FREQ_480M) {
|
||||
/* Clear this register to let the digital part know 480M PLL is used */
|
||||
SET_PERI_REG_MASK(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL);
|
||||
/* Configure 480M PLL */
|
||||
div_ref = 0;
|
||||
div7_0 = 8;
|
||||
dr1 = 0;
|
||||
dr3 = 0;
|
||||
dchgp = 5;
|
||||
dcur = 4;
|
||||
I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x6B);
|
||||
} else {
|
||||
/* Clear this register to let the digital part know 320M PLL is used */
|
||||
CLEAR_PERI_REG_MASK(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL);
|
||||
/* Configure 320M PLL */
|
||||
div_ref = 0;
|
||||
div7_0 = 4;
|
||||
dr1 = 0;
|
||||
dr3 = 0;
|
||||
dchgp = 5;
|
||||
dcur = 5;
|
||||
I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x69);
|
||||
}
|
||||
uint8_t i2c_bbpll_lref = (dchgp << I2C_BBPLL_OC_DCHGP_LSB) | (div_ref);
|
||||
uint8_t i2c_bbpll_div_7_0 = div7_0;
|
||||
uint8_t i2c_bbpll_dcur = (2 << I2C_BBPLL_OC_DLREF_SEL_LSB ) | (1 << I2C_BBPLL_OC_DHREF_SEL_LSB) | dcur;
|
||||
I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_REF_DIV, i2c_bbpll_lref);
|
||||
I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0);
|
||||
I2C_WRITEREG_MASK_RTC(I2C_BBPLL, I2C_BBPLL_OC_DR1, dr1);
|
||||
I2C_WRITEREG_MASK_RTC(I2C_BBPLL, I2C_BBPLL_OC_DR3, dr3);
|
||||
I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_DCUR, i2c_bbpll_dcur);
|
||||
|
||||
// Enable calibration by software
|
||||
I2C_WRITEREG_MASK_RTC(I2C_BBPLL, I2C_BBPLL_IR_CAL_ENX_CAP, 1);
|
||||
for (int ext_cap = 0; ext_cap < 16; ext_cap++) {
|
||||
uint8_t cal_result;
|
||||
I2C_WRITEREG_MASK_RTC(I2C_BBPLL, I2C_BBPLL_IR_CAL_EXT_CAP, ext_cap);
|
||||
cal_result = I2C_READREG_MASK_RTC(I2C_BBPLL, I2C_BBPLL_OR_CAL_CAP);
|
||||
if (cal_result == 0) {
|
||||
break;
|
||||
}
|
||||
if (ext_cap == 15) {
|
||||
SOC_LOGE(TAG, "BBPLL SOFTWARE CAL FAIL");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
s_cur_pll_freq = pll_freq;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to one of PLL-based frequencies. Current frequency can be XTAL or PLL.
|
||||
* PLL must already be enabled.
|
||||
* @param cpu_freq new CPU frequency
|
||||
*/
|
||||
static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz)
|
||||
{
|
||||
//int dbias = DIG_DBIAS_80M_160M;
|
||||
int per_conf = DPORT_CPUPERIOD_SEL_80;
|
||||
if (cpu_freq_mhz == 80) {
|
||||
/* nothing to do */
|
||||
} else if (cpu_freq_mhz == 160) {
|
||||
per_conf = DPORT_CPUPERIOD_SEL_160;
|
||||
} else {
|
||||
SOC_LOGE(TAG, "invalid frequency");
|
||||
abort();
|
||||
}
|
||||
REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, per_conf);
|
||||
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0);
|
||||
//REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, dbias);
|
||||
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_PLL);
|
||||
rtc_clk_apb_freq_update(80 * MHZ);
|
||||
ets_update_cpu_frequency(cpu_freq_mhz);
|
||||
}
|
||||
|
||||
bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *out_config)
|
||||
{
|
||||
uint32_t source_freq_mhz;
|
||||
rtc_cpu_freq_src_t source;
|
||||
uint32_t divider;
|
||||
uint32_t real_freq_mhz;
|
||||
|
||||
uint32_t xtal_freq = (uint32_t) rtc_clk_xtal_freq_get();
|
||||
if (freq_mhz <= xtal_freq) {
|
||||
divider = xtal_freq / freq_mhz;
|
||||
real_freq_mhz = (xtal_freq + divider / 2) / divider; /* round */
|
||||
if (real_freq_mhz != freq_mhz) {
|
||||
// no suitable divider
|
||||
return false;
|
||||
}
|
||||
|
||||
source_freq_mhz = xtal_freq;
|
||||
source = RTC_CPU_FREQ_SRC_XTAL;
|
||||
} else if (freq_mhz == 80) {
|
||||
real_freq_mhz = freq_mhz;
|
||||
source = RTC_CPU_FREQ_SRC_PLL;
|
||||
source_freq_mhz = RTC_PLL_FREQ_480M;
|
||||
divider = 6;
|
||||
} else if (freq_mhz == 160) {
|
||||
real_freq_mhz = freq_mhz;
|
||||
source = RTC_CPU_FREQ_SRC_PLL;
|
||||
source_freq_mhz = RTC_PLL_FREQ_480M;
|
||||
divider = 3;
|
||||
} else {
|
||||
// unsupported frequency
|
||||
return false;
|
||||
}
|
||||
*out_config = (rtc_cpu_freq_config_t) {
|
||||
.source = source,
|
||||
.div = divider,
|
||||
.source_freq_mhz = source_freq_mhz,
|
||||
.freq_mhz = real_freq_mhz
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config)
|
||||
{
|
||||
rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||
uint32_t soc_clk_sel = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL);
|
||||
if (soc_clk_sel != DPORT_SOC_CLK_SEL_XTAL) {
|
||||
rtc_clk_cpu_freq_to_xtal(xtal_freq, 1);
|
||||
}
|
||||
if (soc_clk_sel == DPORT_SOC_CLK_SEL_PLL) {
|
||||
rtc_clk_bbpll_disable();
|
||||
}
|
||||
if (config->source == RTC_CPU_FREQ_SRC_XTAL) {
|
||||
if (config->div > 1) {
|
||||
rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div);
|
||||
}
|
||||
} else if (config->source == RTC_CPU_FREQ_SRC_PLL) {
|
||||
rtc_clk_bbpll_enable();
|
||||
rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), config->source_freq_mhz);
|
||||
rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz);
|
||||
} else if (config->source == RTC_CPU_FREQ_SRC_8M) {
|
||||
rtc_clk_cpu_freq_to_8m();
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config)
|
||||
{
|
||||
rtc_cpu_freq_src_t source;
|
||||
uint32_t source_freq_mhz;
|
||||
uint32_t div;
|
||||
uint32_t freq_mhz;
|
||||
uint32_t soc_clk_sel = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL);
|
||||
switch (soc_clk_sel) {
|
||||
case DPORT_SOC_CLK_SEL_XTAL: {
|
||||
source = RTC_CPU_FREQ_SRC_XTAL;
|
||||
div = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1;
|
||||
source_freq_mhz = (uint32_t) rtc_clk_xtal_freq_get();
|
||||
freq_mhz = source_freq_mhz / div;
|
||||
}
|
||||
break;
|
||||
case DPORT_SOC_CLK_SEL_PLL: {
|
||||
source = RTC_CPU_FREQ_SRC_PLL;
|
||||
uint32_t cpuperiod_sel = REG_GET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL);
|
||||
uint32_t pllfreq_sel = REG_GET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL);
|
||||
source_freq_mhz = (pllfreq_sel) ? RTC_PLL_FREQ_480M : RTC_PLL_FREQ_320M;
|
||||
if (cpuperiod_sel == DPORT_CPUPERIOD_SEL_80) {
|
||||
div = (source_freq_mhz == RTC_PLL_FREQ_480M) ? 6 : 4;
|
||||
freq_mhz = 80;
|
||||
} else if (cpuperiod_sel == DPORT_CPUPERIOD_SEL_160) {
|
||||
div = (source_freq_mhz == RTC_PLL_FREQ_480M) ? 3 : 2;
|
||||
div = 3;
|
||||
freq_mhz = 160;
|
||||
} else {
|
||||
SOC_LOGE(TAG, "unsupported frequency configuration");
|
||||
abort();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DPORT_SOC_CLK_SEL_8M:
|
||||
source = RTC_CPU_FREQ_SRC_8M;
|
||||
source_freq_mhz = 8;
|
||||
div = 1;
|
||||
freq_mhz = source_freq_mhz;
|
||||
break;
|
||||
case DPORT_SOC_CLK_SEL_APLL:
|
||||
default:
|
||||
SOC_LOGE(TAG, "unsupported frequency configuration");
|
||||
abort();
|
||||
}
|
||||
*out_config = (rtc_cpu_freq_config_t) {
|
||||
.source = source,
|
||||
.source_freq_mhz = source_freq_mhz,
|
||||
.div = div,
|
||||
.freq_mhz = freq_mhz
|
||||
};
|
||||
}
|
||||
|
||||
void rtc_clk_cpu_freq_set(rtc_cpu_freq_t cpu_freq)
|
||||
{
|
||||
rtc_xtal_freq_t xtal_freq = RTC_XTAL_FREQ_40M;
|
||||
/* Switch CPU to XTAL frequency first */
|
||||
//REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_XTAL);
|
||||
//REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, APB_CTRL_SOC_CLK_SEL_XTL);
|
||||
//REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 1);
|
||||
//ets_update_cpu_frequency(xtal_freq);
|
||||
/* Frequency switch is synchronized to SLOW_CLK cycle. Wait until the switch
|
||||
* is complete before disabling the PLL.
|
||||
*/
|
||||
rtc_clk_wait_for_slow_cycle();
|
||||
REG_SET_BIT(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL);
|
||||
//REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, 0);
|
||||
// SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG,
|
||||
// RTC_CNTL_BB_I2C_FORCE_PD | RTC_CNTL_BBPLL_FORCE_PD |
|
||||
// RTC_CNTL_BBPLL_I2C_FORCE_PD);
|
||||
s_cur_pll_freq = 0;
|
||||
rtc_clk_apb_freq_update(xtal_freq * MHZ);
|
||||
if (cpu_freq == RTC_CPU_FREQ_XTAL) {
|
||||
/* already at XTAL, nothing to do */
|
||||
} else if (cpu_freq == RTC_CPU_FREQ_2M) {
|
||||
/* set up divider to produce 2MHz from XTAL */
|
||||
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, (xtal_freq / 2) - 1);
|
||||
ets_update_cpu_frequency(2);
|
||||
rtc_clk_apb_freq_update(2 * MHZ);
|
||||
} else {
|
||||
/* use PLL as clock source */
|
||||
if (cpu_freq == RTC_CPU_FREQ_80M) {
|
||||
|
||||
REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, 0);
|
||||
ets_update_cpu_frequency(80);
|
||||
s_cur_pll_freq = RTC_PLL_FREQ_480M;
|
||||
} else if (cpu_freq == RTC_CPU_FREQ_160M) {
|
||||
//REG_CLR_BIT(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL);
|
||||
REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, 1);
|
||||
ets_update_cpu_frequency(160);
|
||||
s_cur_pll_freq = RTC_PLL_FREQ_480M;
|
||||
}
|
||||
#define APB_CTRL_SOC_CLK_SEL_PLL 1
|
||||
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, APB_CTRL_SOC_CLK_SEL_PLL);
|
||||
rtc_clk_wait_for_slow_cycle();
|
||||
rtc_clk_apb_freq_update(80 * MHZ);
|
||||
}
|
||||
s_cur_pll_freq = cpu_freq;
|
||||
}
|
||||
|
||||
void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config)
|
||||
{
|
||||
if (config->source == RTC_CPU_FREQ_SRC_XTAL) {
|
||||
rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div);
|
||||
} else if (config->source == RTC_CPU_FREQ_SRC_PLL &&
|
||||
s_cur_pll_freq == config->source_freq_mhz) {
|
||||
rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz);
|
||||
} else {
|
||||
/* fallback */
|
||||
rtc_clk_cpu_freq_set_config(config);
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_clk_cpu_freq_set_xtal(void)
|
||||
{
|
||||
int freq_mhz = (int) rtc_clk_xtal_freq_get();
|
||||
|
||||
rtc_clk_cpu_freq_to_xtal(freq_mhz, 1);
|
||||
rtc_clk_bbpll_disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to XTAL frequency. Does not disable the PLL.
|
||||
*/
|
||||
void rtc_clk_cpu_freq_to_xtal(int freq, int div)
|
||||
{
|
||||
ets_update_cpu_frequency(freq);
|
||||
/* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */
|
||||
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0);
|
||||
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, div - 1);
|
||||
/* no need to adjust the REF_TICK */
|
||||
/* switch clock source */
|
||||
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_XTAL);
|
||||
rtc_clk_apb_freq_update(freq * MHZ);
|
||||
/* lower the voltage */
|
||||
if (freq <= 2) {
|
||||
//REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_2M);
|
||||
} else {
|
||||
//REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_XTAL);
|
||||
}
|
||||
}
|
||||
|
||||
static void rtc_clk_cpu_freq_to_8m(void)
|
||||
{
|
||||
ets_update_cpu_frequency(8);
|
||||
//REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_XTAL);
|
||||
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0);
|
||||
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_8M);
|
||||
rtc_clk_apb_freq_update(RTC_FAST_CLK_FREQ_8M);
|
||||
}
|
||||
|
||||
rtc_xtal_freq_t rtc_clk_xtal_freq_get(void)
|
||||
{
|
||||
uint32_t xtal_freq_reg = READ_PERI_REG(RTC_XTAL_FREQ_REG);
|
||||
if (!clk_val_is_valid(xtal_freq_reg)) {
|
||||
SOC_LOGW(TAG, "invalid RTC_XTAL_FREQ_REG value: 0x%08x", xtal_freq_reg);
|
||||
return RTC_XTAL_FREQ_40M;
|
||||
}
|
||||
return reg_val_to_clk_val(xtal_freq_reg);
|
||||
}
|
||||
|
||||
void rtc_clk_xtal_freq_update(rtc_xtal_freq_t xtal_freq)
|
||||
{
|
||||
WRITE_PERI_REG(RTC_XTAL_FREQ_REG, clk_val_to_reg_val(xtal_freq));
|
||||
}
|
||||
|
||||
void rtc_clk_apb_freq_update(uint32_t apb_freq)
|
||||
{
|
||||
WRITE_PERI_REG(RTC_APB_FREQ_REG, clk_val_to_reg_val(apb_freq >> 12));
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_apb_freq_get(void)
|
||||
{
|
||||
uint32_t freq_hz = reg_val_to_clk_val(READ_PERI_REG(RTC_APB_FREQ_REG)) << 12;
|
||||
// round to the nearest MHz
|
||||
freq_hz += MHZ / 2;
|
||||
uint32_t remainder = freq_hz % MHZ;
|
||||
return freq_hz - remainder;
|
||||
}
|
||||
|
||||
void rtc_clk_divider_set(uint32_t div)
|
||||
{
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD);
|
||||
REG_SET_FIELD(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV, div);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD);
|
||||
}
|
||||
|
||||
void rtc_clk_8m_divider_set(uint32_t div)
|
||||
{
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD);
|
||||
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, div);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD);
|
||||
}
|
||||
|
||||
/* Name used in libphy.a:phy_chip_v7.o
|
||||
* TODO: update the library to use rtc_clk_xtal_freq_get
|
||||
*/
|
||||
rtc_xtal_freq_t rtc_get_xtal(void) __attribute__((alias("rtc_clk_xtal_freq_get")));
|
59
components/esp_hw_support/port/esp32c3/rtc_clk_common.h
Normal file
59
components/esp_hw_support/port/esp32c3/rtc_clk_common.h
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright 2020 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#define MHZ (1000000)
|
||||
|
||||
#define DPORT_CPUPERIOD_SEL_80 0
|
||||
#define DPORT_CPUPERIOD_SEL_160 1
|
||||
#define DPORT_CPUPERIOD_SEL_240 2
|
||||
|
||||
#define DPORT_SOC_CLK_SEL_XTAL 0
|
||||
#define DPORT_SOC_CLK_SEL_PLL 1
|
||||
#define DPORT_SOC_CLK_SEL_8M 2
|
||||
#define DPORT_SOC_CLK_SEL_APLL 3
|
||||
|
||||
#define RTC_FAST_CLK_FREQ_8M 8500000
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void rtc_clk_cpu_freq_to_xtal(int freq, int div);
|
||||
|
||||
/* Values of RTC_XTAL_FREQ_REG and RTC_APB_FREQ_REG are stored as two copies in
|
||||
* lower and upper 16-bit halves. These are the routines to work with such a
|
||||
* representation.
|
||||
*/
|
||||
static inline bool clk_val_is_valid(uint32_t val)
|
||||
{
|
||||
return (val & 0xffff) == ((val >> 16) & 0xffff) &&
|
||||
val != 0 &&
|
||||
val != UINT32_MAX;
|
||||
}
|
||||
|
||||
static inline uint32_t reg_val_to_clk_val(uint32_t val)
|
||||
{
|
||||
return val & UINT16_MAX;
|
||||
}
|
||||
|
||||
static inline uint32_t clk_val_to_reg_val(uint32_t val)
|
||||
{
|
||||
return (val & UINT16_MAX) | ((val & UINT16_MAX) << 16);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
87
components/esp_hw_support/port/esp32c3/rtc_clk_init.c
Normal file
87
components/esp_hw_support/port/esp32c3/rtc_clk_init.c
Normal file
@@ -0,0 +1,87 @@
|
||||
// Copyright 2020 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.
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include "esp32c3/rom/ets_sys.h"
|
||||
#include "esp32c3/rom/rtc.h"
|
||||
#include "esp32c3/rom/uart.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/rtc_periph.h"
|
||||
#include "soc/sens_periph.h"
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "soc/apb_ctrl_reg.h"
|
||||
#include "i2c_rtc_clk.h"
|
||||
#include "soc_log.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "rtc_clk_common.h"
|
||||
#include "esp_rom_uart.h"
|
||||
|
||||
static const char* TAG = "rtc_clk_init";
|
||||
|
||||
void rtc_clk_init(rtc_clk_config_t cfg)
|
||||
{
|
||||
rtc_cpu_freq_config_t old_config, new_config;
|
||||
|
||||
/* Set tuning parameters for 8M and 90k clocks.
|
||||
* Note: this doesn't attempt to set the clocks to precise frequencies.
|
||||
* Instead, we calibrate these clocks against XTAL frequency later, when necessary.
|
||||
* - SCK_DCAP value controls tuning of 90k clock.
|
||||
* The higher the value of DCAP is, the lower is the frequency.
|
||||
* - CK8M_DFREQ value controls tuning of 8M clock.
|
||||
* CLK_8M_DFREQ constant gives the best temperature characteristics.
|
||||
*/
|
||||
REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_SCK_DCAP, cfg.slow_clk_dcap);
|
||||
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DFREQ, cfg.clk_8m_dfreq);
|
||||
|
||||
/* Configure 90k clock division */
|
||||
rtc_clk_divider_set(cfg.clk_rtc_clk_div);
|
||||
|
||||
/* Configure 8M clock division */
|
||||
rtc_clk_8m_divider_set(cfg.clk_8m_clk_div);
|
||||
|
||||
/* Enable the internal bus used to configure PLLs */
|
||||
SET_PERI_REG_BITS(ANA_CONFIG_REG, ANA_CONFIG_M, ANA_CONFIG_M, ANA_CONFIG_S);
|
||||
CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, I2C_APLL_M | I2C_BBPLL_M);
|
||||
|
||||
rtc_xtal_freq_t xtal_freq = cfg.xtal_freq;
|
||||
esp_rom_uart_tx_wait_idle(0);
|
||||
rtc_clk_xtal_freq_update(xtal_freq);
|
||||
rtc_clk_apb_freq_update(xtal_freq * MHZ);
|
||||
|
||||
/* Set CPU frequency */
|
||||
rtc_clk_cpu_freq_get_config(&old_config);
|
||||
bool res = rtc_clk_cpu_freq_mhz_to_config(cfg.cpu_freq_mhz, &new_config);
|
||||
if (!res) {
|
||||
SOC_LOGE(TAG, "invalid CPU frequency value");
|
||||
abort();
|
||||
}
|
||||
rtc_clk_cpu_freq_set_config(&new_config);
|
||||
|
||||
/* Re-calculate the ccount to make time calculation correct. */
|
||||
//XTHAL_SET_CCOUNT( (uint64_t)XTHAL_GET_CCOUNT() * cfg.cpu_freq_mhz / freq_before );
|
||||
|
||||
/* Slow & fast clocks setup */
|
||||
if (cfg.slow_freq == RTC_SLOW_FREQ_32K_XTAL) {
|
||||
rtc_clk_32k_enable(true);
|
||||
}
|
||||
if (cfg.fast_freq == RTC_FAST_FREQ_8M) {
|
||||
bool need_8md256 = cfg.slow_freq == RTC_SLOW_FREQ_8MD256;
|
||||
rtc_clk_8m_enable(true, need_8md256);
|
||||
}
|
||||
rtc_clk_fast_freq_set(cfg.fast_freq);
|
||||
rtc_clk_slow_freq_set(cfg.slow_freq);
|
||||
}
|
187
components/esp_hw_support/port/esp32c3/rtc_init.c
Normal file
187
components/esp_hw_support/port/esp32c3/rtc_init.c
Normal file
@@ -0,0 +1,187 @@
|
||||
// Copyright 2020 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.
|
||||
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "soc/gpio_reg.h"
|
||||
#include "soc/spi_mem_reg.h"
|
||||
#include "soc/extmem_reg.h"
|
||||
#include "soc/system_reg.h"
|
||||
#include "i2c_rtc_clk.h"
|
||||
|
||||
void rtc_init(rtc_config_t cfg)
|
||||
{
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PVTMON_PU);
|
||||
rtc_clk_set_xtal_wait();
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, cfg.pll_wait);
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, cfg.ck8m_wait);
|
||||
|
||||
/* Moved from rtc sleep to rtc init to save sleep function running time */
|
||||
// set shortest possible sleep time limit
|
||||
//REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_MIN_SLP_VAL, RTC_CNTL_MIN_SLP_VAL_MIN);
|
||||
|
||||
/* This power domian removed
|
||||
* set rom&ram timer
|
||||
* REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_ROM_RAM_POWERUP_TIMER, ROM_RAM_POWERUP_CYCLES);
|
||||
* REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_ROM_RAM_WAIT_TIMER, ROM_RAM_WAIT_CYCLES);
|
||||
*/
|
||||
// set wifi timer
|
||||
rtc_init_config_t rtc_init_cfg = RTC_INIT_CONFIG_DEFAULT();
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_WIFI_POWERUP_TIMER, rtc_init_cfg.wifi_powerup_cycles);
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_WIFI_WAIT_TIMER, rtc_init_cfg.wifi_wait_cycles);
|
||||
// set rtc peri timer
|
||||
//REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_POWERUP_TIMER, rtc_init_cfg.rtc_powerup_cycles);
|
||||
//REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_WAIT_TIMER, rtc_init_cfg.rtc_wait_cycles);
|
||||
// set digital wrap timer
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_DG_WRAP_POWERUP_TIMER, rtc_init_cfg.dg_wrap_powerup_cycles);
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_DG_WRAP_WAIT_TIMER, rtc_init_cfg.dg_wrap_wait_cycles);
|
||||
// set rtc memory timer
|
||||
//REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_RTCMEM_POWERUP_TIMER, rtc_init_cfg.rtc_mem_powerup_cycles);
|
||||
//REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_RTCMEM_WAIT_TIMER, rtc_init_cfg.rtc_mem_wait_cycles);
|
||||
|
||||
//SET_PERI_REG_MASK(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_INC_HEARTBEAT_PERIOD);
|
||||
|
||||
/* Reset RTC bias to default value (needed if waking up from deep sleep) */
|
||||
//REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_WAK, RTC_CNTL_DBIAS_1V10);
|
||||
//REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_SLP, RTC_CNTL_DBIAS_1V10);
|
||||
|
||||
|
||||
if (cfg.clkctl_init) {
|
||||
//clear CMMU clock force on
|
||||
CLEAR_PERI_REG_MASK(EXTMEM_CACHE_MMU_POWER_CTRL_REG, EXTMEM_CACHE_MMU_MEM_FORCE_ON);
|
||||
//clear rom clock force on
|
||||
//REG_SET_FIELD(SYSTEM_ROM_CTRL_0_REG, SYSTEM_ROM_IRAM0_CLKGATE_FORCE_ON, 0);
|
||||
//clear sram clock force on
|
||||
//REG_SET_FIELD(SYSTEM_SRAM_CTRL_0_REG, SYSTEM_SRAM_CLKGATE_FORCE_ON, 0);
|
||||
//clear tag clock force on
|
||||
CLEAR_PERI_REG_MASK(EXTMEM_ICACHE_TAG_POWER_CTRL_REG, EXTMEM_ICACHE_TAG_MEM_FORCE_ON);
|
||||
//clear register clock force on
|
||||
CLEAR_PERI_REG_MASK(SPI_MEM_CLOCK_GATE_REG(0), SPI_MEM_CLK_EN);
|
||||
CLEAR_PERI_REG_MASK(SPI_MEM_CLOCK_GATE_REG(1), SPI_MEM_CLK_EN);
|
||||
}
|
||||
|
||||
if (cfg.pwrctl_init) {
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
|
||||
//cancel xtal force pu if no need to force power up
|
||||
//cannot cancel xtal force pu if pll is force power on
|
||||
if (!(cfg.xtal_fpu | cfg.bbpll_fpu)) {
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_XTL_FORCE_PU);
|
||||
} else {
|
||||
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_XTL_FORCE_PU);
|
||||
}
|
||||
// CLEAR APLL close
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD);
|
||||
|
||||
//cancel bbpll force pu if setting no force power up
|
||||
if (!cfg.bbpll_fpu) {
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BBPLL_FORCE_PU);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BBPLL_I2C_FORCE_PU);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PU);
|
||||
} else {
|
||||
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BBPLL_FORCE_PU);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BBPLL_I2C_FORCE_PU);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PU);
|
||||
}
|
||||
//cancel RTC REG force PU
|
||||
//CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FORCE_PU);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_DBOOST_FORCE_PU);
|
||||
|
||||
//combine two rtc memory options
|
||||
//CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_MEM_FORCE_PU);
|
||||
//CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_MEM_FORCE_NOISO);
|
||||
|
||||
if (cfg.rtc_dboost_fpd) {
|
||||
SET_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_DBOOST_FORCE_PD);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_DBOOST_FORCE_PD);
|
||||
}
|
||||
|
||||
//cancel sar i2c pd force
|
||||
//CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PD);
|
||||
//cancel digital pu force
|
||||
//CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_MEM_FORCE_PU);
|
||||
//cannel i2c_reset_protect pd force
|
||||
//CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG,RTC_CNTL_I2C_RESET_POR_FORCE_PD);
|
||||
|
||||
/* If this mask is enabled, all soc memories cannot enter power down mode */
|
||||
/* We should control soc memory power down mode from RTC, so we will not touch this register any more */
|
||||
//CLEAR_PERI_REG_MASK(SYSTEM_MEM_PD_MASK_REG, SYSTEM_LSLP_MEM_PD_MASK);
|
||||
/* If this pd_cfg is set to 1, all memory won't enter low power mode during light sleep */
|
||||
/* If this pd_cfg is set to 0, all memory will enter low power mode during light sleep */
|
||||
rtc_sleep_pd_config_t pd_cfg = RTC_SLEEP_PD_CONFIG_ALL(0);
|
||||
rtc_sleep_pd(pd_cfg);
|
||||
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_FORCE_PU);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PU);
|
||||
// ROM_RAM power domain is removed
|
||||
// CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_CPU_ROM_RAM_FORCE_PU);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_WRAP_FORCE_NOISO);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_NOISO);
|
||||
// CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_CPU_ROM_RAM_FORCE_NOISO);
|
||||
//CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FORCE_NOISO);
|
||||
//cancel digital PADS force no iso
|
||||
if (cfg.cpu_waiti_clk_gate) {
|
||||
CLEAR_PERI_REG_MASK(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPU_WAIT_MODE_FORCE_ON);
|
||||
} else {
|
||||
SET_PERI_REG_MASK(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPU_WAIT_MODE_FORCE_ON);
|
||||
}
|
||||
/*if SYSTEM_CPU_WAIT_MODE_FORCE_ON == 0 , the cpu clk will be closed when cpu enter WAITI mode*/
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_NOISO);
|
||||
}
|
||||
}
|
||||
|
||||
rtc_vddsdio_config_t rtc_vddsdio_get_config()
|
||||
{
|
||||
rtc_vddsdio_config_t result;
|
||||
uint32_t sdio_conf_reg = REG_READ(RTC_CNTL_SDIO_CONF_REG);
|
||||
result.drefh = (sdio_conf_reg & RTC_CNTL_DREFH_SDIO_M) >> RTC_CNTL_DREFH_SDIO_S;
|
||||
result.drefm = (sdio_conf_reg & RTC_CNTL_DREFM_SDIO_M) >> RTC_CNTL_DREFM_SDIO_S;
|
||||
result.drefl = (sdio_conf_reg & RTC_CNTL_DREFL_SDIO_M) >> RTC_CNTL_DREFL_SDIO_S;
|
||||
if (sdio_conf_reg & RTC_CNTL_SDIO_FORCE) {
|
||||
// Get configuration from RTC
|
||||
result.force = 1;
|
||||
result.enable = (sdio_conf_reg & RTC_CNTL_XPD_SDIO_REG_M) >> RTC_CNTL_XPD_SDIO_REG_S;
|
||||
result.tieh = (sdio_conf_reg & RTC_CNTL_SDIO_TIEH_M) >> RTC_CNTL_SDIO_TIEH_S;
|
||||
return result;
|
||||
} else {
|
||||
result.force = 0;
|
||||
}
|
||||
|
||||
// Otherwise, VDD_SDIO is controlled by bootstrapping pin
|
||||
uint32_t strap_reg = REG_READ(GPIO_STRAP_REG);
|
||||
result.force = 0;
|
||||
result.tieh = (strap_reg & BIT(5)) ? RTC_VDDSDIO_TIEH_1_8V : RTC_VDDSDIO_TIEH_3_3V;
|
||||
result.enable = 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
void rtc_vddsdio_set_config(rtc_vddsdio_config_t config)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
val |= (config.force << RTC_CNTL_SDIO_FORCE_S);
|
||||
val |= (config.enable << RTC_CNTL_XPD_SDIO_REG_S);
|
||||
val |= (config.drefh << RTC_CNTL_DREFH_SDIO_S);
|
||||
val |= (config.drefm << RTC_CNTL_DREFM_SDIO_S);
|
||||
val |= (config.drefl << RTC_CNTL_DREFL_SDIO_S);
|
||||
val |= (config.tieh << RTC_CNTL_SDIO_TIEH_S);
|
||||
val |= RTC_CNTL_SDIO_PD_EN;
|
||||
REG_WRITE(RTC_CNTL_SDIO_CONF_REG, val);
|
||||
}
|
67
components/esp_hw_support/port/esp32c3/rtc_pm.c
Normal file
67
components/esp_hw_support/port/esp32c3/rtc_pm.c
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright 2020 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.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/apb_ctrl_reg.h"
|
||||
|
||||
typedef enum {
|
||||
PM_LIGHT_SLEEP = BIT(2), /*!< WiFi PD, memory in light sleep */
|
||||
} pm_sleep_mode_t;
|
||||
|
||||
typedef enum {
|
||||
PM_SW_NOREJECT = 0,
|
||||
PM_SW_REJECT = 1
|
||||
} pm_sw_reject_t;
|
||||
|
||||
|
||||
/* These MAC-related functions are defined in the closed source part of
|
||||
* RTC library
|
||||
*/
|
||||
extern void pm_mac_init(void);
|
||||
extern int pm_check_mac_idle(void);
|
||||
extern void pm_mac_deinit(void);
|
||||
|
||||
/* This sleep-related function is called from the closed source part of RTC
|
||||
* library.
|
||||
*/
|
||||
pm_sw_reject_t pm_set_sleep_mode(pm_sleep_mode_t sleep_mode, void(*pmac_save_params)(void))
|
||||
{
|
||||
(void) pmac_save_params; /* unused */
|
||||
|
||||
pm_mac_deinit();
|
||||
if (pm_check_mac_idle()) {
|
||||
pm_mac_init();
|
||||
return PM_SW_REJECT;
|
||||
}
|
||||
|
||||
rtc_sleep_config_t cfg = { 0 };
|
||||
|
||||
switch (sleep_mode) {
|
||||
case PM_LIGHT_SLEEP:
|
||||
cfg.wifi_pd_en = 1;
|
||||
cfg.dig_dbias_wak = 4;
|
||||
cfg.dig_dbias_slp = 0;
|
||||
cfg.rtc_dbias_wak = 0;
|
||||
cfg.rtc_dbias_slp = 0;
|
||||
rtc_sleep_init(cfg);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0 && "unsupported sleep mode");
|
||||
}
|
||||
return PM_SW_NOREJECT;
|
||||
}
|
69
components/esp_hw_support/port/esp32c3/rtc_sleep.c
Normal file
69
components/esp_hw_support/port/esp32c3/rtc_sleep.c
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright 2020 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.
|
||||
|
||||
#include <stdint.h>
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/apb_ctrl_reg.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/i2s_reg.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "esp32c3/rom/ets_sys.h"
|
||||
|
||||
/**
|
||||
* Configure whether certain peripherals are powered down in deep sleep
|
||||
* @param cfg power down flags as rtc_sleep_pd_config_t structure
|
||||
*/
|
||||
void rtc_sleep_pd(rtc_sleep_pd_config_t cfg)
|
||||
{
|
||||
abort(); // TODO ESP32-C3 IDF-2106
|
||||
}
|
||||
|
||||
void rtc_sleep_init(rtc_sleep_config_t cfg)
|
||||
{
|
||||
abort(); // TODO ESP32-C3 IDF-2106
|
||||
}
|
||||
|
||||
void rtc_sleep_set_wakeup_time(uint64_t t)
|
||||
{
|
||||
WRITE_PERI_REG(RTC_CNTL_SLP_TIMER0_REG, t & UINT32_MAX);
|
||||
WRITE_PERI_REG(RTC_CNTL_SLP_TIMER1_REG, t >> 32);
|
||||
}
|
||||
|
||||
uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu)
|
||||
{
|
||||
REG_SET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA, wakeup_opt);
|
||||
REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_SLEEP_REJECT_ENA, reject_opt);
|
||||
|
||||
/* Start entry into sleep mode */
|
||||
SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SLEEP_EN);
|
||||
|
||||
while (GET_PERI_REG_MASK(RTC_CNTL_INT_RAW_REG,
|
||||
RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW) == 0) {
|
||||
;
|
||||
}
|
||||
/* In deep sleep mode, we never get here */
|
||||
uint32_t reject = REG_GET_FIELD(RTC_CNTL_INT_RAW_REG, RTC_CNTL_SLP_REJECT_INT_RAW);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG,
|
||||
RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR);
|
||||
|
||||
/* restore config if it is a light sleep */
|
||||
if (lslp_mem_inf_fpu) {
|
||||
rtc_sleep_pd_config_t pd_cfg = RTC_SLEEP_PD_CONFIG_ALL(0);
|
||||
rtc_sleep_pd(pd_cfg);
|
||||
}
|
||||
return reject;
|
||||
}
|
181
components/esp_hw_support/port/esp32c3/rtc_time.c
Normal file
181
components/esp_hw_support/port/esp32c3/rtc_time.c
Normal file
@@ -0,0 +1,181 @@
|
||||
// Copyright 2020 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.
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp32c3/rom/ets_sys.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
/* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
|
||||
* This feature counts the number of XTAL clock cycles within a given number of
|
||||
* RTC_SLOW_CLK cycles.
|
||||
*
|
||||
* Slow clock calibration feature has two modes of operation: one-off and cycling.
|
||||
* In cycling mode (which is enabled by default on SoC reset), counting of XTAL
|
||||
* cycles within RTC_SLOW_CLK cycle is done continuously. Cycling mode is enabled
|
||||
* using TIMG_RTC_CALI_START_CYCLING bit. In one-off mode counting is performed
|
||||
* once, and TIMG_RTC_CALI_RDY bit is set when counting is done. One-off mode is
|
||||
* enabled using TIMG_RTC_CALI_START bit.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Clock calibration function used by rtc_clk_cal and rtc_clk_cal_ratio
|
||||
* @param cal_clk which clock to calibrate
|
||||
* @param slowclk_cycles number of slow clock cycles to count
|
||||
* @return number of XTAL clock cycles within the given number of slow clock cycles
|
||||
*/
|
||||
uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
{
|
||||
/* On ESP32S3, choosing RTC_CAL_RTC_MUX results in calibration of
|
||||
* the 90k RTC clock regardless of the currenlty selected SLOW_CLK.
|
||||
* On the ESP32, it used the currently selected SLOW_CLK.
|
||||
* The following code emulates ESP32 behavior:
|
||||
*/
|
||||
if (cal_clk == RTC_CAL_RTC_MUX) {
|
||||
rtc_slow_freq_t slow_freq = rtc_clk_slow_freq_get();
|
||||
if (slow_freq == RTC_SLOW_FREQ_32K_XTAL) {
|
||||
cal_clk = RTC_CAL_32K_XTAL;
|
||||
} else if (slow_freq == RTC_SLOW_FREQ_8MD256) {
|
||||
cal_clk = RTC_CAL_8MD256;
|
||||
}
|
||||
}
|
||||
/* Enable requested clock (150k clock is always on) */
|
||||
int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN);
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) {
|
||||
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, 1);
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_8MD256) {
|
||||
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN);
|
||||
}
|
||||
/* Prepare calibration */
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cal_clk);
|
||||
/* There may be another calibration process already running during we call this function,
|
||||
* so we should wait the last process is done.
|
||||
*/
|
||||
if (!GET_PERI_REG_MASK(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT)) {
|
||||
if (GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING)) {
|
||||
while (!GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY));
|
||||
}
|
||||
}
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles);
|
||||
/* Figure out how long to wait for calibration to finish */
|
||||
|
||||
/* Set timeout reg and expect time delay*/
|
||||
uint32_t expected_freq;
|
||||
if (cal_clk == RTC_CAL_32K_XTAL) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_X32K_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = RTC_SLOW_CLK_FREQ_32K;
|
||||
} else if (cal_clk == RTC_CAL_8MD256) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_8MD256_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = RTC_SLOW_CLK_FREQ_8MD256;
|
||||
} else {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_150K_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = RTC_SLOW_CLK_FREQ_90K;
|
||||
}
|
||||
uint32_t us_time_estimate = (uint32_t) (((uint64_t) slowclk_cycles) * MHZ / expected_freq);
|
||||
/* Start calibration */
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
|
||||
SET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
|
||||
|
||||
/* Wait for calibration to finish up to another us_time_estimate */
|
||||
esp_rom_delay_us(us_time_estimate);
|
||||
uint32_t cal_val;
|
||||
while (true) {
|
||||
if (GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY)) {
|
||||
cal_val = REG_GET_FIELD(TIMG_RTCCALICFG1_REG(0), TIMG_RTC_CALI_VALUE);
|
||||
break;
|
||||
}
|
||||
if (GET_PERI_REG_MASK(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT)) {
|
||||
cal_val = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
|
||||
|
||||
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, dig_32k_xtal_state);
|
||||
|
||||
if (cal_clk == RTC_CAL_8MD256) {
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN);
|
||||
}
|
||||
|
||||
return cal_val;
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
{
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
uint64_t ratio_64 = ((xtal_cycles << RTC_CLK_CAL_FRACT)) / slowclk_cycles;
|
||||
uint32_t ratio = (uint32_t)(ratio_64 & UINT32_MAX);
|
||||
return ratio;
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
{
|
||||
rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
uint64_t divider = ((uint64_t)xtal_freq) * slowclk_cycles;
|
||||
uint64_t period_64 = ((xtal_cycles << RTC_CLK_CAL_FRACT) + divider / 2 - 1) / divider;
|
||||
uint32_t period = (uint32_t)(period_64 & UINT32_MAX);
|
||||
return period;
|
||||
}
|
||||
|
||||
uint64_t rtc_time_us_to_slowclk(uint64_t time_in_us, uint32_t period)
|
||||
{
|
||||
/* Overflow will happen in this function if time_in_us >= 2^45, which is about 400 days.
|
||||
* TODO: fix overflow.
|
||||
*/
|
||||
return (time_in_us << RTC_CLK_CAL_FRACT) / period;
|
||||
}
|
||||
|
||||
uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period)
|
||||
{
|
||||
return (rtc_cycles * period) >> RTC_CLK_CAL_FRACT;
|
||||
}
|
||||
|
||||
uint64_t rtc_time_get(void)
|
||||
{
|
||||
SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE);
|
||||
uint64_t t = READ_PERI_REG(RTC_CNTL_TIME0_REG);
|
||||
t |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32;
|
||||
return t;
|
||||
}
|
||||
|
||||
uint64_t rtc_light_slp_time_get(void)
|
||||
{
|
||||
uint64_t t_wake = READ_PERI_REG(RTC_CNTL_TIME_LOW0_REG);
|
||||
t_wake |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME_HIGH0_REG)) << 32;
|
||||
uint64_t t_slp = READ_PERI_REG(RTC_CNTL_TIME_LOW1_REG);
|
||||
t_slp |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME_HIGH1_REG)) << 32;
|
||||
return (t_wake - t_slp);
|
||||
}
|
||||
|
||||
uint64_t rtc_deep_slp_time_get(void)
|
||||
{
|
||||
uint64_t t_slp = READ_PERI_REG(RTC_CNTL_TIME_LOW1_REG);
|
||||
t_slp |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME_HIGH1_REG)) << 32;
|
||||
uint64_t t_wake = rtc_time_get();
|
||||
return (t_wake - t_slp);
|
||||
}
|
||||
|
||||
void rtc_clk_wait_for_slow_cycle(void) //This function may not by useful any more
|
||||
{
|
||||
SET_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_SLOW_CLK_NEXT_EDGE);
|
||||
while (GET_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_SLOW_CLK_NEXT_EDGE)) {
|
||||
esp_rom_delay_us(1);
|
||||
}
|
||||
}
|
91
components/esp_hw_support/port/esp32c3/soc_memory_layout.c
Normal file
91
components/esp_hw_support/port/esp32c3/soc_memory_layout.c
Normal file
@@ -0,0 +1,91 @@
|
||||
// Copyright 2020 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 BOOTLOADER_BUILD
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "esp_attr.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "esp_heap_caps.h"
|
||||
|
||||
/**
|
||||
* @brief Memory type descriptors. These describe the capabilities of a type of memory in the SoC.
|
||||
* Each type of memory map consists of one or more regions in the address space.
|
||||
* Each type contains an array of prioritized capabilities.
|
||||
* Types with later entries are only taken if earlier ones can't fulfill the memory request.
|
||||
*
|
||||
* - For a normal malloc (MALLOC_CAP_DEFAULT), give away the DRAM-only memory first, then pass off any dual-use IRAM regions, finally eat into the application memory.
|
||||
* - For a malloc where 32-bit-aligned-only access is okay, first allocate IRAM, then DRAM, finally application IRAM.
|
||||
* - Application mallocs (PIDx) will allocate IRAM first, if possible, then DRAM.
|
||||
* - Most other malloc caps only fit in one region anyway.
|
||||
*
|
||||
*/
|
||||
const soc_memory_type_desc_t soc_memory_types[] = {
|
||||
// Type 0: DRAM
|
||||
{ "DRAM", { MALLOC_CAP_8BIT | MALLOC_CAP_DEFAULT, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA | MALLOC_CAP_32BIT, 0 }, false, false},
|
||||
// Type 1: DRAM used for startup stacks
|
||||
{ "STACK/DRAM", { MALLOC_CAP_8BIT | MALLOC_CAP_DEFAULT, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA | MALLOC_CAP_32BIT, MALLOC_CAP_RETENTION }, false, true},
|
||||
// Type 2: DRAM which has an alias on the I-port
|
||||
{ "D/IRAM", { 0, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL | MALLOC_CAP_DEFAULT, MALLOC_CAP_32BIT | MALLOC_CAP_EXEC }, true, false},
|
||||
// Type 3: IRAM
|
||||
{ "IRAM", { MALLOC_CAP_EXEC | MALLOC_CAP_32BIT | MALLOC_CAP_INTERNAL, 0, 0 }, false, false},
|
||||
{ "FAKEDRAM", { MALLOC_CAP_8BIT|MALLOC_CAP_DEFAULT, MALLOC_CAP_INTERNAL|MALLOC_CAP_32BIT, 0 }, false, false},
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ESP32C3_MEMPROT_FEATURE //TODO ESP32-C3 IDF-2092
|
||||
#define SOC_MEMORY_TYPE_DEFAULT 0
|
||||
#else
|
||||
#define SOC_MEMORY_TYPE_DEFAULT 2
|
||||
#endif
|
||||
|
||||
const size_t soc_memory_type_count = sizeof(soc_memory_types) / sizeof(soc_memory_type_desc_t);
|
||||
|
||||
/**
|
||||
* @brief Region descriptors. These describe all regions of memory available, and map them to a type in the above type.
|
||||
*
|
||||
* @note Because of requirements in the coalescing code which merges adjacent regions,
|
||||
* this list should always be sorted from low to high by start address.
|
||||
*
|
||||
*/
|
||||
const soc_memory_region_t soc_memory_regions[] = {
|
||||
{ 0x3FC80000, 0x20000, SOC_MEMORY_TYPE_DEFAULT, 0x40380000}, //Block 4, can be remapped to ROM, can be used as trace memory
|
||||
{ 0x3FCA0000, 0x20000, SOC_MEMORY_TYPE_DEFAULT, 0x403A0000}, //Block 5, can be remapped to ROM, can be used as trace memory
|
||||
{ 0x3FCC0000, 0x20000, 1, 0x403C0000}, //Block 9, can be used as trace memory
|
||||
#ifdef CONFIG_ESP32C3_ALLOW_RTC_FAST_MEM_AS_HEAP
|
||||
{ 0x50000000, 0x2000, 5, 0}, //Fast RTC memory
|
||||
#endif
|
||||
};
|
||||
|
||||
const size_t soc_memory_region_count = sizeof(soc_memory_regions) / sizeof(soc_memory_region_t);
|
||||
|
||||
|
||||
extern int _data_start, _heap_start, _iram_start, _iram_end;
|
||||
|
||||
/**
|
||||
* Reserved memory regions.
|
||||
* These are removed from the soc_memory_regions array when heaps are created.
|
||||
*
|
||||
*/
|
||||
|
||||
// Static data region. DRAM used by data+bss and possibly rodata
|
||||
SOC_RESERVE_MEMORY_REGION((intptr_t)&_data_start, (intptr_t)&_heap_start, dram_data);
|
||||
|
||||
// Target has a big D/IRAM region, the part used by code is reserved
|
||||
// The address of the D/I bus are in the same order, directly shift IRAM address to get reserved DRAM address
|
||||
#define I_D_OFFSET (SOC_DIRAM_IRAM_LOW - SOC_DIRAM_DRAM_LOW)
|
||||
SOC_RESERVE_MEMORY_REGION((intptr_t)&_iram_start - I_D_OFFSET, (intptr_t)&_iram_end - I_D_OFFSET, iram_code);
|
||||
|
||||
#endif // BOOTLOADER_BUILD
|
Reference in New Issue
Block a user