Implement system_* APIs in IDF

This commit is contained in:
Ivan Grokhotkov 2016-11-21 17:15:37 +08:00
parent 2393d829de
commit 8b2f933a51
9 changed files with 365 additions and 152 deletions

View file

@ -116,9 +116,7 @@ void IRAM_ATTR call_start_cpu0()
//Flush and enable icache for APP CPU
Cache_Flush(1);
Cache_Read_Enable(1);
//Un-stall the app cpu; the panic handler may have stalled it.
CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_APPCPU_C1_M);
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_APPCPU_C0_M);
esp_cpu_unstall(1);
//Enable clock gating and reset the app cpu.
SET_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN);
CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_C_REG, DPORT_APPCPU_RUNSTALL);

View file

@ -0,0 +1,44 @@
// Copyright 2013-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.
#include "esp_attr.h"
#include "soc/cpu.h"
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
void IRAM_ATTR esp_cpu_stall(int cpu_id)
{
if (cpu_id == 1) {
CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_APPCPU_C1_M);
SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21<<RTC_CNTL_SW_STALL_APPCPU_C1_S);
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_APPCPU_C0_M);
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2<<RTC_CNTL_SW_STALL_APPCPU_C0_S);
} else {
CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_PROCPU_C1_M);
SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21<<RTC_CNTL_SW_STALL_PROCPU_C1_S);
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_PROCPU_C0_M);
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2<<RTC_CNTL_SW_STALL_PROCPU_C0_S);
}
}
void IRAM_ATTR esp_cpu_unstall(int cpu_id)
{
if (cpu_id == 1) {
CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_APPCPU_C1_M);
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_APPCPU_C0_M);
} else {
CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_PROCPU_C1_M);
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_PROCPU_C0_M);
}
}

View file

@ -24,167 +24,99 @@
extern "C" {
#endif
/** \defgroup System_APIs System APIs
* @brief System APIs
*/
/** @addtogroup System_APIs
* @{
*/
/**
* @attention application don't need to call this function anymore. It do nothing and will
* be removed in future version.
*/
void system_init(void) __attribute__ ((deprecated));
/**
* @brief Get information of the SDK version.
*
* @param null
*
* @return Information of the SDK version.
*/
const char *system_get_sdk_version(void);
/**
* @brief Reset to default settings.
*
* Reset to default settings of the following APIs : wifi_station_set_auto_connect,
* wifi_set_phy_mode, wifi_softap_set_config related, wifi_station_set_config
* related, and wifi_set_opmode.
*
* @param null
*
* @return null
* Function has been deprecated, please use esp_wifi_restore instead.
* This name will be removed in a future release.
*/
void system_restore(void);
void system_restore(void) __attribute__ ((deprecated));
/**
* @brief Restart PRO and APP CPUs.
*
* This function can be called both from PRO and APP CPUs.
* After successful restart, CPU reset reason will be SW_CPU_RESET.
* Peripherals (except for WiFi, BT, UART0, SPI1, and legacy timers) are not reset.
* This function does not return.
*/
void esp_restart(void) __attribute__ ((noreturn));
/**
* @brief Restart system.
*
* @param null
*
* @return null
* Function has been renamed to esp_restart.
* This name will be removed in a future release.
*/
void system_restart(void);
void system_restart(void) __attribute((deprecated, noreturn));
/**
* @brief Get system time, unit: microsecond.
*
* @param null
*
* @return System time, unit: microsecond.
* This function is deprecated. Use 'gettimeofday' function for 64-bit precision.
* This definition will be removed in a future release.
*/
uint32_t system_get_time(void);
uint32_t system_get_time(void) __attribute__ ((deprecated));
/**
* @brief Get the size of available heap.
*
* @param null
* Note that the returned value may be larger than the maximum contiguous block
* which can be allocated.
*
* @return Available heap size.
* @return Available heap size, in bytes.
*/
uint32_t system_get_free_heap_size(void);
uint32_t esp_get_free_heap_size(void);
/**
* @brief Get RTC time, unit: RTC clock cycle.
* @brief Get the size of available heap.
*
* @param null
* Function has been renamed to esp_get_free_heap_size.
* This name will be removed in a future release.
*
* @return RTC time.
* @return Available heap size, in bytes.
*/
uint64_t system_get_rtc_time(void);
uint32_t system_get_free_heap_size(void) __attribute__ ((deprecated));
/**
* @brief Read user data from the RTC memory.
*
* The user data segment (1024 bytes, as shown below) is used to store user data.
*
* |<---- system data(512 bytes) ---->|<----------- user data(1024 bytes) --------->|
*
* @attention Read and write unit for data stored in the RTC memory is 4 bytes.
* @attention src_addr is the block number (4 bytes per block). So when reading data
* at the beginning of the user data segment, src_addr will be 512/4 = 128,
* n will be data length.
*
* @param uint16 src : source address of rtc memory, src_addr >= 128
* @param void *dst : data pointer
* @param uint16 n : data length, unit: byte
*
* @return true : succeed
* @return false : fail
*/
bool system_rtc_mem_read(uint16_t src, void *dst, uint16_t n);
/**
* @brief Write user data to the RTC memory.
*
* During deep-sleep, only RTC is working. So users can store their data
* in RTC memory if it is needed. The user data segment below (1024 bytes)
* is used to store the user data.
*
* |<---- system data(512 bytes) ---->|<----------- user data(1024 bytes) --------->|
*
* @attention Read and write unit for data stored in the RTC memory is 4 bytes.
* @attention src_addr is the block number (4 bytes per block). So when storing data
* at the beginning of the user data segment, src_addr will be 512/4 = 128,
* n will be data length.
*
* @param uint16 src : source address of rtc memory, src_addr >= 128
* @param void *dst : data pointer
* @param uint16 n : data length, unit: byte
*
* @return true : succeed
* @return false : fail
*/
bool system_rtc_mem_write(uint16_t dst, const void *src, uint16_t n);
/** \defgroup System_boot_APIs Boot APIs
* @brief boot APIs
*/
/** @addtogroup System_boot_APIs
* @{
*/
/**
* @}
*/
/** \defgroup Hardware_MAC_APIs Hardware MAC APIs
* @brief Hardware MAC address APIs
*
* In WiFi MAC, only ESP32 station MAC is the hardware MAC, ESP32 softAP MAC is a software MAC
* calculated from ESP32 station MAC.
* So users need to call wifi_get_macaddr to query the ESP32 softAP MAC if ESP32 station MAC changed.
*
*/
/** @addtogroup Hardware_MAC_APIs
* @{
*/
* @brief Get one random 32-bit word from hardware RNG
*
* @return random value between 0 and UINT32_MAX
*/
uint32_t esp_random(void);
/**
* @brief Read hardware MAC address.
*
* @param uint8 mac[6] : the hardware MAC address, length: 6 bytes.
* In WiFi MAC, only ESP32 station MAC is the hardware MAC, ESP32 softAP MAC is a software MAC
* calculated from ESP32 station MAC.
* So users need to call esp_wifi_get_macaddr to query the ESP32 softAP MAC if ESP32 station MAC changed.
*
* @return esp_err_t
* @param mac hardware MAC address, length: 6 bytes.
*
* @return ESP_OK on success
*/
esp_err_t system_efuse_read_mac(uint8_t mac[6]);
esp_err_t esp_efuse_read_mac(uint8_t mac[6]);
/**
* @}
* @brief Read hardware MAC address.
*
* Function has been renamed to esp_efuse_read_mac.
* This name will be removed in a future release.
*
* @param mac hardware MAC address, length: 6 bytes.
* @return ESP_OK on success
*/
esp_err_t system_efuse_read_mac(uint8_t mac[6]) __attribute__ ((deprecated));
/**
* @}
*/
#ifdef __cplusplus
}
#endif

View file

@ -186,6 +186,21 @@ esp_err_t esp_wifi_start(void);
*/
esp_err_t esp_wifi_stop(void);
/**
* @brief Restore WiFi stack persistent settings to default values
*
* This function will reset settings made using the following APIs:
* - esp_wifi_get_auto_connect,
* - esp_wifi_set_protocol,
* - esp_wifi_set_config related
* - esp_wifi_set_mode
*
* @return
* - ESP_OK: succeed
* - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init
*/
esp_err_t esp_wifi_restore(void);
/**
* @brief Connect the ESP32 WiFi station to the AP.
*

View file

@ -43,10 +43,9 @@ extern "C" {
/**
* @brief get whether the wifi driver is allowed to transmit data or not
*
* @param none
*
* @return true : upper layer should stop to transmit data to wifi driver
* @return false : upper layer can transmit data to wifi driver
* @return
* - true : upper layer should stop to transmit data to wifi driver
* - false : upper layer can transmit data to wifi driver
*/
bool esp_wifi_internal_tx_is_stop(void);
@ -54,8 +53,6 @@ bool esp_wifi_internal_tx_is_stop(void);
* @brief free the rx buffer which allocated by wifi driver
*
* @param void* buffer: rx buffer pointer
*
* @return nonoe
*/
void esp_wifi_internal_free_rx_buffer(void* buffer);
@ -78,7 +75,6 @@ int esp_wifi_internal_tx(wifi_interface_t wifi_if, void *buffer, u16_t len);
* @brief The WiFi RX callback function
*
* Each time the WiFi need to forward the packets to high layer, the callback function will be called
*
*/
typedef esp_err_t (*wifi_rxcb_t)(void *buffer, uint16_t len, void *eb);
@ -90,18 +86,18 @@ typedef esp_err_t (*wifi_rxcb_t)(void *buffer, uint16_t len, void *eb);
* @param wifi_interface_t ifx : interface
* @param wifi_rxcb_t fn : WiFi RX callback
*
* @return ESP_OK : succeed
* @return others : fail
* @return
* - ESP_OK : succeed
* - others : fail
*/
esp_err_t esp_wifi_internal_reg_rxcb(wifi_interface_t ifx, wifi_rxcb_t fn);
/**
* @brief Notify WIFI driver that the station got ip successfully
*
* @param none
*
* @return ESP_OK : succeed
* @return others : fail
* @return
* - ESP_OK : succeed
* - others : fail
*/
esp_err_t esp_wifi_internal_set_sta_ip(void);

View file

@ -51,7 +51,10 @@ static inline void cpu_write_itlb(unsigned vpn, unsigned attr)
asm volatile ("witlb %1, %0; isync\n" :: "r" (vpn), "r" (attr));
}
/* Make page 0 access raise an exception.
/**
* @brief Configure memory region protection
*
* Make page 0 access raise an exception.
* Also protect some other unused pages so we can catch weirdness.
* Useful attribute values:
* 0 cached, RW
@ -70,9 +73,7 @@ static inline void cpu_configure_region_protection()
cpu_write_itlb(0x20000000, 0);
}
/*
/**
* @brief Set CPU frequency to the value defined in menuconfig
*
* Called from cpu_start.c, not intended to be called from other places.
@ -81,4 +82,16 @@ static inline void cpu_configure_region_protection()
*/
void esp_set_cpu_freq(void);
/**
* @brief Stall CPU using RTC controller
* @param cpu_id ID of the CPU to stall (0 = PRO, 1 = APP)
*/
void esp_cpu_stall(int cpu_id);
/**
* @brief Un-stall CPU using RTC controller
* @param cpu_id ID of the CPU to un-stall (0 = PRO, 1 = APP)
*/
void esp_cpu_unstall(int cpu_id);
#endif

View file

@ -27,6 +27,7 @@
#include "soc/rtc_cntl_reg.h"
#include "soc/timer_group_struct.h"
#include "soc/timer_group_reg.h"
#include "soc/cpu.h"
#include "esp_gdbstub.h"
#include "esp_panic.h"
@ -108,21 +109,10 @@ static const char *edesc[]={
void commonErrorHandler(XtExcFrame *frame);
//The fact that we've panic'ed probably means the other CPU is now running wild, possibly
//messing up the serial output, so we kill it here.
static void haltOtherCore() {
if (xPortGetCoreID()==0) {
//Kill app cpu
CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_APPCPU_C1_M);
SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21<<RTC_CNTL_SW_STALL_APPCPU_C1_S);
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_APPCPU_C0_M);
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2<<RTC_CNTL_SW_STALL_APPCPU_C0_S);
} else {
//Kill pro cpu
CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_PROCPU_C1_M);
SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21<<RTC_CNTL_SW_STALL_PROCPU_C1_S);
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_PROCPU_C0_M);
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2<<RTC_CNTL_SW_STALL_PROCPU_C0_S);
}
//messing up the serial output, so we stall it here.
static void haltOtherCore()
{
esp_cpu_stall( xPortGetCoreID() == 0 ? 1 : 0 );
}
//Returns true when a debugger is attached using JTAG.

View file

@ -0,0 +1,199 @@
// Copyright 2013-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.
#include "esp_system.h"
#include "esp_attr.h"
#include "esp_wifi.h"
#include "esp_wifi_internal.h"
#include "esp_log.h"
#include "rom/efuse.h"
#include "rom/cache.h"
#include "rom/uart.h"
#include "soc/dport_reg.h"
#include "soc/efuse_reg.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/timer_group_reg.h"
#include "soc/timer_group_struct.h"
#include "soc/cpu.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/xtensa_api.h"
static const char* TAG = "system_api";
esp_err_t system_efuse_read_mac(uint8_t mac[6])
{
uint8_t efuse_crc;
uint8_t calc_crc;
uint32_t mac_low = REG_READ(EFUSE_BLK0_RDATA1_REG);
uint32_t 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, "MAC address CRC error, efuse_crc = 0x%02x; calc_crc = 0x%02x", efuse_crc, calc_crc);
abort();
}
}
return ESP_OK;
}
void IRAM_ATTR system_restart(void)
{
esp_wifi_stop();
// Disable scheduler on this core.
vTaskSuspendAll();
const uint32_t core_id = xPortGetCoreID();
const uint32_t other_core_id = core_id == 0 ? 1 : 0;
esp_cpu_stall(other_core_id);
// We need to disable TG0/TG1 watchdogs
// First enable RTC watchdog to be on the safe side
REG_WRITE(RTC_CNTL_WDTWPROTECT_REG, RTC_CNTL_WDT_WKEY_VALUE);
REG_WRITE(RTC_CNTL_WDTCONFIG0_REG,
RTC_CNTL_WDT_FLASHBOOT_MOD_EN_M |
(1 << RTC_CNTL_WDT_SYS_RESET_LENGTH_S) |
(1 << RTC_CNTL_WDT_CPU_RESET_LENGTH_S) );
REG_WRITE(RTC_CNTL_WDTCONFIG1_REG, 128000);
// 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;
// Disable all interrupts
xt_ints_off(0xFFFFFFFF);
// Disable cache
Cache_Read_Disable(0);
Cache_Read_Disable(1);
// Flush any data left in UART FIFO
uart_tx_flush(0);
uart_tx_flush(1);
uart_tx_flush(2);
// Reset wifi/bluetooth (bb/mac)
SET_PERI_REG_MASK(DPORT_WIFI_RST_EN_REG, 0x1f);
REG_WRITE(DPORT_WIFI_RST_EN_REG, 0);
// Reset timer/spi/uart
SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG,
DPORT_TIMERS_RST | DPORT_SPI_RST_1 | DPORT_UART_RST);
REG_WRITE(DPORT_PERIP_RST_EN_REG, 0);
// Reset CPUs
if (core_id == 0) {
// Running on PRO CPU: APP CPU is stalled. Can reset both CPUs.
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG,
RTC_CNTL_SW_PROCPU_RST_M | RTC_CNTL_SW_APPCPU_RST_M);
} else {
// Running on APP CPU: need to reset PRO CPU and unstall it,
// then stall APP CPU
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_PROCPU_RST_M);
esp_cpu_unstall(0);
esp_cpu_stall(1);
}
while(true) {
;
}
}
void system_restore(void)
{
esp_wifi_restore();
}
#if 0
void system_deep_sleep_instant(uint64_t time_in_us)
{
u32 period, cycle_h, cycle_l;
{
struct rst_info debug_data;
memset(&debug_data, 0, sizeof(struct rst_info));
WRITE_PERI_REG(RTC_STORE0, DEEP_SLEEP_AWAKE_FLAG);
debug_data.flag = DEEP_SLEEP_AWAKE_FLAG;
system_write_rtc_mem(0, &debug_data, sizeof(struct rst_info));
}
rtc_set_cpu_freq(XTAL_AUTO, CPU_XTAL);
esp_set_deep_sleep_wake_stub(esp_wake_deep_sleep);
period = rtc_slowck_cali(CALI_RTC_MUX, 128, XTAL_AUTO);
rtc_usec2rtc(time_in_us >> 32, time_in_us, period, &cycle_h, &cycle_l);
rtc_slp_prep_lite(1, 0);
rtc_sleep(cycle_h, cycle_l, TIMER_EXPIRE_EN, 0);
}
static uint64_t deep_sleep_time;
static void system_deep_sleep_step2(void)
{
system_deep_sleep_instant(deep_sleep_time);
}
void system_deep_sleep(uint64 time_in_us)
{
wifi_set_sleep_flag(1);
deep_sleep_time = time_in_us;
os_timer_disarm(&sta_con_timer);
os_timer_setfn(&sta_con_timer, (os_timer_func_t *)system_deep_sleep_step2, NULL);
os_timer_arm(&sta_con_timer, 100, 0);
}
#endif
uint32_t system_get_free_heap_size(void)
{
return xPortGetFreeHeapSize();
}
struct rst_info *system_get_rst_info(void)
{
return NULL;
}
const char* system_get_sdk_version(void)
{
return "master";
}

View file

@ -184,3 +184,29 @@ int settimeofday(const struct timeval *tv, const struct timezone *tz)
return -1;
#endif
}
uint32_t system_get_time(void)
{
#if defined( WITH_FRC1 ) || defined( WITH_RTC )
return get_time_since_boot();
#else
return 0;
#endif
}
uint32_t system_get_current_time(void) __attribute__((alias("system_get_time")));
uint32_t system_relative_time(uint32_t current_time)
{
return system_get_time() - current_time;
}
uint64_t system_get_rtc_time(void)
{
#ifdef WITH_RTC
return get_rtc_time_us();
#else
return 0;
#endif
}