Merge branch 'master' into feature/btdm_avrc

This commit is contained in:
wangmengyang 2017-03-13 16:21:41 +08:00
commit 383db0dc81
160 changed files with 5135 additions and 1227 deletions

View file

@ -167,6 +167,7 @@ test_report:
only:
- master
- triggers
- /^release\/v.*$/
tags:
- report
variables:
@ -231,7 +232,7 @@ push_master_to_github:
- chmod 600 ~/.ssh/id_rsa
- echo -e "Host github.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
- git remote add github git@github.com:espressif/esp-idf.git
- git push --follow-tags github HEAD:master
- git push --follow-tags github HEAD
deploy_docs:
@ -269,7 +270,7 @@ check_doc_links:
- triggers
script:
# must be triggered with CHECK_LINKS=Yes, otherwise exit without test
- test $CHECK_LINKS = "Yes" || exit 0
- test "$CHECK_LINKS" = "Yes" || exit 0
# can only run on master branch (otherwise the commit is not on Github yet)
- test "${CI_BUILD_REF_NAME}" = "master" || exit 0
- cd docs
@ -287,6 +288,7 @@ check_doc_links:
when: on_success
only:
- master
- /^release\/v.*$/
- triggers
allow_failure: true

View file

@ -33,6 +33,7 @@
#include "esp_ota_ops.h"
#include "rom/queue.h"
#include "rom/crc.h"
#include "soc/dport_reg.h"
#include "esp_log.h"
@ -42,7 +43,7 @@
typedef struct ota_ops_entry_ {
uint32_t handle;
esp_partition_t part;
const esp_partition_t *part;
uint32_t erased_size;
uint32_t wrote_size;
#ifdef CONFIG_FLASH_ENCRYPTION_ENABLED
@ -68,21 +69,38 @@ static ota_select s_ota_select[2];
const static char *TAG = "esp_ota_ops";
/* Return true if this is an OTA app partition */
static bool is_ota_partition(const esp_partition_t *p)
{
return (p != NULL
&& p->type == ESP_PARTITION_TYPE_APP
&& p->subtype >= ESP_PARTITION_SUBTYPE_APP_OTA_0
&& p->subtype < ESP_PARTITION_SUBTYPE_APP_OTA_MAX);
}
esp_err_t esp_ota_begin(const esp_partition_t *partition, size_t image_size, esp_ota_handle_t *out_handle)
{
ota_ops_entry_t *new_entry;
esp_err_t ret = ESP_OK;
if ((partition == NULL) || (out_handle == NULL)) {
return ESP_ERR_INVALID_ARG;
}
ota_ops_entry_t *new_entry = (ota_ops_entry_t *) calloc(sizeof(ota_ops_entry_t), 1);
if (new_entry == 0) {
return ESP_ERR_NO_MEM;
partition = esp_partition_verify(partition);
if (partition == NULL) {
return ESP_ERR_NOT_FOUND;
}
// if input image size is 0 or OTA_SIZE_UNKNOWN, will erase all areas in this partition
if (!is_ota_partition(partition)) {
return ESP_ERR_INVALID_ARG;
}
if (partition == esp_ota_get_running_partition()) {
return ESP_ERR_OTA_PARTITION_CONFLICT;
}
// If input image size is 0 or OTA_SIZE_UNKNOWN, erase entire partition
if ((image_size == 0) || (image_size == OTA_SIZE_UNKNOWN)) {
ret = esp_partition_erase_range(partition, 0, partition->size);
} else {
@ -90,11 +108,14 @@ esp_err_t esp_ota_begin(const esp_partition_t *partition, size_t image_size, esp
}
if (ret != ESP_OK) {
free(new_entry);
new_entry = NULL;
return ret;
}
new_entry = (ota_ops_entry_t *) calloc(sizeof(ota_ops_entry_t), 1);
if (new_entry == NULL) {
return ESP_ERR_NO_MEM;
}
LIST_INSERT_HEAD(&s_ota_ops_entries_head, new_entry, entries);
if ((image_size == 0) || (image_size == OTA_SIZE_UNKNOWN)) {
@ -103,7 +124,7 @@ esp_err_t esp_ota_begin(const esp_partition_t *partition, size_t image_size, esp
new_entry->erased_size = image_size;
}
memcpy(&new_entry->part, partition, sizeof(esp_partition_t));
new_entry->part = partition;
new_entry->handle = ++s_ota_ops_last_handle;
*out_handle = new_entry->handle;
return ESP_OK;
@ -165,7 +186,7 @@ esp_err_t esp_ota_write(esp_ota_handle_t handle, const void *data, size_t size)
}
#endif
ret = esp_partition_write(&it->part, it->wrote_size, data_bytes, size);
ret = esp_partition_write(it->part, it->wrote_size, data_bytes, size);
if(ret == ESP_OK){
it->wrote_size += size;
}
@ -215,13 +236,13 @@ esp_err_t esp_ota_end(esp_ota_handle_t handle)
}
#endif
if (esp_image_basic_verify(it->part.address, true, &image_size) != ESP_OK) {
if (esp_image_basic_verify(it->part->address, true, &image_size) != ESP_OK) {
ret = ESP_ERR_OTA_VALIDATE_FAILED;
goto cleanup;
}
#ifdef CONFIG_SECURE_BOOT_ENABLED
ret = esp_secure_boot_verify_signature(it->part.address, image_size);
ret = esp_secure_boot_verify_signature(it->part->address, image_size);
if (ret != ESP_OK) {
ret = ESP_ERR_OTA_VALIDATE_FAILED;
goto cleanup;
@ -301,7 +322,7 @@ static esp_err_t esp_rewrite_ota_data(esp_partition_subtype_t subtype)
//so current ota app sub type id is x , dest bin subtype is y,total ota app count is n
//seq will add (x + n*1 + 1 - seq)%n
if (SUB_TYPE_ID(subtype) >= ota_app_count) {
return ESP_ERR_NOT_FOUND;
return ESP_ERR_INVALID_ARG;
}
ret = esp_partition_mmap(find_partition, 0, find_partition->size, SPI_FLASH_MMAP_DATA, &result, &ota_data_map);
@ -321,9 +342,9 @@ static esp_err_t esp_rewrite_ota_data(esp_partition_subtype_t subtype)
}
if (s_ota_select[0].ota_seq >= s_ota_select[1].ota_seq) {
return rewrite_ota_seq((SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count, 0, find_partition);
} else {
return rewrite_ota_seq((SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count, 1, find_partition);
} else {
return rewrite_ota_seq((SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count, 0, find_partition);
}
} else if (ota_select_valid(&s_ota_select[0])) {
@ -446,3 +467,79 @@ const esp_partition_t *esp_ota_get_boot_partition(void)
return esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
}
}
const esp_partition_t* esp_ota_get_running_partition(void)
{
/* Find the flash address of this exact function. By definition that is part
of the currently running firmware. Then find the enclosing partition. */
size_t phys_offs = spi_flash_cache2phys(esp_ota_get_running_partition);
assert (phys_offs != SPI_FLASH_CACHE2PHYS_FAIL); /* indicates cache2phys lookup is buggy */
esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP,
ESP_PARTITION_SUBTYPE_ANY,
NULL);
assert(it != NULL); /* has to be at least one app partition */
while (it != NULL) {
const esp_partition_t *p = esp_partition_get(it);
if (p->address <= phys_offs && p->address + p->size > phys_offs) {
esp_partition_iterator_release(it);
return p;
}
it = esp_partition_next(it);
}
abort(); /* Partition table is invalid or corrupt */
}
const esp_partition_t* esp_ota_get_next_update_partition(const esp_partition_t *start_from)
{
const esp_partition_t *default_ota = NULL;
bool next_is_result = false;
if (start_from == NULL) {
start_from = esp_ota_get_running_partition();
} else {
start_from = esp_partition_verify(start_from);
}
assert (start_from != NULL);
/* at this point, 'start_from' points to actual partition table data in flash */
/* Two possibilities: either we want the OTA partition immediately after the current running OTA partition, or we
want the first OTA partition in the table (for the case when the last OTA partition is the running partition, or
if the current running partition is not OTA.)
This loop iterates subtypes instead of using esp_partition_find, so we
get all OTA partitions in a known order (low slot to high slot).
*/
for (esp_partition_subtype_t t = ESP_PARTITION_SUBTYPE_APP_OTA_0;
t != ESP_PARTITION_SUBTYPE_APP_OTA_MAX;
t++) {
const esp_partition_t *p = esp_partition_find_first(ESP_PARTITION_TYPE_APP, t, NULL);
if (p == NULL) {
continue;
}
if (default_ota == NULL) {
/* Default to first OTA partition we find,
will be used if nothing else matches */
default_ota = p;
}
if (p == start_from) {
/* Next OTA partition is the one to use */
next_is_result = true;
}
else if (next_is_result) {
return p;
}
}
return default_ota;
}

View file

@ -27,57 +27,76 @@ extern "C"
{
#endif
#define OTA_SIZE_UNKNOWN 0xffffffff
#define OTA_SIZE_UNKNOWN 0xffffffff /*!< Used for esp_ota_begin() if new image size is unknown */
#define ESP_ERR_OTA_BASE 0x1500 /*!< base error code for ota_ops api */
#define ESP_ERR_OTA_PARTITION_CONFLICT (ESP_ERR_OTA_BASE + 0x01) /*!< want to write or erase current running partition */
#define ESP_ERR_OTA_SELECT_INFO_INVALID (ESP_ERR_OTA_BASE + 0x02) /*!< ota data partition info is error */
#define ESP_ERR_OTA_VALIDATE_FAILED (ESP_ERR_OTA_BASE + 0x03) /*!< validate ota image failed */
#define ESP_ERR_OTA_BASE 0x1500 /*!< Base error code for ota_ops api */
#define ESP_ERR_OTA_PARTITION_CONFLICT (ESP_ERR_OTA_BASE + 0x01) /*!< Error if request was to write or erase the current running partition */
#define ESP_ERR_OTA_SELECT_INFO_INVALID (ESP_ERR_OTA_BASE + 0x02) /*!< Error if OTA data partition contains invalid content */
#define ESP_ERR_OTA_VALIDATE_FAILED (ESP_ERR_OTA_BASE + 0x03) /*!< Error if OTA app image is invalid */
/**
* @brief Opaque handle for application update obtained from app_ops.
* @brief Opaque handle for an application OTA update
*
* esp_ota_begin() returns a handle which is then used for subsequent
* calls to esp_ota_write() and esp_ota_end().
*/
typedef uint32_t esp_ota_handle_t;
/**
* @brief format input partition in flash to 0xFF as input image size,
* if unkown image size ,pass 0x0 or 0xFFFFFFFF, it will erase all the
* partition ,Otherwise, erase the required range
*
* @param partition Pointer to partition structure which need to be updated
* Must be non-NULL.
* @param image_size size of image need to be updated
* @param out_handle handle which should be used for esp_ota_write or esp_ota_end call
* @brief Commence an OTA update writing to the specified partition.
* @return:
* - ESP_OK: if format ota image OK
* - ESP_ERR_OTA_PARTITION_CONFLICT: operate current running bin
* - ESP_ERR_OTA_SELECT_INFO_INVALID: ota bin select info invalid
* The specified partition is erased to the specified image size.
*
* If image size is not yet known, pass OTA_SIZE_UNKNOWN which will
* cause the entire partition to be erased.
*
* On success, this function allocates memory that remains in use
* until esp_ota_end() is called with the returned handle.
*
* @param partition Pointer to info for partition which will receive the OTA update. Required.
* @param image_size Size of new OTA app image. Partition will be erased in order to receive this size of image. If 0 or OTA_SIZE_UNKNOWN, the entire partition is erased.
* @param out_handle On success, returns a handle which should be used for subsequent esp_ota_write() and esp_ota_end() calls.
* @return
* - ESP_OK: OTA operation commenced successfully.
* - ESP_ERR_INVALID_ARG: partition or out_handle arguments were NULL, or partition doesn't point to an OTA app partition.
* - ESP_ERR_NO_MEM: Cannot allocate memory for OTA operation.
* - ESP_ERR_OTA_PARTITION_CONFLICT: Partition holds the currently running firmware, cannot update in place.
* - ESP_ERR_NOT_FOUND: Partition argument not found in partition table.
* - ESP_ERR_OTA_SELECT_INFO_INVALID: The OTA data partition contains invalid data.
* - ESP_ERR_INVALID_SIZE: Partition doesn't fit in configured flash size.
* - ESP_ERR_FLASH_OP_TIMEOUT or ESP_ERR_FLASH_OP_FAIL: Flash write failed.
*/
esp_err_t esp_ota_begin(const esp_partition_t* partition, size_t image_size, esp_ota_handle_t* out_handle);
/**
* @brief Write data to input input partition
* @brief Write OTA update data to partition
*
* @param handle Handle obtained from esp_ota_begin
* @param data Pointer to data write to flash
* @param size data size of recieved data
* This function can be called multiple times as
* data is received during the OTA operation. Data is written
* sequentially to the partition.
*
* @return:
* - ESP_OK: if write flash data OK
* - ESP_ERR_OTA_PARTITION_CONFLICT: operate current running bin
* - ESP_ERR_OTA_SELECT_INFO_INVALID: ota bin select info invalid
* @param handle Handle obtained from esp_ota_begin
* @param data Data buffer to write
* @param size Size of data buffer in bytes.
*
* @return
* - ESP_OK: Data was written to flash successfully.
* - ESP_ERR_INVALID_ARG: handle is invalid.
* - ESP_ERR_OTA_VALIDATE_FAILED: First byte of image contains invalid app image magic byte.
* - ESP_ERR_FLASH_OP_TIMEOUT or ESP_ERR_FLASH_OP_FAIL: Flash write failed.
* - ESP_ERR_OTA_SELECT_INFO_INVALID: OTA data partition has invalid contents
*/
esp_err_t esp_ota_write(esp_ota_handle_t handle, const void* data, size_t size);
/**
* @brief Finish the update and validate written data
* @brief Finish OTA update and validate newly written app image.
*
* @param handle Handle obtained from esp_ota_begin.
* @param handle Handle obtained from esp_ota_begin().
*
* @note After calling esp_ota_end(), the handle is no longer valid and any memory associated with it is freed (regardless of result).
*
* @return:
* @return
* - ESP_OK: Newly written OTA app image is valid.
* - ESP_ERR_NOT_FOUND: OTA handle was not found.
* - ESP_ERR_INVALID_ARG: Handle was never written to.
@ -87,27 +106,61 @@ esp_err_t esp_ota_write(esp_ota_handle_t handle, const void* data, size_t size);
esp_err_t esp_ota_end(esp_ota_handle_t handle);
/**
* @brief Set next boot partition, call system_restart() will switch to run it
* @brief Configure OTA data for a new boot partition
*
* @note if you want switch to run a bin file
* has never been checked before,please validate it's signature firstly
* @note If this function returns ESP_OK, calling esp_restart() will boot the newly configured app partition.
*
* @param partition Pointer to partition structure which need to boot
* @param partition Pointer to info for partition containing app image to boot.
*
* @return:
* - ESP_OK: if set next boot partition OK
* - ESP_ERR_OTA_SELECT_INFO_INVALID: ota bin select info invalid
* @return
* - ESP_OK: OTA data updated, next reboot will use specified partition.
* - ESP_ERR_INVALID_ARG: partition argument was NULL or didn't point to a valid OTA partition of type "app".
* - ESP_ERR_OTA_VALIDATE_FAILED: Partition contained invalid app image. Also returned if secure boot is enabled and signature validation failed.
* - ESP_ERR_NOT_FOUND: OTA data partition not found.
* - ESP_ERR_FLASH_OP_TIMEOUT or ESP_ERR_FLASH_OP_FAIL: Flash erase or write failed.
*/
esp_err_t esp_ota_set_boot_partition(const esp_partition_t* partition);
/**
* @brief Get partition info of current running image
*
* @return pointer to esp_partition_t structure, or NULL if no partition is found or
* operate flash failed,This pointer is valid for the lifetime of the application.
* @brief Get partition info of currently configured boot app
*
* If esp_ota_set_boot_partition() has been called, the partition which was set by that function will be returned.
*
* If esp_ota_set_boot_partition() has not been called, the result is
* equivalent to esp_ota_get_running_partition().
*
* @return Pointer to info for partition structure, or NULL if no partition is found or flash read operation failed. Returned pointer is valid for the lifetime of the application.
*/
const esp_partition_t* esp_ota_get_boot_partition(void);
/**
* @brief Get partition info of currently running app
*
* This function is different to esp_ota_get_boot_partition() in that
* it ignores any change of selected boot partition caused by
* esp_ota_set_boot_partition(). Only the app whose code is currently
* running will have its partition information returned.
*
* @return Pointer to info for partition structure, or NULL if no partition is found or flash read operation failed. Returned pointer is valid for the lifetime of the application.
*/
const esp_partition_t* esp_ota_get_running_partition(void);
/**
* @brief Return the next OTA app partition which should be written with a new firmware.
*
* Call this function to find an OTA app partition which can be passed to esp_ota_begin().
*
* Finds next partition round-robin, starting from the current running partition.
*
* @param start_from If set, treat this partition info as describing the current running partition. Can be NULL, in which case esp_ota_get_running_partition() is used to find the currently running partition. The result of this function is never the same as this argument.
*
* @return Pointer to info for partition which should be updated next. NULL result indicates invalid OTA data partition, or that no eligible OTA app slot partition was found.
*
*/
const esp_partition_t* esp_ota_get_next_update_partition(const esp_partition_t *start_from);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,5 @@
#
#Component Makefile
#
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

View file

@ -0,0 +1,86 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/semphr.h>
#include <unity.h>
#include <test_utils.h>
#include <esp_ota_ops.h>
/* These OTA tests currently don't assume an OTA partition exists
on the device, so they're a bit limited
*/
TEST_CASE("esp_ota_begin() verifies arguments", "[ota]")
{
const esp_partition_t *running = esp_ota_get_running_partition();
esp_partition_t partition;
static esp_ota_handle_t handle = 0;
if (handle != 0) { /* clean up from any previous test */
esp_ota_end(handle);
handle = 0;
}
/* running partition & configured boot partition are same */
TEST_ASSERT_NOT_NULL(running);
/* trying to 'begin' on running partition fails */
TEST_ASSERT_NOT_EQUAL(ESP_OK, esp_ota_begin(running, OTA_SIZE_UNKNOWN, &handle));
TEST_ASSERT_EQUAL(0, handle);
memcpy(&partition, running, sizeof(esp_partition_t));
partition.address--;
/* non existent partition fails */
TEST_ASSERT_EQUAL_HEX(ESP_ERR_NOT_FOUND, esp_ota_begin(&partition, OTA_SIZE_UNKNOWN, &handle));
TEST_ASSERT_EQUAL(0, handle);
}
TEST_CASE("esp_ota_get_next_update_partition logic", "[ota]")
{
const esp_partition_t *running = esp_ota_get_running_partition();
const esp_partition_t *factory = esp_partition_find_first(ESP_PARTITION_TYPE_APP,
ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
const esp_partition_t *ota_0 = esp_partition_find_first(ESP_PARTITION_TYPE_APP,
ESP_PARTITION_SUBTYPE_APP_OTA_0, NULL);
const esp_partition_t *ota_1 = esp_partition_find_first(ESP_PARTITION_TYPE_APP,
ESP_PARTITION_SUBTYPE_APP_OTA_1, NULL);
const esp_partition_t *ota_2 = esp_partition_find_first(ESP_PARTITION_TYPE_APP,
ESP_PARTITION_SUBTYPE_APP_OTA_2, NULL);
TEST_ASSERT_NOT_NULL(running);
TEST_ASSERT_NOT_NULL(factory);
TEST_ASSERT_NOT_NULL(ota_0);
TEST_ASSERT_NOT_NULL(ota_1);
TEST_ASSERT_NULL(ota_2); /* this partition shouldn't exist in test partition table */
TEST_ASSERT_EQUAL_PTR(factory, running); /* this may not be true if/when we get OTA tests that do OTA updates */
/* (The test steps verify subtypes before verifying pointer equality, because the failure messages are more readable
this way.)
*/
/* Factory app OTA updates OTA 0 slot */
const esp_partition_t *p = esp_ota_get_next_update_partition(NULL);
TEST_ASSERT_EQUAL_HEX8(ESP_PARTITION_SUBTYPE_APP_OTA_0, p->subtype);
TEST_ASSERT_EQUAL_PTR(ota_0, p);
p = esp_ota_get_next_update_partition(factory);
TEST_ASSERT_EQUAL_HEX8(ESP_PARTITION_SUBTYPE_APP_OTA_0, p->subtype);
TEST_ASSERT_EQUAL_PTR(ota_0, p);
/* OTA slot 0 updates OTA slot 1 */
p = esp_ota_get_next_update_partition(ota_0);
TEST_ASSERT_EQUAL_HEX8(ESP_PARTITION_SUBTYPE_APP_OTA_1, p->subtype);
TEST_ASSERT_EQUAL_PTR(ota_1, p);
/* OTA slot 1 updates OTA slot 0 */
p = esp_ota_get_next_update_partition(ota_1);
TEST_ASSERT_EQUAL_HEX8(ESP_PARTITION_SUBTYPE_APP_OTA_0, p->subtype);;
TEST_ASSERT_EQUAL_PTR(ota_0, p);
}

View file

@ -46,6 +46,7 @@
#include "bootloader_random.h"
#include "bootloader_config.h"
#include "rtc.h"
#include "flash_qio_mode.h"
extern int _bss_start;
extern int _bss_end;
@ -106,14 +107,13 @@ void IRAM_ATTR call_start_cpu0()
}
/**
* @function : load_partition_table
* @description: Parse partition table, get useful data such as location of
* OTA info sector, factory app sector, and test app sector.
/** @brief Load partition table
*
* @inputs: bs bootloader state structure used to save the data
* @return: return true, if the partition table is loaded (and MD5 checksum is valid)
* Parse partition table, get useful data such as location of
* OTA data partition, factory app partition, and test app partition.
*
* @param bs bootloader state structure used to save read data
* @return return true if the partition table was succesfully loaded and MD5 checksum is valid.
*/
bool load_partition_table(bootloader_state_t* bs)
{
@ -263,6 +263,10 @@ void bootloader_main()
ESP_LOGI(TAG, "Enabling RNG early entropy source...");
bootloader_random_enable();
#if CONFIG_FLASHMODE_QIO || CONFIG_FLASHMODE_QOUT
bootloader_enable_qio_mode();
#endif
if(esp_image_load_header(0x1000, true, &fhdr) != ESP_OK) {
ESP_LOGE(TAG, "failed to load bootloader header!");
return;
@ -635,28 +639,21 @@ void print_flash_info(const esp_image_header_t* phdr)
}
ESP_LOGI(TAG, "SPI Speed : %s", str );
switch ( phdr->spi_mode ) {
case ESP_IMAGE_SPI_MODE_QIO:
/* SPI mode could have been set to QIO during boot already,
so test the SPI registers not the flash header */
uint32_t spi_ctrl = REG_READ(SPI_CTRL_REG(0));
if (spi_ctrl & SPI_FREAD_QIO) {
str = "QIO";
break;
case ESP_IMAGE_SPI_MODE_QOUT:
} else if (spi_ctrl & SPI_FREAD_QUAD) {
str = "QOUT";
break;
case ESP_IMAGE_SPI_MODE_DIO:
} else if (spi_ctrl & SPI_FREAD_DIO) {
str = "DIO";
break;
case ESP_IMAGE_SPI_MODE_DOUT:
} else if (spi_ctrl & SPI_FREAD_DUAL) {
str = "DOUT";
break;
case ESP_IMAGE_SPI_MODE_FAST_READ:
} else if (spi_ctrl & SPI_FASTRD_MODE) {
str = "FAST READ";
break;
case ESP_IMAGE_SPI_MODE_SLOW_READ:
} else {
str = "SLOW READ";
break;
default:
str = "DIO";
break;
}
ESP_LOGI(TAG, "SPI Mode : %s", str );

View file

@ -8,6 +8,7 @@
LINKER_SCRIPTS := \
esp32.bootloader.ld \
$(IDF_PATH)/components/esp32/ld/esp32.rom.ld \
$(IDF_PATH)/components/esp32/ld/esp32.peripherals.ld \
esp32.bootloader.rom.ld
COMPONENT_ADD_LDFLAGS := -L $(COMPONENT_PATH) -lmain $(addprefix -T ,$(LINKER_SCRIPTS))

View file

@ -0,0 +1,230 @@
// 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.
#include <stddef.h>
#include <stdint.h>
#include "flash_qio_mode.h"
#include "esp_log.h"
#include "rom/spi_flash.h"
#include "soc/spi_struct.h"
#include "sdkconfig.h"
/* SPI flash controller */
#define SPIFLASH SPI1
/* SPI commands (actual on-wire commands not SPI controller bitmasks)
Suitable for use with the execute_flash_command static function.
*/
#define CMD_RDID 0x9F
#define CMD_WRSR 0x01
#define CMD_WRSR2 0x31 /* Not all SPI flash uses this command */
#define CMD_WREN 0x06
#define CMD_WRDI 0x04
#define CMD_RDSR 0x05
#define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */
static const char *TAG = "qio_mode";
typedef unsigned (*read_status_fn_t)();
typedef void (*write_status_fn_t)(unsigned);
typedef struct __attribute__((packed)) {
const char *manufacturer;
uint8_t mfg_id; /* 8-bit JEDEC manufacturer ID */
uint16_t flash_id; /* 16-bit JEDEC flash chip ID */
uint16_t id_mask; /* Bits to match on in flash chip ID */
read_status_fn_t read_status_fn;
write_status_fn_t write_status_fn;
uint8_t status_qio_bit;
} qio_info_t;
/* Read 8 bit status using RDSR command */
static unsigned read_status_8b_rdsr();
/* Read 8 bit status (second byte) using RDSR2 command */
static unsigned read_status_8b_rdsr2();
/* read 16 bit status using RDSR & RDSR2 (low and high bytes) */
static unsigned read_status_16b_rdsr_rdsr2();
/* Write 8 bit status using WRSR */
static void write_status_8b_wrsr(unsigned new_status);
/* Write 8 bit status (second byte) using WRSR2 */
static void write_status_8b_wrsr2(unsigned new_status);
/* Write 16 bit status using WRSR */
static void write_status_16b_wrsr(unsigned new_status);
/* Array of known flash chips and data to enable Quad I/O mode
Manufacturer & flash ID can be tested by running "esptool.py
flash_id"
If manufacturer ID matches, and flash ID ORed with flash ID mask
matches, enable_qio_mode() will execute "Read Cmd", test if bit
number "QIE Bit" is set, and if not set it will call "Write Cmd"
with this bit set.
Searching of this table stops when the first match is found.
*/
const static qio_info_t chip_data[] = {
/* Manufacturer, mfg_id, flash_id, id mask, Read Status, Write Status, QIE Bit */
{ "MXIC", 0xC2, 0x2000, 0xFF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 },
{ "ISSI", 0x9D, 0x4000, 0xFF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 },
{ "WinBond", 0xEF, 0x4000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 },
/* Final entry is default entry, if no other IDs have matched.
This approach works for chips including:
GigaDevice (mfg ID 0xC8, flash IDs including 4016),
FM25Q32 (QOUT mode only, mfg ID 0xA1, flash IDs including 4016)
*/
{ NULL, 0xFF, 0xFFFF, 0xFFFF, read_status_8b_rdsr2, write_status_8b_wrsr2, 1 },
};
#define NUM_CHIPS (sizeof(chip_data) / sizeof(qio_info_t))
static void enable_qio_mode(read_status_fn_t read_status_fn,
write_status_fn_t write_status_fn,
uint8_t status_qio_bit);
/* Generic function to use the "user command" SPI controller functionality
to send commands to the SPI flash and read the respopnse.
The command passed here is always the on-the-wire command given to the SPI flash unit.
*/
static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len);
void bootloader_enable_qio_mode(void)
{
uint32_t raw_flash_id;
uint8_t mfg_id;
uint16_t flash_id;
int i;
ESP_LOGD(TAG, "Probing for QIO mode enable...");
SPI_Wait_Idle(&g_rom_flashchip);
/* Set up some of the SPIFLASH user/ctrl variables which don't change
while we're probing using execute_flash_command() */
SPIFLASH.ctrl.val = 0;
SPIFLASH.user.usr_dummy = 0;
SPIFLASH.user.usr_addr = 0;
SPIFLASH.user.usr_command = 1;
SPIFLASH.user2.usr_command_bitlen = 7;
raw_flash_id = execute_flash_command(CMD_RDID, 0, 0, 24);
ESP_LOGD(TAG, "Raw SPI flash chip id 0x%x", raw_flash_id);
mfg_id = raw_flash_id & 0xFF;
flash_id = (raw_flash_id >> 16) | (raw_flash_id & 0xFF00);
ESP_LOGD(TAG, "Manufacturer ID 0x%02x chip ID 0x%04x", mfg_id, flash_id);
for (i = 0; i < NUM_CHIPS-1; i++) {
const qio_info_t *chip = &chip_data[i];
if (mfg_id == chip->mfg_id && (flash_id & chip->id_mask) == (chip->flash_id & chip->id_mask)) {
ESP_LOGI(TAG, "Enabling QIO for flash chip %s", chip_data[i].manufacturer);
break;
}
}
if (i == NUM_CHIPS - 1) {
ESP_LOGI(TAG, "Enabling default flash chip QIO");
}
enable_qio_mode(chip_data[i].read_status_fn,
chip_data[i].write_status_fn,
chip_data[i].status_qio_bit);
}
static void enable_qio_mode(read_status_fn_t read_status_fn,
write_status_fn_t write_status_fn,
uint8_t status_qio_bit)
{
uint32_t status;
SPI_Wait_Idle(&g_rom_flashchip);
status = read_status_fn();
ESP_LOGD(TAG, "Initial flash chip status 0x%x", status);
if ((status & (1<<status_qio_bit)) == 0) {
execute_flash_command(CMD_WREN, 0, 0, 0);
write_status_fn(status | (1<<status_qio_bit));
SPI_Wait_Idle(&g_rom_flashchip);
status = read_status_fn();
ESP_LOGD(TAG, "Updated flash chip status 0x%x", status);
if ((status & (1<<status_qio_bit)) == 0) {
ESP_LOGE(TAG, "Failed to set QIE bit, not enabling QIO mode");
return;
}
} else {
ESP_LOGD(TAG, "QIO mode already enabled in flash");
}
ESP_LOGD(TAG, "Enabling QIO mode...");
SpiFlashRdMode mode;
#if CONFIG_FLASHMODE_QOUT
mode = SPI_FLASH_QOUT_MODE;
#else
mode = SPI_FLASH_QIO_MODE;
#endif
SPIMasterReadModeCnfig(mode);
}
static unsigned read_status_8b_rdsr()
{
return execute_flash_command(CMD_RDSR, 0, 0, 8);
}
static unsigned read_status_8b_rdsr2()
{
return execute_flash_command(CMD_RDSR2, 0, 0, 8);
}
static unsigned read_status_16b_rdsr_rdsr2()
{
return execute_flash_command(CMD_RDSR, 0, 0, 8) | (execute_flash_command(CMD_RDSR2, 0, 0, 8) << 8);
}
static void write_status_8b_wrsr(unsigned new_status)
{
execute_flash_command(CMD_WRSR, new_status, 8, 0);
}
static void write_status_8b_wrsr2(unsigned new_status)
{
execute_flash_command(CMD_WRSR2, new_status, 8, 0);
}
static void write_status_16b_wrsr(unsigned new_status)
{
execute_flash_command(CMD_WRSR, new_status, 16, 0);
}
static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len)
{
SPIFLASH.user2.usr_command_value = command;
SPIFLASH.user.usr_miso = miso_len > 0;
SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0;
SPIFLASH.user.usr_mosi = mosi_len > 0;
SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0;
SPIFLASH.data_buf[0] = mosi_data;
SPIFLASH.cmd.usr = 1;
while(SPIFLASH.cmd.usr != 0)
{ }
return SPIFLASH.data_buf[0];
}

View file

@ -0,0 +1,29 @@
// 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.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Enable Quad I/O mode in bootloader (if configured)
*
* Queries attached SPI flash ID and sends correct SPI flash
* commands to enable QIO or QOUT mode, then enables this mode.
*/
void bootloader_enable_qio_mode(void);
#ifdef __cplusplus
}
#endif

View file

@ -33,7 +33,7 @@
*
* @return true if flash encryption is enabled.
*/
static inline IRAM_ATTR bool esp_flash_encryption_enabled(void) {
static inline /** @cond */ IRAM_ATTR /** @endcond */ bool esp_flash_encryption_enabled(void) {
uint32_t flash_crypt_cnt = REG_GET_FIELD(EFUSE_BLK0_RDATA0_REG, EFUSE_RD_FLASH_CRYPT_CNT);
/* __builtin_parity is in flash, so we calculate parity inline */
bool enabled = false;

View file

@ -62,6 +62,11 @@ void bootloader_fill_random(void *buffer, size_t length)
void bootloader_random_enable(void)
{
/* Ensure the hardware RNG is enabled following a soft reset. This should always be the case already (this clock is
never disabled while the CPU is running), this is a "belts and braces" type check.
*/
SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_RNG_EN);
/* Enable SAR ADC in test mode to feed ADC readings of the 1.1V
reference via I2S into the RNG entropy input.

View file

@ -108,6 +108,16 @@ esp_err_t esp_image_basic_verify(uint32_t src_addr, bool log_errors, uint32_t *p
*p_length = 0;
}
if (src_addr % SPI_FLASH_MMU_PAGE_SIZE != 0) {
/* Image must start on a 64KB boundary
(This is not a technical limitation, only the flash mapped regions need to be 64KB aligned. But the most
consistent way to do this is to have all the offsets internal to the image correctly 64KB aligned, and then
start the image on a 64KB boundary also.)
*/
return ESP_ERR_INVALID_ARG;
}
err = esp_image_load_header(src_addr, log_errors, &image_header);
if (err != ESP_OK) {
return err;

View file

@ -17,6 +17,15 @@ config BLUEDROID_MEM_DEBUG
help
Bluedroid memory debug
config BT_DRAM_RELEASE
bool "Release DRAM from Classic BT controller"
depends on BT_ENABLED
default n
help
This option should only be used when BLE only.
Open this option will release about 30K DRAM from Classic BT.
The released DRAM will be used as system heap memory.
# Memory reserved at start of DRAM for Bluetooth stack
config BT_RESERVE_DRAM
hex

View file

@ -19,13 +19,13 @@
#include "bt.h"
#include "future.h"
static bool esp_already_enable = false;
static bool esp_already_init = false;
static bool bd_already_enable = false;
static bool bd_already_init = false;
esp_bluedroid_status_t esp_bluedroid_get_status(void)
{
if (esp_already_init) {
if (esp_already_enable) {
if (bd_already_init) {
if (bd_already_enable) {
return ESP_BLUEDROID_STATUS_ENABLED;
} else {
return ESP_BLUEDROID_STATUS_INITIALIZED;
@ -40,15 +40,20 @@ esp_err_t esp_bluedroid_enable(void)
btc_msg_t msg;
future_t **future_p;
if (esp_already_enable) {
LOG_ERROR("%s already enable\n", __func__);
if (!bd_already_init) {
LOG_ERROR("Bludroid not initialised\n");
return ESP_ERR_INVALID_STATE;
}
if (bd_already_enable) {
LOG_ERROR("Bluedroid already enabled\n");
return ESP_ERR_INVALID_STATE;
}
future_p = btc_main_get_future_p(BTC_MAIN_ENABLE_FUTURE);
*future_p = future_new();
if (*future_p == NULL) {
LOG_ERROR("%s failed\n", __func__);
LOG_ERROR("Bluedroid enable failed\n");
return ESP_ERR_NO_MEM;
}
@ -58,11 +63,11 @@ esp_err_t esp_bluedroid_enable(void)
btc_transfer_context(&msg, NULL, 0, NULL);
if (future_await(*future_p) == FUTURE_FAIL) {
LOG_ERROR("%s failed\n", __func__);
LOG_ERROR("Bluedroid enable failed\n");
return ESP_FAIL;
}
esp_already_enable = true;
bd_already_enable = true;
return ESP_OK;
}
@ -72,15 +77,15 @@ esp_err_t esp_bluedroid_disable(void)
btc_msg_t msg;
future_t **future_p;
if (!esp_already_enable) {
LOG_ERROR("%s already disable\n", __func__);
if (!bd_already_enable) {
LOG_ERROR("Bluedroid already disabled\n");
return ESP_ERR_INVALID_STATE;
}
future_p = btc_main_get_future_p(BTC_MAIN_DISABLE_FUTURE);
*future_p = future_new();
if (*future_p == NULL) {
LOG_ERROR("%s failed\n", __func__);
LOG_ERROR("Bluedroid disable failed\n");
return ESP_ERR_NO_MEM;
}
@ -90,11 +95,11 @@ esp_err_t esp_bluedroid_disable(void)
btc_transfer_context(&msg, NULL, 0, NULL);
if (future_await(*future_p) == FUTURE_FAIL) {
LOG_ERROR("%s failed\n", __func__);
LOG_ERROR("Bluedroid disable failed\n");
return ESP_FAIL;
}
esp_already_enable = false;
bd_already_enable = false;
return ESP_OK;
}
@ -105,19 +110,19 @@ esp_err_t esp_bluedroid_init(void)
future_t **future_p;
if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) {
LOG_ERROR("%s conroller not init\n", __func__);
LOG_ERROR("Conroller not initialised\n");
return ESP_ERR_INVALID_STATE;
}
if (esp_already_init) {
LOG_ERROR("%s already init\n", __func__);
if (bd_already_init) {
LOG_ERROR("Bluedroid already initialised\n");
return ESP_ERR_INVALID_STATE;
}
future_p = btc_main_get_future_p(BTC_MAIN_INIT_FUTURE);
*future_p = future_new();
if (*future_p == NULL) {
LOG_ERROR("%s failed\n", __func__);
LOG_ERROR("Bluedroid initialise failed\n");
return ESP_ERR_NO_MEM;
}
@ -129,11 +134,11 @@ esp_err_t esp_bluedroid_init(void)
btc_transfer_context(&msg, NULL, 0, NULL);
if (future_await(*future_p) == FUTURE_FAIL) {
LOG_ERROR("%s failed\n", __func__);
LOG_ERROR("Bluedroid initialise failed\n");
return ESP_FAIL;
}
esp_already_init = true;
bd_already_init = true;
return ESP_OK;
}
@ -144,15 +149,20 @@ esp_err_t esp_bluedroid_deinit(void)
btc_msg_t msg;
future_t **future_p;
if (!esp_already_init) {
LOG_ERROR("%s already deinit\n", __func__);
if (!bd_already_init) {
LOG_ERROR("Bluedroid already de-initialised\n");
return ESP_ERR_INVALID_STATE;
}
if (bd_already_enable) {
LOG_ERROR("Bludroid already enabled, do disable first\n");
return ESP_ERR_INVALID_STATE;
}
future_p = btc_main_get_future_p(BTC_MAIN_DEINIT_FUTURE);
*future_p = future_new();
if (*future_p == NULL) {
LOG_ERROR("%s failed\n", __func__);
LOG_ERROR("Bluedroid de-initialise failed\n");
return ESP_ERR_NO_MEM;
}
@ -162,15 +172,14 @@ esp_err_t esp_bluedroid_deinit(void)
btc_transfer_context(&msg, NULL, 0, NULL);
if (future_await(*future_p) == FUTURE_FAIL) {
LOG_ERROR("%s failed\n", __func__);
LOG_ERROR("Bluedroid de-initialise failed\n");
return ESP_FAIL;
}
btc_deinit();
esp_already_init = false;
bd_already_init = false;
return ESP_OK;
}

View file

@ -142,6 +142,27 @@ esp_err_t esp_ble_gatts_add_char(uint16_t service_handle, esp_bt_uuid_t *char_
return ESP_ERR_INVALID_STATE;
}
/* parameter validation check */
if ((control != NULL) && (control->auto_rsp == GATT_STACK_RSP)){
if (char_val == NULL){
LOG_ERROR("Error in %s, line=%d, for stack respond attribute, char_val should not be NULL here\n",\
__func__, __LINE__);
return ESP_ERR_INVALID_ARG;
} else if (char_val->attr_max_len == 0){
LOG_ERROR("Error in %s, line=%d, for stack respond attribute, attribute max length should not be 0\n",\
__func__, __LINE__);
return ESP_ERR_INVALID_ARG;
}
}
if (char_val != NULL){
if (char_val->attr_len > char_val->attr_max_len){
LOG_ERROR("Error in %s, line=%d,attribute actual length (%d) should not be larger than max length (%d)\n",\
__func__, __LINE__, char_val->attr_len, char_val->attr_max_len);
return ESP_ERR_INVALID_ARG;
}
}
memset(&arg, 0, sizeof(btc_ble_gatts_args_t));
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_GATTS;
@ -175,6 +196,29 @@ esp_err_t esp_ble_gatts_add_char_descr (uint16_t service_handle,
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
/* parameter validation check */
if ((control != NULL) && (control->auto_rsp == GATT_STACK_RSP)){
if (char_descr_val == NULL){
LOG_ERROR("Error in %s, line=%d, for stack respond attribute, char_descr_val should not be NULL here\n",\
__func__, __LINE__);
return ESP_ERR_INVALID_ARG;
}
else if (char_descr_val->attr_max_len == 0){
LOG_ERROR("Error in %s, line=%d, for stack respond attribute, attribute max length should not be 0\n",\
__func__, __LINE__);
return ESP_ERR_INVALID_ARG;
}
}
if (char_descr_val != NULL){
if (char_descr_val->attr_len > char_descr_val->attr_max_len){
LOG_ERROR("Error in %s, line=%d,attribute actual length (%d) should not be larger than max length (%d)\n",\
__func__, __LINE__, char_descr_val->attr_len, char_descr_val->attr_max_len);
return ESP_ERR_INVALID_ARG;
}
}
memset(&arg, 0, sizeof(btc_ble_gatts_args_t));
msg.sig = BTC_SIG_API_CALL;

View file

@ -46,6 +46,8 @@ typedef enum {
ESP_GAP_BLE_SCAN_RESULT_EVT, /*!< When one scan result ready, the event comes each time */
ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT, /*!< When raw advertising data set complete, the event comes */
ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT, /*!< When raw advertising data set complete, the event comes */
ESP_GAP_BLE_ADV_START_COMPLETE_EVT, /*!< When start advertising complete, the event comes */
ESP_GAP_BLE_SCAN_START_COMPLETE_EVT, /*!< When start scan complete, the event comes */
} esp_gap_ble_cb_event_t;
/// Advertising data maximum length
@ -284,6 +286,18 @@ typedef union {
struct ble_scan_rsp_data_raw_cmpl_evt_param {
esp_bt_status_t status; /*!< Indicate the set raw advertising data operation success status */
} scan_rsp_data_raw_cmpl; /*!< Event parameter of ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT */
/**
* @brief ESP_GAP_BLE_ADV_START_COMPLETE_EVT
*/
struct ble_adv_start_cmpl_evt_param {
esp_bt_status_t status; /*!< Indicate advertising start operation success status */
} adv_start_cmpl; /*!< Event parameter of ESP_GAP_BLE_ADV_START_COMPLETE_EVT */
/**
* @brief ESP_GAP_BLE_SCAN_START_COMPLETE_EVT
*/
struct ble_scan_start_cmpl_evt_param {
esp_bt_status_t status; /*!< Indicate scan start operation success status */
} scan_start_cmpl; /*!< Event parameter of ESP_GAP_BLE_SCAN_START_COMPLETE_EVT */
} esp_ble_gap_cb_param_t;
/**

View file

@ -506,7 +506,7 @@ void bta_av_rc_opened(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
p_scb->rc_handle = p_data->rc_conn_chg.handle;
APPL_TRACE_DEBUG("bta_av_rc_opened shdl:%d, srch %d", i + 1, p_scb->rc_handle);
shdl = i+1;
LOG_INFO("%s allow incoming AVRCP connections:%d", __func__, p_scb->use_rc);
APPL_TRACE_DEBUG("%s allow incoming AVRCP connections:%d", __func__, p_scb->use_rc);
bta_sys_stop_timer(&p_scb->timer);
disc = p_scb->hndl;
break;

View file

@ -4534,12 +4534,11 @@ void bta_dm_ble_observe (tBTA_DM_MSG *p_data)
bta_dm_search_cb.p_scan_cback = p_data->ble_observe.p_cback;
if ((status = BTM_BleObserve(TRUE, p_data->ble_observe.duration,
bta_dm_observe_results_cb, bta_dm_observe_cmpl_cb)) != BTM_CMD_STARTED) {
tBTA_DM_SEARCH data;
APPL_TRACE_WARNING(" %s BTM_BleObserve failed. status %d\n", __FUNCTION__, status);
data.inq_cmpl.num_resps = 0;
if (bta_dm_search_cb.p_scan_cback) {
bta_dm_search_cb.p_scan_cback(BTA_DM_INQ_CMPL_EVT, &data);
}
}
if (p_data->ble_observe.p_start_scan_cback) {
status = (status == BTM_CMD_STARTED ? BTA_SUCCESS : BTA_FAILURE);
p_data->ble_observe.p_start_scan_cback(status);
}
} else {
bta_dm_search_cb.p_scan_cback = NULL;
@ -4576,13 +4575,21 @@ void bta_dm_ble_set_adv_params (tBTA_DM_MSG *p_data)
*******************************************************************************/
void bta_dm_ble_set_adv_params_all (tBTA_DM_MSG *p_data)
{
BTM_BleSetAdvParamsStartAdv(p_data->ble_set_adv_params_all.adv_int_min,
tBTA_STATUS status = BTA_FAILURE;
if (BTM_BleSetAdvParamsStartAdv(p_data->ble_set_adv_params_all.adv_int_min,
p_data->ble_set_adv_params_all.adv_int_max,
p_data->ble_set_adv_params_all.adv_type,
p_data->ble_set_adv_params_all.addr_type_own,
p_data->ble_set_adv_params_all.p_dir_bda,
p_data->ble_set_adv_params_all.channel_map,
p_data->ble_set_adv_params_all.adv_filter_policy);
p_data->ble_set_adv_params_all.adv_filter_policy) == BTM_SUCCESS) {
status = BTA_SUCCESS;
}
if (p_data->ble_set_adv_params_all.p_start_adv_cback) {
(*p_data->ble_set_adv_params_all.p_start_adv_cback)(status);
}
}
/*******************************************************************************

View file

@ -1009,7 +1009,7 @@ void BTA_DmSetBleAdvParams (UINT16 adv_int_min, UINT16 adv_int_max,
void BTA_DmSetBleAdvParamsAll (UINT16 adv_int_min, UINT16 adv_int_max,
UINT8 adv_type, tBLE_ADDR_TYPE addr_type_own,
tBTM_BLE_ADV_CHNL_MAP chnl_map, tBTM_BLE_AFP adv_fil_pol,
tBLE_BD_ADDR *p_dir_bda)
tBLE_BD_ADDR *p_dir_bda, tBTA_START_ADV_CMPL_CBACK p_start_adv_cb)
{
#if BLE_INCLUDED == TRUE
tBTA_DM_API_BLE_ADV_PARAMS_ALL *p_msg;
@ -1029,6 +1029,7 @@ void BTA_DmSetBleAdvParamsAll (UINT16 adv_int_min, UINT16 adv_int_max,
p_msg->addr_type_own = addr_type_own;
p_msg->channel_map = chnl_map;
p_msg->adv_filter_policy = adv_fil_pol;
p_msg->p_start_adv_cback = p_start_adv_cb;
if (p_dir_bda != NULL) {
p_msg->p_dir_bda = (tBLE_BD_ADDR *)(p_msg + 1);
memcpy(p_msg->p_dir_bda, p_dir_bda, sizeof(tBLE_BD_ADDR));
@ -2127,7 +2128,8 @@ void BTA_DmCloseACL(BD_ADDR bd_addr, BOOLEAN remove_dev, tBTA_TRANSPORT transpor
**
*******************************************************************************/
extern void BTA_DmBleObserve(BOOLEAN start, UINT8 duration,
tBTA_DM_SEARCH_CBACK *p_results_cb)
tBTA_DM_SEARCH_CBACK *p_results_cb,
tBTA_START_SCAN_CMPL_CBACK *p_start_scan_cb)
{
tBTA_DM_API_BLE_OBSERVE *p_msg;
@ -2140,6 +2142,7 @@ extern void BTA_DmBleObserve(BOOLEAN start, UINT8 duration,
p_msg->start = start;
p_msg->duration = duration;
p_msg->p_cback = p_results_cb;
p_msg->p_start_scan_cback = p_start_scan_cb;
bta_sys_sendmsg(p_msg);
}

View file

@ -471,7 +471,8 @@ typedef struct {
BT_HDR hdr;
BOOLEAN start;
UINT16 duration;
tBTA_DM_SEARCH_CBACK *p_cback;
tBTA_DM_SEARCH_CBACK *p_cback;
tBTA_START_SCAN_CMPL_CBACK *p_start_scan_cback;
} tBTA_DM_API_BLE_OBSERVE;
typedef struct {
@ -506,6 +507,7 @@ typedef struct {
tBTM_BLE_ADV_CHNL_MAP channel_map;
tBTM_BLE_AFP adv_filter_policy;
tBLE_BD_ADDR *p_dir_bda;
tBTA_START_ADV_CMPL_CBACK *p_start_adv_cback;
} tBTA_DM_API_BLE_ADV_PARAMS_ALL;

View file

@ -400,6 +400,8 @@ typedef struct {
typedef void (tBTA_SET_ADV_DATA_CMPL_CBACK) (tBTA_STATUS status);
typedef void (tBTA_START_ADV_CMPL_CBACK) (tBTA_STATUS status);
/* advertising channel map */
#define BTA_BLE_ADV_CHNL_37 BTM_BLE_ADV_CHNL_37
#define BTA_BLE_ADV_CHNL_38 BTM_BLE_ADV_CHNL_38
@ -1095,6 +1097,8 @@ typedef void (tBTA_BLE_SCAN_SETUP_CBACK) (tBTA_BLE_BATCH_SCAN_EVT evt,
tBTA_DM_BLE_REF_VALUE ref_value,
tBTA_STATUS status);
typedef void (tBTA_START_SCAN_CMPL_CBACK) (tBTA_STATUS status);
typedef void (tBTA_BLE_TRACK_ADV_CMPL_CBACK)(int action, tBTA_STATUS status,
tBTA_DM_BLE_PF_AVBL_SPACE avbl_space,
tBTA_DM_BLE_REF_VALUE ref_value);
@ -1891,7 +1895,7 @@ extern void BTA_DmSetBleAdvParams (UINT16 adv_int_min, UINT16 adv_int_max,
extern void BTA_DmSetBleAdvParamsAll (UINT16 adv_int_min, UINT16 adv_int_max,
UINT8 adv_type, tBLE_ADDR_TYPE addr_type_own,
tBTM_BLE_ADV_CHNL_MAP chnl_map, tBTM_BLE_AFP adv_fil_pol,
tBLE_BD_ADDR *p_dir_bda);
tBLE_BD_ADDR *p_dir_bda, tBTA_START_ADV_CMPL_CBACK p_start_adv_cb);
/*******************************************************************************
@ -1997,7 +2001,8 @@ extern void BTA_DmSetEncryption(BD_ADDR bd_addr, tBTA_TRANSPORT transport,
**
*******************************************************************************/
extern void BTA_DmBleObserve(BOOLEAN start, UINT8 duration,
tBTA_DM_SEARCH_CBACK *p_results_cb);
tBTA_DM_SEARCH_CBACK *p_results_cb,
tBTA_START_SCAN_CMPL_CBACK *p_start_scan_cb);
extern void BTA_DmBleStopAdvertising(void);

View file

@ -49,7 +49,7 @@ static void queue_int_add(connect_node_t *p_param)
for (const list_node_t *node = list_begin(connect_queue); node != list_end(connect_queue); node = list_next(node)) {
if (((connect_node_t *)list_node(node))->uuid == p_param->uuid) {
LOG_INFO("%s dropping duplicate connect request for uuid: %04x", __func__, p_param->uuid);
LOG_DEBUG("%s dropping duplicate connect request for uuid: %04x", __func__, p_param->uuid);
return;
}
}

View file

@ -41,14 +41,14 @@ bt_status_t btc_storage_add_bonded_device(bt_bdaddr_t *remote_bd_addr,
bdstr_t bdstr;
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
LOG_INFO("add to storage: Remote device:%s\n", bdstr);
LOG_DEBUG("add to storage: Remote device:%s\n", bdstr);
int ret = btc_config_set_int(bdstr, "LinkKeyType", (int)key_type);
ret &= btc_config_set_int(bdstr, "PinLength", (int)pin_length);
ret &= btc_config_set_bin(bdstr, "LinkKey", link_key, sizeof(LINK_KEY));
/* write bonded info immediately */
btc_config_flush();
LOG_INFO("Storage add rslt %d\n", ret);
LOG_DEBUG("Storage add rslt %d\n", ret);
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
}
@ -72,7 +72,7 @@ static bt_status_t btc_in_fetch_bonded_devices(int add)
continue;
}
LOG_INFO("Remote device:%s\n", name);
LOG_DEBUG("Remote device:%s\n", name);
LINK_KEY link_key;
size_t size = sizeof(link_key);
if (btc_config_get_bin(name, "LinkKey", link_key, &size)) {
@ -99,7 +99,7 @@ static bt_status_t btc_in_fetch_bonded_devices(int add)
}
}
if (!bt_linkkey_file_found) {
LOG_INFO("Remote device:%s, no link key\n", name);
LOG_DEBUG("Remote device:%s, no link key\n", name);
}
}
return BT_STATUS_SUCCESS;
@ -122,7 +122,7 @@ bt_status_t btc_storage_load_bonded_devices(void)
{
bt_status_t status;
status = btc_in_fetch_bonded_devices(1);
LOG_INFO("Storage load rslt %d\n", status);
LOG_DEBUG("Storage load rslt %d\n", status);
return status;
}
@ -140,7 +140,7 @@ bt_status_t btc_storage_remove_bonded_device(bt_bdaddr_t *remote_bd_addr)
{
bdstr_t bdstr;
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
LOG_INFO("Add to storage: Remote device:%s\n", bdstr);
LOG_DEBUG("Add to storage: Remote device:%s\n", bdstr);
int ret = 1;
if (btc_config_exist(bdstr, "LinkKeyType")) {

View file

@ -606,7 +606,7 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
case BTA_AV_RECONFIG_EVT:
if ((btc_av_cb.flags & BTC_AV_FLAG_PENDING_START) &&
(p_av->reconfig.status == BTA_AV_SUCCESS)) {
APPL_TRACE_WARNING("reconfig done BTA_AVstart()\n");
LOG_WARN("reconfig done BTA_AVstart()\n");
BTA_AvStart();
} else if (btc_av_cb.flags & BTC_AV_FLAG_PENDING_START) {
btc_av_cb.flags &= ~BTC_AV_FLAG_PENDING_START;
@ -905,7 +905,7 @@ static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data)
memcpy(&(arg.mcc.cie), (uint8_t *)p_data + 3, ESP_A2D_CIE_LEN_SBC);
btc_transfer_context(&msg, &arg, sizeof(btc_av_args_t), NULL);
} else {
APPL_TRACE_ERROR("ERROR dump_codec_info A2D_ParsSbcInfo fail:%d\n", a2d_status);
LOG_ERROR("ERROR dump_codec_info A2D_ParsSbcInfo fail:%d\n", a2d_status);
}
}
}
@ -972,7 +972,7 @@ static bt_status_t connect_int(bt_bdaddr_t *bd_addr, uint16_t uuid)
btc_av_connect_req_t connect_req;
connect_req.target_bda = bd_addr;
connect_req.uuid = uuid;
LOG_INFO("%s\n", __FUNCTION__);
LOG_DEBUG("%s\n", __FUNCTION__);
btc_sm_dispatch(btc_av_cb.sm_handle, BTC_AV_CONNECT_REQ_EVT, (char *)&connect_req);
@ -998,7 +998,7 @@ bt_status_t btc_a2d_sink_connect(bt_bdaddr_t* remote_bda)
*******************************************************************************/
static void btc_a2d_sink_deinit(void)
{
LOG_INFO("%s\n", __FUNCTION__);
LOG_DEBUG("%s\n", __FUNCTION__);
btc_a2dp_stop_media_task();

View file

@ -145,8 +145,6 @@ static void handle_rc_features(void)
}
LOG_DEBUG("%s: rc_features=0x%x", __FUNCTION__, rc_features);
// todo: uncomment the following line when added the AVRC target role
// BTC_HAL_CBACK(bt_rc_callbacks, remote_features_cb, &rc_addr, rc_features)
}
@ -386,7 +384,7 @@ BOOLEAN btc_rc_get_connected_peer(BD_ADDR peer_addr)
*******************************************************************************/
static void btc_avrc_ct_init(void)
{
LOG_INFO("## %s ##", __FUNCTION__);
LOG_DEBUG("## %s ##", __FUNCTION__);
memset (&btc_rc_vb, 0, sizeof(btc_rc_vb));
btc_rc_vb.rc_vol_label=MAX_LABEL;

View file

@ -367,7 +367,26 @@ static void btc_ble_set_scan_rsp_data_raw(uint8_t *raw_scan_rsp, uint32_t raw_sc
BTA_DmBleSetScanRspRaw(raw_scan_rsp, raw_scan_rsp_len, p_scan_rsp_data_cback);
}
static void btc_ble_start_advertising (esp_ble_adv_params_t *ble_adv_params)
static void btc_start_adv_callback(tBTA_STATUS status)
{
esp_ble_gap_cb_param_t param;
bt_status_t ret;
btc_msg_t msg;
msg.sig = BTC_SIG_API_CB;
msg.pid = BTC_PID_GAP_BLE;
msg.act = ESP_GAP_BLE_ADV_START_COMPLETE_EVT;
param.adv_start_cmpl.status = status;
ret = btc_transfer_context(&msg, &param,
sizeof(esp_ble_gap_cb_param_t), NULL);
if (ret != BT_STATUS_SUCCESS) {
LOG_ERROR("%s btc_transfer_context failed\n", __func__);
}
}
static void btc_ble_start_advertising (esp_ble_adv_params_t *ble_adv_params, tBTA_START_ADV_CMPL_CBACK start_adv_cback)
{
tBLE_BD_ADDR peer_addr;
@ -398,7 +417,8 @@ static void btc_ble_start_advertising (esp_ble_adv_params_t *ble_adv_params)
ble_adv_params->own_addr_type,
ble_adv_params->channel_map,
ble_adv_params->adv_filter_policy,
&peer_addr);
&peer_addr,
start_adv_cback);
}
@ -456,8 +476,7 @@ static void btc_search_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data
param.scan_rst.ble_addr_type = p_data->inq_res.ble_addr_type;
param.scan_rst.ble_evt_type = p_data->inq_res.ble_evt_type;
param.scan_rst.flag = p_data->inq_res.flag;
memcpy(param.scan_rst.ble_adv, p_data->inq_res.p_eir,
ESP_BLE_ADV_DATA_LEN_MAX);
memcpy(param.scan_rst.ble_adv, p_data->inq_res.p_eir, sizeof(param.scan_rst.ble_adv));
break;
}
case BTA_DM_INQ_CMPL_EVT: {
@ -487,12 +506,33 @@ static void btc_search_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data
btc_transfer_context(&msg, &param, sizeof(esp_ble_gap_cb_param_t), NULL);
}
static void btc_ble_start_scanning(uint8_t duration, tBTA_DM_SEARCH_CBACK *results_cb)
static void btc_start_scan_callback(tBTA_STATUS status)
{
if ((duration != 0) && (results_cb != NULL)) {
esp_ble_gap_cb_param_t param;
bt_status_t ret;
btc_msg_t msg;
msg.sig = BTC_SIG_API_CB;
msg.pid = BTC_PID_GAP_BLE;
msg.act = ESP_GAP_BLE_SCAN_START_COMPLETE_EVT;
param.scan_start_cmpl.status = status;
ret = btc_transfer_context(&msg, &param,
sizeof(esp_ble_gap_cb_param_t), NULL);
if (ret != BT_STATUS_SUCCESS) {
LOG_ERROR("%s btc_transfer_context failed\n", __func__);
}
}
static void btc_ble_start_scanning(uint8_t duration,
tBTA_DM_SEARCH_CBACK *results_cb,
tBTA_START_SCAN_CMPL_CBACK *start_scan_cb)
{
if ((duration != 0) && (results_cb != NULL) && (start_scan_cb != NULL)) {
///Start scan the device
BTA_DmBleObserve(true, duration, results_cb);
BTA_DmBleObserve(true, duration, results_cb, start_scan_cb);
} else {
LOG_ERROR("The scan duration or p_results_cb invalid\n");
}
@ -501,7 +541,7 @@ static void btc_ble_start_scanning(uint8_t duration, tBTA_DM_SEARCH_CBACK *resul
static void btc_ble_stop_scanning(void)
{
uint8_t duration = 0;
BTA_DmBleObserve(false, duration, NULL);
BTA_DmBleObserve(false, duration, NULL, NULL);
}
@ -576,6 +616,12 @@ void btc_gap_ble_cb_handler(btc_msg_t *msg)
case ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT:
btc_gap_ble_cb_to_app(ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT, param);
break;
case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
btc_gap_ble_cb_to_app(ESP_GAP_BLE_ADV_START_COMPLETE_EVT, param);
break;
case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:
btc_gap_ble_cb_to_app(ESP_GAP_BLE_SCAN_START_COMPLETE_EVT, param);
break;
default:
break;
@ -695,13 +741,13 @@ void btc_gap_ble_call_handler(btc_msg_t *msg)
btc_ble_set_scan_params(&arg->set_scan_param.scan_params, btc_scan_params_callback);
break;
case BTC_GAP_BLE_ACT_START_SCAN:
btc_ble_start_scanning(arg->start_scan.duration, btc_search_callback);
btc_ble_start_scanning(arg->start_scan.duration, btc_search_callback, btc_start_scan_callback);
break;
case BTC_GAP_BLE_ACT_STOP_SCAN:
btc_ble_stop_scanning();
break;
case BTC_GAP_BLE_ACT_START_ADV:
btc_ble_start_advertising(&arg->start_adv.adv_params);
btc_ble_start_advertising(&arg->start_adv.adv_params, btc_start_adv_callback);
break;
case BTC_GAP_BLE_ACT_STOP_ADV:
btc_ble_stop_advertising();

View file

@ -182,13 +182,16 @@ static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db,
future_t *future_p;
esp_ble_gatts_cb_param_t param;
//set the attribute table create service flag to ture
//set the attribute table create service flag to true
btc_creat_tab_env.is_tab_creat_svc = true;
btc_creat_tab_env.num_handle = max_nb_attr;
for(int i = 0; i < max_nb_attr; i++){
if(gatts_attr_db[i].att_desc.uuid_length== ESP_UUID_LEN_16){
uuid = (gatts_attr_db[i].att_desc.uuid_p[1] << 8) + (gatts_attr_db[i].att_desc.uuid_p[0]);
}
else{
continue;
}
future_p = future_new();
if (future_p == NULL) {
LOG_ERROR("%s failed:no mem\n", __func__);

View file

@ -20,7 +20,7 @@
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "esp_task.h"
#include "bt_defs.h"
#define portBASE_TYPE int
@ -43,25 +43,25 @@ enum {
// SIG_BTIF_WORK = 0xff
};
#define HCI_HOST_TASK_STACK_SIZE 1500
#define HCI_HOST_TASK_PRIO (configMAX_PRIORITIES - 2)
#define HCI_HOST_TASK_NAME "hciHostT"
#define HCI_HOST_QUEUE_NUM 40
#define HCI_HOST_TASK_STACK_SIZE (2048 + BT_TASK_EXTRA_STACK_SIZE)
#define HCI_HOST_TASK_PRIO (configMAX_PRIORITIES - 2)
#define HCI_HOST_TASK_NAME "hciHostT"
#define HCI_HOST_QUEUE_NUM 40
#define HCI_H4_TASK_STACK_SIZE 1500
#define HCI_H4_TASK_PRIO (configMAX_PRIORITIES - 3)
#define HCI_H4_TASK_NAME "hciH4T"
#define HCI_H4_QUEUE_NUM 60
#define HCI_H4_TASK_STACK_SIZE (2048 + BT_TASK_EXTRA_STACK_SIZE)
#define HCI_H4_TASK_PRIO (configMAX_PRIORITIES - 3)
#define HCI_H4_TASK_NAME "hciH4T"
#define HCI_H4_QUEUE_NUM 60
#define BTU_TASK_STACK_SIZE 4096
#define BTU_TASK_PRIO (configMAX_PRIORITIES - 4)
#define BTU_TASK_NAME "btuT"
#define BTU_QUEUE_NUM 50
#define BTU_TASK_STACK_SIZE (3584 + BT_TASK_EXTRA_STACK_SIZE)
#define BTU_TASK_PRIO (configMAX_PRIORITIES - 4)
#define BTU_TASK_NAME "btuT"
#define BTU_QUEUE_NUM 50
#define BTC_TASK_STACK_SIZE CONFIG_BTC_TASK_STACK_SIZE //by menuconfig
#define BTC_TASK_NAME "btcT"
#define BTC_TASK_PRIO (configMAX_PRIORITIES - 5)
#define BTC_TASK_QUEUE_NUM 20
#define BTC_TASK_STACK_SIZE (CONFIG_BTC_TASK_STACK_SIZE + BT_TASK_EXTRA_STACK_SIZE) //by menuconfig
#define BTC_TASK_NAME "btcT"
#define BTC_TASK_PRIO (configMAX_PRIORITIES - 5)
#define BTC_TASK_QUEUE_NUM 20
void btu_task_post(uint32_t sig);
void hci_host_task_post(void);

View file

@ -2935,14 +2935,18 @@ tBTM_STATUS btm_ble_start_scan(void)
tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var;
tBTM_STATUS status = BTM_CMD_STARTED;
/* start scan, disable duplicate filtering */
if (!btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, p_inq->scan_duplicate_filter)) {
if (p_inq->adv_mode != BTM_BLE_ADV_DISABLE) {
status = BTM_NO_RESOURCES;
} else {
if (p_inq->scan_type == BTM_BLE_SCAN_MODE_ACTI) {
btm_ble_set_topology_mask(BTM_BLE_STATE_ACTIVE_SCAN_BIT);
/* start scan, disable duplicate filtering */
if (!btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, p_inq->scan_duplicate_filter)) {
status = BTM_NO_RESOURCES;
} else {
btm_ble_set_topology_mask(BTM_BLE_STATE_PASSIVE_SCAN_BIT);
if (p_inq->scan_type == BTM_BLE_SCAN_MODE_ACTI) {
btm_ble_set_topology_mask(BTM_BLE_STATE_ACTIVE_SCAN_BIT);
} else {
btm_ble_set_topology_mask(BTM_BLE_STATE_PASSIVE_SCAN_BIT);
}
}
}
return status;
@ -2961,15 +2965,17 @@ void btm_ble_stop_scan(void)
{
BTM_TRACE_EVENT ("btm_ble_stop_scan ");
/* Clear the inquiry callback if set */
btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
if (btm_cb.ble_ctr_cb.inq_var.adv_mode == BTM_BLE_ADV_DISABLE) {
/* Clear the inquiry callback if set */
btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
/* stop discovery now */
btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
/* stop discovery now */
btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
btm_update_scanner_filter_policy(SP_ADV_ALL);
btm_update_scanner_filter_policy(SP_ADV_ALL);
btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_SCAN;
btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_SCAN;
}
}
/*******************************************************************************
**
@ -3089,9 +3095,15 @@ static BOOLEAN btm_ble_adv_states_operation(BTM_TOPOLOGY_FUNC_PTR *p_handler, UI
*******************************************************************************/
tBTM_STATUS btm_ble_start_adv(void)
{
tBTM_BLE_CB *p_ble_cb = & btm_cb.ble_ctr_cb;
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
tBTM_STATUS rt = BTM_NO_RESOURCES;
BTM_TRACE_EVENT ("btm_ble_start_adv\n");
if (BTM_BLE_IS_OBS_ACTIVE(p_ble_cb->scan_activity)) {
return BTM_NO_RESOURCES;
}
if (!btm_ble_adv_states_operation (btm_ble_topology_check, p_cb->evt_type)) {
return BTM_WRONG_MODE;
}
@ -3133,10 +3145,12 @@ tBTM_STATUS btm_ble_start_adv(void)
*******************************************************************************/
tBTM_STATUS btm_ble_stop_adv(void)
{
tBTM_BLE_CB *p_ble_cb = & btm_cb.ble_ctr_cb;
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
tBTM_STATUS rt = BTM_SUCCESS;
if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE) {
if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE
&& !BTM_BLE_IS_OBS_ACTIVE(p_ble_cb->scan_activity)) {
if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE)) {
p_cb->fast_adv_on = FALSE;
p_cb->adv_mode = BTM_BLE_ADV_DISABLE;

View file

@ -268,14 +268,21 @@ static tGATT_STATUS read_attr_value (void *p_attr,
status = GATT_SUCCESS;
}
} else { /* characteristic description or characteristic value */
if (p_attr16->control.auto_rsp == GATT_RSP_BY_STACK) {
if (p_attr16->p_value != NULL && p_attr16->p_value->attr_val.attr_val != NULL) {
uint8_t *value = p_attr16->p_value->attr_val.attr_val + offset;
len = (mtu >= p_attr16->p_value->attr_val.attr_len) ? (p_attr16->p_value->attr_val.attr_len) : mtu;
ARRAY_TO_STREAM(p, value, len);
if (p_attr16->p_value == NULL || p_attr16->p_value->attr_val.attr_val == NULL) {
status = GATT_ESP_ERROR;
}
else if (offset > p_attr16->p_value->attr_val.attr_len){
/*if offset equal to max_len, should respond with zero byte value
//if offset is greater than max_len, should respond with an error*/
status = GATT_INVALID_OFFSET;
} else {
UINT8 *value = (UINT8 *)(p_attr16->p_value->attr_val.attr_val) + offset;
UINT16 len_left = p_attr16->p_value->attr_val.attr_len - offset;
len = (mtu >= len_left) ? (len_left) : mtu;
ARRAY_TO_STREAM(p, value, len);
status = GATT_STACK_RSP;
}
status = GATT_STACK_RSP;
} else {
status = GATT_PENDING;
@ -463,6 +470,27 @@ UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm,
tBT_UUID uuid = {LEN_UUID_16, {GATT_UUID_CHAR_DECLARE}};
GATT_TRACE_DEBUG("gatts_add_characteristic perm=0x%0x property=0x%0x\n", perm, property);
/* parameter validation check */
if ((control != NULL) && (control->auto_rsp == GATT_STACK_RSP)){
if (attr_val == NULL){
GATT_TRACE_ERROR("Error in %s, line=%d, for stack respond attribute, attr_val should not be NULL here\n",\
__func__, __LINE__);
return 0;
} else if (attr_val->attr_max_len == 0){
GATT_TRACE_ERROR("Error in %s, line=%d, for stack respond attribute, attribute max length should not be 0\n",\
__func__, __LINE__);
return 0;
}
}
if (attr_val != NULL){
if (attr_val->attr_len > attr_val->attr_max_len){
GATT_TRACE_ERROR("Error in %s, line=%d,attribute actual length should not be larger than max length\n",\
__func__, __LINE__);
return 0;
}
}
if ((p_char_decl = (tGATT_ATTR16 *)allocate_attr_in_db(p_db, &uuid, GATT_PERM_READ)) != NULL) {
if (!copy_extra_byte_in_db(p_db, (void **)&p_char_decl->p_value, sizeof(tGATT_CHAR_DECL))) {
@ -483,10 +511,9 @@ UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm,
p_char_val->control.auto_rsp = control->auto_rsp;
} else {
p_char_val->control.auto_rsp = GATT_RSP_DEFAULT;
}
if (attr_val != NULL) {
if (attr_val != NULL) {
if (!copy_extra_byte_in_db(p_db, (void **)&p_char_val->p_value, sizeof(tGATT_ATTR_VAL))) {
deallocate_attr_in_db(p_db, p_char_val);
return 0;
@ -496,12 +523,23 @@ UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm,
p_char_val->p_value->attr_val.attr_len = attr_val->attr_len;
p_char_val->p_value->attr_val.attr_max_len = attr_val->attr_max_len;
p_char_val->p_value->attr_val.attr_val = GKI_getbuf(attr_val->attr_max_len);
if (p_char_val->p_value->attr_val.attr_val != NULL) {
GATT_TRACE_DEBUG("attribute value not NULL");
memcpy(p_char_val->p_value->attr_val.attr_val, attr_val->attr_val, attr_val->attr_len);
if (p_char_val->p_value->attr_val.attr_val == NULL) {
deallocate_attr_in_db(p_db, p_char_decl);
deallocate_attr_in_db(p_db, p_char_val);
GATT_TRACE_WARNING("Warning in %s, line=%d, insufficient resource to allocate for attribute value\n", __func__, __LINE__);
return 0;
}
//initiate characteristic attribute value part
memset(p_char_val->p_value->attr_val.attr_val, 0, attr_val->attr_max_len);
if (attr_val->attr_val != NULL) {
if (attr_val->attr_max_len < attr_val->attr_len){
GATT_TRACE_ERROR("Error in %s, Line=%d, attribute actual length (%d) should not larger than max size (%d)\n",
__func__, __LINE__, attr_val->attr_len, attr_val->attr_max_len);
}
UINT16 actual_len = (attr_val->attr_max_len < attr_val->attr_len) ? (attr_val->attr_max_len) : (attr_val->attr_len);
memcpy(p_char_val->p_value->attr_val.attr_val, attr_val->attr_val, actual_len);
}
} else {
p_char_val->p_value = NULL;
}
return p_char_val->handle;
@ -582,14 +620,35 @@ UINT16 gatts_add_char_descr (tGATT_SVC_DB *p_db, tGATT_PERM perm,
GATT_TRACE_DEBUG("gatts_add_char_descr uuid=0x%04x\n", p_descr_uuid->uu.uuid16);
/* parameter validation check */
if ((control != NULL) && (control->auto_rsp == GATT_STACK_RSP)){
if (attr_val == NULL){
GATT_TRACE_ERROR("Error in %s, line=%d, for stack respond attribute, attr_val should not be NULL here\n",\
__func__, __LINE__);
return 0;
} else if (attr_val->attr_max_len == 0){
GATT_TRACE_ERROR("Error in %s, line=%d, for stack respond attribute, attribute max length should not be 0\n",\
__func__, __LINE__);
return 0;
}
}
if (attr_val != NULL){
if (attr_val->attr_len > attr_val->attr_max_len){
GATT_TRACE_ERROR("Error in %s, line=%d,attribute actual length (%d) should not be larger than max length (%d)\n",\
__func__, __LINE__, attr_val->attr_len, attr_val->attr_max_len);
return 0;
}
}
/* Add characteristic descriptors */
if ((p_char_dscptr = (tGATT_ATTR16 *)allocate_attr_in_db(p_db, p_descr_uuid, perm)) == NULL) {
deallocate_attr_in_db(p_db, p_char_dscptr);
GATT_TRACE_DEBUG("gatts_add_char_descr Fail for adding char descriptors.");
return 0;
} else {
if (control != NULL) {
p_char_dscptr->control.auto_rsp = control->auto_rsp;
}
p_char_dscptr->control.auto_rsp = (control == NULL) ? GATT_RSP_DEFAULT : (control->auto_rsp);
if (attr_val != NULL) {
if (!copy_extra_byte_in_db(p_db, (void **)&p_char_dscptr->p_value, sizeof(tGATT_ATTR_VAL))) {
deallocate_attr_in_db(p_db, p_char_dscptr);
@ -597,10 +656,17 @@ UINT16 gatts_add_char_descr (tGATT_SVC_DB *p_db, tGATT_PERM perm,
}
p_char_dscptr->p_value->attr_val.attr_len = attr_val->attr_len;
p_char_dscptr->p_value->attr_val.attr_max_len = attr_val->attr_max_len;
if (attr_val->attr_val != NULL) {
if (attr_val->attr_max_len != 0) {
p_char_dscptr->p_value->attr_val.attr_val = GKI_getbuf(attr_val->attr_max_len);
if (p_char_dscptr->p_value->attr_val.attr_val != NULL) {
memset(p_char_dscptr->p_value->attr_val.attr_val, 0, attr_val->attr_max_len);
if (p_char_dscptr->p_value->attr_val.attr_val == NULL) {
deallocate_attr_in_db(p_db, p_char_dscptr);
GATT_TRACE_WARNING("Warning in %s, line=%d, insufficient resource to allocate for descriptor value\n", __func__, __LINE__);
return 0;
}
//initiate characteristic attribute value part
memset(p_char_dscptr->p_value->attr_val.attr_val, 0, attr_val->attr_max_len);
if(attr_val->attr_val != NULL) {
memcpy(p_char_dscptr->p_value->attr_val.attr_val, attr_val->attr_val, attr_val->attr_len);
}
}
@ -625,7 +691,7 @@ UINT16 gatts_add_char_descr (tGATT_SVC_DB *p_db, tGATT_PERM perm,
**
*******************************************************************************/
tGATT_STATUS gatts_set_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle,
UINT16 length, UINT8 *value)
UINT16 length, UINT8 *value)
{
tGATT_ATTR16 *p_cur;
@ -637,51 +703,46 @@ tGATT_STATUS gatts_set_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle,
GATT_TRACE_DEBUG("gatts_set_attribute_value Fail:p_db->p_attr_list is NULL.\n");
return GATT_INVALID_PDU;
}
if ((length > 0) && (value == NULL)){
GATT_TRACE_ERROR("Error in %s, line=%d, value should not be NULL here\n",__func__, __LINE__);
return GATT_INVALID_PDU;
}
p_cur = (tGATT_ATTR16 *) p_db->p_attr_list;
while (p_cur != NULL) {
if (p_cur->handle == attr_handle) {
/* for characteristic should not be set, return GATT_NOT_FOUND */
if (p_cur->uuid_type == GATT_ATTR_UUID_TYPE_16) {
switch (p_cur->uuid) {
case GATT_UUID_PRI_SERVICE:
case GATT_UUID_SEC_SERVICE:
case GATT_UUID_CHAR_DECLARE:
case GATT_UUID_INCLUDE_SERVICE:
return GATT_NOT_FOUND;
default:
if (p_cur->p_value != NULL && p_cur->p_value->attr_val.attr_max_len < length) {
GATT_TRACE_ERROR("gatts_set_attribute_vaule failt:Invalid value length");
return GATT_INVALID_ATTR_LEN;
} else if (p_cur->p_value != NULL && p_cur->p_value->attr_val.attr_max_len > 0) {
memcpy(p_cur->p_value->attr_val.attr_val, value, length);
p_cur->p_value->attr_val.attr_len = length;
} else {
return GATT_INVALID_ATTR_LEN;
}
break;
}
} else {
if (p_cur->p_value != NULL && p_cur->p_value->attr_val.attr_max_len < length) {
GATT_TRACE_ERROR("gatts_set_attribute_vaule failt:Invalid value length");
} else if (p_cur->p_value != NULL && p_cur->p_value->attr_val.attr_max_len > 0) {
memcpy(p_cur->p_value->attr_val.attr_val, value, length);
p_cur->p_value->attr_val.attr_len = length;
} else {
return GATT_INVALID_ATTR_LEN;
case GATT_UUID_PRI_SERVICE:
case GATT_UUID_SEC_SERVICE:
case GATT_UUID_CHAR_DECLARE:
return GATT_NOT_FOUND;
break;
}
}
/* in other cases, value can be set*/
if ((p_cur->p_value == NULL) || (p_cur->p_value->attr_val.attr_val == NULL) \
|| (p_cur->p_value->attr_val.attr_max_len == 0)){
GATT_TRACE_ERROR("Error in %s, line=%d, attribute value should not be NULL here\n", __func__, __LINE__);
return GATT_NOT_FOUND;
} else if (p_cur->p_value->attr_val.attr_max_len < length) {
GATT_TRACE_ERROR("gatts_set_attribute_value failed:Invalid value length");
return GATT_INVALID_ATTR_LEN;
} else{
memcpy(p_cur->p_value->attr_val.attr_val, value, length);
p_cur->p_value->attr_val.attr_len = length;
}
break;
}
p_cur = p_cur->p_next;
}
return GATT_SUCCESS;
}
/*******************************************************************************
**
** Function gatts_get_attribute_value
@ -872,20 +933,25 @@ tGATT_STATUS gatts_write_attr_value_by_handle(tGATT_SVC_DB *p_db,
return GATT_APP_RSP;
}
if (p_attr->p_value != NULL && (p_attr->p_value->attr_val.attr_max_len >=
offset + len)) {
if ((p_attr->p_value != NULL) &&
(p_attr->p_value->attr_val.attr_max_len >= offset + len) &&
p_attr->p_value->attr_val.attr_val != NULL) {
memcpy(p_attr->p_value->attr_val.attr_val + offset, p_value, len);
p_attr->p_value->attr_val.attr_len = len + offset;
return GATT_SUCCESS;
} else {
return GATT_NOT_LONG;
} else if (p_attr->p_value->attr_val.attr_max_len < offset + len){
GATT_TRACE_DEBUG("Remote device try to write with a length larger then attribute's max length\n");
return GATT_INVALID_ATTR_LEN;
} else if ((p_attr->p_value == NULL) || (p_attr->p_value->attr_val.attr_val == NULL)){
GATT_TRACE_ERROR("Error in %s, line=%d, %s should not be NULL here\n", __func__, __LINE__, \
(p_attr->p_value == NULL) ? "p_value" : "attr_val.attr_val");
return GATT_ESP_ERROR;
}
}
p_attr = (tGATT_ATTR16 *)p_attr->p_next;
}
}
return status;

View file

@ -33,6 +33,42 @@
#define GATT_MTU_REQ_MIN_LEN 2
/*******************************************************************************
**
** Function gatt_send_packet
**
** Description This function is called to send gatt packets directly
**
** Returns status
**
*******************************************************************************/
tGATT_STATUS gatt_send_packet (tGATT_TCB *p_tcb, UINT8 *p_data, UINT16 len)
{
BT_HDR *p_msg = NULL;
UINT8 *p_m = NULL;
UINT16 buf_len;
tGATT_STATUS status;
if (len > p_tcb->payload_size){
return GATT_ILLEGAL_PARAMETER;
}
buf_len = (UINT16)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET);
if ((p_msg = (BT_HDR *)GKI_getbuf(buf_len)) == NULL) {
return GATT_NO_RESOURCES;
}
memset(p_msg, 0, buf_len);
p_msg->len = len;
p_m = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
memcpy(p_m, p_data, len);
status = attp_send_sr_msg(p_tcb, p_msg);
return status;
}
/*******************************************************************************
**
** Function gatt_sr_enqueue_cmd
@ -300,7 +336,11 @@ void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U
UINT32 trans_id = 0;
tGATT_IF gatt_if;
UINT16 conn_id;
UINT16 queue_num = 0;
BOOLEAN is_prepare_write_valid = FALSE;
BOOLEAN is_need_dequeue_sr_cmd = FALSE;
tGATT_PREPARE_WRITE_RECORD *prepare_record = NULL;
tGATT_PREPARE_WRITE_QUEUE_DATA * queue_data = NULL;
UNUSED(len);
#if GATT_CONFORMANCE_TESTING == TRUE
@ -319,11 +359,60 @@ void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U
/* mask the flag */
flag &= GATT_PREP_WRITE_EXEC;
prepare_record = &(p_tcb->prepare_write_record);
queue_num = prepare_record->queue._count;
/* no prep write is queued */
//if received prepare_write packets include stack_rsp and app_rsp,
//stack respond to execute_write only when stack_rsp handle has invalid_offset
//or invalid_length error;
//app need to respond to execute_write if it has received app_rsp handle packets
if (((prepare_record->error_code_app == GATT_SUCCESS) &&
(prepare_record->total_num == queue_num))
|| (flag == GATT_PREP_WRITE_CANCEL)){
tGATT_EXEC_WRITE_RSP gatt_exec_write_rsp;
gatt_exec_write_rsp.op_code = GATT_RSP_EXEC_WRITE;
gatt_send_packet(p_tcb, (UINT8 *)(&gatt_exec_write_rsp), sizeof(gatt_exec_write_rsp));
gatt_dequeue_sr_cmd(p_tcb);
if (flag != GATT_PREP_WRITE_CANCEL){
is_prepare_write_valid = TRUE;
}
GATT_TRACE_DEBUG("Send execute_write_rsp\n");
} else if ((prepare_record->error_code_app == GATT_SUCCESS) &&
(prepare_record->total_num > queue_num)){
//No error for stack_rsp's handles and there exist some app_rsp's handles,
//so exec_write_rsp depends to app's response; but stack_rsp's data is valid
//TODO: there exist problem if stack_rsp's data is valid but app_rsp's data is not valid.
is_prepare_write_valid = TRUE;
} else if(prepare_record->total_num < queue_num) {
GATT_TRACE_ERROR("Error in %s, line=%d, prepare write total number (%d) \
should not smaller than prepare queue number (%d)\n", \
__func__, __LINE__,prepare_record->total_num, queue_num);
} else if (prepare_record->error_code_app != GATT_SUCCESS){
GATT_TRACE_DEBUG("Send error code for execute_write, code=0x%x\n", prepare_record->error_code_app);
is_need_dequeue_sr_cmd = (prepare_record->total_num == queue_num) ? TRUE : FALSE;
gatt_send_error_rsp(p_tcb, prepare_record->error_code_app, GATT_REQ_EXEC_WRITE, 0, is_need_dequeue_sr_cmd);
}
//dequeue prepare write data
while(GKI_getfirst(&(prepare_record->queue))) {
queue_data = GKI_dequeue(&(prepare_record->queue));
if (is_prepare_write_valid){
if((queue_data->p_attr->p_value != NULL) && (queue_data->p_attr->p_value->attr_val.attr_val != NULL)){
memcpy(queue_data->p_attr->p_value->attr_val.attr_val+queue_data->offset, queue_data->value, queue_data->len);
}
}
GKI_freebuf(queue_data);
}
/* according to ble spec, even if there is no prep write queued,
* need to respond execute_write_response
* Note: exec_write_rsp callback should be called after all data has been written*/
if (!gatt_sr_is_prep_cnt_zero(p_tcb)) {
trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, 0);
gatt_sr_copy_prep_cnt_to_cback_cnt(p_tcb);
if (prepare_record->total_num > queue_num){
trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, 0);
gatt_sr_copy_prep_cnt_to_cback_cnt(p_tcb);
}
for (i = 0; i < GATT_MAX_APPS; i++) {
if (p_tcb->prep_cnt[i]) {
@ -336,10 +425,10 @@ void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U
p_tcb->prep_cnt[i] = 0;
}
}
} else { /* nothing needs to be executed , send response now */
GATT_TRACE_ERROR("gatt_process_exec_write_req: no prepare write pending");
gatt_send_error_rsp(p_tcb, GATT_ERROR, GATT_REQ_EXEC_WRITE, 0, FALSE);
}
prepare_record->total_num = 0;
prepare_record->error_code_app = GATT_SUCCESS;
}
/*******************************************************************************
@ -987,54 +1076,29 @@ void gatts_process_read_by_type_req(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len,
void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle,
UINT8 op_code, UINT16 len, UINT8 *p_data)
{
UINT16 buf_len = (UINT16)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET);
tGATTS_DATA sr_data;
UINT32 trans_id;
tGATT_STATUS status;
UINT8 sec_flag, key_size, *p = p_data, *p_m;
UINT8 sec_flag, key_size, *p = p_data;
tGATT_SR_REG *p_sreg;
UINT16 conn_id, offset = 0;
BT_HDR *p_msg = NULL;
memset(&sr_data, 0, sizeof(tGATTS_DATA));
sr_data.write_req.need_rsp = FALSE;
if ((p_msg = (BT_HDR *)GKI_getbuf(buf_len)) == NULL) {
GATT_TRACE_ERROR("gatts_process_write_req failed. no resources.\n");
}
memset(p_msg, 0, buf_len);
p_m = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
*p_m ++ = op_code + 1;
p_msg->len = 1;
buf_len = p_tcb->payload_size - 1;
switch (op_code) {
case GATT_REQ_PREPARE_WRITE:
sr_data.write_req.is_prep = TRUE;
STREAM_TO_UINT16(sr_data.write_req.offset, p);
UINT16_TO_STREAM(p_m, sr_data.write_req.is_prep);
offset = sr_data.write_req.offset;
len -= 2;
/* fall through */
case GATT_SIGN_CMD_WRITE:
if (op_code == GATT_SIGN_CMD_WRITE) {
GATT_TRACE_DEBUG("Write CMD with data sigining" );
GATT_TRACE_DEBUG("Write CMD with data signing" );
len -= GATT_AUTH_SIGN_LEN;
}
/* fall through */
case GATT_CMD_WRITE:
case GATT_REQ_WRITE:
if (op_code == GATT_REQ_WRITE || op_code == GATT_REQ_PREPARE_WRITE) {
sr_data.write_req.need_rsp = TRUE;
if(op_code == GATT_REQ_PREPARE_WRITE){
memcpy(p_m, p, len);
p_msg->len += len;
}
}
sr_data.write_req.handle = handle;
sr_data.write_req.len = len;
if (len != 0 && p != NULL) {
memcpy (sr_data.write_req.value, p, len);
}
break;
}
@ -1059,42 +1123,182 @@ void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle,
conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_sreg->gatt_if);
status = gatts_write_attr_value_by_handle(gatt_cb.sr_reg[i_rcb].p_db,
handle, offset, p, len);
if((sr_data.write_req.need_rsp == TRUE) && (status == GATT_APP_RSP)){
if((op_code == GATT_REQ_WRITE) && (status == GATT_APP_RSP)){
sr_data.write_req.need_rsp = TRUE;
status = GATT_PENDING;
}
else{
sr_data.write_req.need_rsp = FALSE;
}
gatt_sr_send_req_callback(conn_id,
trans_id,
GATTS_REQ_TYPE_WRITE,
&sr_data);
if (status == GATT_SUCCESS) {
attp_send_sr_msg(p_tcb, p_msg);
gatt_dequeue_sr_cmd(p_tcb);
} else {
GKI_freebuf(p_msg);
}
} else {
GATT_TRACE_ERROR("max pending command, send error\n");
GATT_TRACE_ERROR("Error in %s, line=%d, max pending command, send error\n", __func__, __LINE__);
status = GATT_BUSY; /* max pending command, application error */
}
}
/* in theroy BUSY is not possible(should already been checked), protected check */
if (status != GATT_PENDING && status != GATT_BUSY && status != GATT_SUCCESS &&
(op_code == GATT_REQ_PREPARE_WRITE || op_code == GATT_REQ_WRITE)) {
gatt_send_error_rsp (p_tcb, status, op_code, handle, FALSE);
gatt_dequeue_sr_cmd(p_tcb);
/* response should be sent only for write_request */
if ((op_code == GATT_REQ_WRITE) && (sr_data.write_req.need_rsp == FALSE)){
if (status == GATT_SUCCESS){
tGATT_WRITE_REQ_RSP gatt_write_req_rsp;
gatt_write_req_rsp.op_code = GATT_RSP_WRITE;
gatt_send_packet(p_tcb, (UINT8 *)(&gatt_write_req_rsp), sizeof(gatt_write_req_rsp));
gatt_dequeue_sr_cmd(p_tcb);
} else if (status != GATT_PENDING){
/* note: in case of GATT_BUSY, will respond this application error to remote device */
gatt_send_error_rsp (p_tcb, status, op_code, handle, TRUE);
}
}
return;
}
/*******************************************************************************
**
** Function gatts_attr_process_preapre_write
**
** Description This function is called to process the prepare write request
** from client.
**
** Returns void
**
*******************************************************************************/
void gatt_attr_process_prepare_write (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle,
UINT8 op_code, UINT16 len, UINT8 *p_data)
{
tGATT_STATUS status;
tGATT_PREPARE_WRITE_QUEUE_DATA * queue_data = NULL;
tGATT_ATTR16 *p_attr;
tGATT_ATTR16 *p_attr_temp;
tGATTS_DATA sr_data;
UINT32 trans_id = 0;
UINT8 sec_flag, key_size, *p = p_data;
tGATT_SR_REG *p_sreg;
UINT16 conn_id, offset = 0;
tGATT_SVC_DB *p_db;
BOOLEAN is_need_prepare_write_rsp = FALSE;
BOOLEAN is_need_queue_data = FALSE;
tGATT_PREPARE_WRITE_RECORD *prepare_record = NULL;
memset(&sr_data, 0, sizeof(tGATTS_DATA));
//get offset from p_data
STREAM_TO_UINT16(offset, p);
len -= 2;
p_sreg = &gatt_cb.sr_reg[i_rcb];
conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_sreg->gatt_if);
//prepare_record = &(prepare_write_record);
prepare_record = &(p_tcb->prepare_write_record);
gatt_sr_get_sec_info(p_tcb->peer_bda,
p_tcb->transport,
&sec_flag,
&key_size);
status = gatts_write_attr_perm_check (gatt_cb.sr_reg[i_rcb].p_db,
op_code,
handle,
sr_data.write_req.offset,
p,
len,
sec_flag,
key_size);
if (status == GATT_SUCCESS){
if ((trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, handle)) != 0) {
p_db = gatt_cb.sr_reg[i_rcb].p_db;
if (p_db && p_db->p_attr_list) {
p_attr = (tGATT_ATTR16 *)p_db->p_attr_list;
while (p_attr && handle >= p_attr->handle) {
if (p_attr->handle == handle ) {
p_attr_temp = p_attr;
if (p_attr->control.auto_rsp == GATT_RSP_BY_APP) {
status = GATT_APP_RSP;
} else if (p_attr->p_value != NULL &&
offset > p_attr->p_value->attr_val.attr_max_len) {
status = GATT_INVALID_OFFSET;
is_need_prepare_write_rsp = TRUE;
is_need_queue_data = TRUE;
} else if (p_attr->p_value != NULL &&
((offset + len) > p_attr->p_value->attr_val.attr_max_len)){
status = GATT_INVALID_ATTR_LEN;
is_need_prepare_write_rsp = TRUE;
is_need_queue_data = TRUE;
} else if (p_attr->p_value == NULL) {
LOG_ERROR("Error in %s, attribute of handle 0x%x not allocate value buffer\n",
__func__, handle);
status = GATT_ESP_ERROR;
} else {
//valid prepare write request, need to send response and queue the data
//status: GATT_SUCCESS
is_need_prepare_write_rsp = TRUE;
is_need_queue_data = TRUE;
}
}
p_attr = (tGATT_ATTR16 *)p_attr->p_next;
}
}
} else{
status = GATT_ESP_ERROR;
GATT_TRACE_ERROR("Error in %s, Line %d: GATT BUSY\n", __func__, __LINE__);
}
}
if (is_need_queue_data){
queue_data = (tGATT_PREPARE_WRITE_QUEUE_DATA *)GKI_getbuf(len + sizeof(tGATT_PREPARE_WRITE_QUEUE_DATA));
if (queue_data == NULL){
status = GATT_PREPARE_Q_FULL;
} else {
queue_data->p_attr = p_attr_temp;
queue_data->len = len;
queue_data->handle = handle;
queue_data->offset = offset;
memcpy(queue_data->value, p, len);
GKI_enqueue(&(prepare_record->queue), queue_data);
}
}
if (is_need_prepare_write_rsp){
//send prepare write response
if (queue_data != NULL){
queue_data->op_code = op_code + 1;
//5: op_code 1 + handle 2 + offset 2
tGATT_STATUS rsp_send_status = gatt_send_packet(p_tcb, &(queue_data->op_code), queue_data->len + 5);
gatt_sr_update_prep_cnt(p_tcb, p_sreg->gatt_if, TRUE, FALSE);
gatt_dequeue_sr_cmd(p_tcb);
if (rsp_send_status != GATT_SUCCESS){
LOG_ERROR("Error in %s, line=%d, fail to send prepare_write_rsp, status=0x%x\n",
__func__, __LINE__, rsp_send_status);
}
} else{
LOG_ERROR("Error in %s, line=%d, queue_data should not be NULL here, fail to send prepare_write_rsp\n",
__func__, __LINE__);
}
}
if ((status == GATT_APP_RSP) || (is_need_prepare_write_rsp)){
prepare_record->total_num++;
memset(&sr_data, 0, sizeof(sr_data));
sr_data.write_req.is_prep = TRUE;
sr_data.write_req.handle = handle;
sr_data.write_req.offset = offset;
sr_data.write_req.len = len;
sr_data.write_req.need_rsp = (status == GATT_APP_RSP) ? TRUE : FALSE;
memcpy(sr_data.write_req.value, p, len);
gatt_sr_send_req_callback(conn_id, trans_id, GATTS_REQ_TYPE_WRITE, &sr_data);
} else{
gatt_send_error_rsp(p_tcb, status, GATT_REQ_PREPARE_WRITE, handle, TRUE);
}
if ((prepare_record->error_code_app == GATT_SUCCESS)
&& ((status == GATT_INVALID_OFFSET) || (status == GATT_INVALID_ATTR_LEN))){
prepare_record->error_code_app = status;
}
}
/*******************************************************************************
**
** Function gatts_process_read_req
@ -1226,9 +1430,11 @@ void gatts_process_attribute_req (tGATT_TCB *p_tcb, UINT8 op_code,
case GATT_REQ_WRITE: /* write char/char descriptor value */
case GATT_CMD_WRITE:
case GATT_SIGN_CMD_WRITE:
case GATT_REQ_PREPARE_WRITE:
gatts_process_write_req(p_tcb, i, handle, op_code, len, p);
break;
case GATT_REQ_PREPARE_WRITE:
gatt_attr_process_prepare_write (p_tcb, i, handle, op_code, len, p);
default:
break;
}

View file

@ -116,6 +116,26 @@ void gatt_free_pending_enc_queue(tGATT_TCB *p_tcb)
}
}
/*******************************************************************************
**
** Function gatt_free_pending_prepare_write_queue
**
** Description Free all buffers in pending prepare write packets queue
**
** Returns None
**
*******************************************************************************/
void gatt_free_pending_prepare_write_queue(tGATT_TCB *p_tcb)
{
GATT_TRACE_DEBUG("gatt_free_pending_prepare_write_queue");
/* release all queued prepare write packets */
while (!GKI_queue_is_empty(&(p_tcb->prepare_write_record.queue))) {
GKI_freebuf (GKI_dequeue (&(p_tcb->prepare_write_record.queue)));
}
p_tcb->prepare_write_record.total_num = 0;
p_tcb->prepare_write_record.error_code_app = GATT_SUCCESS;
}
/*******************************************************************************
**
** Function gatt_delete_dev_from_srv_chg_clt_list
@ -2108,6 +2128,7 @@ void gatt_cleanup_upon_disc(BD_ADDR bda, UINT16 reason, tBT_TRANSPORT transport)
btu_stop_timer (&p_tcb->conf_timer_ent);
gatt_free_pending_ind(p_tcb);
gatt_free_pending_enc_queue(p_tcb);
gatt_free_pending_prepare_write_queue(p_tcb);
for (i = 0; i < GATT_MAX_APPS; i ++) {
p_reg = &gatt_cb.cl_rcb[i];

View file

@ -133,6 +133,16 @@ typedef struct {
UINT8 reason;
} tGATT_ERROR;
/* Execute write response structure */
typedef struct {
UINT8 op_code;
}__attribute__((packed)) tGATT_EXEC_WRITE_RSP;
/* Write request response structure */
typedef struct {
UINT8 op_code;
}__attribute__((packed)) tGATT_WRITE_REQ_RSP;
/* server response message to ATT protocol
*/
typedef union {
@ -329,6 +339,32 @@ typedef struct {
UINT16 count;
} tGATT_SRV_LIST_INFO;
/* prepare write queue data */
typedef struct{
//len: length of value
tGATT_ATTR16 *p_attr;
UINT16 len;
UINT8 op_code;
UINT16 handle;
UINT16 offset;
UINT8 value[2];
}__attribute__((packed)) tGATT_PREPARE_WRITE_QUEUE_DATA;
/* structure to store prepare write packts information */
typedef struct{
//only store prepare write packets which need
//to be responded by stack (not by application)
BUFFER_Q queue;
//store the total number of prepare write packets
//including that should be responded by stack or by application
UINT16 total_num;
//store application error code for prepare write,
//invalid offset && invalid length
UINT8 error_code_app;
}tGATT_PREPARE_WRITE_RECORD;
typedef struct {
BUFFER_Q pending_enc_clcb; /* pending encryption channel q */
tGATT_SEC_ACTION sec_act;
@ -362,6 +398,7 @@ typedef struct {
BOOLEAN in_use;
UINT8 tcb_idx;
tGATT_PREPARE_WRITE_RECORD prepare_write_record; /* prepare write packets record */
} tGATT_TCB;

View file

@ -310,30 +310,41 @@ typedef void (tBTM_RAND_ENC_CB) (tBTM_RAND_ENC *p1);
typedef UINT32 tBTM_BLE_AD_MASK;
#define BTM_BLE_AD_TYPE_FLAG HCI_EIR_FLAGS_TYPE /* 0x01 */
#define BTM_BLE_AD_TYPE_16SRV_PART HCI_EIR_MORE_16BITS_UUID_TYPE /* 0x02 */
#define BTM_BLE_AD_TYPE_16SRV_CMPL HCI_EIR_COMPLETE_16BITS_UUID_TYPE /* 0x03 */
#define BTM_BLE_AD_TYPE_32SRV_PART HCI_EIR_MORE_32BITS_UUID_TYPE /* 0x04 */
#define BTM_BLE_AD_TYPE_32SRV_CMPL HCI_EIR_COMPLETE_32BITS_UUID_TYPE /* 0x05 */
#define BTM_BLE_AD_TYPE_128SRV_PART HCI_EIR_MORE_128BITS_UUID_TYPE /* 0x06 */
#define BTM_BLE_AD_TYPE_128SRV_CMPL HCI_EIR_COMPLETE_128BITS_UUID_TYPE /* 0x07 */
#define BTM_BLE_AD_TYPE_NAME_SHORT HCI_EIR_SHORTENED_LOCAL_NAME_TYPE /* 0x08 */
#define BTM_BLE_AD_TYPE_NAME_CMPL HCI_EIR_COMPLETE_LOCAL_NAME_TYPE /* 0x09 */
#define BTM_BLE_AD_TYPE_TX_PWR HCI_EIR_TX_POWER_LEVEL_TYPE /* 0x0A */
#define BTM_BLE_AD_TYPE_DEV_CLASS 0x0D
#define BTM_BLE_AD_TYPE_SM_TK 0x10
#define BTM_BLE_AD_TYPE_SM_OOB_FLAG 0x11
#define BTM_BLE_AD_TYPE_INT_RANGE 0x12
#define BTM_BLE_AD_TYPE_SOL_SRV_UUID 0x14
#define BTM_BLE_AD_TYPE_128SOL_SRV_UUID 0x15
#define BTM_BLE_AD_TYPE_SERVICE_DATA 0x16
#define BTM_BLE_AD_TYPE_PUBLIC_TARGET 0x17
#define BTM_BLE_AD_TYPE_RANDOM_TARGET 0x18
#define BTM_BLE_AD_TYPE_APPEARANCE 0x19
#define BTM_BLE_AD_TYPE_ADV_INT 0x1a
#define BTM_BLE_AD_TYPE_32SOL_SRV_UUID 0x1b
#define BTM_BLE_AD_TYPE_32SERVICE_DATA 0x1c
#define BTM_BLE_AD_TYPE_128SERVICE_DATA 0x1d
#define BTM_BLE_AD_TYPE_FLAG HCI_EIR_FLAGS_TYPE /* 0x01 */
#define BTM_BLE_AD_TYPE_16SRV_PART HCI_EIR_MORE_16BITS_UUID_TYPE /* 0x02 */
#define BTM_BLE_AD_TYPE_16SRV_CMPL HCI_EIR_COMPLETE_16BITS_UUID_TYPE /* 0x03 */
#define BTM_BLE_AD_TYPE_32SRV_PART HCI_EIR_MORE_32BITS_UUID_TYPE /* 0x04 */
#define BTM_BLE_AD_TYPE_32SRV_CMPL HCI_EIR_COMPLETE_32BITS_UUID_TYPE /* 0x05 */
#define BTM_BLE_AD_TYPE_128SRV_PART HCI_EIR_MORE_128BITS_UUID_TYPE /* 0x06 */
#define BTM_BLE_AD_TYPE_128SRV_CMPL HCI_EIR_COMPLETE_128BITS_UUID_TYPE /* 0x07 */
#define BTM_BLE_AD_TYPE_NAME_SHORT HCI_EIR_SHORTENED_LOCAL_NAME_TYPE /* 0x08 */
#define BTM_BLE_AD_TYPE_NAME_CMPL HCI_EIR_COMPLETE_LOCAL_NAME_TYPE /* 0x09 */
#define BTM_BLE_AD_TYPE_TX_PWR HCI_EIR_TX_POWER_LEVEL_TYPE /* 0x0A */
#define BTM_BLE_AD_TYPE_DEV_CLASS 0x0D
#define BTM_BLE_AD_TYPE_SM_TK 0x10
#define BTM_BLE_AD_TYPE_SM_OOB_FLAG 0x11
#define BTM_BLE_AD_TYPE_INT_RANGE 0x12
#define BTM_BLE_AD_TYPE_SOL_SRV_UUID 0x14
#define BTM_BLE_AD_TYPE_128SOL_SRV_UUID 0x15
#define BTM_BLE_AD_TYPE_SERVICE_DATA 0x16
#define BTM_BLE_AD_TYPE_PUBLIC_TARGET 0x17
#define BTM_BLE_AD_TYPE_RANDOM_TARGET 0x18
#define BTM_BLE_AD_TYPE_APPEARANCE 0x19
#define BTM_BLE_AD_TYPE_ADV_INT 0x1a
#define BTM_BLE_AD_TYPE_LE_DEV_ADDR 0x1b
#define BTM_BLE_AD_TYPE_LE_ROLE 0x1c
#define BTM_BLE_AD_TYPE_SPAIR_C256 0x1d
#define BTM_BLE_AD_TYPE_SPAIR_R256 0x1e
#define BTM_BLE_AD_TYPE_32SOL_SRV_UUID 0x1f
#define BTM_BLE_AD_TYPE_32SERVICE_DATA 0x20
#define BTM_BLE_AD_TYPE_128SERVICE_DATA 0x21
#define BTM_BLE_AD_TYPE_LE_SECURE_CONFIRM 0x22
#define BTM_BLE_AD_TYPE_LE_SECURE_RANDOM 0x23
#define BTM_BLE_AD_TYPE_URI 0x24
#define BTM_BLE_AD_TYPE_INDOOR_POSITION 0x25
#define BTM_BLE_AD_TYPE_TRANS_DISC_DATA 0x26
#define BTM_BLE_AD_TYPE_LE_SUPPORT_FEATURE 0x27
#define BTM_BLE_AD_TYPE_CHAN_MAP_UPDATE 0x28
#define BTM_BLE_AD_TYPE_MANU HCI_EIR_MANUFACTURER_SPECIFIC_TYPE /* 0xff */
typedef UINT8 tBTM_BLE_AD_TYPE;

View file

@ -65,6 +65,8 @@
#define GATT_CONGESTED 0x8f
#define GATT_STACK_RSP 0x90
#define GATT_APP_RSP 0x91
//Error caused by customer application or stack bug
#define GATT_ESP_ERROR 0X9f
/* 0xE0 ~ 0xFC reserved for future use */
#define GATT_CCC_CFG_ERR 0xFD /* Client Characteristic Configuration Descriptor Improperly Configured */

View file

@ -32,9 +32,14 @@
#if CONFIG_BT_ENABLED
/* Bluetooth system and controller config */
#define BTDM_CFG_BT_EM_RELEASE (1<<0)
#define BTDM_CFG_BT_DATA_RELEASE (1<<1)
/* Other reserved for future */
/* not for user call, so don't put to include file */
extern void btdm_osi_funcs_register(void *osi_funcs);
extern void btdm_controller_init(void);
extern void btdm_controller_init(uint32_t config_mask);
extern void btdm_controller_schedule(void);
extern void btdm_controller_deinit(void);
extern int btdm_controller_enable(esp_bt_mode_t mode);
@ -73,7 +78,7 @@ struct osi_funcs_t {
void *(*_mutex_create)(void);
int32_t (*_mutex_lock)(void *mutex);
int32_t (*_mutex_unlock)(void *mutex);
esp_err_t (* _read_efuse_mac)(uint8_t mac[6]);
int32_t (* _read_efuse_mac)(uint8_t mac[6]);
};
/* Static variable declare */
@ -124,6 +129,11 @@ static int32_t IRAM_ATTR mutex_unlock_wrapper(void *mutex)
return (int32_t)xSemaphoreGive(mutex);
}
static int32_t IRAM_ATTR read_mac_wrapper(uint8_t mac[6])
{
return esp_read_mac(mac, ESP_MAC_BT);
}
static struct osi_funcs_t osi_funcs = {
._set_isr = xt_set_interrupt_handler,
._ints_on = xt_ints_on,
@ -136,7 +146,7 @@ static struct osi_funcs_t osi_funcs = {
._mutex_create = mutex_create_wrapper,
._mutex_lock = mutex_lock_wrapper,
._mutex_unlock = mutex_unlock_wrapper,
._read_efuse_mac = esp_efuse_read_mac,
._read_efuse_mac = read_mac_wrapper
};
bool esp_vhci_host_check_send_available(void)
@ -154,11 +164,25 @@ void esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback)
API_vhci_host_register_callback((const vhci_host_callback_t *)callback);
}
static uint32_t btdm_config_mask_load(void)
{
uint32_t mask = 0x0;
#ifdef CONFIG_BT_DRAM_RELEASE
mask |= (BTDM_CFG_BT_EM_RELEASE | BTDM_CFG_BT_DATA_RELEASE);
#endif
return mask;
}
static void bt_controller_task(void *pvParam)
{
uint32_t btdm_cfg_mask = 0;
btdm_osi_funcs_register(&osi_funcs);
btdm_controller_init();
btdm_cfg_mask = btdm_config_mask_load();
btdm_controller_init(btdm_cfg_mask);
btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
/* Loop */

@ -1 +1 @@
Subproject commit dbac82b5c2694f2639161b0a2b3c0bd8c7d3efc5
Subproject commit 9a4bb1d5287572664f170f9df4dbfd71babdfc68

View file

@ -50,10 +50,12 @@ extern "C" {
typedef struct {
gpio_num_t gpio_cd; ///< GPIO number of card detect signal
gpio_num_t gpio_wp; ///< GPIO number of write protect signal
uint8_t width; ///< Bus width used by the slot (might be less than the max width supported)
} sdmmc_slot_config_t;
#define SDMMC_SLOT_NO_CD ((gpio_num_t) -1) ///< indicates that card detect line is not used
#define SDMMC_SLOT_NO_WP ((gpio_num_t) -1) ///< indicates that write protect line is not used
#define SDMMC_SLOT_WIDTH_DEFAULT 0 ///< use the default width for the slot (8 for slot 0, 4 for slot 1)
/**
* Macro defining default configuration of SDMMC host slot
@ -61,6 +63,7 @@ typedef struct {
#define SDMMC_SLOT_CONFIG_DEFAULT() {\
.gpio_cd = SDMMC_SLOT_NO_CD, \
.gpio_wp = SDMMC_SLOT_NO_WP, \
.width = SDMMC_SLOT_WIDTH_DEFAULT, \
}
/**

View file

@ -478,7 +478,8 @@ esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_
* @param uart_queue UART event queue handle (out param). On success, a new queue handle is written here to provide
* access to UART events. If set to NULL, driver will not use an event queue.
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info. Do not set ESP_INTR_FLAG_IRAM here
* (the driver's ISR handler is not located in IRAM)
*
* @return
* - ESP_OK Success

View file

@ -299,20 +299,31 @@ esp_err_t sdmmc_host_init_slot(int slot, const sdmmc_slot_config_t* slot_config)
}
int gpio_cd = slot_config->gpio_cd;
int gpio_wp = slot_config->gpio_wp;
uint8_t slot_width = slot_config->width;
// Configure pins
const sdmmc_slot_info_t* pslot = &s_slot_info[slot];
if (slot_width == SDMMC_SLOT_WIDTH_DEFAULT) {
slot_width = pslot->width;
}
else if (slot_width > pslot->width) {
return ESP_ERR_INVALID_ARG;
}
configure_pin(pslot->clk);
configure_pin(pslot->cmd);
configure_pin(pslot->d0);
configure_pin(pslot->d1);
configure_pin(pslot->d2);
configure_pin(pslot->d3);
if (pslot->width == 8) {
configure_pin(pslot->d4);
configure_pin(pslot->d5);
configure_pin(pslot->d6);
configure_pin(pslot->d7);
if (slot_width >= 4) {
configure_pin(pslot->d1);
configure_pin(pslot->d2);
configure_pin(pslot->d3);
if (slot_width == 8) {
configure_pin(pslot->d4);
configure_pin(pslot->d5);
configure_pin(pslot->d6);
configure_pin(pslot->d7);
}
}
if (gpio_cd != -1) {
gpio_set_direction(gpio_cd, GPIO_MODE_INPUT);

View file

@ -470,7 +470,7 @@ esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_
}
//internal isr handler for default driver code.
static void IRAM_ATTR uart_rx_intr_handler_default(void *param)
static void uart_rx_intr_handler_default(void *param)
{
uart_obj_t *p_uart = (uart_obj_t*) param;
uint8_t uart_num = p_uart->uart_num;
@ -1002,6 +1002,9 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b
ESP_LOGE(UART_TAG, "UART driver already installed");
return ESP_FAIL;
}
assert((intr_alloc_flags & ESP_INTR_FLAG_IRAM) == 0); /* uart_rx_intr_handler_default is not in IRAM */
uart_isr_register(uart_num, uart_rx_intr_handler_default, p_uart_obj[uart_num], intr_alloc_flags, &p_uart_obj[uart_num]->intr_handle);
uart_intr_config_t uart_intr = {
.intr_enable_mask = UART_RXFIFO_FULL_INT_ENA_M

View file

@ -105,6 +105,28 @@ config MEMMAP_SPISRAM
main memory map. Enable this if you have this hardware and want to use it in the same
way as on-chip RAM.
choice NUMBER_OF_MAC_ADDRESS_GENERATED_FROM_EFUSE
bool "Number of MAC address generated from the hardware MAC address in efuse"
default FOUR_MAC_ADDRESS_FROM_EFUSE
help
Config the number of MAC address which is generated from the hardware MAC address in efuse.
If the number is two, the MAC addresses of WiFi station and bluetooth are generated from
the hardware MAC address in efuse. The MAC addresses of WiFi softap and ethernet are derived
from that of WiFi station and bluetooth respectively.
If the number is four, the MAC addresses of WiFi station, WiFi softap, bluetooth and ethernet
are all generated from the hardware MAC address in efuse.
config TWO_MAC_ADDRESS_FROM_EFUSE
bool "Two"
config FOUR_MAC_ADDRESS_FROM_EFUSE
bool "Four"
endchoice
config NUMBER_OF_MAC_ADDRESS_GENERATED_FROM_EFUSE
int
default 2 if TWO_MAC_ADDRESS_FROM_EFUSE
default 4 if FOUR_MAC_ADDRESS_FROM_EFUSE
config SYSTEM_EVENT_QUEUE_SIZE
int "System event queue size"
default 32
@ -491,15 +513,61 @@ config SW_COEXIST_ENABLE
automatically managed, no user intervention is required.
config ESP32_WIFI_RX_BUFFER_NUM
int "Max number of WiFi RX buffers"
config ESP32_WIFI_STATIC_RX_BUFFER_NUM
int "Max number of WiFi static RX buffers"
depends on WIFI_ENABLED
range 2 25
default 10
help
Set the number of WiFi rx buffers. Each buffer takes approximately 1.6KB of RAM.
Larger number for higher throughput but more memory. Smaller number for lower
throughput but less memory.
Set the number of WiFi static rx buffers. Each buffer takes approximately 1.6KB of RAM.
The static rx buffers are allocated when esp_wifi_init is called, they are not freed
until esp_wifi_deinit is called.
WiFi hardware use these buffers to receive packets, generally larger number for higher
throughput but more memory, smaller number for lower throughput but less memory.
config ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM
int "Max number of WiFi dynamic RX buffers"
depends on WIFI_ENABLED
range 0 64
default 0
help
Set the number of WiFi dynamic rx buffers, 0 means no limitation for dynamic rx buffer
allocation. The size of dynamic rx buffers is not fixed.
For each received packet in static rx buffers, WiFi driver makes a copy
to dynamic rx buffers and then deliver it to high layer stack. The dynamic rx buffer
is freed when the application, such as socket, successfully received the packet.
For some applications, the WiFi driver receiving speed is faster than application
consuming speed, we may run out of memory if no limitation for the dynamic rx buffer
number. Generally the number of dynamic rx buffer should be no less than static
rx buffer number if it is not 0.
config ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM
int "Max number of WiFi dynamic TX buffers"
depends on WIFI_ENABLED
range 16 64
default 32
help
Set the number of WiFi dynamic tx buffers, 0 means no limitation for dynamic tx buffer
allocation. The size of dynamic tx buffers is not fixed.
For each tx packet from high layer stack, WiFi driver make a copy of it. For some applications,
especially the UDP application, the high layer deliver speed is faster than the WiFi tx
speed, we may run out of memory if no limitation for the dynamic tx buffer number.
config ESP32_WIFI_AMPDU_ENABLED
bool "WiFi AMPDU"
depends on WIFI_ENABLED
default y
help
Select this option to enable AMPDU feature
config ESP32_WIFI_NVS_ENABLED
bool "WiFi NVS flash"
depends on WIFI_ENABLED
default y
help
Select this option to enable WiFi NVS flash
config PHY_ENABLED
bool

View file

@ -38,7 +38,7 @@
#include "tcpip_adapter.h"
#include "heap_alloc_caps.h"
#include "esp_heap_alloc_caps.h"
#include "sdkconfig.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
@ -106,8 +106,6 @@ void IRAM_ATTR call_start_cpu0()
memset(&_rtc_bss_start, 0, (&_rtc_bss_end - &_rtc_bss_start) * sizeof(_rtc_bss_start));
}
// Initialize heap allocator
heap_alloc_caps_init();
ESP_EARLY_LOGI(TAG, "Pro cpu up.");
@ -131,6 +129,15 @@ void IRAM_ATTR call_start_cpu0()
ESP_EARLY_LOGI(TAG, "Single core mode");
CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN);
#endif
/* Initialize heap allocator. WARNING: This *needs* to happen *after* the app cpu has booted.
If the heap allocator is initialized first, it will put free memory linked list items into
memory also used by the ROM. Starting the app cpu will let its ROM initialize that memory,
corrupting those linked lists. Initializing the allocator *after* the app cpu has booted
works around this problem. */
heap_alloc_caps_init();
ESP_EARLY_LOGI(TAG, "Pro cpu start user code");
start_cpu0();
}
@ -250,6 +257,8 @@ static void main_task(void* args)
// Now that the application is about to start, disable boot watchdogs
REG_CLR_BIT(TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN_S);
REG_CLR_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN);
//Enable allocation in region where the startup stacks were located.
heap_alloc_enable_nonos_stack_tag();
app_main();
vTaskDelete(NULL);
}

View file

@ -126,6 +126,9 @@ void IRAM_ATTR esp_deep_sleep_start()
if (s_config.wakeup_triggers & EXT_EVENT1_TRIG_EN) {
ext1_wakeup_prepare();
}
if (s_config.wakeup_triggers & SAR_TRIG_EN) {
SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_WAKEUP_FORCE_EN);
}
// TODO: move timer wakeup configuration into a similar function
// once rtc_sleep is opensourced.
@ -163,6 +166,10 @@ void system_deep_sleep(uint64_t) __attribute__((alias("esp_deep_sleep")));
esp_err_t esp_deep_sleep_enable_ulp_wakeup()
{
#ifdef CONFIG_ULP_COPROC_ENABLED
if(s_config.wakeup_triggers & RTC_EXT_EVENT0_TRIG_EN) {
ESP_LOGE(TAG, "Conflicting wake-up trigger: ext0");
return ESP_ERR_INVALID_STATE;
}
s_config.wakeup_triggers |= RTC_SAR_TRIG_EN;
return ESP_OK;
#else
@ -177,6 +184,26 @@ esp_err_t esp_deep_sleep_enable_timer_wakeup(uint64_t time_in_us)
return ESP_OK;
}
esp_err_t esp_deep_sleep_enable_touchpad_wakeup()
{
if (s_config.wakeup_triggers & (RTC_EXT_EVENT0_TRIG_EN)) {
ESP_LOGE(TAG, "Conflicting wake-up trigger: ext0");
return ESP_ERR_INVALID_STATE;
}
s_config.wakeup_triggers |= RTC_TOUCH_TRIG_EN;
return ESP_OK;
}
touch_pad_t esp_deep_sleep_get_touchpad_wakeup_status()
{
if (esp_deep_sleep_get_wakeup_cause() != ESP_DEEP_SLEEP_WAKEUP_TOUCHPAD) {
return TOUCH_PAD_MAX;
}
uint32_t touch_mask = REG_GET_FIELD(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_MEAS_EN);
assert(touch_mask != 0 && "wakeup reason is RTC_TOUCH_TRIG_EN but SENS_TOUCH_MEAS_EN is zero");
return (touch_pad_t) (__builtin_ffs(touch_mask) - 1);
}
esp_err_t esp_deep_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level)
{
if (level < 0 || level > 1) {
@ -185,6 +212,10 @@ esp_err_t esp_deep_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level)
if (!RTC_GPIO_IS_VALID_GPIO(gpio_num)) {
return ESP_ERR_INVALID_ARG;
}
if (s_config.wakeup_triggers & (RTC_TOUCH_TRIG_EN | RTC_SAR_TRIG_EN)) {
ESP_LOGE(TAG, "Conflicting wake-up triggers: touch / ULP");
return ESP_ERR_INVALID_STATE;
}
s_config.ext0_rtc_gpio_num = rtc_gpio_desc[gpio_num].rtc_num;
s_config.ext0_trigger_level = level;
s_config.wakeup_triggers |= RTC_EXT_EVENT0_TRIG_EN;
@ -276,8 +307,7 @@ static void ext1_wakeup_prepare()
uint64_t esp_deep_sleep_get_ext1_wakeup_status()
{
int wakeup_reason = REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_CAUSE);
if (wakeup_reason != RTC_EXT_EVENT1_TRIG) {
if (esp_deep_sleep_get_wakeup_cause() != ESP_DEEP_SLEEP_WAKEUP_EXT1) {
return 0;
}
uint32_t status = REG_GET_FIELD(RTC_CNTL_EXT_WAKEUP1_STATUS_REG, RTC_CNTL_EXT_WAKEUP1_STATUS);
@ -296,6 +326,28 @@ uint64_t esp_deep_sleep_get_ext1_wakeup_status()
return gpio_mask;
}
esp_deep_sleep_wakeup_cause_t esp_deep_sleep_get_wakeup_cause()
{
if (rtc_get_reset_reason(0) != DEEPSLEEP_RESET) {
return ESP_DEEP_SLEEP_WAKEUP_UNDEFINED;
}
uint32_t wakeup_cause = REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_CAUSE);
if (wakeup_cause & RTC_EXT_EVENT0_TRIG) {
return ESP_DEEP_SLEEP_WAKEUP_EXT0;
} else if (wakeup_cause & RTC_EXT_EVENT1_TRIG) {
return ESP_DEEP_SLEEP_WAKEUP_EXT1;
} else if (wakeup_cause & RTC_TIMER_EXPIRE) {
return ESP_DEEP_SLEEP_WAKEUP_TIMER;
} else if (wakeup_cause & RTC_TOUCH_TRIG) {
return ESP_DEEP_SLEEP_WAKEUP_TOUCHPAD;
} else if (wakeup_cause & RTC_SAR_TRIG) {
return ESP_DEEP_SLEEP_WAKEUP_ULP;
} else {
return ESP_DEEP_SLEEP_WAKEUP_UNDEFINED;
}
}
esp_err_t esp_deep_sleep_pd_config(esp_deep_sleep_pd_domain_t domain,
esp_deep_sleep_pd_option_t option)
{
@ -333,13 +385,15 @@ static uint32_t get_power_down_flags()
s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] = ESP_PD_OPTION_ON;
}
// RTC_PERIPH is needed for EXT0 wakeup and for ULP.
// If RTC_PERIPH is auto, and both EXT0 and ULP aren't enabled,
// power down RTC_PERIPH.
// RTC_PERIPH is needed for EXT0 wakeup.
// If RTC_PERIPH is auto, and EXT0 isn't enabled, power down RTC_PERIPH.
if (s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] == ESP_PD_OPTION_AUTO) {
if (s_config.wakeup_triggers &
(RTC_SAR_TRIG_EN | RTC_EXT_EVENT0_TRIG_EN)) {
if (s_config.wakeup_triggers & RTC_EXT_EVENT0_TRIG_EN) {
s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] = ESP_PD_OPTION_ON;
} else if (s_config.wakeup_triggers & (RTC_TOUCH_TRIG_EN | RTC_SAR_TRIG_EN)) {
// In both rev. 0 and rev. 1 of ESP32, forcing power up of RTC_PERIPH
// prevents ULP timer and touch FSMs from working correctly.
s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] = ESP_PD_OPTION_OFF;
}
}

View file

@ -45,14 +45,9 @@ do{\
}\
} while(0)
typedef esp_err_t (*system_event_handle_fn_t)(system_event_t *e);
typedef struct {
system_event_id_t event_id;
system_event_handle_fn_t event_handle;
} system_event_handle_t;
typedef esp_err_t (*system_event_handler_t)(system_event_t *e);
#ifdef CONFIG_WIFI_ENABLED
static esp_err_t system_event_ap_start_handle_default(system_event_t *event);
static esp_err_t system_event_ap_stop_handle_default(system_event_t *event);
static esp_err_t system_event_sta_start_handle_default(system_event_t *event);
@ -60,39 +55,50 @@ static esp_err_t system_event_sta_stop_handle_default(system_event_t *event);
static esp_err_t system_event_sta_connected_handle_default(system_event_t *event);
static esp_err_t system_event_sta_disconnected_handle_default(system_event_t *event);
static esp_err_t system_event_sta_got_ip_default(system_event_t *event);
#endif
#ifdef CONFIG_ETHERNET
static esp_err_t system_event_eth_start_handle_default(system_event_t *event);
static esp_err_t system_event_eth_stop_handle_default(system_event_t *event);
static esp_err_t system_event_eth_connected_handle_default(system_event_t *event);
static esp_err_t system_event_eth_disconnected_handle_default(system_event_t *event);
#endif
static system_event_handle_t g_system_event_handle_table[] = {
{SYSTEM_EVENT_WIFI_READY, NULL},
{SYSTEM_EVENT_SCAN_DONE, NULL},
{SYSTEM_EVENT_STA_START, system_event_sta_start_handle_default},
{SYSTEM_EVENT_STA_STOP, system_event_sta_stop_handle_default},
{SYSTEM_EVENT_STA_CONNECTED, system_event_sta_connected_handle_default},
{SYSTEM_EVENT_STA_DISCONNECTED, system_event_sta_disconnected_handle_default},
{SYSTEM_EVENT_STA_AUTHMODE_CHANGE, NULL},
{SYSTEM_EVENT_STA_GOT_IP, system_event_sta_got_ip_default},
{SYSTEM_EVENT_STA_WPS_ER_SUCCESS, NULL},
{SYSTEM_EVENT_STA_WPS_ER_FAILED, NULL},
{SYSTEM_EVENT_STA_WPS_ER_TIMEOUT, NULL},
{SYSTEM_EVENT_STA_WPS_ER_PIN, NULL},
{SYSTEM_EVENT_AP_START, system_event_ap_start_handle_default},
{SYSTEM_EVENT_AP_STOP, system_event_ap_stop_handle_default},
{SYSTEM_EVENT_AP_STACONNECTED, NULL},
{SYSTEM_EVENT_AP_STADISCONNECTED, NULL},
{SYSTEM_EVENT_AP_PROBEREQRECVED, NULL},
{SYSTEM_EVENT_AP_STA_GOT_IP6, NULL},
{SYSTEM_EVENT_ETH_START, system_event_eth_start_handle_default},
{SYSTEM_EVENT_ETH_STOP, system_event_eth_stop_handle_default},
{SYSTEM_EVENT_ETH_CONNECTED, system_event_eth_connected_handle_default},
{SYSTEM_EVENT_ETH_DISCONNECTED, system_event_eth_disconnected_handle_default},
{SYSTEM_EVENT_ETH_GOT_IP, NULL},
{SYSTEM_EVENT_MAX, NULL},
/* Default event handler functions
Any entry in this table which is disabled by config will have a NULL handler.
*/
static const system_event_handler_t default_event_handlers[SYSTEM_EVENT_MAX] = {
#ifdef CONFIG_WIFI_ENABLED
[SYSTEM_EVENT_WIFI_READY] = NULL,
[SYSTEM_EVENT_SCAN_DONE] = NULL,
[SYSTEM_EVENT_STA_START] = system_event_sta_start_handle_default,
[SYSTEM_EVENT_STA_STOP] = system_event_sta_stop_handle_default,
[SYSTEM_EVENT_STA_CONNECTED] = system_event_sta_connected_handle_default,
[SYSTEM_EVENT_STA_DISCONNECTED] = system_event_sta_disconnected_handle_default,
[SYSTEM_EVENT_STA_AUTHMODE_CHANGE] = NULL,
[SYSTEM_EVENT_STA_GOT_IP] = system_event_sta_got_ip_default,
[SYSTEM_EVENT_STA_WPS_ER_SUCCESS] = NULL,
[SYSTEM_EVENT_STA_WPS_ER_FAILED] = NULL,
[SYSTEM_EVENT_STA_WPS_ER_TIMEOUT] = NULL,
[SYSTEM_EVENT_STA_WPS_ER_PIN] = NULL,
[SYSTEM_EVENT_AP_START] = system_event_ap_start_handle_default,
[SYSTEM_EVENT_AP_STOP] = system_event_ap_stop_handle_default,
[SYSTEM_EVENT_AP_STACONNECTED] = NULL,
[SYSTEM_EVENT_AP_STADISCONNECTED] = NULL,
[SYSTEM_EVENT_AP_PROBEREQRECVED] = NULL,
[SYSTEM_EVENT_AP_STA_GOT_IP6] = NULL,
#endif
#ifdef CONFIG_ETHERNET
[SYSTEM_EVENT_ETH_START] = system_event_eth_start_handle_default,
[SYSTEM_EVENT_ETH_STOP] = system_event_eth_stop_handle_default,
[SYSTEM_EVENT_ETH_CONNECTED] = system_event_eth_connected_handle_default,
[SYSTEM_EVENT_ETH_DISCONNECTED] = system_event_eth_disconnected_handle_default,
[SYSTEM_EVENT_ETH_GOT_IP] = NULL,
#endif
};
#ifdef CONFIG_ETHERNET
esp_err_t system_event_eth_start_handle_default(system_event_t *event)
{
tcpip_adapter_ip_info_t eth_ip;
@ -121,7 +127,6 @@ esp_err_t system_event_eth_connected_handle_default(system_event_t *event)
tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_ETH, &status);
if (status == TCPIP_ADAPTER_DHCP_INIT) {
tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_ETH);
} else if (status == TCPIP_ADAPTER_DHCP_STOPPED) {
tcpip_adapter_ip_info_t eth_ip;
@ -149,9 +154,9 @@ esp_err_t system_event_eth_disconnected_handle_default(system_event_t *event)
tcpip_adapter_down(TCPIP_ADAPTER_IF_ETH);
return ESP_OK;
}
#endif
#ifdef CONFIG_WIFI_ENABLED
static esp_err_t system_event_sta_got_ip_default(system_event_t *event)
{
WIFI_API_CALL_CHECK("esp_wifi_internal_set_sta_ip", esp_wifi_internal_set_sta_ip(), ESP_OK);
@ -245,6 +250,7 @@ esp_err_t system_event_sta_disconnected_handle_default(system_event_t *event)
WIFI_API_CALL_CHECK("esp_wifi_internal_reg_rxcb", esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, NULL), ESP_OK);
return ESP_OK;
}
#endif
static esp_err_t esp_system_event_debug(system_event_t *event)
{
@ -377,10 +383,10 @@ esp_err_t esp_event_process_default(system_event_t *event)
}
esp_system_event_debug(event);
if ((event->event_id < SYSTEM_EVENT_MAX) && (event->event_id == g_system_event_handle_table[event->event_id].event_id)) {
if (g_system_event_handle_table[event->event_id].event_handle) {
if ((event->event_id < SYSTEM_EVENT_MAX)) {
if (default_event_handlers[event->event_id] != NULL) {
ESP_LOGV(TAG, "enter default callback");
g_system_event_handle_table[event->event_id].event_handle(event);
default_event_handlers[event->event_id](event);
ESP_LOGV(TAG, "exit default callback");
}
} else {

View file

@ -36,6 +36,7 @@ hardwiring addresses.
//Amount of priority slots for the tag descriptors.
#define NO_PRIOS 3
typedef struct {
const char *name;
uint32_t prio[NO_PRIOS];
@ -46,6 +47,9 @@ typedef struct {
Tag descriptors. These describe the capabilities of a bit of memory that's tagged with the index into this table.
Each tag contains NO_PRIOS entries; later entries are only taken if earlier ones can't fulfill the memory request.
Make sure there are never more than HEAPREGIONS_MAX_TAGCOUNT (in heap_regions.h) tags (ex the last empty marker)
WARNING: The current code assumes the ROM stacks are located in tag 1; no allocation from this tag can be done until
the FreeRTOS scheduler has started.
*/
static const tag_desc_t tag_desc[]={
{ "DRAM", { MALLOC_CAP_DMA|MALLOC_CAP_8BIT, MALLOC_CAP_32BIT, 0 }, false}, //Tag 0: Plain ole D-port RAM
@ -89,8 +93,8 @@ This array is *NOT* const because it gets modified depending on what pools are/a
static HeapRegionTagged_t regions[]={
{ (uint8_t *)0x3F800000, 0x20000, 15, 0}, //SPI SRAM, if available
{ (uint8_t *)0x3FFAE000, 0x2000, 0, 0}, //pool 16 <- used for rom code
{ (uint8_t *)0x3FFB0000, 0x8000, 0, 0}, //pool 15 <- can be used for BT
{ (uint8_t *)0x3FFB8000, 0x8000, 0, 0}, //pool 14 <- can be used for BT
{ (uint8_t *)0x3FFB0000, 0x8000, 0, 0}, //pool 15 <- if BT is enabled, used as BT HW shared memory
{ (uint8_t *)0x3FFB8000, 0x8000, 0, 0}, //pool 14 <- if BT is enabled, used data memory for BT ROM functions.
{ (uint8_t *)0x3FFC0000, 0x2000, 0, 0}, //pool 10-13, mmu page 0
{ (uint8_t *)0x3FFC2000, 0x2000, 0, 0}, //pool 10-13, mmu page 1
{ (uint8_t *)0x3FFC4000, 0x2000, 0, 0}, //pool 10-13, mmu page 2
@ -134,6 +138,16 @@ static HeapRegionTagged_t regions[]={
{ NULL, 0, 0, 0} //end
};
/* For the startup code, the stacks live in memory tagged by this tag. Hence, we only enable allocating from this tag
once FreeRTOS has started up completely. */
#define NONOS_STACK_TAG 1
static bool nonos_stack_in_use=true;
void heap_alloc_enable_nonos_stack_tag()
{
nonos_stack_in_use=false;
}
//Modify regions array to disable the given range of memory.
static void disable_mem_region(void *from, void *to) {
@ -185,22 +199,43 @@ void heap_alloc_caps_init() {
//Disable the bits of memory where this code is loaded.
disable_mem_region(&_data_start, &_heap_start); //DRAM used by bss/data static variables
disable_mem_region(&_init_start, &_iram_text_end); //IRAM used by code
disable_mem_region((void*)0x3ffae000, (void*)0x3ffb0000); //knock out ROM data region
disable_mem_region((void*)0x40070000, (void*)0x40078000); //CPU0 cache region
disable_mem_region((void*)0x40078000, (void*)0x40080000); //CPU1 cache region
// TODO: this region should be checked, since we don't need to knock out all region finally
disable_mem_region((void*)0x3ffe0000, (void*)0x3ffe8000); //knock out ROM data region
/* Warning: The ROM stack is located in the 0x3ffe0000 area. We do not specifically disable that area here because
after the scheduler has started, the ROM stack is not used anymore by anything. We handle it instead by not allowing
any mallocs from tag 1 (the IRAM/DRAM region) until the scheduler has started.
The 0x3ffe0000 region also contains static RAM for various ROM functions. The following lines
reserve the regions for UART and ETSC, so these functions are usable. Libraries like xtos, which are
not usable in FreeRTOS anyway, are commented out in the linker script so they cannot be used; we
do not disable their memory regions here and they will be used as general purpose heap memory.
Enabling the heap allocator for this region but disabling allocation here until FreeRTOS is started up
is a somewhat risky action in theory, because on initializing the allocator, vPortDefineHeapRegionsTagged
will go and write linked list entries at the start and end of all regions. For the ESP32, these linked
list entries happen to end up in a region that is not touched by the stack; they can be placed safely there.*/
disable_mem_region((void*)0x3ffe0000, (void*)0x3ffe0440); //Reserve ROM PRO data region
disable_mem_region((void*)0x3ffe4000, (void*)0x3ffe4350); //Reserve ROM APP data region
#if CONFIG_BT_ENABLED
disable_mem_region((void*)0x3ffb0000, (void*)0x3ffc0000); //knock out BT data region
#if CONFIG_BT_DRAM_RELEASE
disable_mem_region((void*)0x3ffb0000, (void*)0x3ffb3000); //Reserve BT data region
disable_mem_region((void*)0x3ffb8000, (void*)0x3ffbbb28); //Reserve BT data region
disable_mem_region((void*)0x3ffbdb28, (void*)0x3ffc0000); //Reserve BT data region
#else
disable_mem_region((void*)0x3ffb0000, (void*)0x3ffc0000); //Reserve BT hardware shared memory & BT data region
#endif
disable_mem_region((void*)0x3ffae000, (void*)0x3ffaff10); //Reserve ROM data region, inc region needed for BT ROM routines
#else
disable_mem_region((void*)0x3ffae000, (void*)0x3ffae2a0); //Reserve ROM data region
#endif
#if CONFIG_MEMMAP_TRACEMEM
#if CONFIG_MEMMAP_TRACEMEM_TWOBANKS
disable_mem_region((void*)0x3fff8000, (void*)0x40000000); //knock out trace mem region
disable_mem_region((void*)0x3fff8000, (void*)0x40000000); //Reserve trace mem region
#else
disable_mem_region((void*)0x3fff8000, (void*)0x3fffc000); //knock out trace mem region
disable_mem_region((void*)0x3fff8000, (void*)0x3fffc000); //Reserve trace mem region
#endif
#endif
@ -311,6 +346,10 @@ void *pvPortMallocCaps( size_t xWantedSize, uint32_t caps )
for (prio=0; prio<NO_PRIOS; prio++) {
//Iterate over tag descriptors for this priority
for (tag=0; tag_desc[tag].prio[prio]!=MALLOC_CAP_INVALID; tag++) {
if (nonos_stack_in_use && tag == NONOS_STACK_TAG) {
//Non-os stack lives here and is still in use. Don't alloc here.
continue;
}
if ((tag_desc[tag].prio[prio]&caps)!=0) {
//Tag has at least one of the caps requested. If caps has other bits set that this prio
//doesn't cover, see if they're available in other prios.

View file

@ -17,6 +17,7 @@
#include <stdint.h>
#include "esp_err.h"
#include "driver/gpio.h"
#include "driver/touch_pad.h"
#ifdef __cplusplus
extern "C" {
@ -50,12 +51,28 @@ typedef enum {
ESP_PD_OPTION_AUTO //!< Keep power domain enabled in deep sleep, if it is needed by one of the wakeup options. Otherwise power it down.
} esp_deep_sleep_pd_option_t;
/**
* @brief Deep sleep wakeup cause
*/
typedef enum {
ESP_DEEP_SLEEP_WAKEUP_UNDEFINED, //! Wakeup was not caused by deep sleep
ESP_DEEP_SLEEP_WAKEUP_EXT0, //! Wakeup caused by external signal using RTC_IO
ESP_DEEP_SLEEP_WAKEUP_EXT1, //! Wakeup caused by external signal using RTC_CNTL
ESP_DEEP_SLEEP_WAKEUP_TIMER, //! Wakeup caused by timer
ESP_DEEP_SLEEP_WAKEUP_TOUCHPAD, //! Wakeup caused by touchpad
ESP_DEEP_SLEEP_WAKEUP_ULP, //! Wakeup caused by ULP program
} esp_deep_sleep_wakeup_cause_t;
/**
* @brief Enable wakeup by ULP coprocessor
* @note In revisions 0 and 1 of the ESP32, ULP wakeup source
* can not be used when RTC_PERIPH power domain is forced
* to be powered on (ESP_PD_OPTION_ON) or when ext0 wakeup
* source is used.
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_STATE if ULP co-processor is not enabled.
* - ESP_ERR_INVALID_STATE if ULP co-processor is not enabled or if wakeup triggers conflict
*/
esp_err_t esp_deep_sleep_enable_ulp_wakeup();
@ -68,6 +85,29 @@ esp_err_t esp_deep_sleep_enable_ulp_wakeup();
*/
esp_err_t esp_deep_sleep_enable_timer_wakeup(uint64_t time_in_us);
/**
* @brief Enable wakeup by touch sensor
*
* @note In revisions 0 and 1 of the ESP32, touch wakeup source
* can not be used when RTC_PERIPH power domain is forced
* to be powered on (ESP_PD_OPTION_ON) or when ext0 wakeup
* source is used.
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_STATE if wakeup triggers conflict
*/
esp_err_t esp_deep_sleep_enable_touchpad_wakeup();
/**
* @brief Get the touch pad which caused wakeup
*
* If wakeup was caused by another source, this function will return TOUCH_PAD_MAX;
*
* @return touch pad which caused wakeup
*/
touch_pad_t esp_deep_sleep_get_touchpad_wakeup_status();
/**
* @brief Enable wakeup using a pin
*
@ -81,6 +121,9 @@ esp_err_t esp_deep_sleep_enable_timer_wakeup(uint64_t time_in_us);
* configured in esp_deep_sleep_start, immediately before
* entering deep sleep.
*
* @note In revisions 0 and 1 of the ESP32, ext0 wakeup source
* can not be used together with touch or ULP wakeup sources.
*
* @param gpio_num GPIO number used as wakeup source. Only GPIOs which are have RTC
* functionality can be used: 0,2,4,12-15,25-27,32-39.
* @param level input level which will trigger wakeup (0=low, 1=high)
@ -88,6 +131,7 @@ esp_err_t esp_deep_sleep_enable_timer_wakeup(uint64_t time_in_us);
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if the selected GPIO is not an RTC GPIO,
* or the mode is invalid
* - ESP_ERR_INVALID_STATE if wakeup triggers conflict
*/
esp_err_t esp_deep_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level);
@ -188,6 +232,15 @@ void esp_deep_sleep(uint64_t time_in_us) __attribute__((noreturn));
*/
void system_deep_sleep(uint64_t time_in_us) __attribute__((noreturn, deprecated));
/**
* @brief Get the source which caused deep sleep wakeup
*
* @return wakeup cause, or ESP_DEEP_SLEEP_WAKEUP_UNDEFINED if reset reason is other than deep sleep reset.
*/
esp_deep_sleep_wakeup_cause_t esp_deep_sleep_get_wakeup_cause();
/**
* @brief Default stub to run on wake from deep sleep.
*

View file

@ -11,10 +11,10 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef __ESP_ERR_H__
#define __ESP_ERR_H__
#pragma once
#include <stdint.h>
#include <stdio.h>
#include <assert.h>
#ifdef __cplusplus
@ -40,15 +40,38 @@ typedef int32_t esp_err_t;
#define ESP_ERR_WIFI_BASE 0x3000 /*!< Starting number of WiFi error codes */
void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression) __attribute__((noreturn));
#ifndef __ASSERT_FUNC
/* This won't happen on IDF, which defines __ASSERT_FUNC in assert.h, but it does happen when building on the host which
uses /usr/include/assert.h or equivalent.
*/
#ifdef __ASSERT_FUNCTION
#define __ASSERT_FUNC __ASSERT_FUNCTION /* used in glibc assert.h */
#else
#define __ASSERT_FUNC "??"
#endif
#endif
/**
* Macro which can be used to check the error code,
* and terminate the program in case the code is not ESP_OK.
* Prints the failed statement to serial output.
* Prints the error code, error location, and the failed statement to serial output.
*
* Disabled if assertions are disabled.
*/
#define ESP_ERROR_CHECK(x) do { esp_err_t rc = (x); if (rc != ESP_OK) { assert(0 && #x);} } while(0);
#ifdef NDEBUG
#define ESP_ERROR_CHECK(x) do { (x); } while (0)
#else
#define ESP_ERROR_CHECK(x) do { \
esp_err_t rc = (x); \
if (rc != ESP_OK) { \
_esp_error_check_failed(rc, __FILE__, __LINE__, \
__ASSERT_FUNC, #x); \
} \
} while(0);
#endif
#ifdef __cplusplus
}
#endif
#endif /* __ESP_ERR_H__ */

View file

@ -38,6 +38,16 @@
*/
void heap_alloc_caps_init();
/**
* @brief Enable the memory region where the startup stacks are located for allocation
*
* On startup, the pro/app CPUs have a certain memory region they use as stack, so we
* cannot do allocations in the regions these stack frames are. When FreeRTOS is
* completely started, they do not use that memory anymore and allocation there can
* be re-enabled.
*/
void heap_alloc_enable_nonos_stack_tag();
/**
* @brief Allocate a chunk of memory which has the given capabilities
*
@ -75,4 +85,6 @@ size_t xPortGetFreeHeapSizeCaps( uint32_t caps );
*/
size_t xPortGetMinimumEverFreeHeapSizeCaps( uint32_t caps );
#endif

View file

@ -24,6 +24,17 @@
extern "C" {
#endif
typedef enum {
ESP_MAC_WIFI_STA,
ESP_MAC_WIFI_SOFTAP,
ESP_MAC_BT,
ESP_MAC_ETH,
} esp_mac_type_t;
#define TWO_MAC_ADDRESS_FROM_EFUSE 2
#define FOUR_MAC_ADDRESS_FROM_EFUSE 4
#define NUM_MAC_ADDRESS_FROM_EFUSE CONFIG_NUMBER_OF_MAC_ADDRESS_GENERATED_FROM_EFUSE
/**
* @attention application don't need to call this function anymore. It do nothing and will
* be removed in future version.
@ -115,6 +126,47 @@ esp_err_t esp_efuse_read_mac(uint8_t* mac);
*/
esp_err_t system_efuse_read_mac(uint8_t mac[6]) __attribute__ ((deprecated));
/**
* @brief Read hardware MAC address and set MAC address of the interface.
*
* This function first reads hardware MAC address from efuse. Then set the MAC address of the interface
* including wifi station, wifi softap, bluetooth and ethernet.
*
* @param mac MAC address of the interface, length: 6 bytes.
* @param type type of MAC address, 0:wifi station, 1:wifi softap, 2:bluetooth, 3:ethernet.
*
* @return ESP_OK on success
*/
esp_err_t esp_read_mac(uint8_t* mac, esp_mac_type_t type);
/**
* @brief Derive MAC address.
*
* This function derives a local MAC address from an universal MAC address.
* Addresses can either be universally administered addresses or locally administered addresses.
* A universally administered address is uniquely assigned to a device by its manufacturer.
* The first three octets (in transmission order) identify the organization that issued the identifier
* and are known as the Organizationally Unique Identifier (OUI).[4] The remainder of the address
* (three octets for MAC-48 and EUI-48 or five for EUI-64) are assigned by that organization in nearly
* any manner they please, subject to the constraint of uniqueness. A locally administered address is
* assigned to a device by a network administrator, overriding the burned-in address.
* Universally administered and locally administered addresses are distinguished by setting
* the second-least-significant bit of the first octet of the address. This bit is also referred to
* as the U/L bit, short for Universal/Local, which identifies how the address is administered.
* If the bit is 0, the address is universally administered. If it is 1, the address is locally administered.
* In the example address 06-00-00-00-00-00 the first octet is 06 (hex), the binary form of which is 00000110,
* where the second-least-significant bit is 1. Therefore, it is a locally administered address.[7] Consequently,
* this bit is 0 in all OUIs.
* In ESP32, universal MAC address is generated from the hardware MAC address in efuse.
* Local MAC address is derived from the universal MAC address.
*
* @param dst_mac Derived local MAC address, length: 6 bytes.
* @param src_mac Source universal MAC address, length: 6 bytes.
*
* @return ESP_OK on success
*/
esp_err_t esp_derive_mac(uint8_t* dst_mac, const uint8_t* src_mac);
/**
* Get SDK version
*

View file

@ -31,22 +31,16 @@
#define ESP_TASK_PRIO_MAX (configMAX_PRIORITIES)
#define ESP_TASK_PRIO_MIN (0)
/* Wifi library task */
#define ESP_TASKD_WATCHDOG_PRIO (ESP_TASK_PRIO_MAX - 1)
#define ESP_TASKD_WATCHDOG_STACK 2048
#define ESP_TASK_WPA2_PRIO (ESP_TASK_PRIO_MAX - 1)
#define ESP_TASK_WPA2_STACK 2048
#define ESP_TASKD_WIFI_PRIO (ESP_TASK_PRIO_MAX - 2)
#define ESP_TASKD_WIFI_STACK 8196
#define ESP_TASKD_WIFI_TIMER_PRIO (ESP_TASK_PRIO_MAX - 3)
#define ESP_TASKD_WIFI_TIMER_STACK 2048
#define ESP_TASK_WPS_PRIO (ESP_TASK_PRIO_MIN + 2)
#define ESP_TASK_WPS_STACK 2048
/* Bt contoller Task */
/* controller */
#define ESP_TASK_BT_CONTROLLER_PRIO (ESP_TASK_PRIO_MAX - 1)
#define ESP_TASK_BT_CONTROLLER_STACK 4096
#ifdef CONFIG_NEWLIB_NANO_FORMAT
#define BT_TASK_EXTRA_STACK_SIZE (0)
#else
#define BT_TASK_EXTRA_STACK_SIZE (512)
#endif
#define ESP_TASK_BT_CONTROLLER_STACK (3584 + BT_TASK_EXTRA_STACK_SIZE)
/* idf task */
#define ESP_TASKD_EVENT_PRIO (ESP_TASK_PRIO_MAX - 5)

View file

@ -94,14 +94,45 @@ extern "C" {
* @brief WiFi stack configuration parameters passed to esp_wifi_init call.
*/
typedef struct {
system_event_handler_t event_handler; /**< WiFi event handler */
uint32_t rx_buf_num; /**< WiFi RX buffer number */
system_event_handler_t event_handler; /**< WiFi event handler */
int static_rx_buf_num; /**< WiFi static RX buffer number */
int dynamic_rx_buf_num; /**< WiFi dynamic RX buffer number */
int dynamic_tx_buf_num; /**< WiFi dynamic TX buffer number */
int ampdu_enable; /**< WiFi AMPDU feature enable flag */
int nvs_enable; /**< WiFi NVS flash enable flag */
int nano_enable; /**< Nano option for printf/scan family enable flag */
int magic; /**< WiFi init magic number, it should be the last field */
} wifi_init_config_t;
#if CONFIG_ESP32_WIFI_AMPDU_ENABLED
#define WIFI_AMPDU_ENABLED 1
#else
#define WIFI_AMPDU_ENABLED 0
#endif
#if CONFIG_ESP32_WIFI_NVS_ENABLED
#define WIFI_NVS_ENABLED 1
#else
#define WIFI_NVS_ENABLED 0
#endif
#if CONFIG_NEWLIB_NANO_FORMAT
#define WIFI_NANO_FORMAT_ENABLED 1
#else
#define WIFI_NANO_FORMAT_ENABLED 0
#endif
#define WIFI_INIT_CONFIG_MAGIC 0x1F2F3F4F
#ifdef CONFIG_WIFI_ENABLED
#define WIFI_INIT_CONFIG_DEFAULT() { \
.event_handler = &esp_event_send, \
.rx_buf_num = CONFIG_ESP32_WIFI_RX_BUFFER_NUM, \
.static_rx_buf_num = CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM,\
.dynamic_rx_buf_num = CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM,\
.dynamic_tx_buf_num = CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM,\
.ampdu_enable = WIFI_AMPDU_ENABLED,\
.nvs_enable = WIFI_NVS_ENABLED,\
.nano_enable = WIFI_NANO_FORMAT_ENABLED,\
.magic = WIFI_INIT_CONFIG_MAGIC\
};
#else
#define WIFI_INIT_CONFIG_DEFAULT #error Wifi is disabled in config, WIFI_INIT_CONFIG_DEFAULT will not work
@ -113,8 +144,11 @@ typedef struct {
* WiFi NVS structure etc, this WiFi also start WiFi task
*
* @attention 1. This API must be called before all other WiFi API can be called
* @attention 2. event_handler field in cfg should be set to a valid event handler function.
* In most cases, use the WIFI_INIT_CONFIG_DEFAULT macro which sets esp_event_send().
* @attention 2. Always use WIFI_INIT_CONFIG_DEFAULT macro to init the config to default values, this can
* guarantee all the fields got correct value when more fields are added into wifi_init_config_t
* in future release. If you want to set your owner initial values, overwrite the default values
* which are set by WIFI_INIT_CONFIG_DEFAULT, please be notified that the field 'magic' of
* wifi_init_config_t should always be WIFI_INIT_CONFIG_MAGIC!
*
* @param config provide WiFi init configuration
*
@ -130,7 +164,6 @@ esp_err_t esp_wifi_init(wifi_init_config_t *config);
* Free all resource allocated in esp_wifi_init and stop WiFi task
*
* @attention 1. This API should be called if you want to remove WiFi driver from the system
* @attention 2. This API can not be called yet and will be done in the future.
*
* @return ESP_OK: succeed
*/
@ -422,6 +455,7 @@ esp_err_t esp_wifi_get_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t *bw);
* @brief Set primary/secondary channel of ESP32
*
* @attention 1. This is a special API for sniffer
* @attention 2. This API should be called after esp_wifi_start() or esp_wifi_set_promiscuous()
*
* @param primary for HT20, primary is the channel number, for HT40, primary is the primary channel
* @param second for HT20, second is ignored, for HT40, second is the second channel

View file

@ -1,34 +1,3 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef HEAP_ALLOC_CAPS_H
#define HEAP_ALLOC_CAPS_H
#define MALLOC_CAP_EXEC (1<<0) //Memory must be able to run executable code
#define MALLOC_CAP_32BIT (1<<1) //Memory must allow for aligned 32-bit data accesses
#define MALLOC_CAP_8BIT (1<<2) //Memory must allow for 8/16/...-bit data accesses
#define MALLOC_CAP_DMA (1<<3) //Memory must be able to accessed by DMA
#define MALLOC_CAP_PID2 (1<<4) //Memory must be mapped to PID2 memory space
#define MALLOC_CAP_PID3 (1<<5) //Memory must be mapped to PID3 memory space
#define MALLOC_CAP_PID4 (1<<6) //Memory must be mapped to PID4 memory space
#define MALLOC_CAP_PID5 (1<<7) //Memory must be mapped to PID5 memory space
#define MALLOC_CAP_PID6 (1<<8) //Memory must be mapped to PID6 memory space
#define MALLOC_CAP_PID7 (1<<9) //Memory must be mapped to PID7 memory space
#define MALLOC_CAP_SPISRAM (1<<10) //Memory must be in SPI SRAM
#define MALLOC_CAP_INVALID (1<<31) //Memory can't be used / list end marker
void heap_alloc_caps_init();
void *pvPortMallocCaps(size_t xWantedSize, uint32_t caps);
#endif
#pragma once
#warning heap_alloc_caps.h has been renamed to esp_heap_alloc_caps.h. The old header file is deprecated and will be removed in v3.0.
#include "esp_heap_alloc_caps.h"

View file

@ -504,12 +504,25 @@ void SPI_Write_Encrypt_Disable(void);
* @param uint32_t len : Length to write, should be 32 bytes aligned.
*
* @return SPI_FLASH_RESULT_OK : Data written successfully.
* SPI_FLASH_RESULT_ERR : Encrypto write error.
* SPI_FLASH_RESULT_ERR : Encryption write error.
* SPI_FLASH_RESULT_TIMEOUT : Encrypto write timeout.
*/
SpiFlashOpResult SPI_Encrypt_Write(uint32_t flash_addr, uint32_t *data, uint32_t len);
/** @brief Wait until SPI flash write operation is complete
*
* @note Please do not call this function in SDK.
*
* Reads the Write In Progress bit of the SPI flash status register,
* repeats until this bit is zero (indicating write complete).
*
* @return SPI_FLASH_RESULT_OK : Write is complete
* SPI_FLASH_RESULT_ERR : Error while reading status.
*/
SpiFlashOpResult SPI_Wait_Idle(SpiFlashChip *spi);
/** @brief Global SpiFlashChip structure used by ROM functions
*
*/

View file

@ -36,16 +36,6 @@ static inline void *get_sp()
return sp;
}
/* Return true if the CPU is in an interrupt context
(PS.UM == 0)
*/
static inline bool cpu_in_interrupt_context(void)
{
uint32_t ps;
RSR(PS, ps);
return (ps & PS_UM) == 0;
}
/* Functions to set page attributes for Region Protection option in the CPU.
* See Xtensa ISA Reference manual for explanation of arguments (section 4.6.3.2).
*/

View file

@ -1035,11 +1035,27 @@
#define DPORT_WIFI_CLK_EN_V 0xFFFFFFFF
#define DPORT_WIFI_CLK_EN_S 0
/* Mask for all Wifi clock bits - 0, 1, 2, 3, 6, 7, 8, 9, 10, 15 */
#define DPORT_WIFI_CLK_WIFI_EN 0x000007cf
#define DPORT_WIFI_CLK_WIFI_EN_M ((DPORT_WIFI_CLK_WIFI_EN_V)<<(DPORT_WIFI_CLK_WIFI_EN_S))
#define DPORT_WIFI_CLK_WIFI_EN_V 0x1FF
#define DPORT_WIFI_CLK_WIFI_EN_S 0
/* Mask for all Bluetooth clock bits - 11, 16, 17 */
#define DPORT_WIFI_CLK_BT_EN 0x61
#define DPORT_WIFI_CLK_BT_EN_M ((DPORT_WIFI_CLK_BT_EN_V)<<(DPORT_WIFI_CLK_BT_EN_S))
#define DPORT_WIFI_CLK_BT_EN_V 0x61
#define DPORT_WIFI_CLK_BT_EN_S 11
/* Remaining single bit clock masks */
#define DPORT_WIFI_CLK_SDIOSLAVE_EN BIT(4)
#define DPORT_WIFI_CLK_SDIO_HOST_EN BIT(13)
#define DPORT_WIFI_CLK_EMAC_EN BIT(14)
#define DPORT_WIFI_CLK_RNG_EN BIT(15)
#define DPORT_CORE_RST_EN_REG (DR_REG_DPORT_BASE + 0x0D0)
/* DPORT_CORE_RST : R/W ;bitpos:[31:0] ;default: 32'h0 ; */
/*description: */
#define DPROT_RW_BTLP_RST (BIT(10))
#define DPROT_RW_BTMAC_RST (BIT(9))
#define DPORT_RW_BTLP_RST (BIT(10))
#define DPORT_RW_BTMAC_RST (BIT(9))
#define DPORT_MACPWR_RST (BIT(8))
#define DPORT_EMAC_RST (BIT(7))
#define DPORT_SDIO_HOST_RST (BIT(6))

View file

@ -88,7 +88,7 @@ static inline void __attribute__ ((deprecated)) PIN_PULLDWN_EN(uint32_t PIN_NAME
#define FUNC_GPIO0_GPIO0_0 0
#define PERIPHS_IO_MUX_U0TXD_U (DR_REG_IO_MUX_BASE +0x88)
#define FUNC_U0TXD_EMAC_RXD2 3
#define FUNC_U0TXD_EMAC_RXD2 5
#define FUNC_U0TXD_GPIO1 2
#define FUNC_U0TXD_CLK_OUT3 1
#define FUNC_U0TXD_U0TXD 0
@ -181,7 +181,7 @@ static inline void __attribute__ ((deprecated)) PIN_PULLDWN_EN(uint32_t PIN_NAME
#define PERIPHS_IO_MUX_MTMS_U (DR_REG_IO_MUX_BASE +0x30)
#define FUNC_MTMS_EMAC_TXD2 5
#define FUNC_MTMS_SD_CLK 4
#define FUNC_MTMS_HS2_CLk 3
#define FUNC_MTMS_HS2_CLK 3
#define FUNC_MTMS_GPIO14 2
#define FUNC_MTMS_HSPICLK 1
#define FUNC_MTMS_MTMS 0

View file

@ -240,7 +240,7 @@
#define RTC_CNTL_TIME_VALID_S 30
/* frequency of RTC slow clock, Hz */
#define RTC_CTNL_SLOWCLK_FREQ 150000
#define RTC_CNTL_SLOWCLK_FREQ 150000
#define RTC_CNTL_TIME0_REG (DR_REG_RTCCNTL_BASE + 0x10)
/* RTC_CNTL_TIME_LO : RO ;bitpos:[31:0] ;default: 32'h0 ; */

View file

@ -60,7 +60,6 @@ PROVIDE ( cache_sram_mmu_set = 0x400097f4 );
PROVIDE ( calc_rtc_memory_crc = 0x40008170 );
PROVIDE ( calloc = 0x4000bee4 );
PROVIDE ( _calloc_r = 0x4000bbf8 );
PROVIDE ( check_pos = 0x400068b8 );
PROVIDE ( _cleanup = 0x40001df8 );
PROVIDE ( _cleanup_r = 0x40001d48 );
PROVIDE ( __clear_cache = 0x40063860 );
@ -101,7 +100,6 @@ PROVIDE ( dbg_state = 0x3ffb8d5d );
PROVIDE ( DebugE256PublicKey_x = 0x3ff97428 );
PROVIDE ( DebugE256PublicKey_y = 0x3ff97408 );
PROVIDE ( DebugE256SecretKey = 0x3ff973e8 );
PROVIDE ( _DebugExceptionVector = 0x40000280 );
PROVIDE ( debug_timer = 0x3ffe042c );
PROVIDE ( debug_timerfn = 0x3ffe0430 );
PROVIDE ( dh_group14_generator = 0x3ff9ac60 );
@ -127,7 +125,6 @@ PROVIDE ( __divdi3 = 0x4000ca84 );
PROVIDE ( __divsc3 = 0x40064200 );
PROVIDE ( __divsf3 = 0x4000234c );
PROVIDE ( __divsi3 = 0x4000c7b8 );
PROVIDE ( _DoubleExceptionVector = 0x400003c0 );
PROVIDE ( dummy_len_plus = 0x3ffae290 );
PROVIDE ( __dummy_lock = 0x4000c728 );
PROVIDE ( __dummy_lock_try = 0x4000c730 );
@ -141,69 +138,8 @@ PROVIDE ( __eqdf2 = 0x400636a8 );
PROVIDE ( __eqsf2 = 0x40063374 );
PROVIDE ( esp_crc8 = 0x4005d144 );
PROVIDE ( _etext = 0x4000d66c );
PROVIDE ( ets_aes_crypt = 0x4005c9b8 );
PROVIDE ( ets_aes_disable = 0x4005c8f8 );
PROVIDE ( ets_aes_enable = 0x4005c8cc );
PROVIDE ( ets_aes_set_endian = 0x4005c928 );
PROVIDE ( ets_aes_setkey_dec = 0x4005c994 );
PROVIDE ( ets_aes_setkey_enc = 0x4005c97c );
PROVIDE ( ets_bigint_disable = 0x4005c4e0 );
PROVIDE ( ets_bigint_enable = 0x4005c498 );
PROVIDE ( ets_bigint_mod_mult_getz = 0x4005c818 );
PROVIDE ( ets_bigint_mod_mult_prepare = 0x4005c7b4 );
PROVIDE ( ets_bigint_mod_power_getz = 0x4005c614 );
PROVIDE ( ets_bigint_mod_power_prepare = 0x4005c54c );
PROVIDE ( ets_bigint_montgomery_mult_getz = 0x4005c7a4 );
PROVIDE ( ets_bigint_montgomery_mult_prepare = 0x4005c6fc );
PROVIDE ( ets_bigint_mult_getz = 0x4005c6e8 );
PROVIDE ( ets_bigint_mult_prepare = 0x4005c630 );
PROVIDE ( ets_bigint_wait_finish = 0x4005c520 );
PROVIDE ( ets_delay_us = 0x40008534 );
PROVIDE ( ets_efuse_get_8M_clock = 0x40008710 );
PROVIDE ( ets_efuse_get_spiconfig = 0x40008658 );
PROVIDE ( ets_efuse_program_op = 0x40008628 );
PROVIDE ( ets_efuse_read_op = 0x40008600 );
PROVIDE ( ets_get_cpu_frequency = 0x4000855c );
PROVIDE ( ets_get_detected_xtal_freq = 0x40008588 );
PROVIDE ( ets_get_xtal_scale = 0x4000856c );
PROVIDE ( ets_install_putc1 = 0x40007d18 );
PROVIDE ( ets_install_putc2 = 0x40007d38 );
PROVIDE ( ets_install_uart_printf = 0x40007d28 );
PROVIDE ( ets_post = 0x4000673c );
PROVIDE ( ets_printf = 0x40007d54 );
PROVIDE ( ets_readySet_ = 0x3ffe01f0 );
PROVIDE ( ets_run = 0x400066bc );
PROVIDE ( ets_secure_boot_check = 0x4005cb40 );
PROVIDE ( ets_secure_boot_check_finish = 0x4005cc04 );
PROVIDE ( ets_secure_boot_check_start = 0x4005cbcc );
PROVIDE ( ets_secure_boot_finish = 0x4005ca84 );
PROVIDE ( ets_secure_boot_hash = 0x4005cad4 );
PROVIDE ( ets_secure_boot_obtain = 0x4005cb14 );
PROVIDE ( ets_secure_boot_rd_abstract = 0x4005cba8 );
PROVIDE ( ets_secure_boot_rd_iv = 0x4005cb84 );
PROVIDE ( ets_secure_boot_start = 0x4005ca34 );
PROVIDE ( ets_set_appcpu_boot_addr = 0x4000689c );
PROVIDE ( ets_set_idle_cb = 0x40006674 );
PROVIDE ( ets_set_startup_callback = 0x4000688c );
PROVIDE ( ets_set_user_start = 0x4000687c );
PROVIDE ( ets_sha_disable = 0x4005c0a8 );
PROVIDE ( ets_sha_enable = 0x4005c07c );
PROVIDE ( ets_sha_finish = 0x4005c104 );
PROVIDE ( ets_sha_init = 0x4005c0d4 );
PROVIDE ( ets_sha_update = 0x4005c2a0 );
PROVIDE ( ets_startup_callback = 0x3ffe0404 );
PROVIDE ( ets_task = 0x40006688 );
PROVIDE ( ets_timer_arm = 0x40008368 );
PROVIDE ( ets_timer_arm_us = 0x400083ac );
PROVIDE ( ets_timer_disarm = 0x400083ec );
PROVIDE ( ets_timer_done = 0x40008428 );
PROVIDE ( ets_timer_handler_isr = 0x40008454 );
PROVIDE ( ets_timer_init = 0x400084e8 );
PROVIDE ( ets_timer_setfn = 0x40008350 );
PROVIDE ( ets_unpack_flash_code = 0x40007018 );
PROVIDE ( ets_unpack_flash_code_legacy = 0x4000694c );
PROVIDE ( ets_update_cpu_frequency_rom = 0x40008550 ); /* Updates g_ticks_per_us on the current CPU only; not on the other core */
PROVIDE ( ets_waiti0 = 0x400067d8 );
PROVIDE ( exc_cause_table = 0x3ff991d0 );
PROVIDE ( _exit_r = 0x4000bd28 );
PROVIDE ( __extendsfdf2 = 0x40002c34 );
@ -213,8 +149,6 @@ PROVIDE ( fflush = 0x40059394 );
PROVIDE ( _fflush_r = 0x40059320 );
PROVIDE ( __ffsdi2 = 0x4000ca2c );
PROVIDE ( __ffssi2 = 0x4000c804 );
PROVIDE ( FilePacketSendDeflatedReqMsgProc = 0x40008b24 );
PROVIDE ( FilePacketSendReqMsgProc = 0x40008860 );
PROVIDE ( _findenv_r = 0x40001f44 );
PROVIDE ( __fixdfdi = 0x40002ac4 );
PROVIDE ( __fixdfsi = 0x40002a78 );
@ -223,11 +157,6 @@ PROVIDE ( __fixsfsi = 0x4000240c );
PROVIDE ( __fixunsdfsi = 0x40002b30 );
PROVIDE ( __fixunssfdi = 0x40002504 );
PROVIDE ( __fixunssfsi = 0x400024ac );
PROVIDE ( FlashDwnLdDeflatedStartMsgProc = 0x40008ad8 );
PROVIDE ( FlashDwnLdParamCfgMsgProc = 0x4000891c );
PROVIDE ( FlashDwnLdStartMsgProc = 0x40008820 );
PROVIDE ( FlashDwnLdStopDeflatedReqMsgProc = 0x40008c18 );
PROVIDE ( FlashDwnLdStopReqMsgProc = 0x400088ec );
PROVIDE ( __floatdidf = 0x4000c988 );
PROVIDE ( __floatdisf = 0x4000c8c0 );
PROVIDE ( __floatsidf = 0x4000c944 );
@ -248,7 +177,6 @@ PROVIDE ( _fwalk = 0x4000c738 );
PROVIDE ( _fwalk_reent = 0x4000c770 );
PROVIDE ( __gcc_bcmp = 0x40064a70 );
PROVIDE ( __gedf2 = 0x40063768 );
PROVIDE ( _GeneralException = 0x40000e14 );
PROVIDE ( __gesf2 = 0x4006340c );
PROVIDE ( __get_current_time_locale = 0x40001834 );
PROVIDE ( _getenv_r = 0x40001fbc );
@ -256,7 +184,6 @@ PROVIDE ( _getpid_r = 0x4000bcfc );
PROVIDE ( __getreent = 0x4000be8c );
PROVIDE ( _gettimeofday_r = 0x4000bc58 );
PROVIDE ( __gettzinfo = 0x40001fcc );
PROVIDE ( GetUartDevice = 0x40009598 );
PROVIDE ( GF_Jacobian_Point_Addition256 = 0x400163a4 );
PROVIDE ( GF_Jacobian_Point_Double256 = 0x40016260 );
PROVIDE ( GF_Point_Jacobian_To_Affine256 = 0x40016b0c );
@ -265,31 +192,6 @@ PROVIDE ( gmtime = 0x40059848 );
PROVIDE ( gmtime_r = 0x40059868 );
PROVIDE ( g_phyFuns_instance = 0x3ffae0c4 );
PROVIDE ( g_rom_flashchip = 0x3ffae270 );
PROVIDE ( gpio_init = 0x40009c20 );
PROVIDE ( gpio_input_get = 0x40009b88 );
PROVIDE ( gpio_input_get_high = 0x40009b9c );
PROVIDE ( gpio_intr_ack = 0x40009dd4 );
PROVIDE ( gpio_intr_ack_high = 0x40009e1c );
PROVIDE ( gpio_intr_handler_register = 0x40009e6c );
PROVIDE ( gpio_intr_pending = 0x40009cec );
PROVIDE ( gpio_intr_pending_high = 0x40009cf8 );
PROVIDE ( gpio_matrix_in = 0x40009edc );
PROVIDE ( gpio_matrix_out = 0x40009f0c );
PROVIDE ( gpio_output_set = 0x40009b24 );
PROVIDE ( gpio_output_set_high = 0x40009b5c );
PROVIDE ( gpio_pad_hold = 0x4000a734 );
PROVIDE ( gpio_pad_pulldown = 0x4000a348 );
PROVIDE ( gpio_pad_pullup = 0x4000a22c );
PROVIDE ( gpio_pad_select_gpio = 0x40009fdc );
PROVIDE ( gpio_pad_set_drv = 0x4000a11c );
PROVIDE ( gpio_pad_unhold = 0x4000a484 );
PROVIDE ( gpio_pending_mask = 0x3ffe0038 );
PROVIDE ( gpio_pending_mask_high = 0x3ffe0044 );
PROVIDE ( gpio_pin_intr_state_set = 0x40009d04 );
PROVIDE ( gpio_pin_wakeup_disable = 0x40009eb0 );
PROVIDE ( gpio_pin_wakeup_enable = 0x40009e7c );
PROVIDE ( gpio_register_get = 0x40009cbc );
PROVIDE ( gpio_register_set = 0x40009bbc );
PROVIDE ( __gtdf2 = 0x400636dc );
PROVIDE ( __gtsf2 = 0x400633a0 );
PROVIDE ( gTxMsg = 0x3ffe0050 );
@ -314,7 +216,6 @@ PROVIDE ( hmac_sha1 = 0x40060acc );
PROVIDE ( hmac_sha1_vector = 0x400609e4 );
PROVIDE ( hmac_sha256 = 0x40060d58 );
PROVIDE ( hmac_sha256_vector = 0x40060c84 );
PROVIDE ( intr_matrix_set = 0x4000681c );
PROVIDE ( isalnum = 0x40000f04 );
PROVIDE ( isalpha = 0x40000f18 );
PROVIDE ( isascii = 0x4000c20c );
@ -333,7 +234,6 @@ PROVIDE ( __itoa = 0x40056678 );
PROVIDE ( jd_decomp = 0x400613e8 );
PROVIDE ( jd_prepare = 0x40060fa8 );
PROVIDE ( ke_env = 0x3ffb93cc );
PROVIDE ( _KernelExceptionVector = 0x40000300 );
PROVIDE ( _kill_r = 0x4000bd10 );
PROVIDE ( labs = 0x40056370 );
PROVIDE ( lb_default_handler = 0x3ff982b8 );
@ -357,15 +257,6 @@ PROVIDE ( ld_sched_params = 0x3ffb96c0 );
PROVIDE ( ld_sync_train_channels = 0x3ff98a3c );
PROVIDE ( __ledf2 = 0x40063704 );
PROVIDE ( __lesf2 = 0x400633c0 );
PROVIDE ( _Level2FromVector = 0x40000954 );
PROVIDE ( _Level2Vector = 0x40000180 );
PROVIDE ( _Level3FromVector = 0x40000a28 );
PROVIDE ( _Level3Vector = 0x400001c0 );
PROVIDE ( _Level4FromVector = 0x40000af8 );
PROVIDE ( _Level4Vector = 0x40000200 );
PROVIDE ( _Level5FromVector = 0x40000c68 );
PROVIDE ( _Level5Vector = 0x40000240 );
PROVIDE ( _LevelOneInterrupt = 0x40000835 );
PROVIDE ( _link_r = 0x4000bc9c );
PROVIDE ( llc_default_handler = 0x3ff98b3c );
PROVIDE ( llc_default_state_tab_p_get = 0x40046058 );
@ -436,10 +327,7 @@ PROVIDE ( memccpy = 0x4000c220 );
PROVIDE ( memchr = 0x4000c244 );
PROVIDE ( memcmp = 0x4000c260 );
PROVIDE ( memcpy = 0x4000c2c8 );
PROVIDE ( MemDwnLdStartMsgProc = 0x40008948 );
PROVIDE ( MemDwnLdStopReqMsgProc = 0x400089dc );
PROVIDE ( memmove = 0x4000c3c0 );
PROVIDE ( MemPacketSendReqMsgProc = 0x40008978 );
PROVIDE ( memrchr = 0x4000c400 );
PROVIDE ( memset = 0x4000c44c );
PROVIDE ( mktime = 0x4005a5e8 );
@ -469,7 +357,6 @@ PROVIDE ( __negsf2 = 0x400020c0 );
PROVIDE ( __negvdi2 = 0x40002e98 );
PROVIDE ( __negvsi2 = 0x40002e78 );
PROVIDE ( __nesf2 = 0x40063374 );
PROVIDE ( _NMIExceptionVector = 0x400002c0 );
PROVIDE ( notEqual256 = 0x40015b04 );
PROVIDE ( __nsau_data = 0x3ff96544 );
PROVIDE ( one_bits = 0x3ff971f8 );
@ -521,7 +408,6 @@ PROVIDE ( r_co_list_push_front = 0x40013ff4 );
PROVIDE ( r_co_list_size = 0x400142ac );
PROVIDE ( r_co_nb_good_channels = 0x40014360 );
PROVIDE ( r_co_slot_to_duration = 0x40014348 );
PROVIDE ( RcvMsg = 0x4000954c );
PROVIDE ( r_dbg_init = 0x40014394 );
PROVIDE ( r_dbg_platform_reset_complete = 0x400143d0 );
PROVIDE ( r_dbg_swdiag_init = 0x40014470 );
@ -560,15 +446,12 @@ PROVIDE ( r_ecc_gen_new_secret_key = 0x400170e4 );
PROVIDE ( r_ecc_get_debug_Keys = 0x40017224 );
PROVIDE ( r_ecc_init = 0x40016dbc );
PROVIDE ( RecvBuff = 0x3ffe009c );
PROVIDE ( recv_packet = 0x40009424 );
PROVIDE ( r_em_buf_init = 0x4001729c );
PROVIDE ( r_em_buf_rx_buff_addr_get = 0x400173e8 );
PROVIDE ( r_em_buf_rx_free = 0x400173c4 );
PROVIDE ( r_em_buf_tx_buff_addr_get = 0x40017404 );
PROVIDE ( r_em_buf_tx_free = 0x4001741c );
PROVIDE ( _rename_r = 0x4000bc28 );
PROVIDE ( _ResetHandler = 0x40000450 );
PROVIDE ( _ResetVector = 0x40000400 );
PROVIDE ( r_F1_256 = 0x400133e4 );
PROVIDE ( r_F2_256 = 0x40013568 );
PROVIDE ( r_F3_256 = 0x40013664 );
@ -1351,7 +1234,6 @@ PROVIDE ( rom_iq_est_disable = 0x40005590 );
PROVIDE ( rom_iq_est_enable = 0x40005514 );
PROVIDE ( rom_linear_to_db = 0x40005f64 );
PROVIDE ( rom_loopback_mode_en = 0x400030f8 );
PROVIDE ( rom_main = 0x400076c4 );
PROVIDE ( rom_meas_tone_pwr_db = 0x40006004 );
PROVIDE ( rom_mhz2ieee = 0x4000404c );
PROVIDE ( rom_noise_floor_auto_set = 0x40003bdc );
@ -1458,10 +1340,6 @@ PROVIDE ( r_rwip_wakeup_delay_set = 0x40055e4c );
PROVIDE ( r_rwip_wakeup_end = 0x40055e18 );
PROVIDE ( r_rwip_wlcoex_set = 0x40055f60 );
PROVIDE ( r_SHA_256 = 0x40013a90 );
PROVIDE ( rtc_boot_control = 0x4000821c );
PROVIDE ( rtc_get_reset_reason = 0x400081d4 );
PROVIDE ( rtc_get_wakeup_cause = 0x400081f4 );
PROVIDE ( rtc_select_apb_bridge = 0x40008288 );
PROVIDE ( rwip_coex_cfg = 0x3ff9914c );
PROVIDE ( rwip_priority = 0x3ff99159 );
PROVIDE ( rwip_rf = 0x3ffbdb28 );
@ -1473,13 +1351,10 @@ PROVIDE ( __sccl = 0x4000c498 );
PROVIDE ( __sclose = 0x400011b8 );
PROVIDE ( SelectSpiFunction = 0x40061f84 );
PROVIDE ( SelectSpiQIO = 0x40061ddc );
PROVIDE ( SendMsg = 0x40009384 );
PROVIDE ( send_packet = 0x40009340 );
PROVIDE ( __seofread = 0x40001148 );
PROVIDE ( setjmp = 0x40056268 );
PROVIDE ( setlocale = 0x40059568 );
PROVIDE ( _setlocale_r = 0x4005950c );
PROVIDE ( set_rtc_memory_crc = 0x40008208 );
PROVIDE ( SetSpiDrvs = 0x40061e78 );
PROVIDE ( __sf_fake_stderr = 0x3ff96458 );
PROVIDE ( __sf_fake_stdin = 0x3ff96498 );
@ -1528,8 +1403,6 @@ PROVIDE ( slc_send_to_host_chain = 0x4000b6a0 );
PROVIDE ( slc_set_host_io_max_window = 0x4000b89c );
PROVIDE ( slc_to_host_chain_recycle = 0x4000b758 );
PROVIDE ( __smakebuf_r = 0x40059108 );
PROVIDE ( software_reset = 0x4000824c );
PROVIDE ( software_reset_cpu = 0x40008264 );
PROVIDE ( specialModP256 = 0x4001600c );
PROVIDE ( spi_cache_sram_init = 0x400626e4 );
PROVIDE ( SPIClkConfig = 0x40062bc8 );
@ -1563,6 +1436,8 @@ PROVIDE ( SPI_Write_Encrypt_Disable = 0x40062e60 );
PROVIDE ( SPI_Write_Encrypt_Enable = 0x40062df4 );
/* This is static function, but can be used, not generated by script*/
PROVIDE ( SPI_write_status = 0x400622f0 );
/* This is static function, but can be used, not generated by script */
PROVIDE ( SPI_Wait_Idle = 0x400622c0 );
PROVIDE ( srand = 0x40001004 );
PROVIDE ( __sread = 0x40001118 );
PROVIDE ( __srefill_r = 0x400593d4 );
@ -1627,7 +1502,6 @@ PROVIDE ( __swbuf_r = 0x40058bec );
PROVIDE ( __swrite = 0x40001150 );
PROVIDE ( __swsetup_r = 0x40058cc8 );
PROVIDE ( sw_to_hw = 0x3ffb8d40 );
PROVIDE ( _SyscallException = 0x400007cf );
PROVIDE ( syscall_table_ptr_app = 0x3ffae020 );
PROVIDE ( syscall_table_ptr_pro = 0x3ffae024 );
PROVIDE ( _system_r = 0x4000bc10 );
@ -1658,31 +1532,7 @@ PROVIDE ( _tzname = 0x3ffae030 );
PROVIDE ( tzset = 0x40001a1c );
PROVIDE ( _tzset_r = 0x40001a28 );
PROVIDE ( __tz_unlock = 0x40001a10 );
PROVIDE ( uartAttach = 0x40008fd0 );
PROVIDE ( uart_baudrate_detect = 0x40009034 );
PROVIDE ( uart_buff_switch = 0x400093c0 );
PROVIDE ( UartConnCheck = 0x40008738 );
PROVIDE ( UartConnectProc = 0x40008a04 );
PROVIDE ( UartDev = 0x3ffe019c );
PROVIDE ( uart_div_modify = 0x400090cc );
PROVIDE ( UartDwnLdProc = 0x40008ce8 );
PROVIDE ( UartGetCmdLn = 0x40009564 );
PROVIDE ( Uart_Init = 0x40009120 );
PROVIDE ( UartRegReadProc = 0x40008a58 );
PROVIDE ( UartRegWriteProc = 0x40008a14 );
PROVIDE ( uart_rx_intr_handler = 0x40008f4c );
PROVIDE ( uart_rx_one_char = 0x400092d0 );
PROVIDE ( uart_rx_one_char_block = 0x400092a4 );
PROVIDE ( uart_rx_readbuff = 0x40009394 );
PROVIDE ( UartRxString = 0x400092fc );
PROVIDE ( UartSetBaudProc = 0x40008aac );
PROVIDE ( UartSpiAttachProc = 0x40008a6c );
PROVIDE ( UartSpiReadProc = 0x40008a80 );
PROVIDE ( uart_tx_flush = 0x40009258 );
PROVIDE ( uart_tx_one_char = 0x40009200 );
PROVIDE ( uart_tx_one_char2 = 0x4000922c );
PROVIDE ( uart_tx_switch = 0x40009028 );
PROVIDE ( uart_tx_wait_idle = 0x40009278 );
PROVIDE ( __ucmpdi2 = 0x40063840 );
PROVIDE ( __udivdi3 = 0x4000cff8 );
PROVIDE ( __udivmoddi4 = 0x40064ab0 );
@ -1697,21 +1547,13 @@ PROVIDE ( _unlink_r = 0x4000bc84 );
PROVIDE ( __unorddf2 = 0x400637f4 );
PROVIDE ( __unordsf2 = 0x40063478 );
PROVIDE ( user_code_start = 0x3ffe0400 );
PROVIDE ( _UserExceptionVector = 0x40000340 );
PROVIDE ( utoa = 0x40056258 );
PROVIDE ( __utoa = 0x400561f0 );
PROVIDE ( VerifyFlashMd5Proc = 0x40008c44 );
PROVIDE ( veryBigHexP256 = 0x3ff9736c );
PROVIDE ( wcrtomb = 0x40058920 );
PROVIDE ( _wcrtomb_r = 0x400588d8 );
PROVIDE ( __wctomb = 0x3ff96540 );
PROVIDE ( _wctomb_r = 0x40058f14 );
PROVIDE ( _WindowOverflow12 = 0x40000100 );
PROVIDE ( _WindowOverflow4 = 0x40000000 );
PROVIDE ( _WindowOverflow8 = 0x40000080 );
PROVIDE ( _WindowUnderflow12 = 0x40000140 );
PROVIDE ( _WindowUnderflow4 = 0x40000040 );
PROVIDE ( _WindowUnderflow8 = 0x400000c0 );
PROVIDE ( write = 0x4000181c );
PROVIDE ( _write_r = 0x4000bd70 );
PROVIDE ( xthal_bcopy = 0x4000c098 );
@ -1727,12 +1569,38 @@ PROVIDE ( xthal_set_intclear = 0x4000c1ec );
PROVIDE ( _xtos_set_intlevel = 0x4000bfdc );
PROVIDE ( g_ticks_per_us_pro = 0x3ffe01e0 );
PROVIDE ( g_ticks_per_us_app = 0x3ffe40f0 );
/*
These functions are xtos-related (or call xtos-related functions) and do not play well
with multicore FreeRTOS. Where needed, we provide alternatives that are multicore
compatible.
compatible. These functions also use a chunk of static RAM, by not using them we can
allocate that RAM for general use.
*/
/*
PROVIDE ( _DebugExceptionVector = 0x40000280 );
PROVIDE ( _DoubleExceptionVector = 0x400003c0 );
PROVIDE ( _KernelExceptionVector = 0x40000300 );
PROVIDE ( _GeneralException = 0x40000e14 );
PROVIDE ( _ResetHandler = 0x40000450 );
PROVIDE ( _ResetVector = 0x40000400 );
PROVIDE ( _UserExceptionVector = 0x40000340 );
PROVIDE ( _NMIExceptionVector = 0x400002c0 );
PROVIDE ( _WindowOverflow12 = 0x40000100 );
PROVIDE ( _WindowOverflow4 = 0x40000000 );
PROVIDE ( _WindowOverflow8 = 0x40000080 );
PROVIDE ( _WindowUnderflow12 = 0x40000140 );
PROVIDE ( _WindowUnderflow4 = 0x40000040 );
PROVIDE ( _WindowUnderflow8 = 0x400000c0 );
PROVIDE ( _Level2FromVector = 0x40000954 );
PROVIDE ( _Level3FromVector = 0x40000a28 );
PROVIDE ( _Level4FromVector = 0x40000af8 );
PROVIDE ( _Level5FromVector = 0x40000c68 );
PROVIDE ( _Level2Vector = 0x40000180 );
PROVIDE ( _Level3Vector = 0x400001c0 );
PROVIDE ( _Level4Vector = 0x40000200 );
PROVIDE ( _Level5Vector = 0x40000240 );
PROVIDE ( _LevelOneInterrupt = 0x40000835 );
PROVIDE ( _SyscallException = 0x400007cf );
PROVIDE ( _xtos_alloca_handler = 0x40000010 );
PROVIDE ( _xtos_cause3_handler = 0x40000dd8 );
PROVIDE ( _xtos_c_handler_table = 0x3ffe0548 );
@ -1758,12 +1626,164 @@ PROVIDE ( _xtos_unhandled_exception = 0x4000c024 );
PROVIDE ( _xtos_unhandled_interrupt = 0x4000c01c );
PROVIDE ( _xtos_vpri_enabled = 0x3ffe0654 );
PROVIDE ( ets_intr_count = 0x3ffe03fc );
*/
/* These functions are part of the UART downloader but also contain general UART functions. */
PROVIDE ( FilePacketSendDeflatedReqMsgProc = 0x40008b24 );
PROVIDE ( FilePacketSendReqMsgProc = 0x40008860 );
PROVIDE ( FlashDwnLdDeflatedStartMsgProc = 0x40008ad8 );
PROVIDE ( FlashDwnLdParamCfgMsgProc = 0x4000891c );
PROVIDE ( FlashDwnLdStartMsgProc = 0x40008820 );
PROVIDE ( FlashDwnLdStopDeflatedReqMsgProc = 0x40008c18 );
PROVIDE ( FlashDwnLdStopReqMsgProc = 0x400088ec );
PROVIDE ( MemDwnLdStartMsgProc = 0x40008948 );
PROVIDE ( MemDwnLdStopReqMsgProc = 0x400089dc );
PROVIDE ( MemPacketSendReqMsgProc = 0x40008978 );
PROVIDE ( uart_baudrate_detect = 0x40009034 );
PROVIDE ( uart_buff_switch = 0x400093c0 );
PROVIDE ( UartConnCheck = 0x40008738 );
PROVIDE ( UartConnectProc = 0x40008a04 );
PROVIDE ( UartDwnLdProc = 0x40008ce8 );
PROVIDE ( UartRegReadProc = 0x40008a58 );
PROVIDE ( UartRegWriteProc = 0x40008a14 );
PROVIDE ( UartSetBaudProc = 0x40008aac );
PROVIDE ( UartSpiAttachProc = 0x40008a6c );
PROVIDE ( UartSpiReadProc = 0x40008a80 );
PROVIDE ( VerifyFlashMd5Proc = 0x40008c44 );
PROVIDE ( GetUartDevice = 0x40009598 );
PROVIDE ( RcvMsg = 0x4000954c );
PROVIDE ( SendMsg = 0x40009384 );
PROVIDE ( UartGetCmdLn = 0x40009564 );
PROVIDE ( UartRxString = 0x400092fc );
PROVIDE ( Uart_Init = 0x40009120 );
PROVIDE ( recv_packet = 0x40009424 );
PROVIDE ( send_packet = 0x40009340 );
PROVIDE ( uartAttach = 0x40008fd0 );
PROVIDE ( uart_div_modify = 0x400090cc );
PROVIDE ( uart_rx_intr_handler = 0x40008f4c );
PROVIDE ( uart_rx_one_char = 0x400092d0 );
PROVIDE ( uart_rx_one_char_block = 0x400092a4 );
PROVIDE ( uart_rx_readbuff = 0x40009394 );
PROVIDE ( uart_tx_flush = 0x40009258 );
PROVIDE ( uart_tx_one_char = 0x40009200 );
PROVIDE ( uart_tx_one_char2 = 0x4000922c );
PROVIDE ( uart_tx_switch = 0x40009028 );
PROVIDE ( uart_tx_wait_idle = 0x40009278 );
/*
These functions are part of the ROM GPIO driver. We do not use them; the provided esp-idf functions
replace them and this way we can re-use the fixed RAM addresses these routines need.
*/
/* <-- So you don't read over it: This comment disables the next lines.
PROVIDE ( gpio_init = 0x40009c20 );
PROVIDE ( gpio_intr_ack = 0x40009dd4 );
PROVIDE ( gpio_intr_ack_high = 0x40009e1c );
PROVIDE ( gpio_intr_handler_register = 0x40009e6c );
PROVIDE ( gpio_intr_pending = 0x40009cec );
PROVIDE ( gpio_intr_pending_high = 0x40009cf8 );
PROVIDE ( gpio_pending_mask = 0x3ffe0038 );
PROVIDE ( gpio_pending_mask_high = 0x3ffe0044 );
PROVIDE ( gpio_pin_intr_state_set = 0x40009d04 );
PROVIDE ( gpio_pin_wakeup_disable = 0x40009eb0 );
PROVIDE ( gpio_pin_wakeup_enable = 0x40009e7c );
PROVIDE ( gpio_register_get = 0x40009cbc );
PROVIDE ( gpio_register_set = 0x40009bbc );
*/
/* These are still part of that driver, but have been verified not to use static RAM, so they can be used. */
PROVIDE ( gpio_output_set = 0x40009b24 );
PROVIDE ( gpio_output_set_high = 0x40009b5c );
PROVIDE ( gpio_input_get = 0x40009b88 );
PROVIDE ( gpio_input_get_high = 0x40009b9c );
PROVIDE ( gpio_matrix_in = 0x40009edc );
PROVIDE ( gpio_matrix_out = 0x40009f0c );
PROVIDE ( gpio_pad_select_gpio = 0x40009fdc );
PROVIDE ( gpio_pad_set_drv = 0x4000a11c );
PROVIDE ( gpio_pad_pulldown = 0x4000a348 );
PROVIDE ( gpio_pad_pullup = 0x4000a22c );
PROVIDE ( gpio_pad_hold = 0x4000a734 );
PROVIDE ( gpio_pad_unhold = 0x4000a484 );
/*
These functions are part of the non-os kernel (etsc).
*/
PROVIDE ( ets_aes_crypt = 0x4005c9b8 );
PROVIDE ( ets_aes_disable = 0x4005c8f8 );
PROVIDE ( ets_aes_enable = 0x4005c8cc );
PROVIDE ( ets_aes_set_endian = 0x4005c928 );
PROVIDE ( ets_aes_setkey_dec = 0x4005c994 );
PROVIDE ( ets_aes_setkey_enc = 0x4005c97c );
PROVIDE ( ets_bigint_disable = 0x4005c4e0 );
PROVIDE ( ets_bigint_enable = 0x4005c498 );
PROVIDE ( ets_bigint_mod_mult_getz = 0x4005c818 );
PROVIDE ( ets_bigint_mod_mult_prepare = 0x4005c7b4 );
PROVIDE ( ets_bigint_mod_power_getz = 0x4005c614 );
PROVIDE ( ets_bigint_mod_power_prepare = 0x4005c54c );
PROVIDE ( ets_bigint_montgomery_mult_getz = 0x4005c7a4 );
PROVIDE ( ets_bigint_montgomery_mult_prepare = 0x4005c6fc );
PROVIDE ( ets_bigint_mult_getz = 0x4005c6e8 );
PROVIDE ( ets_bigint_mult_prepare = 0x4005c630 );
PROVIDE ( ets_bigint_wait_finish = 0x4005c520 );
PROVIDE ( ets_post = 0x4000673c );
PROVIDE ( ets_run = 0x400066bc );
PROVIDE ( ets_set_idle_cb = 0x40006674 );
PROVIDE ( ets_task = 0x40006688 );
PROVIDE ( ets_efuse_get_8M_clock = 0x40008710 );
PROVIDE ( ets_efuse_get_spiconfig = 0x40008658 );
PROVIDE ( ets_efuse_program_op = 0x40008628 );
PROVIDE ( ets_efuse_read_op = 0x40008600 );
PROVIDE ( ets_intr_lock = 0x400067b0 );
PROVIDE ( ets_intr_unlock = 0x400067c4 );
PROVIDE ( ets_isr_attach = 0x400067ec );
PROVIDE ( ets_isr_mask = 0x400067fc );
PROVIDE ( ets_isr_unmask = 0x40006808 );
*/
PROVIDE ( ets_waiti0 = 0x400067d8 );
PROVIDE ( intr_matrix_set = 0x4000681c );
PROVIDE ( check_pos = 0x400068b8 );
PROVIDE ( ets_set_appcpu_boot_addr = 0x4000689c );
PROVIDE ( ets_set_startup_callback = 0x4000688c );
PROVIDE ( ets_set_user_start = 0x4000687c );
PROVIDE ( ets_unpack_flash_code = 0x40007018 );
PROVIDE ( ets_unpack_flash_code_legacy = 0x4000694c );
PROVIDE ( rom_main = 0x400076c4 );
PROVIDE ( ets_install_putc1 = 0x40007d18 );
PROVIDE ( ets_install_putc2 = 0x40007d38 );
PROVIDE ( ets_install_uart_printf = 0x40007d28 );
PROVIDE ( ets_printf = 0x40007d54 );
PROVIDE ( rtc_boot_control = 0x4000821c );
PROVIDE ( rtc_get_reset_reason = 0x400081d4 );
PROVIDE ( rtc_get_wakeup_cause = 0x400081f4 );
PROVIDE ( rtc_select_apb_bridge = 0x40008288 );
PROVIDE ( set_rtc_memory_crc = 0x40008208 );
PROVIDE ( software_reset = 0x4000824c );
PROVIDE ( software_reset_cpu = 0x40008264 );
PROVIDE ( ets_secure_boot_check = 0x4005cb40 );
PROVIDE ( ets_secure_boot_check_finish = 0x4005cc04 );
PROVIDE ( ets_secure_boot_check_start = 0x4005cbcc );
PROVIDE ( ets_secure_boot_finish = 0x4005ca84 );
PROVIDE ( ets_secure_boot_hash = 0x4005cad4 );
PROVIDE ( ets_secure_boot_obtain = 0x4005cb14 );
PROVIDE ( ets_secure_boot_rd_abstract = 0x4005cba8 );
PROVIDE ( ets_secure_boot_rd_iv = 0x4005cb84 );
PROVIDE ( ets_secure_boot_start = 0x4005ca34 );
PROVIDE ( ets_sha_disable = 0x4005c0a8 );
PROVIDE ( ets_sha_enable = 0x4005c07c );
PROVIDE ( ets_sha_finish = 0x4005c104 );
PROVIDE ( ets_sha_init = 0x4005c0d4 );
PROVIDE ( ets_sha_update = 0x4005c2a0 );
PROVIDE ( ets_delay_us = 0x40008534 );
PROVIDE ( ets_get_cpu_frequency = 0x4000855c );
PROVIDE ( ets_get_detected_xtal_freq = 0x40008588 );
PROVIDE ( ets_get_xtal_scale = 0x4000856c );
PROVIDE ( ets_timer_arm = 0x40008368 );
PROVIDE ( ets_timer_arm_us = 0x400083ac );
PROVIDE ( ets_timer_disarm = 0x400083ec );
PROVIDE ( ets_timer_done = 0x40008428 );
PROVIDE ( ets_timer_handler_isr = 0x40008454 );
PROVIDE ( ets_timer_init = 0x400084e8 );
PROVIDE ( ets_timer_setfn = 0x40008350 );
PROVIDE ( ets_update_cpu_frequency_rom = 0x40008550 ); /* Updates g_ticks_per_us on the current CPU only; not on the other core */
/* Following are static data, but can be used, not generated by script <<<<< btdm data */
PROVIDE ( ld_acl_env = 0x3ffb8258 );
PROVIDE ( ld_active_ch_map = 0x3ffb8334 );
@ -1783,3 +1803,4 @@ PROVIDE ( ld_sco_env = 0x3ffb824c );
PROVIDE ( ld_sscan_env = 0x3ffb832c );
PROVIDE ( ld_strain_env = 0x3ffb8330 );
/* Above are static data, but can be used, not generated by script >>>>> btdm data */

@ -1 +1 @@
Subproject commit ed85cf9156f2ef358c29d07fb849a73c5758eecb
Subproject commit ffe5a4c14fe9c933c776fadc62fa9d409929e6f9

View file

@ -34,6 +34,7 @@
#include "esp_attr.h"
#include "esp_err.h"
#include "esp_core_dump.h"
#include "esp_spi_flash.h"
/*
Panic handlers; these get called when an unhandled exception occurs or the assembly-level
@ -107,11 +108,8 @@ void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, s
static bool abort_called;
void abort()
static __attribute__((noreturn)) inline void invoke_abort()
{
#if !CONFIG_ESP32_PANIC_SILENT_REBOOT
ets_printf("abort() was called at PC 0x%08x\n", (intptr_t)__builtin_return_address(0) - 3);
#endif
abort_called = true;
while(1) {
__asm__ ("break 0,0");
@ -119,6 +117,14 @@ void abort()
}
}
void abort()
{
#if !CONFIG_ESP32_PANIC_SILENT_REBOOT
ets_printf("abort() was called at PC 0x%08x\n", (intptr_t)__builtin_return_address(0) - 3);
#endif
invoke_abort();
}
static const char *edesc[] = {
"IllegalInstruction", "Syscall", "InstructionFetchError", "LoadStoreError",
@ -441,4 +447,11 @@ void esp_clear_watchpoint(int no)
}
}
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 (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();
}

View file

@ -60,7 +60,7 @@ esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data,
}
}
// Enable WiFi peripheral clock
SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, 0x87cf);
SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_WIFI_EN | DPORT_WIFI_CLK_RNG_EN);
ESP_LOGV(TAG, "register_chipv7_phy, init_data=%p, cal_data=%p, mode=%d",
init_data, calibration_data, mode);
phy_set_wifi_mode_only(0);
@ -82,10 +82,10 @@ esp_err_t esp_phy_rf_deinit(void)
_lock_acquire(&s_phy_rf_init_lock);
if (s_phy_rf_init_count == 1) {
// Disable PHY and RF. TODO: convert this function to another one.
pm_close_rf();
// Disable WiFi peripheral clock
CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, 0x87cf);
// Disable PHY and RF.
phy_close_rf();
// Disable WiFi peripheral clock. Do not disable clock for hardware RNG
CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_WIFI_EN);
} else {
#if CONFIG_SW_COEXIST_ENABLE
coex_deinit();

View file

@ -138,7 +138,7 @@ uint32_t rtc_sleep(uint32_t cycles_h, uint32_t cycles_l, uint32_t wakeup_opt, ui
/**
* @brief Shutdown PHY and RF. TODO: convert this function to another one.
*/
void pm_close_rf(void);
void phy_close_rf(void);
#ifdef __cplusplus
}

View file

@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string.h>
#include "esp_system.h"
#include "esp_attr.h"
#include "esp_wifi.h"
@ -72,6 +74,87 @@ esp_err_t esp_efuse_read_mac(uint8_t* mac)
esp_err_t system_efuse_read_mac(uint8_t mac[6]) __attribute__((alias("esp_efuse_read_mac")));
esp_err_t esp_derive_mac(uint8_t* dst_mac, const uint8_t* src_mac)
{
uint8_t idx;
if (dst_mac == NULL || src_mac == NULL) {
ESP_LOGE(TAG, "mac address param is NULL");
return ESP_ERR_INVALID_ARG;
}
memcpy(dst_mac, src_mac, 6);
for (idx = 0; idx < 64; idx++) {
dst_mac[0] = src_mac[0] | 0x02;
dst_mac[0] ^= idx << 2;
if (memcmp(dst_mac, src_mac, 6)) {
break;
}
}
return ESP_OK;
}
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(NUM_MAC_ADDRESS_FROM_EFUSE == FOUR_MAC_ADDRESS_FROM_EFUSE \
|| NUM_MAC_ADDRESS_FROM_EFUSE == TWO_MAC_ADDRESS_FROM_EFUSE, \
"incorrect NUM_MAC_ADDRESS_FROM_EFUSE value");
esp_efuse_read_mac(efuse_mac);
switch (type) {
case ESP_MAC_WIFI_STA:
memcpy(mac, efuse_mac, 6);
break;
case ESP_MAC_WIFI_SOFTAP:
if (NUM_MAC_ADDRESS_FROM_EFUSE == FOUR_MAC_ADDRESS_FROM_EFUSE) {
memcpy(mac, efuse_mac, 6);
mac[5] += 1;
}
else if (NUM_MAC_ADDRESS_FROM_EFUSE == TWO_MAC_ADDRESS_FROM_EFUSE) {
esp_derive_mac(mac, efuse_mac);
}
break;
case ESP_MAC_BT:
memcpy(mac, efuse_mac, 6);
if (NUM_MAC_ADDRESS_FROM_EFUSE == FOUR_MAC_ADDRESS_FROM_EFUSE) {
mac[5] += 2;
}
else if (NUM_MAC_ADDRESS_FROM_EFUSE == TWO_MAC_ADDRESS_FROM_EFUSE) {
mac[5] += 1;
}
break;
case ESP_MAC_ETH:
if (NUM_MAC_ADDRESS_FROM_EFUSE == FOUR_MAC_ADDRESS_FROM_EFUSE) {
memcpy(mac, efuse_mac, 6);
mac[5] += 3;
}
else if (NUM_MAC_ADDRESS_FROM_EFUSE == TWO_MAC_ADDRESS_FROM_EFUSE) {
efuse_mac[5] += 1;
esp_derive_mac(mac, efuse_mac);
}
break;
default:
ESP_LOGW(TAG, "incorrect mac type");
break;
}
return ESP_OK;
}
void esp_restart_noos() __attribute__ ((noreturn));
@ -132,7 +215,7 @@ void IRAM_ATTR esp_restart_noos()
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 |
DPROT_RW_BTMAC_RST | DPROT_RW_BTLP_RST);
DPORT_RW_BTMAC_RST | DPORT_RW_BTLP_RST);
REG_WRITE(DPORT_CORE_RST_EN_REG, 0);
// Reset timer/spi/uart

View file

@ -0,0 +1,20 @@
#include <stdio.h>
#include "unity.h"
#include "rom/ets_sys.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/sens_reg.h"
TEST_CASE("can control TSENS using registers", "[rtc][ignore]")
{
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 3, SENS_FORCE_XPD_SAR_S);
SET_PERI_REG_BITS(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_CLK_DIV, 10, SENS_TSENS_CLK_DIV_S);
CLEAR_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP);
CLEAR_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_DUMP_OUT);
SET_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP_FORCE);
SET_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP);
ets_delay_us(100);
SET_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_DUMP_OUT);
ets_delay_us(5);
int res = GET_PERI_REG_BITS2(SENS_SAR_SLAVE_ADDR3_REG, SENS_TSENS_OUT, SENS_TSENS_OUT_S);
printf("res=%d\n", res);
}

View file

@ -46,30 +46,32 @@ config ESPTOOLPY_COMPRESSED
decompress it on the fly before flashing it. For most payloads, this should result in a
speed increase.
choice ESPTOOLPY_FLASHMODE
choice FLASHMODE
prompt "Flash SPI mode"
default ESPTOOLPY_FLASHMODE_DIO
default FLASHMODE_DIO
help
Mode the flash chip is flashed in, as well as the default mode for the
binary to run in.
config ESPTOOLPY_FLASHMODE_QIO
config FLASHMODE_QIO
bool "QIO"
config ESPTOOLPY_FLASHMODE_QOUT
config FLASHMODE_QOUT
bool "QOUT"
config ESPTOOLPY_FLASHMODE_DIO
config FLASHMODE_DIO
bool "DIO"
config ESPTOOLPY_FLASHMODE_DOUT
config FLASHMODE_DOUT
bool "DOUT"
endchoice
# Note: we use esptool.py to flash bootloader in
# dio mode for QIO/QOUT, bootloader then upgrades
# itself to quad mode during initialisation
config ESPTOOLPY_FLASHMODE
string
default "qio" if ESPTOOLPY_FLASHMODE_QIO
default "qout" if ESPTOOLPY_FLASHMODE_QOUT
default "dio" if ESPTOOLPY_FLASHMODE_DIO
default "dout" if ESPTOOLPY_FLASHMODE_DOUT
default "dio" if FLASHMODE_QIO
default "dio" if FLASHMODE_QOUT
default "dio" if FLASHMODE_DIO
default "dout" if FLASHMODE_DOUT
choice ESPTOOLPY_FLASHFREQ
prompt "Flash SPI speed"
@ -138,24 +140,16 @@ choice ESPTOOLPY_BEFORE
wired from the serial port to the ESP32. Most USB development
boards do this internally.
The "Reset with ESP32R0 Windows workaround" option works
around an automatic reset bug in hardware, when using Windows
with some development boards. This fix only works if you're
using a silicon revision 0 ESP32.
config ESPTOOLPY_BEFORE_RESET
bool "Reset to bootloader"
config ESPTOOLPY_BEFORE_NORESET
bool "No reset"
config ESPTOOLPY_BEFORE_ESP32R0
bool "Reset with ESP32R0 Windows workaround"
endchoice
config ESPTOOLPY_BEFORE
string
default "default_reset" if ESPTOOLPY_BEFORE_RESET
default "no_reset" if ESPTOOLPY_BEFORE_NORESET
default "esp32r0" if ESPTOOLPY_BEFORE_ESP32R0
choice ESPTOOLPY_AFTER
prompt "After flashing"

@ -1 +1 @@
Subproject commit e9e9179f6fc3f2ecfc568987d3224b5e53a05f06
Subproject commit 907273664ada32fc33f3fbfeba99550512c67e4d

View file

@ -75,8 +75,7 @@ esp_err_t emac_post(emac_sig_t sig, emac_par_t par);
static void emac_macaddr_init(void)
{
esp_efuse_read_mac(&(emac_config.macaddr[0]));
emac_config.macaddr[5] = emac_config.macaddr[5] + 3;
esp_read_mac(&(emac_config.macaddr[0]), ESP_MAC_ETH);
}
void esp_eth_get_mac(uint8_t mac[6])

View file

@ -18,39 +18,71 @@
#include <sys/time.h>
static const char* TAG = "ff_diskio";
static ff_diskio_impl_t s_impls[_VOLUMES] = { { 0 } };
static ff_diskio_impl_t * s_impls[_VOLUMES];
static sdmmc_card_t* s_cards[_VOLUMES] = { NULL };
static bool s_impls_initialized = false;
PARTITION VolToPart[] = {
{0, 1}, /* Logical drive 0 ==> Physical drive 0, 1st partition */
{1, 0} /* Logical drive 1 ==> Physical drive 1, auto detection */
};
esp_err_t ff_diskio_get_drive(BYTE* out_pdrv)
{
BYTE i;
for(i=0; i<_VOLUMES; i++) {
if (!s_impls[i]) {
*out_pdrv = i;
return ESP_OK;
}
}
return ESP_ERR_NOT_FOUND;
}
void ff_diskio_register(BYTE pdrv, const ff_diskio_impl_t* discio_impl)
{
assert(pdrv < _VOLUMES);
memcpy(&s_impls[pdrv], discio_impl, sizeof(ff_diskio_impl_t));
if (!s_impls_initialized) {
s_impls_initialized = true;
memset(s_impls, 0, _VOLUMES * sizeof(ff_diskio_impl_t*));
}
if (s_impls[pdrv]) {
ff_diskio_impl_t* im = s_impls[pdrv];
s_impls[pdrv] = NULL;
free(im);
}
if (!discio_impl) {
return;
}
ff_diskio_impl_t * impl = (ff_diskio_impl_t *)malloc(sizeof(ff_diskio_impl_t));
assert(impl != NULL);
memcpy(impl, discio_impl, sizeof(ff_diskio_impl_t));
s_impls[pdrv] = impl;
}
DSTATUS ff_disk_initialize (BYTE pdrv)
{
return s_impls[pdrv].init(pdrv);
return s_impls[pdrv]->init(pdrv);
}
DSTATUS ff_disk_status (BYTE pdrv)
{
return s_impls[pdrv].status(pdrv);
return s_impls[pdrv]->status(pdrv);
}
DRESULT ff_disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count)
{
return s_impls[pdrv].read(pdrv, buff, sector, count);
return s_impls[pdrv]->read(pdrv, buff, sector, count);
}
DRESULT ff_disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count)
{
return s_impls[pdrv].write(pdrv, buff, sector, count);
return s_impls[pdrv]->write(pdrv, buff, sector, count);
}
DRESULT ff_disk_ioctl (BYTE pdrv, BYTE cmd, void* buff)
{
return s_impls[pdrv].ioctl(pdrv, cmd, buff);
return s_impls[pdrv]->ioctl(pdrv, cmd, buff);
}
DWORD get_fattime(void)

View file

@ -58,16 +58,19 @@ typedef struct {
} ff_diskio_impl_t;
/**
* Register diskio driver for given drive number.
* Register or unregister diskio driver for given drive number.
*
* When FATFS library calls one of disk_xxx functions for driver number pdrv,
* corresponding function in discio_impl for given pdrv will be called.
*
* @param pdrv drive number
* @param discio_impl pointer to ff_diskio_impl_t structure with diskio functions
* @param discio_impl pointer to ff_diskio_impl_t structure with diskio functions
* or NULL to unregister and free previously registered drive
*/
void ff_diskio_register(BYTE pdrv, const ff_diskio_impl_t* discio_impl);
#define ff_diskio_unregister(pdrv_) ff_diskio_register(pdrv_, NULL)
/**
* Register SD/MMC diskio driver
*
@ -76,6 +79,16 @@ void ff_diskio_register(BYTE pdrv, const ff_diskio_impl_t* discio_impl);
*/
void ff_diskio_register_sdmmc(BYTE pdrv, sdmmc_card_t* card);
/**
* Get next available drive number
*
* @param out_pdrv pointer to the byte to set if successful
*
* @return ESP_OK on success
* ESP_ERR_NOT_FOUND if all drives are attached
*/
esp_err_t ff_diskio_get_drive(BYTE* out_pdrv);
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */

View file

@ -51,11 +51,31 @@ esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive,
* @note FATFS structure returned by esp_vfs_fat_register is destroyed after
* this call. Make sure to call f_mount function to unmount it before
* calling esp_vfs_fat_unregister.
* This function is left for compatibility and will be changed in
* future versions to accept base_path and replace the method below
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_STATE if FATFS is not registered in VFS
*/
esp_err_t esp_vfs_fat_unregister();
esp_err_t esp_vfs_fat_unregister() __attribute__((deprecated));
/**
* @brief Un-register FATFS from VFS
*
* @note FATFS structure returned by esp_vfs_fat_register is destroyed after
* this call. Make sure to call f_mount function to unmount it before
* calling esp_vfs_fat_unregister_ctx.
* Difference between this function and the one above is that this one
* will release the correct drive, while the one above will release
* the last registered one
*
* @param base_path path prefix where FATFS is registered. This is the same
* used when esp_vfs_fat_register was called
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_STATE if FATFS is not registered in VFS
*/
esp_err_t esp_vfs_fat_unregister_path(const char* base_path);
/**
* @brief Configuration arguments for esp_vfs_fat_sdmmc_mount function

View file

@ -28,6 +28,7 @@
typedef struct {
char fat_drive[8];
char base_path[ESP_VFS_PATH_MAX];
size_t max_files;
FATFS fs;
FIL files[0];
@ -42,7 +43,6 @@ typedef struct {
struct dirent cur_dirent;
} vfs_fat_dir_t;
static const char* TAG = "vfs_fat";
static size_t vfs_fat_write(void* p, int fd, const void * data, size_t size);
@ -64,15 +64,42 @@ static int vfs_fat_closedir(void* ctx, DIR* pdir);
static int vfs_fat_mkdir(void* ctx, const char* name, mode_t mode);
static int vfs_fat_rmdir(void* ctx, const char* name);
static char s_base_path[ESP_VFS_PATH_MAX];
static vfs_fat_ctx_t* s_fat_ctxs[_VOLUMES] = { NULL, NULL };
//backwards-compatibility with esp_vfs_fat_unregister()
static vfs_fat_ctx_t* s_fat_ctx = NULL;
static size_t find_context_index_by_path(const char* base_path)
{
for(size_t i=0; i<_VOLUMES; i++) {
if (s_fat_ctxs[i] && !strcmp(s_fat_ctxs[i]->base_path, base_path)) {
return i;
}
}
return _VOLUMES;
}
static size_t find_unused_context_index()
{
for(size_t i=0; i<_VOLUMES; i++) {
if (!s_fat_ctxs[i]) {
return i;
}
}
return _VOLUMES;
}
esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive, size_t max_files, FATFS** out_fs)
{
if (s_fat_ctx) {
size_t ctx = find_context_index_by_path(base_path);
if (ctx < _VOLUMES) {
return ESP_ERR_INVALID_STATE;
}
ctx = find_unused_context_index();
if (ctx == _VOLUMES) {
return ESP_ERR_NO_MEM;
}
const esp_vfs_t vfs = {
.flags = ESP_VFS_FLAG_CONTEXT_PTR,
.write_p = &vfs_fat_write,
@ -95,22 +122,45 @@ esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive, siz
.rmdir_p = &vfs_fat_rmdir
};
size_t ctx_size = sizeof(vfs_fat_ctx_t) + max_files * sizeof(FIL);
s_fat_ctx = (vfs_fat_ctx_t*) calloc(1, ctx_size);
if (s_fat_ctx == NULL) {
vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) calloc(1, ctx_size);
if (fat_ctx == NULL) {
return ESP_ERR_NO_MEM;
}
s_fat_ctx->max_files = max_files;
strncpy(s_fat_ctx->fat_drive, fat_drive, sizeof(s_fat_ctx->fat_drive) - 1);
*out_fs = &s_fat_ctx->fs;
esp_err_t err = esp_vfs_register(base_path, &vfs, s_fat_ctx);
fat_ctx->max_files = max_files;
strlcpy(fat_ctx->fat_drive, fat_drive, sizeof(fat_ctx->fat_drive) - 1);
strlcpy(fat_ctx->base_path, base_path, sizeof(fat_ctx->base_path) - 1);
esp_err_t err = esp_vfs_register(base_path, &vfs, fat_ctx);
if (err != ESP_OK) {
free(s_fat_ctx);
s_fat_ctx = NULL;
free(fat_ctx);
return err;
}
_lock_init(&s_fat_ctx->lock);
strncpy(s_base_path, base_path, sizeof(s_base_path) - 1);
s_base_path[sizeof(s_base_path) - 1] = 0;
_lock_init(&fat_ctx->lock);
s_fat_ctxs[ctx] = fat_ctx;
//compatibility
s_fat_ctx = fat_ctx;
*out_fs = &fat_ctx->fs;
return ESP_OK;
}
esp_err_t esp_vfs_fat_unregister_path(const char* base_path)
{
size_t ctx = find_context_index_by_path(base_path);
if (ctx == _VOLUMES) {
return ESP_ERR_INVALID_STATE;
}
vfs_fat_ctx_t* fat_ctx = s_fat_ctxs[ctx];
esp_err_t err = esp_vfs_unregister(fat_ctx->base_path);
if (err != ESP_OK) {
return err;
}
_lock_close(&fat_ctx->lock);
free(fat_ctx);
s_fat_ctxs[ctx] = NULL;
return ESP_OK;
}
@ -119,12 +169,10 @@ esp_err_t esp_vfs_fat_unregister()
if (s_fat_ctx == NULL) {
return ESP_ERR_INVALID_STATE;
}
esp_err_t err = esp_vfs_unregister(s_base_path);
esp_err_t err = esp_vfs_fat_unregister_path(s_fat_ctx->base_path);
if (err != ESP_OK) {
return err;
}
_lock_close(&s_fat_ctx->lock);
free(s_fat_ctx);
s_fat_ctx = NULL;
return ESP_OK;
}
@ -197,11 +245,23 @@ static void file_cleanup(vfs_fat_ctx_t* ctx, int fd)
memset(&ctx->files[fd], 0, sizeof(FIL));
}
static void prepend_drive_to_path(void * ctx, const char * path, const char * path2){
static char buf[FILENAME_MAX+3];
static char buf2[FILENAME_MAX+3];
sprintf(buf, "%s%s", ((vfs_fat_ctx_t*)ctx)->fat_drive, path);
path = (const char *)buf;
if(path2){
sprintf(buf2, "%s%s", ((vfs_fat_ctx_t*)ctx)->fat_drive, path2);
path2 = (const char *)buf;
}
}
static int vfs_fat_open(void* ctx, const char * path, int flags, int mode)
{
prepend_drive_to_path(ctx, path, NULL);
ESP_LOGV(TAG, "%s: path=\"%s\", flags=%x, mode=%x", __func__, path, flags, mode);
vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx;
_lock_acquire(&s_fat_ctx->lock);
_lock_acquire(&fat_ctx->lock);
int fd = get_next_fd(fat_ctx);
if (fd < 0) {
ESP_LOGE(TAG, "open: no free file descriptors");
@ -218,7 +278,7 @@ static int vfs_fat_open(void* ctx, const char * path, int flags, int mode)
goto out;
}
out:
_lock_release(&s_fat_ctx->lock);
_lock_release(&fat_ctx->lock);
return fd;
}
@ -257,7 +317,7 @@ static ssize_t vfs_fat_read(void* ctx, int fd, void * dst, size_t size)
static int vfs_fat_close(void* ctx, int fd)
{
vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx;
_lock_acquire(&s_fat_ctx->lock);
_lock_acquire(&fat_ctx->lock);
FIL* file = &fat_ctx->files[fd];
FRESULT res = f_close(file);
file_cleanup(fat_ctx, fd);
@ -267,7 +327,7 @@ static int vfs_fat_close(void* ctx, int fd)
errno = fresult_to_errno(res);
rc = -1;
}
_lock_release(&s_fat_ctx->lock);
_lock_release(&fat_ctx->lock);
return rc;
}
@ -308,6 +368,7 @@ static int vfs_fat_fstat(void* ctx, int fd, struct stat * st)
static int vfs_fat_stat(void* ctx, const char * path, struct stat * st)
{
prepend_drive_to_path(ctx, path, NULL);
FILINFO info;
FRESULT res = f_stat(path, &info);
if (res != FR_OK) {
@ -337,6 +398,7 @@ static int vfs_fat_stat(void* ctx, const char * path, struct stat * st)
static int vfs_fat_unlink(void* ctx, const char *path)
{
prepend_drive_to_path(ctx, path, NULL);
FRESULT res = f_unlink(path);
if (res != FR_OK) {
ESP_LOGD(TAG, "%s: fresult=%d", __func__, res);
@ -348,6 +410,7 @@ static int vfs_fat_unlink(void* ctx, const char *path)
static int vfs_fat_link(void* ctx, const char* n1, const char* n2)
{
prepend_drive_to_path(ctx, n1, n2);
const size_t copy_buf_size = 4096;
void* buf = malloc(copy_buf_size);
if (buf == NULL) {
@ -402,6 +465,7 @@ fail1:
static int vfs_fat_rename(void* ctx, const char *src, const char *dst)
{
prepend_drive_to_path(ctx, src, dst);
FRESULT res = f_rename(src, dst);
if (res != FR_OK) {
ESP_LOGD(TAG, "%s: fresult=%d", __func__, res);
@ -413,6 +477,7 @@ static int vfs_fat_rename(void* ctx, const char *src, const char *dst)
static DIR* vfs_fat_opendir(void* ctx, const char* name)
{
prepend_drive_to_path(ctx, name, NULL);
vfs_fat_dir_t* fat_dir = calloc(1, sizeof(vfs_fat_dir_t));
if (!fat_dir) {
errno = ENOMEM;
@ -517,6 +582,7 @@ static void vfs_fat_seekdir(void* ctx, DIR* pdir, long offset)
static int vfs_fat_mkdir(void* ctx, const char* name, mode_t mode)
{
(void) mode;
prepend_drive_to_path(ctx, name, NULL);
FRESULT res = f_mkdir(name);
if (res != FR_OK) {
ESP_LOGD(TAG, "%s: fresult=%d", __func__, res);
@ -528,6 +594,7 @@ static int vfs_fat_mkdir(void* ctx, const char* name, mode_t mode)
static int vfs_fat_rmdir(void* ctx, const char* name)
{
prepend_drive_to_path(ctx, name, NULL);
FRESULT res = f_unlink(name);
if (res != FR_OK) {
ESP_LOGD(TAG, "%s: fresult=%d", __func__, res);

View file

@ -13,6 +13,7 @@
// limitations under the License.
#include <stdlib.h>
#include <string.h>
#include "esp_log.h"
#include "esp_vfs.h"
#include "esp_vfs_fat.h"
@ -22,6 +23,8 @@
static const char* TAG = "vfs_fat_sdmmc";
static sdmmc_card_t* s_card = NULL;
static uint8_t s_pdrv = 0;
static char * s_base_path = NULL;
esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path,
const sdmmc_host_t* host_config,
@ -35,18 +38,37 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path,
if (s_card != NULL) {
return ESP_ERR_INVALID_STATE;
}
// connect SDMMC driver to FATFS
BYTE pdrv = 0xFF;
if (ff_diskio_get_drive(&pdrv) != ESP_OK || pdrv == 0xFF) {
ESP_LOGD(TAG, "the maximum count of volumes is already mounted");
return ESP_ERR_NO_MEM;
}
s_base_path = strdup(base_path);
if(!s_base_path){
ESP_LOGD(TAG, "could not copy base_path");
return ESP_ERR_NO_MEM;
}
// enable SDMMC
sdmmc_host_init();
// enable card slot
sdmmc_host_init_slot(host_config->slot, slot_config);
esp_err_t err = sdmmc_host_init_slot(host_config->slot, slot_config);
if (err != ESP_OK) {
return err;
}
s_card = malloc(sizeof(sdmmc_card_t));
if (s_card == NULL) {
return ESP_ERR_NO_MEM;
err = ESP_ERR_NO_MEM;
goto fail;
}
// probe and initialize card
esp_err_t err = sdmmc_card_init(host_config, s_card);
err = sdmmc_card_init(host_config, s_card);
if (err != ESP_OK) {
ESP_LOGD(TAG, "sdmmc_card_init failed 0x(%x)", err);
goto fail;
@ -55,12 +77,13 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path,
*out_card = s_card;
}
// connect SDMMC driver to FATFS
ff_diskio_register_sdmmc(0, s_card);
ff_diskio_register_sdmmc(pdrv, s_card);
s_pdrv = pdrv;
char drv[3] = {(char)('0' + pdrv), ':', 0};
// connect FATFS to VFS
FATFS* fs;
err = esp_vfs_fat_register(base_path, "", mount_config->max_files, &fs);
err = esp_vfs_fat_register(base_path, drv, mount_config->max_files, &fs);
if (err == ESP_ERR_INVALID_STATE) {
// it's okay, already registered with VFS
} else if (err != ESP_OK) {
@ -69,7 +92,7 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path,
}
// Try to mount partition
FRESULT res = f_mount(fs, "", 1);
FRESULT res = f_mount(fs, drv, 1);
if (res != FR_OK) {
err = ESP_FAIL;
ESP_LOGW(TAG, "failed to mount card (%d)", res);
@ -79,7 +102,7 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path,
ESP_LOGW(TAG, "partitioning card");
DWORD plist[] = {100, 0, 0, 0};
workbuf = malloc(workbuf_size);
res = f_fdisk(0, plist, workbuf);
res = f_fdisk(s_pdrv, plist, workbuf);
if (res != FR_OK) {
err = ESP_FAIL;
ESP_LOGD(TAG, "f_fdisk failed (%d)", res);
@ -94,7 +117,7 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path,
}
free(workbuf);
ESP_LOGW(TAG, "mounting again");
res = f_mount(fs, "", 0);
res = f_mount(fs, drv, 0);
if (res != FR_OK) {
err = ESP_FAIL;
ESP_LOGD(TAG, "f_mount failed after formatting (%d)", res);
@ -104,8 +127,10 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path,
return ESP_OK;
fail:
sdmmc_host_deinit();
free(workbuf);
esp_vfs_unregister(base_path);
esp_vfs_fat_unregister_path(base_path);
ff_diskio_unregister(pdrv);
free(s_card);
s_card = NULL;
return err;
@ -117,10 +142,15 @@ esp_err_t esp_vfs_fat_sdmmc_unmount()
return ESP_ERR_INVALID_STATE;
}
// unmount
f_mount(0, "", 0);
char drv[3] = {(char)('0' + s_pdrv), ':', 0};
f_mount(0, drv, 0);
// release SD driver
ff_diskio_unregister(s_pdrv);
free(s_card);
s_card = NULL;
sdmmc_host_deinit();
return esp_vfs_fat_unregister();
esp_err_t err = esp_vfs_fat_unregister_path(s_base_path);
free(s_base_path);
s_base_path = NULL;
return err;
}

View file

@ -52,6 +52,25 @@ static void create_file_with_text(const char* name, const char* text)
TEST_ASSERT_EQUAL(0, fclose(f));
}
TEST_CASE("Mount fails cleanly without card inserted", "[fatfs][ignore]")
{
HEAP_SIZE_CAPTURE();
sdmmc_host_t host = SDMMC_HOST_DEFAULT();
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
.format_if_mount_failed = false,
.max_files = 5
};
for (int i = 0; i < 3; ++i) {
printf("Initializing card, attempt %d ", i);
esp_err_t err = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, NULL);
printf(" err=%d\n", err);
TEST_ESP_ERR(ESP_FAIL, err);
}
HEAP_SIZE_CHECK(0);
}
TEST_CASE("can create and write file on sd card", "[fatfs][ignore]")
{
HEAP_SIZE_CAPTURE();

View file

@ -76,17 +76,38 @@ config FREERTOS_CHECK_STACKOVERFLOW_CANARY
(configCHECK_FOR_STACK_OVERFLOW=2)
endchoice
config FREERTOS_WATCHPOINT_END_OF_STACK
bool "Set a debug watchpoint as a stack overflow check"
default n
help
FreeRTOS can check if a stack has overflown its bounds by checking either the value of
the stack pointer or by checking the integrity of canary bytes. (See FREERTOS_CHECK_STACKOVERFLOW
for more information.) These checks only happen on a context switch, and the situation that caused
the stack overflow may already be long gone by then. This option will use the debug memory
watchpoint 1 (the second one) to allow breaking into the debugger (or panic'ing) as soon as any
of the last 32 bytes on the stack of a task are overwritten. The side effect is that using gdb, you
effectively only have one watchpoint; the 2nd one is overwritten as soon as a task switch happens.
This check only triggers if the stack overflow writes within 4 bytes of the end of the stack, rather than
overshooting further, so it is worth combining this approach with one of the other stack overflow check methods.
When this watchpoint is hit, gdb will stop with a SIGTRAP message. When no OCD is attached, esp-idf
will panic on an unhandled debug exception.
config FREERTOS_THREAD_LOCAL_STORAGE_POINTERS
int "Amount of thread local storage pointers"
range 0 256 if !WIFI_ENABLED
range 1 256 if WIFI_ENABLED
int "Number of thread local storage pointers"
range 0 256 if !(WIFI_ENABLED || ETHERNET)
range 1 256 if WIFI_ENABLED || ETHERNET
default 1
help
FreeRTOS has the ability to store per-thread pointers in the task
control block. This controls the amount of pointers available;
0 turns off this functionality.
control block. This controls the number of pointers available.
If using the WiFi stack, this value must be at least 1.
Value 0 turns off this functionality.
If using the LWIP TCP/IP stack (with WiFi or Ethernet), this value must be at least 1. See the
LWIP_THREAD_LOCAL_STORAGE_INDEX config item in LWIP configuration to determine which thread-local-storage
pointer is reserved for LWIP.
choice FREERTOS_ASSERT
prompt "FreeRTOS assertions"
@ -164,6 +185,17 @@ config FREERTOS_LEGACY_TICK_HOOK
endif #FREERTOS_LEGACY_HOOKS
config FREERTOS_MAX_TASK_NAME_LEN
int "Maximum task name length"
range 1 256
default 16
help
Changes the maximum task name length. Each task allocated will
include this many bytes for a task name. Using a shorter value
saves a small amount of RAM, a longer value allows more complex
names.
For most uses, the default of 16 is OK.
menuconfig FREERTOS_DEBUG_INTERNALS
bool "Debug FreeRTOS internals"
@ -192,22 +224,6 @@ config FREERTOS_PORTMUX_DEBUG_RECURSIVE
portMUX usage.
endif #FREERTOS_UNICORE
config FREERTOS_WATCHPOINT_END_OF_STACK
bool "Set a debug watchpoint at the end of each stack"
default n
help
FreeRTOS can check if a stack has overflown its bounds by checking either the value of
the stack pointer or by checking the integrity of canary bytes. (See FREERTOS_CHECK_STACKOVERFLOW
for more information.) These checks only happen on a context switch, and the situation that caused
the stack overflow may already be long gone by then. This option will use the debug memory
watchpoint 1 (the second one) to allow breaking into the debugger (or panic'ing) as soon as any
of the last 32 bytes on the stack of a task are overwritten. The side effect is that using gdb, you
effectively only have one watchpoint; the 2nd one is overwritten as soon as a task switch happens.
When this watchpoint is hit, gdb will stop with a SIGTRAP message. When no OCD is attached, esp-idf
will panic on an unhandled debug exception.
endif # FREERTOS_DEBUG_INTERNALS
endmenu

View file

@ -119,13 +119,10 @@ typedef struct xEventGroupDefinition
UBaseType_t uxEventGroupNumber;
#endif
portMUX_TYPE eventGroupMux;
} EventGroup_t;
/* Again: one mux for all events. Maybe this can be made more granular. ToDo: look into that. -JD */
static portMUX_TYPE xEventGroupMux = portMUX_INITIALIZER_UNLOCKED;
/*-----------------------------------------------------------*/
/*
@ -156,6 +153,8 @@ EventGroup_t *pxEventBits;
traceEVENT_GROUP_CREATE_FAILED();
}
vPortCPUInitializeMutex(&pxEventBits->eventGroupMux);
return ( EventGroupHandle_t ) pxEventBits;
}
/*-----------------------------------------------------------*/
@ -176,6 +175,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
#endif
vTaskSuspendAll();
taskENTER_CRITICAL(&pxEventBits->eventGroupMux);
{
uxOriginalBitValue = pxEventBits->uxEventBits;
@ -217,6 +217,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
}
}
}
taskEXIT_CRITICAL( &pxEventBits->eventGroupMux );
xAlreadyYielded = xTaskResumeAll();
if( xTicksToWait != ( TickType_t ) 0 )
@ -239,7 +240,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
{
/* The task timed out, just return the current event bit value. */
taskENTER_CRITICAL( &xEventGroupMux );
taskENTER_CRITICAL( &pxEventBits->eventGroupMux );
{
uxReturn = pxEventBits->uxEventBits;
@ -256,7 +257,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
mtCOVERAGE_TEST_MARKER();
}
}
taskEXIT_CRITICAL( &xEventGroupMux );
taskEXIT_CRITICAL( &pxEventBits->eventGroupMux );
xTimeoutOccurred = pdTRUE;
}
@ -295,6 +296,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
#endif
vTaskSuspendAll();
taskENTER_CRITICAL( &pxEventBits->eventGroupMux );
{
const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
@ -361,6 +363,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
}
}
taskEXIT_CRITICAL( &pxEventBits->eventGroupMux );
xAlreadyYielded = xTaskResumeAll();
if( xTicksToWait != ( TickType_t ) 0 )
@ -382,7 +385,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
{
taskENTER_CRITICAL( &xEventGroupMux );
taskENTER_CRITICAL( &pxEventBits->eventGroupMux );
{
/* The task timed out, just return the current event bit value. */
uxReturn = pxEventBits->uxEventBits;
@ -405,7 +408,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
mtCOVERAGE_TEST_MARKER();
}
}
taskEXIT_CRITICAL( &xEventGroupMux );
taskEXIT_CRITICAL( &pxEventBits->eventGroupMux );
/* Prevent compiler warnings when trace macros are not used. */
xTimeoutOccurred = pdFALSE;
@ -434,7 +437,7 @@ EventBits_t uxReturn;
configASSERT( xEventGroup );
configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
taskENTER_CRITICAL( &xEventGroupMux );
taskENTER_CRITICAL( &pxEventBits->eventGroupMux );
{
traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
@ -445,7 +448,7 @@ EventBits_t uxReturn;
/* Clear the bits. */
pxEventBits->uxEventBits &= ~uxBitsToClear;
}
taskEXIT_CRITICAL( &xEventGroupMux );
taskEXIT_CRITICAL( &pxEventBits->eventGroupMux );
return uxReturn;
}
@ -498,7 +501,9 @@ BaseType_t xMatchFound = pdFALSE;
pxList = &( pxEventBits->xTasksWaitingForBits );
pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
vTaskSuspendAll();
taskENTER_CRITICAL(&pxEventBits->eventGroupMux);
{
traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
@ -570,6 +575,7 @@ BaseType_t xMatchFound = pdFALSE;
bit was set in the control word. */
pxEventBits->uxEventBits &= ~uxBitsToClear;
}
taskEXIT_CRITICAL(&pxEventBits->eventGroupMux);
( void ) xTaskResumeAll();
return pxEventBits->uxEventBits;
@ -578,10 +584,11 @@ BaseType_t xMatchFound = pdFALSE;
void vEventGroupDelete( EventGroupHandle_t xEventGroup )
{
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
vTaskSuspendAll();
taskENTER_CRITICAL( &pxEventBits->eventGroupMux );
{
traceEVENT_GROUP_DELETE( xEventGroup );
@ -593,6 +600,7 @@ const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
( void ) xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
}
taskEXIT_CRITICAL( &pxEventBits->eventGroupMux );
vPortFree( pxEventBits );
}
( void ) xTaskResumeAll();

View file

@ -187,7 +187,7 @@
#define configAPPLICATION_ALLOCATED_HEAP 1
#define configTOTAL_HEAP_SIZE (&_heap_end - &_heap_start)//( ( size_t ) (64 * 1024) )
#define configMAX_TASK_NAME_LEN ( 16 )
#define configMAX_TASK_NAME_LEN ( CONFIG_FREERTOS_MAX_TASK_NAME_LEN )
#define configUSE_TRACE_FACILITY 0 /* Used by vTaskList in main.c */
#define configUSE_STATS_FORMATTING_FUNCTIONS 0 /* Used by vTaskList in main.c */
#define configUSE_TRACE_FACILITY_2 0 /* Provided by Xtensa port patch */

View file

@ -194,6 +194,12 @@ void vPortYieldOtherCore( BaseType_t coreid) PRIVILEGED_FUNCTION;
*/
void vPortSetStackWatchpoint( void* pxStackStart );
/*
* Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs
* aren't detected here, but they normally cannot call C code, so that should not be an issue anyway.
*/
BaseType_t xPortInIsrContext();
/*
* The structures and methods of manipulating the MPU are contained within the
* port layer.

View file

@ -115,7 +115,7 @@ extern void _xt_coproc_init(void);
/*-----------------------------------------------------------*/
unsigned port_xSchedulerRunning[portNUM_PROCESSORS] = {0}; // Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting
unsigned port_interruptNesting[portNUM_PROCESSORS] = {0}; // Interrupt nesting level
unsigned port_interruptNesting[portNUM_PROCESSORS] = {0}; // Interrupt nesting level. Increased/decreased in portasm.c, _frxt_int_enter/_frxt_int_exit
/*-----------------------------------------------------------*/
@ -256,9 +256,24 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMOR
#endif
/*
* Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs
* aren't detected here, but they normally cannot call C code, so that should not be an issue anyway.
*/
BaseType_t xPortInIsrContext()
{
unsigned int irqStatus;
BaseType_t ret;
irqStatus=portENTER_CRITICAL_NESTED();
ret=(port_interruptNesting[xPortGetCoreID()] != 0);
portEXIT_CRITICAL_NESTED(irqStatus);
return ret;
}
void vPortAssertIfInISR()
{
configASSERT(port_interruptNesting[xPortGetCoreID()]==0)
configASSERT(xPortInIsrContext());
}
/*

View file

@ -1046,25 +1046,59 @@ UBaseType_t x;
}
/*-----------------------------------------------------------*/
static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode, const BaseType_t xCoreID )
static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode, BaseType_t xCoreID )
{
TCB_t *curTCB;
BaseType_t i;
TCB_t *curTCB, *tcb0, *tcb1;
/* Ensure interrupts don't access the task lists while the lists are being
updated. */
taskENTER_CRITICAL(&xTaskQueueMutex);
{
uxCurrentNumberOfTasks++;
//If the task has no affinity and nothing is scheduled on this core, just throw it this core.
//If it has affinity, throw it on the core that needs it if nothing is already scheduled there.
BaseType_t xMyCore = xCoreID;
if ( xMyCore == tskNO_AFFINITY) xMyCore = xPortGetCoreID();
if( pxCurrentTCB[ xMyCore ] == NULL )
// Determine which core this task starts on
if ( xCoreID == tskNO_AFFINITY )
{
if ( portNUM_PROCESSORS == 1 )
{
xCoreID = 0;
}
else
{
// if the task has no affinity, put it on either core if nothing is currently scheduled there. Failing that,
// put it on the core where it will preempt the lowest priority running task. If neither of these are true,
// queue it on the currently running core.
tcb0 = pxCurrentTCB[0];
tcb1 = pxCurrentTCB[1];
if ( tcb0 == NULL )
{
xCoreID = 0;
}
else if ( tcb1 == NULL )
{
xCoreID = 1;
}
else if ( tcb0->uxPriority < pxNewTCB->uxPriority && tcb0->uxPriority < tcb1->uxPriority )
{
xCoreID = 0;
}
else if ( tcb1->uxPriority < pxNewTCB->uxPriority )
{
xCoreID = 1;
}
else
{
xCoreID = xPortGetCoreID(); // Both CPU have higher priority tasks running on them, so this won't run yet
}
}
}
// If nothing is running on this core, put the new task there now
if( pxCurrentTCB[ xCoreID ] == NULL )
{
/* There are no other tasks, or all the other tasks are in
the suspended state - make this the current task. */
pxCurrentTCB[ xMyCore ] = pxNewTCB;
pxCurrentTCB[ xCoreID ] = pxNewTCB;
if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
{
@ -1090,19 +1124,11 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode
so far. */
if( xSchedulerRunning == pdFALSE )
{
/* Scheduler isn't running yet. We need to determine on which CPU to run this task. */
for ( i=0; i<portNUM_PROCESSORS; i++ )
/* Scheduler isn't running yet. We need to determine on which CPU to run this task.
Schedule now if either nothing is scheduled yet or we can replace a task of lower prio. */
if ( pxCurrentTCB[xCoreID] == NULL || pxCurrentTCB[xCoreID]->uxPriority <= pxNewTCB->uxPriority )
{
/* Can we schedule this task on core i? */
if (xCoreID == tskNO_AFFINITY || xCoreID == i)
{
/* Schedule if nothing is scheduled yet, or overwrite a task of lower prio. */
if ( pxCurrentTCB[i] == NULL || pxCurrentTCB[i]->uxPriority <= pxNewTCB->uxPriority )
{
pxCurrentTCB[i] = pxNewTCB;
break;
}
}
pxCurrentTCB[xCoreID] = pxNewTCB;
}
}
else
@ -1130,37 +1156,27 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode
if( xSchedulerRunning != pdFALSE )
{
taskENTER_CRITICAL(&xTaskQueueMutex);
curTCB = pxCurrentTCB[ xPortGetCoreID() ];
taskENTER_CRITICAL(&xTaskQueueMutex);
curTCB = pxCurrentTCB[ xCoreID ];
/* Scheduler is running. If the created task is of a higher priority than an executing task
then it should run now.
ToDo: This only works for the current core. If a task is scheduled on an other processor,
the other processor will keep running the task it's working on, and only switch to the newer
task on a timer interrupt. */
//No mux here, uxPriority is mostly atomic and there's not really any harm if this check misfires.
if( curTCB->uxPriority < pxNewTCB->uxPriority )
then it should run now.
*/
if( curTCB == NULL || curTCB->uxPriority < pxNewTCB->uxPriority )
{
/* Scheduler is running. If the created task is of a higher priority than an executing task
then it should run now.
No mux here, uxPriority is mostly atomic and there's not really any harm if this check misfires.
*/
if( tskCAN_RUN_HERE( xCoreID ) && curTCB->uxPriority < pxNewTCB->uxPriority )
if( xCoreID == xPortGetCoreID() )
{
taskYIELD_IF_USING_PREEMPTION_MUX(&xTaskQueueMutex);
}
else if( xCoreID != xPortGetCoreID() ) {
else {
taskYIELD_OTHER_CORE(xCoreID, pxNewTCB->uxPriority);
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
taskEXIT_CRITICAL(&xTaskQueueMutex);
taskEXIT_CRITICAL(&xTaskQueueMutex);
}
else
{

View file

@ -11,9 +11,10 @@
#define BIT_RESPONSE(TASK) (1 << (TASK+1))
#define ALL_RESPONSE_BITS (((1 << NUM_TASKS) - 1) << 1)
static const int NUM_TASKS = 4;
static const int COUNT = 4000;
static const int NUM_TASKS = 8;
static const int COUNT = 1000;
static EventGroupHandle_t eg;
static SemaphoreHandle_t done_sem;
static void task_event_group_call_response(void *param)
{
@ -24,47 +25,51 @@ static void task_event_group_call_response(void *param)
for (int i = 0; i < COUNT; i++) {
/* Wait until the common "call" bit is set, starts off all tasks
(clear on return) */
while (!xEventGroupWaitBits(eg, BIT_CALL, true, false, portMAX_DELAY)) {
}
TEST_ASSERT( xEventGroupWaitBits(eg, BIT_CALL, true, false, portMAX_DELAY) );
/* Set our individual "response" bit */
xEventGroupSetBits(eg, BIT_RESPONSE(task_num));
}
printf("Task %d done\n", task_num);
/* Delay is due to not-yet-fixed bug with deleting tasks at same time */
vTaskDelay(100 / portTICK_PERIOD_MS);
xSemaphoreGive(done_sem);
vTaskDelete(NULL);
}
TEST_CASE("FreeRTOS Event Groups", "[freertos][ignore]")
TEST_CASE("FreeRTOS Event Groups", "[freertos]")
{
eg = xEventGroupCreate();
done_sem = xSemaphoreCreateCounting(NUM_TASKS, 0);
/* Note: task_event_group_call_response all have higher priority than us, so will block together.
/* Note: task_event_group_call_response all have higher priority than this task, so on this core
they will always preempt this task.
This is important because we need to know they'll all have blocked on BIT_CALL each time we
signal it, or they get out of sync.
This is important because we need to know all tasks have blocked on BIT_CALL each time we signal it,
or they get out of sync.
*/
for (int c = 0; c < NUM_TASKS; c++) {
xTaskCreatePinnedToCore(task_event_group_call_response, "tsk_call_resp", 4096, (void *)c, configMAX_PRIORITIES - 1, NULL, c % portNUM_PROCESSORS);
}
/* Scheduler weirdness, if we don't sleep a few ticks here then the tasks on the other CPU aren't running yet... */
vTaskDelay(10);
/* Tasks all start instantly, but this task will resume running at the same time as the higher priority tasks on the
other processor may still be setting up, so give a tick for them to also block on BIT_CALL... */
vTaskDelay(1);
for (int i = 0; i < COUNT; i++) {
if (i % 100 == 0) {
//printf("Call %d\n", i);
}
/* signal all tasks with "CALL" bit... */
xEventGroupSetBits(eg, BIT_CALL);
while (xEventGroupWaitBits(eg, ALL_RESPONSE_BITS, true, true, portMAX_DELAY) != ALL_RESPONSE_BITS) {
}
TEST_ASSERT_EQUAL_HEX16(ALL_RESPONSE_BITS, xEventGroupWaitBits(eg, ALL_RESPONSE_BITS, true, true, 100 / portMAX_DELAY));
}
}
/* Ensure all tasks cleaned up correctly */
for (int c = 0; c < NUM_TASKS; c++) {
TEST_ASSERT( xSemaphoreTake(done_sem, 100/portTICK_PERIOD_MS) );
}
vSemaphoreDelete(done_sem);
vEventGroupDelete(eg);
}
#define BIT_DONE(X) (1<<(NUM_TASKS+1+X))
@ -82,24 +87,32 @@ static void task_test_sync(void *param)
}
int after_done = xEventGroupSetBits(eg, BIT_DONE(task_num));
printf("Done %d = %x\n", task_num, after_done);
printf("Done %d = 0x%08x\n", task_num, after_done);
/* Delay is due to not-yet-fixed bug with deleting tasks at same time */
vTaskDelay(100 / portTICK_PERIOD_MS);
xSemaphoreGive(done_sem);
vTaskDelete(NULL);
}
TEST_CASE("FreeRTOS Event Group Sync", "[freertos][ignore]")
TEST_CASE("FreeRTOS Event Group Sync", "[freertos]")
{
eg = xEventGroupCreate();
done_sem = xSemaphoreCreateCounting(NUM_TASKS, 0);
for (int c = 0; c < NUM_TASKS; c++) {
xTaskCreatePinnedToCore(task_test_sync, "task_test_sync", 4096, (void *)c, configMAX_PRIORITIES - 1, NULL, c % portNUM_PROCESSORS);
}
for (int c = 0; c < NUM_TASKS; c++) {
printf("Waiting on %d (%x)\n", c, BIT_DONE(c));
xEventGroupWaitBits(eg, BIT_DONE(c), false, false, portMAX_DELAY);
printf("Waiting on %d (0x%08x)\n", c, BIT_DONE(c));
TEST_ASSERT( xEventGroupWaitBits(eg, BIT_DONE(c), false, false, portMAX_DELAY) );
}
/* Ensure all tasks cleaned up correctly */
for (int c = 0; c < NUM_TASKS; c++) {
TEST_ASSERT( xSemaphoreTake(done_sem, 100/portTICK_PERIOD_MS) );
}
vSemaphoreDelete(done_sem);
vEventGroupDelete(eg);
}

View file

@ -0,0 +1,51 @@
/*
See if xPortInIsrContext works
*/
#include <esp_types.h>
#include <stdio.h>
#include "rom/ets_sys.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "freertos/xtensa_api.h"
#include "unity.h"
#include "esp_intr_alloc.h"
#include "xtensa/hal.h"
static volatile int in_int_context, int_handled;
static void testint(void *arg) {
xthal_set_ccompare(1, xthal_get_ccount()+8000000000);
ets_printf("INT!\n");
if (xPortInIsrContext()) in_int_context++;
int_handled++;
}
static void testthread(void *arg) {
intr_handle_t handle;
in_int_context=0;
int_handled=0;
TEST_ASSERT(!xPortInIsrContext());
xthal_set_ccompare(2, xthal_get_ccount()+8000000);
esp_intr_alloc(ETS_INTERNAL_TIMER1_INTR_SOURCE, 0, &testint, NULL, &handle);
vTaskDelay(100 / portTICK_PERIOD_MS);
TEST_ASSERT(int_handled);
TEST_ASSERT(in_int_context);
esp_intr_free(handle);
vTaskDelete(NULL);
}
TEST_CASE("xPortInIsrContext test", "[freertos]")
{
xTaskCreatePinnedToCore(testthread, "tst" , 4096, NULL, 3, NULL, 0);
vTaskDelay(150 / portTICK_PERIOD_MS);
xTaskCreatePinnedToCore(testthread, "tst" , 4096, NULL, 3, NULL, 1);
vTaskDelay(150 / portTICK_PERIOD_MS);
}

View file

@ -10,13 +10,17 @@
static void task_delete_self(void *param)
{
printf("Task %p running on core %d. Deleting shortly...\n", xTaskGetCurrentTaskHandle(), xPortGetCoreID());
vTaskDelay(5);
vTaskDelete(NULL);
}
TEST_CASE("FreeRTOS Delete Tasks", "[freertos][ignore]")
TEST_CASE("FreeRTOS Delete Tasks", "[freertos]")
{
uint32_t before_count = uxTaskGetNumberOfTasks();
xTaskCreatePinnedToCore(task_delete_self, "tsk_self_a", 4096, NULL, configMAX_PRIORITIES - 1, NULL, 0);
xTaskCreatePinnedToCore(task_delete_self, "tsk_self_a", 4096, NULL, configMAX_PRIORITIES - 1, NULL, 0);
TEST_ASSERT_EQUAL(before_count + 2, uxTaskGetNumberOfTasks());
vTaskDelay(200 / portTICK_PERIOD_MS);
printf("Done?\n");
TEST_ASSERT_EQUAL(before_count, uxTaskGetNumberOfTasks());
}

View file

@ -0,0 +1,49 @@
/*
Generic test for malloc/free
*/
#include <esp_types.h>
#include <stdio.h>
#include "rom/ets_sys.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "freertos/xtensa_api.h"
#include "unity.h"
#include "soc/uart_reg.h"
#include "soc/dport_reg.h"
#include "soc/io_mux_reg.h"
static int tryAllocMem() {
int **mem;
int i, noAllocated, j;
mem=malloc(sizeof(int)*1024);
if (!mem) return 0;
for (i=0; i<1024; i++) {
mem[i]=malloc(1024);
if (mem[i]==NULL) break;
for (j=0; j<1024/4; j++) mem[i][j]=(0xdeadbeef);
}
noAllocated=i;
for (i=0; i<noAllocated; i++) {
for (j=0; j<1024/4; j++) {
TEST_ASSERT(mem[i][j]==(0xdeadbeef));
}
free(mem[i]);
}
free(mem);
return noAllocated;
}
TEST_CASE("Malloc/overwrite, then free all available DRAM", "[freertos]")
{
int m1=0, m2=0;
m1=tryAllocMem();
m2=tryAllocMem();
printf("Could allocate %dK on first try, %dK on 2nd try.\n", m1, m2);
TEST_ASSERT(m1==m2);
}

View file

@ -2,7 +2,7 @@ menu "LWIP"
config L2_TO_L3_COPY
bool "Enable copy between Layer2 and Layer3 packets"
default 0
default n
help
If this feature is enabled, all traffic from layer2(WIFI Driver) will be
copied to a new buffer before sending it to layer3(LWIP stack), freeing
@ -18,7 +18,7 @@ config L2_TO_L3_COPY
config LWIP_MAX_SOCKETS
int "Max number of open sockets"
range 1 16
range 1 32
default 10
help
Sockets take up a certain amount of memory, and allowing fewer
@ -35,14 +35,14 @@ config LWIP_THREAD_LOCAL_STORAGE_INDEX
config LWIP_SO_REUSE
bool "Enable SO_REUSEADDR option"
default 0
default n
help
Enabling this option allows binding to a port which remains in
TIME_WAIT.
config LWIP_SO_RCVBUF
bool "Enable SO_RCVBUF option"
default 0
default n
help
Enabling this option allows checking for available data on a netconn.
@ -57,14 +57,14 @@ config LWIP_DHCP_MAX_NTP_SERVERS
config LWIP_IP_FRAG
bool "Enable fragment outgoing IP packets"
default 0
default n
help
Enabling this option allows fragmenting outgoing IP packets if their size
exceeds MTU.
config LWIP_IP_REASSEMBLY
bool "Enable reassembly incoming fragmented IP packets"
default 0
default n
help
Enabling this option allows reassemblying incoming fragmented IP packets.
@ -84,7 +84,7 @@ config TCP_SYNMAXRTX
config LWIP_DHCP_DOES_ARP_CHECK
bool "Enable an ARP check on the offered address"
default 1
default y
help
Enabling this option allows check if the offered IP address is not already
in use by another host on the network.

View file

@ -550,10 +550,17 @@ dhcp_t1_timeout(struct netif *netif)
DHCP_STATE_RENEWING, not DHCP_STATE_BOUND */
dhcp_renew(netif);
/* Calculate next timeout */
#if ESP_DHCP_TIMER
if (((netif->dhcp->t2_timeout - dhcp->lease_used) / 2) >= (60 + DHCP_COARSE_TIMER_SECS / 2) )
{
netif->dhcp->t1_renew_time = (netif->dhcp->t2_timeout - dhcp->lease_used) / 2;
}
#else
if (((netif->dhcp->t2_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS))
{
netif->dhcp->t1_renew_time = ((netif->dhcp->t2_timeout - dhcp->lease_used) / 2);
}
#endif
}
}
@ -576,10 +583,17 @@ dhcp_t2_timeout(struct netif *netif)
DHCP_STATE_REBINDING, not DHCP_STATE_BOUND */
dhcp_rebind(netif);
/* Calculate next timeout */
#if ESP_DHCP_TIMER
if (((netif->dhcp->t0_timeout - dhcp->lease_used) / 2) >= (60 + DHCP_COARSE_TIMER_SECS / 2))
{
netif->dhcp->t2_rebind_time = ((netif->dhcp->t0_timeout - dhcp->lease_used) / 2);
}
#else
if (((netif->dhcp->t0_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS))
{
netif->dhcp->t2_rebind_time = ((netif->dhcp->t0_timeout - dhcp->lease_used) / 2);
}
#endif
}
}
@ -1060,6 +1074,47 @@ dhcp_bind(struct netif *netif)
/* reset time used of lease */
dhcp->lease_used = 0;
#if ESP_DHCP_TIMER
if (dhcp->offered_t0_lease != 0xffffffffUL) {
/* set renewal period timer */
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t0 renewal timer %"U32_F" secs\n", dhcp->offered_t0_lease));
timeout = dhcp->offered_t0_lease;
dhcp->t0_timeout = timeout;
if (dhcp->t0_timeout == 0) {
dhcp->t0_timeout = 120;
}
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t0_lease*1000));
}
/* temporary DHCP lease? */
if (dhcp->offered_t1_renew != 0xffffffffUL) {
/* set renewal period timer */
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew));
timeout = dhcp->offered_t1_renew;
dhcp->t1_timeout = timeout;
if (dhcp->t1_timeout == 0) {
dhcp->t1_timeout = dhcp->t0_timeout>>1;
}
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000));
dhcp->t1_renew_time = dhcp->t1_timeout;
}
/* set renewal period timer */
if (dhcp->offered_t2_rebind != 0xffffffffUL) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind));
timeout = dhcp->offered_t2_rebind;
dhcp->t2_timeout = timeout;
if (dhcp->t2_timeout == 0) {
dhcp->t2_timeout = (dhcp->t0_timeout>>3)*7;
}
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000));
dhcp->t2_rebind_time = dhcp->t2_timeout;
}
/* If we have sub 1 minute lease, t2 and t1 will kick in at the same time. */
if ((dhcp->t1_timeout >= dhcp->t2_timeout) && (dhcp->t2_timeout > 0)) {
dhcp->t1_timeout = 0;
}
#else
if (dhcp->offered_t0_lease != 0xffffffffUL) {
/* set renewal period timer */
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t0 renewal timer %"U32_F" secs\n", dhcp->offered_t0_lease));
@ -1108,6 +1163,7 @@ dhcp_bind(struct netif *netif)
if ((dhcp->t1_timeout >= dhcp->t2_timeout) && (dhcp->t2_timeout > 0)) {
dhcp->t1_timeout = 0;
}
#endif
if (dhcp->subnet_mask_given) {
/* copy offered network mask */

View file

@ -78,11 +78,6 @@
#include <string.h>
#if ESP_LWIP
#include "esp_wifi_internal.h"
#include "esp_eth.h"
#endif
#define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf))
/* Since the pool is created in memp, PBUF_POOL_BUFSIZE will be automatically
aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */
@ -350,10 +345,10 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
p->ref = 1;
/* set flags */
p->flags = 0;
#if ESP_LWIP
p->user_buf = NULL;
p->user_flag = PBUF_USER_FLAG_OWNER_NULL;
p->l2_owner = NULL;
p->l2_buf = NULL;
#endif
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p));
@ -720,14 +715,13 @@ pbuf_free(struct pbuf *p)
memp_free(MEMP_PBUF_POOL, p);
/* is this a ROM or RAM referencing pbuf? */
} else if (type == PBUF_ROM || type == PBUF_REF) {
#if ESP_LWIP
if (type == PBUF_REF && p->user_flag == PBUF_USER_FLAG_OWNER_WIFI ) {
esp_wifi_internal_free_rx_buffer(p->user_buf);
}
if (type == PBUF_REF && p->user_flag == PBUF_USER_FLAG_OWNER_ETH ) {
esp_eth_free_rx_buf(p->user_buf);
}
if (p->l2_owner != NULL
&& p->l2_buf != NULL
&& p->l2_owner->l2_buffer_free_notify != NULL) {
p->l2_owner->l2_buffer_free_notify(p->l2_buf);
}
#endif
memp_free(MEMP_PBUF, p);
/* type == PBUF_RAM */

View file

@ -45,7 +45,7 @@ extern "C" {
#endif
/** period (in seconds) of the application calling dhcp_coarse_tmr() */
#define DHCP_COARSE_TIMER_SECS 60
#define DHCP_COARSE_TIMER_SECS 1
/** period (in milliseconds) of the application calling dhcp_coarse_tmr() */
#define DHCP_COARSE_TIMER_MSECS (DHCP_COARSE_TIMER_SECS * 1000UL)
/** period (in milliseconds) of the application calling dhcp_fine_tmr() */
@ -76,12 +76,12 @@ struct dhcp
struct dhcp_msg *msg_out; /* outgoing msg */
u16_t options_out_len; /* outgoing msg options length */
u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */
u16_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */
u16_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */
u16_t t1_renew_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next renew try */
u16_t t2_rebind_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next rebind try */
u16_t lease_used; /* #ticks with period DHCP_COARSE_TIMER_SECS since last received DHCP ack */
u16_t t0_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for lease time */
u32_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */
u32_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */
u32_t t1_renew_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next renew try */
u32_t t2_rebind_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next rebind try */
u32_t lease_used; /* #ticks with period DHCP_COARSE_TIMER_SECS since last received DHCP ack */
u32_t t0_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for lease time */
ip_addr_t server_ip_addr; /* dhcp server address that offered this lease (ip_addr_t because passed to UDP) */
ip4_addr_t offered_ip_addr;
ip4_addr_t offered_sn_mask;

View file

@ -330,6 +330,10 @@ struct netif {
u16_t loop_cnt_current;
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
#endif /* ENABLE_LOOPBACK */
#if ESP_LWIP
void (*l2_buffer_free_notify)(void *user_buf); /* Allows LWIP to notify driver when a L2-supplied pbuf can be freed */
#endif
};
#if LWIP_CHECKSUM_CTRL_PER_NETIF

View file

@ -105,12 +105,6 @@ typedef enum {
/** indicates this pbuf includes a TCP FIN flag */
#define PBUF_FLAG_TCP_FIN 0x20U
#if ESP_LWIP
#define PBUF_USER_FLAG_OWNER_NULL 0
#define PBUF_USER_FLAG_OWNER_WIFI 1
#define PBUF_USER_FLAG_OWNER_ETH 2
#endif
struct pbuf {
/** next pbuf in singly linked pbuf chain */
struct pbuf *next;
@ -142,10 +136,10 @@ struct pbuf {
* the stack itself, or pbuf->next pointers from a chain.
*/
u16_t ref;
#if ESP_LWIP
void *user_buf;
u8_t user_flag;
struct netif *l2_owner;
void *l2_buf;
#endif
};

View file

@ -602,6 +602,7 @@
#define ESP_LIGHT_SLEEP 1
#define ESP_L2_TO_L3_COPY CONFIG_L2_TO_L3_COPY
#define ESP_CNT_DEBUG 0
#define ESP_DHCP_TIMER 1
#define TCP_WND_DEFAULT (4*TCP_MSS)
#define TCP_SND_BUF_DEFAULT (2*TCP_MSS)

View file

@ -82,7 +82,10 @@ ethernet_low_level_init(struct netif *netif)
netif->flags |= NETIF_FLAG_IGMP;
#endif
#endif
/* Do whatever else is needed to initialize interface. */
#ifndef CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE
netif->l2_buffer_free_notify = esp_eth_free_rx_buf;
#endif
}
/**
@ -152,11 +155,12 @@ ethernetif_input(struct netif *netif, void *buffer, uint16_t len)
if(buffer== NULL || netif == NULL)
goto _exit;
#if CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE
#ifdef CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE
p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM);
if (p == NULL) {
return;
}
p->l2_owner = NULL;
memcpy(p->payload, buffer, len);
/* full packet send to tcpip_thread to process */
@ -171,13 +175,13 @@ if (netif->input(p, netif) != ERR_OK) {
return;
}
p->payload = buffer;
p->user_flag = PBUF_USER_FLAG_OWNER_ETH;
p->user_buf = buffer;
p->l2_owner = netif;
p->l2_buf = buffer;
/* full packet send to tcpip_thread to process */
if (netif->input(p, netif) != ERR_OK) {
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
p->user_flag = PBUF_USER_FLAG_OWNER_NULL;
p->l2_owner = NULL;
pbuf_free(p);
}
#endif

View file

@ -84,7 +84,9 @@ low_level_init(struct netif *netif)
#endif
#endif
/* Do whatever else is needed to initialize interface. */
#if !ESP_L2_TO_L3_COPY
netif->l2_buffer_free_notify = esp_wifi_internal_free_rx_buffer;
#endif
}
/**
@ -119,6 +121,7 @@ low_level_output(struct netif *netif, struct pbuf *p)
LWIP_DEBUGF(PBUF_DEBUG, ("low_level_output: pbuf is a list, application may has bug"));
q = pbuf_alloc(PBUF_RAW_TX, p->tot_len, PBUF_RAM);
if (q != NULL) {
q->l2_owner = NULL;
pbuf_copy(q, p);
} else {
return ERR_MEM;
@ -154,6 +157,7 @@ wlanif_input(struct netif *netif, void *buffer, u16_t len, void* eb)
esp_wifi_internal_free_rx_buffer(eb);
return;
}
p->l2_owner = NULL;
memcpy(p->payload, buffer, len);
esp_wifi_internal_free_rx_buffer(eb);
#else
@ -163,8 +167,8 @@ wlanif_input(struct netif *netif, void *buffer, u16_t len, void* eb)
return;
}
p->payload = buffer;
p->user_buf = eb;
p->user_flag = PBUF_USER_FLAG_OWNER_WIFI;
p->l2_owner = netif;
p->l2_buf = eb;
#endif
/* full packet send to tcpip_thread to process */

View file

@ -29,6 +29,7 @@
#include MBEDTLS_CONFIG_FILE
#endif
#include "platform.h"
#include "bignum.h"
#include "ecp.h"

View file

@ -43,6 +43,9 @@
static const __attribute__((unused)) char *TAG = "bignum";
#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
#define biL (ciL << 3) /* bits in limb */
#if defined(CONFIG_MBEDTLS_MPI_USE_INTERRUPT)
static SemaphoreHandle_t op_complete_sem;
@ -72,6 +75,7 @@ void esp_mpi_acquire_hardware( void )
{
/* newlib locks lazy initialize on ESP-IDF */
_lock_acquire(&mpi_lock);
REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_RSA);
/* also clear reset on digital signature, otherwise RSA is held in reset */
REG_CLR_BIT(DPORT_PERI_RST_EN_REG,
@ -82,6 +86,8 @@ void esp_mpi_acquire_hardware( void )
while(REG_READ(RSA_CLEAN_REG) != 1);
// Note: from enabling RSA clock to here takes about 1.3us
#ifdef CONFIG_MBEDTLS_MPI_USE_INTERRUPT
rsa_isr_initialise();
#endif
@ -416,6 +422,7 @@ static int modular_multiply_finish(mbedtls_mpi *Z, const mbedtls_mpi *X, const m
#if defined(MBEDTLS_MPI_MUL_MPI_ALT) /* MBEDTLS_MPI_MUL_MPI_ALT */
static int mpi_mult_mpi_failover_mod_mult(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words);
static int mpi_mult_mpi_overlong(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t Y_bits, size_t words_result);
/* Z = X * Y */
int mbedtls_mpi_mul_mpi( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y )
@ -468,12 +475,19 @@ int mbedtls_mpi_mul_mpi( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi
if (words_mult * 32 > 2048) {
/* Calculate new length of Z */
words_z = bits_to_hardware_words(bits_x + bits_y);
if (words_z * 32 > 4096) {
ESP_LOGE(TAG, "ERROR: %d bit result %d bits * %d bits too large for hardware unit\n", words_z * 32, bits_x, bits_y);
return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
}
else {
if (words_z * 32 <= 4096) {
/* Note: it's possible to use mpi_mult_mpi_overlong
for this case as well, but it's very slightly
slower and requires a memory allocation.
*/
return mpi_mult_mpi_failover_mod_mult(Z, X, Y, words_z);
} else {
/* Still too long for the hardware unit... */
if(bits_y > bits_x) {
return mpi_mult_mpi_overlong(Z, X, Y, bits_y, words_z);
} else {
return mpi_mult_mpi_overlong(Z, Y, X, bits_x, words_z);
}
}
}
@ -561,5 +575,64 @@ static int mpi_mult_mpi_failover_mod_mult(mbedtls_mpi *Z, const mbedtls_mpi *X,
return ret;
}
/* Deal with the case when X & Y are too long for the hardware unit, by splitting one operand
into two halves.
Y must be the longer operand
Slice Y into Yp, Ypp such that:
Yp = lower 'b' bits of Y
Ypp = upper 'b' bits of Y (right shifted)
Such that
Z = X * Y
Z = X * (Yp + Ypp<<b)
Z = (X * Yp) + (X * Ypp<<b)
Note that this function may recurse multiple times, if both X & Y
are too long for the hardware multiplication unit.
*/
static int mpi_mult_mpi_overlong(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t bits_y, size_t words_result)
{
int ret;
mbedtls_mpi Ztemp;
const size_t limbs_y = (bits_y + biL - 1) / biL;
/* Rather than slicing in two on bits we slice on limbs (32 bit words) */
const size_t limbs_slice = limbs_y / 2;
/* Yp holds lower bits of Y (declared to reuse Y's array contents to save on copying) */
const mbedtls_mpi Yp = {
.p = Y->p,
.n = limbs_slice,
.s = Y->s
};
/* Ypp holds upper bits of Y, right shifted (also reuses Y's array contents) */
const mbedtls_mpi Ypp = {
.p = Y->p + limbs_slice,
.n = limbs_y - limbs_slice,
.s = Y->s
};
mbedtls_mpi_init(&Ztemp);
/* Grow Z to result size early, avoid interim allocations */
mbedtls_mpi_grow(Z, words_result);
/* Get result Ztemp = Yp * X (need temporary variable Ztemp) */
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi(&Ztemp, X, &Yp) );
/* Z = Ypp * Y */
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi(Z, X, &Ypp) );
/* Z = Z << b */
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(Z, limbs_slice * biL) );
/* Z += Ztemp */
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi(Z, Z, &Ztemp) );
cleanup:
mbedtls_mpi_free(&Ztemp);
return ret;
}
#endif /* MBEDTLS_MPI_MUL_MPI_ALT */

View file

@ -0,0 +1,240 @@
/* mbedTLS RSA functionality tests
Focus on testing functionality where we use ESP32 hardware
accelerated crypto features.
*/
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <esp_system.h>
#include "mbedtls/rsa.h"
#include "mbedtls/pk.h"
#include "mbedtls/x509_crt.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "unity.h"
#include "sdkconfig.h"
/* Taken from openssl s_client -connect api.gigafive.com:443 -showcerts
*/
static const char *rsa4096_cert = "-----BEGIN CERTIFICATE-----\n"\
"MIIExzCCA6+gAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBkjELMAkGA1UEBhMCVVMx\n"\
"CzAJBgNVBAgMAkNBMRQwEgYDVQQHDAtTYW50YSBDbGFyYTElMCMGA1UECgwcR2ln\n"\
"YWZpdmUgVGVjaG5vbG9neSBQYXJ0bmVyczEZMBcGA1UEAwwQR2lnYWZpdmUgUm9v\n"\
"dCBDQTEeMBwGCSqGSIb3DQEJARYPY2FAZ2lnYWZpdmUuY29tMB4XDTE2MDgyNzE2\n"\
"NDYyM1oXDTI2MDgyNTE2NDYyM1owgZcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJD\n"\
"QTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExKTAnBgNVBAoMIEdpZ2FmaXZlIFRlY2hu\n"\
"b2xvZ3kgUGFydG5lcnMgTExDMRkwFwYDVQQDDBBhcGkuZ2lnYWZpdmUuY29tMR8w\n"\
"HQYJKoZIhvcNAQkBFhBjcmxAZ2lnYWZpdmUuY29tMIICIjANBgkqhkiG9w0BAQEF\n"\
"AAOCAg8AMIICCgKCAgEAof82VrEpXMpsI/ddW6RLeTeSYtxiXZZkRbDKN6otYgEk\n"\
"vA8yRbzei2cO2A/8+Erhe9beYLAMXWF+bjoUAFwnuIcbmufgHprOYzX/7CYXCsrH\n"\
"LrJfVF6kvjCXy2W3xSvgh8ZgHNWnBGzl13tq19Fz8x0AhK5GQ9608oJCbnQjpVSI\n"\
"lZDl3JVOifCeXf2c7nMhVOC/reTeto0Gbchs8Ox50WyojmfYbVjOQcA7f8p1eI+D\n"\
"XUJK01cUGVu6/KarVArGHh5LsiyXOadbyeyOXPmjyrgarG3IIBeQSNECfJZPc/OW\n"\
"lFszjU4YLDckI4x+tReiuFQbQPN5sDplcEldmZZm/8XD36ddvAaDds+SYlPXxDK7\n"\
"7L8RBVUG2Ylc9YZf7RE6IMDmdQmsCZDX0VxySYEmzv5lnAx4mzzaXcgS+kHMOLyK\n"\
"n9UxmpzwQoqqC9tMZqwRaeKW1njR1dSwQLqirBPfGCWKkpkpm7C3HEfeeLrasral\n"\
"aPf6LAwN3A4ZKHa5Jmne7W+1eYS1aTXOAOLIPcXRAh1B80H+SusIdM9d6vk2YTIg\n"\
"khwGQV3sgM6nIO5+T/8z141UEjWbtP7pb/u0+G9Cg7TwvRoO2UukxdvOwNto1G2e\n"\
"J3rKB/JSYsYWnPHvvh9XR+55PZ4iCf9Rqw/IP82uyGipR9gxlHqN8WhMTj9tNEkC\n"\
"AwEAAaMhMB8wHQYDVR0OBBYEFISCemcSriz1HFhRXluw9H+Bv9lEMA0GCSqGSIb3\n"\
"DQEBCwUAA4IBAQCMetK0xe6Y/uZpb1ARh+hHYcHI3xI+IG4opWJeoB1gDh/xpNAW\n"\
"j6t5MGbLoqNMBXbqL26hnKVspyvCxw7ebI5ZJgjtbrD1t+0D8yrgIZzr7AWGA9Hj\n"\
"WIHqDHGDxwkmfjVVPmuO3l5RtJmL6KV6kVL2bOvVI6gECpFLddmOTtg+iXDfSw3x\n"\
"0+ueMYKr8QLF+TCxfzQTHvTHvOJtcZHecc1n7PYbRmI2p7tV6RoBpV69oM6NAVUV\n"\
"i2QoSxm0pYzDzavOaxwhEPHT34Tpg6fwXy1QokFD9OtxRFtdpTjL3bMWpatZE+ba\n"\
"cjvvf0utMW5fNjTTxu1nnpuxZM3ifTCqZJ+9\n"\
"-----END CERTIFICATE-----\n";
/* Root cert from openssl s_client -connect google.com:443 -showcerts
*/
static const char *rsa2048_cert = "-----BEGIN CERTIFICATE-----\n"\
"MIIDfTCCAuagAwIBAgIDErvmMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT\n"\
"MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0\n"\
"aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDIwNTIxMDQwMDAwWhcNMTgwODIxMDQwMDAw\n"\
"WjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UE\n"\
"AxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n"\
"CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9m\n"\
"OSm9BXiLnTjoBbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIu\n"\
"T8rxh0PBFpVXLVDviS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6c\n"\
"JmTM386DGXHKTubU1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmR\n"\
"Cw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5asz\n"\
"PeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo4HwMIHtMB8GA1UdIwQYMBaAFEjm\n"\
"aPkr0rKV10fYIyAQTzOYkJ/UMB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrM\n"\
"TjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjA6BgNVHR8EMzAxMC+g\n"\
"LaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNvbS9jcmxzL3NlY3VyZWNhLmNybDBO\n"\
"BgNVHSAERzBFMEMGBFUdIAAwOzA5BggrBgEFBQcCARYtaHR0cHM6Ly93d3cuZ2Vv\n"\
"dHJ1c3QuY29tL3Jlc291cmNlcy9yZXBvc2l0b3J5MA0GCSqGSIb3DQEBBQUAA4GB\n"\
"AHbhEm5OSxYShjAGsoEIz/AIx8dxfmbuwu3UOx//8PDITtZDOLC5MH0Y0FWDomrL\n"\
"NhGc6Ehmo21/uBPUR/6LWlxz/K7ZGzIZOKuXNBSqltLroxwUCEm2u+WR74M26x1W\n"\
"b8ravHNjkOR/ez4iyz0H7V84dJzjA1BOoa+Y7mHyhD8S\n"\
"-----END CERTIFICATE-----\n";
/* Some random input bytes to public key encrypt */
static const uint8_t pki_input[4096/8] = {
0, 1, 4, 6, 7, 9, 33, 103, 49, 11, 56, 211, 67, 92 };
/* Result of an RSA4096 operation using cert's public key
(raw PKI, no padding/etc) */
static const uint8_t pki_rsa4096_output[] = {
0x91, 0x87, 0xcd, 0x04, 0x80, 0x7c, 0x8b, 0x0b,
0x0c, 0xc0, 0x38, 0x37, 0x7a, 0xe3, 0x2c, 0x94,
0xea, 0xc4, 0xcb, 0x83, 0x2c, 0x77, 0x71, 0x14,
0x11, 0x85, 0x16, 0x61, 0xd3, 0x64, 0x2a, 0x0f,
0xf9, 0x6b, 0x45, 0x04, 0x66, 0x5d, 0x15, 0xf1,
0xcf, 0x69, 0x77, 0x90, 0xb9, 0x41, 0x68, 0xa9,
0xa6, 0xfd, 0x94, 0xdc, 0x6a, 0xce, 0xc7, 0xb6,
0x41, 0xd9, 0x44, 0x3c, 0x02, 0xb6, 0xc7, 0x26,
0xce, 0xec, 0x66, 0x21, 0xa8, 0xe8, 0xf4, 0xa9,
0x33, 0x4a, 0x6c, 0x28, 0x0f, 0x50, 0x30, 0x32,
0x28, 0x00, 0xbb, 0x2c, 0xc3, 0x44, 0x72, 0x31,
0x93, 0xd4, 0xde, 0x29, 0x6b, 0xfa, 0x31, 0xfd,
0x3a, 0x05, 0xc6, 0xb1, 0x28, 0x43, 0x57, 0x20,
0xf7, 0xf8, 0x13, 0x0c, 0x4a, 0x80, 0x00, 0xab,
0x1f, 0xe8, 0x88, 0xad, 0x56, 0xf2, 0xda, 0x5a,
0x50, 0xe9, 0x02, 0x09, 0x21, 0x2a, 0xfc, 0x82,
0x68, 0x34, 0xf9, 0x04, 0xa3, 0x25, 0xe1, 0x0f,
0xa8, 0x77, 0x29, 0x94, 0xb6, 0x9d, 0x5a, 0x08,
0x33, 0x8d, 0x27, 0x6a, 0xc0, 0x3b, 0xad, 0x91,
0x8a, 0x83, 0xa9, 0x2e, 0x48, 0xcd, 0x67, 0xa3,
0x3a, 0x35, 0x41, 0x85, 0xfa, 0x3f, 0x61, 0x1f,
0x80, 0xeb, 0xcd, 0x5a, 0xc5, 0x14, 0x7b, 0xab,
0x9c, 0x45, 0x11, 0xd2, 0x25, 0x9a, 0x16, 0xeb,
0x9c, 0xfa, 0xbe, 0x73, 0x18, 0xbd, 0x25, 0x8e,
0x99, 0x6d, 0xb3, 0xbc, 0xac, 0x2d, 0xa2, 0x53,
0xe8, 0x7c, 0x38, 0x1b, 0x7a, 0x75, 0xff, 0x76,
0x4f, 0x48, 0x5b, 0x39, 0x20, 0x5a, 0x7b, 0x82,
0xd3, 0x33, 0x33, 0x2a, 0xab, 0x6a, 0x7a, 0x42,
0x1d, 0x1f, 0xd1, 0x61, 0x58, 0xd7, 0x38, 0x52,
0xdf, 0xb0, 0x61, 0x98, 0x63, 0xb7, 0xa1, 0x4e,
0xdb, 0x9b, 0xcb, 0xb7, 0x85, 0xc4, 0x3e, 0x03,
0xe5, 0x59, 0x50, 0x28, 0x5a, 0x4d, 0x7f, 0x53,
0x2e, 0x99, 0x1d, 0x6d, 0x85, 0x27, 0x78, 0x34,
0x5e, 0xae, 0xc9, 0x1b, 0x37, 0x96, 0xde, 0x40,
0x87, 0x35, 0x3c, 0x1f, 0xe0, 0x8f, 0xfb, 0x3a,
0x58, 0x0e, 0x60, 0xe9, 0x06, 0xbd, 0x83, 0x03,
0x92, 0xde, 0x5e, 0x69, 0x28, 0xb1, 0x00, 0xeb,
0x44, 0xca, 0x3c, 0x49, 0x03, 0x10, 0xa8, 0x84,
0xa6, 0xbb, 0xd5, 0xda, 0x98, 0x8c, 0x6f, 0xa3,
0x0f, 0x39, 0xf3, 0xa7, 0x7d, 0xd5, 0x3b, 0xe2,
0x85, 0x12, 0xda, 0xa4, 0x4d, 0x80, 0x97, 0xcb,
0x11, 0xe0, 0x89, 0x90, 0xff, 0x5b, 0x72, 0x19,
0x59, 0xd1, 0x39, 0x23, 0x9f, 0xb0, 0x00, 0xe2,
0x45, 0x72, 0xc6, 0x9a, 0xbc, 0xe1, 0xd1, 0x51,
0x6b, 0x35, 0xd2, 0x49, 0xbf, 0xb6, 0xfe, 0xab,
0x09, 0xf7, 0x9d, 0xa4, 0x6e, 0x69, 0xb6, 0xf9,
0xde, 0xe3, 0x57, 0x0c, 0x1a, 0x96, 0xf1, 0xcc,
0x1c, 0x92, 0xdb, 0x44, 0xf4, 0x45, 0xfa, 0x8f,
0x87, 0xcf, 0xf4, 0xd2, 0xa1, 0xf8, 0x69, 0x18,
0xcf, 0xdc, 0xa0, 0x1f, 0xb0, 0x26, 0xad, 0x81,
0xab, 0xdf, 0x78, 0x18, 0xa2, 0x74, 0xba, 0x2f,
0xec, 0x70, 0xa2, 0x1f, 0x56, 0xee, 0xff, 0xc9,
0xfe, 0xb1, 0xe1, 0x9b, 0xea, 0x0e, 0x33, 0x14,
0x5f, 0x6e, 0xca, 0xee, 0x02, 0x56, 0x5a, 0x67,
0x42, 0x9a, 0xbf, 0x55, 0xc0, 0x0f, 0x8e, 0x01,
0x67, 0x63, 0x6e, 0xd1, 0x57, 0xf7, 0xf1, 0xc6,
0x92, 0x9e, 0xb5, 0x45, 0xe1, 0x50, 0x58, 0x94,
0x20, 0x90, 0x6a, 0x29, 0x2d, 0x4b, 0xd1, 0xb5,
0x68, 0x63, 0xb5, 0xe6, 0xd8, 0x6e, 0x84, 0x80,
0xad, 0xe6, 0x03, 0x1e, 0x51, 0xc2, 0xa8, 0x6d,
0x84, 0xec, 0x2d, 0x7c, 0x61, 0x02, 0xd1, 0xda,
0xf5, 0x94, 0xfa, 0x2d, 0xa6, 0xed, 0x89, 0x6a,
0x6a, 0xda, 0x07, 0x5d, 0x83, 0xfc, 0x43, 0x76,
0x7c, 0xca, 0x8c, 0x00, 0xfc, 0xb9, 0x2c, 0x23,
};
static const uint8_t pki_rsa2048_output[] = {
0x47, 0x0b, 0xe5, 0x8a, 0xcd, 0x2f, 0x78, 0x07,
0x69, 0x69, 0x70, 0xff, 0x81, 0xdf, 0x96, 0xf0,
0xed, 0x82, 0x3a, 0x3d, 0x46, 0xab, 0xe9, 0xc3,
0xb5, 0xd9, 0xca, 0xa2, 0x05, 0xa9, 0xf6, 0x6e,
0xad, 0x6c, 0xe0, 0xd1, 0xa2, 0xb4, 0xf2, 0x78,
0x4a, 0x93, 0xfc, 0x45, 0xe1, 0x9b, 0xdd, 0x62,
0xf9, 0x66, 0x2a, 0x14, 0x38, 0x12, 0xb6, 0x50,
0x0b, 0xe3, 0x53, 0x9c, 0x12, 0x56, 0xf1, 0xb7,
0x83, 0xd5, 0xf3, 0x24, 0x81, 0xcc, 0x5a, 0xeb,
0xec, 0xac, 0x68, 0xa8, 0x0c, 0xd7, 0x84, 0x7a,
0xbb, 0x77, 0x7b, 0xd5, 0x5b, 0xcf, 0x7b, 0x25,
0xd0, 0x75, 0x80, 0x21, 0x12, 0x97, 0x6b, 0xe1,
0xb6, 0x51, 0x12, 0x52, 0x6e, 0x01, 0x92, 0xb7,
0xcc, 0x70, 0x4b, 0x46, 0x11, 0x98, 0x5a, 0x84,
0x1c, 0x90, 0x45, 0x0f, 0x15, 0x77, 0xdb, 0x79,
0xe8, 0xff, 0x1f, 0xaa, 0x58, 0x95, 0xce, 0x3c,
0x65, 0x0c, 0x66, 0x29, 0xe1, 0x9c, 0x41, 0xbb,
0xde, 0x65, 0xb8, 0x29, 0x36, 0x94, 0xbd, 0x87,
0x93, 0x39, 0xc5, 0xeb, 0x49, 0x21, 0xc1, 0xeb,
0x48, 0xbd, 0x19, 0x13, 0x4d, 0x40, 0x90, 0x88,
0xc6, 0x12, 0xd9, 0xf7, 0xdd, 0xc8, 0x4f, 0x89,
0xc0, 0x91, 0xf8, 0xeb, 0xcf, 0xe3, 0x12, 0x17,
0x88, 0x9c, 0x88, 0xf4, 0xf5, 0xae, 0xf4, 0x15,
0xfe, 0x17, 0xf6, 0xa4, 0x74, 0x49, 0x02, 0x05,
0x11, 0x3b, 0x92, 0x25, 0x39, 0x2c, 0x4b, 0x08,
0x19, 0x76, 0x13, 0x8d, 0xf9, 0xda, 0xae, 0xdf,
0x30, 0xda, 0xcc, 0xbb, 0x3f, 0xb9, 0xb0, 0xd6,
0x5c, 0x78, 0x4b, 0x2b, 0x35, 0x51, 0x17, 0x48,
0xf5, 0xd4, 0x39, 0x7e, 0x05, 0x83, 0x68, 0x86,
0x44, 0x5f, 0x56, 0x1d, 0x2c, 0x53, 0xd3, 0x64,
0x3a, 0xb2, 0x0c, 0x4a, 0x85, 0xd6, 0x5b, 0x7e,
0xf9, 0xe9, 0x50, 0x29, 0x5d, 0x4f, 0xcc, 0xc9,
};
_Static_assert(sizeof(pki_rsa2048_output) == 2048/8, "rsa2048 output is wrong size");
_Static_assert(sizeof(pki_rsa4096_output) == 4096/8, "rsa4096 output is wrong size");
static void test_cert(const char *cert, const uint8_t *expected_output, size_t output_len);
TEST_CASE("mbedtls RSA4096 cert", "[mbedtls]")
{
test_cert(rsa4096_cert, pki_rsa4096_output, 4096/8);
}
TEST_CASE("mbedtls RSA2048 cert", "[mbedtls]")
{
test_cert(rsa2048_cert, pki_rsa2048_output, 2048/8);
}
static void test_cert(const char *cert, const uint8_t *expected_output, size_t output_len)
{
mbedtls_x509_crt crt;
mbedtls_rsa_context *rsa;
char buf[output_len];
bzero(buf, output_len);
mbedtls_x509_crt_init(&crt);
TEST_ASSERT_EQUAL_HEX16_MESSAGE(0,
-mbedtls_x509_crt_parse(&crt,
(const uint8_t *)cert,
strlen(cert)+1),
"parse cert");
rsa = mbedtls_pk_rsa(crt.pk);
TEST_ASSERT_NOT_NULL(rsa);
TEST_ASSERT_EQUAL_HEX16_MESSAGE(0,
-mbedtls_rsa_check_pubkey(rsa),
"check cert pubkey");
mbedtls_x509_crt_info(buf, sizeof(buf), "", &crt);
puts(buf);
TEST_ASSERT_EQUAL_HEX16_MESSAGE(0,
-mbedtls_rsa_public(rsa, pki_input, (uint8_t *)buf),
"RSA PK operation");
/*
// Dump buffer for debugging
for(int i = 0; i < output_len; i++) {
printf("0x%02x, ", buf[i]);
}
printf("\n");
*/
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_output, buf, output_len);
mbedtls_x509_crt_free(&crt);
}

View file

@ -21,6 +21,7 @@
#include "freertos/semphr.h"
#include "freertos/portmacro.h"
#include "freertos/task.h"
#include "freertos/portable.h"
/* Notes on our newlib lock implementation:
*
@ -126,7 +127,7 @@ static int IRAM_ATTR lock_acquire_generic(_lock_t *lock, uint32_t delay, uint8_t
}
BaseType_t success;
if (cpu_in_interrupt_context()) {
if (xPortInIsrContext()) {
/* In ISR Context */
if (mutex_type == queueQUEUE_TYPE_RECURSIVE_MUTEX) {
abort(); /* recursive mutexes make no sense in ISR context */
@ -180,7 +181,7 @@ static void IRAM_ATTR lock_release_generic(_lock_t *lock, uint8_t mutex_type) {
return;
}
if (cpu_in_interrupt_context()) {
if (xPortInIsrContext()) {
if (mutex_type == queueQUEUE_TYPE_RECURSIVE_MUTEX) {
abort(); /* indicates logic bug, it shouldn't be possible to lock recursively in ISR */
}

View file

@ -52,7 +52,7 @@ static uint64_t get_rtc_time_us()
uint64_t low = READ_PERI_REG(RTC_CNTL_TIME0_REG);
uint64_t high = READ_PERI_REG(RTC_CNTL_TIME1_REG);
uint64_t ticks = (high << 32) | low;
return ticks * 100 / (RTC_CTNL_SLOWCLK_FREQ / 10000); // scale RTC_CTNL_SLOWCLK_FREQ to avoid overflow
return ticks * 100 / (RTC_CNTL_SLOWCLK_FREQ / 10000); // scale RTC_CNTL_SLOWCLK_FREQ to avoid overflow
}
#endif // WITH_RTC

View file

@ -2,6 +2,7 @@ TEST_PROGRAM=test_nvs
all: $(TEST_PROGRAM)
SOURCE_FILES = \
esp_error_check_stub.cpp \
$(addprefix ../src/, \
nvs_types.cpp \
nvs_api.cpp \

View file

@ -0,0 +1,9 @@
#include "catch.hpp"
#include "esp_err.h"
void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression)
{
printf("ESP_ERROR_CHECK failed: esp_err_t 0x%x at %p\n", rc, __builtin_return_address(0));
printf("file: \"%s\" line %d\nfunc: %s\nexpression: %s\n", file, line, function, expression);
abort();
}

Some files were not shown because too many files have changed in this diff Show more