forked from espressif/esp-idf
Compare commits
223 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f5e484fc79 | ||
|
|
997844bbc3 | ||
|
|
10f0879fdb | ||
|
|
d016f69ffc | ||
|
|
847d9631b9 | ||
|
|
3c5eb41914 | ||
|
|
be26894259 | ||
|
|
bdc671aee3 | ||
|
|
ca1628b310 | ||
|
|
2f634a82d5 | ||
|
|
a46d166c49 | ||
|
|
0c88beb9c4 | ||
|
|
c5875e64b1 | ||
|
|
0efba69571 | ||
|
|
ec70ed86e0 | ||
|
|
064474fca6 | ||
|
|
d98e2a3d5f | ||
|
|
8e8cf08d2d | ||
|
|
3ffcb03f60 | ||
|
|
0a0ad4309f | ||
|
|
63324950fa | ||
|
|
0a7fedcbbd | ||
|
|
9d854cd6b0 | ||
|
|
eddee33f98 | ||
|
|
510f86d451 | ||
|
|
4bdc7853cf | ||
|
|
7718c60d81 | ||
|
|
8b09f2f01f | ||
|
|
ac8b720880 | ||
|
|
fdc70f5b7f | ||
|
|
5d1864b7d7 | ||
|
|
9003e6d1eb | ||
|
|
029ed39579 | ||
|
|
da340c02cc | ||
|
|
06d169e518 | ||
|
|
1af2a470dc | ||
|
|
6842dc1d2d | ||
|
|
1801a10828 | ||
|
|
b7fe47292f | ||
|
|
61af5f66a4 | ||
|
|
ad9395f74a | ||
|
|
c7c07c5fb2 | ||
|
|
5e15bafd26 | ||
|
|
43f1c37458 | ||
|
|
611493af37 | ||
|
|
23a3f97af1 | ||
|
|
15480c49e3 | ||
|
|
6ceabe794e | ||
|
|
758e185090 | ||
|
|
770075609f | ||
|
|
bef5f431d9 | ||
|
|
7a1df44319 | ||
|
|
bfac558b6f | ||
|
|
e040cd1a68 | ||
|
|
6c4351908c | ||
|
|
d69e42348f | ||
|
|
221993edd4 | ||
|
|
989a390798 | ||
|
|
8f2659e2ad | ||
|
|
a07f18ff9f | ||
|
|
443d8a187b | ||
|
|
eaf03e06d5 | ||
|
|
034c05c82e | ||
|
|
94fd4ffa2e | ||
|
|
c9bc1943fa | ||
|
|
68612afa09 | ||
|
|
25253b22cc | ||
|
|
c2090fc962 | ||
|
|
c811a2c2f4 | ||
|
|
3266c6a2d4 | ||
|
|
02c3414fc0 | ||
|
|
6afad65ecb | ||
|
|
f735dfa617 | ||
|
|
496b27eb0a | ||
|
|
aeeb255d35 | ||
|
|
e2c29bf4db | ||
|
|
aae7b6e1ae | ||
|
|
37b9d3f886 | ||
|
|
5f5a2d9c5a | ||
|
|
24fc73c4e0 | ||
|
|
b85c0ec352 | ||
|
|
4620826c83 | ||
|
|
404979d71a | ||
|
|
0a894c2b30 | ||
|
|
2bcfeb612f | ||
|
|
3facb2dcfa | ||
|
|
b408043d7e | ||
|
|
42ea9b7cb1 | ||
|
|
aa42bb3355 | ||
|
|
372ae83fde | ||
|
|
46f777a254 | ||
|
|
90f464c671 | ||
|
|
32aa2ab24e | ||
|
|
8f9a3d508e | ||
|
|
cec2713416 | ||
|
|
d8d32d71c9 | ||
|
|
f66638c360 | ||
|
|
14b204e201 | ||
|
|
8eb3c959dc | ||
|
|
ac6f45d290 | ||
|
|
168880fe7b | ||
|
|
e5ac1eb83f | ||
|
|
33a8c60b2c | ||
|
|
e1bd7b9d8f | ||
|
|
9582cbe5b8 | ||
|
|
a130dcd5ec | ||
|
|
51584d4f2a | ||
|
|
a3374b2d2f | ||
|
|
0cb13d47cc | ||
|
|
087c72e8ea | ||
|
|
2e8e620d94 | ||
|
|
59a66f90c7 | ||
|
|
83b2a98682 | ||
|
|
c670dc6d14 | ||
|
|
2bf87b0a53 | ||
|
|
7d9aff3913 | ||
|
|
cf44cbfdc9 | ||
|
|
a1eb5c77e9 | ||
|
|
1e64f241f9 | ||
|
|
57975000fe | ||
|
|
b6b7a59958 | ||
|
|
b74fc002f1 | ||
|
|
721e26019e | ||
|
|
9cb1729107 | ||
|
|
ea173fc189 | ||
|
|
886e846dc0 | ||
|
|
0fba64486a | ||
|
|
c71a9e5704 | ||
|
|
6c66b39221 | ||
|
|
07c8e86987 | ||
|
|
d6a975f6b2 | ||
|
|
d0db75899d | ||
|
|
05b7db9cd8 | ||
|
|
667f3dfbad | ||
|
|
bf7b430f55 | ||
|
|
00d2c3037a | ||
|
|
5c1d1c0f45 | ||
|
|
55b6ff6fbd | ||
|
|
d59d373edc | ||
|
|
9e2ae1271d | ||
|
|
0825981026 | ||
|
|
83728f3832 | ||
|
|
8b422cd8b1 | ||
|
|
7691b8effb | ||
|
|
c35cd9d0fe | ||
|
|
be2779818b | ||
|
|
fdf79ce300 | ||
|
|
dc87416df0 | ||
|
|
a26b0dbaab | ||
|
|
06837c7efa | ||
|
|
5516dc7d0c | ||
|
|
d976bbec08 | ||
|
|
d8105a565e | ||
|
|
7cb3e99740 | ||
|
|
5edd6a4ddf | ||
|
|
396159299c | ||
|
|
34a326130a | ||
|
|
e5eccb409e | ||
|
|
154e579cfc | ||
|
|
0c2c192013 | ||
|
|
95ad53153f | ||
|
|
43ee24a52e | ||
|
|
dffcb3d0fb | ||
|
|
ffe304268d | ||
|
|
3a4cf61318 | ||
|
|
2ec7449c37 | ||
|
|
c226560f6b | ||
|
|
08a06865ec | ||
|
|
26619521fb | ||
|
|
50b87ff953 | ||
|
|
66d65e66fd | ||
|
|
cb0b143cb3 | ||
|
|
171096e856 | ||
|
|
69c95bf983 | ||
|
|
e7d95dc787 | ||
|
|
c7c7d5d01d | ||
|
|
b2e08332e3 | ||
|
|
affb956da5 | ||
|
|
9e79d0e06f | ||
|
|
01547c4bd8 | ||
|
|
198ce9095a | ||
|
|
4c267ef0a6 | ||
|
|
b8c9bb4247 | ||
|
|
49231ae961 | ||
|
|
75f856ac37 | ||
|
|
680710df2f | ||
|
|
84effb1708 | ||
|
|
16629eaf99 | ||
|
|
550872d629 | ||
|
|
ebee6f3c3f | ||
|
|
26cf75cb44 | ||
|
|
67fea1b6bf | ||
|
|
c2d2d58ff1 | ||
|
|
6c21202065 | ||
|
|
608e189a53 | ||
|
|
ba3266e2ec | ||
|
|
cc230188ea | ||
|
|
09a8221d31 | ||
|
|
093fc90b92 | ||
|
|
219c579084 | ||
|
|
cc518c3d05 | ||
|
|
5e8b07bdea | ||
|
|
e9bbe44d19 | ||
|
|
e6c97308b9 | ||
|
|
3c9cc070dd | ||
|
|
306df682cc | ||
|
|
0c71604b80 | ||
|
|
3d13370968 | ||
|
|
d87d385e6f | ||
|
|
8dd7662696 | ||
|
|
95eb9626a4 | ||
|
|
ea6f4fd2ff | ||
|
|
e954c47abd | ||
|
|
9f85fb2843 | ||
|
|
a0666b9be8 | ||
|
|
90ee294139 | ||
|
|
aed907c728 | ||
|
|
067678bdf9 | ||
|
|
018524ec7e | ||
|
|
3a4218156c | ||
|
|
5594a511c9 | ||
|
|
d955043aea | ||
|
|
68e7ecec67 |
87
.github/workflows/docker.yml
vendored
Normal file
87
.github/workflows/docker.yml
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
name: docker
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'release/*'
|
||||
tags:
|
||||
- 'v*.*'
|
||||
|
||||
env:
|
||||
# Platforms to build the image for
|
||||
BUILD_PLATFORMS: linux/amd64
|
||||
DOCKERHUB_REPO: ${{ github.repository_owner }}/idf
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
# Disable the job in forks
|
||||
if: ${{ github.repository_owner == 'espressif' }}
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Depending on the branch/tag, set CLONE_BRANCH_OR_TAG variable (used in the Dockerfile
|
||||
# as a build arg) and TAG_NAME (used when tagging the image).
|
||||
#
|
||||
# The following 3 steps cover the alternatives (tag, release branch, master branch):
|
||||
- name: Set variables (tags)
|
||||
if: ${{ github.ref_type == 'tag' }}
|
||||
run: |
|
||||
echo "CLONE_BRANCH_OR_TAG=$GITHUB_REF_NAME" >> $GITHUB_ENV
|
||||
echo "TAG_NAME=$GITHUB_REF_NAME" >> $GITHUB_ENV
|
||||
- name: Set variables (release branches)
|
||||
if: ${{ github.ref_type == 'branch' && startsWith(github.ref_name, 'release/') }}
|
||||
run: |
|
||||
echo "CLONE_BRANCH_OR_TAG=$GITHUB_REF_NAME" >> $GITHUB_ENV
|
||||
echo "TAG_NAME=release-${GITHUB_REF_NAME##release/}" >> $GITHUB_ENV
|
||||
- name: Set variables (main branch)
|
||||
if: ${{ github.ref_type == 'branch' && github.ref_name == 'master' }}
|
||||
run: |
|
||||
echo "CLONE_BRANCH_OR_TAG=master" >> $GITHUB_ENV
|
||||
echo "TAG_NAME=latest" >> $GITHUB_ENV
|
||||
|
||||
# Display the variables set above, just in case.
|
||||
- name: Check variables
|
||||
run: |
|
||||
echo "CLONE_BRANCH_OR_TAG: $CLONE_BRANCH_OR_TAG"
|
||||
echo "CHECKOUT_REF: $CHECKOUT_REF"
|
||||
echo "TAG_NAME: $TAG_NAME"
|
||||
|
||||
# The following steps are the standard boilerplate from
|
||||
# https://github.com/marketplace/actions/build-and-push-docker-images
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Set up QEMU for multiarch builds
|
||||
uses: docker/setup-qemu-action@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: tools/docker
|
||||
push: true
|
||||
tags: ${{ env.DOCKERHUB_REPO }}:${{ env.TAG_NAME }}
|
||||
platforms: ${{ env.BUILD_PLATFORMS }}
|
||||
build-args: |
|
||||
IDF_CLONE_URL=${{ github.server_url }}/${{ github.repository }}.git
|
||||
IDF_CLONE_BRANCH_OR_TAG=${{ env.CLONE_BRANCH_OR_TAG }}
|
||||
|
||||
- name: Update Docker Hub repository description (master branch)
|
||||
if: ${{ github.ref_type == 'branch' && github.ref_name == 'master' }}
|
||||
uses: peter-evans/dockerhub-description@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
# Token based authentication is not supported here:
|
||||
# https://github.com/peter-evans/dockerhub-description/issues/10
|
||||
# https://github.com/docker/roadmap/issues/115#issuecomment-891694974
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
repository: ${{ env.DOCKERHUB_REPO }}
|
||||
readme-filepath: ./tools/docker/README.md
|
||||
@@ -9,7 +9,7 @@ entries:
|
||||
SEGGER_SYSVIEW_Config_FreeRTOS (noflash)
|
||||
SEGGER_SYSVIEW_FreeRTOS (noflash)
|
||||
|
||||
[mapping:driver]
|
||||
[mapping:app_trace_driver]
|
||||
archive: libdriver.a
|
||||
entries:
|
||||
if SYSVIEW_TS_SOURCE_TIMER_00 = y || SYSVIEW_TS_SOURCE_TIMER_01 = y
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "unity.h"
|
||||
|
||||
#include "bootloader_common.h"
|
||||
#include "../include_bootloader/bootloader_flash.h"
|
||||
#include "../include_bootloader/bootloader_flash_priv.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp_ota_ops.h"
|
||||
|
||||
@@ -309,6 +309,15 @@ menu "Bootloader config"
|
||||
in this area of memory, you can increase it. It must be a multiple of 4 bytes.
|
||||
This area (rtc_retain_mem_t) is reserved and has access from the bootloader and an application.
|
||||
|
||||
config BOOTLOADER_FLASH_XMC_SUPPORT
|
||||
bool "Enable the support for flash chips of XMC (READ HELP FIRST)"
|
||||
default y
|
||||
help
|
||||
Perform the startup flow recommended by XMC. Please consult XMC for the details of this flow.
|
||||
XMC chips will be forbidden to be used, when this option is disabled.
|
||||
|
||||
DON'T DISABLE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.
|
||||
|
||||
endmenu # Bootloader
|
||||
|
||||
|
||||
|
||||
61
components/bootloader_support/include/bootloader_flash.h
Normal file
61
components/bootloader_support/include/bootloader_flash.h
Normal file
@@ -0,0 +1,61 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_spi_flash.h> /* including in bootloader for error values */
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Read flash ID by sending 0x9F command
|
||||
* @return flash raw ID
|
||||
* mfg_id = (ID >> 16) & 0xFF;
|
||||
flash_id = ID & 0xffff;
|
||||
*/
|
||||
uint32_t bootloader_read_flash_id(void);
|
||||
|
||||
#if SOC_CACHE_SUPPORT_WRAP
|
||||
/**
|
||||
* @brief Set the burst mode setting command for specified wrap mode.
|
||||
*
|
||||
* @param mode The specified warp mode.
|
||||
* @return always ESP_OK
|
||||
*/
|
||||
esp_err_t bootloader_flash_wrap_set(spi_flash_wrap_mode_t mode);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Startup flow recommended by XMC. Call at startup before any erase/write operation.
|
||||
*
|
||||
* @return ESP_OK When startup successfully, otherwise ESP_FAIL (indiciating you should reboot before erase/write).
|
||||
*/
|
||||
esp_err_t bootloader_flash_xmc_startup(void);
|
||||
|
||||
/**
|
||||
* @brief Unlock Flash write protect.
|
||||
* Please do not call this function in SDK.
|
||||
*
|
||||
* @note This can be overridden because it's attribute weak.
|
||||
*/
|
||||
esp_err_t bootloader_flash_unlock(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -19,11 +19,28 @@
|
||||
#include <stdint.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_spi_flash.h> /* including in bootloader for error values */
|
||||
#include "sdkconfig.h"
|
||||
#include "bootloader_flash.h"
|
||||
|
||||
#define FLASH_SECTOR_SIZE 0x1000
|
||||
#define FLASH_BLOCK_SIZE 0x10000
|
||||
#define MMAP_ALIGNED_MASK 0x0000FFFF
|
||||
|
||||
/* SPI commands (actual on-wire commands not SPI controller bitmasks)
|
||||
Suitable for use with the bootloader_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 */
|
||||
#define CMD_OTPEN 0x3A /* Enable OTP mode, not all SPI flash uses this command */
|
||||
#define CMD_RDSFDP 0x5A /* Read the SFDP of the flash */
|
||||
#define CMD_WRAP 0x77 /* Set burst with wrap command */
|
||||
|
||||
|
||||
/* Provide a Flash API for bootloader_support code,
|
||||
that can be used from bootloader or app code.
|
||||
|
||||
@@ -136,4 +153,29 @@ static inline uint32_t bootloader_cache_pages_to_map(uint32_t size, uint32_t vad
|
||||
return (size + (vaddr - (vaddr & MMU_FLASH_MASK)) + MMU_BLOCK_SIZE - 1) / MMU_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Execute a user command on the flash
|
||||
*
|
||||
* @param command The command value to execute.
|
||||
* @param mosi_data MOSI data to send
|
||||
* @param mosi_len Length of MOSI data, in bits
|
||||
* @param miso_len Length of MISO data to receive, in bits
|
||||
* @return Received MISO data
|
||||
*/
|
||||
uint32_t bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len);
|
||||
|
||||
/**
|
||||
* @brief Read the SFDP of the flash
|
||||
*
|
||||
* @param sfdp_addr Address of the parameter to read
|
||||
* @param miso_byte_num Bytes to read
|
||||
* @return The read SFDP, little endian, 4 bytes at most
|
||||
*/
|
||||
uint32_t bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num);
|
||||
|
||||
/**
|
||||
* @brief Enable the flash write protect (WEL bit).
|
||||
*/
|
||||
void bootloader_enable_wp(void);
|
||||
|
||||
#endif
|
||||
@@ -13,6 +13,8 @@
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "esp32s2/rom/gpio.h"
|
||||
#endif
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
|
||||
@@ -13,13 +13,44 @@
|
||||
// limitations under the License.
|
||||
#include <stddef.h>
|
||||
|
||||
#include <bootloader_flash.h>
|
||||
#include <bootloader_flash_priv.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_flash_encrypt.h>
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/spi_flash.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
# include "soc/spi_struct.h"
|
||||
# include "soc/spi_reg.h"
|
||||
/* SPI flash controller */
|
||||
# define SPIFLASH SPI1
|
||||
#else
|
||||
# include "soc/spi_mem_struct.h"
|
||||
# include "soc/spi_mem_reg.h"
|
||||
/* SPI flash controller */
|
||||
# define SPIFLASH SPIMEM1
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/spi_flash.h" //For SPI_Encrypt_Write
|
||||
#include "esp32s2/rom/ets_sys.h"
|
||||
#endif
|
||||
|
||||
#define BYTESHIFT(VAR, IDX) (((VAR) >> ((IDX) * 8)) & 0xFF)
|
||||
#define ISSI_ID 0x9D
|
||||
#define MXIC_ID 0xC2
|
||||
#define GD_Q_ID_HIGH 0xC8
|
||||
#define GD_Q_ID_MID 0x40
|
||||
#define GD_Q_ID_LOW 0x16
|
||||
|
||||
#define ESP_BOOTLOADER_SPIFLASH_BP_MASK_ISSI (BIT7 | BIT5 | BIT4 | BIT3 | BIT2)
|
||||
#define ESP_BOOTLOADER_SPIFLASH_QE_GD_SR2 BIT1 // QE position when you write 8 bits(for SR2) at one time.
|
||||
#define ESP_BOOTLOADER_SPIFLASH_QE_SR1_2BYTE BIT9 // QE position when you write 16 bits at one time.
|
||||
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
/* Normal app version maps to esp_spi_flash.h operations...
|
||||
*/
|
||||
@@ -89,7 +120,7 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
|
||||
return spi_flash_erase_range(start_addr, size);
|
||||
}
|
||||
|
||||
#else
|
||||
#else //BOOTLOADER_BUILD
|
||||
/* Bootloader version, uses ROM functions only */
|
||||
#include "soc/dport_reg.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
@@ -318,7 +349,7 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
err = spi_to_esp_err(esp_rom_spiflash_unlock());
|
||||
err = bootloader_flash_unlock();
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
@@ -364,4 +395,332 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
|
||||
}
|
||||
return spi_to_esp_err(rc);
|
||||
}
|
||||
|
||||
#endif // BOOTLOADER_BUILD
|
||||
|
||||
FORCE_INLINE_ATTR bool is_issi_chip(const esp_rom_spiflash_chip_t* chip)
|
||||
{
|
||||
return BYTESHIFT(chip->device_id, 2) == ISSI_ID;
|
||||
}
|
||||
|
||||
// For GD25Q32, GD25Q64, GD25Q127C, GD25Q128, which use single command to read/write different SR.
|
||||
FORCE_INLINE_ATTR bool is_gd_q_chip(const esp_rom_spiflash_chip_t* chip)
|
||||
{
|
||||
return BYTESHIFT(chip->device_id, 2) == GD_Q_ID_HIGH && BYTESHIFT(chip->device_id, 1) == GD_Q_ID_MID && BYTESHIFT(chip->device_id, 0) >= GD_Q_ID_LOW;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR bool is_mxic_chip(const esp_rom_spiflash_chip_t* chip)
|
||||
{
|
||||
return BYTESHIFT(chip->device_id, 2) == MXIC_ID;
|
||||
}
|
||||
|
||||
esp_err_t IRAM_ATTR __attribute__((weak)) bootloader_flash_unlock(void)
|
||||
{
|
||||
// At the beginning status == new_status == status_sr2 == new_status_sr2 == 0.
|
||||
// If the register doesn't need to be updated, keep them the same (0), so that no command will be actually sent.
|
||||
uint16_t status = 0; // status for SR1 or SR1+SR2 if writing SR with 01H + 2Bytes.
|
||||
uint16_t new_status = 0;
|
||||
uint8_t status_sr2 = 0; // status_sr2 for SR2.
|
||||
uint8_t new_status_sr2 = 0;
|
||||
uint8_t sr1_bit_num = 0;
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
if (is_issi_chip(&g_rom_flashchip) || is_mxic_chip(&g_rom_flashchip)) {
|
||||
// Currently ISSI & MXIC share the same command and register layout, which is different from the default model.
|
||||
// If any code here needs to be modified, check both chips.
|
||||
status = bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8);
|
||||
|
||||
/* Clear all bits in the mask.
|
||||
(This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.)
|
||||
*/
|
||||
sr1_bit_num = 8;
|
||||
new_status = status & (~ESP_BOOTLOADER_SPIFLASH_BP_MASK_ISSI);
|
||||
} else if (is_gd_q_chip(&g_rom_flashchip)) {
|
||||
/* The GD chips behaviour is to clear all bits in SR1 and clear bits in SR2 except QE bit.
|
||||
Use 01H to write SR1 and 31H to write SR2.
|
||||
*/
|
||||
status = bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8);
|
||||
sr1_bit_num = 8;
|
||||
new_status = 0;
|
||||
|
||||
status_sr2 = bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8);
|
||||
new_status_sr2 = status_sr2 & ESP_BOOTLOADER_SPIFLASH_QE_GD_SR2;
|
||||
} else {
|
||||
/* For common behaviour, like XMC chips, Use 01H+2Bytes to write both SR1 and SR2*/
|
||||
status = bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8) | (bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8) << 8);
|
||||
|
||||
/* Clear all bits except QE, if it is set.
|
||||
(This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.)
|
||||
*/
|
||||
sr1_bit_num = 16;
|
||||
new_status = status & ESP_BOOTLOADER_SPIFLASH_QE_SR1_2BYTE;
|
||||
}
|
||||
|
||||
// When SR is written, set to true to indicate that WRDI need to be sent to ensure the protection is ON before return.
|
||||
bool status_written = false;
|
||||
// Skip if nothing needs to be changed. Meaningless writing to SR increases the risk during write and wastes time.
|
||||
if (status != new_status) {
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
bootloader_execute_flash_command(CMD_WREN, 0, 0, 0);
|
||||
bootloader_execute_flash_command(CMD_WRSR, new_status, sr1_bit_num, 0);
|
||||
status_written = true;
|
||||
}
|
||||
|
||||
if (status_sr2 != new_status_sr2) {
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
bootloader_execute_flash_command(CMD_WREN, 0, 0, 0);
|
||||
bootloader_execute_flash_command(CMD_WRSR2, new_status_sr2, 8, 0);
|
||||
status_written = true;
|
||||
}
|
||||
|
||||
if (status_written) {
|
||||
//Call esp_rom_spiflash_wait_idle to make sure previous WRSR is completed.
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* dummy_len_plus values defined in ROM for SPI flash configuration */
|
||||
extern uint8_t g_rom_spiflash_dummy_len_plus[];
|
||||
IRAM_ATTR static uint32_t bootloader_flash_execute_command_common(
|
||||
uint8_t command,
|
||||
uint32_t addr_len, uint32_t address,
|
||||
uint8_t dummy_len,
|
||||
uint8_t mosi_len, uint32_t mosi_data,
|
||||
uint8_t miso_len)
|
||||
{
|
||||
assert(mosi_len <= 32);
|
||||
assert(miso_len <= 32);
|
||||
uint32_t old_ctrl_reg = SPIFLASH.ctrl.val;
|
||||
uint32_t old_user_reg = SPIFLASH.user.val;
|
||||
uint32_t old_user1_reg = SPIFLASH.user1.val;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.ctrl.val = SPI_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
|
||||
#else
|
||||
SPIFLASH.ctrl.val = SPI_MEM_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
|
||||
#endif
|
||||
//command phase
|
||||
SPIFLASH.user.usr_command = 1;
|
||||
SPIFLASH.user2.usr_command_bitlen = 7;
|
||||
SPIFLASH.user2.usr_command_value = command;
|
||||
//addr phase
|
||||
SPIFLASH.user.usr_addr = addr_len > 0;
|
||||
SPIFLASH.user1.usr_addr_bitlen = addr_len - 1;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.addr = (addr_len > 0)? (address << (32-addr_len)) : 0;
|
||||
#else
|
||||
SPIFLASH.addr = address;
|
||||
#endif
|
||||
//dummy phase
|
||||
if (miso_len > 0) {
|
||||
uint32_t total_dummy = dummy_len + g_rom_spiflash_dummy_len_plus[1];
|
||||
SPIFLASH.user.usr_dummy = total_dummy > 0;
|
||||
SPIFLASH.user1.usr_dummy_cyclelen = total_dummy - 1;
|
||||
} else {
|
||||
SPIFLASH.user.usr_dummy = 0;
|
||||
SPIFLASH.user1.usr_dummy_cyclelen = 0;
|
||||
}
|
||||
//output data
|
||||
SPIFLASH.user.usr_mosi = mosi_len > 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0;
|
||||
#else
|
||||
SPIFLASH.mosi_dlen.usr_mosi_bit_len = mosi_len ? (mosi_len - 1) : 0;
|
||||
#endif
|
||||
SPIFLASH.data_buf[0] = mosi_data;
|
||||
//input data
|
||||
SPIFLASH.user.usr_miso = miso_len > 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0;
|
||||
#else
|
||||
SPIFLASH.miso_dlen.usr_miso_bit_len = miso_len ? (miso_len - 1) : 0;
|
||||
#endif
|
||||
|
||||
SPIFLASH.cmd.usr = 1;
|
||||
while (SPIFLASH.cmd.usr != 0) {
|
||||
}
|
||||
SPIFLASH.ctrl.val = old_ctrl_reg;
|
||||
SPIFLASH.user.val = old_user_reg;
|
||||
SPIFLASH.user1.val = old_user1_reg;
|
||||
|
||||
uint32_t ret = SPIFLASH.data_buf[0];
|
||||
if (miso_len < 32) {
|
||||
//set unused bits to 0
|
||||
ret &= ~(UINT32_MAX << miso_len);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t IRAM_ATTR bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len)
|
||||
{
|
||||
const uint8_t addr_len = 0;
|
||||
const uint8_t address = 0;
|
||||
const uint8_t dummy_len = 0;
|
||||
|
||||
return bootloader_flash_execute_command_common(command, addr_len, address,
|
||||
dummy_len, mosi_len, mosi_data, miso_len);
|
||||
}
|
||||
|
||||
// cmd(0x5A) + 24bit address + 8 cycles dummy
|
||||
uint32_t IRAM_ATTR bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num)
|
||||
{
|
||||
assert(miso_byte_num <= 4);
|
||||
const uint8_t command = CMD_RDSFDP;
|
||||
const uint8_t addr_len = 24;
|
||||
const uint8_t dummy_len = 8;
|
||||
const uint8_t mosi_len = 0;
|
||||
const uint32_t mosi_data = 0;
|
||||
const uint8_t miso_len = miso_byte_num * 8;
|
||||
|
||||
return bootloader_flash_execute_command_common(command, addr_len, sfdp_addr,
|
||||
dummy_len, mosi_len, mosi_data, miso_len);
|
||||
}
|
||||
|
||||
void bootloader_enable_wp(void)
|
||||
{
|
||||
bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */
|
||||
}
|
||||
|
||||
uint32_t IRAM_ATTR bootloader_read_flash_id(void)
|
||||
{
|
||||
uint32_t id = bootloader_execute_flash_command(CMD_RDID, 0, 0, 24);
|
||||
id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00);
|
||||
return id;
|
||||
}
|
||||
|
||||
#if SOC_CACHE_SUPPORT_WRAP
|
||||
esp_err_t bootloader_flash_wrap_set(spi_flash_wrap_mode_t mode)
|
||||
{
|
||||
uint32_t reg_bkp_ctrl = SPIFLASH.ctrl.val;
|
||||
uint32_t reg_bkp_usr = SPIFLASH.user.val;
|
||||
SPIFLASH.user.fwrite_dio = 0;
|
||||
SPIFLASH.user.fwrite_dual = 0;
|
||||
SPIFLASH.user.fwrite_qio = 1;
|
||||
SPIFLASH.user.fwrite_quad = 0;
|
||||
SPIFLASH.ctrl.fcmd_dual = 0;
|
||||
SPIFLASH.ctrl.fcmd_quad = 0;
|
||||
SPIFLASH.user.usr_dummy = 0;
|
||||
SPIFLASH.user.usr_addr = 1;
|
||||
SPIFLASH.user.usr_command = 1;
|
||||
SPIFLASH.user2.usr_command_bitlen = 7;
|
||||
SPIFLASH.user2.usr_command_value = CMD_WRAP;
|
||||
SPIFLASH.user1.usr_addr_bitlen = 23;
|
||||
SPIFLASH.addr = 0;
|
||||
SPIFLASH.user.usr_miso = 0;
|
||||
SPIFLASH.user.usr_mosi = 1;
|
||||
SPIFLASH.mosi_dlen.usr_mosi_bit_len = 7;
|
||||
SPIFLASH.data_buf[0] = (uint32_t) mode << 4;;
|
||||
SPIFLASH.cmd.usr = 1;
|
||||
while(SPIFLASH.cmd.usr != 0)
|
||||
{ }
|
||||
|
||||
SPIFLASH.ctrl.val = reg_bkp_ctrl;
|
||||
SPIFLASH.user.val = reg_bkp_usr;
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif //SOC_CACHE_SUPPORT_WRAP
|
||||
|
||||
/*******************************************************************************
|
||||
* XMC startup flow
|
||||
******************************************************************************/
|
||||
|
||||
#define XMC_SUPPORT CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT
|
||||
#define XMC_VENDOR_ID 0x20
|
||||
|
||||
#if BOOTLOADER_BUILD
|
||||
#define BOOTLOADER_FLASH_LOG(level, ...) ESP_LOG##level(TAG, ##__VA_ARGS__)
|
||||
#else
|
||||
static DRAM_ATTR char bootloader_flash_tag[] = "bootloader_flash";
|
||||
#define BOOTLOADER_FLASH_LOG(level, ...) ESP_DRAM_LOG##level(bootloader_flash_tag, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if XMC_SUPPORT
|
||||
//strictly check the model
|
||||
static IRAM_ATTR bool is_xmc_chip_strict(uint32_t rdid)
|
||||
{
|
||||
uint32_t vendor_id = BYTESHIFT(rdid, 2);
|
||||
uint32_t mfid = BYTESHIFT(rdid, 1);
|
||||
uint32_t cpid = BYTESHIFT(rdid, 0);
|
||||
|
||||
if (vendor_id != XMC_VENDOR_ID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool matched = false;
|
||||
if (mfid == 0x40) {
|
||||
if (cpid >= 0x13 && cpid <= 0x20) {
|
||||
matched = true;
|
||||
}
|
||||
} else if (mfid == 0x41) {
|
||||
if (cpid >= 0x17 && cpid <= 0x20) {
|
||||
matched = true;
|
||||
}
|
||||
} else if (mfid == 0x50) {
|
||||
if (cpid >= 0x15 && cpid <= 0x16) {
|
||||
matched = true;
|
||||
}
|
||||
}
|
||||
return matched;
|
||||
}
|
||||
|
||||
esp_err_t IRAM_ATTR bootloader_flash_xmc_startup(void)
|
||||
{
|
||||
// If the RDID value is a valid XMC one, may skip the flow
|
||||
const bool fast_check = true;
|
||||
if (fast_check && is_xmc_chip_strict(g_rom_flashchip.device_id)) {
|
||||
BOOTLOADER_FLASH_LOG(D, "XMC chip detected by RDID (%08X), skip.", g_rom_flashchip.device_id);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Check the Manufacturer ID in SFDP registers (JEDEC standard). If not XMC chip, no need to run the flow
|
||||
const int sfdp_mfid_addr = 0x10;
|
||||
uint8_t mf_id = (bootloader_flash_read_sfdp(sfdp_mfid_addr, 1) & 0xff);
|
||||
if (mf_id != XMC_VENDOR_ID) {
|
||||
BOOTLOADER_FLASH_LOG(D, "non-XMC chip detected by SFDP Read (%02X), skip.", mf_id);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
BOOTLOADER_FLASH_LOG(I, "XM25QHxxC startup flow");
|
||||
// Enter DPD
|
||||
bootloader_execute_flash_command(0xB9, 0, 0, 0);
|
||||
// Enter UDPD
|
||||
bootloader_execute_flash_command(0x79, 0, 0, 0);
|
||||
// Exit UDPD
|
||||
bootloader_execute_flash_command(0xFF, 0, 0, 0);
|
||||
// Delay tXUDPD
|
||||
ets_delay_us(2000);
|
||||
// Release Power-down
|
||||
bootloader_execute_flash_command(0xAB, 0, 0, 0);
|
||||
ets_delay_us(20);
|
||||
// Read flash ID and check again
|
||||
g_rom_flashchip.device_id = bootloader_read_flash_id();
|
||||
if (!is_xmc_chip_strict(g_rom_flashchip.device_id)) {
|
||||
BOOTLOADER_FLASH_LOG(E, "XMC flash startup fail");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#else
|
||||
//only compare the vendor id
|
||||
static IRAM_ATTR bool is_xmc_chip(uint32_t rdid)
|
||||
{
|
||||
uint32_t vendor_id = (rdid >> 16) & 0xFF;
|
||||
return (vendor_id == XMC_VENDOR_ID);
|
||||
}
|
||||
|
||||
esp_err_t IRAM_ATTR bootloader_flash_xmc_startup(void)
|
||||
{
|
||||
if (is_xmc_chip(g_rom_flashchip.device_id)) {
|
||||
BOOTLOADER_FLASH_LOG(E, "XMC chip detected (%08X) while support disabled.", g_rom_flashchip.device_id);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#endif //XMC_SUPPORT
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "bootloader_init.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "bootloader_random.h"
|
||||
#include "bootloader_clock.h"
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_random.h"
|
||||
#include "bootloader_config.h"
|
||||
#include "bootloader_common.h"
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "bootloader_common.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "bootloader_mem.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/dport_reg.h"
|
||||
@@ -259,7 +260,7 @@ static esp_err_t bootloader_init_spi_flash(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_rom_spiflash_unlock();
|
||||
bootloader_flash_unlock();
|
||||
|
||||
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
||||
bootloader_enable_qio_mode();
|
||||
@@ -267,6 +268,8 @@ static esp_err_t bootloader_init_spi_flash(void)
|
||||
|
||||
print_flash_info(&bootloader_image_hdr);
|
||||
update_flash_config(&bootloader_image_hdr);
|
||||
//ensure the flash is write-protected
|
||||
bootloader_enable_wp();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -305,11 +308,13 @@ static void bootloader_init_uart_console(void)
|
||||
const uint32_t tx_idx = tx_idx_list[uart_num];
|
||||
const uint32_t rx_idx = rx_idx_list[uart_num];
|
||||
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[uart_rx_gpio], PIN_FUNC_GPIO);
|
||||
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[uart_rx_gpio]);
|
||||
gpio_pad_pullup(uart_rx_gpio);
|
||||
|
||||
gpio_matrix_out(uart_tx_gpio, tx_idx, 0, 0);
|
||||
gpio_matrix_in(uart_rx_gpio, rx_idx, 0);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[uart_tx_gpio], PIN_FUNC_GPIO);
|
||||
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
|
||||
@@ -450,6 +455,11 @@ esp_err_t bootloader_init(void)
|
||||
bootloader_print_banner();
|
||||
// update flash ID
|
||||
bootloader_flash_update_id();
|
||||
// Check and run XMC startup flow
|
||||
if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!");
|
||||
goto err;
|
||||
}
|
||||
// read bootloader header
|
||||
if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
|
||||
goto err;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#include <strings.h>
|
||||
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_flash_partitions.h"
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_random.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_secure_boot.h"
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "bootloader_clock.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "bootloader_mem.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
|
||||
#include "esp32s2/rom/cache.h"
|
||||
#include "esp32s2/rom/ets_sys.h"
|
||||
@@ -205,7 +206,7 @@ static esp_err_t bootloader_init_spi_flash(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_rom_spiflash_unlock();
|
||||
bootloader_flash_unlock();
|
||||
|
||||
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
||||
bootloader_enable_qio_mode();
|
||||
@@ -213,6 +214,8 @@ static esp_err_t bootloader_init_spi_flash(void)
|
||||
|
||||
print_flash_info(&bootloader_image_hdr);
|
||||
update_flash_config(&bootloader_image_hdr);
|
||||
//ensure the flash is write-protected
|
||||
bootloader_enable_wp();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -251,11 +254,13 @@ static void bootloader_init_uart_console(void)
|
||||
const uint32_t tx_idx = tx_idx_list[uart_num];
|
||||
const uint32_t rx_idx = rx_idx_list[uart_num];
|
||||
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[uart_rx_gpio], PIN_FUNC_GPIO);
|
||||
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[uart_rx_gpio]);
|
||||
gpio_pad_pullup(uart_rx_gpio);
|
||||
|
||||
gpio_matrix_out(uart_tx_gpio, tx_idx, 0, 0);
|
||||
gpio_matrix_in(uart_rx_gpio, rx_idx, 0);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[uart_tx_gpio], PIN_FUNC_GPIO);
|
||||
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
|
||||
@@ -372,6 +377,11 @@ esp_err_t bootloader_init(void)
|
||||
bootloader_print_banner();
|
||||
// update flash ID
|
||||
bootloader_flash_update_id();
|
||||
// Check and run XMC startup flow
|
||||
if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!");
|
||||
goto err;
|
||||
}
|
||||
// read bootloader header
|
||||
if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
|
||||
goto err;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#include <strings.h>
|
||||
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_random.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "esp_image_format.h"
|
||||
@@ -303,8 +303,8 @@ static esp_err_t encrypt_bootloader(void)
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to encrypt bootloader in place: 0x%x", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "bootloader encrypted successfully");
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "esp_secure_boot.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_utility.h"
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_fault.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <esp_log.h>
|
||||
#include <esp_attr.h>
|
||||
#include <esp_spi_flash.h>
|
||||
#include <bootloader_flash.h>
|
||||
#include <bootloader_flash_priv.h>
|
||||
#include <bootloader_random.h>
|
||||
#include <bootloader_sha.h>
|
||||
#include "bootloader_util.h"
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <stdint.h>
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "flash_qio_mode.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
@@ -25,30 +26,10 @@
|
||||
#include "esp32s2/rom/efuse.h"
|
||||
#include "soc/spi_mem_struct.h"
|
||||
#endif
|
||||
#include "soc/spi_struct.h"
|
||||
#include "soc/spi_reg.h"
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/* SPI flash controller */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define SPIFLASH SPI1
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#define SPIFLASH SPIMEM1
|
||||
#endif
|
||||
|
||||
/* 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 */
|
||||
#define CMD_OTPEN 0x3A /* Enable OTP mode, not all SPI flash uses this command */
|
||||
|
||||
static const char *TAG = "qio_mode";
|
||||
|
||||
@@ -126,56 +107,6 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
|
||||
|
||||
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);
|
||||
|
||||
/* dummy_len_plus values defined in ROM for SPI flash configuration */
|
||||
extern uint8_t g_rom_spiflash_dummy_len_plus[];
|
||||
uint32_t bootloader_read_flash_id(void)
|
||||
{
|
||||
uint32_t id = execute_flash_command(CMD_RDID, 0, 0, 24);
|
||||
id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00);
|
||||
return id;
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#define FLASH_WRAP_CMD 0x77
|
||||
typedef enum {
|
||||
FLASH_WRAP_MODE_8B = 0,
|
||||
FLASH_WRAP_MODE_16B = 2,
|
||||
FLASH_WRAP_MODE_32B = 4,
|
||||
FLASH_WRAP_MODE_64B = 6,
|
||||
FLASH_WRAP_MODE_DISABLE = 1
|
||||
} spi_flash_wrap_mode_t;
|
||||
static esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode)
|
||||
{
|
||||
uint32_t reg_bkp_ctrl = SPIFLASH.ctrl.val;
|
||||
uint32_t reg_bkp_usr = SPIFLASH.user.val;
|
||||
SPIFLASH.user.fwrite_dio = 0;
|
||||
SPIFLASH.user.fwrite_dual = 0;
|
||||
SPIFLASH.user.fwrite_qio = 1;
|
||||
SPIFLASH.user.fwrite_quad = 0;
|
||||
SPIFLASH.ctrl.fcmd_dual = 0;
|
||||
SPIFLASH.ctrl.fcmd_quad = 0;
|
||||
SPIFLASH.user.usr_dummy = 0;
|
||||
SPIFLASH.user.usr_addr = 1;
|
||||
SPIFLASH.user.usr_command = 1;
|
||||
SPIFLASH.user2.usr_command_bitlen = 7;
|
||||
SPIFLASH.user2.usr_command_value = FLASH_WRAP_CMD;
|
||||
SPIFLASH.user1.usr_addr_bitlen = 23;
|
||||
SPIFLASH.addr = 0;
|
||||
SPIFLASH.user.usr_miso = 0;
|
||||
SPIFLASH.user.usr_mosi = 1;
|
||||
SPIFLASH.mosi_dlen.usr_mosi_bit_len = 7;
|
||||
SPIFLASH.data_buf[0] = (uint32_t) mode << 4;;
|
||||
SPIFLASH.cmd.usr = 1;
|
||||
while (SPIFLASH.cmd.usr != 0) {
|
||||
}
|
||||
|
||||
SPIFLASH.ctrl.val = reg_bkp_ctrl;
|
||||
SPIFLASH.user.val = reg_bkp_usr;
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
void bootloader_enable_qio_mode(void)
|
||||
{
|
||||
@@ -208,8 +139,8 @@ void bootloader_enable_qio_mode(void)
|
||||
enable_qio_mode(chip_data[i].read_status_fn,
|
||||
chip_data[i].write_status_fn,
|
||||
chip_data[i].status_qio_bit);
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
spi_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
|
||||
#if SOC_CACHE_SUPPORT_WRAP
|
||||
bootloader_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -226,7 +157,7 @@ static esp_err_t enable_qio_mode(read_status_fn_t 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);
|
||||
bootloader_execute_flash_command(CMD_WREN, 0, 0, 0);
|
||||
write_status_fn(status | (1 << status_qio_bit));
|
||||
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
@@ -264,95 +195,48 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
|
||||
|
||||
static unsigned read_status_8b_rdsr(void)
|
||||
{
|
||||
return execute_flash_command(CMD_RDSR, 0, 0, 8);
|
||||
return bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8);
|
||||
}
|
||||
|
||||
static unsigned read_status_8b_rdsr2(void)
|
||||
{
|
||||
return execute_flash_command(CMD_RDSR2, 0, 0, 8);
|
||||
return bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8);
|
||||
}
|
||||
|
||||
static unsigned read_status_16b_rdsr_rdsr2(void)
|
||||
{
|
||||
return execute_flash_command(CMD_RDSR, 0, 0, 8) | (execute_flash_command(CMD_RDSR2, 0, 0, 8) << 8);
|
||||
return bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8) | (bootloader_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);
|
||||
bootloader_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);
|
||||
bootloader_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);
|
||||
bootloader_execute_flash_command(CMD_WRSR, new_status, 16, 0);
|
||||
}
|
||||
|
||||
static unsigned read_status_8b_xmc25qu64a(void)
|
||||
{
|
||||
execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */
|
||||
bootloader_execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
uint32_t read_status = execute_flash_command(CMD_RDSR, 0, 0, 8);
|
||||
execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */
|
||||
uint32_t read_status = bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8);
|
||||
bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */
|
||||
return read_status;
|
||||
}
|
||||
|
||||
static void write_status_8b_xmc25qu64a(unsigned new_status)
|
||||
{
|
||||
execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */
|
||||
bootloader_execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
execute_flash_command(CMD_WRSR, new_status, 8, 0);
|
||||
bootloader_execute_flash_command(CMD_WRSR, new_status, 8, 0);
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */
|
||||
}
|
||||
|
||||
static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len)
|
||||
{
|
||||
uint32_t old_ctrl_reg = SPIFLASH.ctrl.val;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.ctrl.val = SPI_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
SPIFLASH.ctrl.val = SPI_MEM_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
|
||||
#endif
|
||||
SPIFLASH.user.usr_dummy = 0;
|
||||
SPIFLASH.user.usr_addr = 0;
|
||||
SPIFLASH.user.usr_command = 1;
|
||||
SPIFLASH.user2.usr_command_bitlen = 7;
|
||||
|
||||
SPIFLASH.user2.usr_command_value = command;
|
||||
SPIFLASH.user.usr_miso = miso_len > 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
SPIFLASH.miso_dlen.usr_miso_bit_len = miso_len ? (miso_len - 1) : 0;
|
||||
#endif
|
||||
SPIFLASH.user.usr_mosi = mosi_len > 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
SPIFLASH.mosi_dlen.usr_mosi_bit_len = mosi_len ? (mosi_len - 1) : 0;
|
||||
#endif
|
||||
SPIFLASH.data_buf[0] = mosi_data;
|
||||
|
||||
if (g_rom_spiflash_dummy_len_plus[1]) {
|
||||
/* When flash pins are mapped via GPIO matrix, need a dummy cycle before reading via MISO */
|
||||
if (miso_len > 0) {
|
||||
SPIFLASH.user.usr_dummy = 1;
|
||||
SPIFLASH.user1.usr_dummy_cyclelen = g_rom_spiflash_dummy_len_plus[1] - 1;
|
||||
} else {
|
||||
SPIFLASH.user.usr_dummy = 0;
|
||||
SPIFLASH.user1.usr_dummy_cyclelen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
SPIFLASH.cmd.usr = 1;
|
||||
while (SPIFLASH.cmd.usr != 0) {
|
||||
}
|
||||
|
||||
SPIFLASH.ctrl.val = old_ctrl_reg;
|
||||
return SPIFLASH.data_buf[0];
|
||||
bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "esp_log.h"
|
||||
@@ -325,7 +325,7 @@ esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signa
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free(sig_be);
|
||||
free(buf);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
@@ -365,7 +365,7 @@ menu "Bluetooth"
|
||||
int "Maximum number of devices in scan duplicate filter"
|
||||
depends on BTDM_BLE_SCAN_DUPL
|
||||
range 10 1000
|
||||
default 200
|
||||
default 100
|
||||
help
|
||||
Maximum number of devices which can be recorded in scan duplicate filter.
|
||||
When the maximum amount of device in the filter is reached, the cache will be refreshed.
|
||||
@@ -381,7 +381,7 @@ menu "Bluetooth"
|
||||
int "Maximum number of Mesh adv packets in scan duplicate filter"
|
||||
depends on BTDM_BLE_MESH_SCAN_DUPL_EN
|
||||
range 10 1000
|
||||
default 200
|
||||
default 100
|
||||
help
|
||||
Maximum number of adv packets which can be recorded in duplicate scan cache for BLE Mesh.
|
||||
When the maximum amount of device in the filter is reached, the cache will be refreshed.
|
||||
|
||||
@@ -42,6 +42,12 @@
|
||||
#define BTC_DYNAMIC_MEMORY FALSE
|
||||
#endif
|
||||
|
||||
#if UC_BT_BLUEDROID_MEM_DEBUG
|
||||
#define HEAP_MEMORY_DEBUG TRUE
|
||||
#else
|
||||
#define HEAP_MEMORY_DEBUG FALSE
|
||||
#endif
|
||||
|
||||
#ifndef BT_BLE_DYNAMIC_ENV_MEMORY
|
||||
#define BT_BLE_DYNAMIC_ENV_MEMORY FALSE
|
||||
#endif
|
||||
|
||||
@@ -80,4 +80,11 @@
|
||||
#define UC_BT_LOG_OSI_TRACE_LEVEL UC_TRACE_LEVEL_WARNING
|
||||
#endif
|
||||
|
||||
//MEMORY DEBUG
|
||||
#ifdef CONFIG_BT_BLUEDROID_MEM_DEBUG
|
||||
#define UC_BT_BLUEDROID_MEM_DEBUG TRUE
|
||||
#else
|
||||
#define UC_BT_BLUEDROID_MEM_DEBUG FALSE
|
||||
#endif
|
||||
|
||||
#endif /* __BT_USER_CONFIG_H__ */
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_pm.h"
|
||||
#include "esp_timer.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
@@ -93,11 +94,6 @@ do{\
|
||||
#define OSI_VERSION 0x00010003
|
||||
#define OSI_MAGIC_VALUE 0xFADEBEAD
|
||||
|
||||
/* SPIRAM Configuration */
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
#define BTDM_MAX_QUEUE_NUM (5)
|
||||
#endif
|
||||
|
||||
/* Types definition
|
||||
************************************************************************
|
||||
*/
|
||||
@@ -115,14 +111,10 @@ typedef struct {
|
||||
intptr_t end;
|
||||
} btdm_dram_available_region_t;
|
||||
|
||||
/* PSRAM configuration */
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
typedef struct {
|
||||
QueueHandle_t handle;
|
||||
void *handle;
|
||||
void *storage;
|
||||
void *buffer;
|
||||
} btdm_queue_item_t;
|
||||
#endif
|
||||
|
||||
/* OSI function */
|
||||
struct osi_funcs_t {
|
||||
@@ -268,10 +260,6 @@ extern uint32_t _btdm_data_end;
|
||||
/* Local Function Declare
|
||||
*********************************************************************
|
||||
*/
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
static bool btdm_queue_generic_register(const btdm_queue_item_t *queue);
|
||||
static bool btdm_queue_generic_deregister(btdm_queue_item_t *queue);
|
||||
#endif /* CONFIG_SPIRAM_USE_MALLOC */
|
||||
static void IRAM_ATTR interrupt_disable(void);
|
||||
static void IRAM_ATTR interrupt_restore(void);
|
||||
static void IRAM_ATTR task_yield(void);
|
||||
@@ -414,11 +402,6 @@ SOC_RESERVE_MEMORY_REGION(SOC_MEM_BT_DATA_START, SOC_MEM_BT_DATA_END,
|
||||
|
||||
static DRAM_ATTR struct osi_funcs_t *osi_funcs_p;
|
||||
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
static DRAM_ATTR btdm_queue_item_t btdm_queue_table[BTDM_MAX_QUEUE_NUM];
|
||||
static DRAM_ATTR SemaphoreHandle_t btdm_queue_table_mux = NULL;
|
||||
#endif /* #if CONFIG_SPIRAM_USE_MALLOC */
|
||||
|
||||
/* Static variable declare */
|
||||
// timestamp when PHY/RF was switched on
|
||||
static DRAM_ATTR int64_t s_time_phy_rf_just_enabled = 0;
|
||||
@@ -458,52 +441,6 @@ static inline void btdm_check_and_init_bb(void)
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
static bool btdm_queue_generic_register(const btdm_queue_item_t *queue)
|
||||
{
|
||||
if (!btdm_queue_table_mux || !queue) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
btdm_queue_item_t *item;
|
||||
xSemaphoreTake(btdm_queue_table_mux, portMAX_DELAY);
|
||||
for (int i = 0; i < BTDM_MAX_QUEUE_NUM; ++i) {
|
||||
item = &btdm_queue_table[i];
|
||||
if (item->handle == NULL) {
|
||||
memcpy(item, queue, sizeof(btdm_queue_item_t));
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
xSemaphoreGive(btdm_queue_table_mux);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool btdm_queue_generic_deregister(btdm_queue_item_t *queue)
|
||||
{
|
||||
if (!btdm_queue_table_mux || !queue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
btdm_queue_item_t *item;
|
||||
xSemaphoreTake(btdm_queue_table_mux, portMAX_DELAY);
|
||||
for (int i = 0; i < BTDM_MAX_QUEUE_NUM; ++i) {
|
||||
item = &btdm_queue_table[i];
|
||||
if (item->handle == queue->handle) {
|
||||
memcpy(queue, item, sizeof(btdm_queue_item_t));
|
||||
memset(item, 0, sizeof(btdm_queue_item_t));
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
xSemaphoreGive(btdm_queue_table_mux);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SPIRAM_USE_MALLOC */
|
||||
|
||||
static void IRAM_ATTR interrupt_disable(void)
|
||||
{
|
||||
if (xPortInIsrContext()) {
|
||||
@@ -534,148 +471,74 @@ static void IRAM_ATTR task_yield_from_isr(void)
|
||||
|
||||
static void *semphr_create_wrapper(uint32_t max, uint32_t init)
|
||||
{
|
||||
btdm_queue_item_t *semphr = heap_caps_calloc(1, sizeof(btdm_queue_item_t), MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
|
||||
assert(semphr);
|
||||
|
||||
#if !CONFIG_SPIRAM_USE_MALLOC
|
||||
return (void *)xSemaphoreCreateCounting(max, init);
|
||||
semphr->handle = (void *)xSemaphoreCreateCounting(max, init);
|
||||
#else
|
||||
StaticQueue_t *queue_buffer = NULL;
|
||||
QueueHandle_t handle = NULL;
|
||||
|
||||
queue_buffer = heap_caps_malloc(sizeof(StaticQueue_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||
if (!queue_buffer) {
|
||||
goto error;
|
||||
}
|
||||
semphr->storage = heap_caps_malloc(sizeof(StaticQueue_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||
assert(semphr->storage);
|
||||
|
||||
handle = xSemaphoreCreateCountingStatic(max, init, queue_buffer);
|
||||
if (!handle) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
btdm_queue_item_t item = {
|
||||
.handle = handle,
|
||||
.storage = NULL,
|
||||
.buffer = queue_buffer,
|
||||
};
|
||||
|
||||
if (!btdm_queue_generic_register(&item)) {
|
||||
goto error;
|
||||
}
|
||||
return handle;
|
||||
|
||||
error:
|
||||
if (handle) {
|
||||
vSemaphoreDelete(handle);
|
||||
}
|
||||
if (queue_buffer) {
|
||||
free(queue_buffer);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
semphr->handle = (void *)xSemaphoreCreateCountingStatic(max, init, semphr->storage);
|
||||
#endif
|
||||
assert(semphr->handle);
|
||||
return semphr;
|
||||
}
|
||||
|
||||
static void semphr_delete_wrapper(void *semphr)
|
||||
{
|
||||
#if !CONFIG_SPIRAM_USE_MALLOC
|
||||
vSemaphoreDelete(semphr);
|
||||
#else
|
||||
btdm_queue_item_t item = {
|
||||
.handle = semphr,
|
||||
.storage = NULL,
|
||||
.buffer = NULL,
|
||||
};
|
||||
|
||||
if (btdm_queue_generic_deregister(&item)) {
|
||||
vSemaphoreDelete(item.handle);
|
||||
free(item.buffer);
|
||||
if (semphr == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
btdm_queue_item_t *semphr_item = (btdm_queue_item_t *)semphr;
|
||||
|
||||
if (semphr_item->handle) {
|
||||
vSemaphoreDelete(semphr_item->handle);
|
||||
}
|
||||
#ifdef CONFIG_SPIRAM_USE_MALLOC
|
||||
if (semphr_item->storage) {
|
||||
free(semphr_item->storage);
|
||||
}
|
||||
#endif
|
||||
|
||||
free(semphr);
|
||||
}
|
||||
|
||||
static int32_t IRAM_ATTR semphr_take_from_isr_wrapper(void *semphr, void *hptw)
|
||||
{
|
||||
return (int32_t)xSemaphoreTakeFromISR(semphr, hptw);
|
||||
return (int32_t)xSemaphoreTakeFromISR(((btdm_queue_item_t *)semphr)->handle, hptw);
|
||||
}
|
||||
|
||||
static int32_t IRAM_ATTR semphr_give_from_isr_wrapper(void *semphr, void *hptw)
|
||||
{
|
||||
return (int32_t)xSemaphoreGiveFromISR(semphr, hptw);
|
||||
return (int32_t)xSemaphoreGiveFromISR(((btdm_queue_item_t *)semphr)->handle, hptw);
|
||||
}
|
||||
|
||||
static int32_t semphr_take_wrapper(void *semphr, uint32_t block_time_ms)
|
||||
{
|
||||
if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) {
|
||||
return (int32_t)xSemaphoreTake(semphr, portMAX_DELAY);
|
||||
return (int32_t)xSemaphoreTake(((btdm_queue_item_t *)semphr)->handle, portMAX_DELAY);
|
||||
} else {
|
||||
return (int32_t)xSemaphoreTake(semphr, block_time_ms / portTICK_PERIOD_MS);
|
||||
return (int32_t)xSemaphoreTake(((btdm_queue_item_t *)semphr)->handle, block_time_ms / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t semphr_give_wrapper(void *semphr)
|
||||
{
|
||||
return (int32_t)xSemaphoreGive(semphr);
|
||||
return (int32_t)xSemaphoreGive(((btdm_queue_item_t *)semphr)->handle);
|
||||
}
|
||||
|
||||
static void *mutex_create_wrapper(void)
|
||||
{
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
StaticQueue_t *queue_buffer = NULL;
|
||||
QueueHandle_t handle = NULL;
|
||||
|
||||
queue_buffer = heap_caps_malloc(sizeof(StaticQueue_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||
if (!queue_buffer) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
handle = xSemaphoreCreateMutexStatic(queue_buffer);
|
||||
if (!handle) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
btdm_queue_item_t item = {
|
||||
.handle = handle,
|
||||
.storage = NULL,
|
||||
.buffer = queue_buffer,
|
||||
};
|
||||
|
||||
if (!btdm_queue_generic_register(&item)) {
|
||||
goto error;
|
||||
}
|
||||
return handle;
|
||||
|
||||
error:
|
||||
if (handle) {
|
||||
vSemaphoreDelete(handle);
|
||||
}
|
||||
if (queue_buffer) {
|
||||
free(queue_buffer);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
#else
|
||||
return (void *)xSemaphoreCreateMutex();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void mutex_delete_wrapper(void *mutex)
|
||||
{
|
||||
#if !CONFIG_SPIRAM_USE_MALLOC
|
||||
vSemaphoreDelete(mutex);
|
||||
#else
|
||||
btdm_queue_item_t item = {
|
||||
.handle = mutex,
|
||||
.storage = NULL,
|
||||
.buffer = NULL,
|
||||
};
|
||||
|
||||
if (btdm_queue_generic_deregister(&item)) {
|
||||
vSemaphoreDelete(item.handle);
|
||||
free(item.buffer);
|
||||
}
|
||||
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int32_t mutex_lock_wrapper(void *mutex)
|
||||
@@ -690,102 +553,71 @@ static int32_t mutex_unlock_wrapper(void *mutex)
|
||||
|
||||
static void *queue_create_wrapper(uint32_t queue_len, uint32_t item_size)
|
||||
{
|
||||
btdm_queue_item_t *queue = NULL;
|
||||
|
||||
queue = (btdm_queue_item_t*)heap_caps_malloc(sizeof(btdm_queue_item_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||
assert(queue);
|
||||
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
StaticQueue_t *queue_buffer = NULL;
|
||||
uint8_t *queue_storage = NULL;
|
||||
QueueHandle_t handle = NULL;
|
||||
|
||||
queue_buffer = heap_caps_malloc(sizeof(StaticQueue_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||
if (!queue_buffer) {
|
||||
goto error;
|
||||
}
|
||||
queue->storage = heap_caps_calloc(1, sizeof(StaticQueue_t) + (queue_len*item_size), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||
assert(queue->storage);
|
||||
|
||||
queue_storage = heap_caps_malloc((queue_len*item_size), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||
if (!queue_storage ) {
|
||||
goto error;
|
||||
}
|
||||
queue->handle = xQueueCreateStatic( queue_len, item_size, ((uint8_t*)(queue->storage)) + sizeof(StaticQueue_t), (StaticQueue_t*)(queue->storage));
|
||||
assert(queue->handle);
|
||||
|
||||
handle = xQueueCreateStatic(queue_len, item_size, queue_storage, queue_buffer);
|
||||
if (!handle) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
btdm_queue_item_t item = {
|
||||
.handle = handle,
|
||||
.storage = queue_storage,
|
||||
.buffer = queue_buffer,
|
||||
};
|
||||
|
||||
if (!btdm_queue_generic_register(&item)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return handle;
|
||||
|
||||
error:
|
||||
if (handle) {
|
||||
vQueueDelete(handle);
|
||||
}
|
||||
if (queue_storage) {
|
||||
free(queue_storage);
|
||||
}
|
||||
if (queue_buffer) {
|
||||
free(queue_buffer);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
#else
|
||||
return (void *)xQueueCreate(queue_len, item_size);
|
||||
queue->handle = xQueueCreate( queue_len, item_size);
|
||||
assert(queue->handle);
|
||||
#endif
|
||||
|
||||
return queue;
|
||||
}
|
||||
|
||||
static void queue_delete_wrapper(void *queue)
|
||||
{
|
||||
#if !CONFIG_SPIRAM_USE_MALLOC
|
||||
vQueueDelete(queue);
|
||||
#else
|
||||
btdm_queue_item_t item = {
|
||||
.handle = queue,
|
||||
.storage = NULL,
|
||||
.buffer = NULL,
|
||||
};
|
||||
btdm_queue_item_t *queue_item = (btdm_queue_item_t *)queue;
|
||||
if (queue_item) {
|
||||
if(queue_item->handle){
|
||||
vQueueDelete(queue_item->handle);
|
||||
}
|
||||
|
||||
if (btdm_queue_generic_deregister(&item)) {
|
||||
vQueueDelete(item.handle);
|
||||
free(item.storage);
|
||||
free(item.buffer);
|
||||
}
|
||||
|
||||
return;
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
if (queue_item->storage) {
|
||||
free(queue_item->storage);
|
||||
}
|
||||
#endif
|
||||
|
||||
free(queue_item);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t queue_send_wrapper(void *queue, void *item, uint32_t block_time_ms)
|
||||
{
|
||||
if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) {
|
||||
return (int32_t)xQueueSend(queue, item, portMAX_DELAY);
|
||||
return (int32_t)xQueueSend(((btdm_queue_item_t*)queue)->handle, item, portMAX_DELAY);
|
||||
} else {
|
||||
return (int32_t)xQueueSend(queue, item, block_time_ms / portTICK_PERIOD_MS);
|
||||
return (int32_t)xQueueSend(((btdm_queue_item_t*)queue)->handle, item, block_time_ms / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t IRAM_ATTR queue_send_from_isr_wrapper(void *queue, void *item, void *hptw)
|
||||
{
|
||||
return (int32_t)xQueueSendFromISR(queue, item, hptw);
|
||||
return (int32_t)xQueueSendFromISR(((btdm_queue_item_t*)queue)->handle, item, hptw);
|
||||
}
|
||||
|
||||
static int32_t queue_recv_wrapper(void *queue, void *item, uint32_t block_time_ms)
|
||||
{
|
||||
if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) {
|
||||
return (int32_t)xQueueReceive(queue, item, portMAX_DELAY);
|
||||
return (int32_t)xQueueReceive(((btdm_queue_item_t*)queue)->handle, item, portMAX_DELAY);
|
||||
} else {
|
||||
return (int32_t)xQueueReceive(queue, item, block_time_ms / portTICK_PERIOD_MS);
|
||||
return (int32_t)xQueueReceive(((btdm_queue_item_t*)queue)->handle, item, block_time_ms / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t IRAM_ATTR queue_recv_from_isr_wrapper(void *queue, void *item, void *hptw)
|
||||
{
|
||||
return (int32_t)xQueueReceiveFromISR(queue, item, hptw);
|
||||
return (int32_t)xQueueReceiveFromISR(((btdm_queue_item_t*)queue)->handle, item, hptw);
|
||||
}
|
||||
|
||||
static int32_t task_create_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id)
|
||||
@@ -1377,14 +1209,6 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
||||
|
||||
ESP_LOGI(BTDM_LOG_TAG, "BT controller compile version [%s]", btdm_controller_get_compile_version());
|
||||
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
btdm_queue_table_mux = xSemaphoreCreateMutex();
|
||||
if (btdm_queue_table_mux == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
memset(btdm_queue_table, 0, sizeof(btdm_queue_item_t) * BTDM_MAX_QUEUE_NUM);
|
||||
#endif
|
||||
|
||||
s_wakeup_req_sem = semphr_create_wrapper(1, 0);
|
||||
if (s_wakeup_req_sem == NULL) {
|
||||
err = ESP_ERR_NO_MEM;
|
||||
@@ -1534,12 +1358,6 @@ esp_err_t esp_bt_controller_deinit(void)
|
||||
semphr_delete_wrapper(s_wakeup_req_sem);
|
||||
s_wakeup_req_sem = NULL;
|
||||
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
vSemaphoreDelete(btdm_queue_table_mux);
|
||||
btdm_queue_table_mux = NULL;
|
||||
memset(btdm_queue_table, 0, sizeof(btdm_queue_item_t) * BTDM_MAX_QUEUE_NUM);
|
||||
#endif
|
||||
|
||||
free(osi_funcs_p);
|
||||
osi_funcs_p = NULL;
|
||||
|
||||
|
||||
Submodule components/bt/controller/lib updated: 26afd7bb31...211206db3c
@@ -1087,6 +1087,13 @@ if BLE_MESH
|
||||
lets the state to be changed at any time.
|
||||
If IV Update test mode is going to be used, this option should be enabled.
|
||||
|
||||
config BLE_MESH_DISCARD_OLD_SEQ_AUTH
|
||||
bool
|
||||
default y
|
||||
help
|
||||
This option is used to decide whether discarding the old SeqAuth when
|
||||
receiving a segmented message.
|
||||
|
||||
menu "BLE Mesh specific test option"
|
||||
|
||||
config BLE_MESH_SELF_TEST
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
|
||||
#define START_PAYLOAD_MAX 20
|
||||
#define CONT_PAYLOAD_MAX 23
|
||||
#define START_LAST_SEG_MAX 2
|
||||
|
||||
#define START_LAST_SEG(gpc) (gpc >> 2)
|
||||
#define CONT_SEG_INDEX(gpc) (gpc >> 2)
|
||||
@@ -1563,6 +1564,12 @@ static void gen_prov_start(struct prov_rx *rx, struct net_buf_simple *buf)
|
||||
return;
|
||||
}
|
||||
|
||||
if (START_LAST_SEG(rx->gpc) > START_LAST_SEG_MAX) {
|
||||
BT_ERR("Invalid SegN 0x%02x", START_LAST_SEG(rx->gpc));
|
||||
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (link.rx.buf->len > link.rx.buf->size) {
|
||||
BT_ERR("Too large provisioning PDU (%u bytes)",
|
||||
link.rx.buf->len);
|
||||
|
||||
@@ -82,6 +82,7 @@ _Static_assert(BLE_MESH_MAX_CONN >= CONFIG_BLE_MESH_PBG_SAME_TIME,
|
||||
|
||||
#define START_PAYLOAD_MAX 20
|
||||
#define CONT_PAYLOAD_MAX 23
|
||||
#define START_LAST_SEG_MAX 2
|
||||
|
||||
#define START_LAST_SEG(gpc) (gpc >> 2)
|
||||
#define CONT_SEG_INDEX(gpc) (gpc >> 2)
|
||||
@@ -2988,6 +2989,12 @@ static void gen_prov_start(const uint8_t idx, struct prov_rx *rx, struct net_buf
|
||||
return;
|
||||
}
|
||||
|
||||
if (START_LAST_SEG(rx->gpc) > START_LAST_SEG_MAX) {
|
||||
BT_ERR("Invalid SegN 0x%02x", START_LAST_SEG(rx->gpc));
|
||||
close_link(idx, CLOSE_REASON_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (link[idx].rx.buf->len > link[idx].rx.buf->size) {
|
||||
BT_ERR("Too large provisioning PDU (%u bytes)",
|
||||
link[idx].rx.buf->len);
|
||||
|
||||
@@ -92,13 +92,7 @@ static struct bt_mesh_proxy_client {
|
||||
#endif
|
||||
struct k_delayed_work sar_timer;
|
||||
struct net_buf_simple buf;
|
||||
} clients[BLE_MESH_MAX_CONN] = {
|
||||
[0 ... (BLE_MESH_MAX_CONN - 1)] = {
|
||||
#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER)
|
||||
.send_beacons = _K_WORK_INITIALIZER(proxy_send_beacons),
|
||||
#endif
|
||||
},
|
||||
};
|
||||
} clients[BLE_MESH_MAX_CONN];
|
||||
|
||||
static uint8_t client_buf_data[CLIENT_BUF_SIZE * BLE_MESH_MAX_CONN];
|
||||
|
||||
@@ -1433,7 +1427,9 @@ int bt_mesh_proxy_server_init(void)
|
||||
|
||||
client->buf.size = CLIENT_BUF_SIZE;
|
||||
client->buf.__buf = client_buf_data + (i * CLIENT_BUF_SIZE);
|
||||
|
||||
#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER)
|
||||
k_work_init(&client->send_beacons, proxy_send_beacons);
|
||||
#endif
|
||||
k_delayed_work_init(&client->sar_timer, proxy_sar_timeout);
|
||||
}
|
||||
|
||||
|
||||
@@ -1396,13 +1396,14 @@ static struct seg_rx *seg_rx_find(struct bt_mesh_net_rx *net_rx,
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Return newer RX context in addition to an exact match, so
|
||||
* the calling function can properly discard an old SeqAuth.
|
||||
* Note: in Zephyr v1.14.0, ">=" is used here which does not
|
||||
* seem to be a right operation, hence we still use the original
|
||||
* "==" here.
|
||||
/* When ">=" is used, return newer RX context in addition to an exact match,
|
||||
* so the calling function can properly discard an old SeqAuth.
|
||||
*/
|
||||
#if CONFIG_BLE_MESH_DISCARD_OLD_SEQ_AUTH
|
||||
if (rx->seq_auth >= *seq_auth) {
|
||||
#else
|
||||
if (rx->seq_auth == *seq_auth) {
|
||||
#endif
|
||||
return rx;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "btc_gatt_util.h"
|
||||
#include "stack/l2cdefs.h"
|
||||
#include "stack/l2c_api.h"
|
||||
#include "gatt_int.h"
|
||||
|
||||
|
||||
#if (GATTC_INCLUDED == TRUE)
|
||||
@@ -327,6 +328,12 @@ esp_err_t esp_ble_gattc_read_char (esp_gatt_if_t gattc_if,
|
||||
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
|
||||
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
|
||||
LOG_WARN("%s, The connection not created.", __func__);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) {
|
||||
LOG_DEBUG("%s, the l2cap chanel is congest.", __func__);
|
||||
return ESP_FAIL;
|
||||
@@ -358,6 +365,12 @@ esp_err_t esp_ble_gattc_read_by_type (esp_gatt_if_t gattc_if,
|
||||
return ESP_GATT_ILLEGAL_PARAMETER;
|
||||
}
|
||||
|
||||
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
|
||||
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
|
||||
LOG_WARN("%s, The connection not created.", __func__);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) {
|
||||
LOG_DEBUG("%s, the l2cap chanel is congest.", __func__);
|
||||
return ESP_FAIL;
|
||||
@@ -384,6 +397,12 @@ esp_err_t esp_ble_gattc_read_multiple(esp_gatt_if_t gattc_if,
|
||||
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
|
||||
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
|
||||
LOG_WARN("%s, The connection not created.", __func__);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) {
|
||||
LOG_DEBUG("%s, the l2cap chanel is congest.", __func__);
|
||||
return ESP_FAIL;
|
||||
@@ -415,6 +434,12 @@ esp_err_t esp_ble_gattc_read_char_descr (esp_gatt_if_t gattc_if,
|
||||
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
|
||||
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
|
||||
LOG_WARN("%s, The connection not created.", __func__);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) {
|
||||
LOG_DEBUG("%s, the l2cap chanel is congest.", __func__);
|
||||
return ESP_FAIL;
|
||||
@@ -442,6 +467,12 @@ esp_err_t esp_ble_gattc_write_char(esp_gatt_if_t gattc_if,
|
||||
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
|
||||
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
|
||||
LOG_WARN("%s, The connection not created.", __func__);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) {
|
||||
LOG_DEBUG("%s, the l2cap chanel is congest.", __func__);
|
||||
return ESP_FAIL;
|
||||
@@ -474,6 +505,12 @@ esp_err_t esp_ble_gattc_write_char_descr (esp_gatt_if_t gattc_if,
|
||||
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
|
||||
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
|
||||
LOG_WARN("%s, The connection not created.", __func__);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) {
|
||||
LOG_DEBUG("%s, the l2cap chanel is congest.", __func__);
|
||||
return ESP_FAIL;
|
||||
@@ -506,6 +543,12 @@ esp_err_t esp_ble_gattc_prepare_write(esp_gatt_if_t gattc_if,
|
||||
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
|
||||
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
|
||||
LOG_WARN("%s, The connection not created.", __func__);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) {
|
||||
LOG_DEBUG("%s, the l2cap chanel is congest.", __func__);
|
||||
return ESP_FAIL;
|
||||
@@ -536,6 +579,12 @@ esp_err_t esp_ble_gattc_prepare_write_char_descr(esp_gatt_if_t gattc_if,
|
||||
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
|
||||
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
|
||||
LOG_WARN("%s, The connection not created.", __func__);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) {
|
||||
LOG_DEBUG("%s, the l2cap chanel is congest.", __func__);
|
||||
return ESP_FAIL;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "common/bt_target.h"
|
||||
#include "stack/l2cdefs.h"
|
||||
#include "stack/l2c_api.h"
|
||||
#include "gatt_int.h"
|
||||
|
||||
#if (GATTS_INCLUDED == TRUE)
|
||||
#define COPY_TO_GATTS_ARGS(_gatt_args, _arg, _arg_type) memcpy(_gatt_args, _arg, sizeof(_arg_type))
|
||||
@@ -251,7 +252,13 @@ esp_err_t esp_ble_gatts_send_indicate(esp_gatt_if_t gatts_if, uint16_t conn_id,
|
||||
btc_ble_gatts_args_t arg;
|
||||
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
|
||||
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
|
||||
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
|
||||
LOG_WARN("%s, The connection not created.", __func__);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) {
|
||||
LOG_DEBUG("%s, the l2cap chanel is congest.", __func__);
|
||||
return ESP_FAIL;
|
||||
@@ -279,7 +286,13 @@ esp_err_t esp_ble_gatts_send_response(esp_gatt_if_t gatts_if, uint16_t conn_id,
|
||||
btc_ble_gatts_args_t arg;
|
||||
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
|
||||
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
|
||||
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
|
||||
LOG_WARN("%s, The connection not created.", __func__);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTS;
|
||||
msg.act = BTC_GATTS_ACT_SEND_RESPONSE;
|
||||
|
||||
@@ -336,6 +336,7 @@ typedef union {
|
||||
struct read_rmt_name_param {
|
||||
esp_bt_status_t stat; /*!< read Remote Name status */
|
||||
uint8_t rmt_name[ESP_BT_GAP_MAX_BDNAME_LEN + 1]; /*!< Remote device name */
|
||||
esp_bd_addr_t bda; /*!< remote bluetooth device address*/
|
||||
} read_rmt_name; /*!< read Remote Name parameter struct */
|
||||
|
||||
/**
|
||||
|
||||
@@ -34,6 +34,10 @@ extern "C" {
|
||||
#define ESP_HF_PEER_FEAT_ECC 0x80 /* Enhanced Call Control */
|
||||
#define ESP_HF_PEER_FEAT_EXTERR 0x100 /* Extended error codes */
|
||||
#define ESP_HF_PEER_FEAT_CODEC 0x200 /* Codec Negotiation */
|
||||
/* HFP 1.7+ */
|
||||
#define ESP_HF_PEER_FEAT_HF_IND 0x400 /* HF Indicators */
|
||||
#define ESP_HF_PEER_FEAT_ESCO_S4 0x800 /* eSCO S4 Setting Supported */
|
||||
|
||||
|
||||
/* CHLD feature masks of HF AG */
|
||||
#define ESP_HF_CHLD_FEAT_REL 0x01 /* 0 Release waiting call or held calls */
|
||||
|
||||
@@ -60,6 +60,9 @@ typedef enum {
|
||||
#define ESP_HF_CLIENT_PEER_FEAT_ECC 0x80 /* Enhanced Call Control */
|
||||
#define ESP_HF_CLIENT_PEER_FEAT_EXTERR 0x100 /* Extended error codes */
|
||||
#define ESP_HF_CLIENT_PEER_FEAT_CODEC 0x200 /* Codec Negotiation */
|
||||
/* HFP 1.7+ */
|
||||
#define ESP_HF_CLIENT_PEER_FEAT_HF_IND 0x400 /* HF Indicators */
|
||||
#define ESP_HF_CLIENT_PEER_FEAT_ESCO_S4 0x800 /* eSCO S4 Setting Supported */
|
||||
|
||||
/* CHLD feature masks of AG */
|
||||
#define ESP_HF_CLIENT_CHLD_FEAT_REL 0x01 /* 0 Release waiting call or held calls */
|
||||
|
||||
@@ -272,7 +272,7 @@ const tBTA_AG_ST_TBL bta_ag_st_tbl[] =
|
||||
/*****************************************************************************
|
||||
** Global data
|
||||
*****************************************************************************/
|
||||
const char *bta_ag_version = "1.6";
|
||||
const uint16_t bta_ag_version = HFP_VERSION_1_7;
|
||||
/* AG control block */
|
||||
#if BTA_DYNAMIC_MEMORY == FALSE
|
||||
tBTA_AG_CB bta_ag_cb;
|
||||
@@ -758,7 +758,7 @@ static void bta_ag_api_enable(tBTA_AG_DATA *p_data)
|
||||
bta_ag_cb.p_cback = p_data->api_enable.p_cback;
|
||||
bta_ag_cb.parse_mode = p_data->api_enable.parse_mode;
|
||||
/* check if mSBC support enabled */
|
||||
if (strcmp(bta_ag_version, "1.6") == 0) {
|
||||
if (bta_ag_version >= HFP_VERSION_1_6) {
|
||||
bta_ag_cb.msbc_enabled = TRUE;
|
||||
bta_ag_cb.scb->negotiated_codec = BTM_SCO_CODEC_MSBC;
|
||||
} else{
|
||||
|
||||
@@ -70,10 +70,11 @@ enum
|
||||
};
|
||||
|
||||
#if (BTM_WBS_INCLUDED == TRUE)
|
||||
#define BTA_AG_NUM_CODECS 3
|
||||
#define BTA_AG_ESCO_SETTING_IDX_CVSD 0 /* eSCO setting for CVSD */
|
||||
#define BTA_AG_NUM_CODECS 4
|
||||
#define BTA_AG_ESCO_SETTING_IDX_CVSD 0 /* eSCO setting for CVSD */
|
||||
#define BTA_AG_ESCO_SETTING_IDX_T1 1 /* eSCO setting for mSBC T1 */
|
||||
#define BTA_AG_ESCO_SETTING_IDX_T2 2 /* eSCO setting for mSBC T2 */
|
||||
#define BTA_AG_ESCO_SETTING_IDX_S4 3 /* eSCO setting for CVSD S4 */
|
||||
|
||||
static const tBTM_ESCO_PARAMS bta_ag_esco_params[BTA_AG_NUM_CODECS] =
|
||||
{
|
||||
@@ -81,9 +82,9 @@ static const tBTM_ESCO_PARAMS bta_ag_esco_params[BTA_AG_NUM_CODECS] =
|
||||
{
|
||||
BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec) */
|
||||
BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec) */
|
||||
0x000a, /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3) */
|
||||
10, /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3) */
|
||||
BTM_VOICE_SETTING_CVSD, /* Inp Linear, Air CVSD, 2s Comp, 16bit */
|
||||
(BTM_SCO_PKT_TYPES_MASK_HV1 + /* Packet Types */
|
||||
(BTM_SCO_PKT_TYPES_MASK_HV1 + /* Packet Types */
|
||||
BTM_SCO_PKT_TYPES_MASK_HV2 +
|
||||
BTM_SCO_PKT_TYPES_MASK_HV3 +
|
||||
BTM_SCO_PKT_TYPES_MASK_EV3 +
|
||||
@@ -91,7 +92,7 @@ static const tBTM_ESCO_PARAMS bta_ag_esco_params[BTA_AG_NUM_CODECS] =
|
||||
BTM_SCO_PKT_TYPES_MASK_EV5 +
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 +
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
|
||||
BTM_ESCO_RETRANS_POWER /* Retransmission effort */
|
||||
BTM_ESCO_RETRANS_POWER /* Retransmission effort */
|
||||
},
|
||||
/* mSBC T1 */
|
||||
{
|
||||
@@ -104,7 +105,7 @@ static const tBTM_ESCO_PARAMS bta_ag_esco_params[BTA_AG_NUM_CODECS] =
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5 |
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 ),
|
||||
BTM_ESCO_RETRANS_QUALITY /* Retransmission effort */
|
||||
BTM_ESCO_RETRANS_QUALITY /* Retransmission effort */
|
||||
},
|
||||
/* mSBC T2*/
|
||||
{
|
||||
@@ -116,26 +117,56 @@ static const tBTM_ESCO_PARAMS bta_ag_esco_params[BTA_AG_NUM_CODECS] =
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
|
||||
BTM_ESCO_RETRANS_QUALITY /* Retransmission effort */
|
||||
BTM_ESCO_RETRANS_QUALITY /* Retransmission effort */
|
||||
},
|
||||
/* HFP 1.7+ */
|
||||
/* eSCO CVSD S4 */
|
||||
{
|
||||
BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec) */
|
||||
BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec) */
|
||||
12, /* 12 ms (HS/HF can use EV3, 2-EV3) */
|
||||
BTM_VOICE_SETTING_CVSD, /* Inp Linear, Air CVSD, 2s Comp, 16bit */
|
||||
(BTM_SCO_LINK_ALL_PKT_MASK |
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
|
||||
BTM_ESCO_RETRANS_QUALITY /* Retransmission effort */
|
||||
}
|
||||
};
|
||||
#else
|
||||
#define BTA_AG_NUM_CODECS 2
|
||||
#define BTA_AG_ESCO_SETTING_IDX_CVSD 0 /* eSCO setting for CVSD S3 */
|
||||
#define BTA_AG_ESCO_SETTING_IDX_S4 1 /* eSCO setting for CVSD S4 */
|
||||
|
||||
/* WBS not included, CVSD by default */
|
||||
static const tBTM_ESCO_PARAMS bta_ag_esco_params =
|
||||
static const tBTM_ESCO_PARAMS bta_ag_esco_params[] =
|
||||
{
|
||||
BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec) */
|
||||
BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec) */
|
||||
0x000a, /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3) */
|
||||
0x0060, /* Inp Linear, Air CVSD, 2s Comp, 16bit */
|
||||
(BTM_SCO_PKT_TYPES_MASK_HV1 + /* Packet Types */
|
||||
BTM_SCO_PKT_TYPES_MASK_HV2 +
|
||||
BTM_SCO_PKT_TYPES_MASK_HV3 +
|
||||
BTM_SCO_PKT_TYPES_MASK_EV3 +
|
||||
BTM_SCO_PKT_TYPES_MASK_EV4 +
|
||||
BTM_SCO_PKT_TYPES_MASK_EV5 +
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 +
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
|
||||
BTM_ESCO_RETRANS_POWER /* Retransmission effort */
|
||||
{
|
||||
BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec) */
|
||||
BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec) */
|
||||
10, /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3) */
|
||||
BTM_VOICE_SETTING_CVSD, /* Inp Linear, Air CVSD, 2s Comp, 16bit */
|
||||
(BTM_SCO_PKT_TYPES_MASK_HV1 + /* Packet Types */
|
||||
BTM_SCO_PKT_TYPES_MASK_HV2 +
|
||||
BTM_SCO_PKT_TYPES_MASK_HV3 +
|
||||
BTM_SCO_PKT_TYPES_MASK_EV3 +
|
||||
BTM_SCO_PKT_TYPES_MASK_EV4 +
|
||||
BTM_SCO_PKT_TYPES_MASK_EV5 +
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 +
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
|
||||
BTM_ESCO_RETRANS_POWER /* Retransmission effort */
|
||||
},
|
||||
/* HFP 1.7+ */
|
||||
/* eSCO CVSD S4 */
|
||||
{
|
||||
BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec) */
|
||||
BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec) */
|
||||
12, /* 12 ms (HS/HF can use EV3, 2-EV3) */
|
||||
BTM_VOICE_SETTING_CVSD, /* Inp Linear, Air CVSD, 2s Comp, 16bit */
|
||||
(BTM_SCO_LINK_ALL_PKT_MASK |
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
|
||||
BTM_ESCO_RETRANS_QUALITY /* Retransmission effort */
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -470,9 +501,9 @@ static void bta_ag_create_sco(tBTA_AG_SCB *p_scb, BOOLEAN is_orig)
|
||||
tBTM_STATUS status;
|
||||
UINT8 *p_bd_addr = NULL;
|
||||
tBTM_ESCO_PARAMS params;
|
||||
UINT8 codec_index = BTA_AG_ESCO_SETTING_IDX_CVSD;
|
||||
#if (BTM_WBS_INCLUDED == TRUE)
|
||||
tBTA_AG_PEER_CODEC esco_codec = BTM_SCO_CODEC_CVSD;
|
||||
int codec_index = 0;
|
||||
#endif
|
||||
#if (BTM_SCO_HCI_INCLUDED == TRUE)
|
||||
tBTM_SCO_ROUTE_TYPE sco_route;
|
||||
@@ -513,11 +544,20 @@ static void bta_ag_create_sco(tBTA_AG_SCB *p_scb, BOOLEAN is_orig)
|
||||
codec_index = BTA_AG_ESCO_SETTING_IDX_T1;
|
||||
}
|
||||
}
|
||||
params = bta_ag_esco_params[codec_index];
|
||||
/* If eSCO codec is CVSD and eSC0 S4 is supported, index is S4 */
|
||||
else if ((esco_codec == BTM_SCO_CODEC_CVSD) && (p_scb->features & BTA_AG_FEAT_ESCO_S4)
|
||||
&& (p_scb->peer_features & BTA_AG_PEER_FEAT_ESCO_S4))
|
||||
{
|
||||
codec_index = BTA_AG_ESCO_SETTING_IDX_S4;
|
||||
}
|
||||
|
||||
#else
|
||||
/* When WBS is not included, use CVSD by default */
|
||||
params = bta_ag_esco_params;
|
||||
if ((p_scb->features & BTA_AG_FEAT_ESCO_S4) && (p_scb->peer_features & BTA_AG_PEER_FEAT_ESCO_S4))
|
||||
{
|
||||
codec_index = BTA_AG_ESCO_SETTING_IDX_S4;
|
||||
}
|
||||
#endif
|
||||
params = bta_ag_esco_params[codec_index];
|
||||
|
||||
if(bta_ag_cb.sco.param_updated) /* If we do not use the default parameters */
|
||||
params = bta_ag_cb.sco.params;
|
||||
@@ -528,10 +568,13 @@ static void bta_ag_create_sco(tBTA_AG_SCB *p_scb, BOOLEAN is_orig)
|
||||
if (esco_codec == BTM_SCO_CODEC_CVSD) /* For CVSD */
|
||||
#endif
|
||||
{
|
||||
/* Use the application packet types (5 slot EV packets not allowed) */
|
||||
params.packet_types = p_bta_ag_cfg->sco_pkt_types |
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5;
|
||||
if (codec_index == BTA_AG_ESCO_SETTING_IDX_CVSD)
|
||||
{
|
||||
/* Use the application packet types (5 slot EV packets not allowed) */
|
||||
params.packet_types = p_bta_ag_cfg->sco_pkt_types |
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1608,6 +1651,7 @@ void bta_ag_sco_conn_rsp(tBTA_AG_SCB *p_scb, tBTM_ESCO_CONN_REQ_EVT_DATA *p_data
|
||||
|
||||
if (p_data->link_type == BTM_LINK_TYPE_SCO)
|
||||
{
|
||||
resp.retrans_effort = BTM_ESCO_RETRANS_OFF;
|
||||
resp.packet_types = (BTM_SCO_LINK_ONLY_MASK |
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 |
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
|
||||
@@ -1616,6 +1660,13 @@ void bta_ag_sco_conn_rsp(tBTA_AG_SCB *p_scb, tBTM_ESCO_CONN_REQ_EVT_DATA *p_data
|
||||
}
|
||||
else /* Allow controller to use all types available except 5-slot EDR */
|
||||
{
|
||||
if ((p_scb->features & BTA_AG_FEAT_ESCO_S4) &&
|
||||
(p_scb->peer_features & BTA_AG_PEER_FEAT_ESCO_S4))
|
||||
{
|
||||
resp.max_latency = 12;
|
||||
resp.retrans_effort = BTM_ESCO_RETRANS_QUALITY;
|
||||
}
|
||||
|
||||
resp.packet_types = (BTM_SCO_LINK_ALL_PKT_MASK |
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5);
|
||||
|
||||
@@ -157,7 +157,7 @@ BOOLEAN bta_ag_add_record(UINT16 service_uuid, char *p_service_name, UINT8 scn,
|
||||
/* add profile descriptor list */
|
||||
if (service_uuid == UUID_SERVCLASS_AG_HANDSFREE) {
|
||||
profile_uuid = UUID_SERVCLASS_HF_HANDSFREE;
|
||||
version = HFP_VERSION_1_6;
|
||||
version = HFP_VERSION_1_7;
|
||||
} else {
|
||||
profile_uuid = UUID_SERVCLASS_HEADSET;
|
||||
version = HSP_VERSION_1_2;
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#define HFP_VERSION_1_1 0x0101
|
||||
#define HFP_VERSION_1_5 0x0105
|
||||
#define HFP_VERSION_1_6 0x0106
|
||||
#define HFP_VERSION_1_7 0x0107
|
||||
|
||||
#define HSP_VERSION_1_0 0x0100
|
||||
#define HSP_VERSION_1_2 0x0102
|
||||
@@ -75,12 +76,12 @@
|
||||
#define BTA_AG_INT 1 /* initiating connection */
|
||||
|
||||
/* feature mask that matches spec */
|
||||
#define BTA_AG_BSRF_FEAT_SPEC (BTA_AG_FEAT_3WAY | BTA_AG_FEAT_ECNR | \
|
||||
BTA_AG_FEAT_VREC | BTA_AG_FEAT_INBAND | \
|
||||
BTA_AG_FEAT_VTAG | BTA_AG_FEAT_REJECT | \
|
||||
BTA_AG_FEAT_ECS | BTA_AG_FEAT_ECC | \
|
||||
BTA_AG_FEAT_EXTERR | BTA_AG_FEAT_CODEC | \
|
||||
BTA_AG_FEAT_VOIP)
|
||||
#define BTA_AG_BSRF_FEAT_SPEC (BTA_AG_FEAT_3WAY | BTA_AG_FEAT_ECNR | \
|
||||
BTA_AG_FEAT_VREC | BTA_AG_FEAT_INBAND | \
|
||||
BTA_AG_FEAT_VTAG | BTA_AG_FEAT_REJECT | \
|
||||
BTA_AG_FEAT_ECS | BTA_AG_FEAT_ECC | \
|
||||
BTA_AG_FEAT_EXTERR | BTA_AG_FEAT_CODEC | \
|
||||
BTA_AG_FEAT_ESCO_S4| BTA_AG_FEAT_VOIP)
|
||||
|
||||
#define BTA_AG_SDP_FEAT_SPEC (BTA_AG_FEAT_3WAY | BTA_AG_FEAT_ECNR | \
|
||||
BTA_AG_FEAT_VREC | BTA_AG_FEAT_INBAND | \
|
||||
|
||||
@@ -232,7 +232,7 @@ const tBTA_HF_CLIENT_ST_TBL bta_hf_client_st_tbl[] = {
|
||||
bta_hf_client_st_closing
|
||||
};
|
||||
|
||||
const char *bta_hf_client_version = "1.6";
|
||||
const int bta_hf_client_version = HFP_HF_VERSION_1_7;
|
||||
|
||||
/* HF Client control block */
|
||||
#if BTA_DYNAMIC_MEMORY == FALSE
|
||||
@@ -387,7 +387,7 @@ static void bta_hf_client_api_enable(tBTA_HF_CLIENT_DATA *p_data)
|
||||
bta_hf_client_cb.p_cback = p_data->api_enable.p_cback;
|
||||
|
||||
/* check if mSBC support enabled */
|
||||
if (strcmp(bta_hf_client_version, "1.6") == 0) {
|
||||
if (bta_hf_client_version >= HFP_HF_VERSION_1_6) {
|
||||
bta_hf_client_cb.msbc_enabled = TRUE;
|
||||
} else{
|
||||
bta_hf_client_cb.msbc_enabled = FALSE;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "bta_hf_client_int.h"
|
||||
#include "bta/bta_hf_client_api.h"
|
||||
#include "common/bt_trace.h"
|
||||
#include <string.h>
|
||||
#include "common/bt_defs.h"
|
||||
@@ -34,6 +35,11 @@
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | \
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5)
|
||||
|
||||
#define BTA_HF_CLIENT_SCO_PARAM_IDX_CVSD 0 /* SCO setting for CVSD */
|
||||
#define BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S3 1 /* eSCO setting for CVSD S3 */
|
||||
#define BTA_HF_CLIENT_ESCO_PARAM_IDX_MSBC_T2 2 /* eSCO setting for mSBC T2 */
|
||||
#define BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S4 3 /* eSCO setting for CVSD S4 */
|
||||
|
||||
static const tBTM_ESCO_PARAMS bta_hf_client_esco_params[] = {
|
||||
/* SCO CVSD */
|
||||
{
|
||||
@@ -72,6 +78,19 @@ static const tBTM_ESCO_PARAMS bta_hf_client_esco_params[] = {
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
|
||||
.retrans_effort = BTM_ESCO_RETRANS_QUALITY,
|
||||
},
|
||||
/* HFP 1.7+ */
|
||||
/* ESCO CVSD S4 */
|
||||
{
|
||||
.rx_bw = BTM_64KBITS_RATE,
|
||||
.tx_bw = BTM_64KBITS_RATE,
|
||||
.max_latency = 12,
|
||||
.voice_contfmt = BTM_VOICE_SETTING_CVSD,
|
||||
/* Allow controller to use all types available except 5-slot EDR */
|
||||
.packet_types = (BTM_SCO_LINK_ALL_PKT_MASK |
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
|
||||
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
|
||||
.retrans_effort = BTM_ESCO_RETRANS_QUALITY,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -178,18 +197,27 @@ static void bta_hf_client_sco_conn_rsp(tBTM_ESCO_CONN_REQ_EVT_DATA *p_data)
|
||||
{
|
||||
tBTM_ESCO_PARAMS resp;
|
||||
UINT8 hci_status = HCI_SUCCESS;
|
||||
UINT8 index = BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S3;
|
||||
#if (BTM_SCO_HCI_INCLUDED == TRUE )
|
||||
tBTA_HFP_CODEC_INFO codec_info = {BTA_HFP_SCO_CODEC_PCM};
|
||||
UINT32 pcm_sample_rate;
|
||||
#endif
|
||||
APPL_TRACE_DEBUG("%s", __FUNCTION__);
|
||||
|
||||
APPL_TRACE_DEBUG("%s: negotiated codec = %d", __FUNCTION__, bta_hf_client_cb.scb.negotiated_codec);
|
||||
|
||||
if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_LISTEN_ST) {
|
||||
if (p_data->link_type == BTM_LINK_TYPE_SCO) {
|
||||
resp = bta_hf_client_esco_params[0];
|
||||
index = BTA_HF_CLIENT_SCO_PARAM_IDX_CVSD;
|
||||
} else {
|
||||
resp = bta_hf_client_esco_params[bta_hf_client_cb.scb.negotiated_codec];
|
||||
if ((bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_CVSD) &&
|
||||
(bta_hf_client_cb.scb.features && BTA_HF_CLIENT_FEAT_ESCO_S4) &&
|
||||
(bta_hf_client_cb.scb.peer_features && BTA_HF_CLIENT_PEER_ESCO_S4)) {
|
||||
index = BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S4;
|
||||
} else if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC) {
|
||||
index = BTA_HF_CLIENT_ESCO_PARAM_IDX_MSBC_T2;
|
||||
}
|
||||
}
|
||||
resp = bta_hf_client_esco_params[index];
|
||||
|
||||
/* tell sys to stop av if any */
|
||||
bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
|
||||
@@ -350,6 +378,7 @@ static void bta_hf_client_sco_create(BOOLEAN is_orig)
|
||||
tBTM_STATUS status;
|
||||
UINT8 *p_bd_addr = NULL;
|
||||
tBTM_ESCO_PARAMS params;
|
||||
UINT8 index = BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S3;
|
||||
#if (BTM_SCO_HCI_INCLUDED == TRUE )
|
||||
tBTM_SCO_ROUTE_TYPE sco_route;
|
||||
tBTA_HFP_CODEC_INFO codec_info = {BTA_HFP_SCO_CODEC_PCM};
|
||||
@@ -364,7 +393,15 @@ static void bta_hf_client_sco_create(BOOLEAN is_orig)
|
||||
return;
|
||||
}
|
||||
|
||||
params = bta_hf_client_esco_params[1];
|
||||
if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_CVSD) {
|
||||
if ((bta_hf_client_cb.scb.features && BTA_HF_CLIENT_FEAT_ESCO_S4) &&
|
||||
(bta_hf_client_cb.scb.peer_features && BTA_HF_CLIENT_PEER_ESCO_S4)) {
|
||||
index = BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S4;
|
||||
}
|
||||
} else if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC) {
|
||||
index = BTA_HF_CLIENT_ESCO_PARAM_IDX_MSBC_T2;
|
||||
}
|
||||
params = bta_hf_client_esco_params[index];
|
||||
|
||||
/* if initiating set current scb and peer bd addr */
|
||||
if (is_orig) {
|
||||
|
||||
@@ -114,7 +114,7 @@ BOOLEAN bta_hf_client_add_record(char *p_service_name, UINT8 scn,
|
||||
|
||||
/* add profile descriptor list */
|
||||
profile_uuid = UUID_SERVCLASS_HF_HANDSFREE;
|
||||
version = HFP_VERSION_1_6;
|
||||
version = HFP_VERSION_1_7;
|
||||
|
||||
result &= SDP_AddProfileDescriptorList(sdp_handle, profile_uuid, version);
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#define HFP_VERSION_1_1 0x0101
|
||||
#define HFP_VERSION_1_5 0x0105
|
||||
#define HFP_VERSION_1_6 0x0106
|
||||
#define HFP_VERSION_1_7 0x0107
|
||||
|
||||
/* RFCOMM MTU SIZE */
|
||||
#define BTA_HF_CLIENT_MTU 256
|
||||
|
||||
@@ -45,12 +45,16 @@
|
||||
#define BTA_AG_FEAT_ECC 0x00000080 /* Enhanced Call Control */
|
||||
#define BTA_AG_FEAT_EXTERR 0x00000100 /* Extended error codes */
|
||||
#define BTA_AG_FEAT_CODEC 0x00000200 /* Codec Negotiation */
|
||||
#define BTA_AG_FEAT_VOIP 0x00000400 /* VoIP call */
|
||||
/* HFP 1.7+ */
|
||||
#define BTA_AG_FEAT_HF_IND 0x00000400 /* HF Indicators */
|
||||
#define BTA_AG_FEAT_ESCO_S4 0x00000800 /* eSCO S4 Setting Supported */
|
||||
|
||||
/* Proprietary features: using 31 ~ 16 bits */
|
||||
#define BTA_AG_FEAT_BTRH 0x00010000 /* CCAP incoming call hold */
|
||||
#define BTA_AG_FEAT_UNAT 0x00020000 /* Pass unknown AT commands to application */
|
||||
#define BTA_AG_FEAT_NOSCO 0x00040000 /* No SCO control performed by BTA AG */
|
||||
#define BTA_AG_FEAT_NO_ESCO 0x00080000 /* Do not allow or use eSCO */
|
||||
#define BTA_AG_FEAT_VOIP 0x00100000 /* VoIP call */
|
||||
typedef UINT32 tBTA_AG_FEAT;
|
||||
|
||||
/* HFP peer features */
|
||||
@@ -62,9 +66,16 @@ typedef UINT32 tBTA_AG_FEAT;
|
||||
#define BTA_AG_PEER_FEAT_ECS 0x0020 /* Enhanced Call Status */
|
||||
#define BTA_AG_PEER_FEAT_ECC 0x0040 /* Enhanced Call Control */
|
||||
#define BTA_AG_PEER_FEAT_CODEC 0x0080 /* Codec Negotiation */
|
||||
#define BTA_AG_PEER_FEAT_VOIP 0x0100 /* VoIP call */
|
||||
/* HFP 1.7+ */
|
||||
#define BTA_AG_PEER_FEAT_HF_IND 0x0100 /* HF Indicators */
|
||||
#define BTA_AG_PEER_FEAT_ESCO_S4 0x0200 /* eSCO S4 Setting Supported */
|
||||
typedef UINT16 tBTA_AG_PEER_FEAT;
|
||||
|
||||
/* Proprietary features: using bits after 12 */
|
||||
/* Pass unknown AT command responses to application */
|
||||
#define BTA_AG_PEER_FEAT_UNAT 0x1000
|
||||
#define BTA_AG_PEER_FEAT_VOIP 0x2000 /* VoIP call */
|
||||
|
||||
/* AG extended call handling - masks not related to any spec */
|
||||
#define BTA_AG_CLIENT_CHLD_REL 0x00000001 /* 0 Release waiting call or held calls */
|
||||
#define BTA_AG_CLIENT_CHLD_REL_ACC 0x00000002 /* 1 Release active calls and accept other (waiting or held) cal */
|
||||
|
||||
@@ -33,6 +33,10 @@
|
||||
** Constants and data types
|
||||
*****************************************************************************/
|
||||
|
||||
/* Hands-Free unit(HF) version */
|
||||
#define HFP_HF_VERSION_1_6 0x0106 /* v1.6 */
|
||||
#define HFP_HF_VERSION_1_7 0x0107 /* v1.7 */
|
||||
|
||||
/* HFP peer (AG) features*/
|
||||
#define BTA_HF_CLIENT_PEER_FEAT_3WAY 0x00000001 /* Three-way calling */
|
||||
#define BTA_HF_CLIENT_PEER_FEAT_ECNR 0x00000002 /* Echo cancellation and/or noise reduction */
|
||||
@@ -44,6 +48,9 @@
|
||||
#define BTA_HF_CLIENT_PEER_ECC 0x00000080 /* Enhanced Call Control */
|
||||
#define BTA_HF_CLIENT_PEER_EXTERR 0x00000100 /* Extended error codes */
|
||||
#define BTA_HF_CLIENT_PEER_CODEC 0x00000200 /* Codec Negotiation */
|
||||
/* HFP 1.7+ */
|
||||
#define BTA_HF_CLIENT_PEER_HF_IND 0x00000400 /* HF Indicators */
|
||||
#define BTA_HF_CLIENT_PEER_ESCO_S4 0x00000800 /* eSCO S4 Setting Supported */
|
||||
|
||||
typedef UINT16 tBTA_HF_CLIENT_PEER_FEAT;
|
||||
|
||||
@@ -56,6 +63,8 @@ typedef UINT16 tBTA_HF_CLIENT_PEER_FEAT;
|
||||
#define BTA_HF_CLIENT_FEAT_ECS 0x00000020 /* Enhanced Call Status */
|
||||
#define BTA_HF_CLIENT_FEAT_ECC 0x00000040 /* Enhanced Call Control */
|
||||
#define BTA_HF_CLIENT_FEAT_CODEC 0x00000080 /* Codec Negotiation */
|
||||
#define BTA_HF_CLIENT_FEAT_HF_IND 0x00000100 /* HF indicators */
|
||||
#define BTA_HF_CLIENT_FEAT_ESCO_S4 0x00000200 /* eSCO S4 Setting Supported */
|
||||
|
||||
/* HFP HF extended call handling - masks not related to any spec */
|
||||
#define BTA_HF_CLIENT_CHLD_REL 0x00000001 /* 0 Release waiting call or held calls */
|
||||
|
||||
@@ -110,12 +110,18 @@ typedef struct {
|
||||
UINT32 sample_rate;
|
||||
} tBTC_A2DP_SINK_CB;
|
||||
|
||||
typedef struct {
|
||||
uint16_t expected_seq_num;
|
||||
bool seq_num_recount;
|
||||
} a2dp_sink_media_pkt_seq_num_t;
|
||||
|
||||
typedef struct {
|
||||
tBTC_A2DP_SINK_CB btc_aa_snk_cb;
|
||||
osi_thread_t *btc_aa_snk_task_hdl;
|
||||
OI_CODEC_SBC_DECODER_CONTEXT context;
|
||||
OI_UINT32 contextData[CODEC_DATA_WORDS(2, SBC_CODEC_FAST_FILTER_BUFFERS)];
|
||||
OI_INT16 pcmData[15 * SBC_MAX_SAMPLES_PER_FRAME * SBC_MAX_CHANNELS];
|
||||
a2dp_sink_media_pkt_seq_num_t media_pkt_seq_num;
|
||||
} a2dp_sink_local_param_t;
|
||||
|
||||
static void btc_a2dp_sink_thread_init(UNUSED_ATTR void *context);
|
||||
@@ -319,6 +325,10 @@ static BOOLEAN btc_a2dp_sink_clear_track(void)
|
||||
void btc_a2dp_sink_set_rx_flush(BOOLEAN enable)
|
||||
{
|
||||
APPL_TRACE_EVENT("## DROP RX %d ##\n", enable);
|
||||
if (enable == FALSE) {
|
||||
a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num = 0x1;
|
||||
a2dp_sink_local_param.media_pkt_seq_num.seq_num_recount = true;
|
||||
}
|
||||
a2dp_sink_local_param.btc_aa_snk_cb.rx_flush = enable;
|
||||
}
|
||||
|
||||
@@ -549,6 +559,18 @@ static void btc_a2dp_sink_handle_inc_media(tBT_SBC_HDR *p_msg)
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_msg->layer_specific != a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num) {
|
||||
/* Because the sequence number of some devices is not recounted */
|
||||
if (!a2dp_sink_local_param.media_pkt_seq_num.seq_num_recount ||
|
||||
a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num != 0x1) {
|
||||
APPL_TRACE_WARNING("Sequence numbers error, recv:0x%x, expect:0x%x, recount:0x%x",
|
||||
p_msg->layer_specific, a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num,
|
||||
a2dp_sink_local_param.media_pkt_seq_num.seq_num_recount);
|
||||
}
|
||||
}
|
||||
a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num = p_msg->layer_specific + 1;
|
||||
a2dp_sink_local_param.media_pkt_seq_num.seq_num_recount = false;
|
||||
|
||||
APPL_TRACE_DEBUG("Number of sbc frames %d, frame_len %d\n", num_sbc_frames, sbc_frame_len);
|
||||
|
||||
for (count = 0; count < num_sbc_frames && sbc_frame_len != 0; count ++) {
|
||||
|
||||
@@ -743,6 +743,7 @@ static void btc_gap_bt_read_remote_name_cmpl_callback(void *p_data)
|
||||
msg.pid = BTC_PID_GAP_BT;
|
||||
msg.act = BTC_GAP_BT_READ_REMOTE_NAME_EVT;
|
||||
|
||||
memcpy(param.read_rmt_name.bda,result->bd_addr,BD_ADDR_LEN);
|
||||
param.read_rmt_name.stat = btc_btm_status_to_esp_status(result->status);
|
||||
memcpy(param.read_rmt_name.rmt_name,result->remote_bd_name,ESP_BT_GAP_MAX_BDNAME_LEN);
|
||||
|
||||
|
||||
@@ -1,20 +1,8 @@
|
||||
/******************************************************************************
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* Copyright (C) 2009-2012 Broadcom Corporation
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
*
|
||||
@@ -68,6 +56,7 @@ static hf_local_param_t *hf_local_param;
|
||||
BTA_AG_FEAT_VREC | \
|
||||
BTA_AG_FEAT_INBAND | \
|
||||
BTA_AG_FEAT_CODEC | \
|
||||
BTA_AG_FEAT_ESCO_S4| \
|
||||
BTA_AG_FEAT_UNAT)
|
||||
#endif
|
||||
#else
|
||||
@@ -78,6 +67,7 @@ static hf_local_param_t *hf_local_param;
|
||||
BTA_AG_FEAT_EXTERR | \
|
||||
BTA_AG_FEAT_VREC | \
|
||||
BTA_AG_FEAT_INBAND | \
|
||||
BTA_AG_FEAT_ESCO_S4| \
|
||||
BTA_AG_FEAT_UNAT)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -51,13 +51,13 @@
|
||||
#endif
|
||||
|
||||
#ifndef BTC_HF_CLIENT_FEATURES
|
||||
#define BTC_HF_CLIENT_FEATURES ( BTA_HF_CLIENT_FEAT_ECNR | \
|
||||
BTA_HF_CLIENT_FEAT_3WAY | \
|
||||
BTA_HF_CLIENT_FEAT_CLI | \
|
||||
BTA_HF_CLIENT_FEAT_VREC | \
|
||||
BTA_HF_CLIENT_FEAT_VOL | \
|
||||
BTA_HF_CLIENT_FEAT_ECS | \
|
||||
BTA_HF_CLIENT_FEAT_ECC | \
|
||||
#define BTC_HF_CLIENT_FEATURES ( BTA_HF_CLIENT_FEAT_ECNR | \
|
||||
BTA_HF_CLIENT_FEAT_3WAY | \
|
||||
BTA_HF_CLIENT_FEAT_CLI | \
|
||||
BTA_HF_CLIENT_FEAT_VREC | \
|
||||
BTA_HF_CLIENT_FEAT_VOL | \
|
||||
BTA_HF_CLIENT_FEAT_ECS | \
|
||||
BTA_HF_CLIENT_FEAT_ECC | \
|
||||
BTA_HF_CLIENT_FEAT_CODEC)
|
||||
#endif
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
/************************************************************************************
|
||||
** Static variables
|
||||
************************************************************************************/
|
||||
const char *btc_hf_client_version = "1.6";
|
||||
const int btc_hf_client_version = HFP_HF_VERSION_1_7;
|
||||
|
||||
#if HFP_DYNAMIC_MEMORY == FALSE
|
||||
static hf_client_local_param_t hf_client_local_param;
|
||||
@@ -200,7 +200,7 @@ static bt_status_t connect_int( bt_bdaddr_t *bd_addr, uint16_t uuid )
|
||||
|
||||
bt_status_t btc_hf_client_connect( bt_bdaddr_t *bd_addr )
|
||||
{
|
||||
BTC_TRACE_EVENT("HFP Client version is %s", btc_hf_client_version);
|
||||
BTC_TRACE_EVENT("HFP Client version is 0x%04x", btc_hf_client_version);
|
||||
CHECK_HF_CLIENT_INIT();
|
||||
return btc_queue_connect(UUID_SERVCLASS_HF_HANDSFREE, bd_addr, connect_int);
|
||||
}
|
||||
@@ -690,33 +690,36 @@ bt_status_t btc_hf_client_execute_service(BOOLEAN b_enable)
|
||||
{
|
||||
BTC_TRACE_EVENT("%s enable:%d", __FUNCTION__, b_enable);
|
||||
|
||||
if (b_enable)
|
||||
{
|
||||
/* Enable and register with BTA-HFClient */
|
||||
BTA_HfClientEnable(bte_hf_client_evt);
|
||||
if (strcmp(btc_hf_client_version, "1.6") == 0)
|
||||
{
|
||||
BTC_TRACE_EVENT("Support Codec Nego. %d ", BTC_HF_CLIENT_FEATURES);
|
||||
BTA_HfClientRegister(BTC_HF_CLIENT_SECURITY, BTC_HF_CLIENT_FEATURES,
|
||||
BTC_HF_CLIENT_SERVICE_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
BTC_TRACE_EVENT("No Codec Nego Supported");
|
||||
hf_client_local_param.btc_hf_client_features = BTC_HF_CLIENT_FEATURES;
|
||||
hf_client_local_param.btc_hf_client_features = hf_client_local_param.btc_hf_client_features & (~BTA_HF_CLIENT_FEAT_CODEC);
|
||||
BTC_TRACE_EVENT("hf_client_local_param.btc_hf_client_features is %d", hf_client_local_param.btc_hf_client_features);
|
||||
BTA_HfClientRegister(BTC_HF_CLIENT_SECURITY, hf_client_local_param.btc_hf_client_features,
|
||||
BTC_HF_CLIENT_SERVICE_NAME);
|
||||
}
|
||||
if (b_enable)
|
||||
{
|
||||
/* Enable and register with BTA-HFClient */
|
||||
BTA_HfClientEnable(bte_hf_client_evt);
|
||||
hf_client_local_param.btc_hf_client_features = BTC_HF_CLIENT_FEATURES;
|
||||
if (btc_hf_client_version >= HFP_HF_VERSION_1_7)
|
||||
{
|
||||
hf_client_local_param.btc_hf_client_features |= BTA_HF_CLIENT_FEAT_ESCO_S4;
|
||||
BTC_TRACE_EVENT("eSCO S4 Setting Supported");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
BTA_HfClientDeregister(hf_client_local_param.btc_hf_client_cb.handle);
|
||||
BTA_HfClientDisable();
|
||||
}
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
else if (btc_hf_client_version >= HFP_HF_VERSION_1_6)
|
||||
{
|
||||
BTC_TRACE_EVENT("No eSCO S4 Setting Supported");
|
||||
}
|
||||
else
|
||||
{
|
||||
BTC_TRACE_EVENT("No Codec Nego Supported");
|
||||
hf_client_local_param.btc_hf_client_features = hf_client_local_param.btc_hf_client_features & (~BTA_HF_CLIENT_FEAT_CODEC);
|
||||
}
|
||||
BTC_TRACE_EVENT("hf_client_local_param.btc_hf_client_features is %d", hf_client_local_param.btc_hf_client_features);
|
||||
BTA_HfClientRegister(BTC_HF_CLIENT_SECURITY, hf_client_local_param.btc_hf_client_features,
|
||||
BTC_HF_CLIENT_SERVICE_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
BTA_HfClientDeregister(hf_client_local_param.btc_hf_client_cb.handle);
|
||||
BTA_HfClientDisable();
|
||||
}
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void process_ind_evt(tBTA_HF_CLIENT_IND *ind)
|
||||
|
||||
@@ -58,14 +58,14 @@ typedef union {
|
||||
tSDP_UUID *p_uuid_list;
|
||||
} start_discovery;
|
||||
//BTC_SPP_ACT_CONNECT
|
||||
struct connect_arg {
|
||||
struct conn_arg {
|
||||
esp_spp_sec_t sec_mask;
|
||||
esp_spp_role_t role;
|
||||
UINT8 remote_scn;
|
||||
esp_bd_addr_t peer_bd_addr;
|
||||
} connect;
|
||||
//BTC_SPP_ACT_DISCONNECT
|
||||
struct disconnect_arg {
|
||||
struct disconn_arg {
|
||||
UINT32 handle;
|
||||
} disconnect;
|
||||
//BTC_SPP_ACT_START_SRV
|
||||
|
||||
@@ -352,6 +352,20 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u
|
||||
}
|
||||
new_user_data = (void *)(uintptr_t)slot->id;
|
||||
break;
|
||||
case BTA_JV_RFCOMM_CL_INIT_EVT:
|
||||
slot = spp_find_slot_by_id(id);
|
||||
if (!slot) {
|
||||
BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
|
||||
p_data->rfc_cl_init.status = ESP_SPP_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (p_data->rfc_cl_init.status == BTA_JV_SUCCESS) {
|
||||
slot->rfc_handle = p_data->rfc_cl_init.handle;
|
||||
} else {
|
||||
spp_free_slot(slot);
|
||||
}
|
||||
break;
|
||||
case BTA_JV_RFCOMM_OPEN_EVT:
|
||||
slot = spp_find_slot_by_id(id);
|
||||
if (!slot) {
|
||||
@@ -359,7 +373,7 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u
|
||||
p_data->rfc_open.status = ESP_SPP_NO_CONNECTION;
|
||||
break;
|
||||
}
|
||||
slot->connected = TRUE;
|
||||
slot->connected = true;
|
||||
slot->rfc_handle = p_data->rfc_open.handle;
|
||||
slot->rfc_port_handle = BTA_JvRfcommGetPortHdl(p_data->rfc_open.handle);
|
||||
BTA_JvSetPmProfile(p_data->rfc_open.handle, BTA_JV_PM_ID_1, BTA_JV_CONN_OPEN);
|
||||
@@ -371,7 +385,7 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u
|
||||
p_data->rfc_close.status = ESP_SPP_NO_CONNECTION;
|
||||
break;
|
||||
}
|
||||
if (slot->connected && p_data->rfc_close.port_status != PORT_LOCAL_CLOSED) {
|
||||
if (slot->rfc_handle && p_data->rfc_close.port_status != PORT_LOCAL_CLOSED) {
|
||||
BTA_JvRfcommClose(slot->rfc_handle, NULL, (void *)slot->id);
|
||||
}
|
||||
p_data->rfc_close.status = BTA_JV_SUCCESS;
|
||||
@@ -505,6 +519,7 @@ static void btc_spp_init(btc_spp_args_t *arg)
|
||||
}
|
||||
if ((spp_local_param.tx_event_group = xEventGroupCreate()) == NULL) {
|
||||
BTC_TRACE_ERROR("%s create tx_event_group failed\n", __func__);
|
||||
osi_mutex_free(&spp_local_param.spp_slot_mutex);
|
||||
ret = ESP_SPP_NO_RESOURCE;
|
||||
break;
|
||||
}
|
||||
@@ -568,11 +583,6 @@ static void btc_spp_uninit(void)
|
||||
osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
||||
} while(0);
|
||||
|
||||
if (spp_local_param.tx_event_group) {
|
||||
vEventGroupDelete(spp_local_param.tx_event_group);
|
||||
spp_local_param.tx_event_group = NULL;
|
||||
}
|
||||
|
||||
if (ret != ESP_SPP_SUCCESS) {
|
||||
esp_spp_cb_param_t param;
|
||||
param.uninit.status = ret;
|
||||
@@ -1037,7 +1047,7 @@ void btc_spp_cb_handler(btc_msg_t *msg)
|
||||
}
|
||||
break;
|
||||
case BTA_JV_RFCOMM_WRITE_EVT:
|
||||
osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
||||
osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
||||
slot = spp_find_slot_by_handle(p_data->rfc_write.handle);
|
||||
if (!slot) {
|
||||
BTC_TRACE_ERROR("%s unable to find RFCOMM slot!, handle:%d", __func__, p_data->rfc_write.handle);
|
||||
@@ -1056,6 +1066,7 @@ void btc_spp_cb_handler(btc_msg_t *msg)
|
||||
BT_HDR *p_buf;
|
||||
serial = slot->serial;
|
||||
if ((p_buf = fixed_queue_try_peek_first(slot->tx.queue)) == NULL) {
|
||||
osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
||||
break;
|
||||
}
|
||||
if (p_data->rfc_write.status == BTA_JV_SUCCESS) {
|
||||
@@ -1121,7 +1132,7 @@ void btc_spp_cb_handler(btc_msg_t *msg)
|
||||
// if rx still has data, delay free slot
|
||||
if (slot->close_alarm == NULL && slot->rx.queue && fixed_queue_length(slot->rx.queue) > 0) {
|
||||
tBTA_JV *p_arg = NULL;
|
||||
if ((p_arg = malloc(sizeof(tBTA_JV))) == NULL) {
|
||||
if ((p_arg = osi_malloc(sizeof(tBTA_JV))) == NULL) {
|
||||
param.close.status = ESP_SPP_NO_RESOURCE;
|
||||
osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
||||
BTC_TRACE_ERROR("%s unable to malloc slot close_alarm arg!", __func__);
|
||||
@@ -1241,6 +1252,10 @@ void btc_spp_cb_handler(btc_msg_t *msg)
|
||||
param.uninit.status = ESP_SPP_SUCCESS;
|
||||
BTA_JvFree();
|
||||
osi_mutex_free(&spp_local_param.spp_slot_mutex);
|
||||
if (spp_local_param.tx_event_group) {
|
||||
vEventGroupDelete(spp_local_param.tx_event_group);
|
||||
spp_local_param.tx_event_group = NULL;
|
||||
}
|
||||
#if SPP_DYNAMIC_MEMORY == TRUE
|
||||
osi_free(spp_local_param_ptr);
|
||||
spp_local_param_ptr = NULL;
|
||||
|
||||
@@ -2085,12 +2085,6 @@ The maximum number of payload octets that the local device can receive in a sing
|
||||
#define BTSNOOP_MEM FALSE
|
||||
#endif
|
||||
|
||||
#if UC_BT_BLUEDROID_MEM_DEBUG
|
||||
#define HEAP_MEMORY_DEBUG TRUE
|
||||
#else
|
||||
#define HEAP_MEMORY_DEBUG FALSE
|
||||
#endif
|
||||
|
||||
#if UC_HEAP_ALLOCATION_FROM_SPIRAM_FIRST
|
||||
#define HEAP_ALLOCATION_FROM_SPIRAM_FIRST TRUE
|
||||
#else
|
||||
|
||||
@@ -1586,8 +1586,8 @@ void avdt_msg_send_grej(tAVDT_CCB *p_ccb, UINT8 sig_id, tAVDT_MSG *p_params)
|
||||
p_buf->len = (UINT16) (p - p_start);
|
||||
|
||||
/* stash sig, label, and message type in buf */
|
||||
p_buf->event = 0;
|
||||
AVDT_BLD_LAYERSPEC(p_buf->layer_specific, 0, p_params->hdr.label);
|
||||
p_buf->event = sig_id;
|
||||
AVDT_BLD_LAYERSPEC(p_buf->layer_specific, AVDT_MSG_TYPE_GRJ, p_params->hdr.label);
|
||||
AVDT_TRACE_DEBUG("avdt_msg_send_grej");
|
||||
|
||||
/* queue message and trigger ccb to send it */
|
||||
|
||||
@@ -2306,6 +2306,7 @@ void btm_process_remote_name (BD_ADDR bda, BD_NAME bdn, UINT16 evt_len, UINT8 hc
|
||||
rem_name.length = 0;
|
||||
rem_name.remote_bd_name[0] = 0;
|
||||
}
|
||||
memcpy(rem_name.bd_addr, p_inq->remname_bda, BD_ADDR_LEN);
|
||||
/* Reset the remote BAD to zero and call callback if possible */
|
||||
memset(p_inq->remname_bda, 0, BD_ADDR_LEN);
|
||||
|
||||
|
||||
@@ -111,12 +111,15 @@ static void btu_hcif_rem_oob_request_evt (UINT8 *p);
|
||||
#if (SMP_INCLUDED == TRUE)
|
||||
static void btu_hcif_simple_pair_complete_evt (UINT8 *p);
|
||||
#endif ///SMP_INCLUDED == TRUE
|
||||
static void btu_hcif_link_supv_to_changed_evt (UINT8 *p);
|
||||
#if L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE
|
||||
static void btu_hcif_enhanced_flush_complete_evt (void);
|
||||
#endif
|
||||
|
||||
#if (BTM_SSR_INCLUDED == TRUE)
|
||||
static void btu_hcif_ssr_evt (UINT8 *p, UINT16 evt_len);
|
||||
#else
|
||||
static void btu_hcif_ssr_evt_dump (UINT8 *p, UINT16 evt_len);
|
||||
#endif /* BTM_SSR_INCLUDED == TRUE */
|
||||
|
||||
#if BLE_INCLUDED == TRUE
|
||||
@@ -289,11 +292,13 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg)
|
||||
case HCI_ESCO_CONNECTION_CHANGED_EVT:
|
||||
btu_hcif_esco_connection_chg_evt (p);
|
||||
break;
|
||||
#if (BTM_SSR_INCLUDED == TRUE)
|
||||
case HCI_SNIFF_SUB_RATE_EVT:
|
||||
#if (BTM_SSR_INCLUDED == TRUE)
|
||||
btu_hcif_ssr_evt (p, hci_evt_len);
|
||||
break;
|
||||
#else
|
||||
btu_hcif_ssr_evt_dump (p, hci_evt_len);
|
||||
#endif /* BTM_SSR_INCLUDED == TRUE */
|
||||
break;
|
||||
case HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT:
|
||||
btu_hcif_host_support_evt (p);
|
||||
break;
|
||||
@@ -327,6 +332,9 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg)
|
||||
btu_hcif_keypress_notif_evt (p);
|
||||
break;
|
||||
#endif ///SMP_INCLUDED == TRUE
|
||||
case HCI_LINK_SUPER_TOUT_CHANGED_EVT:
|
||||
btu_hcif_link_supv_to_changed_evt (p);
|
||||
break;
|
||||
#if L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE
|
||||
case HCI_ENHANCED_FLUSH_COMPLETE_EVT:
|
||||
btu_hcif_enhanced_flush_complete_evt ();
|
||||
@@ -565,6 +573,7 @@ static void btu_hcif_connection_comp_evt (UINT8 *p)
|
||||
btm_sco_connected (status, bda, handle, &esco_data);
|
||||
}
|
||||
#endif /* BTM_SCO_INCLUDED */
|
||||
HCI_TRACE_WARNING("hcif conn complete: hdl 0x%x, st 0x%x", handle, status);
|
||||
}
|
||||
|
||||
|
||||
@@ -621,6 +630,8 @@ static void btu_hcif_disconnection_comp_evt (UINT8 *p)
|
||||
|
||||
handle = HCID_GET_HANDLE (handle);
|
||||
|
||||
HCI_TRACE_WARNING("hcif disc complete: hdl 0x%x, rsn 0x%x", handle, reason);
|
||||
|
||||
#if BTM_SCO_INCLUDED == TRUE
|
||||
/* If L2CAP doesn't know about it, send it to SCO */
|
||||
if (!l2c_link_hci_disc_comp (handle, reason)) {
|
||||
@@ -1411,6 +1422,8 @@ static void btu_hcif_mode_change_evt (UINT8 *p)
|
||||
btm_sco_chk_pend_unpark (status, handle);
|
||||
#endif
|
||||
btm_pm_proc_mode_change (status, handle, current_mode, interval);
|
||||
HCI_TRACE_WARNING("hcif mode change: hdl 0x%x, mode %d, intv %d, status 0x%x",
|
||||
handle, current_mode, interval, status);
|
||||
|
||||
/*
|
||||
#if (HID_DEV_INCLUDED == TRUE) && (HID_DEV_PM_INCLUDED == TRUE)
|
||||
@@ -1433,6 +1446,26 @@ static void btu_hcif_ssr_evt (UINT8 *p, UINT16 evt_len)
|
||||
{
|
||||
btm_pm_proc_ssr_evt(p, evt_len);
|
||||
}
|
||||
#else
|
||||
static void btu_hcif_ssr_evt_dump (UINT8 *p, UINT16 evt_len)
|
||||
{
|
||||
UINT8 status;
|
||||
UINT16 handle;
|
||||
UINT16 max_tx_lat;
|
||||
UINT16 max_rx_lat;
|
||||
|
||||
STREAM_TO_UINT8 (status, p);
|
||||
STREAM_TO_UINT16 (handle, p);
|
||||
STREAM_TO_UINT16 (max_tx_lat, p);
|
||||
STREAM_TO_UINT16 (max_rx_lat, p);
|
||||
|
||||
UNUSED(status);
|
||||
UNUSED(handle);
|
||||
UNUSED(max_tx_lat);
|
||||
UNUSED(max_rx_lat);
|
||||
|
||||
HCI_TRACE_WARNING("hcif ssr evt: st 0x%x, hdl 0x%x, tx_lat %d rx_lat %d", status, handle, max_tx_lat, max_rx_lat);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -1777,6 +1810,30 @@ static void btu_hcif_simple_pair_complete_evt (UINT8 *p)
|
||||
btm_simple_pair_complete(p);
|
||||
}
|
||||
#endif ///SMP_INCLUDED == TRUE
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btu_hcif_link_supv_to_changed_evt
|
||||
**
|
||||
** Description Process event HCI_LINK_SUPER_TOUT_CHANGED_EVT
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void btu_hcif_link_supv_to_changed_evt (UINT8 *p)
|
||||
{
|
||||
UINT16 handle;
|
||||
UINT16 supv_to;
|
||||
|
||||
STREAM_TO_UINT16(handle, p);
|
||||
STREAM_TO_UINT16(supv_to, p);
|
||||
|
||||
UNUSED(handle);
|
||||
UNUSED(supv_to);
|
||||
|
||||
HCI_TRACE_WARNING("hcif link supv_to changed: hdl 0x%x, supv_to %d", handle, supv_to);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btu_hcif_enhanced_flush_complete_evt
|
||||
|
||||
@@ -312,6 +312,12 @@ BT_HDR *attp_build_value_cmd (UINT16 payload_size, UINT8 op_code, UINT16 handle,
|
||||
p_buf->len += 2;
|
||||
}
|
||||
|
||||
if(payload_size < GATT_DEF_BLE_MTU_SIZE || payload_size > GATT_MAX_MTU_SIZE) {
|
||||
GATT_TRACE_ERROR("invalid payload_size %d", payload_size);
|
||||
osi_free(p_buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (len > 0 && p_data != NULL) {
|
||||
/* ensure data not exceed MTU size */
|
||||
if (payload_size - p_buf->len < len) {
|
||||
|
||||
@@ -583,6 +583,11 @@ tGATT_STATUS GATTS_HandleValueIndication (UINT16 conn_id, UINT16 attr_handle, U
|
||||
return (tGATT_STATUS) GATT_INVALID_CONN_ID;
|
||||
}
|
||||
|
||||
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
|
||||
GATT_TRACE_ERROR("connection not established\n");
|
||||
return GATT_WRONG_STATE;
|
||||
}
|
||||
|
||||
if (! GATT_HANDLE_IS_VALID (attr_handle)) {
|
||||
return GATT_ILLEGAL_PARAMETER;
|
||||
}
|
||||
@@ -650,6 +655,11 @@ tGATT_STATUS GATTS_HandleValueNotification (UINT16 conn_id, UINT16 attr_handle,
|
||||
return (tGATT_STATUS) GATT_INVALID_CONN_ID;
|
||||
}
|
||||
|
||||
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
|
||||
GATT_TRACE_ERROR("connection not established\n");
|
||||
return GATT_WRONG_STATE;
|
||||
}
|
||||
|
||||
if (GATT_HANDLE_IS_VALID (attr_handle)) {
|
||||
notif.handle = attr_handle;
|
||||
notif.len = val_len;
|
||||
@@ -697,6 +707,11 @@ tGATT_STATUS GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id,
|
||||
return (tGATT_STATUS) GATT_INVALID_CONN_ID;
|
||||
}
|
||||
|
||||
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
|
||||
GATT_TRACE_ERROR("connection not established\n");
|
||||
return GATT_WRONG_STATE;
|
||||
}
|
||||
|
||||
if (p_tcb->sr_cmd.trans_id != trans_id) {
|
||||
GATT_TRACE_ERROR ("GATTS_SendRsp conn_id: %u waiting for op_code = %02x\n",
|
||||
conn_id, p_tcb->sr_cmd.op_code);
|
||||
@@ -818,6 +833,11 @@ tGATT_STATUS GATTC_ConfigureMTU (UINT16 conn_id)
|
||||
return GATT_ILLEGAL_PARAMETER;
|
||||
}
|
||||
|
||||
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
|
||||
GATT_TRACE_ERROR("connection not established\n");
|
||||
return GATT_ERROR;
|
||||
}
|
||||
|
||||
/* Validate that the link is BLE, not BR/EDR */
|
||||
if (p_tcb->transport != BT_TRANSPORT_LE) {
|
||||
return GATT_ERROR;
|
||||
@@ -870,6 +890,10 @@ tGATT_STATUS GATTC_Discover (UINT16 conn_id, tGATT_DISC_TYPE disc_type,
|
||||
return GATT_ILLEGAL_PARAMETER;
|
||||
}
|
||||
|
||||
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
|
||||
GATT_TRACE_ERROR("connection not established\n");
|
||||
return GATT_ERROR;
|
||||
}
|
||||
|
||||
if (gatt_is_clcb_allocated(conn_id)) {
|
||||
GATT_TRACE_ERROR("GATTC_Discover GATT_BUSY conn_id = %d", conn_id);
|
||||
@@ -932,6 +956,11 @@ tGATT_STATUS GATTC_Read (UINT16 conn_id, tGATT_READ_TYPE type, tGATT_READ_PARAM
|
||||
return GATT_ILLEGAL_PARAMETER;
|
||||
}
|
||||
|
||||
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
|
||||
GATT_TRACE_ERROR("connection not established\n");
|
||||
return GATT_ERROR;
|
||||
}
|
||||
|
||||
if (gatt_is_clcb_allocated(conn_id)) {
|
||||
GATT_TRACE_ERROR("GATTC_Read GATT_BUSY conn_id = %d", conn_id);
|
||||
return GATT_BUSY;
|
||||
@@ -1010,6 +1039,11 @@ tGATT_STATUS GATTC_Write (UINT16 conn_id, tGATT_WRITE_TYPE type, tGATT_VALUE *p_
|
||||
return GATT_ILLEGAL_PARAMETER;
|
||||
}
|
||||
|
||||
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
|
||||
GATT_TRACE_ERROR("connection not established\n");
|
||||
return GATT_ERROR;
|
||||
}
|
||||
|
||||
if (gatt_is_clcb_allocated(conn_id)) {
|
||||
GATT_TRACE_ERROR("GATTC_Write GATT_BUSY conn_id = %d", conn_id);
|
||||
return GATT_BUSY;
|
||||
@@ -1076,6 +1110,11 @@ tGATT_STATUS GATTC_ExecuteWrite (UINT16 conn_id, BOOLEAN is_execute)
|
||||
return GATT_ILLEGAL_PARAMETER;
|
||||
}
|
||||
|
||||
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
|
||||
GATT_TRACE_ERROR("connection not established\n");
|
||||
return GATT_ERROR;
|
||||
}
|
||||
|
||||
if (gatt_is_clcb_allocated(conn_id)) {
|
||||
GATT_TRACE_ERROR("GATTC_Write GATT_BUSY conn_id = %d", conn_id);
|
||||
return GATT_BUSY;
|
||||
|
||||
@@ -896,6 +896,26 @@ BOOLEAN gatt_is_bda_connected(BD_ADDR bda)
|
||||
return connected;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatt_check_connection_state_by_tcb
|
||||
**
|
||||
** Description
|
||||
**
|
||||
** Returns TRUE if connected. Otherwise connection not established.
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN gatt_check_connection_state_by_tcb(tGATT_TCB *p_tcb)
|
||||
{
|
||||
BOOLEAN connected = FALSE;
|
||||
|
||||
if(p_tcb && gatt_get_ch_state(p_tcb) == GATT_CH_OPEN) {
|
||||
connected = TRUE;
|
||||
}
|
||||
|
||||
return connected;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatt_find_i_tcb_by_addr
|
||||
|
||||
@@ -751,6 +751,8 @@ extern tGATT_STATUS gatts_read_attr_perm_check(tGATT_SVC_DB *p_db, BOOLEAN is_lo
|
||||
extern void gatts_update_srv_list_elem(UINT8 i_sreg, UINT16 handle, BOOLEAN is_primary);
|
||||
extern tBT_UUID *gatts_get_service_uuid (tGATT_SVC_DB *p_db);
|
||||
|
||||
extern BOOLEAN gatt_check_connection_state_by_tcb(tGATT_TCB *p_tcb);
|
||||
|
||||
extern void gatt_reset_bgdev_list(void);
|
||||
extern uint16_t gatt_get_local_mtu(void);
|
||||
extern void gatt_set_local_mtu(uint16_t mtu);
|
||||
|
||||
@@ -191,6 +191,7 @@ BOOLEAN btsnd_hcic_disconnect (UINT16 handle, UINT8 reason)
|
||||
UINT8_TO_STREAM (pp, reason);
|
||||
|
||||
btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
|
||||
HCI_TRACE_WARNING("hci cmd send: disconnect: hdl 0x%x, rsn:0x%x", handle, reason);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
@@ -776,6 +777,8 @@ BOOLEAN btsnd_hcic_sniff_mode (UINT16 handle, UINT16 max_sniff_period,
|
||||
UINT16_TO_STREAM (pp, sniff_timeout);
|
||||
|
||||
btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
|
||||
HCI_TRACE_WARNING("hci cmd send: sniff: hdl 0x%x, intv(%d %d)",
|
||||
handle, min_sniff_period, max_sniff_period);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
@@ -799,6 +802,7 @@ BOOLEAN btsnd_hcic_exit_sniff_mode (UINT16 handle)
|
||||
UINT16_TO_STREAM (pp, handle);
|
||||
|
||||
btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
|
||||
HCI_TRACE_WARNING("hci cmd send: unsniff: hdl 0x%x", handle);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -2331,6 +2331,13 @@ void l2ble_update_att_acl_pkt_num(UINT8 type, tl2c_buff_param_t *param)
|
||||
xSemaphoreGive(buff_semaphore);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
|
||||
L2CAP_TRACE_ERROR("connection not established\n");
|
||||
xSemaphoreGive(buff_semaphore);
|
||||
break;
|
||||
}
|
||||
|
||||
tL2C_LCB * p_lcb = l2cu_find_lcb_by_bd_addr (p_tcb->peer_bda, BT_TRANSPORT_LE);
|
||||
if (p_lcb == NULL){
|
||||
L2CAP_TRACE_ERROR("%s not found p_lcb", __func__);
|
||||
|
||||
@@ -51,7 +51,8 @@ idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS ${includes}
|
||||
PRIV_INCLUDE_DIRS "include/driver"
|
||||
PRIV_REQUIRES efuse esp_timer esp_ipc
|
||||
REQUIRES esp_ringbuf freertos soc) #cannot totally hide soc headers, since there are a lot arguments in the driver are chip-dependent
|
||||
REQUIRES esp_ringbuf freertos soc #cannot totally hide soc headers, since there are a lot arguments in the driver are chip-dependent
|
||||
LDFRAGMENTS linker.lf)
|
||||
|
||||
# uses C11 atomic feature
|
||||
set_source_files_properties(spi_master.c PROPERTIES COMPILE_FLAGS -std=gnu11)
|
||||
|
||||
@@ -92,6 +92,48 @@ menu "Driver configurations"
|
||||
- Alert logging (i.e., setting of the TWAI_ALERT_AND_LOG flag)
|
||||
will have no effect.
|
||||
|
||||
config TWAI_ERRATA_FIX_BUS_OFF_REC
|
||||
bool "Add SW workaround for REC change during bus-off"
|
||||
depends on IDF_TARGET_ESP32
|
||||
default n
|
||||
help
|
||||
When the bus-off condition is reached, the REC should be reset to 0 and frozen (via LOM) by the
|
||||
driver's ISR. However on the ESP32, there is an edge case where the REC will increase before the
|
||||
driver's ISR can respond in time (e.g., due to the rapid occurrence of bus errors), thus causing the
|
||||
REC to be non-zero after bus-off. A non-zero REC can prevent bus-off recovery as the bus-off recovery
|
||||
condition is that both TEC and REC become 0. Enabling this option will add a workaround in the driver
|
||||
to forcibly reset REC to zero on reaching bus-off.
|
||||
|
||||
config TWAI_ERRATA_FIX_TX_INTR_LOST
|
||||
bool "Add SW workaround for TX interrupt lost errata"
|
||||
depends on IDF_TARGET_ESP32
|
||||
default n
|
||||
help
|
||||
On the ESP32, when a transmit interrupt occurs, and interrupt register is read on the same APB clock
|
||||
cycle, the transmit interrupt could be lost. Enabling this option will add a workaround that checks the
|
||||
transmit buffer status bit to recover any lost transmit interrupt.
|
||||
|
||||
config TWAI_ERRATA_FIX_RX_FRAME_INVALID
|
||||
bool "Add SW workaround for invalid RX frame errata"
|
||||
depends on IDF_TARGET_ESP32
|
||||
default n
|
||||
help
|
||||
On the ESP32, when receiving a data or remote frame, if a bus error occurs in the data or CRC field,
|
||||
the data of the next received frame could be invalid. Enabling this option will add a workaround that
|
||||
will reset the peripheral on detection of this errata condition. Note that if a frame is transmitted on
|
||||
the bus whilst the reset is ongoing, the message will not be receive by the peripheral sent on the bus
|
||||
during the reset, the message will be lost.
|
||||
|
||||
config TWAI_ERRATA_FIX_RX_FIFO_CORRUPT
|
||||
bool "Add SW workaround for RX FIFO corruption errata"
|
||||
depends on IDF_TARGET_ESP32
|
||||
default n
|
||||
help
|
||||
On the ESP32, when the RX FIFO overruns and the RX message counter maxes out at 64 messages, the entire
|
||||
RX FIFO is no longer recoverable. Enabling this option will add a workaround that resets the peripheral
|
||||
on detection of this errata condition. Note that if a frame is being sent on the bus during the reset
|
||||
bus during the reset, the message will be lost.
|
||||
|
||||
endmenu # TWAI Configuration
|
||||
|
||||
menu "UART configuration"
|
||||
|
||||
@@ -289,6 +289,10 @@ esp_err_t touch_pad_config(touch_pad_t touch_num, uint16_t threshold)
|
||||
|
||||
esp_err_t touch_pad_init(void)
|
||||
{
|
||||
#ifdef CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2
|
||||
ESP_LOGE(TOUCH_TAG, "Touch Pad can't work because it provides current to external XTAL");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
#endif // CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2
|
||||
if (rtc_touch_mux == NULL) {
|
||||
rtc_touch_mux = xSemaphoreCreateMutex();
|
||||
}
|
||||
|
||||
@@ -318,6 +318,14 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
p_i2s_obj[i2s_num]->sample_rate = rate;
|
||||
|
||||
/**
|
||||
* Due to hardware issue, bck division on ESP32/ESP32-S2 should be greater than 8 in slave mode
|
||||
* So the factor need to be an appropriate value
|
||||
*/
|
||||
if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_SLAVE)) {
|
||||
factor = 16 * bits;
|
||||
}
|
||||
double clkmdiv = (double)I2S_BASE_CLK / (rate * factor);
|
||||
|
||||
if (clkmdiv > 256) {
|
||||
@@ -498,7 +506,7 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg)
|
||||
//Avoid spurious interrupt
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
i2s_event_t i2s_event;
|
||||
int dummy;
|
||||
|
||||
@@ -917,7 +925,7 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config,
|
||||
}
|
||||
memset(p_i2s_obj[i2s_num], 0, sizeof(i2s_obj_t));
|
||||
|
||||
portMUX_TYPE i2s_spinlock_unlocked[1] = {portMUX_INITIALIZER_UNLOCKED};
|
||||
portMUX_TYPE i2s_spinlock_unlocked[1] = {portMUX_INITIALIZER_UNLOCKED};
|
||||
for (int x = 0; x < I2S_NUM_MAX; x++) {
|
||||
i2s_spinlock[x] = i2s_spinlock_unlocked[0];
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ esp_err_t gpio_set_intr_type(gpio_num_t gpio_num, gpio_int_type_t intr_type);
|
||||
/**
|
||||
* @brief Enable GPIO module interrupt signal
|
||||
*
|
||||
* @note Please do not use the interrupt of GPIO36 and GPIO39 when using ADC or Wi-Fi with sleep mode enabled.
|
||||
* @note Please do not use the interrupt of GPIO36 and GPIO39 when using ADC or Wi-Fi and Bluetooth with sleep mode enabled.
|
||||
* Please refer to the comments of `adc1_get_raw`.
|
||||
* Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue.
|
||||
* As a workaround, call adc_power_acquire() in the app. This will result in higher power consumption (by ~1mA),
|
||||
|
||||
@@ -61,6 +61,7 @@ esp_err_t ledc_timer_config(const ledc_timer_config_t* timer_conf);
|
||||
* @brief LEDC update channel parameters
|
||||
* @note Call this function to activate the LEDC updated parameters.
|
||||
* After ledc_set_duty, we need to call this function to update the settings.
|
||||
* And the new LEDC parameters don't take effect until the next PWM cycle.
|
||||
* @note ledc_set_duty, ledc_set_duty_with_hpoint and ledc_update_duty are not thread-safe, do not call these functions to
|
||||
* control one LEDC channel in different tasks at the same time.
|
||||
* A thread-safe version of API is ledc_set_duty_and_update
|
||||
@@ -178,6 +179,9 @@ esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t
|
||||
|
||||
/**
|
||||
* @brief LEDC get duty
|
||||
* This function returns the duty at the present PWM cycle.
|
||||
* You shouldn't expect the function to return the new duty in the same cycle of calling ledc_update_duty,
|
||||
* because duty update doesn't take effect until the next cycle.
|
||||
*
|
||||
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
|
||||
* @param channel LEDC channel (0-7), select from ledc_channel_t
|
||||
@@ -360,7 +364,8 @@ void ledc_fade_func_uninstall(void);
|
||||
* Other duty operations will have to wait until the fade operation has finished.
|
||||
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
|
||||
* @param channel LEDC channel number
|
||||
* @param fade_mode Whether to block until fading done.
|
||||
* @param fade_mode Whether to block until fading done. See ledc_types.h ledc_fade_mode_t for more info.
|
||||
* Note that this function will not return until fading to the target duty if LEDC_FADE_WAIT_DONE mode is selected.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
|
||||
@@ -133,7 +133,7 @@ esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *
|
||||
* @param host_id SPI peripheral to free
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG if parameter is invalid
|
||||
* - ESP_ERR_INVALID_STATE if not all devices on the bus are freed
|
||||
* - ESP_ERR_INVALID_STATE if bus hasn't been initialized before, or not all devices on the bus are freed
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t spi_bus_free(spi_host_device_t host_id);
|
||||
|
||||
@@ -28,6 +28,7 @@ extern "C" {
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_NO_MEM Touch pad init error
|
||||
* - ESP_ERR_NOT_SUPPORTED Touch pad is providing current to external XTAL
|
||||
*/
|
||||
esp_err_t touch_pad_init(void);
|
||||
|
||||
|
||||
@@ -40,9 +40,9 @@ extern "C" {
|
||||
* configured. The other members of the general configuration structure are
|
||||
* assigned default values.
|
||||
*/
|
||||
#define TWAI_GENERAL_CONFIG_DEFAULT(tx_io_num, rx_io_num, op_mode) {.mode = op_mode, .tx_io = tx_io_num, .rx_io = rx_io_num, \
|
||||
.clkout_io = TWAI_IO_UNUSED, .bus_off_io = TWAI_IO_UNUSED, \
|
||||
.tx_queue_len = 5, .rx_queue_len = 5, \
|
||||
#define TWAI_GENERAL_CONFIG_DEFAULT(tx_io_num, rx_io_num, op_mode) {.mode = op_mode, .tx_io = tx_io_num, .rx_io = rx_io_num, \
|
||||
.clkout_io = TWAI_IO_UNUSED, .bus_off_io = TWAI_IO_UNUSED, \
|
||||
.tx_queue_len = 5, .rx_queue_len = 5, \
|
||||
.alerts_enabled = TWAI_ALERT_NONE, .clkout_divider = 0, \
|
||||
.intr_flags = ESP_INTR_FLAG_LEVEL1}
|
||||
|
||||
@@ -56,22 +56,25 @@ extern "C" {
|
||||
* @note The TWAI_ALERT_AND_LOG flag is not an actual alert, but will configure
|
||||
* the TWAI driver to log to UART when an enabled alert occurs.
|
||||
*/
|
||||
#define TWAI_ALERT_TX_IDLE 0x0001 /**< Alert(1): No more messages to transmit */
|
||||
#define TWAI_ALERT_TX_SUCCESS 0x0002 /**< Alert(2): The previous transmission was successful */
|
||||
#define TWAI_ALERT_BELOW_ERR_WARN 0x0004 /**< Alert(4): Both error counters have dropped below error warning limit */
|
||||
#define TWAI_ALERT_ERR_ACTIVE 0x0008 /**< Alert(8): TWAI controller has become error active */
|
||||
#define TWAI_ALERT_RECOVERY_IN_PROGRESS 0x0010 /**< Alert(16): TWAI controller is undergoing bus recovery */
|
||||
#define TWAI_ALERT_BUS_RECOVERED 0x0020 /**< Alert(32): TWAI controller has successfully completed bus recovery */
|
||||
#define TWAI_ALERT_ARB_LOST 0x0040 /**< Alert(64): The previous transmission lost arbitration */
|
||||
#define TWAI_ALERT_ABOVE_ERR_WARN 0x0080 /**< Alert(128): One of the error counters have exceeded the error warning limit */
|
||||
#define TWAI_ALERT_BUS_ERROR 0x0100 /**< Alert(256): A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus */
|
||||
#define TWAI_ALERT_TX_FAILED 0x0200 /**< Alert(512): The previous transmission has failed (for single shot transmission) */
|
||||
#define TWAI_ALERT_RX_QUEUE_FULL 0x0400 /**< Alert(1024): The RX queue is full causing a frame to be lost */
|
||||
#define TWAI_ALERT_ERR_PASS 0x0800 /**< Alert(2048): TWAI controller has become error passive */
|
||||
#define TWAI_ALERT_BUS_OFF 0x1000 /**< Alert(4096): Bus-off condition occurred. TWAI controller can no longer influence bus */
|
||||
#define TWAI_ALERT_ALL 0x1FFF /**< Bit mask to enable all alerts during configuration */
|
||||
#define TWAI_ALERT_NONE 0x0000 /**< Bit mask to disable all alerts during configuration */
|
||||
#define TWAI_ALERT_AND_LOG 0x2000 /**< Bit mask to enable alerts to also be logged when they occur. Note that logging from the ISR is disabled if CONFIG_TWAI_ISR_IN_IRAM is enabled (see docs). */
|
||||
#define TWAI_ALERT_TX_IDLE 0x00000001 /**< Alert(1): No more messages to transmit */
|
||||
#define TWAI_ALERT_TX_SUCCESS 0x00000002 /**< Alert(2): The previous transmission was successful */
|
||||
#define TWAI_ALERT_BELOW_ERR_WARN 0x00000004 /**< Alert(4): Both error counters have dropped below error warning limit */
|
||||
#define TWAI_ALERT_ERR_ACTIVE 0x00000008 /**< Alert(8): TWAI controller has become error active */
|
||||
#define TWAI_ALERT_RECOVERY_IN_PROGRESS 0x00000010 /**< Alert(16): TWAI controller is undergoing bus recovery */
|
||||
#define TWAI_ALERT_BUS_RECOVERED 0x00000020 /**< Alert(32): TWAI controller has successfully completed bus recovery */
|
||||
#define TWAI_ALERT_ARB_LOST 0x00000040 /**< Alert(64): The previous transmission lost arbitration */
|
||||
#define TWAI_ALERT_ABOVE_ERR_WARN 0x00000080 /**< Alert(128): One of the error counters have exceeded the error warning limit */
|
||||
#define TWAI_ALERT_BUS_ERROR 0x00000100 /**< Alert(256): A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus */
|
||||
#define TWAI_ALERT_TX_FAILED 0x00000200 /**< Alert(512): The previous transmission has failed (for single shot transmission) */
|
||||
#define TWAI_ALERT_RX_QUEUE_FULL 0x00000400 /**< Alert(1024): The RX queue is full causing a frame to be lost */
|
||||
#define TWAI_ALERT_ERR_PASS 0x00000800 /**< Alert(2048): TWAI controller has become error passive */
|
||||
#define TWAI_ALERT_BUS_OFF 0x00001000 /**< Alert(4096): Bus-off condition occurred. TWAI controller can no longer influence bus */
|
||||
#define TWAI_ALERT_RX_FIFO_OVERRUN 0x00002000 /**< Alert(8192): An RX FIFO overrun has occurred */
|
||||
#define TWAI_ALERT_TX_RETRIED 0x00004000 /**< Alert(16384): An message transmission was cancelled and retried due to an errata workaround */
|
||||
#define TWAI_ALERT_PERIPH_RESET 0x00008000 /**< Alert(32768): The TWAI controller was reset */
|
||||
#define TWAI_ALERT_ALL 0x0000FFFF /**< Bit mask to enable all alerts during configuration */
|
||||
#define TWAI_ALERT_NONE 0x00000000 /**< Bit mask to disable all alerts during configuration */
|
||||
#define TWAI_ALERT_AND_LOG 0x00010000 /**< Bit mask to enable alerts to also be logged when they occur. Note that logging from the ISR is disabled if CONFIG_TWAI_ISR_IN_IRAM is enabled (see docs). */
|
||||
|
||||
/** @endcond */
|
||||
|
||||
@@ -117,7 +120,8 @@ typedef struct {
|
||||
uint32_t tx_error_counter; /**< Current value of Transmit Error Counter */
|
||||
uint32_t rx_error_counter; /**< Current value of Receive Error Counter */
|
||||
uint32_t tx_failed_count; /**< Number of messages that failed transmissions */
|
||||
uint32_t rx_missed_count; /**< Number of messages that were lost due to a full RX queue */
|
||||
uint32_t rx_missed_count; /**< Number of messages that were lost due to a full RX queue (or errata workaround if enabled) */
|
||||
uint32_t rx_overrun_count; /**< Number of messages that were lost due to a RX FIFO overrun */
|
||||
uint32_t arb_lost_count; /**< Number of instances arbitration was lost */
|
||||
uint32_t bus_error_count; /**< Number of instances a bus error has occurred */
|
||||
} twai_status_info_t;
|
||||
@@ -168,9 +172,9 @@ esp_err_t twai_driver_uninstall(void);
|
||||
*
|
||||
* This function starts the TWAI driver, putting the TWAI driver into the running
|
||||
* state. This allows the TWAI driver to participate in TWAI bus activities such
|
||||
* as transmitting/receiving messages. The RX queue is reset in this function,
|
||||
* clearing any unread messages. This function can only be called when the TWAI
|
||||
* driver is in the stopped state.
|
||||
* as transmitting/receiving messages. The TX and RX queue are reset in this function,
|
||||
* clearing any messages that are unread or pending transmission. This function
|
||||
* can only be called when the TWAI driver is in the stopped state.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: TWAI driver is now running
|
||||
|
||||
@@ -199,7 +199,7 @@ esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_
|
||||
static IRAM_ATTR esp_err_t ledc_duty_config(ledc_mode_t speed_mode, ledc_channel_t channel, int hpoint_val, int duty_val,
|
||||
ledc_duty_direction_t duty_direction, uint32_t duty_num, uint32_t duty_cycle, uint32_t duty_scale)
|
||||
{
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
portENTER_CRITICAL_SAFE(&ledc_spinlock);
|
||||
if (hpoint_val >= 0) {
|
||||
ledc_hal_set_hpoint(&(p_ledc_obj[speed_mode]->ledc_hal), channel, hpoint_val);
|
||||
}
|
||||
@@ -211,7 +211,7 @@ static IRAM_ATTR esp_err_t ledc_duty_config(ledc_mode_t speed_mode, ledc_channel
|
||||
ledc_hal_set_duty_cycle(&(p_ledc_obj[speed_mode]->ledc_hal), channel, duty_cycle);
|
||||
ledc_hal_set_duty_scale(&(p_ledc_obj[speed_mode]->ledc_hal), channel, duty_scale);
|
||||
ledc_ls_channel_update(speed_mode, channel);
|
||||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
portEXIT_CRITICAL_SAFE(&ledc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -472,8 +472,8 @@ esp_err_t ledc_set_duty_with_hpoint(ledc_mode_t speed_mode, ledc_channel_t chann
|
||||
hpoint, //uint32_t hpoint_val,
|
||||
duty, //uint32_t duty_val,
|
||||
1, //uint32_t increase,
|
||||
1, //uint32_t duty_num,
|
||||
1, //uint32_t duty_cycle,
|
||||
0, //uint32_t duty_num,
|
||||
0, //uint32_t duty_cycle,
|
||||
0 //uint32_t duty_scale
|
||||
);
|
||||
_ledc_fade_hw_release(speed_mode, channel);
|
||||
@@ -492,8 +492,8 @@ esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t
|
||||
LEDC_VAL_NO_CHANGE,
|
||||
duty, //uint32_t duty_val,
|
||||
1, //uint32_t increase,
|
||||
1, //uint32_t duty_num,
|
||||
1, //uint32_t duty_cycle,
|
||||
0, //uint32_t duty_num,
|
||||
0, //uint32_t duty_cycle,
|
||||
0 //uint32_t duty_scale
|
||||
);
|
||||
_ledc_fade_hw_release(speed_mode, channel);
|
||||
@@ -573,9 +573,9 @@ void IRAM_ATTR ledc_fade_isr(void* arg)
|
||||
ledc_calc_fade_end_channel(&intr_status, &channel);
|
||||
|
||||
// clear interrupt
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
portENTER_CRITICAL_ISR(&ledc_spinlock);
|
||||
ledc_hal_clear_fade_end_intr_status(&(p_ledc_obj[speed_mode]->ledc_hal), channel);
|
||||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
portEXIT_CRITICAL_ISR(&ledc_spinlock);
|
||||
|
||||
if (s_ledc_fade_rec[speed_mode][channel] == NULL) {
|
||||
//fade object not initialized yet.
|
||||
@@ -621,9 +621,9 @@ void IRAM_ATTR ledc_fade_isr(void* arg)
|
||||
1,
|
||||
0);
|
||||
}
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
portENTER_CRITICAL_ISR(&ledc_spinlock);
|
||||
ledc_hal_set_duty_start(&(p_ledc_obj[speed_mode]->ledc_hal), channel, true);
|
||||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
portEXIT_CRITICAL_ISR(&ledc_spinlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -763,7 +763,10 @@ static void _ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, led
|
||||
ledc_enable_intr_type(speed_mode, channel, LEDC_INTR_FADE_END);
|
||||
ledc_update_duty(speed_mode, channel);
|
||||
if (fade_mode == LEDC_FADE_WAIT_DONE) {
|
||||
xSemaphoreTake(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem, portMAX_DELAY);
|
||||
// Waiting for fade done
|
||||
_ledc_fade_hw_acquire(speed_mode, channel);
|
||||
// Release hardware to support next time fade configure
|
||||
_ledc_fade_hw_release(speed_mode, channel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -805,7 +808,6 @@ esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_f
|
||||
LEDC_CHECK(p_ledc_obj[speed_mode] != NULL, LEDC_NOT_INIT, ESP_ERR_INVALID_STATE);
|
||||
_ledc_fade_hw_acquire(speed_mode, channel);
|
||||
_ledc_fade_start(speed_mode, channel, fade_mode);
|
||||
_ledc_fade_hw_release(speed_mode, channel);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -842,14 +844,13 @@ esp_err_t ledc_set_duty_and_update(ledc_mode_t speed_mode, ledc_channel_t channe
|
||||
LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode");
|
||||
LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel");
|
||||
LEDC_ARG_CHECK(duty <= ledc_get_max_duty(speed_mode, channel), "target_duty");
|
||||
LEDC_ARG_CHECK(hpoint <= LEDC_HPOINT_VAL_MAX, "hpoint");
|
||||
LEDC_CHECK(p_ledc_obj[speed_mode] != NULL, LEDC_NOT_INIT, ESP_ERR_INVALID_STATE);
|
||||
LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK , LEDC_FADE_INIT_ERROR_STR, ESP_FAIL);
|
||||
_ledc_op_lock_acquire(speed_mode, channel);
|
||||
LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK, LEDC_FADE_INIT_ERROR_STR, ESP_FAIL);
|
||||
_ledc_fade_hw_acquire(speed_mode, channel);
|
||||
_ledc_set_fade_with_step(speed_mode, channel, duty, 0, 1);
|
||||
_ledc_fade_start(speed_mode, channel, LEDC_FADE_WAIT_DONE);
|
||||
ledc_duty_config(speed_mode, channel, hpoint, duty, 1, 0, 0, 0);
|
||||
ledc_update_duty(speed_mode, channel);
|
||||
_ledc_fade_hw_release(speed_mode, channel);
|
||||
_ledc_op_lock_release(speed_mode, channel);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -865,9 +866,6 @@ esp_err_t ledc_set_fade_time_and_start(ledc_mode_t speed_mode, ledc_channel_t ch
|
||||
_ledc_fade_hw_acquire(speed_mode, channel);
|
||||
_ledc_set_fade_with_time(speed_mode, channel, target_duty, max_fade_time_ms);
|
||||
_ledc_fade_start(speed_mode, channel, fade_mode);
|
||||
if (fade_mode == LEDC_FADE_WAIT_DONE) {
|
||||
_ledc_fade_hw_release(speed_mode, channel);
|
||||
}
|
||||
_ledc_op_lock_release(speed_mode, channel);
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -886,9 +884,6 @@ esp_err_t ledc_set_fade_step_and_start(ledc_mode_t speed_mode, ledc_channel_t ch
|
||||
_ledc_fade_hw_acquire(speed_mode, channel);
|
||||
_ledc_set_fade_with_step(speed_mode, channel, target_duty, scale, cycle_num);
|
||||
_ledc_fade_start(speed_mode, channel, fade_mode);
|
||||
if (fade_mode == LEDC_FADE_WAIT_DONE) {
|
||||
_ledc_fade_hw_release(speed_mode, channel);
|
||||
}
|
||||
_ledc_op_lock_release(speed_mode, channel);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
9
components/driver/linker.lf
Normal file
9
components/driver/linker.lf
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
[mapping:driver]
|
||||
archive: libdriver.a
|
||||
entries:
|
||||
# TWAI workarounds that require periph_module_reset() won't work if cache is disabled due to the use of switch jump
|
||||
# tables in periph_module_reset(). We prevent any part of periph_module_reset() (either text or RO data) from being
|
||||
# placed in flash.
|
||||
if TWAI_ISR_IN_IRAM = y && (TWAI_ERRATA_FIX_RX_FRAME_INVALID = y || TWAI_ERRATA_FIX_RX_FIFO_CORRUPT = y):
|
||||
periph_ctrl: periph_module_reset (noflash)
|
||||
@@ -13,6 +13,7 @@
|
||||
// limitations under the License.
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "hal/clk_gate_ll.h"
|
||||
#include "esp_attr.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
|
||||
static portMUX_TYPE periph_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
@@ -661,7 +661,8 @@ static esp_err_t recv_flush_data(void)
|
||||
static void sdio_intr_recv(void* arg)
|
||||
{
|
||||
portBASE_TYPE yield = 0;
|
||||
while (sdio_slave_hal_recv_done(context.hal)) {
|
||||
bool triggered = sdio_slave_hal_recv_done(context.hal);
|
||||
while (triggered) {
|
||||
portENTER_CRITICAL_ISR(&context.recv_spinlock);
|
||||
bool has_next_item = sdio_slave_hal_recv_has_next_item(context.hal);
|
||||
portEXIT_CRITICAL_ISR(&context.recv_spinlock);
|
||||
@@ -670,8 +671,9 @@ static void sdio_intr_recv(void* arg)
|
||||
xSemaphoreGiveFromISR(context.recv_event, &yield);
|
||||
continue; //check the linked list again skip the interrupt checking
|
||||
}
|
||||
// if no more items on the list, go back and check again the interrupt,
|
||||
// if no more items on the list, check the interrupt again,
|
||||
// will loop until the interrupt bit is kept cleared.
|
||||
triggered = sdio_slave_hal_recv_done(context.hal);
|
||||
}
|
||||
if (yield) portYIELD_FROM_ISR();
|
||||
}
|
||||
|
||||
@@ -567,6 +567,10 @@ const spi_bus_attr_t* spi_bus_get_attr(spi_host_device_t host_id)
|
||||
|
||||
esp_err_t spi_bus_free(spi_host_device_t host_id)
|
||||
{
|
||||
if (bus_ctx[host_id] == NULL) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
esp_err_t err = ESP_OK;
|
||||
spicommon_bus_context_t* ctx = bus_ctx[host_id];
|
||||
spi_bus_attr_t* bus_attr = &ctx->bus_attr;
|
||||
|
||||
@@ -662,8 +662,8 @@ static SPI_MASTER_ISR_ATTR esp_err_t check_trans_valid(spi_device_handle_t handl
|
||||
spi_host_t *host = handle->host;
|
||||
const spi_bus_attr_t* bus_attr = host->bus_attr;
|
||||
//check transmission length
|
||||
SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_RXDATA)==0 ||trans_desc->rxlength <= 32, "rxdata transfer > 32 bits without configured DMA", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_TXDATA)==0 ||trans_desc->length <= 32, "txdata transfer > 32 bits without configured DMA", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_RXDATA)==0 || trans_desc->rxlength <= 32, "SPI_TRANS_USE_RXDATA only available for rxdata transfer <= 32 bits", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_TXDATA)==0 || trans_desc->length <= 32, "SPI_TRANS_USE_TXDATA only available for txdata transfer <= 32 bits", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(trans_desc->length <= bus_attr->max_transfer_sz*8, "txdata transfer > host maximum", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(trans_desc->rxlength <= bus_attr->max_transfer_sz*8, "rxdata transfer > host maximum", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK((handle->cfg.flags & SPI_DEVICE_HALFDUPLEX) || trans_desc->rxlength <= trans_desc->length, "rx length > tx length in full duplex mode", ESP_ERR_INVALID_ARG);
|
||||
|
||||
@@ -728,11 +728,11 @@ TEST_CASE("GPIO ISR service test", "[gpio][ignore]")
|
||||
{
|
||||
const int test_io18 = GPIO_NUM_18;
|
||||
const int test_io19 = GPIO_NUM_19;
|
||||
static gpio_isr_param_t io18_param = {
|
||||
gpio_isr_param_t io18_param = {
|
||||
.gpio_num = GPIO_NUM_18,
|
||||
.isr_cnt = 0,
|
||||
};
|
||||
static gpio_isr_param_t io19_param = {
|
||||
gpio_isr_param_t io19_param = {
|
||||
.gpio_num = GPIO_NUM_19,
|
||||
.isr_cnt = 0,
|
||||
};
|
||||
|
||||
@@ -31,6 +31,12 @@
|
||||
#define HIGHEST_LIMIT 10000
|
||||
#define LOWEST_LIMIT -10000
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
#define TEST_SPEED_MODE LEDC_HIGH_SPEED_MODE
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2
|
||||
#define TEST_SPEED_MODE LEDC_LOW_SPEED_MODE
|
||||
#endif
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2)
|
||||
//no runners
|
||||
|
||||
@@ -99,12 +105,39 @@ static void timer_frequency_test(ledc_channel_t channel, ledc_timer_bit_t timer_
|
||||
frequency_set_get(ledc_ch_config.speed_mode, ledc_ch_config.timer_sel, 9000, 9025, 5);
|
||||
}
|
||||
|
||||
static void fade_setup(void)
|
||||
{
|
||||
ledc_channel_config_t ledc_ch_config = {
|
||||
.gpio_num = PULSE_IO,
|
||||
.speed_mode = TEST_SPEED_MODE,
|
||||
.channel = LEDC_CHANNEL_0,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
.timer_sel = LEDC_TIMER_0,
|
||||
.duty = 0,
|
||||
.hpoint = 0,
|
||||
};
|
||||
ledc_timer_config_t ledc_time_config = {
|
||||
.speed_mode = TEST_SPEED_MODE,
|
||||
.duty_resolution = LEDC_TIMER_13_BIT,
|
||||
.timer_num = LEDC_TIMER_0,
|
||||
.freq_hz = 2000,
|
||||
.clk_cfg = LEDC_USE_APB_CLK,
|
||||
};
|
||||
|
||||
TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
|
||||
TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
|
||||
vTaskDelay(5 / portTICK_PERIOD_MS);
|
||||
|
||||
//initialize fade service
|
||||
TEST_ESP_OK(ledc_fade_func_install(0));
|
||||
}
|
||||
|
||||
static void timer_duty_set_get(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty)
|
||||
{
|
||||
TEST_ESP_OK(ledc_set_duty(speed_mode, channel, duty));
|
||||
TEST_ESP_OK(ledc_update_duty(speed_mode, channel));
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
TEST_ASSERT_EQUAL_INT32(ledc_get_duty(speed_mode, channel), duty);
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
TEST_ASSERT_EQUAL_INT32(duty, ledc_get_duty(speed_mode, channel));
|
||||
}
|
||||
|
||||
// use logic analyzer to view
|
||||
@@ -277,9 +310,9 @@ TEST_CASE("LEDC set and get frequency", "[ledc][test_env=UT_T1_LEDC][timeout=60]
|
||||
timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_3, LEDC_LOW_SPEED_MODE);
|
||||
}
|
||||
|
||||
// the duty need to be detected by waveform given by the logic analyzer
|
||||
// can't get it directly, so set it "ignore"
|
||||
TEST_CASE("LEDC set and get dut(with logic analyzer)", "[ledc][ignore]")
|
||||
// duty should be manually checked from the waveform using a logic analyzer
|
||||
// this test is enabled only for testting the settings
|
||||
TEST_CASE("LEDC set and get duty", "[ledc]")
|
||||
{
|
||||
ledc_timer_t timer_list[4] = {LEDC_TIMER_0, LEDC_TIMER_1, LEDC_TIMER_2, LEDC_TIMER_3};
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
@@ -331,7 +364,7 @@ TEST_CASE("LEDC timer set", "[ledc][test_env=UT_T1_LEDC]")
|
||||
count = wave_count(1000);
|
||||
TEST_ASSERT_UINT32_WITHIN(10, count, freq_get);
|
||||
|
||||
//set timer 3 as 500Hz, use APB_CLK
|
||||
//set timer 0 as 500Hz, use APB_CLK
|
||||
TEST_ESP_OK(ledc_timer_set(test_speed_mode, LEDC_TIMER_0, 5000, 13, LEDC_APB_CLK));
|
||||
TEST_ESP_OK(ledc_timer_rst(test_speed_mode, LEDC_TIMER_0));
|
||||
TEST_ASSERT_EQUAL_INT32(ledc_get_freq(test_speed_mode, LEDC_TIMER_0), 500);
|
||||
@@ -403,102 +436,111 @@ TEST_CASE("LEDC timer pause and resume", "[ledc][test_env=UT_T1_LEDC]")
|
||||
TEST_ASSERT_UINT32_WITHIN(5, count, 5000);
|
||||
}
|
||||
|
||||
TEST_CASE("LEDC fade with time(logic analyzer)", "[ledc][test_env=UT_T1_LEDC]")
|
||||
TEST_CASE("LEDC fade with time", "[ledc]")
|
||||
{
|
||||
#ifdef CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE
|
||||
return;
|
||||
#endif
|
||||
const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
|
||||
fade_setup();
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
const ledc_mode_t test_speed_mode = LEDC_HIGH_SPEED_MODE;
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2
|
||||
const ledc_mode_t test_speed_mode = LEDC_LOW_SPEED_MODE;
|
||||
#endif
|
||||
ledc_channel_config_t ledc_ch_config = {
|
||||
.gpio_num = PULSE_IO,
|
||||
.speed_mode = test_speed_mode,
|
||||
.channel = LEDC_CHANNEL_0,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
.timer_sel = LEDC_TIMER_0,
|
||||
.duty = 0,
|
||||
.hpoint = 0,
|
||||
};
|
||||
TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
|
||||
|
||||
ledc_timer_config_t ledc_time_config = {
|
||||
.speed_mode = test_speed_mode,
|
||||
.duty_resolution = LEDC_TIMER_13_BIT,
|
||||
.timer_num = LEDC_TIMER_0,
|
||||
.freq_hz = 5000,
|
||||
.clk_cfg = LEDC_USE_APB_CLK,
|
||||
};
|
||||
TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
|
||||
|
||||
//initialize fade service
|
||||
TEST_ESP_OK(ledc_fade_func_install(0));
|
||||
|
||||
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 1000));
|
||||
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 200));
|
||||
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE));
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
TEST_ASSERT_EQUAL_INT32(ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0), 4000);
|
||||
TEST_ASSERT_EQUAL_INT32(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
|
||||
|
||||
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 0, 1000));
|
||||
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 0, 200));
|
||||
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
TEST_ASSERT_EQUAL_INT32(ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0), 0);
|
||||
// duty should not be too far from initial value
|
||||
TEST_ASSERT_INT32_WITHIN(20, 4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
|
||||
vTaskDelay(210 / portTICK_PERIOD_MS);
|
||||
TEST_ASSERT_EQUAL_INT32(0, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
|
||||
|
||||
//deinitial fade service
|
||||
//deinitialize fade service
|
||||
ledc_fade_func_uninstall();
|
||||
}
|
||||
|
||||
TEST_CASE("LEDC fade with step(logic analyzer)", "[ledc][test_env=UT_T1_LEDC]")
|
||||
TEST_CASE("LEDC fade with step", "[ledc]")
|
||||
{
|
||||
#ifdef CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE
|
||||
return;
|
||||
#endif
|
||||
const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
|
||||
fade_setup();
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
const ledc_mode_t test_speed_mode = LEDC_HIGH_SPEED_MODE;
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2
|
||||
const ledc_mode_t test_speed_mode = LEDC_LOW_SPEED_MODE;
|
||||
#endif
|
||||
ledc_channel_config_t ledc_ch_config = {
|
||||
.gpio_num = PULSE_IO,
|
||||
.speed_mode = test_speed_mode,
|
||||
.channel = LEDC_CHANNEL_0,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
.timer_sel = LEDC_TIMER_0,
|
||||
.duty = 0,
|
||||
.hpoint = 0,
|
||||
};
|
||||
TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
|
||||
|
||||
ledc_timer_config_t ledc_time_config = {
|
||||
.speed_mode = test_speed_mode,
|
||||
.duty_resolution = LEDC_TIMER_13_BIT,
|
||||
.timer_num = LEDC_TIMER_0,
|
||||
.freq_hz = 5000,
|
||||
.clk_cfg = LEDC_USE_APB_CLK,
|
||||
};
|
||||
TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
|
||||
|
||||
//initialize fade service.
|
||||
TEST_ESP_OK(ledc_fade_func_install(0));
|
||||
|
||||
TEST_ESP_OK(ledc_set_fade_with_step(test_speed_mode, LEDC_CHANNEL_0, 4000, 2, 1));
|
||||
TEST_ESP_OK(ledc_set_fade_with_step(test_speed_mode, LEDC_CHANNEL_0, 4000, 4, 1));
|
||||
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE));
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
TEST_ASSERT_EQUAL_INT32(ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0), 4000);
|
||||
TEST_ASSERT_EQUAL_INT32(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
|
||||
|
||||
TEST_ESP_OK(ledc_set_fade_with_step(test_speed_mode, LEDC_CHANNEL_0, 0, 4, 2));
|
||||
TEST_ESP_OK(ledc_set_fade_with_step(test_speed_mode, LEDC_CHANNEL_0, 0, 4, 1));
|
||||
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
TEST_ASSERT_EQUAL_INT32(ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0), 0);
|
||||
// duty should not be too far from initial value
|
||||
TEST_ASSERT_INT32_WITHIN(20, 4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
|
||||
vTaskDelay(525 / portTICK_PERIOD_MS);
|
||||
TEST_ASSERT_EQUAL_INT32(0, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
|
||||
|
||||
//scaler=0 check
|
||||
TEST_ASSERT(ledc_set_fade_with_step(test_speed_mode, LEDC_CHANNEL_0, 4000, 0, 1) == ESP_ERR_INVALID_ARG);
|
||||
|
||||
//deinitial fade service
|
||||
//deinitialize fade service
|
||||
ledc_fade_func_uninstall();
|
||||
}
|
||||
|
||||
TEST_CASE("LEDC fast switching duty with fade_wait_done", "[ledc]")
|
||||
{
|
||||
const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
|
||||
fade_setup();
|
||||
|
||||
// fade function will block until fading to the target duty
|
||||
int64_t fade_start, fade_stop;
|
||||
fade_start = esp_timer_get_time();
|
||||
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 200));
|
||||
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE));
|
||||
TEST_ASSERT_EQUAL_INT32(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
|
||||
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 1000, 150));
|
||||
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE));
|
||||
TEST_ASSERT_EQUAL_INT32(1000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
|
||||
fade_stop = esp_timer_get_time();
|
||||
int time_ms = (fade_stop - fade_start) / 1000;
|
||||
TEST_ASSERT_TRUE(fabs(time_ms - 350) < 20);
|
||||
|
||||
// next duty update will not take place until last fade reaches its target duty
|
||||
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 200));
|
||||
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE));
|
||||
TEST_ASSERT_EQUAL_INT32(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
|
||||
TEST_ESP_OK(ledc_set_duty(test_speed_mode, LEDC_CHANNEL_0, 500));
|
||||
TEST_ESP_OK(ledc_update_duty(test_speed_mode, LEDC_CHANNEL_0));
|
||||
vTaskDelay(5 / portTICK_PERIOD_MS);
|
||||
TEST_ASSERT_EQUAL_INT32(500, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
|
||||
|
||||
//deinitialize fade service
|
||||
ledc_fade_func_uninstall();
|
||||
}
|
||||
|
||||
TEST_CASE("LEDC fast switching duty with fade_no_wait", "[ledc]")
|
||||
{
|
||||
const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
|
||||
fade_setup();
|
||||
|
||||
// fade function returns immediately, but next fade still needs to wait for last fade ends
|
||||
int64_t fade_start, first_fade_complete;
|
||||
fade_start = esp_timer_get_time();
|
||||
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 200));
|
||||
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));
|
||||
TEST_ASSERT_LESS_THAN(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
|
||||
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 1000, 150));
|
||||
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));
|
||||
first_fade_complete = esp_timer_get_time();
|
||||
// duty should not be too far from first fade target duty
|
||||
TEST_ASSERT_INT32_WITHIN(20, 4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
|
||||
int time_ms = (first_fade_complete - fade_start) / 1000;
|
||||
TEST_ASSERT_TRUE(fabs(time_ms - 200) < 20);
|
||||
vTaskDelay(158 / portTICK_PERIOD_MS);
|
||||
TEST_ASSERT_EQUAL_INT32(1000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
|
||||
|
||||
// next duty update will not take place until last fade reaches its target duty
|
||||
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 200));
|
||||
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));
|
||||
TEST_ASSERT_LESS_THAN(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
|
||||
TEST_ESP_OK(ledc_set_duty(test_speed_mode, LEDC_CHANNEL_0, 500));
|
||||
TEST_ESP_OK(ledc_update_duty(test_speed_mode, LEDC_CHANNEL_0));
|
||||
vTaskDelay(5 / portTICK_PERIOD_MS);
|
||||
TEST_ASSERT_EQUAL_INT32(500, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
|
||||
|
||||
//deinitialize fade service
|
||||
ledc_fade_func_uninstall();
|
||||
}
|
||||
|
||||
|
||||
@@ -843,8 +843,8 @@ TEST_CASE("Timer interrupt register", "[hw_timer]")
|
||||
// This case will check under this fix, whether the interrupt status is cleared after timer_group initialization.
|
||||
static void timer_group_test_init(void)
|
||||
{
|
||||
static const uint32_t time_ms = 100; //Alarm value 100ms.
|
||||
static const uint16_t timer_div = 10; //Timer prescaler
|
||||
static const uint32_t time_ms = 100; // Alarm value 100ms.
|
||||
static const uint16_t timer_div = TIMER_DIVIDER; // Timer prescaler
|
||||
static const uint32_t ste_val = time_ms * (TIMER_BASE_CLK / timer_div / 1000);
|
||||
timer_config_t config = {
|
||||
.divider = timer_div,
|
||||
@@ -882,11 +882,45 @@ static void timer_group_test_second_stage(void)
|
||||
{
|
||||
TEST_ASSERT_EQUAL(ESP_RST_SW, esp_reset_reason());
|
||||
timer_group_test_init();
|
||||
TEST_ASSERT_EQUAL(0, timer_group_get_intr_status_in_isr(TIMER_GROUP_0) & TIMER_INTR_T0);
|
||||
// After enable the interrupt, timer alarm should not trigger immediately
|
||||
TEST_ESP_OK(timer_enable_intr(TIMER_GROUP_0, TIMER_0));
|
||||
//After the timer_group is initialized, TIMERG0.int_raw.t0 should be cleared.
|
||||
TEST_ASSERT_EQUAL(0, timer_group_get_intr_status_in_isr(TIMER_GROUP_0) & TIMER_INTR_T0);
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_STAGES("timer_group software reset test",
|
||||
"[intr_status][intr_status = 0]",
|
||||
timer_group_test_first_stage,
|
||||
timer_group_test_second_stage);
|
||||
|
||||
"[intr_status][intr_status = 0]",
|
||||
timer_group_test_first_stage,
|
||||
timer_group_test_second_stage);
|
||||
//
|
||||
// Timer check reinitialization sequence
|
||||
//
|
||||
TEST_CASE("Timer check reinitialization sequence", "[hw_timer]")
|
||||
{
|
||||
// 1. step - install driver
|
||||
timer_group_test_init();
|
||||
// 2 - register interrupt and start timer
|
||||
TEST_ESP_OK(timer_enable_intr(TIMER_GROUP_0, TIMER_0));
|
||||
TEST_ESP_OK(timer_start(TIMER_GROUP_0, TIMER_0));
|
||||
// Do some work
|
||||
vTaskDelay(80 / portTICK_PERIOD_MS);
|
||||
// 3 - deinit timer driver
|
||||
TEST_ESP_OK(timer_deinit(TIMER_GROUP_0, TIMER_0));
|
||||
timer_config_t config = {
|
||||
.divider = TIMER_DIVIDER,
|
||||
.counter_dir = TIMER_COUNT_UP,
|
||||
.counter_en = TIMER_START,
|
||||
.alarm_en = TIMER_ALARM_EN,
|
||||
.intr_type = TIMER_INTR_LEVEL,
|
||||
.auto_reload = TIMER_AUTORELOAD_EN,
|
||||
};
|
||||
// 4 - reinstall driver
|
||||
TEST_ESP_OK(timer_init(TIMER_GROUP_0, TIMER_0, &config));
|
||||
// 5 - enable interrupt
|
||||
TEST_ESP_OK(timer_enable_intr(TIMER_GROUP_0, TIMER_0));
|
||||
vTaskDelay(30 / portTICK_PERIOD_MS);
|
||||
// The pending timer interrupt should not be triggered
|
||||
TEST_ASSERT_EQUAL(0, timer_group_get_intr_status_in_isr(TIMER_GROUP_0) & TIMER_INTR_T0);
|
||||
}
|
||||
|
||||
@@ -320,7 +320,7 @@ esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, const timer
|
||||
|
||||
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
|
||||
timer_hal_init(&(p_timer_obj[group_num][timer_num]->hal), group_num, timer_num);
|
||||
timer_hal_intr_disable(&(p_timer_obj[group_num][timer_num]->hal));
|
||||
timer_hal_reset_periph(&(p_timer_obj[group_num][timer_num]->hal));
|
||||
timer_hal_clear_intr_status(&(p_timer_obj[group_num][timer_num]->hal));
|
||||
timer_hal_set_auto_reload(&(p_timer_obj[group_num][timer_num]->hal), config->auto_reload);
|
||||
timer_hal_set_divider(&(p_timer_obj[group_num][timer_num]->hal), config->divider);
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
@@ -28,6 +27,7 @@
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "driver/twai.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/twai_periph.h"
|
||||
#include "hal/twai_hal.h"
|
||||
|
||||
@@ -57,14 +57,6 @@
|
||||
|
||||
#define DRIVER_DEFAULT_INTERRUPTS 0xE7 //Exclude data overrun (bit[3]) and brp_div (bit[4])
|
||||
|
||||
//Control flags
|
||||
#define CTRL_FLAG_STOPPED 0x001 //TWAI peripheral in stopped state
|
||||
#define CTRL_FLAG_RECOVERING 0x002 //Bus is undergoing bus recovery
|
||||
#define CTRL_FLAG_ERR_WARN 0x004 //TEC or REC is >= error warning limit
|
||||
#define CTRL_FLAG_ERR_PASSIVE 0x008 //TEC or REC is >= 128
|
||||
#define CTRL_FLAG_BUS_OFF 0x010 //Bus-off due to TEC >= 256
|
||||
#define CTRL_FLAG_TX_BUFF_OCCUPIED 0x020 //Transmit buffer is occupied
|
||||
|
||||
#define ALERT_LOG_LEVEL_WARNING TWAI_ALERT_ARB_LOST //Alerts above and including this level use ESP_LOGW
|
||||
#define ALERT_LOG_LEVEL_ERROR TWAI_ALERT_TX_FAILED //Alerts above and including this level use ESP_LOGE
|
||||
|
||||
@@ -73,9 +65,10 @@
|
||||
//Control structure for TWAI driver
|
||||
typedef struct {
|
||||
//Control and status members
|
||||
uint32_t control_flags;
|
||||
twai_state_t state;
|
||||
twai_mode_t mode;
|
||||
uint32_t rx_missed_count;
|
||||
uint32_t rx_overrun_count;
|
||||
uint32_t tx_failed_count;
|
||||
uint32_t arb_lost_count;
|
||||
uint32_t bus_error_count;
|
||||
@@ -129,102 +122,55 @@ TWAI_ISR_ATTR static void twai_alert_handler(uint32_t alert_code, int *alert_req
|
||||
ESP_EARLY_LOGI(TWAI_TAG, "Alert %d", alert_code);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif //CONFIG_TWAI_ISR_IN_IRAM
|
||||
}
|
||||
}
|
||||
|
||||
static inline void twai_handle_bus_off(int *alert_req)
|
||||
{
|
||||
//Bus-Off condition. TEC should set and held at 127, REC should be 0, reset mode entered
|
||||
TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_BUS_OFF);
|
||||
/* Note: REC is still allowed to increase during bus-off. REC > err_warn
|
||||
can prevent "bus recovery complete" interrupt from occurring. Set to
|
||||
listen only mode to freeze REC. */
|
||||
twai_hal_handle_bus_off(&twai_context);
|
||||
twai_alert_handler(TWAI_ALERT_BUS_OFF, alert_req);
|
||||
}
|
||||
|
||||
static inline void twai_handle_recovery_complete(int *alert_req)
|
||||
{
|
||||
//Bus recovery complete.
|
||||
bool recov_cplt = twai_hal_handle_bus_recov_cplt(&twai_context);
|
||||
assert(recov_cplt);
|
||||
|
||||
//Reset and set flags to the equivalent of the stopped state
|
||||
TWAI_RESET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_RECOVERING | CTRL_FLAG_ERR_WARN |
|
||||
CTRL_FLAG_ERR_PASSIVE | CTRL_FLAG_BUS_OFF |
|
||||
CTRL_FLAG_TX_BUFF_OCCUPIED);
|
||||
TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_STOPPED);
|
||||
twai_alert_handler(TWAI_ALERT_BUS_RECOVERED, alert_req);
|
||||
}
|
||||
|
||||
static inline void twai_handle_recovery_in_progress(int * alert_req)
|
||||
{
|
||||
//Bus-recovery in progress. TEC has dropped below error warning limit
|
||||
twai_alert_handler(TWAI_ALERT_RECOVERY_IN_PROGRESS, alert_req);
|
||||
}
|
||||
|
||||
static inline void twai_handle_above_ewl(int *alert_req)
|
||||
{
|
||||
//TEC or REC surpassed error warning limit
|
||||
TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_ERR_WARN);
|
||||
twai_alert_handler(TWAI_ALERT_ABOVE_ERR_WARN, alert_req);
|
||||
}
|
||||
|
||||
static inline void twai_handle_below_ewl(int *alert_req)
|
||||
{
|
||||
//TEC and REC are both below error warning
|
||||
TWAI_RESET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_ERR_WARN);
|
||||
twai_alert_handler(TWAI_ALERT_BELOW_ERR_WARN, alert_req);
|
||||
}
|
||||
|
||||
static inline void twai_handle_error_passive(int *alert_req)
|
||||
{
|
||||
//Entered error passive
|
||||
TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_ERR_PASSIVE);
|
||||
twai_alert_handler(TWAI_ALERT_ERR_PASS, alert_req);
|
||||
}
|
||||
|
||||
static inline void twai_handle_error_active(int *alert_req)
|
||||
{
|
||||
//Returned to error active
|
||||
TWAI_RESET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_ERR_PASSIVE);
|
||||
twai_alert_handler(TWAI_ALERT_ERR_ACTIVE, alert_req);
|
||||
}
|
||||
|
||||
static inline void twai_handle_bus_error(int *alert_req)
|
||||
{
|
||||
// ECC register is read to re-arm bus error interrupt. ECC is not used
|
||||
twai_hal_handle_bus_error(&twai_context);
|
||||
p_twai_obj->bus_error_count++;
|
||||
twai_alert_handler(TWAI_ALERT_BUS_ERROR, alert_req);
|
||||
}
|
||||
|
||||
static inline void twai_handle_arb_lost(int *alert_req)
|
||||
{
|
||||
//ALC register is read to re-arm arb lost interrupt. ALC is not used
|
||||
twai_hal_handle_arb_lost(&twai_context);
|
||||
p_twai_obj->arb_lost_count++;
|
||||
twai_alert_handler(TWAI_ALERT_ARB_LOST, alert_req);
|
||||
}
|
||||
|
||||
static inline void twai_handle_rx_buffer_frames(BaseType_t *task_woken, int *alert_req)
|
||||
{
|
||||
#ifdef TWAI_SUPPORTS_RX_STATUS
|
||||
uint32_t msg_count = twai_hal_get_rx_msg_count(&twai_context);
|
||||
|
||||
for (int i = 0; i < msg_count; i++) {
|
||||
for (uint32_t i = 0; i < msg_count; i++) {
|
||||
twai_hal_frame_t frame;
|
||||
twai_hal_read_rx_buffer_and_clear(&twai_context, &frame);
|
||||
//Copy frame into RX Queue
|
||||
if (xQueueSendFromISR(p_twai_obj->rx_queue, &frame, task_woken) == pdTRUE) {
|
||||
p_twai_obj->rx_msg_count++;
|
||||
} else {
|
||||
p_twai_obj->rx_missed_count++;
|
||||
twai_alert_handler(TWAI_ALERT_RX_QUEUE_FULL, alert_req);
|
||||
if (twai_hal_read_rx_buffer_and_clear(&twai_context, &frame)) {
|
||||
//Valid frame copied from RX buffer
|
||||
if (xQueueSendFromISR(p_twai_obj->rx_queue, &frame, task_woken) == pdTRUE) {
|
||||
p_twai_obj->rx_msg_count++;
|
||||
} else { //Failed to send to queue
|
||||
p_twai_obj->rx_missed_count++;
|
||||
twai_alert_handler(TWAI_ALERT_RX_QUEUE_FULL, alert_req);
|
||||
}
|
||||
} else { //Failed to read from RX buffer because message is overrun
|
||||
p_twai_obj->rx_overrun_count++;
|
||||
twai_alert_handler(TWAI_ALERT_RX_FIFO_OVERRUN, alert_req);
|
||||
}
|
||||
}
|
||||
//Todo: Add Software Filters
|
||||
//Todo: Check for data overrun of RX FIFO, then trigger alert
|
||||
#else //TWAI_SUPPORTS_RX_STATUS
|
||||
uint32_t msg_count = twai_hal_get_rx_msg_count(&twai_context);
|
||||
bool overrun = false;
|
||||
//Clear all valid RX frames
|
||||
for (int i = 0; i < msg_count; i++) {
|
||||
twai_hal_frame_t frame;
|
||||
if (twai_hal_read_rx_buffer_and_clear(&twai_context, &frame)) {
|
||||
//Valid frame copied from RX buffer
|
||||
if (xQueueSendFromISR(p_twai_obj->rx_queue, &frame, task_woken) == pdTRUE) {
|
||||
p_twai_obj->rx_msg_count++;
|
||||
} else {
|
||||
p_twai_obj->rx_missed_count++;
|
||||
twai_alert_handler(TWAI_ALERT_RX_QUEUE_FULL, alert_req);
|
||||
}
|
||||
} else {
|
||||
overrun = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//All remaining frames are treated as overrun. Clear them all
|
||||
if (overrun) {
|
||||
p_twai_obj->rx_overrun_count += twai_hal_clear_rx_fifo_overrun(&twai_context);
|
||||
twai_alert_handler(TWAI_ALERT_RX_FIFO_OVERRUN, alert_req);
|
||||
}
|
||||
#endif //TWAI_SUPPORTS_RX_STATUS
|
||||
}
|
||||
|
||||
static inline void twai_handle_tx_buffer_frame(BaseType_t *task_woken, int *alert_req)
|
||||
@@ -252,7 +198,6 @@ static inline void twai_handle_tx_buffer_frame(BaseType_t *task_woken, int *aler
|
||||
}
|
||||
} else {
|
||||
//No more frames to transmit
|
||||
TWAI_RESET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_TX_BUFF_OCCUPIED);
|
||||
twai_alert_handler(TWAI_ALERT_TX_IDLE, alert_req);
|
||||
}
|
||||
}
|
||||
@@ -261,49 +206,69 @@ TWAI_ISR_ATTR static void twai_intr_handler_main(void *arg)
|
||||
{
|
||||
BaseType_t task_woken = pdFALSE;
|
||||
int alert_req = 0;
|
||||
uint32_t event;
|
||||
uint32_t events;
|
||||
TWAI_ENTER_CRITICAL_ISR();
|
||||
if (p_twai_obj == NULL) { //Incase intr occurs whilst driver is being uninstalled
|
||||
if (p_twai_obj == NULL) { //In case intr occurs whilst driver is being uninstalled
|
||||
TWAI_EXIT_CRITICAL_ISR();
|
||||
return;
|
||||
}
|
||||
event = twai_hal_decode_interrupt_events(&twai_context, p_twai_obj->control_flags & CTRL_FLAG_RECOVERING);
|
||||
events = twai_hal_get_events(&twai_context); //Get the events that triggered the interrupt
|
||||
|
||||
if (event & TWAI_HAL_EVENT_BUS_OFF) {
|
||||
twai_handle_bus_off(&alert_req);
|
||||
#if defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || defined(CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT)
|
||||
if (events & TWAI_HAL_EVENT_NEED_PERIPH_RESET) {
|
||||
twai_hal_prepare_for_reset(&twai_context);
|
||||
periph_module_reset(PERIPH_TWAI_MODULE);
|
||||
twai_hal_recover_from_reset(&twai_context);
|
||||
p_twai_obj->rx_missed_count += twai_hal_get_reset_lost_rx_cnt(&twai_context);
|
||||
twai_alert_handler(TWAI_ALERT_PERIPH_RESET, &alert_req);
|
||||
}
|
||||
if (event & TWAI_HAL_EVENT_BUS_RECOV_CPLT) {
|
||||
twai_handle_recovery_complete(&alert_req);
|
||||
}
|
||||
if (event & TWAI_HAL_EVENT_BUS_RECOV_PROGRESS) {
|
||||
twai_handle_recovery_in_progress(&alert_req);
|
||||
}
|
||||
if (event & TWAI_HAL_EVENT_ABOVE_EWL) {
|
||||
twai_handle_above_ewl(&alert_req);
|
||||
}
|
||||
if (event & TWAI_HAL_EVENT_BELOW_EWL) {
|
||||
twai_handle_below_ewl(&alert_req);
|
||||
}
|
||||
if (event & TWAI_HAL_EVENT_ERROR_PASSIVE) {
|
||||
twai_handle_error_passive(&alert_req);
|
||||
}
|
||||
if (event & TWAI_HAL_EVENT_ERROR_ACTIVE) {
|
||||
twai_handle_error_active(&alert_req);
|
||||
}
|
||||
if (event & TWAI_HAL_EVENT_BUS_ERR) {
|
||||
twai_handle_bus_error(&alert_req);
|
||||
}
|
||||
if (event & TWAI_HAL_EVENT_ARB_LOST) {
|
||||
twai_handle_arb_lost(&alert_req);
|
||||
}
|
||||
if (event & TWAI_HAL_EVENT_RX_BUFF_FRAME) {
|
||||
#endif
|
||||
if (events & TWAI_HAL_EVENT_RX_BUFF_FRAME) {
|
||||
//Note: This event will never occur if there is a periph reset event
|
||||
twai_handle_rx_buffer_frames(&task_woken, &alert_req);
|
||||
}
|
||||
//TX command related handlers should be called last, so that other commands
|
||||
//do not overwrite the TX command related bits in the command register.
|
||||
if (event & TWAI_HAL_EVENT_TX_BUFF_FREE) {
|
||||
if (events & TWAI_HAL_EVENT_TX_BUFF_FREE) {
|
||||
twai_handle_tx_buffer_frame(&task_woken, &alert_req);
|
||||
}
|
||||
|
||||
//Handle events that only require alerting (i.e. no handler)
|
||||
if (events & TWAI_HAL_EVENT_BUS_OFF) {
|
||||
p_twai_obj->state = TWAI_STATE_BUS_OFF;
|
||||
twai_alert_handler(TWAI_ALERT_BUS_OFF, &alert_req);
|
||||
}
|
||||
if (events & TWAI_HAL_EVENT_BUS_RECOV_CPLT) {
|
||||
p_twai_obj->state = TWAI_STATE_STOPPED;
|
||||
twai_alert_handler(TWAI_ALERT_BUS_RECOVERED, &alert_req);
|
||||
}
|
||||
if (events & TWAI_HAL_EVENT_BUS_ERR) {
|
||||
p_twai_obj->bus_error_count++;
|
||||
twai_alert_handler(TWAI_ALERT_BUS_ERROR, &alert_req);
|
||||
}
|
||||
if (events & TWAI_HAL_EVENT_ARB_LOST) {
|
||||
p_twai_obj->arb_lost_count++;
|
||||
twai_alert_handler(TWAI_ALERT_ARB_LOST, &alert_req);
|
||||
}
|
||||
if (events & TWAI_HAL_EVENT_BUS_RECOV_PROGRESS) {
|
||||
//Bus-recovery in progress. TEC has dropped below error warning limit
|
||||
twai_alert_handler(TWAI_ALERT_RECOVERY_IN_PROGRESS, &alert_req);
|
||||
}
|
||||
if (events & TWAI_HAL_EVENT_ERROR_PASSIVE) {
|
||||
//Entered error passive
|
||||
twai_alert_handler(TWAI_ALERT_ERR_PASS, &alert_req);
|
||||
}
|
||||
if (events & TWAI_HAL_EVENT_ERROR_ACTIVE) {
|
||||
//Returned to error active
|
||||
twai_alert_handler(TWAI_ALERT_ERR_ACTIVE, &alert_req);
|
||||
}
|
||||
if (events & TWAI_HAL_EVENT_ABOVE_EWL) {
|
||||
//TEC or REC surpassed error warning limit
|
||||
twai_alert_handler(TWAI_ALERT_ABOVE_ERR_WARN, &alert_req);
|
||||
}
|
||||
if (events & TWAI_HAL_EVENT_BELOW_EWL) {
|
||||
//TEC and REC are both below error warning
|
||||
twai_alert_handler(TWAI_ALERT_BELOW_ERR_WARN, &alert_req);
|
||||
}
|
||||
|
||||
TWAI_EXIT_CRITICAL_ISR();
|
||||
|
||||
if (p_twai_obj->alert_semphr != NULL && alert_req) {
|
||||
@@ -335,6 +300,7 @@ static void twai_configure_gpio(gpio_num_t tx, gpio_num_t rx, gpio_num_t clkout,
|
||||
gpio_set_pull_mode(clkout, GPIO_FLOATING);
|
||||
gpio_matrix_out(clkout, TWAI_CLKOUT_IDX, false, false);
|
||||
gpio_pad_select_gpio(clkout);
|
||||
|
||||
}
|
||||
|
||||
//Configure bus status pin (Optional)
|
||||
@@ -433,6 +399,8 @@ cleanup:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ---------------------------- Public Functions ---------------------------- */
|
||||
|
||||
esp_err_t twai_driver_install(const twai_general_config_t *g_config, const twai_timing_config_t *t_config, const twai_filter_config_t *f_config)
|
||||
@@ -464,7 +432,7 @@ esp_err_t twai_driver_install(const twai_general_config_t *g_config, const twai_
|
||||
TWAI_CHECK(p_twai_obj_dummy != NULL, ESP_ERR_NO_MEM);
|
||||
|
||||
//Initialize flags and variables. All other members are already set to zero by twai_alloc_driver_obj()
|
||||
p_twai_obj_dummy->control_flags = CTRL_FLAG_STOPPED;
|
||||
p_twai_obj_dummy->state = TWAI_STATE_STOPPED;
|
||||
p_twai_obj_dummy->mode = g_config->mode;
|
||||
p_twai_obj_dummy->alerts_enabled = g_config->alerts_enabled;
|
||||
|
||||
@@ -483,7 +451,6 @@ esp_err_t twai_driver_install(const twai_general_config_t *g_config, const twai_
|
||||
bool init = twai_hal_init(&twai_context);
|
||||
assert(init);
|
||||
twai_hal_configure(&twai_context, t_config, f_config, DRIVER_DEFAULT_INTERRUPTS, g_config->clkout_divider);
|
||||
//Todo: Allow interrupt to be registered to specified CPU
|
||||
TWAI_EXIT_CRITICAL();
|
||||
|
||||
//Allocate GPIO and Interrupts
|
||||
@@ -496,7 +463,6 @@ esp_err_t twai_driver_install(const twai_general_config_t *g_config, const twai_
|
||||
return ESP_OK; //TWAI module is still in reset mode, users need to call twai_start() afterwards
|
||||
|
||||
err:
|
||||
//Free can driver object
|
||||
twai_free_driver_obj(p_twai_obj_dummy);
|
||||
return ret;
|
||||
}
|
||||
@@ -508,8 +474,7 @@ esp_err_t twai_driver_uninstall(void)
|
||||
TWAI_ENTER_CRITICAL();
|
||||
//Check state
|
||||
TWAI_CHECK_FROM_CRIT(p_twai_obj != NULL, ESP_ERR_INVALID_STATE);
|
||||
TWAI_CHECK_FROM_CRIT(p_twai_obj->control_flags & (CTRL_FLAG_STOPPED | CTRL_FLAG_BUS_OFF), ESP_ERR_INVALID_STATE);
|
||||
//Todo: Add check to see if in reset mode. //Enter reset mode to stop any TWAI bus activity
|
||||
TWAI_CHECK_FROM_CRIT(p_twai_obj->state == TWAI_STATE_STOPPED || p_twai_obj->state == TWAI_STATE_BUS_OFF, ESP_ERR_INVALID_STATE);
|
||||
//Clear registers by reading
|
||||
twai_hal_deinit(&twai_context);
|
||||
periph_module_disable(PERIPH_TWAI_MODULE); //Disable TWAI peripheral
|
||||
@@ -533,18 +498,18 @@ esp_err_t twai_start(void)
|
||||
//Check state
|
||||
TWAI_ENTER_CRITICAL();
|
||||
TWAI_CHECK_FROM_CRIT(p_twai_obj != NULL, ESP_ERR_INVALID_STATE);
|
||||
TWAI_CHECK_FROM_CRIT(p_twai_obj->control_flags & CTRL_FLAG_STOPPED, ESP_ERR_INVALID_STATE);
|
||||
TWAI_CHECK_FROM_CRIT(p_twai_obj->state == TWAI_STATE_STOPPED, ESP_ERR_INVALID_STATE);
|
||||
|
||||
//Reset RX queue, and RX message count
|
||||
//Reset RX queue, RX message count, amd TX queue
|
||||
xQueueReset(p_twai_obj->rx_queue);
|
||||
if (p_twai_obj->tx_queue != NULL) {
|
||||
xQueueReset(p_twai_obj->tx_queue);
|
||||
}
|
||||
p_twai_obj->rx_msg_count = 0;
|
||||
//Todo: Add assert to see if in reset mode. //Should already be in bus-off mode, set again to make sure
|
||||
p_twai_obj->tx_msg_count = 0;
|
||||
twai_hal_start(&twai_context, p_twai_obj->mode);
|
||||
|
||||
//Currently in listen only mode, need to set to mode specified by configuration
|
||||
bool started = twai_hal_start(&twai_context, p_twai_obj->mode);
|
||||
assert(started);
|
||||
|
||||
TWAI_RESET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_STOPPED);
|
||||
p_twai_obj->state = TWAI_STATE_RUNNING;
|
||||
TWAI_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -554,19 +519,16 @@ esp_err_t twai_stop(void)
|
||||
//Check state
|
||||
TWAI_ENTER_CRITICAL();
|
||||
TWAI_CHECK_FROM_CRIT(p_twai_obj != NULL, ESP_ERR_INVALID_STATE);
|
||||
TWAI_CHECK_FROM_CRIT(!(p_twai_obj->control_flags & (CTRL_FLAG_STOPPED | CTRL_FLAG_BUS_OFF)), ESP_ERR_INVALID_STATE);
|
||||
TWAI_CHECK_FROM_CRIT(p_twai_obj->state == TWAI_STATE_RUNNING, ESP_ERR_INVALID_STATE);
|
||||
|
||||
bool stopped = twai_hal_stop(&twai_context);
|
||||
assert(stopped);
|
||||
|
||||
TWAI_RESET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_TX_BUFF_OCCUPIED);
|
||||
TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_STOPPED);
|
||||
twai_hal_stop(&twai_context);
|
||||
|
||||
//Reset TX Queue and message count
|
||||
if (p_twai_obj->tx_queue != NULL) {
|
||||
xQueueReset(p_twai_obj->tx_queue);
|
||||
}
|
||||
p_twai_obj->tx_msg_count = 0;
|
||||
p_twai_obj->state = TWAI_STATE_STOPPED;
|
||||
|
||||
TWAI_EXIT_CRITICAL();
|
||||
|
||||
@@ -583,18 +545,17 @@ esp_err_t twai_transmit(const twai_message_t *message, TickType_t ticks_to_wait)
|
||||
TWAI_ENTER_CRITICAL();
|
||||
//Check State
|
||||
TWAI_CHECK_FROM_CRIT(!(p_twai_obj->mode == TWAI_MODE_LISTEN_ONLY), ESP_ERR_NOT_SUPPORTED);
|
||||
TWAI_CHECK_FROM_CRIT(!(p_twai_obj->control_flags & (CTRL_FLAG_STOPPED | CTRL_FLAG_BUS_OFF)), ESP_ERR_INVALID_STATE);
|
||||
TWAI_CHECK_FROM_CRIT(p_twai_obj->state == TWAI_STATE_RUNNING, ESP_ERR_INVALID_STATE);
|
||||
//Format frame
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
twai_hal_frame_t tx_frame;
|
||||
twai_hal_format_frame(message, &tx_frame);
|
||||
|
||||
//Check if frame can be sent immediately
|
||||
if ((p_twai_obj->tx_msg_count == 0) && !(p_twai_obj->control_flags & CTRL_FLAG_TX_BUFF_OCCUPIED)) {
|
||||
if (p_twai_obj->tx_msg_count == 0) {
|
||||
//No other frames waiting to transmit. Bypass queue and transmit immediately
|
||||
twai_hal_set_tx_buffer_and_transmit(&twai_context, &tx_frame);
|
||||
p_twai_obj->tx_msg_count++;
|
||||
TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_TX_BUFF_OCCUPIED);
|
||||
ret = ESP_OK;
|
||||
}
|
||||
TWAI_EXIT_CRITICAL();
|
||||
@@ -606,19 +567,19 @@ esp_err_t twai_transmit(const twai_message_t *message, TickType_t ticks_to_wait)
|
||||
} else if (xQueueSend(p_twai_obj->tx_queue, &tx_frame, ticks_to_wait) == pdTRUE) {
|
||||
//Copied to TX Queue
|
||||
TWAI_ENTER_CRITICAL();
|
||||
if (p_twai_obj->control_flags & (CTRL_FLAG_STOPPED | CTRL_FLAG_BUS_OFF)) {
|
||||
//TX queue was reset (due to stop/bus_off), remove copied frame from queue to prevent transmission
|
||||
int res = xQueueReceive(p_twai_obj->tx_queue, &tx_frame, 0);
|
||||
assert(res == pdTRUE);
|
||||
ret = ESP_ERR_INVALID_STATE;
|
||||
} else if ((p_twai_obj->tx_msg_count == 0) && !(p_twai_obj->control_flags & CTRL_FLAG_TX_BUFF_OCCUPIED)) {
|
||||
//TX buffer was freed during copy, manually trigger transmission
|
||||
int res = xQueueReceive(p_twai_obj->tx_queue, &tx_frame, 0);
|
||||
assert(res == pdTRUE);
|
||||
twai_hal_set_tx_buffer_and_transmit(&twai_context, &tx_frame);
|
||||
p_twai_obj->tx_msg_count++;
|
||||
TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_TX_BUFF_OCCUPIED);
|
||||
ret = ESP_OK;
|
||||
if ((!twai_hal_check_state_flags(&twai_context, TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED)) && uxQueueMessagesWaiting(p_twai_obj->tx_queue) > 0) {
|
||||
//If the TX buffer is free but the TX queue is not empty. Check if we need to manually start a transmission
|
||||
if (twai_hal_check_state_flags(&twai_context, TWAI_HAL_STATE_FLAG_BUS_OFF) || !twai_hal_check_state_flags(&twai_context, TWAI_HAL_STATE_FLAG_RUNNING)) {
|
||||
//TX buffer became free due to bus-off or is no longer running. No need to start a transmission
|
||||
ret = ESP_ERR_INVALID_STATE;
|
||||
} else {
|
||||
//Manually start a transmission
|
||||
int res = xQueueReceive(p_twai_obj->tx_queue, &tx_frame, 0);
|
||||
assert(res == pdTRUE);
|
||||
twai_hal_set_tx_buffer_and_transmit(&twai_context, &tx_frame);
|
||||
p_twai_obj->tx_msg_count++;
|
||||
ret = ESP_OK;
|
||||
}
|
||||
} else {
|
||||
//Frame was copied to queue, waiting to be transmitted
|
||||
p_twai_obj->tx_msg_count++;
|
||||
@@ -694,20 +655,17 @@ esp_err_t twai_initiate_recovery(void)
|
||||
TWAI_ENTER_CRITICAL();
|
||||
//Check state
|
||||
TWAI_CHECK_FROM_CRIT(p_twai_obj != NULL, ESP_ERR_INVALID_STATE);
|
||||
TWAI_CHECK_FROM_CRIT(p_twai_obj->control_flags & CTRL_FLAG_BUS_OFF, ESP_ERR_INVALID_STATE);
|
||||
TWAI_CHECK_FROM_CRIT(!(p_twai_obj->control_flags & CTRL_FLAG_RECOVERING), ESP_ERR_INVALID_STATE);
|
||||
TWAI_CHECK_FROM_CRIT(p_twai_obj->state == TWAI_STATE_BUS_OFF, ESP_ERR_INVALID_STATE);
|
||||
|
||||
//Reset TX Queue/Counters
|
||||
if (p_twai_obj->tx_queue != NULL) {
|
||||
xQueueReset(p_twai_obj->tx_queue);
|
||||
}
|
||||
p_twai_obj->tx_msg_count = 0;
|
||||
TWAI_RESET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_TX_BUFF_OCCUPIED);
|
||||
TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_RECOVERING);
|
||||
|
||||
//Trigger start of recovery process
|
||||
bool started = twai_hal_start_bus_recovery(&twai_context);
|
||||
assert(started);
|
||||
twai_hal_start_bus_recovery(&twai_context);
|
||||
p_twai_obj->state = TWAI_STATE_RECOVERING;
|
||||
TWAI_EXIT_CRITICAL();
|
||||
|
||||
return ESP_OK;
|
||||
@@ -726,17 +684,10 @@ esp_err_t twai_get_status_info(twai_status_info_t *status_info)
|
||||
status_info->msgs_to_rx = p_twai_obj->rx_msg_count;
|
||||
status_info->tx_failed_count = p_twai_obj->tx_failed_count;
|
||||
status_info->rx_missed_count = p_twai_obj->rx_missed_count;
|
||||
status_info->rx_overrun_count = p_twai_obj->rx_overrun_count;
|
||||
status_info->arb_lost_count = p_twai_obj->arb_lost_count;
|
||||
status_info->bus_error_count = p_twai_obj->bus_error_count;
|
||||
if (p_twai_obj->control_flags & CTRL_FLAG_RECOVERING) {
|
||||
status_info->state = TWAI_STATE_RECOVERING;
|
||||
} else if (p_twai_obj->control_flags & CTRL_FLAG_BUS_OFF) {
|
||||
status_info->state = TWAI_STATE_BUS_OFF;
|
||||
} else if (p_twai_obj->control_flags & CTRL_FLAG_STOPPED) {
|
||||
status_info->state = TWAI_STATE_STOPPED;
|
||||
} else {
|
||||
status_info->state = TWAI_STATE_RUNNING;
|
||||
}
|
||||
status_info->state = p_twai_obj->state;
|
||||
TWAI_EXIT_CRITICAL();
|
||||
|
||||
return ESP_OK;
|
||||
@@ -750,7 +701,7 @@ esp_err_t twai_clear_transmit_queue(void)
|
||||
|
||||
TWAI_ENTER_CRITICAL();
|
||||
//If a message is currently undergoing transmission, the tx interrupt handler will decrement tx_msg_count
|
||||
p_twai_obj->tx_msg_count = (p_twai_obj->control_flags & CTRL_FLAG_TX_BUFF_OCCUPIED) ? 1 : 0;
|
||||
p_twai_obj->tx_msg_count = twai_hal_check_state_flags(&twai_context, TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED) ? 1 : 0;
|
||||
xQueueReset(p_twai_obj->tx_queue);
|
||||
TWAI_EXIT_CRITICAL();
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include "esp_types.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
@@ -68,6 +69,9 @@ static const char *UART_TAG = "uart";
|
||||
| (UART_INTR_BRK_DET) \
|
||||
| (UART_INTR_PARITY_ERR))
|
||||
|
||||
|
||||
#define UART_ENTER_CRITICAL_SAFE(mux) portENTER_CRITICAL_SAFE(mux)
|
||||
#define UART_EXIT_CRITICAL_SAFE(mux) portEXIT_CRITICAL_SAFE(mux)
|
||||
#define UART_ENTER_CRITICAL_ISR(mux) portENTER_CRITICAL_ISR(mux)
|
||||
#define UART_EXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL_ISR(mux)
|
||||
#define UART_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux)
|
||||
@@ -695,6 +699,19 @@ static int UART_ISR_ATTR uart_find_pattern_from_last(uint8_t *buf, int length, u
|
||||
return len;
|
||||
}
|
||||
|
||||
static uint32_t UART_ISR_ATTR uart_enable_tx_write_fifo(uart_port_t uart_num, const uint8_t *pbuf, uint32_t len)
|
||||
{
|
||||
uint32_t sent_len = 0;
|
||||
UART_ENTER_CRITICAL_SAFE(&(uart_context[uart_num].spinlock));
|
||||
if (UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX)) {
|
||||
uart_hal_set_rts(&(uart_context[uart_num].hal), 0);
|
||||
uart_hal_ena_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
|
||||
}
|
||||
uart_hal_write_txfifo(&(uart_context[uart_num].hal), pbuf, len, &sent_len);
|
||||
UART_EXIT_CRITICAL_SAFE(&(uart_context[uart_num].spinlock));
|
||||
return sent_len;
|
||||
}
|
||||
|
||||
//internal isr handler for default driver code.
|
||||
static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
|
||||
{
|
||||
@@ -764,19 +781,9 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
|
||||
}
|
||||
}
|
||||
if (p_uart->tx_len_tot > 0 && p_uart->tx_ptr && p_uart->tx_len_cur > 0) {
|
||||
//To fill the TX FIFO.
|
||||
uint32_t send_len = 0;
|
||||
// Set RS485 RTS pin before transmission if the half duplex mode is enabled
|
||||
if (UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX)) {
|
||||
UART_ENTER_CRITICAL_ISR(&(uart_context[uart_num].spinlock));
|
||||
uart_hal_set_rts(&(uart_context[uart_num].hal), 0);
|
||||
uart_hal_ena_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
|
||||
UART_EXIT_CRITICAL_ISR(&(uart_context[uart_num].spinlock));
|
||||
}
|
||||
uart_hal_write_txfifo(&(uart_context[uart_num].hal),
|
||||
(const uint8_t *)p_uart->tx_ptr,
|
||||
(p_uart->tx_len_cur > tx_fifo_rem) ? tx_fifo_rem : p_uart->tx_len_cur,
|
||||
&send_len);
|
||||
// To fill the TX FIFO.
|
||||
uint32_t send_len = uart_enable_tx_write_fifo(uart_num, (const uint8_t *) p_uart->tx_ptr,
|
||||
MIN(p_uart->tx_len_cur, tx_fifo_rem));
|
||||
p_uart->tx_ptr += send_len;
|
||||
p_uart->tx_len_tot -= send_len;
|
||||
p_uart->tx_len_cur -= send_len;
|
||||
@@ -980,6 +987,7 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
|
||||
// Workaround for RS485: If the RS485 half duplex mode is active
|
||||
// and transmitter is in idle state then reset received buffer and reset RTS pin
|
||||
// skip this behavior for other UART modes
|
||||
uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
|
||||
UART_ENTER_CRITICAL_ISR(&(uart_context[uart_num].spinlock));
|
||||
uart_hal_disable_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
|
||||
if (UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX)) {
|
||||
@@ -987,7 +995,6 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
|
||||
uart_hal_set_rts(&(uart_context[uart_num].hal), 1);
|
||||
}
|
||||
UART_EXIT_CRITICAL_ISR(&(uart_context[uart_num].spinlock));
|
||||
uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
|
||||
xSemaphoreGiveFromISR(p_uart_obj[uart_num]->tx_done_sem, &HPTaskAwoken);
|
||||
}
|
||||
} else {
|
||||
@@ -1056,13 +1063,7 @@ int uart_tx_chars(uart_port_t uart_num, const char *buffer, uint32_t len)
|
||||
}
|
||||
int tx_len = 0;
|
||||
xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY);
|
||||
if (UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX)) {
|
||||
UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock));
|
||||
uart_hal_set_rts(&(uart_context[uart_num].hal), 0);
|
||||
uart_hal_ena_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
|
||||
UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock));
|
||||
}
|
||||
uart_hal_write_txfifo(&(uart_context[uart_num].hal), (const uint8_t *) buffer, len, (uint32_t *)&tx_len);
|
||||
tx_len = (int)uart_enable_tx_write_fifo(uart_num, (const uint8_t *) buffer, len);
|
||||
xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);
|
||||
return tx_len;
|
||||
}
|
||||
@@ -1100,14 +1101,7 @@ static int uart_tx_all(uart_port_t uart_num, const char *src, size_t size, bool
|
||||
while (size) {
|
||||
//semaphore for tx_fifo available
|
||||
if (pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_fifo_sem, (portTickType)portMAX_DELAY)) {
|
||||
uint32_t sent = 0;
|
||||
if (UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX)) {
|
||||
UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock));
|
||||
uart_hal_set_rts(&(uart_context[uart_num].hal), 0);
|
||||
uart_hal_ena_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
|
||||
UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock));
|
||||
}
|
||||
uart_hal_write_txfifo(&(uart_context[uart_num].hal), (const uint8_t *)src, size, &sent);
|
||||
uint32_t sent = uart_enable_tx_write_fifo(uart_num, (const uint8_t *) src, size);
|
||||
if (sent < size) {
|
||||
p_uart_obj[uart_num]->tx_waiting_fifo = true;
|
||||
uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT);
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_EFUSE_LEN_OF_3_4_SCHEME_BLOCK_IN_BYTES (24)
|
||||
#define ESP_EFUSE_LEN_OF_REPEAT_BLOCK_IN_BYTES (16)
|
||||
|
||||
#define COUNT_EFUSE_REG_PER_BLOCK 8 /* The number of registers per block. */
|
||||
|
||||
#define ESP_EFUSE_SECURE_VERSION_NUM_BLOCK EFUSE_BLK3
|
||||
|
||||
@@ -97,8 +97,12 @@ esp_err_t esp_efuse_utility_fill_buff(unsigned int num_reg, esp_efuse_block_t ef
|
||||
*
|
||||
* If CONFIG_EFUSE_VIRTUAL is set, writing will not be performed.
|
||||
* After the function is completed, the writing registers are cleared.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: The operation was successfully completed.
|
||||
* - ESP_FAIL: The operation was not successfully completed.
|
||||
*/
|
||||
void esp_efuse_utility_burn_efuses(void);
|
||||
esp_err_t esp_efuse_utility_burn_efuses(void);
|
||||
|
||||
/**
|
||||
* @brief Returns the number of array elements for placing these "bits" in an array with the length of each element equal to "size_of_base".
|
||||
@@ -151,6 +155,19 @@ esp_err_t esp_efuse_utility_apply_new_coding_scheme(void);
|
||||
*/
|
||||
void esp_efuse_utility_clear_program_registers(void);
|
||||
|
||||
/**
|
||||
* @brief Checks the correctness of burned data in the given block.
|
||||
*
|
||||
* @note Internal use. Do not call it.
|
||||
*
|
||||
* @param[in] block Index of efuse block.
|
||||
* @param[in] r_data_len Block length for reading data in bytes (multiple of 4).
|
||||
*
|
||||
* @return True - written data are correct.
|
||||
* False - written data are incorrect.
|
||||
*/
|
||||
bool esp_efuse_utility_is_correct_written_data(esp_efuse_block_t block, unsigned r_data_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
static const char *TAG = "efuse";
|
||||
|
||||
#define ESP_EFUSE_BLOCK_ERROR_BITS(error_reg, block) ((error_reg) & (0x0F << (4 * (block))))
|
||||
|
||||
#ifdef CONFIG_EFUSE_VIRTUAL
|
||||
extern uint32_t virt_blocks[EFUSE_BLK_MAX][COUNT_EFUSE_REG_PER_BLOCK];
|
||||
#endif // CONFIG_EFUSE_VIRTUAL
|
||||
@@ -34,12 +36,14 @@ const esp_efuse_range_addr_t range_read_addr_blocks[] = {
|
||||
{EFUSE_BLK3_RDATA0_REG, EFUSE_BLK3_RDATA7_REG} // range address of EFUSE_BLK3
|
||||
};
|
||||
|
||||
/*Range addresses to write blocks*/
|
||||
static uint32_t write_mass_blocks[EFUSE_BLK_MAX][COUNT_EFUSE_REG_PER_BLOCK] = { 0 };
|
||||
|
||||
/*Range addresses to write blocks (it is not real regs, it is a buffer) */
|
||||
const esp_efuse_range_addr_t range_write_addr_blocks[] = {
|
||||
{EFUSE_BLK0_WDATA0_REG, EFUSE_BLK0_WDATA6_REG}, // range address of EFUSE_BLK0
|
||||
{EFUSE_BLK1_WDATA0_REG, EFUSE_BLK1_WDATA7_REG}, // range address of EFUSE_BLK1
|
||||
{EFUSE_BLK2_WDATA0_REG, EFUSE_BLK2_WDATA7_REG}, // range address of EFUSE_BLK2
|
||||
{EFUSE_BLK3_WDATA0_REG, EFUSE_BLK3_WDATA7_REG} // range address of EFUSE_BLK3
|
||||
{(uint32_t) &write_mass_blocks[EFUSE_BLK0][0], (uint32_t) &write_mass_blocks[EFUSE_BLK0][6]},
|
||||
{(uint32_t) &write_mass_blocks[EFUSE_BLK1][0], (uint32_t) &write_mass_blocks[EFUSE_BLK1][7]},
|
||||
{(uint32_t) &write_mass_blocks[EFUSE_BLK2][0], (uint32_t) &write_mass_blocks[EFUSE_BLK2][7]},
|
||||
{(uint32_t) &write_mass_blocks[EFUSE_BLK3][0], (uint32_t) &write_mass_blocks[EFUSE_BLK3][7]},
|
||||
};
|
||||
|
||||
#define EFUSE_CONF_WRITE 0x5A5A /* eFuse_pgm_op_ena, force no rd/wr disable. */
|
||||
@@ -48,6 +52,17 @@ const esp_efuse_range_addr_t range_write_addr_blocks[] = {
|
||||
#define EFUSE_CMD_READ 0x01 /* Command to read. */
|
||||
|
||||
#ifndef CONFIG_EFUSE_VIRTUAL
|
||||
/* Addresses to write blocks*/
|
||||
const uint32_t start_write_addr[] = {
|
||||
EFUSE_BLK0_WDATA0_REG,
|
||||
EFUSE_BLK1_WDATA0_REG,
|
||||
EFUSE_BLK2_WDATA0_REG,
|
||||
EFUSE_BLK3_WDATA0_REG,
|
||||
};
|
||||
|
||||
static void apply_repeat_encoding(const uint8_t *in_bytes, uint32_t *out_words, size_t in_bytes_len);
|
||||
static void unite_write_mass_blocks_and_wr_regs(void);
|
||||
|
||||
// Update Efuse timing configuration
|
||||
static esp_err_t esp_efuse_set_timing(void)
|
||||
{
|
||||
@@ -71,52 +86,149 @@ static esp_err_t esp_efuse_set_timing(void)
|
||||
REG_SET_FIELD(EFUSE_CLK_REG, EFUSE_CLK_SEL1, clk_sel1);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool efuse_ll_get_dec_warnings(unsigned block)
|
||||
{
|
||||
if (block == 0 || block > 4) {
|
||||
return false;
|
||||
}
|
||||
uint32_t error_reg = REG_GET_FIELD(EFUSE_DEC_STATUS_REG, EFUSE_DEC_WARNINGS);
|
||||
return ESP_EFUSE_BLOCK_ERROR_BITS(error_reg, block - 1) != 0;
|
||||
}
|
||||
|
||||
bool efuse_hal_is_coding_error_in_block(unsigned block)
|
||||
{
|
||||
return block > 0 &&
|
||||
esp_efuse_get_coding_scheme(block) == EFUSE_CODING_SCHEME_3_4 &&
|
||||
efuse_ll_get_dec_warnings(block);
|
||||
}
|
||||
|
||||
#endif // ifndef CONFIG_EFUSE_VIRTUAL
|
||||
|
||||
static void efuse_hal_clear_program_registers(void)
|
||||
{
|
||||
for (uint32_t r = EFUSE_BLK0_WDATA0_REG; r <= EFUSE_BLK0_WDATA6_REG; r += 4) {
|
||||
REG_WRITE(r, 0);
|
||||
}
|
||||
for (uint32_t r = EFUSE_BLK1_WDATA0_REG; r <= EFUSE_BLK1_WDATA7_REG; r += 4) {
|
||||
REG_WRITE(r, 0);
|
||||
}
|
||||
for (uint32_t r = EFUSE_BLK2_WDATA0_REG; r <= EFUSE_BLK2_WDATA7_REG; r += 4) {
|
||||
REG_WRITE(r, 0);
|
||||
}
|
||||
for (uint32_t r = EFUSE_BLK3_WDATA0_REG; r <= EFUSE_BLK3_WDATA7_REG; r += 4) {
|
||||
REG_WRITE(r, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Efuse read operation: copies data from physical efuses to efuse read registers.
|
||||
void esp_efuse_utility_clear_program_registers(void)
|
||||
{
|
||||
REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_READ);
|
||||
efuse_hal_clear_program_registers();
|
||||
}
|
||||
|
||||
// Burn values written to the efuse write registers
|
||||
void esp_efuse_utility_burn_efuses(void)
|
||||
esp_err_t esp_efuse_utility_burn_efuses(void)
|
||||
{
|
||||
esp_err_t error = ESP_OK;
|
||||
#ifdef CONFIG_EFUSE_VIRTUAL
|
||||
ESP_LOGW(TAG, "Virtual efuses enabled: Not really burning eFuses");
|
||||
for (int num_block = EFUSE_BLK0; num_block < EFUSE_BLK_MAX; num_block++) {
|
||||
esp_efuse_coding_scheme_t scheme = esp_efuse_get_coding_scheme(num_block);
|
||||
if (scheme == EFUSE_CODING_SCHEME_3_4) {
|
||||
uint8_t buf[COUNT_EFUSE_REG_PER_BLOCK * 4] = { 0 };
|
||||
int i = 0;
|
||||
for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4, ++i) {
|
||||
*((uint32_t*)buf + i) = REG_READ(addr_wr_block);
|
||||
}
|
||||
int j = 0;
|
||||
uint32_t out_buf[COUNT_EFUSE_REG_PER_BLOCK] = { 0 };
|
||||
for (int k = 0; k < 4; ++k, ++j) {
|
||||
memcpy((uint8_t*)out_buf + j * 6, &buf[k * 8], 6);
|
||||
}
|
||||
for (int k = 0; k < COUNT_EFUSE_REG_PER_BLOCK; ++k) {
|
||||
REG_WRITE(range_write_addr_blocks[num_block].start + k * 4, out_buf[k]);
|
||||
}
|
||||
}
|
||||
for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) {
|
||||
int subblock = 0;
|
||||
for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) {
|
||||
virt_blocks[num_block][subblock++] |= REG_READ(addr_wr_block);
|
||||
}
|
||||
}
|
||||
#else
|
||||
esp_efuse_set_timing();
|
||||
// Permanently update values written to the efuse write registers
|
||||
REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_WRITE);
|
||||
REG_WRITE(EFUSE_CMD_REG, EFUSE_CMD_PGM);
|
||||
while (REG_READ(EFUSE_CMD_REG) != 0) {};
|
||||
REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_READ);
|
||||
REG_WRITE(EFUSE_CMD_REG, EFUSE_CMD_READ);
|
||||
while (REG_READ(EFUSE_CMD_REG) != 0) {};
|
||||
#else // CONFIG_EFUSE_VIRTUAL
|
||||
if (esp_efuse_set_timing() != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Efuse fields are not burnt");
|
||||
} else {
|
||||
// Support the (old) use case where data is written directly to EFUSE_BLKx_WDATA0_REG without using the eFuse API.
|
||||
unite_write_mass_blocks_and_wr_regs();
|
||||
|
||||
// Permanently update values written to the efuse write registers
|
||||
// It is necessary to process blocks in the order from MAX-> EFUSE_BLK0, because EFUSE_BLK0 has protection bits for other blocks.
|
||||
for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) {
|
||||
esp_efuse_coding_scheme_t scheme = esp_efuse_get_coding_scheme(num_block);
|
||||
bool need_burn_block = false;
|
||||
for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) {
|
||||
if (REG_READ(addr_wr_block) != 0) {
|
||||
need_burn_block = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!need_burn_block) {
|
||||
continue;
|
||||
}
|
||||
if (error) {
|
||||
// It is done for a use case: BLOCK2 (Flash encryption key) could have an error (incorrect written data)
|
||||
// in this case we can not burn any data into BLOCK0 because it might set read/write protections of BLOCK2.
|
||||
ESP_LOGE(TAG, "BLOCK%d can not be burned because a previous block got an error, skipped.", num_block);
|
||||
continue;
|
||||
}
|
||||
efuse_hal_clear_program_registers();
|
||||
unsigned w_data_len;
|
||||
unsigned r_data_len;
|
||||
if (scheme == EFUSE_CODING_SCHEME_3_4) {
|
||||
esp_efuse_utility_apply_34_encoding((void *)range_write_addr_blocks[num_block].start, (uint32_t *)start_write_addr[num_block], ESP_EFUSE_LEN_OF_3_4_SCHEME_BLOCK_IN_BYTES);
|
||||
r_data_len = ESP_EFUSE_LEN_OF_3_4_SCHEME_BLOCK_IN_BYTES;
|
||||
w_data_len = 32;
|
||||
} else if (scheme == EFUSE_CODING_SCHEME_REPEAT) {
|
||||
apply_repeat_encoding((void *)range_write_addr_blocks[num_block].start, (uint32_t *)start_write_addr[num_block], ESP_EFUSE_LEN_OF_REPEAT_BLOCK_IN_BYTES);
|
||||
r_data_len = ESP_EFUSE_LEN_OF_REPEAT_BLOCK_IN_BYTES;
|
||||
w_data_len = 32;
|
||||
} else {
|
||||
r_data_len = (range_read_addr_blocks[num_block].end - range_read_addr_blocks[num_block].start) + sizeof(uint32_t);
|
||||
w_data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t);
|
||||
memcpy((void *)start_write_addr[num_block], (void *)range_write_addr_blocks[num_block].start, w_data_len);
|
||||
}
|
||||
|
||||
uint32_t backup_write_data[8];
|
||||
memcpy(backup_write_data, (void *)start_write_addr[num_block], w_data_len);
|
||||
int repeat_burn_op = 1;
|
||||
bool correct_written_data;
|
||||
bool coding_error_before = efuse_hal_is_coding_error_in_block(num_block);
|
||||
if (coding_error_before) {
|
||||
ESP_LOGW(TAG, "BLOCK%d already has a coding error", num_block);
|
||||
}
|
||||
bool coding_error_occurred;
|
||||
|
||||
do {
|
||||
ESP_LOGI(TAG, "BURN BLOCK%d", num_block);
|
||||
// BURN a block
|
||||
REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_WRITE);
|
||||
REG_WRITE(EFUSE_CMD_REG, EFUSE_CMD_PGM);
|
||||
while (REG_READ(EFUSE_CMD_REG) != 0) {};
|
||||
REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_READ);
|
||||
REG_WRITE(EFUSE_CMD_REG, EFUSE_CMD_READ);
|
||||
while (REG_READ(EFUSE_CMD_REG) != 0) {};
|
||||
|
||||
bool coding_error_after = efuse_hal_is_coding_error_in_block(num_block);
|
||||
coding_error_occurred = (coding_error_before != coding_error_after) && coding_error_before == false;
|
||||
if (coding_error_occurred) {
|
||||
ESP_LOGW(TAG, "BLOCK%d got a coding error", num_block);
|
||||
}
|
||||
|
||||
correct_written_data = esp_efuse_utility_is_correct_written_data(num_block, r_data_len);
|
||||
if (!correct_written_data || coding_error_occurred) {
|
||||
ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op);
|
||||
memcpy((void *)start_write_addr[num_block], (void *)backup_write_data, w_data_len);
|
||||
}
|
||||
|
||||
} while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3);
|
||||
|
||||
if (coding_error_occurred) {
|
||||
ESP_LOGW(TAG, "Coding error was not fixed");
|
||||
}
|
||||
if (!correct_written_data) {
|
||||
ESP_LOGE(TAG, "Written data are incorrect");
|
||||
error = ESP_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_EFUSE_VIRTUAL
|
||||
esp_efuse_utility_reset();
|
||||
return error;
|
||||
}
|
||||
|
||||
esp_err_t esp_efuse_utility_apply_34_encoding(const uint8_t *in_bytes, uint32_t *out_words, size_t in_bytes_len)
|
||||
@@ -148,20 +260,27 @@ esp_err_t esp_efuse_utility_apply_34_encoding(const uint8_t *in_bytes, uint32_t
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static bool read_w_data_and_check_fill(esp_efuse_block_t num_block, uint32_t *buf_w_data)
|
||||
#ifndef CONFIG_EFUSE_VIRTUAL
|
||||
static void unite_write_mass_blocks_and_wr_regs(void)
|
||||
{
|
||||
bool blk_is_filled = false;
|
||||
int i = 0;
|
||||
for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4, ++i) {
|
||||
buf_w_data[i] = REG_READ(addr_wr_block);
|
||||
if (buf_w_data[i] != 0) {
|
||||
REG_WRITE(addr_wr_block, 0);
|
||||
blk_is_filled = true;
|
||||
for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) {
|
||||
uint32_t wr_reg = start_write_addr[num_block];
|
||||
for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) {
|
||||
REG_WRITE(addr_wr_block, REG_READ(addr_wr_block) | REG_READ(wr_reg));
|
||||
wr_reg += 4;
|
||||
}
|
||||
}
|
||||
return blk_is_filled;
|
||||
esp_efuse_utility_clear_program_registers();
|
||||
}
|
||||
|
||||
static void apply_repeat_encoding(const uint8_t *in_bytes, uint32_t *out_words, size_t in_bytes_len)
|
||||
{
|
||||
for (unsigned i = 0; i < 2; i++) {
|
||||
memcpy(&out_words[i * 4], (uint32_t *)in_bytes, in_bytes_len);
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_EFUSE_VIRTUAL
|
||||
|
||||
static void read_r_data(esp_efuse_block_t num_block, uint32_t* buf_r_data)
|
||||
{
|
||||
int i = 0;
|
||||
@@ -170,27 +289,30 @@ static void read_r_data(esp_efuse_block_t num_block, uint32_t* buf_r_data)
|
||||
}
|
||||
}
|
||||
|
||||
// After esp_efuse_write.. functions EFUSE_BLKx_WDATAx_REG were filled is not coded values.
|
||||
// This function reads EFUSE_BLKx_WDATAx_REG registers, applies coding scheme and writes encoded values back to EFUSE_BLKx_WDATAx_REG.
|
||||
// This function just checkes that given data for blocks will not rise a coding issue during the burn operation.
|
||||
// Encoded data will be set during the burn operation.
|
||||
esp_err_t esp_efuse_utility_apply_new_coding_scheme()
|
||||
{
|
||||
uint8_t buf_w_data[COUNT_EFUSE_REG_PER_BLOCK * 4];
|
||||
uint8_t buf_r_data[COUNT_EFUSE_REG_PER_BLOCK * 4];
|
||||
uint32_t reg[COUNT_EFUSE_REG_PER_BLOCK];
|
||||
// start with EFUSE_BLK1. EFUSE_BLK0 - always uses EFUSE_CODING_SCHEME_NONE.
|
||||
for (int num_block = EFUSE_BLK1; num_block < EFUSE_BLK_MAX; num_block++) {
|
||||
esp_efuse_coding_scheme_t scheme = esp_efuse_get_coding_scheme(num_block);
|
||||
// check and apply a new coding scheme.
|
||||
if (scheme != EFUSE_CODING_SCHEME_NONE) {
|
||||
memset(buf_w_data, 0, sizeof(buf_w_data));
|
||||
memset((uint8_t*)reg, 0, sizeof(reg));
|
||||
if (read_w_data_and_check_fill(num_block, (uint32_t*)buf_w_data) == true) {
|
||||
bool is_write_data = false;
|
||||
for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) {
|
||||
if (REG_READ(addr_wr_block)) {
|
||||
is_write_data = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_write_data) {
|
||||
read_r_data(num_block, (uint32_t*)buf_r_data);
|
||||
uint8_t* buf_w_data = (uint8_t*)range_write_addr_blocks[num_block].start;
|
||||
if (scheme == EFUSE_CODING_SCHEME_3_4) {
|
||||
if (*((uint32_t*)buf_w_data + 6) != 0 || *((uint32_t*)buf_w_data + 7) != 0) {
|
||||
return ESP_ERR_CODING;
|
||||
}
|
||||
for (int i = 0; i < 24; ++i) {
|
||||
for (int i = 0; i < ESP_EFUSE_LEN_OF_3_4_SCHEME_BLOCK_IN_BYTES; ++i) {
|
||||
if (buf_w_data[i] != 0) {
|
||||
int st_offset_buf = (i / 6) * 6;
|
||||
// check that place is free.
|
||||
@@ -200,32 +322,14 @@ esp_err_t esp_efuse_utility_apply_new_coding_scheme()
|
||||
return ESP_ERR_CODING;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t err = esp_efuse_utility_apply_34_encoding(&buf_w_data[st_offset_buf], reg, 6);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
int num_reg = (st_offset_buf / 6) * 2;
|
||||
for (int r = 0; r < 2; r++) {
|
||||
REG_WRITE(range_write_addr_blocks[num_block].start + (num_reg + r) * 4, reg[r]);
|
||||
}
|
||||
i = st_offset_buf + 5;
|
||||
}
|
||||
}
|
||||
} else if (scheme == EFUSE_CODING_SCHEME_REPEAT) {
|
||||
uint32_t* buf_32 = (uint32_t*)buf_w_data;
|
||||
for (int i = 4; i < 8; ++i) {
|
||||
if (*(buf_32 + i) != 0) {
|
||||
if (*((uint32_t*)buf_w_data + i) != 0) {
|
||||
return ESP_ERR_CODING;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (buf_32[i] != 0) {
|
||||
REG_WRITE(range_write_addr_blocks[num_block].start + i * 4, buf_32[i]);
|
||||
REG_WRITE(range_write_addr_blocks[num_block].start + (i + 4) * 4, buf_32[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
|
||||
static const char *TAG = "efuse";
|
||||
|
||||
#define ESP_EFUSE_BLOCK_ERROR_BITS(error_reg, block) ((error_reg) & (0x0F << (4 * (block))))
|
||||
|
||||
#ifdef CONFIG_EFUSE_VIRTUAL
|
||||
extern uint32_t virt_blocks[EFUSE_BLK_MAX][COUNT_EFUSE_REG_PER_BLOCK];
|
||||
#endif // CONFIG_EFUSE_VIRTUAL
|
||||
@@ -66,6 +68,25 @@ static esp_err_t esp_efuse_set_timing(void)
|
||||
uint32_t clock_hz = esp_clk_apb_freq();
|
||||
return ets_efuse_set_timing(clock_hz) ? ESP_FAIL : ESP_OK;
|
||||
}
|
||||
|
||||
static bool efuse_hal_is_coding_error_in_block(unsigned block)
|
||||
{
|
||||
if (block == 0) {
|
||||
for (unsigned i = 0; i < 5; i++) {
|
||||
if (REG_READ(EFUSE_RD_REPEAT_ERR0_REG + i * 4)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (block <= 10) {
|
||||
// EFUSE_RD_RS_ERR0_REG: (hi) BLOCK8, BLOCK7, BLOCK6, BLOCK5, BLOCK4, BLOCK3, BLOCK2, BLOCK1 (low)
|
||||
// EFUSE_RD_RS_ERR1_REG: BLOCK10, BLOCK9
|
||||
block--;
|
||||
uint32_t error_reg = REG_READ(EFUSE_RD_RS_ERR0_REG + (block / 8) * 4);
|
||||
return ESP_EFUSE_BLOCK_ERROR_BITS(error_reg, block % 8) != 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // ifndef CONFIG_EFUSE_VIRTUAL
|
||||
|
||||
// Efuse read operation: copies data from physical efuses to efuse read registers.
|
||||
@@ -76,8 +97,9 @@ void esp_efuse_utility_clear_program_registers(void)
|
||||
}
|
||||
|
||||
// Burn values written to the efuse write registers
|
||||
void esp_efuse_utility_burn_efuses(void)
|
||||
esp_err_t esp_efuse_utility_burn_efuses(void)
|
||||
{
|
||||
esp_err_t error = ESP_OK;
|
||||
#ifdef CONFIG_EFUSE_VIRTUAL
|
||||
ESP_LOGW(TAG, "Virtual efuses enabled: Not really burning eFuses");
|
||||
for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) {
|
||||
@@ -86,30 +108,90 @@ void esp_efuse_utility_burn_efuses(void)
|
||||
virt_blocks[num_block][subblock++] |= REG_READ(addr_wr_block);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#else // CONFIG_EFUSE_VIRTUAL
|
||||
if (esp_efuse_set_timing() != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Efuse fields are not burnt");
|
||||
} else {
|
||||
// Permanently update values written to the efuse write registers
|
||||
// It is necessary to process blocks in the order from MAX-> EFUSE_BLK0, because EFUSE_BLK0 has protection bits for other blocks.
|
||||
for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) {
|
||||
bool need_burn_block = false;
|
||||
for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) {
|
||||
if (REG_READ(addr_wr_block) != 0) {
|
||||
if (esp_efuse_get_coding_scheme(num_block) == EFUSE_CODING_SCHEME_RS) {
|
||||
uint8_t block_rs[12];
|
||||
ets_efuse_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs);
|
||||
memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs));
|
||||
}
|
||||
int data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t);
|
||||
memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)range_write_addr_blocks[num_block].start, data_len);
|
||||
ets_efuse_program(num_block);
|
||||
need_burn_block = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!need_burn_block) {
|
||||
continue;
|
||||
}
|
||||
if (error) {
|
||||
// It is done for a use case: BLOCK2 (Flash encryption key) could have an error (incorrect written data)
|
||||
// in this case we can not burn any data into BLOCK0 because it might set read/write protections of BLOCK2.
|
||||
ESP_LOGE(TAG, "BLOCK%d can not be burned because a previous block got an error, skipped.", num_block);
|
||||
continue;
|
||||
}
|
||||
ets_efuse_clear_program_registers();
|
||||
if (esp_efuse_get_coding_scheme(num_block) == EFUSE_CODING_SCHEME_RS) {
|
||||
uint8_t block_rs[12];
|
||||
ets_efuse_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs);
|
||||
memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs));
|
||||
}
|
||||
unsigned r_data_len = (range_read_addr_blocks[num_block].end - range_read_addr_blocks[num_block].start) + sizeof(uint32_t);
|
||||
unsigned data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t);
|
||||
memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)range_write_addr_blocks[num_block].start, data_len);
|
||||
|
||||
uint32_t backup_write_data[8 + 3]; // 8 words are data and 3 words are RS coding data
|
||||
memcpy(backup_write_data, (void *)EFUSE_PGM_DATA0_REG, sizeof(backup_write_data));
|
||||
int repeat_burn_op = 1;
|
||||
bool correct_written_data;
|
||||
bool coding_error_before = efuse_hal_is_coding_error_in_block(num_block);
|
||||
if (coding_error_before) {
|
||||
ESP_LOGW(TAG, "BLOCK%d already has a coding error", num_block);
|
||||
}
|
||||
bool coding_error_occurred;
|
||||
|
||||
do {
|
||||
ESP_LOGI(TAG, "BURN BLOCK%d", num_block);
|
||||
ets_efuse_program(num_block); // BURN a block
|
||||
|
||||
bool coding_error_after;
|
||||
for (unsigned i = 0; i < 5; i++) {
|
||||
ets_efuse_read();
|
||||
coding_error_after = efuse_hal_is_coding_error_in_block(num_block);
|
||||
if (coding_error_after == true) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
coding_error_occurred = (coding_error_before != coding_error_after) && coding_error_before == false;
|
||||
if (coding_error_occurred) {
|
||||
ESP_LOGW(TAG, "BLOCK%d got a coding error", num_block);
|
||||
}
|
||||
|
||||
correct_written_data = esp_efuse_utility_is_correct_written_data(num_block, r_data_len);
|
||||
if (!correct_written_data || coding_error_occurred) {
|
||||
ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op);
|
||||
memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data));
|
||||
}
|
||||
|
||||
} while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3);
|
||||
|
||||
if (coding_error_occurred) {
|
||||
ESP_LOGW(TAG, "Coding error was not fixed");
|
||||
if (num_block == 0) {
|
||||
ESP_LOGE(TAG, "BLOCK0 got a coding error, which might be critical for security");
|
||||
error = ESP_FAIL;
|
||||
}
|
||||
}
|
||||
if (!correct_written_data) {
|
||||
ESP_LOGE(TAG, "Written data are incorrect");
|
||||
error = ESP_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_EFUSE_VIRTUAL
|
||||
esp_efuse_utility_reset();
|
||||
return error;
|
||||
}
|
||||
|
||||
// After esp_efuse_write.. functions EFUSE_BLKx_WDATAx_REG were filled is not coded values.
|
||||
|
||||
@@ -94,7 +94,7 @@ esp_err_t esp_efuse_write_field_blob(const esp_efuse_desc_t* field[], const void
|
||||
if (err == ESP_OK) {
|
||||
err = esp_efuse_utility_apply_new_coding_scheme();
|
||||
if (err == ESP_OK) {
|
||||
esp_efuse_utility_burn_efuses();
|
||||
err = esp_efuse_utility_burn_efuses();
|
||||
}
|
||||
}
|
||||
esp_efuse_utility_reset();
|
||||
@@ -129,7 +129,7 @@ esp_err_t esp_efuse_write_field_cnt(const esp_efuse_desc_t* field[], size_t cnt)
|
||||
if (err == ESP_OK) {
|
||||
err = esp_efuse_utility_apply_new_coding_scheme();
|
||||
if (err == ESP_OK) {
|
||||
esp_efuse_utility_burn_efuses();
|
||||
err = esp_efuse_utility_burn_efuses();
|
||||
}
|
||||
}
|
||||
esp_efuse_utility_reset();
|
||||
@@ -193,7 +193,7 @@ esp_err_t esp_efuse_write_reg(esp_efuse_block_t blk, unsigned int num_reg, uint3
|
||||
if (err == ESP_OK) {
|
||||
err = esp_efuse_utility_apply_new_coding_scheme();
|
||||
if (err == ESP_OK) {
|
||||
esp_efuse_utility_burn_efuses();
|
||||
err = esp_efuse_utility_burn_efuses();
|
||||
}
|
||||
}
|
||||
esp_efuse_utility_reset();
|
||||
@@ -271,7 +271,7 @@ esp_err_t esp_efuse_batch_write_commit(void)
|
||||
} else {
|
||||
esp_err_t err = esp_efuse_utility_apply_new_coding_scheme();
|
||||
if (err == ESP_OK) {
|
||||
esp_efuse_utility_burn_efuses();
|
||||
err = esp_efuse_utility_burn_efuses();
|
||||
}
|
||||
esp_efuse_batch_write_cancel();
|
||||
return err;
|
||||
|
||||
@@ -48,7 +48,7 @@ void esp_efuse_reset(void)
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE
|
||||
|
||||
#include "../include_bootloader/bootloader_flash.h"
|
||||
#include "../include_bootloader/bootloader_flash_priv.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
|
||||
static uint32_t esp_efuse_flash_offset = 0;
|
||||
|
||||
@@ -354,3 +354,29 @@ static bool check_range_of_bits(esp_efuse_block_t blk, int offset_in_bits, int s
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool esp_efuse_utility_is_correct_written_data(esp_efuse_block_t block, unsigned r_data_len)
|
||||
{
|
||||
uint32_t* w_data = (uint32_t*)range_write_addr_blocks[block].start;
|
||||
uint32_t* r_data = (uint32_t*)range_read_addr_blocks[block].start;
|
||||
|
||||
bool correct_written_data = memcmp(w_data, r_data, r_data_len) == 0;
|
||||
if (correct_written_data) {
|
||||
ESP_LOGI(TAG, "BURN BLOCK%d - OK (write block == read block)", block);
|
||||
return true;
|
||||
}
|
||||
|
||||
correct_written_data = true;
|
||||
for (unsigned i = 0; i < r_data_len / 4; i++) {
|
||||
if ((*(r_data + i) & *(w_data + i)) != *(w_data + i)) {
|
||||
correct_written_data = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (correct_written_data) {
|
||||
ESP_LOGI(TAG, "BURN BLOCK%d - OK (all write block bits are set)", block);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "BURN BLOCK%d - ERROR (written bits != read bits)", block);
|
||||
}
|
||||
return correct_written_data;
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ TEST_CASE("Test Coding Scheme for efuse manager", "[efuse]")
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
TEST_ASSERT_EQUAL_HEX32_ARRAY(encoded, w_data_after_coding, 8);
|
||||
TEST_ASSERT_EQUAL_HEX32_ARRAY(buf, w_data_after_coding, 8);
|
||||
}
|
||||
esp_efuse_utility_reset();
|
||||
bootloader_random_disable();
|
||||
@@ -193,7 +193,7 @@ TEST_CASE("Test data does not match the coding scheme", "[efuse]")
|
||||
esp_efuse_utility_reset();
|
||||
|
||||
for (int i = 0; i < count_useful_reg; ++i) {
|
||||
REG_WRITE(EFUSE_BLK2_WDATA0_REG + i * 4, 0xABCDEF01 + i);
|
||||
TEST_ESP_OK(esp_efuse_utility_write_reg(2, i, 0xABCDEF01 + i));
|
||||
}
|
||||
|
||||
if (coding_scheme == EFUSE_CODING_SCHEME_NONE) {
|
||||
|
||||
@@ -564,18 +564,35 @@ menu "ESP32-specific"
|
||||
bool "Internal 8.5MHz oscillator, divided by 256 (~33kHz)"
|
||||
endchoice
|
||||
|
||||
config ESP32_RTC_EXT_CRYST_ADDIT_CURRENT
|
||||
bool "Additional current for external 32kHz crystal"
|
||||
choice ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_METHOD
|
||||
prompt "Additional current for external 32kHz crystal"
|
||||
depends on ESP32_RTC_CLK_SRC_EXT_CRYS
|
||||
default "n"
|
||||
depends on ESP32_REV_MIN <= 1
|
||||
default ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_NONE
|
||||
help
|
||||
Choose which additional current is used for rtc external crystal.
|
||||
With some 32kHz crystal configurations, the X32N and X32P pins may not have enough
|
||||
drive strength to keep the crystal oscillating. Choose the method to provide
|
||||
additional current from touchpad 9 to the external 32kHz crystal. Note that
|
||||
the deep sleep current is slightly high (4-5uA) and the touchpad and the
|
||||
wakeup sources of both touchpad and ULP are not available in method 1 and method 2.
|
||||
|
||||
- With some 32kHz crystal configurations, the X32N and X32P pins may not
|
||||
have enough drive strength to keep the crystal oscillating during deep sleep.
|
||||
If this option is enabled, additional current from touchpad 9 is provided
|
||||
internally to drive the 32kHz crystal. If this option is enabled, deep sleep current
|
||||
is slightly higher (4-5uA) and the touchpad and ULP wakeup sources are not available.
|
||||
This problem is fixed in ESP32 ECO 3, so this workaround is not needed. Setting the
|
||||
project configuration to minimum revision ECO3 will disable this option, , allow
|
||||
all wakeup sources, and save some code size.
|
||||
|
||||
- "None" option will not provide additional current to external crystal
|
||||
- "Method 1" option can't ensure 100% to solve the external 32k crystal start failed
|
||||
issue, but the touchpad can work in this method.
|
||||
- "Method 2" option can solve the external 32k issue, but the touchpad can't work
|
||||
in this method.
|
||||
|
||||
config ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_NONE
|
||||
bool "None"
|
||||
config ESP32_RTC_EXT_CRYST_ADDIT_CURRENT
|
||||
bool "Method 1"
|
||||
config ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2
|
||||
bool "Method 2"
|
||||
endchoice
|
||||
|
||||
config ESP32_RTC_CLK_CAL_CYCLES
|
||||
int "Number of cycles for RTC_SLOW_CLK calibration"
|
||||
|
||||
@@ -263,9 +263,9 @@ void esp_perip_clk_init(void)
|
||||
/* For reason that only reset CPU, do not disable the clocks
|
||||
* that have been enabled before reset.
|
||||
*/
|
||||
if ((rst_reas[0] >= TGWDT_CPU_RESET && rst_reas[0] <= RTCWDT_CPU_RESET)
|
||||
if ((rst_reas[0] == TGWDT_CPU_RESET || rst_reas[0] == SW_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET)
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
|| (rst_reas[1] >= TGWDT_CPU_RESET && rst_reas[1] <= RTCWDT_CPU_RESET)
|
||||
|| (rst_reas[1] == TGWDT_CPU_RESET || rst_reas[1] == SW_CPU_RESET || rst_reas[1] == RTCWDT_CPU_RESET)
|
||||
#endif
|
||||
) {
|
||||
common_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN_REG);
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_efuse.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_mem.h"
|
||||
|
||||
#ifdef CONFIG_APP_BUILD_TYPE_ELF_RAM
|
||||
@@ -439,7 +440,7 @@ void start_cpu0_default(void)
|
||||
|
||||
extern void esp_rom_spiflash_attach(uint32_t, bool);
|
||||
esp_rom_spiflash_attach(ets_efuse_get_spiconfig(), false);
|
||||
esp_rom_spiflash_unlock();
|
||||
bootloader_flash_unlock();
|
||||
#else
|
||||
// This assumes that DROM is the first segment in the application binary, i.e. that we can read
|
||||
// the binary header through cache by accessing SOC_DROM_LOW address.
|
||||
@@ -531,12 +532,20 @@ void start_cpu1_default(void)
|
||||
}
|
||||
#endif //!CONFIG_FREERTOS_UNICORE
|
||||
|
||||
#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||
/**
|
||||
* This function overwrites a the same function of libsupc++ (part of libstdc++).
|
||||
* Consequently, libsupc++ will then follow our configured exception emergency pool size.
|
||||
*
|
||||
* It will be called even with -fno-exception for user code since the stdlib still uses exceptions.
|
||||
*/
|
||||
size_t __cxx_eh_arena_size_get(void)
|
||||
{
|
||||
#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||
return CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE;
|
||||
}
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void do_global_ctors(void)
|
||||
{
|
||||
|
||||
@@ -68,8 +68,6 @@ static portMUX_TYPE s_switch_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||
static pm_mode_t s_mode = PM_MODE_CPU_MAX;
|
||||
/* True when switch is in progress */
|
||||
static volatile bool s_is_switching;
|
||||
/* When switch is in progress, this is the mode we are switching into */
|
||||
static pm_mode_t s_new_mode = PM_MODE_CPU_MAX;
|
||||
/* Number of times each mode was locked */
|
||||
static size_t s_mode_lock_counts[PM_MODE_COUNT];
|
||||
/* Bit mask of locked modes. BIT(i) is set iff s_mode_lock_counts[i] > 0. */
|
||||
@@ -301,7 +299,7 @@ void IRAM_ATTR esp_pm_impl_switch_mode(pm_mode_t mode,
|
||||
#endif // WITH_PROFILING
|
||||
}
|
||||
portEXIT_CRITICAL_SAFE(&s_switch_lock);
|
||||
if (need_switch && new_mode != s_mode) {
|
||||
if (need_switch) {
|
||||
do_switch(new_mode);
|
||||
}
|
||||
}
|
||||
@@ -372,16 +370,15 @@ static void IRAM_ATTR do_switch(pm_mode_t new_mode)
|
||||
if (!s_is_switching) {
|
||||
break;
|
||||
}
|
||||
if (s_new_mode <= new_mode) {
|
||||
portEXIT_CRITICAL_ISR(&s_switch_lock);
|
||||
return;
|
||||
}
|
||||
if (s_need_update_ccompare[core_id]) {
|
||||
s_need_update_ccompare[core_id] = false;
|
||||
}
|
||||
portEXIT_CRITICAL_ISR(&s_switch_lock);
|
||||
} while (true);
|
||||
s_new_mode = new_mode;
|
||||
if (new_mode == s_mode) {
|
||||
portEXIT_CRITICAL_ISR(&s_switch_lock);
|
||||
return;
|
||||
}
|
||||
s_is_switching = true;
|
||||
bool config_changed = s_config_changed;
|
||||
s_config_changed = false;
|
||||
@@ -495,8 +492,8 @@ void esp_pm_impl_waiti(void)
|
||||
* the lock so that vApplicationSleep can attempt to enter light sleep.
|
||||
*/
|
||||
esp_pm_impl_idle_hook();
|
||||
s_skipped_light_sleep[core_id] = false;
|
||||
}
|
||||
s_skipped_light_sleep[core_id] = true;
|
||||
#else
|
||||
asm("waiti 0");
|
||||
#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
||||
|
||||
@@ -419,7 +419,8 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source)
|
||||
|
||||
esp_err_t esp_sleep_enable_ulp_wakeup(void)
|
||||
{
|
||||
#ifdef CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT
|
||||
#if ((defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT) || (defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2))
|
||||
ESP_LOGE(TAG, "Failed to enable wakeup when provide current to external 32kHz crystal");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
#endif
|
||||
#ifdef CONFIG_ESP32_ULP_COPROC_ENABLED
|
||||
@@ -455,7 +456,8 @@ static void timer_wakeup_prepare(void)
|
||||
|
||||
esp_err_t esp_sleep_enable_touchpad_wakeup(void)
|
||||
{
|
||||
#ifdef CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT
|
||||
#if ((defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT) || (defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2))
|
||||
ESP_LOGE(TAG, "Failed to enable wakeup when provide current to external 32kHz crystal");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
#endif
|
||||
if (s_config.wakeup_triggers & (RTC_EXT0_TRIG_EN)) {
|
||||
@@ -660,10 +662,14 @@ static uint32_t get_power_down_flags(void)
|
||||
|
||||
// Labels are defined in the linker script, see esp32.ld.
|
||||
extern int _rtc_slow_length;
|
||||
/**
|
||||
* Compiler considers "(size_t) &_rtc_slow_length > 0" to always be true.
|
||||
* So use a volatile variable to prevent compiler from doing this optimization.
|
||||
*/
|
||||
volatile size_t rtc_slow_mem_used = (size_t)&_rtc_slow_length;
|
||||
|
||||
if ((s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] == ESP_PD_OPTION_AUTO) &&
|
||||
((size_t) &_rtc_slow_length > 0 ||
|
||||
(s_config.wakeup_triggers & RTC_ULP_TRIG_EN))) {
|
||||
(rtc_slow_mem_used > 0 || (s_config.wakeup_triggers & RTC_ULP_TRIG_EN))) {
|
||||
s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] = ESP_PD_OPTION_ON;
|
||||
}
|
||||
|
||||
@@ -696,10 +702,11 @@ static uint32_t get_power_down_flags(void)
|
||||
}
|
||||
|
||||
const char* option_str[] = {"OFF", "ON", "AUTO(OFF)" /* Auto works as OFF */};
|
||||
ESP_LOGD(TAG, "RTC_PERIPH: %s, RTC_SLOW_MEM: %s, RTC_FAST_MEM: %s",
|
||||
option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH]],
|
||||
option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM]],
|
||||
option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM]]);
|
||||
/* This function is called from a critical section, log with ESP_EARLY_LOGD. */
|
||||
ESP_EARLY_LOGD(TAG, "RTC_PERIPH: %s, RTC_SLOW_MEM: %s, RTC_FAST_MEM: %s",
|
||||
option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH]],
|
||||
option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM]],
|
||||
option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM]]);
|
||||
|
||||
// Prepare flags based on the selected options
|
||||
uint32_t pd_flags = 0;
|
||||
|
||||
@@ -189,10 +189,11 @@ esp_err_t esp_spiram_add_to_heapalloc(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static uint8_t *dma_heap;
|
||||
|
||||
esp_err_t esp_spiram_reserve_dma_pool(size_t size) {
|
||||
if (size == 0) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
ESP_EARLY_LOGI(TAG, "Reserving pool of %dK of internal memory for DMA/internal allocations", size/1024);
|
||||
/* Pool may be allocated in multiple non-contiguous chunks, depending on available RAM */
|
||||
while (size > 0) {
|
||||
@@ -200,7 +201,8 @@ esp_err_t esp_spiram_reserve_dma_pool(size_t size) {
|
||||
next_size = MIN(next_size, size);
|
||||
|
||||
ESP_EARLY_LOGD(TAG, "Allocating block of size %d bytes", next_size);
|
||||
dma_heap = heap_caps_malloc(next_size, MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL);
|
||||
|
||||
uint8_t *dma_heap = heap_caps_malloc(next_size, MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL);
|
||||
if (!dma_heap || next_size == 0) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
@@ -229,9 +229,10 @@ void esp_perip_clk_init(void)
|
||||
/* For reason that only reset CPU, do not disable the clocks
|
||||
* that have been enabled before reset.
|
||||
*/
|
||||
if (rst_reas[0] >= TG0WDT_CPU_RESET &&
|
||||
rst_reas[0] <= TG0WDT_CPU_RESET &&
|
||||
rst_reas[0] != RTCWDT_BROWN_OUT_RESET) {
|
||||
if (rst_reas[0] == TG0WDT_CPU_RESET ||
|
||||
rst_reas[0] == RTC_SW_CPU_RESET ||
|
||||
rst_reas[0] == RTCWDT_CPU_RESET ||
|
||||
rst_reas[0] == TG1WDT_CPU_RESET) {
|
||||
common_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN_REG);
|
||||
hwcrypto_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN1_REG);
|
||||
wifi_bt_sdio_clk = ~DPORT_READ_PERI_REG(DPORT_WIFI_CLK_EN_REG);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user