mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
ce1fe776cf
Some ESP32 boards (like my SparkFun ESP32 Thing) have a main clock crystal that runs at 26MHz, not 40MHz. RIOT appears to assume 40MHz. The mismatch causes the UART to not sync properly, resulting in garbage written to the terminal instead of log output. I’ve added: * A new board configuration constant ESP32_XTAL_FREQ that defaults to 40, but can be overridden by a board def or at build time to force a specific value (i.e. 26). * Some code spliced into system_clk_init() to check this constant and call rtc_clk_init() to set the correct frequency. * A copy of the rtf_clk_init() function from the ESP-IDF sources. Fixes #10272
593 lines
17 KiB
C
593 lines
17 KiB
C
// 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.
|
|
|
|
/* PLEASE NOTE: This file is a collection of required functions from
|
|
different files in ESP-IDF */
|
|
|
|
#define ENABLE_DEBUG 0
|
|
#include "debug.h"
|
|
#include "esp_common.h"
|
|
#include "log.h"
|
|
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include <sys/time.h>
|
|
|
|
#include "esp_attr.h"
|
|
#include "sdk_conf.h"
|
|
|
|
#include "driver/periph_ctrl.h"
|
|
#include "esp32/esp_spiram.h"
|
|
#include "esp32/esp_system.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "heap/esp_heap_caps_init.h"
|
|
#include "log/esp_log.h"
|
|
#include "periph/hwrng.h"
|
|
#include "rom/rtc.h"
|
|
#include "rom/cache.h"
|
|
#include "rom/efuse.h"
|
|
#include "rom/uart.h"
|
|
#include "soc/cpu.h"
|
|
#include "soc/efuse_reg.h"
|
|
#include "soc/gpio_reg.h"
|
|
#include "soc/rtc.h"
|
|
#include "soc/rtc_cntl_reg.h"
|
|
#include "soc/timer_group_reg.h"
|
|
#include "soc/timer_group_struct.h"
|
|
#include "xtensa/core-macros.h"
|
|
#include "xtensa/xtensa_api.h"
|
|
|
|
#include "syscalls.h"
|
|
|
|
/* This function is not part on newlib API, it is defined in libc/stdio/local.h
|
|
* There is no nice way to get __cleanup member populated while avoiding __sinit,
|
|
* so extern declaration is used here.
|
|
*/
|
|
extern void _cleanup_r(struct _reent* r);
|
|
|
|
/**
|
|
* This is the replacement for newlib's _REENT_INIT_PTR and __sinit.
|
|
* The problem with __sinit is that it allocates three FILE structures
|
|
* (stdin, stdout, stderr). Having individual standard streams for each task
|
|
* is a bit too much on a small embedded system. So we point streams
|
|
* to the streams of the global struct _reent, which are initialized in
|
|
* startup code.
|
|
*/
|
|
void IRAM_ATTR esp_reent_init(struct _reent* r)
|
|
{
|
|
memset(r, 0, sizeof(*r));
|
|
r->_stdout = _GLOBAL_REENT->_stdout;
|
|
r->_stderr = _GLOBAL_REENT->_stderr;
|
|
r->_stdin = _GLOBAL_REENT->_stdin;
|
|
r->__cleanup = &_cleanup_r;
|
|
r->__sdidinit = 1;
|
|
r->__sglue._next = NULL;
|
|
r->__sglue._niobs = 0;
|
|
r->__sglue._iobs = NULL;
|
|
r->_current_locale = "C";
|
|
}
|
|
|
|
/* source: /path/to/esp-idf/components/esp32/panic.c */
|
|
void IRAM_ATTR esp_panic_wdt_stop (void)
|
|
{
|
|
WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, RTC_CNTL_WDT_WKEY_VALUE);
|
|
WRITE_PERI_REG(RTC_CNTL_WDTFEED_REG, 1);
|
|
REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_STG0, RTC_WDT_STG_SEL_OFF);
|
|
REG_CLR_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_EN);
|
|
WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, 0);
|
|
}
|
|
|
|
/* source: /path/to/esp-idf/components/esp32/panic.c */
|
|
void _esp_error_check_failed(esp_err_t rc, const char *file, int line,
|
|
const char *function, const char *expression)
|
|
{
|
|
ets_printf("ESP_ERROR_CHECK failed: esp_err_t 0x%x at 0x%08x\n",
|
|
rc, (intptr_t)__builtin_return_address(0) - 3);
|
|
#if 0 /* TODO */
|
|
if (spi_flash_cache_enabled()) { /* strings may be in flash cache */
|
|
ets_printf("file: \"%s\" line %d\nfunc: %s\nexpression: %s\n",
|
|
file, line, function, expression);
|
|
}
|
|
invoke_abort();
|
|
#endif
|
|
exit(1);
|
|
|
|
while (1) {}
|
|
}
|
|
|
|
/*
|
|
* provided by: /path/to/esp-idf/component/log/log.c
|
|
*/
|
|
uint32_t IRAM_ATTR esp_log_timestamp(void)
|
|
{
|
|
return system_get_time() / USEC_PER_MSEC;
|
|
}
|
|
|
|
/*
|
|
* provided by: /path/to/esp-idf/component/log/log.c
|
|
*/
|
|
void IRAM_ATTR esp_log_write(esp_log_level_t level,
|
|
const char* tag, const char* format, ...)
|
|
{
|
|
if ((unsigned)level > CONFIG_LOG_DEFAULT_LEVEL) {
|
|
return;
|
|
}
|
|
|
|
char _printf_buf[PRINTF_BUFSIZ];
|
|
|
|
const char* prefix = (strchr (format, ':') + 2);
|
|
|
|
char lc = 'U';
|
|
switch (level) {
|
|
case LOG_NONE : return;
|
|
case LOG_ERROR : lc = 'E'; break;
|
|
case LOG_WARNING: lc = 'W'; break;
|
|
case LOG_INFO : lc = 'I'; break;
|
|
case LOG_DEBUG : lc = 'D'; break;
|
|
case LOG_ALL : lc = 'V'; break;
|
|
}
|
|
#ifdef LOG_TAG_IN_BRACKETS
|
|
ets_printf("%c (%u) [%10s]: ", lc, system_get_time_ms(), tag);
|
|
#else
|
|
ets_printf("%c (%u) %10s: ", lc, system_get_time_ms(), tag);
|
|
#endif
|
|
|
|
va_list arglist;
|
|
va_start(arglist, format);
|
|
|
|
/* remove time and tag argument from argument list */
|
|
va_arg(arglist, unsigned);
|
|
va_arg(arglist, const char*);
|
|
|
|
int ret = vsnprintf(_printf_buf, PRINTF_BUFSIZ, prefix, arglist);
|
|
|
|
if (ret > 0) {
|
|
ets_printf (_printf_buf);
|
|
}
|
|
|
|
va_end(arglist);
|
|
}
|
|
|
|
/*
|
|
* provided by: /path/to/esp-idf/component/log/log.c
|
|
*/
|
|
void esp_log_level_set(const char* tag, esp_log_level_t level)
|
|
{
|
|
/* TODO implementation */
|
|
}
|
|
|
|
static bool _spi_ram_initialized = false;
|
|
|
|
/*
|
|
* source: /path/to/esp-idf/component/esp32/cpu_start.c
|
|
*/
|
|
void spi_ram_init(void)
|
|
{
|
|
_spi_ram_initialized = false;
|
|
|
|
#if CONFIG_SPIRAM_SUPPORT
|
|
esp_spiram_init_cache();
|
|
if (esp_spiram_init() == ESP_OK) {
|
|
_spi_ram_initialized = true;
|
|
}
|
|
else {
|
|
ets_printf("Failed to init external SPI RAM\n");
|
|
_spi_ram_initialized = false;
|
|
}
|
|
#else
|
|
ets_printf("External SPI RAM functions not enabled\n");
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* source: /path/to/esp-idf/component/esp32/cpu_start.c
|
|
*/
|
|
void spi_ram_heap_init(void)
|
|
{
|
|
#if CONFIG_SPIRAM_SUPPORT
|
|
|
|
#if CONFIG_SPIRAM_MEMTEST
|
|
if (!esp_spiram_test()) {
|
|
return;
|
|
}
|
|
#endif /* CONFIG_SPIRAM_MEMTEST */
|
|
|
|
#if CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC
|
|
esp_err_t r=esp_spiram_add_to_heapalloc();
|
|
if (r != ESP_OK) {
|
|
ets_printf("External SPI RAM could not be added to heap!\n");
|
|
abort();
|
|
}
|
|
|
|
#if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL
|
|
r=esp_spiram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL);
|
|
if (r != ESP_OK) {
|
|
ets_printf("Could not reserve internal/DMA pool!\n");
|
|
abort();
|
|
}
|
|
#endif /* CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL */
|
|
|
|
#if CONFIG_SPIRAM_USE_MALLOC
|
|
heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL);
|
|
#endif /* CONFIG_SPIRAM_USE_MALLOC */
|
|
|
|
#endif /* CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC */
|
|
|
|
#else /* CONFIG_SPIRAM_SUPPORT */
|
|
ets_printf("External SPI RAM functions not enabled\n");
|
|
#endif /* CONFIG_SPIRAM_SUPPORT */
|
|
}
|
|
|
|
static const char* TAG = "system_api";
|
|
static uint8_t base_mac_addr[6] = { 0 };
|
|
|
|
/*
|
|
* source: /path/to/esp-idf/component/esp32/system_api.c
|
|
*/
|
|
esp_err_t esp_efuse_mac_get_default(uint8_t* mac)
|
|
{
|
|
uint32_t mac_low;
|
|
uint32_t mac_high;
|
|
uint8_t efuse_crc;
|
|
uint8_t calc_crc;
|
|
|
|
mac_low = REG_READ(EFUSE_BLK0_RDATA1_REG);
|
|
mac_high = REG_READ(EFUSE_BLK0_RDATA2_REG);
|
|
|
|
mac[0] = mac_high >> 8;
|
|
mac[1] = mac_high;
|
|
mac[2] = mac_low >> 24;
|
|
mac[3] = mac_low >> 16;
|
|
mac[4] = mac_low >> 8;
|
|
mac[5] = mac_low;
|
|
|
|
efuse_crc = mac_high >> 16;
|
|
|
|
calc_crc = esp_crc8(mac, 6);
|
|
|
|
if (efuse_crc != calc_crc) {
|
|
// Small range of MAC addresses are accepted even if CRC is invalid.
|
|
// These addresses are reserved for Espressif internal use.
|
|
if ((mac_high & 0xFFFF) == 0x18fe) {
|
|
if ((mac_low >= 0x346a85c7) && (mac_low <= 0x346a85f8)) {
|
|
return ESP_OK;
|
|
}
|
|
} else {
|
|
ESP_LOGE(TAG, "Base MAC address from BLK0 of EFUSE CRC error, efuse_crc = 0x%02x; calc_crc = 0x%02x", efuse_crc, calc_crc);
|
|
abort();
|
|
}
|
|
}
|
|
return ESP_OK;
|
|
}
|
|
|
|
/*
|
|
* source: /path/to/esp-idf/component/esp32/system_api.c
|
|
*/
|
|
esp_err_t esp_derive_mac(uint8_t* local_mac, const uint8_t* universal_mac)
|
|
{
|
|
uint8_t idx;
|
|
|
|
if (local_mac == NULL || universal_mac == NULL) {
|
|
ESP_LOGE(TAG, "mac address param is NULL");
|
|
return ESP_ERR_INVALID_ARG;
|
|
}
|
|
|
|
memcpy(local_mac, universal_mac, 6);
|
|
for (idx = 0; idx < 64; idx++) {
|
|
local_mac[0] = universal_mac[0] | 0x02;
|
|
local_mac[0] ^= idx << 2;
|
|
|
|
if (memcmp(local_mac, universal_mac, 6)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
/*
|
|
* source: /path/to/esp-idf/component/esp32/system_api.c
|
|
*/
|
|
esp_err_t esp_base_mac_addr_get(uint8_t *mac)
|
|
{
|
|
uint8_t null_mac[6] = {0};
|
|
|
|
if (memcmp(base_mac_addr, null_mac, 6) == 0) {
|
|
ESP_LOGI(TAG, "Base MAC address is not set, read default base MAC address from BLK0 of EFUSE");
|
|
return ESP_ERR_INVALID_MAC;
|
|
}
|
|
|
|
memcpy(mac, base_mac_addr, 6);
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
/*
|
|
* source: /path/to/esp-idf/component/esp32/system_api.c
|
|
*/
|
|
esp_err_t esp_read_mac(uint8_t* mac, esp_mac_type_t type)
|
|
{
|
|
uint8_t efuse_mac[6];
|
|
|
|
if (mac == NULL) {
|
|
ESP_LOGE(TAG, "mac address param is NULL");
|
|
return ESP_ERR_INVALID_ARG;
|
|
}
|
|
|
|
if (type < ESP_MAC_WIFI_STA || type > ESP_MAC_ETH) {
|
|
ESP_LOGE(TAG, "mac type is incorrect");
|
|
return ESP_ERR_INVALID_ARG;
|
|
}
|
|
|
|
_Static_assert(UNIVERSAL_MAC_ADDR_NUM == FOUR_UNIVERSAL_MAC_ADDR \
|
|
|| UNIVERSAL_MAC_ADDR_NUM == TWO_UNIVERSAL_MAC_ADDR, \
|
|
"incorrect NUM_MAC_ADDRESS_FROM_EFUSE value");
|
|
|
|
if (esp_base_mac_addr_get(efuse_mac) != ESP_OK) {
|
|
esp_efuse_mac_get_default(efuse_mac);
|
|
}
|
|
|
|
switch (type) {
|
|
case ESP_MAC_WIFI_STA:
|
|
memcpy(mac, efuse_mac, 6);
|
|
break;
|
|
case ESP_MAC_WIFI_SOFTAP:
|
|
if (UNIVERSAL_MAC_ADDR_NUM == FOUR_UNIVERSAL_MAC_ADDR) {
|
|
memcpy(mac, efuse_mac, 6);
|
|
mac[5] += 1;
|
|
}
|
|
else if (UNIVERSAL_MAC_ADDR_NUM == TWO_UNIVERSAL_MAC_ADDR) {
|
|
esp_derive_mac(mac, efuse_mac);
|
|
}
|
|
break;
|
|
case ESP_MAC_BT:
|
|
memcpy(mac, efuse_mac, 6);
|
|
if (UNIVERSAL_MAC_ADDR_NUM == FOUR_UNIVERSAL_MAC_ADDR) {
|
|
mac[5] += 2;
|
|
}
|
|
else if (UNIVERSAL_MAC_ADDR_NUM == TWO_UNIVERSAL_MAC_ADDR) {
|
|
mac[5] += 1;
|
|
}
|
|
break;
|
|
case ESP_MAC_ETH:
|
|
if (UNIVERSAL_MAC_ADDR_NUM == FOUR_UNIVERSAL_MAC_ADDR) {
|
|
memcpy(mac, efuse_mac, 6);
|
|
mac[5] += 3;
|
|
}
|
|
else if (UNIVERSAL_MAC_ADDR_NUM == TWO_UNIVERSAL_MAC_ADDR) {
|
|
efuse_mac[5] += 1;
|
|
esp_derive_mac(mac, efuse_mac);
|
|
}
|
|
break;
|
|
default:
|
|
ESP_LOGW(TAG, "incorrect mac type");
|
|
break;
|
|
}
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
/*
|
|
* source: /path/to/esp-idf/component/esp32/system_api.c
|
|
*/
|
|
/* "inner" restart function for after RTOS, interrupts & anything else on this
|
|
* core are already stopped. Stalls other core, resets hardware,
|
|
* triggers restart.
|
|
*/
|
|
void IRAM_ATTR esp_restart_noos(void)
|
|
{
|
|
// Disable interrupts
|
|
xt_ints_off(0xFFFFFFFF);
|
|
|
|
// Enable RTC watchdog for 1 second
|
|
REG_WRITE(RTC_CNTL_WDTWPROTECT_REG, RTC_CNTL_WDT_WKEY_VALUE);
|
|
REG_WRITE(RTC_CNTL_WDTCONFIG0_REG,
|
|
RTC_CNTL_WDT_FLASHBOOT_MOD_EN_M |
|
|
(RTC_WDT_STG_SEL_RESET_SYSTEM << RTC_CNTL_WDT_STG0_S) |
|
|
(RTC_WDT_STG_SEL_RESET_RTC << RTC_CNTL_WDT_STG1_S) |
|
|
(1 << RTC_CNTL_WDT_SYS_RESET_LENGTH_S) |
|
|
(1 << RTC_CNTL_WDT_CPU_RESET_LENGTH_S) );
|
|
REG_WRITE(RTC_CNTL_WDTCONFIG1_REG, rtc_clk_slow_freq_get_hz() * 1);
|
|
|
|
// Reset and stall the other CPU.
|
|
// CPU must be reset before stalling, in case it was running a s32c1i
|
|
// instruction. This would cause memory pool to be locked by arbiter
|
|
// to the stalled CPU, preventing current CPU from accessing this pool.
|
|
const uint32_t core_id = 0;
|
|
const uint32_t other_core_id = (core_id == 0) ? 1 : 0;
|
|
esp_cpu_reset(other_core_id);
|
|
esp_cpu_stall(other_core_id);
|
|
|
|
// Other core is now stalled, can access DPORT registers directly
|
|
esp_dport_access_int_abort();
|
|
|
|
// Disable TG0/TG1 watchdogs
|
|
TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
|
|
TIMERG0.wdt_config0.en = 0;
|
|
TIMERG0.wdt_wprotect=0;
|
|
TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
|
|
TIMERG1.wdt_config0.en = 0;
|
|
TIMERG1.wdt_wprotect=0;
|
|
|
|
// Flush any data left in UART FIFOs
|
|
uart_tx_wait_idle(0);
|
|
uart_tx_wait_idle(1);
|
|
uart_tx_wait_idle(2);
|
|
|
|
// Disable cache
|
|
Cache_Read_Disable(0);
|
|
Cache_Read_Disable(1);
|
|
|
|
// 2nd stage bootloader reconfigures SPI flash signals.
|
|
// Reset them to the defaults expected by ROM.
|
|
WRITE_PERI_REG(GPIO_FUNC0_IN_SEL_CFG_REG, 0x30);
|
|
WRITE_PERI_REG(GPIO_FUNC1_IN_SEL_CFG_REG, 0x30);
|
|
WRITE_PERI_REG(GPIO_FUNC2_IN_SEL_CFG_REG, 0x30);
|
|
WRITE_PERI_REG(GPIO_FUNC3_IN_SEL_CFG_REG, 0x30);
|
|
WRITE_PERI_REG(GPIO_FUNC4_IN_SEL_CFG_REG, 0x30);
|
|
WRITE_PERI_REG(GPIO_FUNC5_IN_SEL_CFG_REG, 0x30);
|
|
|
|
// Reset wifi/bluetooth/ethernet/sdio (bb/mac)
|
|
DPORT_SET_PERI_REG_MASK(DPORT_CORE_RST_EN_REG,
|
|
DPORT_BB_RST | DPORT_FE_RST | DPORT_MAC_RST |
|
|
DPORT_BT_RST | DPORT_BTMAC_RST | DPORT_SDIO_RST |
|
|
DPORT_SDIO_HOST_RST | DPORT_EMAC_RST | DPORT_MACPWR_RST |
|
|
DPORT_RW_BTMAC_RST | DPORT_RW_BTLP_RST);
|
|
DPORT_REG_WRITE(DPORT_CORE_RST_EN_REG, 0);
|
|
|
|
// Reset timer/spi/uart
|
|
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG,
|
|
DPORT_TIMERS_RST | DPORT_SPI_RST_1 | DPORT_UART_RST);
|
|
DPORT_REG_WRITE(DPORT_PERIP_RST_EN_REG, 0);
|
|
|
|
// Set CPU back to XTAL source, no PLL, same as hard reset
|
|
rtc_clk_cpu_freq_set(RTC_CPU_FREQ_XTAL);
|
|
|
|
// Clear entry point for APP CPU
|
|
DPORT_REG_WRITE(DPORT_APPCPU_CTRL_D_REG, 0);
|
|
|
|
// Reset CPUs
|
|
if (core_id == 0) {
|
|
// Running on PRO CPU: APP CPU is stalled. Can reset both CPUs.
|
|
esp_cpu_reset(1);
|
|
esp_cpu_reset(0);
|
|
} else {
|
|
// Running on APP CPU: need to reset PRO CPU and unstall it,
|
|
// then reset APP CPU
|
|
esp_cpu_reset(0);
|
|
esp_cpu_unstall(0);
|
|
esp_cpu_reset(1);
|
|
}
|
|
while(true) {
|
|
;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* source: /path/to/esp-idf/components/wpa_supplicant/port/os_xtensa.c
|
|
*/
|
|
typedef long os_time_t;
|
|
struct os_time {
|
|
os_time_t sec;
|
|
os_time_t usec;
|
|
};
|
|
|
|
int os_get_time(struct os_time *t)
|
|
{
|
|
return gettimeofday((struct timeval*) t, NULL);
|
|
}
|
|
|
|
/*
|
|
* source: /path/to/esp-idf/components/wpa_supplicant/port/os_xtensa.c
|
|
*/
|
|
unsigned long os_random(void)
|
|
{
|
|
return esp_random();
|
|
}
|
|
|
|
/*
|
|
* provided by: /path/to/esp-idf/components/wpa_supplicant/port/os_xtensa.c
|
|
*/
|
|
int os_get_random(unsigned char *buf, size_t len)
|
|
{
|
|
hwrng_read((void*)buf, len);
|
|
return 0;
|
|
}
|
|
|
|
uint32_t esp_random(void)
|
|
{
|
|
uint32_t tmp;
|
|
hwrng_read((void*)&tmp, sizeof(uint32_t));
|
|
return tmp;
|
|
}
|
|
|
|
/*
|
|
* source: /path/to/esp-idf/components/lwip/netif/ethernet.c
|
|
*/
|
|
#define ETH_HWADDR_LEN 6
|
|
|
|
struct eth_addr {
|
|
uint8_t addr[ETH_HWADDR_LEN];
|
|
};
|
|
|
|
#ifndef MODULE_LWIP_ETHERNET
|
|
const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
|
|
#endif
|
|
|
|
#if MODULE_ESP_WIFI_ANY
|
|
/*
|
|
* source: /path/to/esp-idf/components/smartconfig_ack.c
|
|
*/
|
|
#include "esp_smartconfig.h"
|
|
#include "smartconfig_ack.h"
|
|
|
|
void sc_ack_send(sc_ack_t *param)
|
|
{
|
|
NOT_SUPPORTED();
|
|
}
|
|
|
|
/*
|
|
* source: /path/to/esp-idf/components/smartconfig_ack.c
|
|
*/
|
|
void sc_ack_send_stop(void)
|
|
{
|
|
NOT_SUPPORTED();
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* source: /path/to/esp-idf/components/bootloader_support/src/bootloader_clock.c
|
|
*/
|
|
void bootloader_clock_configure(void)
|
|
{
|
|
// ROM bootloader may have put a lot of text into UART0 FIFO.
|
|
// Wait for it to be printed.
|
|
// This is not needed on power on reset, when ROM bootloader is running at
|
|
// 40 MHz. But in case of TG WDT reset, CPU may still be running at >80 MHZ,
|
|
// and will be done with the bootloader much earlier than UART FIFO is empty.
|
|
uart_tx_wait_idle(0);
|
|
|
|
/* Set CPU to 80MHz. Keep other clocks unmodified. */
|
|
rtc_cpu_freq_t cpu_freq = RTC_CPU_FREQ_80M;
|
|
#ifndef RIOT_VERSION
|
|
/* On ESP32 rev 0, switching to 80MHz if clock was previously set to
|
|
* 240 MHz may cause the chip to lock up (see section 3.5 of the errata
|
|
* document). For rev. 0, switch to 240 instead if it was chosen in
|
|
* menuconfig.
|
|
*/
|
|
uint32_t chip_ver_reg = REG_READ(EFUSE_BLK0_RDATA3_REG);
|
|
if ((chip_ver_reg & EFUSE_RD_CHIP_VER_REV1_M) == 0 &&
|
|
CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ == 240) {
|
|
cpu_freq = RTC_CPU_FREQ_240M;
|
|
}
|
|
#endif
|
|
|
|
rtc_clk_config_t clk_cfg = RTC_CLK_CONFIG_DEFAULT();
|
|
clk_cfg.xtal_freq = CONFIG_ESP32_XTAL_FREQ;
|
|
clk_cfg.cpu_freq = cpu_freq;
|
|
clk_cfg.slow_freq = rtc_clk_slow_freq_get();
|
|
clk_cfg.fast_freq = rtc_clk_fast_freq_get();
|
|
rtc_clk_init(clk_cfg);
|
|
/* As a slight optimization, if 32k XTAL was enabled in sdkconfig, we enable
|
|
* it here. Usually it needs some time to start up, so we amortize at least
|
|
* part of the start up time by enabling 32k XTAL early.
|
|
* App startup code will wait until the oscillator has started up.
|
|
*/
|
|
#ifdef CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL
|
|
if (!rtc_clk_32k_enabled()) {
|
|
rtc_clk_32k_bootstrap(CONFIG_ESP32_RTC_XTAL_BOOTSTRAP_CYCLES);
|
|
}
|
|
#endif
|
|
}
|