mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'master' into feature/btdm_avrc
This commit is contained in:
commit
383db0dc81
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
5
components/app_update/test/component.mk
Normal file
5
components/app_update/test/component.mk
Normal file
@ -0,0 +1,5 @@
|
||||
#
|
||||
#Component Makefile
|
||||
#
|
||||
|
||||
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
|
86
components/app_update/test/test_ota_ops.c
Normal file
86
components/app_update/test/test_ota_ops.c
Normal 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);
|
||||
}
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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))
|
||||
|
230
components/bootloader/src/main/flash_qio_mode.c
Normal file
230
components/bootloader/src/main/flash_qio_mode.c
Normal 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];
|
||||
}
|
29
components/bootloader/src/main/flash_qio_mode.h
Normal file
29
components/bootloader/src/main/flash_qio_mode.h
Normal 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
|
@ -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;
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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")) {
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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, ¶m,
|
||||
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, ¶m, 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, ¶m,
|
||||
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();
|
||||
|
@ -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__);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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
|
@ -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, \
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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__ */
|
||||
|
@ -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
|
@ -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
|
||||
*
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
*
|
||||
*/
|
||||
|
@ -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).
|
||||
*/
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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 ; */
|
||||
|
@ -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
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
20
components/esp32/test/test_tsens.c
Normal file
20
components/esp32/test/test_tsens.c
Normal 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);
|
||||
}
|
@ -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
|
@ -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])
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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 */
|
||||
|
@ -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.
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
51
components/freertos/test/test_freertos_isinisrcontext.c
Normal file
51
components/freertos/test/test_freertos_isinisrcontext.c
Normal 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);
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
49
components/freertos/test/test_malloc.c
Normal file
49
components/freertos/test/test_malloc.c
Normal 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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include "platform.h"
|
||||
#include "bignum.h"
|
||||
#include "ecp.h"
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
240
components/mbedtls/test/test_rsa.c
Normal file
240
components/mbedtls/test/test_rsa.c
Normal 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);
|
||||
}
|
@ -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 */
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user