mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
rebase the origin to the local
This commit is contained in:
commit
2be5e73090
2
.gitignore
vendored
2
.gitignore
vendored
@ -35,6 +35,8 @@ docs/man/
|
||||
tools/unit-test-app/sdkconfig
|
||||
tools/unit-test-app/sdkconfig.old
|
||||
tools/unit-test-app/build
|
||||
tools/unit-test-app/builds
|
||||
tools/unit-test-app/output
|
||||
|
||||
# AWS IoT Examples require device-specific certs/keys
|
||||
examples/protocols/aws_iot/*/main/certs/*.pem.*
|
||||
|
195
.gitlab-ci.yml
195
.gitlab-ci.yml
@ -113,19 +113,17 @@ build_esp_idf_tests:
|
||||
<<: *build_template
|
||||
artifacts:
|
||||
paths:
|
||||
- tools/unit-test-app/build/*.bin
|
||||
- tools/unit-test-app/build/*.elf
|
||||
- tools/unit-test-app/build/*.map
|
||||
- tools/unit-test-app/build/download.config
|
||||
- tools/unit-test-app/build/bootloader/*.bin
|
||||
- tools/unit-test-app/output
|
||||
- components/idf_test/unit_test/TestCaseAll.yml
|
||||
- components/idf_test/unit_test/CIConfigs/*.yml
|
||||
expire_in: 6 mos
|
||||
script:
|
||||
- cd tools/unit-test-app
|
||||
- make TESTS_ALL=1
|
||||
# cut last line in case make V=0/1 is set by default
|
||||
- make print_flash_cmd | tail -n 1 > build/download.config
|
||||
- make help # make sure kconfig tools are built in single process
|
||||
- make ut-clean-all-configs
|
||||
- export EXTRA_CFLAGS="-Werror -Werror=deprecated-declarations"
|
||||
- export EXTRA_CXXFLAGS=${EXTRA_CFLAGS}
|
||||
- make ut-build-all-configs TESTS_ALL=1
|
||||
- python tools/UnitTestParser.py
|
||||
|
||||
.build_examples_template: &build_examples_template
|
||||
@ -135,6 +133,7 @@ build_esp_idf_tests:
|
||||
- build_examples/*/*/*/build/*.bin
|
||||
- build_examples/*/*/*/build/*.elf
|
||||
- build_examples/*/*/*/build/*.map
|
||||
- build_examples/*/*/*/build/download.config
|
||||
- build_examples/*/*/*/build/bootloader/*.bin
|
||||
expire_in: 1 week
|
||||
variables:
|
||||
@ -413,21 +412,29 @@ check_submodule_sync:
|
||||
assign_test:
|
||||
<<: *build_template
|
||||
stage: assign_test
|
||||
dependencies:
|
||||
- build_esp_idf_tests
|
||||
- build_ssc
|
||||
# gitlab ci do not support match job with RegEx or wildcard now in dependencies.
|
||||
# we have a lot build example jobs. now we don't use dependencies, just download all artificats of build stage.
|
||||
variables:
|
||||
UT_BIN_PATH: "tools/unit-test-app/output"
|
||||
OUTPUT_BIN_PATH: "test_bins/ESP32_IDF"
|
||||
TEST_FW_PATH: "$CI_PROJECT_DIR/tools/tiny-test-fw"
|
||||
EXAMPLE_CONFIG_OUTPUT_PATH: "$CI_PROJECT_DIR/examples/test_configs"
|
||||
artifacts:
|
||||
paths:
|
||||
- test_bins
|
||||
- components/idf_test/*/CIConfigs
|
||||
- components/idf_test/*/TC.sqlite
|
||||
- $EXAMPLE_CONFIG_OUTPUT_PATH
|
||||
expire_in: 1 mos
|
||||
before_script: *add_gitlab_key_before
|
||||
script:
|
||||
# first move test bins together: test_bins/CHIP_SDK/TestApp/bin_files
|
||||
- mkdir -p test_bins/ESP32_IDF/UT
|
||||
- cp -r tools/unit-test-app/build/* test_bins/ESP32_IDF/UT
|
||||
- cp -r SSC/ssc_bin/* test_bins/ESP32_IDF
|
||||
- mkdir -p $OUTPUT_BIN_PATH
|
||||
# copy and rename folder name to "UT_config"
|
||||
- for CONFIG in $(ls $UT_BIN_PATH); do cp -r "$UT_BIN_PATH/$CONFIG" "$OUTPUT_BIN_PATH/UT_$CONFIG"; done
|
||||
- cp -r SSC/ssc_bin/* $OUTPUT_BIN_PATH
|
||||
# assign example tests
|
||||
- python $TEST_FW_PATH/CIAssignExampleTest.py $IDF_PATH/examples $IDF_PATH/.gitlab-ci.yml $EXAMPLE_CONFIG_OUTPUT_PATH
|
||||
# clone test script to assign tests
|
||||
- git clone $TEST_SCRIPT_REPOSITORY
|
||||
- cd auto_test_script
|
||||
@ -437,6 +444,34 @@ assign_test:
|
||||
# assgin integration test cases
|
||||
- python CIAssignTestCases.py -t $IDF_PATH/components/idf_test/integration_test -c $IDF_PATH/.gitlab-ci.yml -b $IDF_PATH/test_bins
|
||||
|
||||
.example_test_template: &example_test_template
|
||||
stage: test
|
||||
when: on_success
|
||||
only:
|
||||
- master
|
||||
- /^release\/v/
|
||||
- /^v\d+\.\d+(\.\d+)?($|-)/
|
||||
- triggers
|
||||
# gitlab ci do not support match job with RegEx or wildcard now in dependencies.
|
||||
# we have a lot build example jobs and the binaries them exceed the limitation of artifacts.
|
||||
# we can't artifact them in one job. For example test jobs, download all artifacts from previous stages.
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- $LOG_PATH
|
||||
expire_in: 6 mos
|
||||
variables:
|
||||
TEST_FW_PATH: "$CI_PROJECT_DIR/tools/tiny-test-fw"
|
||||
TEST_CASE_PATH: "$CI_PROJECT_DIR/examples"
|
||||
CONFIG_FILE: "$CI_PROJECT_DIR/examples/test_configs/$CI_JOB_NAME.yml"
|
||||
LOG_PATH: "$CI_PROJECT_DIR/TEST_LOGS"
|
||||
script:
|
||||
# first test if config file exists, if not exist, exit 0
|
||||
- test -e $CONFIG_FILE || exit 0
|
||||
- cd $TEST_FW_PATH
|
||||
# run test
|
||||
- python Runner.py $TEST_CASE_PATH -c $CONFIG_FILE
|
||||
|
||||
.test_template: &test_template
|
||||
stage: test
|
||||
when: on_success
|
||||
@ -507,47 +542,179 @@ nvs_compatible_test:
|
||||
# run test
|
||||
- python CIRunner.py -l "$LOG_PATH/$CI_JOB_NAME" -c $CONFIG_FILE -e $LOCAL_ENV_CONFIG_PATH -t $TEST_CASE_FILE_PATH -m $MODULE_UPDATE_FILE
|
||||
|
||||
example_test_001_01:
|
||||
<<: *example_test_template
|
||||
tags:
|
||||
- ESP32
|
||||
- Example_WIFI
|
||||
|
||||
UT_001_01:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_1
|
||||
- UT_default
|
||||
|
||||
UT_001_02:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_1
|
||||
- UT_default
|
||||
|
||||
UT_001_03:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_1
|
||||
- UT_default
|
||||
|
||||
UT_001_04:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_1
|
||||
- UT_default
|
||||
|
||||
UT_001_05:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_SDMODE
|
||||
- UT_default
|
||||
|
||||
UT_001_06:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_SPIMODE
|
||||
- UT_default
|
||||
|
||||
UT_001_07:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_1
|
||||
- UT_default
|
||||
|
||||
UT_001_08:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_1
|
||||
- UT_default
|
||||
|
||||
UT_002_01:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_1
|
||||
- UT_release
|
||||
|
||||
UT_002_02:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_1
|
||||
- UT_release
|
||||
|
||||
UT_002_03:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_1
|
||||
- UT_release
|
||||
|
||||
UT_002_04:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_1
|
||||
- UT_release
|
||||
|
||||
UT_002_05:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_SDMODE
|
||||
- UT_release
|
||||
|
||||
UT_002_06:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_SPIMODE
|
||||
- UT_release
|
||||
|
||||
UT_002_07:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_1
|
||||
- UT_release
|
||||
|
||||
UT_002_08:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_1
|
||||
- UT_release
|
||||
|
||||
UT_003_01:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_1
|
||||
- UT_single_core
|
||||
|
||||
UT_003_02:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_1
|
||||
- UT_single_core
|
||||
|
||||
UT_003_03:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_1
|
||||
- UT_single_core
|
||||
|
||||
UT_003_04:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_1
|
||||
- UT_single_core
|
||||
|
||||
UT_003_05:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_SDMODE
|
||||
- UT_single_core
|
||||
|
||||
UT_003_06:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_SPIMODE
|
||||
- UT_single_core
|
||||
|
||||
UT_003_07:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_1
|
||||
- UT_single_core
|
||||
|
||||
UT_003_08:
|
||||
<<: *unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_1
|
||||
- UT_single_core
|
||||
|
||||
IT_001_01:
|
||||
<<: *test_template
|
||||
|
14
Kconfig
14
Kconfig
@ -93,7 +93,19 @@ config OPTIMIZATION_ASSERTIONS_DISABLED
|
||||
|
||||
endchoice # assertions
|
||||
|
||||
endmenu # Optimization level
|
||||
config CXX_EXCEPTIONS
|
||||
bool "Enable C++ exceptions"
|
||||
default n
|
||||
help
|
||||
Enabling this option compiles all IDF C++ files with exception support enabled.
|
||||
|
||||
Disabling this option disables C++ exception support in all compiled files, and any libstdc++ code which throws
|
||||
an exception will abort instead.
|
||||
|
||||
Enabling this option currently adds an additional 20KB of heap overhead, and 4KB of additional heap is allocated
|
||||
the first time an exception is thrown in user code.
|
||||
|
||||
endmenu # Compiler Options
|
||||
|
||||
menu "Component config"
|
||||
source "$COMPONENT_KCONFIGS"
|
||||
|
@ -63,13 +63,13 @@ config SYSVIEW_ENABLE
|
||||
help
|
||||
Enables supporrt for SEGGER SystemView tracing functionality.
|
||||
|
||||
if !FREERTOS_UNICORE
|
||||
choice SYSVIEW_TS_SOURCE
|
||||
prompt "ESP32 timer to use as SystemView timestamp source"
|
||||
depends on SYSVIEW_ENABLE
|
||||
default SYSVIEW_TS_SOURCE_TIMER_00
|
||||
help
|
||||
SystemView needs one source for timestamps when tracing events from both cores.
|
||||
SystemView needs to use a hardware timer as the source of timestamps
|
||||
when tracing
|
||||
This option selects HW timer for it.
|
||||
|
||||
config SYSVIEW_TS_SOURCE_TIMER_00
|
||||
@ -93,7 +93,6 @@ config SYSVIEW_TS_SOURCE_TIMER_11
|
||||
Select this to use timer 1 of group 1
|
||||
|
||||
endchoice
|
||||
endif #FREERTOS_UNICORE
|
||||
|
||||
config SYSVIEW_EVT_OVERFLOW_ENABLE
|
||||
bool "Trace Buffer Overflow Event"
|
||||
|
@ -203,8 +203,6 @@ const static char *TAG = "esp_apptrace";
|
||||
#define ESP_APPTRACE_LOGV( format, ... ) ESP_APPTRACE_LOG_LEV(V, ESP_LOG_VERBOSE, format, ##__VA_ARGS__)
|
||||
#define ESP_APPTRACE_LOGO( format, ... ) ESP_APPTRACE_LOG_LEV(E, ESP_LOG_NONE, format, ##__VA_ARGS__)
|
||||
|
||||
#define ESP_APPTRACE_CPUTICKS2US(_t_) ((_t_)/(XT_CLOCK_FREQ/1000000))
|
||||
|
||||
// TODO: move these (and same definitions in trax.c to dport_reg.h)
|
||||
#define TRACEMEM_MUX_PROBLK0_APPBLK1 0
|
||||
#define TRACEMEM_MUX_BLK0_ONLY 1
|
||||
|
@ -15,23 +15,24 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_app_trace_util.h"
|
||||
#include "esp_clk.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////// TIMEOUT /////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// TODO: get actual clock from PLL config
|
||||
#define ESP_APPTRACE_CPUTICKS2US(_t_) ((_t_)/(XT_CLOCK_FREQ/1000000))
|
||||
#define ESP_APPTRACE_US2CPUTICKS(_t_) ((_t_)*(XT_CLOCK_FREQ/1000000))
|
||||
#define ESP_APPTRACE_CPUTICKS2US(_t_, _cpu_freq_) ((_t_)/(_cpu_freq_/1000000))
|
||||
#define ESP_APPTRACE_US2CPUTICKS(_t_, _cpu_freq_) ((_t_)*(_cpu_freq_/1000000))
|
||||
|
||||
esp_err_t esp_apptrace_tmo_check(esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
int cpu_freq = esp_clk_cpu_freq();
|
||||
if (tmo->tmo != ESP_APPTRACE_TMO_INFINITE) {
|
||||
unsigned cur = portGET_RUN_TIME_COUNTER_VALUE();
|
||||
if (tmo->start <= cur) {
|
||||
tmo->elapsed = ESP_APPTRACE_CPUTICKS2US(cur - tmo->start);
|
||||
tmo->elapsed = ESP_APPTRACE_CPUTICKS2US(cur - tmo->start, cpu_freq);
|
||||
} else {
|
||||
tmo->elapsed = ESP_APPTRACE_CPUTICKS2US(0xFFFFFFFF - tmo->start + cur);
|
||||
tmo->elapsed = ESP_APPTRACE_CPUTICKS2US(0xFFFFFFFF - tmo->start + cur, cpu_freq);
|
||||
}
|
||||
if (tmo->elapsed >= tmo->tmo) {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
@ -54,7 +55,11 @@ esp_err_t esp_apptrace_lock_take(esp_apptrace_lock_t *lock, esp_apptrace_tmo_t *
|
||||
// FIXME: if mux is busy it is not good idea to loop during the whole tmo with disabled IRQs.
|
||||
// So we check mux state using zero tmo, restore IRQs and let others tasks/IRQs to run on this CPU
|
||||
// while we are doing our own tmo check.
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
|
||||
bool success = vPortCPUAcquireMutexTimeout(&lock->mux, 0, __FUNCTION__, __LINE__);
|
||||
#else
|
||||
bool success = vPortCPUAcquireMutexTimeout(&lock->mux, 0);
|
||||
#endif
|
||||
if (success) {
|
||||
lock->int_state = int_state;
|
||||
return ESP_OK;
|
||||
@ -75,7 +80,11 @@ esp_err_t esp_apptrace_lock_give(esp_apptrace_lock_t *lock)
|
||||
unsigned int_state = lock->int_state;
|
||||
// after call to the following func we can not be sure that lock->int_state
|
||||
// is not overwritten by other CPU who has acquired the mux just after we released it. See esp_apptrace_lock_take().
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
|
||||
vPortCPUReleaseMutex(&lock->mux, __FUNCTION__, __LINE__);
|
||||
#else
|
||||
vPortCPUReleaseMutex(&lock->mux);
|
||||
#endif
|
||||
portEXIT_CRITICAL_NESTED(int_state);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -14,9 +14,9 @@
|
||||
|
||||
// This module implements runtime file I/O API for GCOV.
|
||||
|
||||
#include "esp_task_wdt.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_task_wdt.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/timer_group_struct.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
|
@ -70,6 +70,7 @@ Revision: $Rev: 3734 $
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_app_trace_util.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_clk.h"
|
||||
|
||||
extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
|
||||
|
||||
@ -85,14 +86,12 @@ extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
|
||||
// The target device name
|
||||
#define SYSVIEW_DEVICE_NAME "ESP32"
|
||||
|
||||
// Timer group timer divisor
|
||||
#define SYSVIEW_TIMER_DIV 2
|
||||
// Frequency of the timestamp.
|
||||
#if CONFIG_FREERTOS_UNICORE == 0
|
||||
#define SYSVIEW_TIMESTAMP_FREQ (TIMER_BASE_CLK/2)
|
||||
#else
|
||||
#define SYSVIEW_TIMESTAMP_FREQ (XT_CLOCK_FREQ)
|
||||
#endif
|
||||
#define SYSVIEW_TIMESTAMP_FREQ (esp_clk_apb_freq() / SYSVIEW_TIMER_DIV)
|
||||
// System Frequency.
|
||||
#define SYSVIEW_CPU_FREQ (XT_CLOCK_FREQ)
|
||||
#define SYSVIEW_CPU_FREQ (esp_clk_cpu_freq())
|
||||
|
||||
// The lowest RAM address used for IDs (pointers)
|
||||
#define SYSVIEW_RAM_BASE (0x3F400000)
|
||||
@ -104,10 +103,8 @@ extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
|
||||
#define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER1_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
|
||||
#endif
|
||||
|
||||
#if CONFIG_FREERTOS_UNICORE == 0
|
||||
static timer_idx_t s_ts_timer_idx;
|
||||
static timer_group_t s_ts_timer_group;
|
||||
#endif
|
||||
|
||||
// SystemView is single core specific: it implies that SEGGER_SYSVIEW_LOCK()
|
||||
// disables IRQs (disables rescheduling globaly). So we can not use finite timeouts for locks and return error
|
||||
@ -214,7 +211,6 @@ static void _cbSendSystemDesc(void) {
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
#if CONFIG_FREERTOS_UNICORE == 0
|
||||
static void SEGGER_SYSVIEW_TS_Init()
|
||||
{
|
||||
timer_config_t config;
|
||||
@ -238,7 +234,7 @@ static void SEGGER_SYSVIEW_TS_Init()
|
||||
config.alarm_en = 0;
|
||||
config.auto_reload = 0;
|
||||
config.counter_dir = TIMER_COUNT_UP;
|
||||
config.divider = 2;
|
||||
config.divider = SYSVIEW_TIMER_DIV;
|
||||
config.counter_en = 0;
|
||||
/*Configure timer*/
|
||||
timer_init(s_ts_timer_group, s_ts_timer_idx, &config);
|
||||
@ -247,14 +243,11 @@ static void SEGGER_SYSVIEW_TS_Init()
|
||||
/*Enable timer interrupt*/
|
||||
timer_start(s_ts_timer_group, s_ts_timer_idx);
|
||||
}
|
||||
#endif
|
||||
|
||||
void SEGGER_SYSVIEW_Conf(void) {
|
||||
U32 disable_evts = 0;
|
||||
|
||||
#if CONFIG_FREERTOS_UNICORE == 0
|
||||
SEGGER_SYSVIEW_TS_Init();
|
||||
#endif
|
||||
SEGGER_SYSVIEW_Init(SYSVIEW_TIMESTAMP_FREQ, SYSVIEW_CPU_FREQ,
|
||||
&SYSVIEW_X_OS_TraceAPI, _cbSendSystemDesc);
|
||||
SEGGER_SYSVIEW_SetRAMBase(SYSVIEW_RAM_BASE);
|
||||
|
@ -26,16 +26,6 @@ const static char *TAG = "segger_rtt";
|
||||
|
||||
#define SYSVIEW_EVENTS_BUF_SZ 255U
|
||||
|
||||
#if SYSVIEW_RTT_MAX_DATA_RATE > 0
|
||||
#include "SEGGER_SYSVIEW_Conf.h"
|
||||
#if CONFIG_FREERTOS_UNICORE == 0
|
||||
#include "driver/timer.h"
|
||||
#define SYSVIEW_TIMESTAMP_FREQ (TIMER_BASE_CLK/2)
|
||||
#else
|
||||
#define SYSVIEW_TIMESTAMP_FREQ (XT_CLOCK_FREQ)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// size of down channel data buf
|
||||
#define SYSVIEW_DOWN_BUF_SIZE 32
|
||||
#define SEGGER_HOST_WAIT_TMO 500 //us
|
||||
|
@ -67,7 +67,7 @@ static void esp_apptrace_test_timer_init(int timer_group, int timer_idx, uint32_
|
||||
config.alarm_en = 1;
|
||||
config.auto_reload = 1;
|
||||
config.counter_dir = TIMER_COUNT_UP;
|
||||
config.divider = 1;
|
||||
config.divider = 2; //Range is 2 to 65536
|
||||
config.intr_type = TIMER_INTR_LEVEL;
|
||||
config.counter_en = TIMER_PAUSE;
|
||||
/*Configure timer*/
|
||||
@ -87,8 +87,6 @@ static void esp_apptrace_test_timer_init(int timer_group, int timer_idx, uint32_
|
||||
#define ESP_APPTRACE_TEST_WRITE_FROM_ISR(_b_, _s_) esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, _b_, _s_, 0UL)
|
||||
#define ESP_APPTRACE_TEST_WRITE_NOWAIT(_b_, _s_) esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, _b_, _s_, 0)
|
||||
|
||||
#define ESP_APPTRACE_TEST_CPUTICKS2US(_t_) ((_t_)/(XT_CLOCK_FREQ/1000000))
|
||||
|
||||
typedef struct {
|
||||
uint8_t *buf;
|
||||
uint32_t buf_sz;
|
||||
@ -405,7 +403,7 @@ static void esp_apptrace_test_ts_init(int timer_group, int timer_idx)
|
||||
config.alarm_en = 0;
|
||||
config.auto_reload = 0;
|
||||
config.counter_dir = TIMER_COUNT_UP;
|
||||
config.divider = 1;
|
||||
config.divider = 2; //Range is 2 to 65536
|
||||
config.counter_en = 0;
|
||||
/*Configure timer*/
|
||||
timer_init(timer_group, timer_idx, &config);
|
||||
@ -422,7 +420,7 @@ static void esp_apptrace_test_ts_cleanup()
|
||||
config.alarm_en = 0;
|
||||
config.auto_reload = 0;
|
||||
config.counter_dir = TIMER_COUNT_UP;
|
||||
config.divider = 1;
|
||||
config.divider = 2; //Range is 2 to 65536
|
||||
config.counter_en = 0;
|
||||
/*Configure timer*/
|
||||
timer_init(s_ts_timer_group, s_ts_timer_idx, &config);
|
||||
|
@ -43,6 +43,16 @@ config BOOTLOADER_SPI_WP_PIN
|
||||
|
||||
The default value (GPIO 7) is correct for WP pin on ESP32-D2WD integrated flash.
|
||||
|
||||
config BOOTLOADER_VDDSDIO_BOOST
|
||||
bool "Increase VDDSDIO LDO voltage to 1.9V"
|
||||
default y
|
||||
help
|
||||
If this option is enabled, and VDDSDIO LDO is set to 1.8V (using EFUSE
|
||||
or MTDI bootstrapping pin), bootloader will change LDO settings to
|
||||
output 1.9V instead. This helps prevent flash chip from browning out
|
||||
during flash programming operations.
|
||||
For 3.3V flash, this option has no effect.
|
||||
|
||||
endmenu # Bootloader
|
||||
|
||||
|
||||
|
@ -73,6 +73,8 @@ static void set_cache_and_start_app(uint32_t drom_addr,
|
||||
uint32_t irom_size,
|
||||
uint32_t entry_addr);
|
||||
static void update_flash_config(const esp_image_header_t* pfhdr);
|
||||
static void vddsdio_configure();
|
||||
static void flash_gpio_configure();
|
||||
static void clock_configure(void);
|
||||
static void uart_console_configure(void);
|
||||
static void wdt_reset_check(void);
|
||||
@ -443,6 +445,8 @@ static bool load_boot_image(const bootloader_state_t *bs, int start_index, esp_i
|
||||
|
||||
void bootloader_main()
|
||||
{
|
||||
vddsdio_configure();
|
||||
flash_gpio_configure();
|
||||
clock_configure();
|
||||
uart_console_configure();
|
||||
wdt_reset_check();
|
||||
@ -737,6 +741,105 @@ static void print_flash_info(const esp_image_header_t* phdr)
|
||||
}
|
||||
|
||||
|
||||
static void vddsdio_configure()
|
||||
{
|
||||
#if CONFIG_BOOTLOADER_VDDSDIO_BOOST
|
||||
rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
|
||||
if (cfg.tieh == 0) { // 1.8V is used
|
||||
cfg.drefh = 3;
|
||||
cfg.drefm = 3;
|
||||
cfg.drefl = 3;
|
||||
cfg.force = 1;
|
||||
cfg.enable = 1;
|
||||
rtc_vddsdio_set_config(cfg);
|
||||
ets_delay_us(10); // wait for regulator to become stable
|
||||
}
|
||||
#endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST
|
||||
}
|
||||
|
||||
|
||||
#define FLASH_CLK_IO 6
|
||||
#define FLASH_CS_IO 11
|
||||
#define FLASH_SPIQ_IO 7
|
||||
#define FLASH_SPID_IO 8
|
||||
#define FLASH_SPIWP_IO 10
|
||||
#define FLASH_SPIHD_IO 9
|
||||
#define FLASH_IO_MATRIX_DUMMY_40M 1
|
||||
#define FLASH_IO_MATRIX_DUMMY_80M 2
|
||||
static void IRAM_ATTR flash_gpio_configure()
|
||||
{
|
||||
int spi_cache_dummy = 0;
|
||||
int drv = 2;
|
||||
#if CONFIG_FLASHMODE_QIO
|
||||
spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN; //qio 3
|
||||
#elif CONFIG_FLASHMODE_QOUT
|
||||
spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; //qout 7
|
||||
#elif CONFIG_FLASHMODE_DIO
|
||||
spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN; //dio 3
|
||||
#elif CONFIG_FLASHMODE_DOUT
|
||||
spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; //dout 7
|
||||
#endif
|
||||
/* dummy_len_plus values defined in ROM for SPI flash configuration */
|
||||
extern uint8_t g_rom_spiflash_dummy_len_plus[];
|
||||
#if CONFIG_ESPTOOLPY_FLASHFREQ_40M
|
||||
g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_40M;
|
||||
g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_40M;
|
||||
SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_40M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY
|
||||
#elif CONFIG_ESPTOOLPY_FLASHFREQ_80M
|
||||
g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_80M;
|
||||
g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_80M;
|
||||
SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_80M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY
|
||||
drv = 3;
|
||||
#endif
|
||||
|
||||
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
|
||||
uint32_t pkg_ver = chip_ver & 0x7;
|
||||
|
||||
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) {
|
||||
// For ESP32D2WD the SPI pins are already configured
|
||||
ESP_LOGI(TAG, "Detected ESP32D2WD");
|
||||
//flash clock signal should come from IO MUX.
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
|
||||
} else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) {
|
||||
// For ESP32PICOD2 the SPI pins are already configured
|
||||
ESP_LOGI(TAG, "Detected ESP32PICOD2");
|
||||
//flash clock signal should come from IO MUX.
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
|
||||
} else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) {
|
||||
// For ESP32PICOD4 the SPI pins are already configured
|
||||
ESP_LOGI(TAG, "Detected ESP32PICOD4");
|
||||
//flash clock signal should come from IO MUX.
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Detected ESP32");
|
||||
const uint32_t spiconfig = ets_efuse_get_spiconfig();
|
||||
if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) {
|
||||
gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0);
|
||||
gpio_matrix_out(FLASH_SPIQ_IO, SPIQ_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPIQ_IO, SPIQ_IN_IDX, 0);
|
||||
gpio_matrix_out(FLASH_SPID_IO, SPID_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPID_IO, SPID_IN_IDX, 0);
|
||||
gpio_matrix_out(FLASH_SPIWP_IO, SPIWP_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPIWP_IO, SPIWP_IN_IDX, 0);
|
||||
gpio_matrix_out(FLASH_SPIHD_IO, SPIHD_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPIHD_IO, SPIHD_IN_IDX, 0);
|
||||
//select pin function gpio
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO);
|
||||
// flash clock signal should come from IO MUX.
|
||||
// set drive ability for clock
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void clock_configure(void)
|
||||
{
|
||||
/* Set CPU to 80MHz. Keep other clocks unmodified. */
|
||||
|
@ -1,14 +1,96 @@
|
||||
menuconfig BT_ENABLED
|
||||
menu Bluetooth
|
||||
|
||||
|
||||
config BT_ENABLED
|
||||
bool "Bluetooth"
|
||||
help
|
||||
Select this option to enable Bluetooth and show the submenu with Bluetooth configuration choices.
|
||||
|
||||
menuconfig BLUEDROID_ENABLED
|
||||
bool "Bluedroid Bluetooth stack enabled"
|
||||
choice BTDM_CONTROLLER_PINNED_TO_CORE_CHOICE
|
||||
prompt "The cpu core which bluetooth controller run"
|
||||
depends on BT_ENABLED && !FREERTOS_UNICORE
|
||||
help
|
||||
Specify the cpu core to run bluetooth controller.
|
||||
Can not specify no-affinity.
|
||||
|
||||
config BTDM_CONTROLLER_PINNED_TO_CORE_0
|
||||
bool "Core 0 (PRO CPU)"
|
||||
config BTDM_CONTROLLER_PINNED_TO_CORE_1
|
||||
bool "Core 1 (APP CPU)"
|
||||
depends on !FREERTOS_UNICORE
|
||||
endchoice
|
||||
|
||||
config BTDM_CONTROLLER_PINNED_TO_CORE
|
||||
int
|
||||
default 0 if BTDM_CONTROLLER_PINNED_TO_CORE_0
|
||||
default 1 if BTDM_CONTROLLER_PINNED_TO_CORE_1
|
||||
default 0
|
||||
|
||||
choice BTDM_CONTROLLER_HCI_MODE_CHOICE
|
||||
prompt "HCI mode"
|
||||
depends on BT_ENABLED
|
||||
default y
|
||||
help
|
||||
This enables the default Bluedroid Bluetooth stack
|
||||
help
|
||||
Speicify HCI mode as VHCI or UART(H4)
|
||||
|
||||
config BTDM_CONTROLLER_HCI_MODE_VHCI
|
||||
bool "VHCI"
|
||||
help
|
||||
Normal option. Mostly, choose this VHCI when bluetooth host run on ESP32, too.
|
||||
|
||||
config BTDM_CONTROLLER_HCI_MODE_UART_H4
|
||||
bool "UART(H4)"
|
||||
help
|
||||
If use external bluetooth host which run on other hardware and use UART as the HCI interface,
|
||||
choose this option.
|
||||
endchoice
|
||||
|
||||
menu "HCI UART(H4) Options"
|
||||
visible if BTDM_CONTROLLER_HCI_MODE_UART_H4
|
||||
|
||||
config BT_HCI_UART_NO
|
||||
int "UART Number for HCI"
|
||||
depends on BTDM_CONTROLLER_HCI_MODE_UART_H4
|
||||
range 1 2
|
||||
default 1
|
||||
help
|
||||
Uart number for HCI. The available uart is UART1 and UART2.
|
||||
|
||||
config BT_HCI_UART_BAUDRATE
|
||||
int "UART Baudrate for HCI"
|
||||
depends on BTDM_CONTROLLER_HCI_MODE_UART_H4
|
||||
range 115200 921600
|
||||
default 921600
|
||||
help
|
||||
UART Baudrate for HCI. Please use standard baudrate.
|
||||
endmenu
|
||||
|
||||
menuconfig BLUEDROID_ENABLED
|
||||
bool "Bluedroid Enable"
|
||||
depends on BTDM_CONTROLLER_HCI_MODE_VHCI
|
||||
default y
|
||||
help
|
||||
This enables the default Bluedroid Bluetooth stack
|
||||
|
||||
choice BLUEDROID_PINNED_TO_CORE_CHOICE
|
||||
prompt "The cpu core which Bluedroid run"
|
||||
depends on BLUEDROID_ENABLED && !FREERTOS_UNICORE
|
||||
help
|
||||
Which the cpu core to run Bluedroid. Can choose core0 and core1.
|
||||
Can not specify no-affinity.
|
||||
|
||||
config BLUEDROID_PINNED_TO_CORE_0
|
||||
bool "Core 0 (PRO CPU)"
|
||||
config BLUEDROID_PINNED_TO_CORE_1
|
||||
bool "Core 1 (APP CPU)"
|
||||
depends on !FREERTOS_UNICORE
|
||||
endchoice
|
||||
|
||||
config BLUEDROID_PINNED_TO_CORE
|
||||
int
|
||||
depends on BLUEDROID_ENABLED
|
||||
default 0 if BLUEDROID_PINNED_TO_CORE_0
|
||||
default 1 if BLUEDROID_PINNED_TO_CORE_1
|
||||
default 0
|
||||
|
||||
config BTC_TASK_STACK_SIZE
|
||||
int "Bluetooth event (callback to application) task stack size"
|
||||
@ -67,44 +149,6 @@ config BT_ACL_CONNECTIONS
|
||||
help
|
||||
Maximum BT/BLE connection count
|
||||
|
||||
#disable now for app cpu due to a known issue
|
||||
config BTDM_CONTROLLER_RUN_APP_CPU
|
||||
bool "Run controller on APP CPU"
|
||||
depends on BT_ENABLED && !FREERTOS_UNICORE && 0
|
||||
default n
|
||||
help
|
||||
Run controller on APP CPU.
|
||||
|
||||
config BTDM_CONTROLLER_RUN_CPU
|
||||
int
|
||||
depends on BT_ENABLED
|
||||
default 1 if BTDM_CONTROLLER_RUN_APP_CPU
|
||||
default 0
|
||||
|
||||
menuconfig BT_HCI_UART
|
||||
bool "HCI use UART as IO"
|
||||
depends on BT_ENABLED && !BLUEDROID_ENABLED
|
||||
default n
|
||||
help
|
||||
Default HCI use VHCI, if this option choose, HCI will use UART(0/1/2) as IO.
|
||||
Besides, it can set uart number and uart baudrate.
|
||||
|
||||
config BT_HCI_UART_NO
|
||||
int "UART Number for HCI"
|
||||
depends on BT_HCI_UART
|
||||
range 1 2
|
||||
default 1
|
||||
help
|
||||
Uart number for HCI.
|
||||
|
||||
config BT_HCI_UART_BAUDRATE
|
||||
int "UART Baudrate for HCI"
|
||||
depends on BT_HCI_UART
|
||||
range 115200 921600
|
||||
default 921600
|
||||
help
|
||||
UART Baudrate for HCI. Please use standard baudrate.
|
||||
|
||||
config SMP_ENABLE
|
||||
bool
|
||||
depends on BLUEDROID_ENABLED
|
||||
@ -115,3 +159,5 @@ config BT_RESERVE_DRAM
|
||||
hex
|
||||
default 0x10000 if BT_ENABLED
|
||||
default 0
|
||||
|
||||
endmenu
|
||||
|
@ -36,7 +36,9 @@ esp_err_t esp_bt_dev_set_device_name(const char *name)
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (!name){
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (strlen(name) > ESP_DEV_DEVICE_NAME_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
@ -203,7 +203,9 @@ esp_err_t esp_ble_gap_update_whitelist(bool add_remove, esp_bd_addr_t remote_bda
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (!remote_bda){
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BLE;
|
||||
msg.act = BTC_GAP_BLE_ACT_UPDATE_WHITE_LIST;
|
||||
|
@ -97,6 +97,7 @@ typedef enum {
|
||||
ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT, /*!< When clear the bond device clear complete, the event comes */
|
||||
ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT, /*!< When get the bond device list complete, the event comes */
|
||||
ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT, /*!< When read the rssi complete, the event comes */
|
||||
ESP_GAP_BLE_ADD_WHITELIST_COMPLETE_EVT, /*!< When add or remove whitelist complete, the event comes */
|
||||
ESP_GAP_BLE_EVT_MAX,
|
||||
} esp_gap_ble_cb_event_t;
|
||||
|
||||
@ -178,10 +179,20 @@ typedef enum {
|
||||
|
||||
/* relate to BTA_DM_BLE_SEC_xxx in bta_api.h */
|
||||
typedef enum {
|
||||
ESP_BLE_SEC_NONE = 0, /* relate to BTA_DM_BLE_SEC_NONE in bta_api.h */
|
||||
ESP_BLE_SEC_ENCRYPT, /* relate to BTA_DM_BLE_SEC_ENCRYPT in bta_api.h */
|
||||
ESP_BLE_SEC_ENCRYPT_NO_MITM, /* relate to BTA_DM_BLE_SEC_ENCRYPT_NO_MITM in bta_api.h */
|
||||
ESP_BLE_SEC_ENCRYPT_MITM, /* relate to BTA_DM_BLE_SEC_ENCRYPT_MITM in bta_api.h */
|
||||
ESP_BLE_SEC_ENCRYPT = 1, /* relate to BTA_DM_BLE_SEC_ENCRYPT in bta_api.h. If the device has already
|
||||
bonded, the stack will used LTK to encrypt with the remote device directly.
|
||||
Else if the device hasn't bonded, the stack will used the default authentication request
|
||||
used the esp_ble_gap_set_security_param function set by the user. */
|
||||
ESP_BLE_SEC_ENCRYPT_NO_MITM, /* relate to BTA_DM_BLE_SEC_ENCRYPT_NO_MITM in bta_api.h. If the device has already
|
||||
bonded, the stack will check the LTK Whether the authentication request has been met, if met, used the LTK
|
||||
to encrypt with the remote device directly, else Re-pair with the remote device.
|
||||
Else if the device hasn't bonded, the stack will used NO MITM authentication request in the current link instead of
|
||||
used the authreq in the esp_ble_gap_set_security_param function set by the user. */
|
||||
ESP_BLE_SEC_ENCRYPT_MITM, /* relate to BTA_DM_BLE_SEC_ENCRYPT_MITM in bta_api.h. If the device has already
|
||||
bonded, the stack will check the LTK Whether the authentication request has been met, if met, used the LTK
|
||||
to encrypt with the remote device directly, else Re-pair with the remote device.
|
||||
Else if the device hasn't bonded, the stack will used MITM authentication request in the current link instead of
|
||||
used the authreq in the esp_ble_gap_set_security_param function set by the user. */
|
||||
}esp_ble_sec_act_t;
|
||||
|
||||
typedef enum {
|
||||
@ -462,6 +473,10 @@ typedef enum {
|
||||
ESP_BLE_EVT_SCAN_RSP = 0x04, /*!< Scan Response (SCAN_RSP) */
|
||||
} esp_ble_evt_type_t;
|
||||
|
||||
typedef enum{
|
||||
ESP_BLE_WHITELIST_REMOVE = 0X00, /*!< remove mac from whitelist */
|
||||
ESP_BLE_WHITELIST_ADD = 0X01, /*!< add address to whitelist */
|
||||
}esp_ble_wl_opration;
|
||||
/**
|
||||
* @brief Gap callback parameters union
|
||||
*/
|
||||
@ -600,6 +615,13 @@ typedef union {
|
||||
if the RSSI cannot be read, the RSSI metric shall be set to 127. */
|
||||
esp_bd_addr_t remote_addr; /*!< The remote device address */
|
||||
} read_rssi_cmpl; /*!< Event parameter of ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT */
|
||||
/**
|
||||
* @brief ESP_GAP_BLE_ADD_WHITELIST_COMPLETE_EVT
|
||||
*/
|
||||
struct ble_add_whitelist_cmpl_evt_param {
|
||||
esp_bt_status_t status; /*!< Indicate the add or remove whitelist operation success status */
|
||||
esp_ble_wl_opration wl_opration; /*!< The value is ESP_BLE_WHITELIST_ADD if add address to whitelist operation success, ESP_BLE_WHITELIST_REMOVE if remove address from the whitelist operation success */
|
||||
} add_whitelist_cmpl; /*!< Event parameter of ESP_GAP_BLE_ADD_WHITELIST_COMPLETE_EVT */
|
||||
} esp_ble_gap_cb_param_t;
|
||||
|
||||
/**
|
||||
@ -864,9 +886,9 @@ esp_err_t esp_ble_gap_read_rssi(esp_bd_addr_t remote_addr);
|
||||
/**
|
||||
* @brief Set a GAP security parameter value. Overrides the default value.
|
||||
*
|
||||
* @param[in] param_type :L the type of the param which to be set
|
||||
* @param[in] param_type : the type of the param which to be set
|
||||
* @param[in] value : the param value
|
||||
* @param[out] len : the length of the param value
|
||||
* @param[in] len : the length of the param value
|
||||
*
|
||||
* @return - ESP_OK : success
|
||||
* - other : failed
|
||||
@ -972,6 +994,12 @@ esp_err_t esp_ble_get_bond_device_list(int *dev_num, esp_ble_bond_dev_t *dev_lis
|
||||
|
||||
/**
|
||||
* @brief This function is to disconnect the physical connection of the peer device
|
||||
* gattc maybe have multiple virtual GATT server connections when multiple app_id registed.
|
||||
* esp_ble_gattc_close (esp_gatt_if_t gattc_if, uint16_t conn_id) only close one virtual GATT server connection.
|
||||
* if there exist other virtual GATT server connections, it does not disconnect the physical connection.
|
||||
* esp_ble_gap_disconnect(esp_bd_addr_t remote_device) disconnect the physical connection directly.
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param[in] remote_device : BD address of the peer device
|
||||
*
|
||||
|
@ -63,6 +63,7 @@ typedef enum {
|
||||
ESP_GATTC_UNREG_FOR_NOTIFY_EVT = 39, /*!< When unregister for notification of a service completes, the event comes */
|
||||
ESP_GATTC_CONNECT_EVT = 40, /*!< When the ble physical connection is set up, the event comes */
|
||||
ESP_GATTC_DISCONNECT_EVT = 41, /*!< When the ble physical connection disconnected, the event comes */
|
||||
ESP_GATTC_READ_MUTIPLE_EVT = 42, /*!< When the ble characteristic or descriptor mutiple complete, the event comes */
|
||||
} esp_gattc_cb_event_t;
|
||||
|
||||
|
||||
@ -200,7 +201,6 @@ typedef union {
|
||||
* @brief ESP_GATTC_CONNECT_EVT
|
||||
*/
|
||||
struct gattc_connect_evt_param {
|
||||
esp_gatt_status_t status; /*!< Operation status */
|
||||
uint16_t conn_id; /*!< Connection id */
|
||||
esp_bd_addr_t remote_bda; /*!< Remote bluetooth device address */
|
||||
} connect; /*!< Gatt client callback param of ESP_GATTC_CONNECT_EVT */
|
||||
@ -209,7 +209,7 @@ typedef union {
|
||||
* @brief ESP_GATTC_DISCONNECT_EVT
|
||||
*/
|
||||
struct gattc_disconnect_evt_param {
|
||||
esp_gatt_status_t status; /*!< Operation status */
|
||||
esp_gatt_conn_reason_t reason; /*!< disconnection reason */
|
||||
uint16_t conn_id; /*!< Connection id */
|
||||
esp_bd_addr_t remote_bda; /*!< Remote bluetooth device address */
|
||||
} disconnect; /*!< Gatt client callback param of ESP_GATTC_DISCONNECT_EVT */
|
||||
|
@ -119,6 +119,8 @@ typedef union {
|
||||
struct gatts_conf_evt_param {
|
||||
esp_gatt_status_t status; /*!< Operation status */
|
||||
uint16_t conn_id; /*!< Connection id */
|
||||
uint16_t len; /*!< The indication or notification value length, len is valid when send notification or indication failed */
|
||||
uint8_t *value; /*!< The indication or notification value , value is valid when send notification or indication failed */
|
||||
} conf; /*!< Gatt server callback param of ESP_GATTS_CONF_EVT (confirm) */
|
||||
|
||||
/**
|
||||
@ -193,7 +195,6 @@ typedef union {
|
||||
struct gatts_connect_evt_param {
|
||||
uint16_t conn_id; /*!< Connection id */
|
||||
esp_bd_addr_t remote_bda; /*!< Remote bluetooth device address */
|
||||
bool is_connected; /*!< Indicate it is connected or not */
|
||||
} connect; /*!< Gatt server callback param of ESP_GATTS_CONNECT_EVT */
|
||||
|
||||
/**
|
||||
@ -202,7 +203,7 @@ typedef union {
|
||||
struct gatts_disconnect_evt_param {
|
||||
uint16_t conn_id; /*!< Connection id */
|
||||
esp_bd_addr_t remote_bda; /*!< Remote bluetooth device address */
|
||||
bool is_connected; /*!< Indicate it is connected or not */
|
||||
esp_gatt_conn_reason_t reason; /*!< Indicate the reason of disconnection */
|
||||
} disconnect; /*!< Gatt server callback param of ESP_GATTS_DISCONNECT_EVT */
|
||||
|
||||
/**
|
||||
|
@ -525,7 +525,7 @@ void bta_dm_set_dev_name (tBTA_DM_MSG *p_data)
|
||||
|
||||
void bta_dm_update_white_list(tBTA_DM_MSG *p_data)
|
||||
{
|
||||
BTM_BleUpdateAdvWhitelist(p_data->white_list.add_remove, p_data->white_list.remote_addr);
|
||||
BTM_BleUpdateAdvWhitelist(p_data->white_list.add_remove, p_data->white_list.remote_addr, p_data->white_list.add_wl_cb);
|
||||
}
|
||||
|
||||
void bta_dm_ble_read_adv_tx_power(tBTA_DM_MSG *p_data)
|
||||
@ -646,7 +646,6 @@ void bta_dm_process_remove_device(BD_ADDR bd_addr)
|
||||
if (bta_dm_cb.p_sec_cback) {
|
||||
tBTA_DM_SEC sec_event;
|
||||
bdcpy(sec_event.link_down.bd_addr, bd_addr);
|
||||
/* No connection, set status to success (acl disc code not valid) */
|
||||
sec_event.link_down.status = HCI_SUCCESS;
|
||||
bta_dm_cb.p_sec_cback(BTA_DM_DEV_UNPAIRED_EVT, &sec_event);
|
||||
}
|
||||
@ -4659,6 +4658,47 @@ void bta_dm_ble_observe (tBTA_DM_MSG *p_data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function bta_dm_ble_scan
|
||||
**
|
||||
** Description This function set the preferred connection scan parameters.
|
||||
**
|
||||
** Parameters:
|
||||
**
|
||||
*******************************************************************************/
|
||||
void bta_dm_ble_scan (tBTA_DM_MSG *p_data)
|
||||
{
|
||||
tBTM_STATUS status;
|
||||
if (p_data->ble_scan.start) {
|
||||
/*Save the callback to be called when a scan results are available */
|
||||
bta_dm_search_cb.p_scan_cback = p_data->ble_scan.p_cback;
|
||||
|
||||
if ((status = BTM_BleScan(TRUE, p_data->ble_scan.duration,
|
||||
bta_dm_observe_results_cb, bta_dm_observe_cmpl_cb)) != BTM_CMD_STARTED) {
|
||||
APPL_TRACE_WARNING(" %s start scan failed. status=0x%x\n", __FUNCTION__, status);
|
||||
}
|
||||
|
||||
if (p_data->ble_scan.p_start_scan_cback) {
|
||||
status = (status == BTM_CMD_STARTED ? BTA_SUCCESS : BTA_FAILURE);
|
||||
p_data->ble_scan.p_start_scan_cback(status);
|
||||
}
|
||||
} else {
|
||||
bta_dm_search_cb.p_scan_cback = NULL;
|
||||
status = BTM_BleScan(FALSE, 0, NULL, NULL);
|
||||
|
||||
if (status != BTM_CMD_STARTED){
|
||||
APPL_TRACE_WARNING(" %s stop scan failed, status=0x%x\n", __FUNCTION__, status);
|
||||
}
|
||||
|
||||
if (p_data->ble_scan.p_stop_scan_cback) {
|
||||
status = (status == BTM_CMD_STARTED ? BTA_SUCCESS : BTA_FAILURE);
|
||||
p_data->ble_scan.p_stop_scan_cback(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function bta_dm_ble_set_adv_params
|
||||
|
@ -183,12 +183,13 @@ void BTA_DmSetDeviceName(char *p_name)
|
||||
|
||||
}
|
||||
|
||||
void BTA_DmUpdateWhiteList(BOOLEAN add_remove, BD_ADDR remote_addr)
|
||||
void BTA_DmUpdateWhiteList(BOOLEAN add_remove, BD_ADDR remote_addr, tBTA_ADD_WHITELIST_CBACK *add_wl_cb)
|
||||
{
|
||||
tBTA_DM_API_UPDATE_WHITE_LIST *p_msg;
|
||||
if ((p_msg = (tBTA_DM_API_UPDATE_WHITE_LIST *)osi_malloc(sizeof(tBTA_DM_API_UPDATE_WHITE_LIST))) != NULL) {
|
||||
p_msg->hdr.event = BTA_DM_API_UPDATE_WHITE_LIST_EVT;
|
||||
p_msg->add_remove = add_remove;
|
||||
p_msg->add_wl_cb = add_wl_cb;
|
||||
memcpy(p_msg->remote_addr, remote_addr, sizeof(BD_ADDR));
|
||||
|
||||
bta_sys_sendmsg(p_msg);
|
||||
@ -2209,6 +2210,47 @@ extern void BTA_DmBleObserve(BOOLEAN start, UINT32 duration,
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTA_DmBleScan
|
||||
**
|
||||
** Description This procedure keep the device listening for advertising
|
||||
** events from a broadcast device.
|
||||
**
|
||||
** Parameters start: start or stop scan.
|
||||
**
|
||||
** Returns void
|
||||
|
||||
**
|
||||
** Returns void.
|
||||
**
|
||||
*******************************************************************************/
|
||||
extern void BTA_DmBleScan(BOOLEAN start, UINT32 duration,
|
||||
tBTA_DM_SEARCH_CBACK *p_results_cb,
|
||||
tBTA_START_STOP_SCAN_CMPL_CBACK *p_start_stop_scan_cb)
|
||||
{
|
||||
tBTA_DM_API_BLE_SCAN *p_msg;
|
||||
|
||||
APPL_TRACE_API("BTA_DmBleScan:start = %d ", start);
|
||||
|
||||
if ((p_msg = (tBTA_DM_API_BLE_SCAN *) osi_malloc(sizeof(tBTA_DM_API_BLE_SCAN))) != NULL) {
|
||||
memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_SCAN));
|
||||
|
||||
p_msg->hdr.event = BTA_DM_API_BLE_SCAN_EVT;
|
||||
p_msg->start = start;
|
||||
p_msg->duration = duration;
|
||||
p_msg->p_cback = p_results_cb;
|
||||
if (start){
|
||||
p_msg->p_start_scan_cback = p_start_stop_scan_cb;
|
||||
}
|
||||
else {
|
||||
p_msg->p_stop_scan_cback = p_start_stop_scan_cb;
|
||||
}
|
||||
|
||||
bta_sys_sendmsg(p_msg);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTA_DmBleStopAdvertising
|
||||
|
@ -97,6 +97,7 @@ enum {
|
||||
support the scan filter setting for the APP******/
|
||||
BTA_DM_API_BLE_SCAN_FIL_PARAM_EVT,
|
||||
BTA_DM_API_BLE_OBSERVE_EVT,
|
||||
BTA_DM_API_BLE_SCAN_EVT,
|
||||
BTA_DM_API_UPDATE_CONN_PARAM_EVT,
|
||||
/*******This event added by Yulong at 2016/9/9 to
|
||||
support the random address setting for the APP******/
|
||||
@ -183,6 +184,7 @@ typedef struct {
|
||||
BT_HDR hdr;
|
||||
BOOLEAN add_remove;
|
||||
BD_ADDR remote_addr;
|
||||
tBTA_ADD_WHITELIST_CBACK *add_wl_cb;
|
||||
}tBTA_DM_API_UPDATE_WHITE_LIST;
|
||||
|
||||
typedef struct {
|
||||
@ -506,6 +508,17 @@ typedef struct {
|
||||
tBTA_START_STOP_ADV_CMPL_CBACK *p_stop_adv_cback;
|
||||
} tBTA_DM_API_BLE_OBSERVE;
|
||||
|
||||
/* Data type for start/stop scan */
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
BOOLEAN start;
|
||||
UINT32 duration;
|
||||
tBTA_DM_SEARCH_CBACK *p_cback;
|
||||
tBTA_START_STOP_SCAN_CMPL_CBACK *p_start_scan_cback;
|
||||
tBTA_START_STOP_SCAN_CMPL_CBACK *p_stop_scan_cback;
|
||||
tBTA_START_STOP_ADV_CMPL_CBACK *p_stop_adv_cback;
|
||||
} tBTA_DM_API_BLE_SCAN;
|
||||
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
BD_ADDR remote_bda;
|
||||
@ -758,6 +771,7 @@ typedef union {
|
||||
tBTA_DM_API_BLE_SCAN_PARAMS ble_set_scan_params;
|
||||
tBTA_DM_API_BLE_SCAN_FILTER_PARAMS ble_set_scan_fil_params;
|
||||
tBTA_DM_API_BLE_OBSERVE ble_observe;
|
||||
tBTA_DM_API_BLE_SCAN ble_scan;
|
||||
tBTA_DM_API_ENABLE_PRIVACY ble_remote_privacy;
|
||||
tBTA_DM_API_LOCAL_PRIVACY ble_local_privacy;
|
||||
tBTA_DM_API_BLE_ADV_PARAMS ble_set_adv_params;
|
||||
@ -1158,6 +1172,7 @@ extern void bta_dm_ble_set_conn_scan_params (tBTA_DM_MSG *p_data);
|
||||
extern void bta_dm_close_gatt_conn(tBTA_DM_MSG *p_data);
|
||||
#endif /* ((defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE) && SDP_INCLUDED == TRUE) && (GATTC_INCLUDED == TRUE) */
|
||||
extern void bta_dm_ble_observe (tBTA_DM_MSG *p_data);
|
||||
extern void bta_dm_ble_scan (tBTA_DM_MSG *p_data);
|
||||
extern void bta_dm_ble_update_conn_params (tBTA_DM_MSG *p_data);
|
||||
extern void bta_dm_ble_disconnect (tBTA_DM_MSG *p_data);
|
||||
extern void bta_dm_ble_set_rand_address(tBTA_DM_MSG *p_data);
|
||||
|
@ -91,6 +91,7 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = {
|
||||
bta_dm_ble_set_scan_params, /* BTA_DM_API_BLE_SCAN_PARAM_EVT */
|
||||
bta_dm_ble_set_scan_fil_params, /* BTA_DM_API_BLE_SCAN_FIL_PARAM_EVT */
|
||||
bta_dm_ble_observe, /* BTA_DM_API_BLE_OBSERVE_EVT*/
|
||||
bta_dm_ble_scan, /* BTA_DM_API_BLE_SCAN_EVT */
|
||||
bta_dm_ble_update_conn_params, /* BTA_DM_API_UPDATE_CONN_PARAM_EVT */
|
||||
/* This handler function added by
|
||||
Yulong at 2016/9/9 to support the
|
||||
|
@ -84,7 +84,8 @@ static UINT16 bta_gattc_opcode_to_int_evt[] = {
|
||||
BTA_GATTC_API_READ_EVT,
|
||||
BTA_GATTC_API_WRITE_EVT,
|
||||
BTA_GATTC_API_EXEC_EVT,
|
||||
BTA_GATTC_API_CFG_MTU_EVT
|
||||
BTA_GATTC_API_CFG_MTU_EVT,
|
||||
BTA_GATTC_API_READ_MULTI_EVT
|
||||
};
|
||||
|
||||
#if (BT_TRACE_VERBOSE == TRUE)
|
||||
@ -711,7 +712,6 @@ void bta_gattc_conncback(tBTA_GATTC_RCB *p_rcb, tBTA_GATTC_DATA *p_data)
|
||||
{
|
||||
if (p_rcb) {
|
||||
bta_gattc_send_connect_cback(p_rcb,
|
||||
BTA_GATT_OK,
|
||||
p_data->int_conn.remote_bda,
|
||||
p_data->int_conn.hdr.layer_specific);
|
||||
|
||||
@ -730,7 +730,7 @@ void bta_gattc_disconncback(tBTA_GATTC_RCB *p_rcb, tBTA_GATTC_DATA *p_data)
|
||||
{
|
||||
if (p_rcb) {
|
||||
bta_gattc_send_disconnect_cback(p_rcb,
|
||||
BTA_GATT_OK,
|
||||
p_data->int_conn.reason,
|
||||
p_data->int_conn.remote_bda,
|
||||
p_data->int_conn.hdr.layer_specific);
|
||||
|
||||
@ -793,7 +793,7 @@ void bta_gattc_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
|
||||
if (p_data->hdr.event == BTA_GATTC_API_CLOSE_EVT) {
|
||||
cb_data.close.status = GATT_Disconnect(p_data->hdr.layer_specific);
|
||||
} else if (p_data->hdr.event == BTA_GATTC_INT_DISCONN_EVT) {
|
||||
cb_data.close.status = p_data->int_conn.reason;
|
||||
cb_data.close.status = BTA_GATT_OK;
|
||||
cb_data.close.reason = p_data->int_conn.reason;
|
||||
}
|
||||
|
||||
@ -1228,8 +1228,12 @@ void bta_gattc_read_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
|
||||
} else {
|
||||
cb_data.read.handle = p_clcb->p_q_cmd->api_read.handle;
|
||||
}
|
||||
|
||||
event = p_clcb->p_q_cmd->api_read.cmpl_evt;
|
||||
|
||||
if (p_clcb->p_q_cmd->hdr.event != BTA_GATTC_API_READ_MULTI_EVT) {
|
||||
event = p_clcb->p_q_cmd->api_read.cmpl_evt;
|
||||
} else {
|
||||
event = p_clcb->p_q_cmd->api_read_multi.cmpl_evt;
|
||||
}
|
||||
cb_data.read.conn_id = p_clcb->bta_conn_id;
|
||||
//free the command data store in the queue.
|
||||
bta_gattc_free_command_data(p_clcb);
|
||||
@ -1350,20 +1354,22 @@ void bta_gattc_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
|
||||
return;
|
||||
}
|
||||
if (p_clcb->p_q_cmd->hdr.event != bta_gattc_opcode_to_int_evt[op - GATTC_OPTYPE_READ]) {
|
||||
mapped_op = p_clcb->p_q_cmd->hdr.event - BTA_GATTC_API_READ_EVT + GATTC_OPTYPE_READ;
|
||||
if ( mapped_op > GATTC_OPTYPE_INDICATION) {
|
||||
mapped_op = 0;
|
||||
}
|
||||
if (p_clcb->p_q_cmd->hdr.event != BTA_GATTC_API_READ_MULTI_EVT) {
|
||||
mapped_op = p_clcb->p_q_cmd->hdr.event - BTA_GATTC_API_READ_EVT + GATTC_OPTYPE_READ;
|
||||
if ( mapped_op > GATTC_OPTYPE_INDICATION) {
|
||||
mapped_op = 0;
|
||||
}
|
||||
|
||||
#if (BT_TRACE_VERBOSE == TRUE)
|
||||
APPL_TRACE_ERROR("expect op:(%s :0x%04x), receive unexpected operation (%s).",
|
||||
bta_gattc_op_code_name[mapped_op] , p_clcb->p_q_cmd->hdr.event,
|
||||
bta_gattc_op_code_name[op]);
|
||||
APPL_TRACE_ERROR("expect op:(%s :0x%04x), receive unexpected operation (%s).",
|
||||
bta_gattc_op_code_name[mapped_op] , p_clcb->p_q_cmd->hdr.event,
|
||||
bta_gattc_op_code_name[op]);
|
||||
#else
|
||||
APPL_TRACE_ERROR("expect op:(%u :0x%04x), receive unexpected operation (%u).",
|
||||
mapped_op , p_clcb->p_q_cmd->hdr.event, op);
|
||||
APPL_TRACE_ERROR("expect op:(%u :0x%04x), receive unexpected operation (%u).",
|
||||
mapped_op , p_clcb->p_q_cmd->hdr.event, op);
|
||||
#endif
|
||||
return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* discard responses if service change indication is received before operation completed */
|
||||
|
@ -545,7 +545,7 @@ void BTA_GATTC_ReadMultiple(UINT16 conn_id, tBTA_GATTC_MULTI *p_read_multi,
|
||||
p_buf->hdr.layer_specific = conn_id;
|
||||
p_buf->auth_req = auth_req;
|
||||
p_buf->num_attr = p_read_multi->num_attr;
|
||||
|
||||
p_buf->cmpl_evt = BTA_GATTC_READ_MUTIPLE_EVT;
|
||||
if (p_buf->num_attr > 0) {
|
||||
memcpy(p_buf->handles, p_read_multi->handles, sizeof(UINT16) * p_read_multi->num_attr);
|
||||
}
|
||||
|
@ -187,6 +187,7 @@ tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb)
|
||||
p_srvc_cb->cur_srvc_idx = 0;
|
||||
p_srvc_cb->cur_char_idx = 0;
|
||||
p_srvc_cb->next_avail_idx = 0;
|
||||
p_srvc_cb->total_attr = 0;
|
||||
}
|
||||
|
||||
return BTA_GATT_OK;
|
||||
|
@ -718,15 +718,13 @@ void bta_gattc_send_open_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS status
|
||||
** Returns
|
||||
**
|
||||
*******************************************************************************/
|
||||
void bta_gattc_send_connect_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS status,
|
||||
BD_ADDR remote_bda, UINT16 conn_id)
|
||||
void bta_gattc_send_connect_cback( tBTA_GATTC_RCB *p_clreg, BD_ADDR remote_bda, UINT16 conn_id)
|
||||
{
|
||||
tBTA_GATTC cb_data;
|
||||
|
||||
if (p_clreg->p_cback) {
|
||||
memset(&cb_data, 0, sizeof(tBTA_GATTC));
|
||||
|
||||
cb_data.connect.status = status;
|
||||
cb_data.connect.client_if = p_clreg->client_if;
|
||||
cb_data.connect.conn_id = conn_id;
|
||||
bdcpy(cb_data.connect.remote_bda, remote_bda);
|
||||
@ -744,7 +742,7 @@ void bta_gattc_send_connect_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS sta
|
||||
** Returns
|
||||
**
|
||||
*******************************************************************************/
|
||||
void bta_gattc_send_disconnect_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS status,
|
||||
void bta_gattc_send_disconnect_cback( tBTA_GATTC_RCB *p_clreg, tGATT_DISCONN_REASON reason,
|
||||
BD_ADDR remote_bda, UINT16 conn_id)
|
||||
{
|
||||
tBTA_GATTC cb_data;
|
||||
@ -752,7 +750,7 @@ void bta_gattc_send_disconnect_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS
|
||||
if (p_clreg->p_cback) {
|
||||
memset(&cb_data, 0, sizeof(tBTA_GATTC));
|
||||
|
||||
cb_data.disconnect.status = status;
|
||||
cb_data.disconnect.reason = reason;
|
||||
cb_data.disconnect.client_if = p_clreg->client_if;
|
||||
cb_data.disconnect.conn_id = conn_id;
|
||||
bdcpy(cb_data.disconnect.remote_bda, remote_bda);
|
||||
|
@ -692,6 +692,15 @@ void bta_gatts_indicate_handle (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg)
|
||||
cb_data.req_data.status = status;
|
||||
cb_data.req_data.conn_id = p_msg->api_indicate.hdr.layer_specific;
|
||||
|
||||
cb_data.req_data.value =(uint8_t *)osi_malloc(p_msg->api_indicate.len);
|
||||
if (cb_data.req_data.value != NULL){
|
||||
memset(cb_data.req_data.value, 0, p_msg->api_indicate.len);
|
||||
cb_data.req_data.data_len = p_msg->api_indicate.len;
|
||||
memcpy(cb_data.req_data.value, p_msg->api_indicate.value, p_msg->api_indicate.len);
|
||||
}else{
|
||||
cb_data.req_data.data_len = 0;
|
||||
APPL_TRACE_ERROR("%s, malloc failed", __func__);
|
||||
}
|
||||
(*p_rcb->p_cback)(BTA_GATTS_CONF_EVT, &cb_data);
|
||||
}
|
||||
} else {
|
||||
|
@ -474,8 +474,10 @@ void BTA_GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id,
|
||||
void BTA_SetAttributeValue(UINT16 attr_handle, UINT16 length, UINT8 *value)
|
||||
{
|
||||
tBTA_GATTS_API_SET_ATTR_VAL *p_buf;
|
||||
UINT16 len = sizeof(tBTA_GATTS_API_SET_ATTR_VAL);
|
||||
if((p_buf = (tBTA_GATTS_API_SET_ATTR_VAL *)osi_malloc(
|
||||
sizeof(tBTA_GATTS_API_SET_ATTR_VAL))) != NULL){
|
||||
memset(p_buf, 0, len);
|
||||
p_buf->hdr.event = BTA_GATTS_API_SET_ATTR_VAL_EVT;
|
||||
p_buf->hdr.layer_specific = attr_handle;
|
||||
p_buf->length = length;
|
||||
|
@ -402,6 +402,8 @@ typedef void (tBTA_SET_ADV_DATA_CMPL_CBACK) (tBTA_STATUS status);
|
||||
|
||||
typedef void (tBTA_START_ADV_CMPL_CBACK) (tBTA_STATUS status);
|
||||
|
||||
typedef tBTM_ADD_WHITELIST_CBACK tBTA_ADD_WHITELIST_CBACK;
|
||||
|
||||
typedef tBTM_SET_PKT_DATA_LENGTH_CBACK tBTA_SET_PKT_DATA_LENGTH_CBACK;
|
||||
|
||||
typedef tBTM_SET_LOCAL_PRIVACY_CBACK tBTA_SET_LOCAL_PRIVACY_CBACK;
|
||||
@ -1410,7 +1412,7 @@ extern void BTA_DisableTestMode(void);
|
||||
*******************************************************************************/
|
||||
extern void BTA_DmSetDeviceName(char *p_name);
|
||||
|
||||
extern void BTA_DmUpdateWhiteList(BOOLEAN add_remove, BD_ADDR remote_addr);
|
||||
extern void BTA_DmUpdateWhiteList(BOOLEAN add_remove, BD_ADDR remote_addr, tBTA_ADD_WHITELIST_CBACK *add_wl_cb);
|
||||
|
||||
extern void BTA_DmBleReadAdvTxPower(tBTA_CMPL_CB *cmpl_cb);
|
||||
|
||||
@ -2034,6 +2036,24 @@ extern void BTA_DmBleObserve(BOOLEAN start, UINT32 duration,
|
||||
tBTA_DM_SEARCH_CBACK *p_results_cb,
|
||||
tBTA_START_STOP_SCAN_CMPL_CBACK *p_start_stop_scan_cb);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTA_DmBleScan
|
||||
**
|
||||
** Description This procedure keep the device listening for advertising
|
||||
** events from a broadcast device.
|
||||
**
|
||||
** Parameters start: start or stop observe.
|
||||
** duration : Duration of the scan. Continuous scan if 0 is passed
|
||||
** p_results_cb: Callback to be called with scan results
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
extern void BTA_DmBleScan(BOOLEAN start, UINT32 duration,
|
||||
tBTA_DM_SEARCH_CBACK *p_results_cb,
|
||||
tBTA_START_STOP_SCAN_CMPL_CBACK *p_start_stop_scan_cb);
|
||||
|
||||
extern void BTA_DmBleStopAdvertising(void);
|
||||
|
||||
extern void BTA_DmSetRandAddress(BD_ADDR rand_addr);
|
||||
|
@ -181,6 +181,7 @@ typedef UINT8 tBTA_GATT_STATUS;
|
||||
#define BTA_GATTC_ADV_VSC_EVT 34 /* ADV VSC event */
|
||||
#define BTA_GATTC_CONNECT_EVT 35 /* GATTC CONNECT event */
|
||||
#define BTA_GATTC_DISCONNECT_EVT 36 /* GATTC DISCONNECT event */
|
||||
#define BTA_GATTC_READ_MUTIPLE_EVT 37 /* GATTC Read mutiple event */
|
||||
|
||||
typedef UINT8 tBTA_GATTC_EVT;
|
||||
|
||||
@ -366,14 +367,13 @@ typedef struct {
|
||||
} tBTA_GATTC_ENC_CMPL_CB;
|
||||
|
||||
typedef struct {
|
||||
tBTA_GATT_STATUS status;
|
||||
UINT16 conn_id;
|
||||
tBTA_GATTC_IF client_if;
|
||||
BD_ADDR remote_bda;
|
||||
} tBTA_GATTC_CONNECT;
|
||||
|
||||
typedef struct {
|
||||
tBTA_GATT_STATUS status;
|
||||
tGATT_DISCONN_REASON reason;
|
||||
UINT16 conn_id;
|
||||
tBTA_GATTC_IF client_if;
|
||||
BD_ADDR remote_bda;
|
||||
@ -522,6 +522,8 @@ typedef struct {
|
||||
UINT32 trans_id;
|
||||
UINT16 conn_id;
|
||||
tBTA_GATTS_REQ_DATA *p_data;
|
||||
UINT16 data_len;
|
||||
UINT8 *value;
|
||||
} tBTA_GATTS_REQ;
|
||||
|
||||
typedef struct {
|
||||
|
@ -72,7 +72,11 @@ typedef UINT16 tBTA_GATTC_INT_EVT;
|
||||
|
||||
/* max client application GATTC can support */
|
||||
#ifndef BTA_GATTC_CL_MAX
|
||||
#define BTA_GATTC_CL_MAX 3 // 32
|
||||
#if (GATT_MAX_PHY_CHANNEL > 3)
|
||||
#define BTA_GATTC_CL_MAX GATT_MAX_PHY_CHANNEL
|
||||
#else
|
||||
#define BTA_GATTC_CL_MAX 3 // The origin value is 10
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* max known devices GATTC can support */
|
||||
@ -165,6 +169,7 @@ typedef struct {
|
||||
tBTA_GATT_AUTH_REQ auth_req;
|
||||
UINT8 num_attr;
|
||||
UINT16 handles[GATT_MAX_READ_MULTI_HANDLES];
|
||||
tBTA_GATTC_EVT cmpl_evt;
|
||||
}tBTA_GATTC_API_READ_MULTI;
|
||||
|
||||
typedef struct {
|
||||
@ -434,9 +439,8 @@ extern void bta_gattc_init_bk_conn(tBTA_GATTC_API_OPEN *p_data, tBTA_GATTC_RCB *
|
||||
extern void bta_gattc_cancel_bk_conn(tBTA_GATTC_API_CANCEL_OPEN *p_data);
|
||||
extern void bta_gattc_send_open_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS status,
|
||||
BD_ADDR remote_bda, UINT16 conn_id, tBTA_TRANSPORT transport, UINT16 mtu);
|
||||
extern void bta_gattc_send_connect_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS status,
|
||||
BD_ADDR remote_bda, UINT16 conn_id);
|
||||
extern void bta_gattc_send_disconnect_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS status,
|
||||
extern void bta_gattc_send_connect_cback( tBTA_GATTC_RCB *p_clreg, BD_ADDR remote_bda, UINT16 conn_id);
|
||||
extern void bta_gattc_send_disconnect_cback( tBTA_GATTC_RCB *p_clreg, tGATT_DISCONN_REASON reason,
|
||||
BD_ADDR remote_bda, UINT16 conn_id);
|
||||
extern void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg);
|
||||
extern void bta_gattc_cfg_mtu(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
|
||||
|
@ -184,29 +184,29 @@ bt_status_t btc_storage_get_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
|
||||
*******************************************************************************/
|
||||
static bt_status_t _btc_storage_remove_ble_bonding_keys(bt_bdaddr_t *remote_bd_addr)
|
||||
{
|
||||
int ret = 1;
|
||||
int ret = 0;
|
||||
bdstr_t bdstr;
|
||||
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
|
||||
|
||||
BTIF_TRACE_DEBUG(" %s in bd addr:%s",__FUNCTION__, bdstr);
|
||||
|
||||
if (btc_config_exist(bdstr, BTC_BLE_STORAGE_ADDR_TYPE_STR)) {
|
||||
ret &= btc_config_remove(bdstr, BTC_BLE_STORAGE_ADDR_TYPE_STR);
|
||||
ret |= btc_config_remove(bdstr, BTC_BLE_STORAGE_ADDR_TYPE_STR);
|
||||
}
|
||||
if (btc_config_exist(bdstr, BTC_BLE_STORAGE_LE_KEY_PENC_STR)) {
|
||||
ret &= btc_config_remove(bdstr, BTC_BLE_STORAGE_LE_KEY_PENC_STR);
|
||||
ret |= btc_config_remove(bdstr, BTC_BLE_STORAGE_LE_KEY_PENC_STR);
|
||||
}
|
||||
if (btc_config_exist(bdstr, BTC_BLE_STORAGE_LE_KEY_PID_STR)) {
|
||||
ret &= btc_config_remove(bdstr, BTC_BLE_STORAGE_LE_KEY_PID_STR);
|
||||
ret |= btc_config_remove(bdstr, BTC_BLE_STORAGE_LE_KEY_PID_STR);
|
||||
}
|
||||
if (btc_config_exist(bdstr, BTC_BLE_STORAGE_LE_KEY_PCSRK_STR)) {
|
||||
ret &= btc_config_remove(bdstr, BTC_BLE_STORAGE_LE_KEY_PCSRK_STR);
|
||||
ret |= btc_config_remove(bdstr, BTC_BLE_STORAGE_LE_KEY_PCSRK_STR);
|
||||
}
|
||||
if (btc_config_exist(bdstr, BTC_BLE_STORAGE_LE_KEY_LENC_STR)) {
|
||||
ret &= btc_config_remove(bdstr, BTC_BLE_STORAGE_LE_KEY_LENC_STR);
|
||||
ret |= btc_config_remove(bdstr, BTC_BLE_STORAGE_LE_KEY_LENC_STR);
|
||||
}
|
||||
if (btc_config_exist(bdstr, BTC_BLE_STORAGE_LE_KEY_LCSRK_STR)) {
|
||||
ret &= btc_config_remove(bdstr, BTC_BLE_STORAGE_LE_KEY_LCSRK_STR);
|
||||
ret |= btc_config_remove(bdstr, BTC_BLE_STORAGE_LE_KEY_LCSRK_STR);
|
||||
}
|
||||
//here don't remove section, because config_save will check it
|
||||
_btc_storage_save();
|
||||
|
@ -467,12 +467,15 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg)
|
||||
LOG_ERROR("BTA_DM_DEV_UNPAIRED_EVT");
|
||||
memcpy(bd_addr.address, p_data->link_down.bd_addr, sizeof(BD_ADDR));
|
||||
btm_set_bond_type_dev(p_data->link_down.bd_addr, BOND_TYPE_UNKNOWN);
|
||||
//remove the bonded key in the config and nvs flash.
|
||||
btc_storage_remove_ble_dev_type(&bd_addr, false);
|
||||
btc_storage_remove_remote_addr_type(&bd_addr, false);
|
||||
btc_storage_remove_ble_bonding_keys(&bd_addr);
|
||||
param.remove_bond_dev_cmpl.status = ESP_BT_STATUS_FAIL;
|
||||
|
||||
if (p_data->link_down.status == HCI_SUCCESS) {
|
||||
//remove the bonded key in the config and nvs flash.
|
||||
btc_storage_remove_ble_dev_type(&bd_addr, false);
|
||||
btc_storage_remove_remote_addr_type(&bd_addr, false);
|
||||
param.remove_bond_dev_cmpl.status = btc_storage_remove_ble_bonding_keys(&bd_addr);
|
||||
}
|
||||
ble_msg.act = ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT;
|
||||
param.remove_bond_dev_cmpl.status = (p_data->link_down.status == HCI_SUCCESS) ? ESP_BT_STATUS_SUCCESS : ESP_BT_STATUS_FAIL;
|
||||
memcpy(param.remove_bond_dev_cmpl.bd_addr, p_data->link_down.bd_addr, sizeof(BD_ADDR));
|
||||
#endif /* #if (SMP_INCLUDED == TRUE) */
|
||||
break;
|
||||
|
@ -139,8 +139,8 @@ bt_status_t btc_transfer_context(btc_msg_t *msg, void *arg, int arg_len, btc_arg
|
||||
|
||||
int btc_init(void)
|
||||
{
|
||||
xBtcQueue = xQueueCreate(BTC_TASK_QUEUE_NUM, sizeof(btc_msg_t));
|
||||
xTaskCreatePinnedToCore(btc_task, "Btc_task", BTC_TASK_STACK_SIZE, NULL, BTC_TASK_PRIO, &xBtcTaskHandle, 0);
|
||||
xBtcQueue = xQueueCreate(BTC_TASK_QUEUE_LEN, sizeof(btc_msg_t));
|
||||
xTaskCreatePinnedToCore(btc_task, "Btc_task", BTC_TASK_STACK_SIZE, NULL, BTC_TASK_PRIO, &xBtcTaskHandle, BTC_TASK_PINNED_TO_CORE);
|
||||
btc_gap_callback_init();
|
||||
/* TODO: initial the profile_tab */
|
||||
|
||||
|
@ -112,10 +112,6 @@ enum {
|
||||
/* 5 frames is equivalent to 6.89*5*2.9 ~= 100 ms @ 44.1 khz, 20 ms mediatick */
|
||||
#define MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ (5)
|
||||
|
||||
#define MEDIA_DATA_Q_LEN (1)
|
||||
#define MEDIA_CTRL_Q_LEN (5)
|
||||
#define COMBINED_MEDIA_Q_LEN (MEDIA_DATA_Q_LEN + MEDIA_CTRL_Q_LEN)
|
||||
|
||||
typedef struct {
|
||||
UINT16 num_frames_to_be_processed;
|
||||
UINT16 len;
|
||||
@ -276,13 +272,13 @@ bool btc_a2dp_start_media_task(void)
|
||||
|
||||
APPL_TRACE_EVENT("## A2DP START MEDIA THREAD ##");
|
||||
|
||||
xBtcMediaQueueSet = xQueueCreateSet(COMBINED_MEDIA_Q_LEN);
|
||||
xBtcMediaQueueSet = xQueueCreateSet(BTC_MEDIA_TASK_QUEUE_SET_LEN);
|
||||
configASSERT(xBtcMediaQueueSet);
|
||||
xBtcMediaDataQueue = xQueueCreate(MEDIA_DATA_Q_LEN, sizeof(void *));
|
||||
xBtcMediaDataQueue = xQueueCreate(BTC_MEDIA_DATA_QUEUE_LEN, sizeof(void *));
|
||||
configASSERT(xBtcMediaDataQueue);
|
||||
xQueueAddToSet(xBtcMediaDataQueue, xBtcMediaQueueSet);
|
||||
|
||||
xBtcMediaCtrlQueue = xQueueCreate(MEDIA_CTRL_Q_LEN, sizeof(void *));
|
||||
xBtcMediaCtrlQueue = xQueueCreate(BTC_MEDIA_CTRL_QUEUE_LEN, sizeof(void *));
|
||||
configASSERT(xBtcMediaCtrlQueue);
|
||||
xQueueAddToSet(xBtcMediaCtrlQueue, xBtcMediaQueueSet);
|
||||
|
||||
|
@ -542,8 +542,8 @@ static void btc_ble_set_scan_params(esp_ble_scan_params_t *scan_params, tBLE_SCA
|
||||
scan_params->scan_interval,
|
||||
scan_params->scan_window,
|
||||
scan_params->scan_type,
|
||||
scan_params->own_addr_type,
|
||||
scan_params->scan_filter_policy,
|
||||
scan_params->own_addr_type,
|
||||
scan_param_setup_cback);
|
||||
} else {
|
||||
btc_scan_params_callback(ESP_DEFAULT_GATT_IF, BTM_ILLEGAL_VALUE);
|
||||
@ -681,6 +681,24 @@ static void btc_set_pkt_length_callback(UINT8 status, tBTM_LE_SET_PKT_DATA_LENGT
|
||||
}
|
||||
}
|
||||
|
||||
static void btc_add_whitelist_complete_callback(UINT8 status, tBTM_WL_OPERATION wl_opration)
|
||||
{
|
||||
esp_ble_gap_cb_param_t param;
|
||||
bt_status_t ret;
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_GAP_BLE;
|
||||
msg.act = ESP_GAP_BLE_ADD_WHITELIST_COMPLETE_EVT;
|
||||
param.add_whitelist_cmpl.status = btc_hci_to_esp_status(status);
|
||||
param.add_whitelist_cmpl.wl_opration = wl_opration;
|
||||
ret = btc_transfer_context(&msg, ¶m,
|
||||
sizeof(esp_ble_gap_cb_param_t), NULL);
|
||||
|
||||
if (ret != BT_STATUS_SUCCESS) {
|
||||
LOG_ERROR("%s btc_transfer_context failed\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
static void btc_set_local_privacy_callback(UINT8 status)
|
||||
{
|
||||
esp_ble_gap_cb_param_t param;
|
||||
@ -741,17 +759,17 @@ static void btc_ble_start_scanning(uint32_t duration,
|
||||
tBTA_START_STOP_SCAN_CMPL_CBACK *start_scan_cb)
|
||||
{
|
||||
if ((results_cb != NULL) && (start_scan_cb != NULL)) {
|
||||
///Start scan the device
|
||||
BTA_DmBleObserve(true, duration, results_cb, start_scan_cb);
|
||||
//Start scan the device
|
||||
BTA_DmBleScan(true, duration, results_cb, start_scan_cb);
|
||||
} else {
|
||||
LOG_ERROR("The scan duration or p_results_cb invalid\n");
|
||||
LOG_ERROR("The start_scan_cb or results_cb invalid\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void btc_ble_stop_scanning(tBTA_START_STOP_SCAN_CMPL_CBACK *stop_scan_cb)
|
||||
{
|
||||
uint8_t duration = 0;
|
||||
BTA_DmBleObserve(false, duration, NULL, stop_scan_cb);
|
||||
BTA_DmBleScan(false, duration, NULL, stop_scan_cb);
|
||||
}
|
||||
|
||||
|
||||
@ -805,14 +823,14 @@ static void btc_ble_set_rand_addr (BD_ADDR rand_addr)
|
||||
BD_ADDR invalid_rand_addr_a, invalid_rand_addr_b;
|
||||
memset(invalid_rand_addr_a, 0xff, sizeof(BD_ADDR));
|
||||
memset(invalid_rand_addr_b, 0x00, sizeof(BD_ADDR));
|
||||
invalid_rand_addr_b[BD_ADDR_LEN - 1] = invalid_rand_addr_b[BD_ADDR_LEN - 1] | BT_STATIC_RAND_ADDR_MASK;
|
||||
if((rand_addr[BD_ADDR_LEN - 1] & BT_STATIC_RAND_ADDR_MASK) == BT_STATIC_RAND_ADDR_MASK
|
||||
invalid_rand_addr_b[0] = invalid_rand_addr_b[0] | BT_STATIC_RAND_ADDR_MASK;
|
||||
if((rand_addr[0] & BT_STATIC_RAND_ADDR_MASK) == BT_STATIC_RAND_ADDR_MASK
|
||||
&& memcmp(invalid_rand_addr_a, rand_addr, BD_ADDR_LEN) != 0
|
||||
&& memcmp(invalid_rand_addr_b, rand_addr, BD_ADDR_LEN) != 0){
|
||||
BTA_DmSetRandAddress(rand_addr);
|
||||
} else {
|
||||
param.set_rand_addr_cmpl.status = ESP_BT_STATUS_INVALID_STATIC_RAND_ADDR;
|
||||
LOG_ERROR("Invalid random address, the high bit should be 0b11, the random part shall not be to 1 or 0");
|
||||
LOG_ERROR("Invalid random address, the high bit should be 0b11, all bits of the random part shall not be to 1 or 0");
|
||||
}
|
||||
} else {
|
||||
param.set_rand_addr_cmpl.status = ESP_BT_STATUS_INVALID_STATIC_RAND_ADDR;
|
||||
@ -1031,7 +1049,7 @@ void btc_gap_ble_call_handler(btc_msg_t *msg)
|
||||
btc_ble_config_local_privacy(arg->cfg_local_privacy.privacy_enable, btc_set_local_privacy_callback);
|
||||
break;
|
||||
case BTC_GAP_BLE_ACT_UPDATE_WHITE_LIST:
|
||||
BTA_DmUpdateWhiteList(arg->update_white_list.add_remove, arg->update_white_list.remote_bda);
|
||||
BTA_DmUpdateWhiteList(arg->update_white_list.add_remove, arg->update_white_list.remote_bda, btc_add_whitelist_complete_callback);
|
||||
break;
|
||||
case BTC_GAP_BLE_ACT_READ_RSSI:
|
||||
BTA_DmBleReadRSSI(arg->read_rssi.remote_addr, btc_read_ble_rssi_cmpl_callback);
|
||||
|
@ -128,7 +128,8 @@ static void btc_gattc_copy_req_data(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
// Allocate buffer for request data if necessary
|
||||
switch (msg->act) {
|
||||
case BTA_GATTC_READ_DESCR_EVT:
|
||||
case BTA_GATTC_READ_CHAR_EVT: {
|
||||
case BTA_GATTC_READ_CHAR_EVT:
|
||||
case BTA_GATTC_READ_MUTIPLE_EVT: {
|
||||
if (p_src_data->read.p_value && p_src_data->read.p_value->p_value) {
|
||||
p_dest_data->read.p_value = (tBTA_GATT_UNFMT *)osi_malloc(sizeof(tBTA_GATT_UNFMT) + p_src_data->read.p_value->len);
|
||||
p_dest_data->read.p_value->p_value = (uint8_t *)(p_dest_data->read.p_value + 1);
|
||||
@ -151,7 +152,8 @@ static void btc_gattc_free_req_data(btc_msg_t *msg)
|
||||
tBTA_GATTC *arg = (tBTA_GATTC *)(msg->arg);
|
||||
switch (msg->act) {
|
||||
case BTA_GATTC_READ_DESCR_EVT:
|
||||
case BTA_GATTC_READ_CHAR_EVT: {
|
||||
case BTA_GATTC_READ_CHAR_EVT:
|
||||
case BTA_GATTC_READ_MUTIPLE_EVT: {
|
||||
if (arg->read.p_value) {
|
||||
osi_free(arg->read.p_value);
|
||||
}
|
||||
@ -554,6 +556,7 @@ esp_gatt_status_t btc_ble_gattc_get_db(uint16_t conn_id, uint16_t start_handle,
|
||||
db[i].attribute_handle = get_db[i].id;
|
||||
db[i].start_handle = get_db[i].start_handle;
|
||||
db[i].end_handle = get_db[i].end_handle;
|
||||
db[i].properties = get_db[i].properties;
|
||||
btc128_to_bta_uuid(&bta_uuid, get_db[i].uuid.uu);
|
||||
bta_to_btc_uuid(&db[i].uuid, &bta_uuid);
|
||||
}
|
||||
@ -806,6 +809,11 @@ void btc_gattc_cb_handler(btc_msg_t *msg)
|
||||
btc_gattc_cb_to_app(ESP_GATTC_READ_DESCR_EVT, gattc_if, ¶m);
|
||||
break;
|
||||
}
|
||||
case BTA_GATTC_READ_MUTIPLE_EVT: {
|
||||
set_read_value(&gattc_if, ¶m, &arg->read);
|
||||
btc_gattc_cb_to_app(ESP_GATTC_READ_MUTIPLE_EVT, gattc_if, ¶m);
|
||||
break;
|
||||
}
|
||||
case BTA_GATTC_WRITE_DESCR_EVT: {
|
||||
tBTA_GATTC_WRITE *write = &arg->write;
|
||||
|
||||
@ -850,7 +858,6 @@ void btc_gattc_cb_handler(btc_msg_t *msg)
|
||||
tBTA_GATTC_CONNECT *connect = &arg->connect;
|
||||
|
||||
gattc_if = connect->client_if;
|
||||
param.connect.status = connect->status;
|
||||
param.connect.conn_id = BTC_GATT_GET_CONN_ID(connect->conn_id);
|
||||
memcpy(param.connect.remote_bda, connect->remote_bda, sizeof(esp_bd_addr_t));
|
||||
btc_gattc_cb_to_app(ESP_GATTC_CONNECT_EVT, gattc_if, ¶m);
|
||||
@ -871,7 +878,7 @@ void btc_gattc_cb_handler(btc_msg_t *msg)
|
||||
tBTA_GATTC_DISCONNECT *disconnect = &arg->disconnect;
|
||||
|
||||
gattc_if = disconnect->client_if;
|
||||
param.disconnect.status = disconnect->status;
|
||||
param.disconnect.reason = disconnect->reason;
|
||||
param.disconnect.conn_id = BTC_GATT_GET_CONN_ID(disconnect->conn_id);
|
||||
memcpy(param.disconnect.remote_bda, disconnect->remote_bda, sizeof(esp_bd_addr_t));
|
||||
btc_gattc_cb_to_app(ESP_GATTC_DISCONNECT_EVT, gattc_if, ¶m);
|
||||
|
@ -527,6 +527,11 @@ static void btc_gatts_cb_param_copy_free(btc_msg_t *msg, tBTA_GATTS *p_data)
|
||||
osi_free(p_data->req_data.p_data);
|
||||
}
|
||||
break;
|
||||
case BTA_GATTS_CONF_EVT:
|
||||
if (p_data && p_data->req_data.value){
|
||||
osi_free(p_data->req_data.value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -787,6 +792,12 @@ void btc_gatts_cb_handler(btc_msg_t *msg)
|
||||
param.conf.conn_id = BTC_GATT_GET_CONN_ID(p_data->req_data.conn_id);
|
||||
param.conf.status = p_data->req_data.status;
|
||||
|
||||
if (p_data->req_data.status != ESP_GATT_OK && p_data->req_data.value){
|
||||
param.conf.len = p_data->req_data.data_len;
|
||||
param.conf.value = p_data->req_data.value;
|
||||
}else{
|
||||
param.conf.len = 0;
|
||||
}
|
||||
btc_gatts_cb_to_app(ESP_GATTS_CONF_EVT, gatts_if, ¶m);
|
||||
break;
|
||||
case BTA_GATTS_CREATE_EVT:
|
||||
@ -849,7 +860,6 @@ void btc_gatts_cb_handler(btc_msg_t *msg)
|
||||
case BTA_GATTS_CONNECT_EVT:
|
||||
gatts_if = p_data->conn.server_if;
|
||||
param.connect.conn_id = BTC_GATT_GET_CONN_ID(p_data->conn.conn_id);
|
||||
param.connect.is_connected = true;
|
||||
memcpy(param.connect.remote_bda, p_data->conn.remote_bda, ESP_BD_ADDR_LEN);
|
||||
|
||||
btc_gatts_cb_to_app(ESP_GATTS_CONNECT_EVT, gatts_if, ¶m);
|
||||
@ -857,7 +867,7 @@ void btc_gatts_cb_handler(btc_msg_t *msg)
|
||||
case BTA_GATTS_DISCONNECT_EVT:
|
||||
gatts_if = p_data->conn.server_if;
|
||||
param.disconnect.conn_id = BTC_GATT_GET_CONN_ID(p_data->conn.conn_id);
|
||||
param.disconnect.is_connected = false;
|
||||
param.disconnect.reason = p_data->conn.reason;
|
||||
memcpy(param.disconnect.remote_bda, p_data->conn.remote_bda, ESP_BD_ADDR_LEN);
|
||||
|
||||
btc_gatts_cb_to_app(ESP_GATTS_DISCONNECT_EVT, gatts_if, ¶m);
|
||||
|
@ -442,9 +442,7 @@ void bta_dm_co_ble_io_req(BD_ADDR bd_addr, tBTA_IO_CAP *p_io_cap,
|
||||
|
||||
/* *p_auth_req by default is FALSE for devices with NoInputNoOutput; TRUE for other devices. */
|
||||
|
||||
if (bte_appl_cfg.ble_auth_req) {
|
||||
*p_auth_req = bte_appl_cfg.ble_auth_req | (bte_appl_cfg.ble_auth_req & 0x04) | ((*p_auth_req) & 0x04);
|
||||
}
|
||||
*p_auth_req = bte_appl_cfg.ble_auth_req | (bte_appl_cfg.ble_auth_req & BTA_LE_AUTH_REQ_MITM) | ((*p_auth_req) & BTA_LE_AUTH_REQ_MITM);
|
||||
|
||||
if (bte_appl_cfg.ble_io_cap <= 4) {
|
||||
*p_io_cap = bte_appl_cfg.ble_io_cap;
|
||||
|
@ -101,8 +101,8 @@ static bool hal_open(const hci_hal_callbacks_t *upper_callbacks)
|
||||
|
||||
hci_hal_env_init(HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX);
|
||||
|
||||
xHciH4Queue = xQueueCreate(HCI_H4_QUEUE_NUM, sizeof(BtTaskEvt_t));
|
||||
xTaskCreatePinnedToCore(hci_hal_h4_rx_handler, HCI_H4_TASK_NAME, HCI_H4_TASK_STACK_SIZE, NULL, HCI_H4_TASK_PRIO, &xHciH4TaskHandle, 0);
|
||||
xHciH4Queue = xQueueCreate(HCI_H4_QUEUE_LEN, sizeof(BtTaskEvt_t));
|
||||
xTaskCreatePinnedToCore(hci_hal_h4_rx_handler, HCI_H4_TASK_NAME, HCI_H4_TASK_STACK_SIZE, NULL, HCI_H4_TASK_PRIO, &xHciH4TaskHandle, HCI_H4_TASK_PINNED_TO_CORE);
|
||||
|
||||
//register vhci host cb
|
||||
esp_vhci_host_register_callback(&vhci_host_cb);
|
||||
|
@ -107,8 +107,8 @@ int hci_start_up(void)
|
||||
goto error;
|
||||
}
|
||||
|
||||
xHciHostQueue = xQueueCreate(HCI_HOST_QUEUE_NUM, sizeof(BtTaskEvt_t));
|
||||
xTaskCreatePinnedToCore(hci_host_thread_handler, HCI_HOST_TASK_NAME, HCI_HOST_TASK_STACK_SIZE, NULL, HCI_HOST_TASK_PRIO, &xHciHostTaskHandle, 0);
|
||||
xHciHostQueue = xQueueCreate(HCI_HOST_QUEUE_LEN, sizeof(BtTaskEvt_t));
|
||||
xTaskCreatePinnedToCore(hci_host_thread_handler, HCI_HOST_TASK_NAME, HCI_HOST_TASK_STACK_SIZE, NULL, HCI_HOST_TASK_PRIO, &xHciHostTaskHandle, HCI_HOST_TASK_PINNED_TO_CORE);
|
||||
|
||||
packet_fragmenter->init(&packet_fragmenter_callbacks);
|
||||
hal->open(&hal_callbacks);
|
||||
|
@ -681,11 +681,15 @@
|
||||
/* The maximum number of simultaneous channels that L2CAP can support. Up to 16*/
|
||||
#ifndef MAX_L2CAP_CHANNELS
|
||||
#if (CLASSIC_BT_INCLUDED == TRUE)
|
||||
#define MAX_L2CAP_CHANNELS 8
|
||||
#define MAX_L2CAP_CHANNELS 16
|
||||
#else
|
||||
#if (SMP_INCLUDED == FALSE)
|
||||
#define MAX_L2CAP_CHANNELS MAX_ACL_CONNECTIONS //This is used in the BLE client when start connected with the peer device
|
||||
#else
|
||||
#define MAX_L2CAP_CHANNELS (MAX_ACL_CONNECTIONS * 2) //This is used in the BLE client when start connected with the peer device and in SMP
|
||||
#endif ///SMP_INCLUDED == FALSE
|
||||
#endif ///CLASSIC_BT_INCLUDED == TRUE
|
||||
#endif
|
||||
#endif ///MAX_L2CAP_CHANNELS
|
||||
|
||||
/* The maximum number of simultaneous applications that can register with L2CAP. */
|
||||
#ifndef MAX_L2CAP_CLIENTS
|
||||
|
@ -57,26 +57,39 @@ typedef enum {
|
||||
SIG_BTU_NUM,
|
||||
} SIG_BTU_t;
|
||||
|
||||
#define TASK_PINNED_TO_CORE (CONFIG_BLUEDROID_PINNED_TO_CORE < portNUM_PROCESSORS ? CONFIG_BLUEDROID_PINNED_TO_CORE : tskNO_AFFINITY)
|
||||
|
||||
#define HCI_HOST_TASK_PINNED_TO_CORE (TASK_PINNED_TO_CORE)
|
||||
#define HCI_HOST_TASK_STACK_SIZE (2048 + BT_TASK_EXTRA_STACK_SIZE)
|
||||
#define HCI_HOST_TASK_PRIO (configMAX_PRIORITIES - 3)
|
||||
#define HCI_HOST_TASK_NAME "hciHostT"
|
||||
#define HCI_HOST_QUEUE_NUM 40
|
||||
#define HCI_HOST_QUEUE_LEN 40
|
||||
|
||||
#define HCI_H4_TASK_PINNED_TO_CORE (TASK_PINNED_TO_CORE)
|
||||
#define HCI_H4_TASK_STACK_SIZE (2048 + BT_TASK_EXTRA_STACK_SIZE)
|
||||
#define HCI_H4_TASK_PRIO (configMAX_PRIORITIES - 4)
|
||||
#define HCI_H4_TASK_NAME "hciH4T"
|
||||
#define HCI_H4_QUEUE_NUM 60
|
||||
#define HCI_H4_QUEUE_LEN 60
|
||||
|
||||
#define BTU_TASK_PINNED_TO_CORE (TASK_PINNED_TO_CORE)
|
||||
#define BTU_TASK_STACK_SIZE (4096 + BT_TASK_EXTRA_STACK_SIZE)
|
||||
#define BTU_TASK_PRIO (configMAX_PRIORITIES - 5)
|
||||
#define BTU_TASK_NAME "btuT"
|
||||
#define BTU_QUEUE_NUM 50
|
||||
#define BTU_QUEUE_LEN 50
|
||||
|
||||
#define BTC_TASK_PINNED_TO_CORE (TASK_PINNED_TO_CORE)
|
||||
#define BTC_TASK_STACK_SIZE (CONFIG_BTC_TASK_STACK_SIZE + BT_TASK_EXTRA_STACK_SIZE) //by menuconfig
|
||||
#define BTC_TASK_NAME "btcT"
|
||||
#define BTC_TASK_PRIO (configMAX_PRIORITIES - 6)
|
||||
#define BTC_TASK_QUEUE_NUM 60
|
||||
#define BTC_TASK_QUEUE_LEN 60
|
||||
|
||||
#define BTC_MEDIA_TASK_PINNED_TO_CORE (TASK_PINNED_TO_CORE)
|
||||
#define BTC_MEDIA_TASK_STACK_SIZE (CONFIG_BTC_TASK_STACK_SIZE + BT_TASK_EXTRA_STACK_SIZE)
|
||||
#define BTC_MEDIA_TASK_NAME "BtcMediaT"
|
||||
#define BTC_MEDIA_TASK_PRIO (configMAX_PRIORITIES - 3)
|
||||
#define BTC_MEDIA_DATA_QUEUE_LEN (1)
|
||||
#define BTC_MEDIA_CTRL_QUEUE_LEN (5)
|
||||
#define BTC_MEDIA_TASK_QUEUE_SET_LEN (BTC_MEDIA_DATA_QUEUE_LEN + BTC_MEDIA_CTRL_QUEUE_LEN)
|
||||
|
||||
#define TASK_POST_NON_BLOCKING (0)
|
||||
#define TASK_POST_BLOCKING (portMAX_DELAY)
|
||||
|
@ -180,7 +180,11 @@ BOOLEAN BTM_SecAddBleKey (BD_ADDR bd_addr, tBTM_LE_KEY_VALUE *p_le_key, tBTM_LE_
|
||||
|
||||
#if (BLE_PRIVACY_SPT == TRUE)
|
||||
if (key_type == BTM_LE_KEY_PID || key_type == BTM_LE_KEY_LID) {
|
||||
btm_ble_resolving_list_load_dev (p_dev_rec);
|
||||
/* It will cause that scanner doesn't send scan request to advertiser
|
||||
* which has sent IRK to us and we have stored the IRK in controller.
|
||||
* It is a design problem of hardware. The temporal solution is not to
|
||||
* send the key to the controller and then resolve the random address in host. */
|
||||
//btm_ble_resolving_list_load_dev (p_dev_rec);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1413,7 +1417,7 @@ tBTM_STATUS btm_ble_set_encryption (BD_ADDR bd_addr, void *p_ref_data, UINT8 lin
|
||||
|
||||
switch (sec_act) {
|
||||
case BTM_BLE_SEC_ENCRYPT:
|
||||
if (link_role == BTM_ROLE_MASTER) {
|
||||
if (link_role == BTM_ROLE_MASTER && (p_rec->ble.key_type & BTM_LE_KEY_PENC)) {
|
||||
/* start link layer encryption using the security info stored */
|
||||
cmd = btm_ble_start_encrypt(bd_addr, FALSE, NULL);
|
||||
break;
|
||||
@ -1422,7 +1426,7 @@ tBTM_STATUS btm_ble_set_encryption (BD_ADDR bd_addr, void *p_ref_data, UINT8 lin
|
||||
sec_request to request the master to encrypt the link */
|
||||
case BTM_BLE_SEC_ENCRYPT_NO_MITM:
|
||||
case BTM_BLE_SEC_ENCRYPT_MITM:
|
||||
if (link_role == BTM_ROLE_MASTER) {
|
||||
if ((link_role == BTM_ROLE_MASTER) && (sec_act != BTM_BLE_SEC_ENCRYPT)) {
|
||||
auth_req = (sec_act == BTM_BLE_SEC_ENCRYPT_NO_MITM)
|
||||
? SMP_AUTH_GEN_BOND : (SMP_AUTH_GEN_BOND | SMP_AUTH_YN_BIT);
|
||||
btm_ble_link_sec_check (bd_addr, auth_req, &sec_req_act);
|
||||
@ -2062,7 +2066,11 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data)
|
||||
p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
|
||||
#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
|
||||
/* add all bonded device into resolving list if IRK is available*/
|
||||
btm_ble_resolving_list_load_dev(p_dev_rec);
|
||||
/* It will cause that scanner doesn't send scan request to advertiser
|
||||
* which has sent IRK to us and we have stored the IRK in controller.
|
||||
* It is a design problem of hardware. The temporal solution is not to
|
||||
* send the key to the controller and then resolve the random address in host. */
|
||||
//btm_ble_resolving_list_load_dev(p_dev_rec);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
|
||||
static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state);
|
||||
static void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state);
|
||||
static void btm_wl_update_to_controller(void);
|
||||
|
||||
// Unfortunately (for now?) we have to maintain a copy of the device whitelist
|
||||
// on the host to determine if a device is pending to be connected or not. This
|
||||
@ -185,9 +185,10 @@ BOOLEAN btm_add_dev_to_controller (BOOLEAN to_add, BD_ADDR bd_addr)
|
||||
else {
|
||||
BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type);
|
||||
|
||||
started = btsnd_hcic_ble_remove_from_white_list (addr_type, bd_addr);
|
||||
if (to_add) {
|
||||
started = btsnd_hcic_ble_add_white_list (addr_type, bd_addr);
|
||||
}else{
|
||||
started = btsnd_hcic_ble_remove_from_white_list (addr_type, bd_addr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,7 +254,7 @@ void btm_enq_wl_dev_operation(BOOLEAN to_add, BD_ADDR bd_addr)
|
||||
** the white list.
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr)
|
||||
BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr, tBTM_ADD_WHITELIST_CBACK *add_wl_cb)
|
||||
{
|
||||
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
|
||||
|
||||
@ -261,6 +262,10 @@ BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr)
|
||||
BTM_TRACE_DEBUG("%s Whitelist full, unable to add device", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
if (add_wl_cb){
|
||||
//save add whitelist complete callback
|
||||
p_cb->add_wl_cb = add_wl_cb;
|
||||
}
|
||||
|
||||
if (to_add) {
|
||||
/* added the bd_addr to the connection hash map queue */
|
||||
@ -273,8 +278,8 @@ BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr)
|
||||
btm_suspend_wl_activity(p_cb->wl_state);
|
||||
/* save the bd_addr to the btm_cb env */
|
||||
btm_enq_wl_dev_operation(to_add, bd_addr);
|
||||
/* save the ba_addr to the controller white list & start the auto connet */
|
||||
btm_resume_wl_activity(p_cb->wl_state);
|
||||
/* save the ba_addr to the controller white list */
|
||||
btm_wl_update_to_controller();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -336,9 +341,16 @@ void btm_ble_white_list_init(UINT8 white_list_size)
|
||||
void btm_ble_add_2_white_list_complete(UINT8 status)
|
||||
{
|
||||
BTM_TRACE_EVENT("%s status=%d", __func__, status);
|
||||
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
|
||||
if (status == HCI_SUCCESS) {
|
||||
--btm_cb.ble_ctr_cb.white_list_avail_size;
|
||||
}
|
||||
// add whitelist complete callback
|
||||
if (p_cb->add_wl_cb)
|
||||
{
|
||||
(*p_cb->add_wl_cb)(status, BTM_WHITELIST_ADD);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@ -350,11 +362,16 @@ void btm_ble_add_2_white_list_complete(UINT8 status)
|
||||
*******************************************************************************/
|
||||
void btm_ble_remove_from_white_list_complete(UINT8 *p, UINT16 evt_len)
|
||||
{
|
||||
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
|
||||
UNUSED(evt_len);
|
||||
BTM_TRACE_EVENT ("%s status=%d", __func__, *p);
|
||||
if (*p == HCI_SUCCESS) {
|
||||
++btm_cb.ble_ctr_cb.white_list_avail_size;
|
||||
}
|
||||
if (p_cb->add_wl_cb)
|
||||
{
|
||||
(*p_cb->add_wl_cb)(*p, BTM_WHITELIST_REMOVE);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@ -594,14 +611,32 @@ static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state)
|
||||
** Returns none.
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state)
|
||||
void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state)
|
||||
{
|
||||
btm_ble_resume_bg_conn();
|
||||
|
||||
if (wl_state & BTM_BLE_WL_ADV) {
|
||||
btm_ble_start_adv();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_wl_update_to_controller
|
||||
**
|
||||
** Description This function is to update white list to controller
|
||||
**
|
||||
** Returns none.
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void btm_wl_update_to_controller(void)
|
||||
{
|
||||
/* whitelist will be added in the btm_ble_resume_bg_conn(), we do not
|
||||
support background connection now, so we nedd to use btm_execute_wl_dev_operation
|
||||
to add whitelist directly ,if we support background connection in the future,
|
||||
please delete btm_execute_wl_dev_operation(). */
|
||||
btm_execute_wl_dev_operation();
|
||||
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
|
@ -74,10 +74,12 @@ static UINT8 btm_set_conn_mode_adv_init_addr(tBTM_BLE_INQ_CB *p_cb,
|
||||
tBLE_ADDR_TYPE *p_peer_addr_type,
|
||||
tBLE_ADDR_TYPE *p_own_addr_type);
|
||||
static void btm_ble_stop_observe(void);
|
||||
static void btm_ble_stop_discover(void);
|
||||
|
||||
#define BTM_BLE_INQ_RESULT 0x01
|
||||
#define BTM_BLE_OBS_RESULT 0x02
|
||||
#define BTM_BLE_SEL_CONN_RESULT 0x04
|
||||
#define BTM_BLE_DISCO_RESULT 0x08
|
||||
|
||||
/* LE states combo bit to check */
|
||||
const UINT8 btm_le_state_combo_tbl[BTM_BLE_STATE_MAX][BTM_BLE_STATE_MAX][2] = {
|
||||
@ -244,9 +246,9 @@ void BTM_BleRegiseterConnParamCallback(tBTM_UPDATE_CONN_PARAM_CBACK *update_conn
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN BTM_BleUpdateAdvWhitelist(BOOLEAN add_remove, BD_ADDR remote_bda)
|
||||
BOOLEAN BTM_BleUpdateAdvWhitelist(BOOLEAN add_remove, BD_ADDR remote_bda, tBTM_ADD_WHITELIST_CBACK *add_wl_cb)
|
||||
{
|
||||
return btm_update_dev_to_white_list(add_remove, remote_bda);
|
||||
return btm_update_dev_to_white_list(add_remove, remote_bda, add_wl_cb);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@ -424,6 +426,84 @@ tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT32 duration,
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_BleScan
|
||||
**
|
||||
** Description This procedure keep the device listening for advertising
|
||||
** events from a broadcast device.
|
||||
**
|
||||
** Parameters start: start or stop scan.
|
||||
** white_list: use white list in observer mode or not.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS BTM_BleScan(BOOLEAN start, UINT32 duration,
|
||||
tBTM_INQ_RESULTS_CB *p_results_cb, tBTM_CMPL_CB *p_cmpl_cb)
|
||||
{
|
||||
tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var;
|
||||
tBTM_STATUS status = BTM_WRONG_MODE;
|
||||
|
||||
if (!controller_get_interface()->supports_ble()) {
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
if (start) {
|
||||
/* shared inquiry database, do not allow scan if any inquiry is active */
|
||||
if (BTM_BLE_IS_DISCO_ACTIVE(btm_cb.ble_ctr_cb.scan_activity)) {
|
||||
BTM_TRACE_ERROR("%s scan already active", __func__);
|
||||
return status;
|
||||
}
|
||||
|
||||
btm_cb.ble_ctr_cb.p_scan_results_cb = p_results_cb;
|
||||
btm_cb.ble_ctr_cb.p_scan_cmpl_cb = p_cmpl_cb;
|
||||
status = BTM_CMD_STARTED;
|
||||
|
||||
/* scan is not started */
|
||||
if (!BTM_BLE_IS_SCAN_ACTIVE(btm_cb.ble_ctr_cb.scan_activity)) {
|
||||
/* assume observe always not using white list */
|
||||
#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
|
||||
/* enable resolving list */
|
||||
btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_SCAN);
|
||||
#endif
|
||||
// if not set scan params, set defalult scan params
|
||||
if (!p_inq->scan_params_set)
|
||||
{
|
||||
/* allow config of scan type */
|
||||
p_inq->scan_type = BTM_BLE_SCAN_MODE_ACTI;
|
||||
p_inq->scan_interval = BTM_BLE_GAP_DISC_SCAN_INT;
|
||||
p_inq->scan_window = BTM_BLE_GAP_DISC_SCAN_WIN;
|
||||
p_inq->sfp = BTM_BLE_DEFAULT_SFP;
|
||||
p_inq->scan_params_set = TRUE;
|
||||
btsnd_hcic_ble_set_scan_params(p_inq->scan_type, p_inq->scan_interval,
|
||||
p_inq->scan_window,
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
|
||||
p_inq->sfp);
|
||||
}
|
||||
p_inq->scan_duplicate_filter = BTM_BLE_DUPLICATE_DISABLE;
|
||||
status = btm_ble_start_scan();
|
||||
}
|
||||
|
||||
if (status == BTM_CMD_STARTED) {
|
||||
btm_cb.ble_ctr_cb.scan_activity |= BTM_LE_DISCOVER_ACTIVE;
|
||||
if (duration != 0)
|
||||
/* start observer timer */
|
||||
{
|
||||
btu_start_timer (&btm_cb.ble_ctr_cb.scan_timer_ent, BTU_TTYPE_BLE_SCAN, duration);
|
||||
}
|
||||
}
|
||||
} else if (BTM_BLE_IS_DISCO_ACTIVE(btm_cb.ble_ctr_cb.scan_activity)) {
|
||||
status = BTM_CMD_STARTED;
|
||||
btm_ble_stop_discover();
|
||||
} else {
|
||||
BTM_TRACE_ERROR("%s scan not active\n", __func__);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_BleBroadcast
|
||||
@ -882,7 +962,7 @@ void BTM_BleClearBgConnDev(void)
|
||||
BOOLEAN BTM_BleUpdateBgConnDev(BOOLEAN add_remove, BD_ADDR remote_bda)
|
||||
{
|
||||
BTM_TRACE_EVENT("%s() add=%d", __func__, add_remove);
|
||||
return btm_update_dev_to_white_list(add_remove, remote_bda);
|
||||
return btm_update_dev_to_white_list(add_remove, remote_bda, NULL);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@ -1263,6 +1343,7 @@ void BTM_BleSetScanFilterParams(tGATT_IF client_if, UINT32 scan_interval, UINT32
|
||||
p_cb->scan_interval = scan_interval;
|
||||
p_cb->scan_window = scan_window;
|
||||
p_cb->sfp = scan_filter_policy;
|
||||
p_cb->scan_params_set = TRUE;
|
||||
|
||||
btsnd_hcic_ble_set_scan_params(p_cb->scan_type, (UINT16)scan_interval,
|
||||
(UINT16)scan_window,
|
||||
@ -2470,6 +2551,10 @@ UINT8 btm_ble_is_discoverable(BD_ADDR bda, UINT8 evt_type, UINT8 *p)
|
||||
if (BTM_BLE_IS_OBS_ACTIVE(btm_cb.ble_ctr_cb.scan_activity)) {
|
||||
rt |= BTM_BLE_OBS_RESULT;
|
||||
}
|
||||
/* for discover, always "discoverable */
|
||||
if (BTM_BLE_IS_DISCO_ACTIVE(btm_cb.ble_ctr_cb.scan_activity)) {
|
||||
rt |= BTM_BLE_DISCO_RESULT;
|
||||
}
|
||||
|
||||
if (BTM_BLE_IS_SEL_CONN_ACTIVE(btm_cb.ble_ctr_cb.scan_activity) &&
|
||||
(evt_type == BTM_BLE_CONNECT_EVT || evt_type == BTM_BLE_CONNECT_DIR_EVT)) {
|
||||
@ -2884,10 +2969,12 @@ void btm_ble_process_adv_pkt (UINT8 *p_data)
|
||||
*******************************************************************************/
|
||||
static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt_type, UINT8 *p)
|
||||
{
|
||||
|
||||
tINQ_DB_ENT *p_i;
|
||||
tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
|
||||
tBTM_INQ_RESULTS_CB *p_inq_results_cb = p_inq->p_inq_results_cb;
|
||||
tBTM_INQ_RESULTS_CB *p_obs_results_cb = btm_cb.ble_ctr_cb.p_obs_results_cb;
|
||||
tBTM_INQ_RESULTS_CB *p_scan_results_cb = btm_cb.ble_ctr_cb.p_scan_results_cb;
|
||||
tBTM_BLE_INQ_CB *p_le_inq_cb = &btm_cb.ble_ctr_cb.inq_var;
|
||||
BOOLEAN update = TRUE;
|
||||
UINT8 result = 0;
|
||||
@ -2902,7 +2989,7 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt
|
||||
/* scan repsonse to be updated */
|
||||
(!p_i->scan_rsp))) {
|
||||
update = TRUE;
|
||||
} else if (BTM_BLE_IS_OBS_ACTIVE(btm_cb.ble_ctr_cb.scan_activity)) {
|
||||
} else if (BTM_BLE_IS_DISCO_ACTIVE(btm_cb.ble_ctr_cb.scan_activity)) {
|
||||
update = FALSE;
|
||||
} else {
|
||||
/* if yes, skip it */
|
||||
@ -2968,6 +3055,9 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt
|
||||
if (p_obs_results_cb && (result & BTM_BLE_OBS_RESULT)) {
|
||||
(p_obs_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);
|
||||
}
|
||||
if (p_scan_results_cb && (result & BTM_BLE_DISCO_RESULT)) {
|
||||
(p_scan_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3088,6 +3178,41 @@ static void btm_ble_stop_observe(void)
|
||||
(p_obs_cb)((tBTM_INQUIRY_CMPL *) &btm_cb.btm_inq_vars.inq_cmpl_info);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_stop_observe
|
||||
**
|
||||
** Description Stop the BLE Observe.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void btm_ble_stop_discover(void)
|
||||
{
|
||||
tBTM_BLE_CB *p_ble_cb = & btm_cb.ble_ctr_cb;
|
||||
tBTM_CMPL_CB *p_scan_cb = p_ble_cb->p_scan_cmpl_cb;
|
||||
|
||||
btu_stop_timer (&p_ble_cb->scan_timer_ent);
|
||||
|
||||
p_ble_cb->scan_activity &= ~BTM_LE_DISCOVER_ACTIVE;
|
||||
|
||||
p_ble_cb->p_scan_results_cb = NULL;
|
||||
p_ble_cb->p_scan_cmpl_cb = NULL;
|
||||
|
||||
if (!BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity)) {
|
||||
/* Clear the inquiry callback if set */
|
||||
btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
|
||||
btm_cb.ble_ctr_cb.inq_var.state = BTM_BLE_STOP_SCAN;
|
||||
/* stop discovery now */
|
||||
btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
|
||||
}
|
||||
|
||||
if (p_scan_cb) {
|
||||
(p_scan_cb)((tBTM_INQUIRY_CMPL *) &btm_cb.btm_inq_vars.inq_cmpl_info);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_adv_states_operation
|
||||
@ -3260,7 +3385,9 @@ void btm_ble_timeout(TIMER_LIST_ENT *p_tle)
|
||||
case BTU_TTYPE_BLE_OBSERVE:
|
||||
btm_ble_stop_observe();
|
||||
break;
|
||||
|
||||
case BTU_TTYPE_BLE_SCAN:
|
||||
btm_ble_stop_discover();
|
||||
break;
|
||||
case BTU_TTYPE_BLE_INQUIRY:
|
||||
btm_ble_stop_inquiry();
|
||||
break;
|
||||
|
@ -168,8 +168,8 @@ void BTU_StartUp(void)
|
||||
|
||||
osi_mutex_new(&btu_l2cap_alarm_lock);
|
||||
|
||||
xBtuQueue = xQueueCreate(BTU_QUEUE_NUM, sizeof(BtTaskEvt_t));
|
||||
xTaskCreatePinnedToCore(btu_task_thread_handler, BTU_TASK_NAME, BTU_TASK_STACK_SIZE, NULL, BTU_TASK_PRIO, &xBtuTaskHandle, 0);
|
||||
xBtuQueue = xQueueCreate(BTU_QUEUE_LEN, sizeof(BtTaskEvt_t));
|
||||
xTaskCreatePinnedToCore(btu_task_thread_handler, BTU_TASK_NAME, BTU_TASK_STACK_SIZE, NULL, BTU_TASK_PRIO, &xBtuTaskHandle, BTU_TASK_PINNED_TO_CORE);
|
||||
|
||||
btu_task_post(SIG_BTU_START_UP, NULL, TASK_POST_BLOCKING);
|
||||
|
||||
|
@ -385,6 +385,7 @@ static void btu_general_alarm_process(TIMER_LIST_ENT *p_tle)
|
||||
case BTU_TTYPE_BLE_GAP_LIM_DISC:
|
||||
case BTU_TTYPE_BLE_RANDOM_ADDR:
|
||||
case BTU_TTYPE_BLE_GAP_FAST_ADV:
|
||||
case BTU_TTYPE_BLE_SCAN:
|
||||
case BTU_TTYPE_BLE_OBSERVE:
|
||||
btm_ble_timeout(p_tle);
|
||||
break;
|
||||
|
@ -567,7 +567,6 @@ tGATT_STATUS GATTS_HandleValueIndication (UINT16 conn_id, UINT16 attr_handle, U
|
||||
|
||||
tGATT_VALUE indication;
|
||||
BT_HDR *p_msg;
|
||||
tGATT_VALUE *p_buf;
|
||||
tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
|
||||
UINT8 tcb_idx = GATT_GET_TCB_IDX(conn_id);
|
||||
tGATT_REG *p_reg = gatt_get_regcb(gatt_if);
|
||||
@ -591,12 +590,16 @@ tGATT_STATUS GATTS_HandleValueIndication (UINT16 conn_id, UINT16 attr_handle, U
|
||||
indication.auth_req = GATT_AUTH_REQ_NONE;
|
||||
|
||||
if (GATT_HANDLE_IS_VALID(p_tcb->indicate_handle)) {
|
||||
/* TODO: need to further check whether deleting pending queue here cause reducing transport performance */
|
||||
/*
|
||||
GATT_TRACE_DEBUG ("Add a pending indication");
|
||||
if ((p_buf = gatt_add_pending_ind(p_tcb, &indication)) != NULL) {
|
||||
cmd_status = GATT_SUCCESS;
|
||||
} else {
|
||||
cmd_status = GATT_NO_RESOURCES;
|
||||
}
|
||||
*/
|
||||
return GATT_BUSY;
|
||||
} else {
|
||||
|
||||
if ( (p_msg = attp_build_sr_msg (p_tcb, GATT_HANDLE_VALUE_IND, (tGATT_SR_MSG *)&indication)) != NULL) {
|
||||
@ -723,7 +726,9 @@ tGATT_STATUS GATTS_SetAttributeValue(UINT16 attr_handle, UINT16 length, UINT8 *v
|
||||
|
||||
GATT_TRACE_DEBUG("GATTS_SetAttributeValue: attr_handle: %u length: %u \n",
|
||||
attr_handle, length);
|
||||
|
||||
if (length <= 0){
|
||||
return GATT_INVALID_ATTR_LEN;
|
||||
}
|
||||
if ((p_decl = gatt_find_hdl_buffer_by_attr_handle(attr_handle)) == NULL) {
|
||||
GATT_TRACE_DEBUG("Service not created\n");
|
||||
return GATT_INVALID_HANDLE;
|
||||
|
@ -421,6 +421,8 @@ void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U
|
||||
if (is_prepare_write_valid){
|
||||
if((queue_data->p_attr->p_value != NULL) && (queue_data->p_attr->p_value->attr_val.attr_val != NULL)){
|
||||
memcpy(queue_data->p_attr->p_value->attr_val.attr_val+queue_data->offset, queue_data->value, queue_data->len);
|
||||
//don't forget to increase the attribute value length in the gatts database.
|
||||
queue_data->p_attr->p_value->attr_val.attr_len += queue_data->len;
|
||||
}
|
||||
}
|
||||
osi_free(queue_data);
|
||||
|
@ -2416,7 +2416,7 @@ BOOLEAN gatt_add_bg_dev_list(tGATT_REG *p_reg, BD_ADDR bd_addr, BOOLEAN is_init
|
||||
p_dev->listen_gif[i] = gatt_if;
|
||||
|
||||
if (i == 0) {
|
||||
ret = BTM_BleUpdateAdvWhitelist(TRUE, bd_addr);
|
||||
ret = BTM_BleUpdateAdvWhitelist(TRUE, bd_addr, NULL);
|
||||
} else {
|
||||
ret = TRUE;
|
||||
}
|
||||
@ -2556,7 +2556,7 @@ BOOLEAN gatt_remove_bg_dev_from_list(tGATT_REG *p_reg, BD_ADDR bd_addr, BOOLEAN
|
||||
}
|
||||
|
||||
if (p_dev->listen_gif[0] == 0) {
|
||||
ret = BTM_BleUpdateAdvWhitelist(FALSE, p_dev->remote_bda);
|
||||
ret = BTM_BleUpdateAdvWhitelist(FALSE, p_dev->remote_bda, NULL);
|
||||
} else {
|
||||
ret = TRUE;
|
||||
}
|
||||
@ -2617,7 +2617,7 @@ void gatt_deregister_bgdev_list(tGATT_IF gatt_if)
|
||||
}
|
||||
|
||||
if (p_dev_list->listen_gif[0] == 0) {
|
||||
BTM_BleUpdateAdvWhitelist(FALSE, p_dev_list->remote_bda);
|
||||
BTM_BleUpdateAdvWhitelist(FALSE, p_dev_list->remote_bda, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -146,6 +146,11 @@ typedef struct {
|
||||
UINT16 supervision_tout;
|
||||
}tBTM_LE_UPDATE_CONN_PRAMS;
|
||||
|
||||
typedef enum{
|
||||
BTM_WHITELIST_REMOVE = 0X00,
|
||||
BTM_WHITELIST_ADD = 0X01,
|
||||
}tBTM_WL_OPERATION;
|
||||
|
||||
|
||||
typedef void (tBTM_DEV_STATUS_CB) (tBTM_DEV_STATUS status);
|
||||
|
||||
@ -177,6 +182,8 @@ typedef void (tBTM_UPDATE_CONN_PARAM_CBACK) (UINT8 status, BD_ADDR bd_addr, tBTM
|
||||
|
||||
typedef void (tBTM_SET_PKT_DATA_LENGTH_CBACK) (UINT8 status, tBTM_LE_SET_PKT_DATA_LENGTH_PARAMS *data_length_params);
|
||||
|
||||
typedef void (tBTM_ADD_WHITELIST_CBACK) (UINT8 status, tBTM_WL_OPERATION wl_opration);
|
||||
|
||||
typedef void (tBTM_SET_LOCAL_PRIVACY_CBACK) (UINT8 status);
|
||||
|
||||
|
||||
@ -234,7 +241,7 @@ typedef void (tBTM_SET_LOCAL_PRIVACY_CBACK) (UINT8 status);
|
||||
|
||||
/* inquiry activity mask */
|
||||
#define BTM_BR_INQ_ACTIVE_MASK (BTM_GENERAL_INQUIRY_ACTIVE|BTM_LIMITED_INQUIRY_ACTIVE|BTM_PERIODIC_INQUIRY_ACTIVE) /* BR/EDR inquiry activity mask */
|
||||
#define BTM_BLE_SCAN_ACTIVE_MASK 0xF0 /* LE scan activity mask */
|
||||
#define BTM_BLE_SCAN_ACTIVE_MASK 0x01F0 /* LE scan activity mask */
|
||||
#define BTM_BLE_INQ_ACTIVE_MASK (BTM_LE_GENERAL_INQUIRY_ACTIVE|BTM_LE_LIMITED_INQUIRY_ACTIVE) /* LE inquiry activity mask*/
|
||||
#define BTM_INQUIRY_ACTIVE_MASK (BTM_BR_INQ_ACTIVE_MASK | BTM_BLE_INQ_ACTIVE_MASK) /* inquiry activity mask */
|
||||
|
||||
|
@ -1207,6 +1207,22 @@ tBTM_STATUS BTM_BleWriteScanRspRaw(UINT8 *p_raw_scan_rsp, UINT32 raw_scan_rsp_le
|
||||
tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT32 duration,
|
||||
tBTM_INQ_RESULTS_CB *p_results_cb, tBTM_CMPL_CB *p_cmpl_cb);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_BleScan
|
||||
**
|
||||
** Description This procedure keep the device listening for advertising
|
||||
** events from a broadcast device.
|
||||
**
|
||||
** Parameters start: start or stop scan.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
//extern
|
||||
tBTM_STATUS BTM_BleScan(BOOLEAN start, UINT32 duration,
|
||||
tBTM_INQ_RESULTS_CB *p_results_cb, tBTM_CMPL_CB *p_cmpl_cb);
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
@ -1695,7 +1711,7 @@ void BTM_BleTurnOnPrivacyOnRemote(BD_ADDR bd_addr,
|
||||
**
|
||||
*******************************************************************************/
|
||||
//extern
|
||||
BOOLEAN BTM_BleUpdateAdvWhitelist(BOOLEAN add_remove, BD_ADDR emote_bda);
|
||||
BOOLEAN BTM_BleUpdateAdvWhitelist(BOOLEAN add_remove, BD_ADDR emote_bda, tBTM_ADD_WHITELIST_CBACK *add_wl_cb);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
|
@ -86,13 +86,15 @@ typedef UINT8 tBTM_BLE_SEC_REQ_ACT;
|
||||
#define BTM_BLE_IS_RESOLVE_BDA(x) ((x[0] & BLE_RESOLVE_ADDR_MASK) == BLE_RESOLVE_ADDR_MSB)
|
||||
|
||||
/* LE scan activity bit mask, continue with LE inquiry bits */
|
||||
#define BTM_LE_SELECT_CONN_ACTIVE 0x40 /* selection connection is in progress */
|
||||
#define BTM_LE_OBSERVE_ACTIVE 0x80 /* observe is in progress */
|
||||
#define BTM_LE_SELECT_CONN_ACTIVE 0x0040 /* selection connection is in progress */
|
||||
#define BTM_LE_OBSERVE_ACTIVE 0x0080 /* observe is in progress */
|
||||
#define BTM_LE_DISCOVER_ACTIVE 0x0100 /* scan is in progress */
|
||||
|
||||
/* BLE scan activity mask checking */
|
||||
#define BTM_BLE_IS_SCAN_ACTIVE(x) ((x) & BTM_BLE_SCAN_ACTIVE_MASK)
|
||||
#define BTM_BLE_IS_INQ_ACTIVE(x) ((x) & BTM_BLE_INQUIRY_MASK)
|
||||
#define BTM_BLE_IS_OBS_ACTIVE(x) ((x) & BTM_LE_OBSERVE_ACTIVE)
|
||||
#define BTM_BLE_IS_DISCO_ACTIVE(x) ((x) & BTM_LE_DISCOVER_ACTIVE)
|
||||
#define BTM_BLE_IS_SEL_CONN_ACTIVE(x) ((x) & BTM_LE_SELECT_CONN_ACTIVE)
|
||||
|
||||
/* BLE ADDR type ID bit */
|
||||
@ -136,6 +138,7 @@ typedef struct {
|
||||
typedef struct {
|
||||
UINT16 discoverable_mode;
|
||||
UINT16 connectable_mode;
|
||||
BOOLEAN scan_params_set;
|
||||
UINT32 scan_window;
|
||||
UINT32 scan_interval;
|
||||
UINT8 scan_type; /* current scan type: active or passive */
|
||||
@ -294,7 +297,7 @@ typedef void (tBTM_DATA_LENGTH_CHANGE_CBACK) (UINT16 max_tx_length, UINT16 max_r
|
||||
/* Define BLE Device Management control structure
|
||||
*/
|
||||
typedef struct {
|
||||
UINT8 scan_activity; /* LE scan activity mask */
|
||||
UINT16 scan_activity; /* LE scan activity mask */
|
||||
|
||||
/*****************************************************
|
||||
** BLE Inquiry
|
||||
@ -306,6 +309,11 @@ typedef struct {
|
||||
tBTM_CMPL_CB *p_obs_cmpl_cb;
|
||||
TIMER_LIST_ENT obs_timer_ent;
|
||||
|
||||
/* scan callback and timer */
|
||||
tBTM_INQ_RESULTS_CB *p_scan_results_cb;
|
||||
tBTM_CMPL_CB *p_scan_cmpl_cb;
|
||||
TIMER_LIST_ENT scan_timer_ent;
|
||||
|
||||
/* background connection procedure cb value */
|
||||
tBTM_BLE_CONN_TYPE bg_conn_type;
|
||||
UINT32 scan_int;
|
||||
@ -314,6 +322,7 @@ typedef struct {
|
||||
|
||||
/* white list information */
|
||||
UINT8 white_list_avail_size;
|
||||
tBTM_ADD_WHITELIST_CBACK *add_wl_cb;
|
||||
tBTM_BLE_WL_STATE wl_state;
|
||||
|
||||
fixed_queue_t *conn_pending_q;
|
||||
@ -357,7 +366,6 @@ tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration);
|
||||
void btm_ble_stop_scan(void);
|
||||
void btm_clear_all_pending_le_entry(void);
|
||||
|
||||
void btm_ble_stop_scan();
|
||||
BOOLEAN btm_ble_send_extended_scan_params(UINT8 scan_type, UINT32 scan_int,
|
||||
UINT32 scan_win, UINT8 addr_type_own,
|
||||
UINT8 scan_filter_policy);
|
||||
@ -405,7 +413,7 @@ void btm_ble_update_sec_key_size(BD_ADDR bd_addr, UINT8 enc_key_size);
|
||||
UINT8 btm_ble_read_sec_key_size(BD_ADDR bd_addr);
|
||||
|
||||
/* white list function */
|
||||
BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr);
|
||||
BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr, tBTM_ADD_WHITELIST_CBACK *add_wl_cb);
|
||||
void btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy);
|
||||
void btm_update_adv_filter_policy(tBTM_BLE_AFP adv_policy);
|
||||
void btm_ble_clear_white_list (void);
|
||||
|
@ -160,9 +160,8 @@ typedef void (*tBTU_EVENT_CALLBACK)(BT_HDR *p_hdr);
|
||||
#define BTU_TTYPE_BLE_GAP_FAST_ADV 106
|
||||
#define BTU_TTYPE_BLE_OBSERVE 107
|
||||
|
||||
|
||||
#define BTU_TTYPE_UCD_TO 108
|
||||
|
||||
#define BTU_TTYPE_BLE_SCAN 109
|
||||
|
||||
|
||||
/* This is the inquiry response information held by BTU, and available
|
||||
|
@ -1469,7 +1469,8 @@ typedef struct {
|
||||
|
||||
#define HCI_FEATURE_SWITCH_MASK 0x20
|
||||
#define HCI_FEATURE_SWITCH_OFF 0
|
||||
#define HCI_SWITCH_SUPPORTED(x) ((x)[HCI_FEATURE_SWITCH_OFF] & HCI_FEATURE_SWITCH_MASK)
|
||||
// temporarily disable ROLE_SWITCH since there is an issue to be fixed
|
||||
#define HCI_SWITCH_SUPPORTED(x) (0 & ((x)[HCI_FEATURE_SWITCH_OFF] & HCI_FEATURE_SWITCH_MASK))
|
||||
|
||||
#define HCI_FEATURE_HOLD_MODE_MASK 0x40
|
||||
#define HCI_FEATURE_HOLD_MODE_OFF 0
|
||||
|
@ -505,8 +505,8 @@ static BOOLEAN l2cble_start_conn_update (tL2C_LCB *p_lcb)
|
||||
up to what has been requested during connection establishement */
|
||||
if (p_lcb->conn_update_mask & L2C_BLE_NOT_DEFAULT_PARAM &&
|
||||
/* current connection interval is greater than default min */
|
||||
p_lcb->waiting_update_conn_min_interval > BTM_BLE_CONN_INT_MIN) {
|
||||
/* use 7.5 ms as fast connection parameter, 0 slave latency */
|
||||
p_lcb->current_used_conn_interval > BTM_BLE_CONN_INT_MAX_DEF) {
|
||||
/* use 6 * 1.25 = 7.5 ms as fast connection parameter, 0 slave latency */
|
||||
min_conn_int = max_conn_int = BTM_BLE_CONN_INT_MIN;
|
||||
slave_latency = BTM_BLE_CONN_SLAVE_LATENCY_DEF;
|
||||
supervision_tout = BTM_BLE_CONN_TIMEOUT_DEF;
|
||||
|
@ -1506,9 +1506,11 @@ tL2C_CCB *l2cu_allocate_ccb (tL2C_LCB *p_lcb, UINT16 cid)
|
||||
p_ccb->tx_mps = L2CAP_FCR_TX_BUF_SIZE - 32;
|
||||
|
||||
p_ccb->xmit_hold_q = fixed_queue_new(SIZE_MAX);
|
||||
#if (CLASSIC_BT_INCLUDED == TRUE)
|
||||
p_ccb->fcrb.srej_rcv_hold_q = fixed_queue_new(SIZE_MAX);
|
||||
p_ccb->fcrb.retrans_q = fixed_queue_new(SIZE_MAX);
|
||||
p_ccb->fcrb.waiting_for_ack_q = fixed_queue_new(SIZE_MAX);
|
||||
#endif ///CLASSIC_BT_INCLUDED == TRUE
|
||||
|
||||
p_ccb->cong_sent = FALSE;
|
||||
p_ccb->buff_quota = 2; /* This gets set after config */
|
||||
@ -1632,6 +1634,15 @@ void l2cu_release_ccb (tL2C_CCB *p_ccb)
|
||||
|
||||
fixed_queue_free(p_ccb->xmit_hold_q, osi_free_func);
|
||||
p_ccb->xmit_hold_q = NULL;
|
||||
#if (CLASSIC_BT_INCLUDED == TRUE)
|
||||
fixed_queue_free(p_ccb->fcrb.srej_rcv_hold_q, osi_free_func);
|
||||
fixed_queue_free(p_ccb->fcrb.retrans_q, osi_free_func);
|
||||
fixed_queue_free(p_ccb->fcrb.waiting_for_ack_q, osi_free_func);
|
||||
p_ccb->fcrb.srej_rcv_hold_q = NULL;
|
||||
p_ccb->fcrb.retrans_q = NULL;
|
||||
p_ccb->fcrb.waiting_for_ack_q = NULL;
|
||||
#endif ///CLASSIC_BT_INCLUDED == TRUE
|
||||
|
||||
|
||||
#if (CLASSIC_BT_INCLUDED == TRUE)
|
||||
l2c_fcr_cleanup (p_ccb);
|
||||
|
@ -1221,25 +1221,16 @@ void smp_decide_association_model(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
|
||||
|
||||
switch (p_cb->selected_association_model) {
|
||||
case SMP_MODEL_ENCRYPTION_ONLY: /* TK = 0, go calculate Confirm */
|
||||
if (p_cb->role == HCI_ROLE_MASTER &&
|
||||
((p_cb->peer_auth_req & SMP_AUTH_YN_BIT) != 0) &&
|
||||
((p_cb->loc_auth_req & SMP_AUTH_YN_BIT) == 0)) {
|
||||
SMP_TRACE_ERROR ("IO capability does not meet authentication requirement\n");
|
||||
failure = SMP_PAIR_AUTH_FAIL;
|
||||
p = (tSMP_INT_DATA *)&failure;
|
||||
int_evt = SMP_AUTH_CMPL_EVT;
|
||||
} else {
|
||||
p_cb->sec_level = SMP_SEC_UNAUTHENTICATE;
|
||||
SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_UNAUTHENTICATE) \n", p_cb->sec_level );
|
||||
p_cb->sec_level = SMP_SEC_UNAUTHENTICATE;
|
||||
SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_UNAUTHENTICATE) \n", p_cb->sec_level );
|
||||
|
||||
key.key_type = SMP_KEY_TYPE_TK;
|
||||
key.p_data = p_cb->tk;
|
||||
p = (tSMP_INT_DATA *)&key;
|
||||
key.key_type = SMP_KEY_TYPE_TK;
|
||||
key.p_data = p_cb->tk;
|
||||
p = (tSMP_INT_DATA *)&key;
|
||||
|
||||
memset(p_cb->tk, 0, BT_OCTET16_LEN);
|
||||
/* TK, ready */
|
||||
int_evt = SMP_KEY_READY_EVT;
|
||||
}
|
||||
memset(p_cb->tk, 0, BT_OCTET16_LEN);
|
||||
/* TK, ready */
|
||||
int_evt = SMP_KEY_READY_EVT;
|
||||
break;
|
||||
|
||||
case SMP_MODEL_PASSKEY:
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "freertos/portmacro.h"
|
||||
#include "xtensa/core-macros.h"
|
||||
#include "esp_types.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_task.h"
|
||||
@ -33,6 +34,9 @@
|
||||
#include "bt.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_pm.h"
|
||||
#include "esp_ipc.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
|
||||
#if CONFIG_BT_ENABLED
|
||||
|
||||
@ -134,6 +138,7 @@ struct osi_funcs_t {
|
||||
int32_t (* _task_create)(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id);
|
||||
void (* _task_delete)(void *task_handle);
|
||||
bool (* _is_in_isr)(void);
|
||||
int (* _cause_sw_intr_to_core)(int core_id, int intr_no);
|
||||
void *(* _malloc)(uint32_t size);
|
||||
void (* _free)(void *p);
|
||||
int32_t (* _read_efuse_mac)(uint8_t mac[6]);
|
||||
@ -147,6 +152,10 @@ static esp_bt_controller_status_t btdm_controller_status = ESP_BT_CONTROLLER_STA
|
||||
|
||||
static portMUX_TYPE global_int_mux = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
static esp_pm_lock_handle_t s_pm_lock;
|
||||
#endif
|
||||
|
||||
static void IRAM_ATTR interrupt_disable(void)
|
||||
{
|
||||
portENTER_CRITICAL(&global_int_mux);
|
||||
@ -269,6 +278,26 @@ static bool IRAM_ATTR is_in_isr_wrapper(void)
|
||||
return (bool)xPortInIsrContext();
|
||||
}
|
||||
|
||||
static void IRAM_ATTR cause_sw_intr(void *arg)
|
||||
{
|
||||
/* just convert void * to int, because the width is the same */
|
||||
uint32_t intr_no = (uint32_t)arg;
|
||||
XTHAL_SET_INTSET((1<<intr_no));
|
||||
}
|
||||
|
||||
static int IRAM_ATTR cause_sw_intr_to_core_wrapper(int core_id, int intr_no)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
if (xPortGetCoreID() == core_id) {
|
||||
cause_sw_intr((void *)intr_no);
|
||||
} else {
|
||||
err = esp_ipc_call(core_id, cause_sw_intr, (void *)intr_no);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int32_t IRAM_ATTR read_mac_wrapper(uint8_t mac[6])
|
||||
{
|
||||
return esp_read_mac(mac, ESP_MAC_BT);
|
||||
@ -310,6 +339,7 @@ static struct osi_funcs_t osi_funcs = {
|
||||
._task_create = task_create_wrapper,
|
||||
._task_delete = task_delete_wrapper,
|
||||
._is_in_isr = is_in_isr_wrapper,
|
||||
._cause_sw_intr_to_core = cause_sw_intr_to_core_wrapper,
|
||||
._malloc = malloc,
|
||||
._free = free,
|
||||
._read_efuse_mac = read_mac_wrapper,
|
||||
@ -340,10 +370,10 @@ static uint32_t btdm_config_mask_load(void)
|
||||
mask |= BTDM_CFG_BT_DATA_RELEASE;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BT_HCI_UART
|
||||
#if CONFIG_BTDM_CONTROLLER_HCI_MODE_UART_H4
|
||||
mask |= BTDM_CFG_HCI_UART;
|
||||
#endif
|
||||
#ifdef CONFIG_BTDM_CONTROLLER_RUN_APP_CPU
|
||||
#if CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE == 1
|
||||
mask |= BTDM_CFG_CONTROLLER_RUN_APP_CPU;
|
||||
#endif
|
||||
return mask;
|
||||
@ -442,14 +472,27 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_err_t err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "bt", &s_pm_lock);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
btdm_osi_funcs_register(&osi_funcs);
|
||||
|
||||
btdm_controller_mem_init();
|
||||
|
||||
periph_module_enable(PERIPH_BT_MODULE);
|
||||
|
||||
btdm_cfg_mask = btdm_config_mask_load();
|
||||
|
||||
ret = btdm_controller_init(btdm_cfg_mask, cfg);
|
||||
if (ret) {
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_lock_delete(s_pm_lock);
|
||||
s_pm_lock = NULL;
|
||||
#endif
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
@ -467,7 +510,15 @@ esp_err_t esp_bt_controller_deinit(void)
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
btdm_controller_status = ESP_BT_CONTROLLER_STATUS_SHUTDOWN;
|
||||
periph_module_disable(PERIPH_BT_MODULE);
|
||||
|
||||
btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE;
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_lock_delete(s_pm_lock);
|
||||
s_pm_lock = NULL;
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -484,6 +535,10 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode)
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_lock_acquire(s_pm_lock);
|
||||
#endif
|
||||
|
||||
esp_phy_load_cal_and_init();
|
||||
|
||||
if (btdm_bb_init_flag == false) {
|
||||
@ -519,6 +574,10 @@ esp_err_t esp_bt_controller_disable(void)
|
||||
btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_lock_release(s_pm_lock);
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,6 @@ typedef enum {
|
||||
ESP_BT_CONTROLLER_STATUS_IDLE = 0,
|
||||
ESP_BT_CONTROLLER_STATUS_INITED,
|
||||
ESP_BT_CONTROLLER_STATUS_ENABLED,
|
||||
ESP_BT_CONTROLLER_STATUS_SHUTDOWN,
|
||||
ESP_BT_CONTROLLER_STATUS_NUM,
|
||||
} esp_bt_controller_status_t;
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 2d33374ca531f92859640f1d055fc4f28d60dfdc
|
||||
Subproject commit 8e62573de3dd9565b2209a3e8fe19a9900320b77
|
@ -1 +1 @@
|
||||
CFLAGS += -DWITH_POSIX
|
||||
CPPFLAGS += -DWITH_POSIX
|
||||
|
@ -185,7 +185,9 @@ esp_err_t esp_console_run(const char* cmdline, int* cmd_ret)
|
||||
|
||||
size_t argc = esp_console_split_argv(s_tmp_line_buf, argv,
|
||||
s_config.max_cmdline_args);
|
||||
|
||||
if (argc == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
const cmd_item_t* cmd = find_command_by_name(argv[0]);
|
||||
if (cmd == NULL) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
|
@ -107,6 +107,8 @@ esp_err_t esp_console_cmd_register(const esp_console_cmd_t *cmd);
|
||||
* @param[out] cmd_ret return code from the command (set if command was run)
|
||||
* @return
|
||||
* - ESP_OK, if command was run
|
||||
* - ESP_ERR_INVALID_ARG, if the command line is empty, or only contained
|
||||
* whitespace
|
||||
* - ESP_ERR_NOT_FOUND, if command with given name wasn't registered
|
||||
* - ESP_ERR_INVALID_STATE, if esp_console_init wasn't called
|
||||
*/
|
||||
|
@ -1,3 +1,11 @@
|
||||
# Mark __cxa_guard_dummy as undefined so that implementation of static guards
|
||||
# is taken from cxx_guards.o instead of libstdc++.a
|
||||
COMPONENT_ADD_LDFLAGS += -u __cxa_guard_dummy
|
||||
|
||||
ifndef CONFIG_CXX_EXCEPTIONS
|
||||
# If exceptions are disabled, ensure our fatal exception
|
||||
# hooks are preferentially linked over libstdc++ which
|
||||
# has full exception support
|
||||
COMPONENT_ADD_LDFLAGS += -u __cxx_fatal_exception
|
||||
endif
|
||||
|
||||
|
87
components/cxx/cxx_exception_stubs.cpp
Normal file
87
components/cxx/cxx_exception_stubs.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <exception>
|
||||
#include <bits/functexcept.h>
|
||||
#include <sdkconfig.h>
|
||||
|
||||
#ifndef CONFIG_CXX_EXCEPTIONS
|
||||
|
||||
const char *FATAL_EXCEPTION = "Fatal C++ exception: ";
|
||||
|
||||
extern "C" void __cxx_fatal_exception(void)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
extern "C" void __cxx_fatal_exception_message(const char *msg)
|
||||
{
|
||||
printf("%s%s\n", FATAL_EXCEPTION, msg);
|
||||
abort();
|
||||
}
|
||||
|
||||
extern "C" void __cxx_fatal_exception_int(int i)
|
||||
{
|
||||
printf("%s (%d)\n", FATAL_EXCEPTION, i);
|
||||
abort();
|
||||
}
|
||||
|
||||
void std::__throw_bad_exception(void) __attribute__((alias("__cxx_fatal_exception")));
|
||||
|
||||
void std::__throw_bad_alloc(void) __attribute__((alias("__cxx_fatal_exception")));
|
||||
|
||||
void std::__throw_bad_cast(void) __attribute__((alias("__cxx_fatal_exception")));
|
||||
|
||||
void std::__throw_bad_typeid(void) __attribute__((alias("__cxx_fatal_exception")));
|
||||
|
||||
void std::__throw_logic_error(const char*) __attribute__((alias("__cxx_fatal_exception_message")));
|
||||
|
||||
void std::__throw_domain_error(const char*) __attribute__((alias("__cxx_fatal_exception_message")));
|
||||
|
||||
void std::__throw_invalid_argument(const char*) __attribute__((alias("__cxx_fatal_exception_message")));
|
||||
|
||||
void std::__throw_length_error(const char*) __attribute__((alias("__cxx_fatal_exception_message")));
|
||||
|
||||
void std::__throw_out_of_range(const char*) __attribute__((alias("__cxx_fatal_exception_message")));
|
||||
|
||||
void std::__throw_out_of_range_fmt(const char*, ...) __attribute__((alias("__cxx_fatal_exception_message")));
|
||||
|
||||
void std::__throw_runtime_error(const char*) __attribute__((alias("__cxx_fatal_exception_message")));
|
||||
|
||||
void std::__throw_range_error(const char*) __attribute__((alias("__cxx_fatal_exception_message")));
|
||||
|
||||
void std::__throw_overflow_error(const char*) __attribute__((alias("__cxx_fatal_exception_message")));
|
||||
|
||||
void std::__throw_underflow_error(const char*) __attribute__((alias("__cxx_fatal_exception_message")));
|
||||
|
||||
void std::__throw_ios_failure(const char*) __attribute__((alias("__cxx_fatal_exception_message")));
|
||||
|
||||
void std::__throw_system_error(int) __attribute__((alias("__cxx_fatal_exception_int")));
|
||||
|
||||
void std::__throw_bad_function_call(void) __attribute__((alias("__cxx_fatal_exception")));
|
||||
|
||||
void std::__throw_future_error(int) __attribute__((alias("__cxx_fatal_exception_int")));
|
||||
|
||||
|
||||
/* The following definitions are needed because libstdc++ is also compiled with
|
||||
__throw_exception_again defined to throw, and some other exception code in a few places.
|
||||
|
||||
This cause exception handler code to be emitted in the library even though it's mostly
|
||||
unreachable (as any libstdc++ "throw" will first call one of the above stubs, which will abort).
|
||||
|
||||
If these are left out, a bunch of unwanted exception handler code is linked.
|
||||
|
||||
Note: these function prototypes are not correct.
|
||||
*/
|
||||
|
||||
extern "C" void __cxa_allocate_exception(void) __attribute__((alias("__cxx_fatal_exception")));
|
||||
extern "C" void __cxa_begin_catch(void) __attribute__((alias("__cxx_fatal_exception")));
|
||||
extern "C" void __cxa_end_catch(void) __attribute__((alias("__cxx_fatal_exception")));
|
||||
extern "C" void __cxa_get_exception_ptr(void) __attribute__((alias("__cxx_fatal_exception")));
|
||||
extern "C" void __cxa_free_exception(void) __attribute__((alias("__cxx_fatal_exception")));
|
||||
extern "C" void __cxa_rethrow(void) __attribute__((alias("__cxx_fatal_exception")));
|
||||
extern "C" void __cxa_throw(void) __attribute__((alias("__cxx_fatal_exception")));
|
||||
extern "C" void __cxa_call_terminate(void) __attribute__((alias("__cxx_fatal_exception")));
|
||||
|
||||
bool std::uncaught_exception() __attribute__((alias("__cxx_fatal_exception")));
|
||||
|
||||
#endif // CONFIG_CXX_EXCEPTIONS
|
@ -92,7 +92,6 @@ public:
|
||||
static SlowInit slowinit(taskId);
|
||||
ESP_LOGD(TAG, "obj=%d after static init, task=%d\n", obj, taskId);
|
||||
xSemaphoreGive(s_slow_init_sem);
|
||||
vTaskDelay(10);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
private:
|
||||
@ -133,6 +132,8 @@ TEST_CASE("static initialization guards work as expected", "[cxx]")
|
||||
TEST_ASSERT_TRUE(xSemaphoreTake(s_slow_init_sem, 500/portTICK_PERIOD_MS));
|
||||
}
|
||||
vSemaphoreDelete(s_slow_init_sem);
|
||||
|
||||
vTaskDelay(10); // Allow tasks to clean up, avoids race with leak detector
|
||||
}
|
||||
|
||||
struct GlobalInitTest
|
||||
@ -187,6 +188,27 @@ TEST_CASE("before scheduler has started, static initializers work correctly", "[
|
||||
TEST_ASSERT_EQUAL(2, StaticInitTestBeforeScheduler::order);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CXX_EXCEPTIONS
|
||||
|
||||
TEST_CASE("c++ exceptions work", "[cxx]")
|
||||
{
|
||||
/* Note: This test currently trips the memory leak threshold
|
||||
as libunwind allocates ~4KB of data on first exception. */
|
||||
int thrown_value;
|
||||
try
|
||||
{
|
||||
throw 20;
|
||||
}
|
||||
catch (int e)
|
||||
{
|
||||
thrown_value = e;
|
||||
}
|
||||
TEST_ASSERT_EQUAL(20, thrown_value);
|
||||
printf("OK?\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* These test cases pull a lot of code from libstdc++ and are disabled for now
|
||||
*/
|
||||
#if 0
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/ringbuf.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/i2c_struct.h"
|
||||
#include "soc/i2c_reg.h"
|
||||
@ -43,12 +44,13 @@ static DRAM_ATTR i2c_dev_t* const I2C[I2C_NUM_MAX] = { &I2C0, &I2C1 };
|
||||
|
||||
#define I2C_ENTER_CRITICAL_ISR(mux) portENTER_CRITICAL_ISR(mux)
|
||||
#define I2C_EXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL_ISR(mux)
|
||||
#define I2C_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux)
|
||||
#define I2C_EXIT_CRITICAL(mux) portEXIT_CRITICAL(mux)
|
||||
#define I2C_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux)
|
||||
#define I2C_EXIT_CRITICAL(mux) portEXIT_CRITICAL(mux)
|
||||
|
||||
#define I2C_DRIVER_ERR_STR "i2c driver install error"
|
||||
#define I2C_DRIVER_MALLOC_ERR_STR "i2c driver malloc error"
|
||||
#define I2C_NUM_ERROR_STR "i2c number error"
|
||||
#define I2C_TIMEING_VAL_ERR_STR "i2c timing value error"
|
||||
#define I2C_ADDR_ERROR_STR "i2c null address error"
|
||||
#define I2C_DRIVER_NOT_INSTALL_ERR_STR "i2c driver not installed"
|
||||
#define I2C_SLAVE_BUFFER_LEN_ERR_STR "i2c buffer size too short for slave mode"
|
||||
@ -60,13 +62,20 @@ static DRAM_ATTR i2c_dev_t* const I2C[I2C_NUM_MAX] = { &I2C0, &I2C1 };
|
||||
#define I2C_CMD_MALLOC_ERR_STR "i2c command link malloc error"
|
||||
#define I2C_TRANS_MODE_ERR_STR "i2c trans mode error"
|
||||
#define I2C_MODE_ERR_STR "i2c mode error"
|
||||
#define I2C_SDA_IO_ERR_STR "sda gpio number error"
|
||||
#define I2C_SCL_IO_ERR_STR "scl gpio number error"
|
||||
#define I2C_CMD_LINK_INIT_ERR_STR "i2c command link error"
|
||||
#define I2C_GPIO_PULLUP_ERR_STR "this i2c pin do not support internal pull-up"
|
||||
#define I2C_FIFO_FULL_THRESH_VAL (28)
|
||||
#define I2C_FIFO_EMPTY_THRESH_VAL (5)
|
||||
#define I2C_IO_INIT_LEVEL (1)
|
||||
#define I2C_SDA_IO_ERR_STR "sda gpio number error"
|
||||
#define I2C_SCL_IO_ERR_STR "scl gpio number error"
|
||||
#define I2C_CMD_LINK_INIT_ERR_STR "i2c command link error"
|
||||
#define I2C_GPIO_PULLUP_ERR_STR "this i2c pin do not support internal pull-up"
|
||||
#define I2C_FIFO_FULL_THRESH_VAL (28)
|
||||
#define I2C_FIFO_EMPTY_THRESH_VAL (5)
|
||||
#define I2C_IO_INIT_LEVEL (1)
|
||||
#define I2C_CMD_ALIVE_INTERVAL_TICK (1000 / portTICK_PERIOD_MS)
|
||||
#define I2C_CMD_EVT_ALIVE (BIT0)
|
||||
#define I2C_CMD_EVT_DONE (BIT1)
|
||||
#define I2C_SLAVE_TIMEOUT_DEFAULT (32000) /* I2C slave timeout value, APB clock cycle number */
|
||||
#define I2C_SLAVE_SDA_SAMPLE_DEFAULT (10) /* I2C slave sample time after scl positive edge default value */
|
||||
#define I2C_SLAVE_SDA_HOLD_DEFAULT (10) /* I2C slave hold time after scl negative edge default value */
|
||||
#define I2C_MASTER_TOUT_CNUM_DEFAULT (8) /* I2C master timeout cycle number of I2C clock, after which the timeout interrupt will be triggered */
|
||||
|
||||
typedef struct {
|
||||
uint8_t byte_num; /*!< cmd byte number */
|
||||
@ -95,19 +104,20 @@ typedef enum {
|
||||
I2C_STATUS_IDLE, /*!< idle status for current master command */
|
||||
I2C_STATUS_ACK_ERROR, /*!< ack error status for current master command */
|
||||
I2C_STATUS_DONE, /*!< I2C command done */
|
||||
I2C_STATUS_TIMEOUT, /*!< I2C bus status error, and operation timeout */
|
||||
} i2c_status_t;
|
||||
|
||||
typedef struct {
|
||||
int i2c_num; /*!< I2C port number */
|
||||
int mode; /*!< I2C mode, master or slave */
|
||||
intr_handle_t intr_handle; /*!< I2C interrupt handle*/
|
||||
|
||||
int cmd_idx; /*!< record current command index, for master mode */
|
||||
int status; /*!< record current command status, for master mode */
|
||||
int rx_cnt; /*!< record current read index, for master mode */
|
||||
uint8_t data_buf[I2C_FIFO_LEN]; /*!< a buffer to store i2c fifo data */
|
||||
|
||||
i2c_cmd_desc_t cmd_link; /*!< I2C command link */
|
||||
xSemaphoreHandle cmd_sem; /*!< semaphore to sync command status */
|
||||
EventGroupHandle_t cmd_evt; /*!< I2C command event bits */
|
||||
xSemaphoreHandle cmd_mux; /*!< semaphore to lock command process */
|
||||
size_t tx_fifo_remain; /*!< tx fifo remain length, for master mode */
|
||||
size_t rx_fifo_remain; /*!< rx fifo remain length, for master mode */
|
||||
@ -123,6 +133,7 @@ typedef struct {
|
||||
static i2c_obj_t *p_i2c_obj[I2C_NUM_MAX] = {0};
|
||||
static void i2c_isr_handler_default(void* arg);
|
||||
static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num);
|
||||
static esp_err_t IRAM_ATTR i2c_hw_fsm_reset(i2c_port_t i2c_num);
|
||||
|
||||
/*
|
||||
For i2c master mode, we don't need to use a buffer for the data, the APIs will execute the master commands
|
||||
@ -131,7 +142,6 @@ we should free or modify the source data only after the i2c_master_cmd_begin fun
|
||||
For i2c slave mode, we need a data buffer to stash the sending and receiving data, because the hardware fifo
|
||||
has only 32 bytes.
|
||||
*/
|
||||
|
||||
esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_buf_len, size_t slv_tx_buf_len,
|
||||
int intr_alloc_flags)
|
||||
{
|
||||
@ -185,12 +195,12 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_
|
||||
ESP_LOGE(I2C_TAG, I2C_SEM_ERR_STR);
|
||||
goto err;
|
||||
}
|
||||
intr_mask |= ( I2C_RXFIFO_FULL_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M );
|
||||
intr_mask |= ( I2C_RXFIFO_FULL_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M);
|
||||
} else {
|
||||
//semaphore to sync sending process, because we only have 32 bytes for hardware fifo.
|
||||
p_i2c->cmd_sem = xSemaphoreCreateBinary();
|
||||
p_i2c->cmd_mux = xSemaphoreCreateMutex();
|
||||
if (p_i2c->cmd_sem == NULL || p_i2c->cmd_mux == NULL) {
|
||||
p_i2c->cmd_evt = xEventGroupCreate();
|
||||
if (p_i2c->cmd_mux == NULL || p_i2c->cmd_evt == NULL) {
|
||||
ESP_LOGE(I2C_TAG, I2C_SEM_ERR_STR);
|
||||
goto err;
|
||||
}
|
||||
@ -203,6 +213,7 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_
|
||||
p_i2c->rx_buf_length = 0;
|
||||
p_i2c->tx_ring_buf = NULL;
|
||||
p_i2c->tx_buf_length = 0;
|
||||
intr_mask |= I2C_ARBITRATION_LOST_INT_ENA_M | I2C_TIME_OUT_INT_ST_M;
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(I2C_TAG, I2C_DRIVER_ERR_STR);
|
||||
@ -212,11 +223,11 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_
|
||||
i2c_isr_register(i2c_num, i2c_isr_handler_default, p_i2c_obj[i2c_num], intr_alloc_flags, &p_i2c_obj[i2c_num]->intr_handle);
|
||||
intr_mask |= ( I2C_TRANS_COMPLETE_INT_ENA_M |
|
||||
I2C_TRANS_START_INT_ENA_M |
|
||||
I2C_ARBITRATION_LOST_INT_ENA_M |
|
||||
I2C_ACK_ERR_INT_ENA_M |
|
||||
I2C_RXFIFO_OVF_INT_ENA_M |
|
||||
I2C_SLAVE_TRAN_COMP_INT_ENA_M );
|
||||
SET_PERI_REG_MASK(I2C_INT_ENA_REG(i2c_num), intr_mask);
|
||||
I2C_SLAVE_TRAN_COMP_INT_ENA_M);
|
||||
I2C[i2c_num]->int_clr.val = intr_mask;
|
||||
I2C[i2c_num]->int_ena.val = intr_mask;
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
@ -232,8 +243,9 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_
|
||||
p_i2c_obj[i2c_num]->tx_ring_buf = NULL;
|
||||
p_i2c_obj[i2c_num]->tx_buf_length = 0;
|
||||
}
|
||||
if (p_i2c_obj[i2c_num]->cmd_sem) {
|
||||
vSemaphoreDelete(p_i2c_obj[i2c_num]->cmd_sem);
|
||||
if (p_i2c_obj[i2c_num]->cmd_evt) {
|
||||
vEventGroupDelete(p_i2c_obj[i2c_num]->cmd_evt);
|
||||
p_i2c_obj[i2c_num]->cmd_evt = NULL;
|
||||
}
|
||||
if (p_i2c_obj[i2c_num]->cmd_mux) {
|
||||
vSemaphoreDelete(p_i2c_obj[i2c_num]->cmd_mux);
|
||||
@ -249,6 +261,26 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
static esp_err_t i2c_hw_enable(i2c_port_t i2c_num)
|
||||
{
|
||||
if (i2c_num == I2C_NUM_0) {
|
||||
periph_module_enable(PERIPH_I2C0_MODULE);
|
||||
} else if (i2c_num == I2C_NUM_1) {
|
||||
periph_module_enable(PERIPH_I2C1_MODULE);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t i2c_hw_disable(i2c_port_t i2c_num)
|
||||
{
|
||||
if (i2c_num == I2C_NUM_0) {
|
||||
periph_module_disable(PERIPH_I2C0_MODULE);
|
||||
} else if (i2c_num == I2C_NUM_1) {
|
||||
periph_module_disable(PERIPH_I2C1_MODULE);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2c_driver_delete(i2c_port_t i2c_num)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
@ -256,17 +288,7 @@ esp_err_t i2c_driver_delete(i2c_port_t i2c_num)
|
||||
|
||||
i2c_obj_t* p_i2c = p_i2c_obj[i2c_num];
|
||||
|
||||
uint32_t intr_mask = I2C_MASTER_TRAN_COMP_INT_ENA_M |
|
||||
I2C_TIME_OUT_INT_ENA_M |
|
||||
I2C_TRANS_COMPLETE_INT_ENA_M |
|
||||
I2C_TRANS_START_INT_ENA_M |
|
||||
I2C_TX_SEND_EMPTY_INT_ENA_M |
|
||||
I2C_ARBITRATION_LOST_INT_ENA_M |
|
||||
I2C_ACK_ERR_INT_ENA_M |
|
||||
I2C_RXFIFO_OVF_INT_ENA_M |
|
||||
I2C_RX_REC_FULL_INT_ENA_M |
|
||||
I2C_SLAVE_TRAN_COMP_INT_ENA_M;
|
||||
CLEAR_PERI_REG_MASK(I2C_INT_ENA_REG(i2c_num), intr_mask);
|
||||
I2C[i2c_num]->int_ena.val = 0;
|
||||
esp_intr_free(p_i2c->intr_handle);
|
||||
p_i2c->intr_handle = NULL;
|
||||
|
||||
@ -274,8 +296,9 @@ esp_err_t i2c_driver_delete(i2c_port_t i2c_num)
|
||||
xSemaphoreTake(p_i2c->cmd_mux, portMAX_DELAY);
|
||||
vSemaphoreDelete(p_i2c->cmd_mux);
|
||||
}
|
||||
if (p_i2c->cmd_sem) {
|
||||
vSemaphoreDelete(p_i2c->cmd_sem);
|
||||
if (p_i2c_obj[i2c_num]->cmd_evt) {
|
||||
vEventGroupDelete(p_i2c_obj[i2c_num]->cmd_evt);
|
||||
p_i2c_obj[i2c_num]->cmd_evt = NULL;
|
||||
}
|
||||
if (p_i2c->slv_rx_mux) {
|
||||
vSemaphoreDelete(p_i2c->slv_rx_mux);
|
||||
@ -297,6 +320,8 @@ esp_err_t i2c_driver_delete(i2c_port_t i2c_num)
|
||||
|
||||
free(p_i2c_obj[i2c_num]);
|
||||
p_i2c_obj[i2c_num] = NULL;
|
||||
|
||||
i2c_hw_disable(i2c_num);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -320,12 +345,13 @@ esp_err_t i2c_reset_rx_fifo(i2c_port_t i2c_num)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void i2c_isr_handler_default(void* arg)
|
||||
static void IRAM_ATTR i2c_isr_handler_default(void* arg)
|
||||
{
|
||||
i2c_obj_t* p_i2c = (i2c_obj_t*) arg;
|
||||
int i2c_num = p_i2c->i2c_num;
|
||||
uint32_t status = I2C[i2c_num]->int_status.val;
|
||||
int idx = 0;
|
||||
|
||||
portBASE_TYPE HPTaskAwoken = pdFALSE;
|
||||
while (status != 0) {
|
||||
status = I2C[i2c_num]->int_status.val;
|
||||
@ -345,6 +371,8 @@ static void i2c_isr_handler_default(void* arg)
|
||||
I2C[i2c_num]->int_clr.trans_start = 1;
|
||||
} else if (status & I2C_TIME_OUT_INT_ST_M) {
|
||||
I2C[i2c_num]->int_clr.time_out = 1;
|
||||
p_i2c_obj[i2c_num]->status = I2C_STATUS_TIMEOUT;
|
||||
i2c_master_cmd_begin_static(i2c_num);
|
||||
} else if (status & I2C_TRANS_COMPLETE_INT_ST_M) {
|
||||
I2C[i2c_num]->int_clr.trans_complete = 1;
|
||||
if (p_i2c->mode == I2C_MODE_SLAVE) {
|
||||
@ -366,6 +394,8 @@ static void i2c_isr_handler_default(void* arg)
|
||||
I2C[i2c_num]->int_clr.master_tran_comp = 1;
|
||||
} else if (status & I2C_ARBITRATION_LOST_INT_ST_M) {
|
||||
I2C[i2c_num]->int_clr.arbitration_lost = 1;
|
||||
p_i2c_obj[i2c_num]->status = I2C_STATUS_TIMEOUT;
|
||||
i2c_master_cmd_begin_static(i2c_num);
|
||||
} else if (status & I2C_SLAVE_TRAN_COMP_INT_ST_M) {
|
||||
I2C[i2c_num]->int_clr.slave_tran_comp = 1;
|
||||
} else if (status & I2C_END_DETECT_INT_ST_M) {
|
||||
@ -406,6 +436,12 @@ static void i2c_isr_handler_default(void* arg)
|
||||
I2C[i2c_num]->int_clr.val = status;
|
||||
}
|
||||
}
|
||||
if (p_i2c->mode == I2C_MODE_MASTER) {
|
||||
xEventGroupSetBitsFromISR(p_i2c->cmd_evt, I2C_CMD_EVT_ALIVE, &HPTaskAwoken);
|
||||
if (HPTaskAwoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t i2c_set_data_mode(i2c_port_t i2c_num, i2c_trans_mode_t tx_trans_mode, i2c_trans_mode_t rx_trans_mode)
|
||||
@ -432,6 +468,101 @@ esp_err_t i2c_get_data_mode(i2c_port_t i2c_num, i2c_trans_mode_t *tx_trans_mode,
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* Some slave device will die by accident and keep the SDA in low level,
|
||||
* in this case, master should send several clock to make the slave release the bus.
|
||||
* Slave mode of ESP32 might also get in wrong state that held the SDA low,
|
||||
* in this case, master device could send a stop signal to make esp32 slave release the bus.
|
||||
**/
|
||||
static esp_err_t i2c_master_clear_bus(i2c_port_t i2c_num)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
int sda_in_sig = 0, scl_in_sig = 0;
|
||||
if (i2c_num == I2C_NUM_0) {
|
||||
sda_in_sig = I2CEXT0_SDA_IN_IDX;
|
||||
scl_in_sig = I2CEXT0_SCL_IN_IDX;
|
||||
} else if (i2c_num == I2C_NUM_1) {
|
||||
sda_in_sig = I2CEXT1_SDA_IN_IDX;
|
||||
scl_in_sig = I2CEXT1_SCL_IN_IDX;
|
||||
}
|
||||
int scl_io = GPIO.func_in_sel_cfg[scl_in_sig].func_sel;
|
||||
int sda_io = GPIO.func_in_sel_cfg[sda_in_sig].func_sel;
|
||||
I2C_CHECK((GPIO_IS_VALID_OUTPUT_GPIO(scl_io)), I2C_SCL_IO_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK((GPIO_IS_VALID_GPIO(sda_io)), I2C_SDA_IO_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
if (gpio_get_level(sda_io) == 1) {
|
||||
return ESP_OK;
|
||||
}
|
||||
gpio_set_direction(scl_io, GPIO_MODE_OUTPUT_OD);
|
||||
gpio_set_direction(sda_io, GPIO_MODE_OUTPUT_OD);
|
||||
gpio_set_level(scl_io, 0);
|
||||
gpio_set_level(sda_io, 0);
|
||||
for (int i = 0; i < 9; i++) {
|
||||
gpio_set_level(scl_io, 1);
|
||||
gpio_set_level(scl_io, 0);
|
||||
}
|
||||
gpio_set_level(scl_io, 1);
|
||||
gpio_set_level(sda_io, 1);
|
||||
i2c_set_pin(i2c_num, sda_io, scl_io, 1, 1, I2C_MODE_MASTER);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**if the power and SDA/SCL wires are in proper condition, everything works find with reading the slave.
|
||||
* If we remove the power supply for the slave during I2C is reading, or directly connect SDA or SCL to ground,
|
||||
* this would cause the I2C FSM get stuck in wrong state, all we can do is to reset the I2C hardware in this case.
|
||||
**/
|
||||
static esp_err_t i2c_hw_fsm_reset(i2c_port_t i2c_num)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
uint32_t ctr = I2C[i2c_num]->ctr.val;
|
||||
uint32_t fifo_conf = I2C[i2c_num]->fifo_conf.val;
|
||||
uint32_t scl_low_period = I2C[i2c_num]->scl_low_period.val;
|
||||
uint32_t scl_high_period = I2C[i2c_num]->scl_high_period.val;
|
||||
uint32_t scl_start_hold = I2C[i2c_num]->scl_start_hold.val;
|
||||
uint32_t scl_rstart_setup = I2C[i2c_num]->scl_rstart_setup.val;
|
||||
uint32_t scl_stop_hold = I2C[i2c_num]->scl_stop_hold.val;
|
||||
uint32_t scl_stop_setup = I2C[i2c_num]->scl_stop_setup.val;
|
||||
uint32_t sda_hold = I2C[i2c_num]->sda_hold.val;
|
||||
uint32_t sda_sample = I2C[i2c_num]->sda_sample.val;
|
||||
uint32_t timeout = I2C[i2c_num]->timeout.val;
|
||||
uint32_t scl_filter_cfg = I2C[i2c_num]->scl_filter_cfg.val;
|
||||
uint32_t sda_filter_cfg = I2C[i2c_num]->sda_filter_cfg.val;
|
||||
uint32_t slave_addr = I2C[i2c_num]->slave_addr.val;
|
||||
|
||||
//to reset the I2C hw module, we need re-enable the hw
|
||||
i2c_hw_disable(i2c_num);
|
||||
i2c_master_clear_bus(i2c_num);
|
||||
i2c_hw_enable(i2c_num);
|
||||
I2C[i2c_num]->int_ena.val = 0;
|
||||
I2C[i2c_num]->ctr.val = ctr & (~I2C_TRANS_START_M);
|
||||
I2C[i2c_num]->fifo_conf.val = fifo_conf;
|
||||
I2C[i2c_num]->scl_low_period.val = scl_low_period;
|
||||
I2C[i2c_num]->scl_high_period.val = scl_high_period;
|
||||
I2C[i2c_num]->scl_start_hold.val = scl_start_hold;
|
||||
I2C[i2c_num]->scl_rstart_setup.val = scl_rstart_setup;
|
||||
I2C[i2c_num]->scl_stop_hold.val = scl_stop_hold;
|
||||
I2C[i2c_num]->scl_stop_setup.val = scl_stop_setup;
|
||||
I2C[i2c_num]->sda_hold.val = sda_hold;
|
||||
I2C[i2c_num]->sda_sample.val = sda_sample;
|
||||
I2C[i2c_num]->timeout.val = timeout;
|
||||
I2C[i2c_num]->scl_filter_cfg.val = scl_filter_cfg;
|
||||
I2C[i2c_num]->sda_filter_cfg.val = sda_filter_cfg;
|
||||
uint32_t intr_mask = ( I2C_TRANS_COMPLETE_INT_ENA_M
|
||||
| I2C_TRANS_START_INT_ENA_M
|
||||
| I2C_ACK_ERR_INT_ENA_M
|
||||
| I2C_RXFIFO_OVF_INT_ENA_M
|
||||
| I2C_SLAVE_TRAN_COMP_INT_ENA_M
|
||||
| I2C_TIME_OUT_INT_ENA_M);
|
||||
if (I2C[i2c_num]->ctr.ms_mode == I2C_MODE_SLAVE) {
|
||||
I2C[i2c_num]->slave_addr.val = slave_addr;
|
||||
intr_mask |= ( I2C_RXFIFO_FULL_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M);
|
||||
} else {
|
||||
intr_mask |= I2C_ARBITRATION_LOST_INT_ENA_M;
|
||||
}
|
||||
I2C[i2c_num]->int_clr.val = intr_mask;
|
||||
I2C[i2c_num]->int_ena.val = intr_mask;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t* i2c_conf)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
@ -443,12 +574,7 @@ esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t* i2c_conf)
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
if (i2c_num == I2C_NUM_0) {
|
||||
periph_module_enable(PERIPH_I2C0_MODULE);
|
||||
} else if (i2c_num == I2C_NUM_1) {
|
||||
periph_module_enable(PERIPH_I2C1_MODULE);
|
||||
}
|
||||
|
||||
i2c_hw_enable(i2c_num);
|
||||
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
I2C[i2c_num]->ctr.rx_lsb_first = I2C_DATA_MODE_MSB_FIRST; //set rx data msb first
|
||||
I2C[i2c_num]->ctr.tx_lsb_first = I2C_DATA_MODE_MSB_FIRST; //set tx data msb first
|
||||
@ -464,26 +590,30 @@ esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t* i2c_conf)
|
||||
I2C[i2c_num]->fifo_conf.fifo_addr_cfg_en = 0;
|
||||
I2C[i2c_num]->fifo_conf.rx_fifo_full_thrhd = I2C_FIFO_FULL_THRESH_VAL;
|
||||
I2C[i2c_num]->fifo_conf.tx_fifo_empty_thrhd = I2C_FIFO_EMPTY_THRESH_VAL;
|
||||
I2C[i2c_num]->int_ena.rx_fifo_full = 1;
|
||||
I2C[i2c_num]->ctr.trans_start = 0;
|
||||
I2C[i2c_num]->timeout.tout = I2C_SLAVE_TIMEOUT_DEFAULT;
|
||||
//set timing for data
|
||||
I2C[i2c_num]->sda_hold.time = I2C_SLAVE_SDA_HOLD_DEFAULT;
|
||||
I2C[i2c_num]->sda_sample.time = I2C_SLAVE_SDA_SAMPLE_DEFAULT;
|
||||
} else {
|
||||
I2C[i2c_num]->fifo_conf.nonfifo_en = 0;
|
||||
int cycle = (I2C_APB_CLK_FREQ / i2c_conf->master.clk_speed);
|
||||
int half_cycle = cycle / 2;
|
||||
I2C[i2c_num]->timeout.tout = cycle * I2C_MASTER_TOUT_CNUM_DEFAULT;
|
||||
//set timing for data
|
||||
I2C[i2c_num]->sda_hold.time = half_cycle / 2;
|
||||
I2C[i2c_num]->sda_sample.time = half_cycle / 2;
|
||||
|
||||
I2C[i2c_num]->scl_low_period.period = half_cycle;
|
||||
I2C[i2c_num]->scl_high_period.period = half_cycle;
|
||||
//set timing for start signal
|
||||
I2C[i2c_num]->scl_start_hold.time = half_cycle;
|
||||
I2C[i2c_num]->scl_rstart_setup.time = half_cycle;
|
||||
//set timing for stop signal
|
||||
I2C[i2c_num]->scl_stop_hold.time = half_cycle;
|
||||
I2C[i2c_num]->scl_stop_setup.time = half_cycle;
|
||||
}
|
||||
//set frequency
|
||||
int half_cycle = ( I2C_APB_CLK_FREQ / i2c_conf->master.clk_speed ) / 2;
|
||||
I2C[i2c_num]->scl_low_period.period = half_cycle - 1;
|
||||
I2C[i2c_num]->scl_high_period.period = ( I2C_APB_CLK_FREQ / i2c_conf->master.clk_speed ) - half_cycle - 1;
|
||||
//set timing for start signal
|
||||
I2C[i2c_num]->scl_start_hold.time = half_cycle;
|
||||
I2C[i2c_num]->scl_rstart_setup.time = half_cycle;
|
||||
//set timing for stop signal
|
||||
I2C[i2c_num]->scl_stop_hold.time = half_cycle;
|
||||
I2C[i2c_num]->scl_stop_setup.time = half_cycle;
|
||||
//set timing for data
|
||||
I2C[i2c_num]->sda_hold.time = half_cycle / 2;
|
||||
I2C[i2c_num]->sda_sample.time = half_cycle / 2;
|
||||
//set timeout of receving data
|
||||
I2C[i2c_num]->timeout.tout = 200000;
|
||||
|
||||
I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -491,6 +621,9 @@ esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t* i2c_conf)
|
||||
esp_err_t i2c_set_period(i2c_port_t i2c_num, int high_period, int low_period)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK((high_period <= I2C_SCL_HIGH_PERIOD_V) && (high_period > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK((low_period <= I2C_SCL_LOW_PERIOD_V) && (low_period > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
I2C[i2c_num]->scl_high_period.period = high_period;
|
||||
I2C[i2c_num]->scl_low_period.period = low_period;
|
||||
@ -515,6 +648,9 @@ esp_err_t i2c_get_period(i2c_port_t i2c_num, int* high_period, int* low_period)
|
||||
esp_err_t i2c_set_start_timing(i2c_port_t i2c_num, int setup_time, int hold_time)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK((hold_time <= I2C_SCL_START_HOLD_TIME_V) && (hold_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK((setup_time <= I2C_SCL_RSTART_SETUP_TIME_V) && (setup_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
I2C[i2c_num]->scl_start_hold.time = hold_time;
|
||||
I2C[i2c_num]->scl_rstart_setup.time = setup_time;
|
||||
return ESP_OK;
|
||||
@ -537,6 +673,9 @@ esp_err_t i2c_get_start_timing(i2c_port_t i2c_num, int* setup_time, int* hold_ti
|
||||
esp_err_t i2c_set_stop_timing(i2c_port_t i2c_num, int setup_time, int hold_time)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK((setup_time <= I2C_SCL_STOP_SETUP_TIME_V) && (setup_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK((hold_time <= I2C_SCL_STOP_HOLD_TIME_V) && (hold_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
I2C[i2c_num]->scl_stop_hold.time = hold_time;
|
||||
I2C[i2c_num]->scl_stop_setup.time = setup_time;
|
||||
return ESP_OK;
|
||||
@ -559,6 +698,9 @@ esp_err_t i2c_get_stop_timing(i2c_port_t i2c_num, int* setup_time, int* hold_tim
|
||||
esp_err_t i2c_set_data_timing(i2c_port_t i2c_num, int sample_time, int hold_time)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK((sample_time <= I2C_SDA_SAMPLE_TIME_V) && (sample_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK((hold_time <= I2C_SDA_HOLD_TIME_V) && (hold_time > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
I2C[i2c_num]->sda_hold.time = hold_time;
|
||||
I2C[i2c_num]->sda_sample.time = sample_time;
|
||||
return ESP_OK;
|
||||
@ -578,6 +720,26 @@ esp_err_t i2c_get_data_timing(i2c_port_t i2c_num, int* sample_time, int* hold_ti
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2c_set_timeout(i2c_port_t i2c_num, int timeout)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK((timeout <= I2C_SDA_SAMPLE_TIME_V) && (timeout > 0), I2C_TIMEING_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
I2C[i2c_num]->timeout.tout = timeout;
|
||||
I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2c_get_timeout(i2c_port_t i2c_num, int* timeout)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
if (timeout) {
|
||||
*timeout = I2C[i2c_num]->timeout.tout;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2c_isr_register(i2c_port_t i2c_num, void (*fn)(void*), void * arg, int intr_alloc_flags, intr_handle_t *handle)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
@ -600,17 +762,20 @@ esp_err_t i2c_isr_free(intr_handle_t handle)
|
||||
return esp_intr_free(handle);
|
||||
}
|
||||
|
||||
esp_err_t i2c_set_pin(i2c_port_t i2c_num, gpio_num_t sda_io_num, gpio_num_t scl_io_num, gpio_pullup_t sda_pullup_en, gpio_pullup_t scl_pullup_en, i2c_mode_t mode)
|
||||
esp_err_t i2c_set_pin(i2c_port_t i2c_num, int sda_io_num, int scl_io_num, gpio_pullup_t sda_pullup_en, gpio_pullup_t scl_pullup_en, i2c_mode_t mode)
|
||||
{
|
||||
I2C_CHECK(( i2c_num < I2C_NUM_MAX ), I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK(((GPIO_IS_VALID_OUTPUT_GPIO(sda_io_num))), I2C_SDA_IO_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK((GPIO_IS_VALID_OUTPUT_GPIO(scl_io_num)) ||
|
||||
I2C_CHECK(((sda_io_num < 0) || ((GPIO_IS_VALID_OUTPUT_GPIO(sda_io_num)))), I2C_SDA_IO_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK(scl_io_num < 0 ||
|
||||
(GPIO_IS_VALID_OUTPUT_GPIO(scl_io_num)) ||
|
||||
(GPIO_IS_VALID_GPIO(scl_io_num) && mode == I2C_MODE_SLAVE),
|
||||
I2C_SCL_IO_ERR_STR,
|
||||
ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK((sda_pullup_en == GPIO_PULLUP_ENABLE && GPIO_IS_VALID_OUTPUT_GPIO(sda_io_num)) ||
|
||||
I2C_CHECK(sda_io_num < 0 ||
|
||||
(sda_pullup_en == GPIO_PULLUP_ENABLE && GPIO_IS_VALID_OUTPUT_GPIO(sda_io_num)) ||
|
||||
sda_pullup_en == GPIO_PULLUP_DISABLE, I2C_GPIO_PULLUP_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK((scl_pullup_en == GPIO_PULLUP_ENABLE && GPIO_IS_VALID_OUTPUT_GPIO(scl_io_num)) ||
|
||||
I2C_CHECK(scl_io_num < 0 ||
|
||||
(scl_pullup_en == GPIO_PULLUP_ENABLE && GPIO_IS_VALID_OUTPUT_GPIO(scl_io_num)) ||
|
||||
scl_pullup_en == GPIO_PULLUP_DISABLE, I2C_GPIO_PULLUP_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
int sda_in_sig, sda_out_sig, scl_in_sig, scl_out_sig;
|
||||
@ -633,6 +798,7 @@ esp_err_t i2c_set_pin(i2c_port_t i2c_num, gpio_num_t sda_io_num, gpio_num_t scl_
|
||||
gpio_set_level(sda_io_num, I2C_IO_INIT_LEVEL);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[sda_io_num], PIN_FUNC_GPIO);
|
||||
gpio_set_direction(sda_io_num, GPIO_MODE_INPUT_OUTPUT_OD);
|
||||
|
||||
if (sda_pullup_en == GPIO_PULLUP_ENABLE) {
|
||||
gpio_set_pull_mode(sda_io_num, GPIO_PULLUP_ONLY);
|
||||
} else {
|
||||
@ -824,17 +990,22 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num)
|
||||
{
|
||||
i2c_obj_t* p_i2c = p_i2c_obj[i2c_num];
|
||||
portBASE_TYPE HPTaskAwoken = pdFALSE;
|
||||
|
||||
//This should never happen
|
||||
if (p_i2c->mode == I2C_MODE_SLAVE) {
|
||||
return;
|
||||
}
|
||||
if (p_i2c->status == I2C_STATUS_DONE) {
|
||||
return;
|
||||
} else if (p_i2c->status == I2C_STATUS_ACK_ERROR) {
|
||||
} else if ((p_i2c->status == I2C_STATUS_ACK_ERROR)
|
||||
|| (p_i2c->status == I2C_STATUS_TIMEOUT)) {
|
||||
I2C[i2c_num]->int_ena.end_detect = 0;
|
||||
I2C[i2c_num]->int_clr.end_detect = 1;
|
||||
I2C[i2c_num]->int_ena.master_tran_comp = 0;
|
||||
xSemaphoreGiveFromISR(p_i2c->cmd_sem, &HPTaskAwoken);
|
||||
if(p_i2c->status == I2C_STATUS_TIMEOUT) {
|
||||
I2C[i2c_num]->int_clr.time_out = 1;
|
||||
I2C[i2c_num]->int_ena.val = 0;
|
||||
}
|
||||
xEventGroupSetBitsFromISR(p_i2c->cmd_evt, I2C_CMD_EVT_DONE, &HPTaskAwoken);
|
||||
if (HPTaskAwoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
@ -853,7 +1024,7 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num)
|
||||
}
|
||||
if (p_i2c->cmd_link.head == NULL) {
|
||||
p_i2c->cmd_link.cur = NULL;
|
||||
xSemaphoreGiveFromISR(p_i2c->cmd_sem, &HPTaskAwoken);
|
||||
xEventGroupSetBitsFromISR(p_i2c->cmd_evt, I2C_CMD_EVT_DONE, &HPTaskAwoken);
|
||||
if (HPTaskAwoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
@ -917,29 +1088,31 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num)
|
||||
}
|
||||
}
|
||||
I2C[i2c_num]->int_clr.end_detect = 1;
|
||||
I2C[i2c_num]->int_clr.master_tran_comp = 1;
|
||||
I2C[i2c_num]->int_ena.end_detect = 1;
|
||||
I2C[i2c_num]->int_ena.master_tran_comp = 1;
|
||||
I2C[i2c_num]->ctr.trans_start = 0;
|
||||
I2C[i2c_num]->ctr.trans_start = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, portBASE_TYPE ticks_to_wait)
|
||||
esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, TickType_t ticks_to_wait)
|
||||
{
|
||||
I2C_CHECK(( i2c_num < I2C_NUM_MAX ), I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
I2C_CHECK(p_i2c_obj[i2c_num] != NULL, I2C_DRIVER_NOT_INSTALL_ERR_STR, ESP_ERR_INVALID_STATE);
|
||||
I2C_CHECK(p_i2c_obj[i2c_num]->mode == I2C_MODE_MASTER, I2C_MASTER_MODE_ERR_STR, ESP_ERR_INVALID_STATE);
|
||||
I2C_CHECK(cmd_handle != NULL, I2C_CMD_LINK_INIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
esp_err_t ret;
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
i2c_obj_t* p_i2c = p_i2c_obj[i2c_num];
|
||||
portTickType ticks_end = xTaskGetTickCount() + ticks_to_wait;
|
||||
portBASE_TYPE res = xSemaphoreTake(p_i2c->cmd_mux, ticks_to_wait);
|
||||
if (res == pdFALSE) {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
xSemaphoreTake(p_i2c->cmd_sem, 0);
|
||||
xEventGroupClearBits(p_i2c->cmd_evt, I2C_CMD_EVT_DONE | I2C_CMD_EVT_ALIVE);
|
||||
if (p_i2c->status == I2C_STATUS_TIMEOUT
|
||||
|| I2C[i2c_num]->status_reg.bus_busy == 1) {
|
||||
i2c_hw_fsm_reset(i2c_num);
|
||||
}
|
||||
i2c_reset_tx_fifo(i2c_num);
|
||||
i2c_reset_rx_fifo(i2c_num);
|
||||
i2c_cmd_desc_t* cmd = (i2c_cmd_desc_t*) cmd_handle;
|
||||
@ -956,21 +1129,59 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle,
|
||||
|
||||
//start send commands, at most 32 bytes one time, isr handler will process the remaining commands.
|
||||
i2c_master_cmd_begin_static(i2c_num);
|
||||
ticks_to_wait = ticks_end - xTaskGetTickCount();
|
||||
res = xSemaphoreTake(p_i2c->cmd_sem, ticks_to_wait);
|
||||
if (res == pdFALSE) {
|
||||
ret = ESP_ERR_TIMEOUT;
|
||||
} else if (p_i2c->status == I2C_STATUS_ACK_ERROR) {
|
||||
ret = ESP_FAIL;
|
||||
if (ticks_to_wait == portMAX_DELAY) {
|
||||
|
||||
} else if (ticks_to_wait == 0) {
|
||||
|
||||
} else {
|
||||
ret = ESP_OK;
|
||||
ticks_to_wait = ticks_end - xTaskGetTickCount();
|
||||
}
|
||||
// Wait event bits
|
||||
EventBits_t uxBits;
|
||||
while (1) {
|
||||
TickType_t wait_time = (ticks_to_wait < (I2C_CMD_ALIVE_INTERVAL_TICK) ? ticks_to_wait : (I2C_CMD_ALIVE_INTERVAL_TICK));
|
||||
// In master mode, since we don't have an interrupt to detective bus error or FSM state, what we do here is to make
|
||||
// sure the interrupt mechanism for master mode is still working.
|
||||
// If the command sending is not finished and there is no interrupt any more, the bus is probably dead caused by external noise.
|
||||
uxBits = xEventGroupWaitBits(p_i2c->cmd_evt, I2C_CMD_EVT_ALIVE | I2C_CMD_EVT_DONE, false, false, wait_time);
|
||||
if (uxBits) {
|
||||
if (uxBits & I2C_CMD_EVT_DONE) {
|
||||
xEventGroupClearBits(p_i2c->cmd_evt, I2C_CMD_EVT_DONE);
|
||||
if (p_i2c->status == I2C_STATUS_TIMEOUT) {
|
||||
// If the I2C slave are powered off or the SDA/SCL are connected to ground, for example,
|
||||
// I2C hw FSM would get stuck in wrong state, we have to reset the I2C module in this case.
|
||||
i2c_hw_fsm_reset(i2c_num);
|
||||
ret = ESP_ERR_TIMEOUT;
|
||||
} else if (p_i2c->status == I2C_STATUS_ACK_ERROR) {
|
||||
ret = ESP_FAIL;
|
||||
} else {
|
||||
ret = ESP_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (uxBits & I2C_CMD_EVT_ALIVE) {
|
||||
xEventGroupClearBits(p_i2c->cmd_evt, I2C_CMD_EVT_ALIVE);
|
||||
}
|
||||
} else {
|
||||
ret = ESP_ERR_TIMEOUT;
|
||||
// If the I2C slave are powered off or the SDA/SCL are connected to ground, for example,
|
||||
// I2C hw FSM would get stuck in wrong state, we have to reset the I2C module in this case.
|
||||
i2c_hw_fsm_reset(i2c_num);
|
||||
break;
|
||||
}
|
||||
if (ticks_to_wait == portMAX_DELAY) {
|
||||
|
||||
} else {
|
||||
TickType_t now = xTaskGetTickCount();
|
||||
ticks_to_wait = ticks_end > now ? (ticks_end - now) : 0;
|
||||
}
|
||||
}
|
||||
p_i2c->status = I2C_STATUS_DONE;
|
||||
xSemaphoreGive(p_i2c->cmd_mux);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int i2c_slave_write_buffer(i2c_port_t i2c_num, uint8_t* data, int size, portBASE_TYPE ticks_to_wait)
|
||||
int i2c_slave_write_buffer(i2c_port_t i2c_num, uint8_t* data, int size, TickType_t ticks_to_wait)
|
||||
{
|
||||
I2C_CHECK(( i2c_num < I2C_NUM_MAX ), I2C_NUM_ERROR_STR, ESP_FAIL);
|
||||
I2C_CHECK((data != NULL), I2C_ADDR_ERROR_STR, ESP_FAIL);
|
||||
@ -1000,7 +1211,7 @@ int i2c_slave_write_buffer(i2c_port_t i2c_num, uint8_t* data, int size, portBASE
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static int i2c_slave_read(i2c_port_t i2c_num, uint8_t* data, size_t max_size, portBASE_TYPE ticks_to_wait)
|
||||
static int i2c_slave_read(i2c_port_t i2c_num, uint8_t* data, size_t max_size, TickType_t ticks_to_wait)
|
||||
{
|
||||
i2c_obj_t* p_i2c = p_i2c_obj[i2c_num];
|
||||
size_t size = 0;
|
||||
@ -1012,7 +1223,7 @@ static int i2c_slave_read(i2c_port_t i2c_num, uint8_t* data, size_t max_size, po
|
||||
return size;
|
||||
}
|
||||
|
||||
int i2c_slave_read_buffer(i2c_port_t i2c_num, uint8_t* data, size_t max_size, portBASE_TYPE ticks_to_wait)
|
||||
int i2c_slave_read_buffer(i2c_port_t i2c_num, uint8_t* data, size_t max_size, TickType_t ticks_to_wait)
|
||||
{
|
||||
I2C_CHECK(( i2c_num < I2C_NUM_MAX ), I2C_NUM_ERROR_STR, ESP_FAIL);
|
||||
I2C_CHECK((data != NULL), I2C_ADDR_ERROR_STR, ESP_FAIL);
|
||||
@ -1044,4 +1255,3 @@ int i2c_slave_read_buffer(i2c_port_t i2c_num, uint8_t* data, size_t max_size, po
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <esp_types.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
@ -22,6 +23,8 @@
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/rtc_io_reg.h"
|
||||
#include "soc/sens_reg.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "rom/lldesc.h"
|
||||
|
||||
#include "driver/gpio.h"
|
||||
@ -45,7 +48,9 @@ static const char* I2S_TAG = "I2S";
|
||||
#define I2S_EXIT_CRITICAL() portEXIT_CRITICAL(&i2s_spinlock[i2s_num])
|
||||
#define I2S_FULL_DUPLEX_SLAVE_MODE_MASK (I2S_MODE_TX | I2S_MODE_RX | I2S_MODE_SLAVE)
|
||||
#define I2S_FULL_DUPLEX_MASTER_MODE_MASK (I2S_MODE_TX | I2S_MODE_RX | I2S_MODE_MASTER)
|
||||
|
||||
#define APLL_MIN_FREQ (350000000)
|
||||
#define APLL_MAX_FREQ (500000000)
|
||||
#define APLL_I2S_MIN_RATE (10675) //in Hz, I2S Clock rate limited by hardware
|
||||
/**
|
||||
* @brief DMA buffer object
|
||||
*
|
||||
@ -77,12 +82,28 @@ typedef struct {
|
||||
int bytes_per_sample; /*!< Bytes per sample*/
|
||||
int bits_per_sample; /*!< Bits per sample*/
|
||||
i2s_mode_t mode; /*!< I2S Working mode*/
|
||||
int use_apll; /*!< I2S use APLL clock */
|
||||
} i2s_obj_t;
|
||||
|
||||
static i2s_obj_t *p_i2s_obj[I2S_NUM_MAX] = {0};
|
||||
static i2s_dev_t* I2S[I2S_NUM_MAX] = {&I2S0, &I2S1};
|
||||
static portMUX_TYPE i2s_spinlock[I2S_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED};
|
||||
|
||||
/**
|
||||
* @brief Pre define APLL parameters, save compute time
|
||||
* | bits_per_sample | rate | sdm0 | sdm1 | sdm2 | odir
|
||||
*/
|
||||
static const int apll_predefine[][6] = {
|
||||
{16, 11025, 38, 80, 5, 31},
|
||||
{16, 16000, 147, 107, 5, 21},
|
||||
{16, 22050, 130, 152, 5, 15},
|
||||
{16, 32000, 129, 212, 5, 10},
|
||||
{16, 44100, 15, 8, 5, 6},
|
||||
{16, 48000, 136, 212, 5, 6},
|
||||
{16, 96000, 143, 212, 5, 2},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static i2s_dma_t *i2s_create_dma_queue(i2s_port_t i2s_num, int dma_buf_count, int dma_buf_len);
|
||||
static esp_err_t i2s_destroy_dma_queue(i2s_port_t i2s_num, i2s_dma_t *dma);
|
||||
static esp_err_t i2s_reset_fifo(i2s_port_t i2s_num)
|
||||
@ -166,6 +187,125 @@ static esp_err_t i2s_isr_register(i2s_port_t i2s_num, uint8_t intr_alloc_flags,
|
||||
return esp_intr_alloc(ETS_I2S0_INTR_SOURCE + i2s_num, intr_alloc_flags, fn, arg, handle);
|
||||
}
|
||||
|
||||
|
||||
static float i2s_get_apll_real_rate(int bits_per_sample, int sdm0, int sdm1, int sdm2, int odir)
|
||||
{
|
||||
int f_xtal = (int)rtc_clk_xtal_freq_get() * 1000000;
|
||||
uint32_t is_rev0 = (GET_PERI_REG_BITS2(EFUSE_BLK0_RDATA3_REG, 1, 15) == 0);
|
||||
if (is_rev0) {
|
||||
sdm0 = 0;
|
||||
sdm1 = 0;
|
||||
}
|
||||
float fout = f_xtal * (sdm2 + sdm1 / 256.0f + sdm0 / 65536.0f + 4);
|
||||
if (fout < APLL_MIN_FREQ || fout > APLL_MAX_FREQ) {
|
||||
return 9999999;
|
||||
}
|
||||
float fpll = fout / (2 * (odir+2)); //== fi2s (N=1, b=0, a=1)
|
||||
return fpll/(8*4*bits_per_sample); //fbck = fi2s/bck_div
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief APLL calculate function, was described by following:
|
||||
* APLL Output frequency is given by the formula:
|
||||
*
|
||||
* apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536)/((o_div + 2) * 2)
|
||||
* apll_freq = fout / ((o_div + 2) * 2)
|
||||
*
|
||||
* The dividend in this expression should be in the range of 240 - 600 MHz.
|
||||
* In rev. 0 of ESP32, sdm0 and sdm1 are unused and always set to 0.
|
||||
* * sdm0 frequency adjustment parameter, 0..255
|
||||
* * sdm1 frequency adjustment parameter, 0..255
|
||||
* * sdm2 frequency adjustment parameter, 0..63
|
||||
* * o_div frequency divider, 0..31
|
||||
*
|
||||
* The most accurate way to find the sdm0..2 and odir parameters is to loop through them all,
|
||||
* then apply the above formula, finding the closest frequency to the desired one.
|
||||
* But 256*256*64*32 = 134.217.728 loops are too slow with ESP32
|
||||
* 1. We will choose the parameters with the highest level of change,
|
||||
* With 350MHz<fout<500MHz, we limit the sdm2 from 4 to 9,
|
||||
* Take average frequency close to the desired frequency, and select sdm2
|
||||
* 2. Next, we look for sequences of less influential and more detailed parameters,
|
||||
* also by taking the average of the largest and smallest frequencies closer to the desired frequency.
|
||||
* 3. And finally, loop through all the most detailed of the parameters, finding the best desired frequency
|
||||
*
|
||||
* @param[in] rate The sample rate
|
||||
* @param[in] bits_per_sample The bits per sample
|
||||
* @param[out] sdm0 The sdm 0
|
||||
* @param[out] sdm1 The sdm 1
|
||||
* @param[out] sdm2 The sdm 2
|
||||
* @param[out] odir The odir
|
||||
*
|
||||
* @return ESP_FAIL or ESP_OK
|
||||
*/
|
||||
static esp_err_t i2s_apll_calculate(int rate, int bits_per_sample, int *sdm0, int *sdm1, int *sdm2, int *odir)
|
||||
{
|
||||
int _odir, _sdm0, _sdm1, _sdm2, i;
|
||||
float avg;
|
||||
float min_rate, max_rate, min_diff;
|
||||
if (rate < APLL_I2S_MIN_RATE) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
//check pre-define apll parameters
|
||||
i = 0;
|
||||
while (apll_predefine[i][0]) {
|
||||
if (apll_predefine[i][0] == bits_per_sample && apll_predefine[i][0] == rate) {
|
||||
*sdm0 = apll_predefine[i][1];
|
||||
*sdm1 = apll_predefine[i][2];
|
||||
*sdm2 = apll_predefine[i][3];
|
||||
*odir = apll_predefine[i][4];
|
||||
return ESP_OK;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
*sdm0 = 0;
|
||||
*sdm1 = 0;
|
||||
*sdm2 = 0;
|
||||
*odir = 0;
|
||||
min_diff = 99999;
|
||||
|
||||
for (_sdm2 = 4; _sdm2 < 9; _sdm2 ++) {
|
||||
max_rate = i2s_get_apll_real_rate(bits_per_sample, 255, 255, _sdm2, 0);
|
||||
min_rate = i2s_get_apll_real_rate(bits_per_sample, 0, 0, _sdm2, 31);
|
||||
avg = (max_rate + min_rate)/2;
|
||||
if(abs(avg - rate) < min_diff) {
|
||||
min_diff = abs(avg - rate);
|
||||
*sdm2 = _sdm2;
|
||||
}
|
||||
}
|
||||
min_diff = 99999;
|
||||
for (_odir = 0; _odir < 32; _odir ++) {
|
||||
max_rate = i2s_get_apll_real_rate(bits_per_sample, 255, 255, *sdm2, _odir);
|
||||
min_rate = i2s_get_apll_real_rate(bits_per_sample, 0, 0, *sdm2, _odir);
|
||||
avg = (max_rate + min_rate)/2;
|
||||
if(abs(avg - rate) < min_diff) {
|
||||
min_diff = abs(avg - rate);
|
||||
*odir = _odir;
|
||||
}
|
||||
}
|
||||
|
||||
min_diff = 99999;
|
||||
for (_sdm1 = 0; _sdm1 < 256; _sdm1 ++) {
|
||||
max_rate = i2s_get_apll_real_rate(bits_per_sample, 255, _sdm1, *sdm2, *odir);
|
||||
min_rate = i2s_get_apll_real_rate(bits_per_sample, 0, _sdm1, *sdm2, *odir);
|
||||
avg = (max_rate + min_rate)/2;
|
||||
if (abs(avg - rate) < min_diff) {
|
||||
min_diff = abs(avg - rate);
|
||||
*sdm1 = _sdm1;
|
||||
}
|
||||
}
|
||||
|
||||
min_diff = 99999;
|
||||
for (_sdm0 = 0; _sdm0 < 256; _sdm0 ++) {
|
||||
avg = i2s_get_apll_real_rate(bits_per_sample, _sdm0, *sdm1, *sdm2, *odir);
|
||||
if (abs(avg - rate) < min_diff) {
|
||||
min_diff = abs(avg - rate);
|
||||
*sdm0 = _sdm0;
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t bits, i2s_channel_t ch)
|
||||
{
|
||||
int factor = (256%bits)? 384 : 256; // According to hardware codec requirement(supported 256fs or 384fs)
|
||||
@ -204,6 +344,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b
|
||||
|
||||
i2s_stop(i2s_num);
|
||||
|
||||
|
||||
uint32_t cur_mode = 0;
|
||||
if (p_i2s_obj[i2s_num]->channel_num != ch) {
|
||||
p_i2s_obj[i2s_num]->channel_num = (ch == 2) ? 2 : 1;
|
||||
@ -278,7 +419,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b
|
||||
}
|
||||
|
||||
double mclk;
|
||||
if (p_i2s_obj[i2s_num]->mode & I2S_MODE_DAC_BUILT_IN) {
|
||||
if (p_i2s_obj[i2s_num]->mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN)) {
|
||||
//DAC uses bclk as sample clock, not WS. WS can be something arbitrary.
|
||||
//Rate as given to this function is the intended sample rate;
|
||||
//According to the TRM, WS clk equals to the sample rate, and bclk is double the speed of WS
|
||||
@ -310,19 +451,33 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b
|
||||
mclk = clkmInteger + denom * clkmDecimals;
|
||||
bck = factor/(bits * channel);
|
||||
}
|
||||
|
||||
I2S[i2s_num]->clkm_conf.clka_en = 0;
|
||||
I2S[i2s_num]->clkm_conf.clkm_div_a = 63;
|
||||
I2S[i2s_num]->clkm_conf.clkm_div_b = clkmDecimals;
|
||||
I2S[i2s_num]->clkm_conf.clkm_div_num = clkmInteger;
|
||||
I2S[i2s_num]->sample_rate_conf.tx_bck_div_num = bck;
|
||||
I2S[i2s_num]->sample_rate_conf.rx_bck_div_num = bck;
|
||||
int sdm0, sdm1, sdm2, odir;
|
||||
if(p_i2s_obj[i2s_num]->use_apll && i2s_apll_calculate(rate, bits, &sdm0, &sdm1, &sdm2, &odir) == ESP_OK) {
|
||||
rtc_clk_apll_enable(1, sdm0, sdm1, sdm2, odir);
|
||||
I2S[i2s_num]->clkm_conf.clkm_div_num = 1;
|
||||
I2S[i2s_num]->clkm_conf.clkm_div_b = 0;
|
||||
I2S[i2s_num]->clkm_conf.clkm_div_a = 1;
|
||||
I2S[i2s_num]->sample_rate_conf.tx_bck_div_num = 8;
|
||||
I2S[i2s_num]->sample_rate_conf.rx_bck_div_num = 8;
|
||||
I2S[i2s_num]->clkm_conf.clka_en = 1;
|
||||
double real_rate = i2s_get_apll_real_rate(bits, sdm0, sdm1, sdm2, odir);
|
||||
ESP_LOGI(I2S_TAG, "APLL: Req RATE: %d, real rate: %0.3f, BITS: %u, CLKM: %u, BCK: %u, MCLK: %0.3f, SCLK: %f, diva: %d, divb: %d",
|
||||
rate, real_rate, bits, 1, 8, (double)I2S_BASE_CLK / mclk, real_rate*bits*channel, 1, 0);
|
||||
} else {
|
||||
I2S[i2s_num]->clkm_conf.clka_en = 0;
|
||||
I2S[i2s_num]->clkm_conf.clkm_div_a = 63;
|
||||
I2S[i2s_num]->clkm_conf.clkm_div_b = clkmDecimals;
|
||||
I2S[i2s_num]->clkm_conf.clkm_div_num = clkmInteger;
|
||||
I2S[i2s_num]->sample_rate_conf.tx_bck_div_num = bck;
|
||||
I2S[i2s_num]->sample_rate_conf.rx_bck_div_num = bck;
|
||||
double real_rate = (double) (I2S_BASE_CLK / (bck * bits * clkmInteger) / 2);
|
||||
ESP_LOGI(I2S_TAG, "PLL_D2: Req RATE: %d, real rate: %0.3f, BITS: %u, CLKM: %u, BCK: %u, MCLK: %0.3f, SCLK: %f, diva: %d, divb: %d",
|
||||
rate, real_rate, bits, clkmInteger, bck, (double)I2S_BASE_CLK / mclk, real_rate*bits*channel, 64, clkmDecimals);
|
||||
}
|
||||
|
||||
I2S[i2s_num]->sample_rate_conf.tx_bits_mod = bits;
|
||||
I2S[i2s_num]->sample_rate_conf.rx_bits_mod = bits;
|
||||
double real_rate = (double) (I2S_BASE_CLK / (bck * bits * clkmInteger) / 2);
|
||||
ESP_LOGI(I2S_TAG, "Req RATE: %d, real rate: %0.3f, BITS: %u, CLKM: %u, BCK: %u, MCLK: %0.3f, SCLK: %f, diva: %d, divb: %d",
|
||||
rate, real_rate, bits, clkmInteger, bck, (double)I2S_BASE_CLK / mclk, real_rate*bits*channel, 64, clkmDecimals);
|
||||
|
||||
|
||||
// wait all writing on-going finish
|
||||
if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) && p_i2s_obj[i2s_num]->tx) {
|
||||
xSemaphoreGive(p_i2s_obj[i2s_num]->tx->mux);
|
||||
@ -528,6 +683,11 @@ esp_err_t i2s_stop(i2s_port_t i2s_num)
|
||||
I2S[i2s_num]->lc_conf.in_rst = 0;
|
||||
I2S[i2s_num]->lc_conf.out_rst = 1;
|
||||
I2S[i2s_num]->lc_conf.out_rst = 0;
|
||||
|
||||
I2S[i2s_num]->conf.tx_reset = 1;
|
||||
I2S[i2s_num]->conf.tx_reset = 0;
|
||||
I2S[i2s_num]->conf.rx_reset = 1;
|
||||
I2S[i2s_num]->conf.rx_reset = 0;
|
||||
I2S_EXIT_CRITICAL();
|
||||
return 0;
|
||||
}
|
||||
@ -535,7 +695,7 @@ esp_err_t i2s_stop(i2s_port_t i2s_num)
|
||||
esp_err_t i2s_set_dac_mode(i2s_dac_mode_t dac_mode)
|
||||
{
|
||||
I2S_CHECK((dac_mode < I2S_DAC_CHANNEL_MAX), "i2s dac mode error", ESP_ERR_INVALID_ARG);
|
||||
if(dac_mode == I2S_DAC_CHANNEL_DISABLE) {
|
||||
if (dac_mode == I2S_DAC_CHANNEL_DISABLE) {
|
||||
dac_output_disable(DAC_CHANNEL_1);
|
||||
dac_output_disable(DAC_CHANNEL_2);
|
||||
dac_i2s_disable();
|
||||
@ -554,6 +714,13 @@ esp_err_t i2s_set_dac_mode(i2s_dac_mode_t dac_mode)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2s_set_adc_mode(adc_unit_t adc_unit, adc1_channel_t adc_channel)
|
||||
{
|
||||
I2S_CHECK((adc_unit < ADC_UNIT_2), "i2s ADC unit error, only support ADC1 for now", ESP_ERR_INVALID_ARG);
|
||||
// For now, we only support SAR ADC1.
|
||||
return adc_i2s_mode_init(adc_unit, adc_channel);
|
||||
}
|
||||
|
||||
esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin)
|
||||
{
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
|
||||
@ -568,7 +735,7 @@ esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin)
|
||||
ESP_LOGE(I2S_TAG, "ws_io_num error");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (pin->data_out_num != -1 && !GPIO_IS_VALID_GPIO(pin->data_out_num)) {
|
||||
if (pin->data_out_num != -1 && !GPIO_IS_VALID_OUTPUT_GPIO(pin->data_out_num)) {
|
||||
ESP_LOGE(I2S_TAG, "data_out_num error");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@ -669,10 +836,14 @@ esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate)
|
||||
I2S_CHECK((p_i2s_obj[i2s_num]->bytes_per_sample > 0), "bits_per_sample not set", ESP_ERR_INVALID_ARG);
|
||||
return i2s_set_clk(i2s_num, rate, p_i2s_obj[i2s_num]->bits_per_sample, p_i2s_obj[i2s_num]->channel_num);
|
||||
}
|
||||
|
||||
static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_config)
|
||||
{
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
|
||||
I2S_CHECK((i2s_config), "param null", ESP_ERR_INVALID_ARG);
|
||||
I2S_CHECK(!((i2s_config->mode & I2S_MODE_ADC_BUILT_IN) && (i2s_num != I2S_NUM_0)), "I2S ADC built-in only support on I2S0", ESP_ERR_INVALID_ARG);
|
||||
I2S_CHECK(!((i2s_config->mode & I2S_MODE_DAC_BUILT_IN) && (i2s_num != I2S_NUM_0)), "I2S DAC built-in only support on I2S0", ESP_ERR_INVALID_ARG);
|
||||
I2S_CHECK(!((i2s_config->mode & I2S_MODE_PDM) && (i2s_num != I2S_NUM_0)), "I2S DAC PDM only support on I2S0", ESP_ERR_INVALID_ARG);
|
||||
|
||||
if (i2s_num == I2S_NUM_1) {
|
||||
periph_module_enable(PERIPH_I2S1_MODULE);
|
||||
@ -680,23 +851,27 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co
|
||||
periph_module_enable(PERIPH_I2S0_MODULE);
|
||||
}
|
||||
|
||||
if(i2s_config->mode & I2S_MODE_ADC_BUILT_IN) {
|
||||
//in ADC built-in mode, we need to call i2s_set_adc_mode to
|
||||
//initialize the specific ADC channel.
|
||||
//in the current stage, we only support ADC1 and single channel mode.
|
||||
//In default data mode, the ADC data is in 12-bit resolution mode.
|
||||
adc_power_on();
|
||||
}
|
||||
// configure I2S data port interface.
|
||||
i2s_reset_fifo(i2s_num);
|
||||
|
||||
//reset i2s
|
||||
I2S[i2s_num]->conf.tx_reset = 1;
|
||||
I2S[i2s_num]->conf.tx_reset = 0;
|
||||
I2S[i2s_num]->conf.rx_reset = 1;
|
||||
I2S[i2s_num]->conf.rx_reset = 0;
|
||||
|
||||
|
||||
//reset dma
|
||||
I2S[i2s_num]->lc_conf.in_rst = 1;
|
||||
I2S[i2s_num]->lc_conf.in_rst = 0;
|
||||
I2S[i2s_num]->lc_conf.out_rst = 1;
|
||||
I2S[i2s_num]->lc_conf.out_rst = 0;
|
||||
|
||||
|
||||
//Enable and configure DMA
|
||||
I2S[i2s_num]->lc_conf.check_owner = 0;
|
||||
I2S[i2s_num]->lc_conf.out_loop_test = 0;
|
||||
@ -707,7 +882,6 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co
|
||||
I2S[i2s_num]->lc_conf.indscr_burst_en = 0;
|
||||
I2S[i2s_num]->lc_conf.out_eof_mode = 1;
|
||||
|
||||
|
||||
I2S[i2s_num]->conf2.lcd_en = 0;
|
||||
I2S[i2s_num]->conf2.camera_en = 0;
|
||||
I2S[i2s_num]->pdm_conf.pcm2pdm_conv_en = 0;
|
||||
@ -751,9 +925,10 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co
|
||||
}
|
||||
}
|
||||
|
||||
if (i2s_config->mode & I2S_MODE_DAC_BUILT_IN) {
|
||||
if (i2s_config->mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN)) {
|
||||
I2S[i2s_num]->conf2.lcd_en = 1;
|
||||
I2S[i2s_num]->conf.tx_right_first = 1;
|
||||
I2S[i2s_num]->conf2.camera_en = 0;
|
||||
}
|
||||
|
||||
if (i2s_config->mode & I2S_MODE_PDM) {
|
||||
@ -813,6 +988,8 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co
|
||||
I2S[i2s_num]->conf.rx_slave_mod = 1; //RX Slave
|
||||
}
|
||||
}
|
||||
|
||||
p_i2s_obj[i2s_num]->use_apll = i2s_config->use_apll;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -873,7 +1050,12 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config,
|
||||
return err;
|
||||
}
|
||||
i2s_stop(i2s_num);
|
||||
i2s_param_config(i2s_num, i2s_config);
|
||||
err = i2s_param_config(i2s_num, i2s_config);
|
||||
if (err != ESP_OK) {
|
||||
i2s_driver_uninstall(i2s_num);
|
||||
ESP_LOGE(I2S_TAG, "I2S param configure error");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (i2s_queue) {
|
||||
p_i2s_obj[i2s_num]->i2s_queue = xQueueCreate(queue_size, sizeof(i2s_event_t));
|
||||
@ -914,6 +1096,10 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num)
|
||||
p_i2s_obj[i2s_num]->i2s_queue = NULL;
|
||||
}
|
||||
|
||||
if(p_i2s_obj[i2s_num]->use_apll) {
|
||||
rtc_clk_apll_enable(0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
free(p_i2s_obj[i2s_num]);
|
||||
p_i2s_obj[i2s_num] = NULL;
|
||||
|
||||
|
@ -20,24 +20,38 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "soc/adc_channel.h"
|
||||
|
||||
typedef enum {
|
||||
ADC_ATTEN_0db = 0, /*!<The input voltage of ADC will be reduced to about 1/1 */
|
||||
ADC_ATTEN_2_5db = 1, /*!<The input voltage of ADC will be reduced to about 1/1.34 */
|
||||
ADC_ATTEN_6db = 2, /*!<The input voltage of ADC will be reduced to about 1/2 */
|
||||
ADC_ATTEN_11db = 3, /*!<The input voltage of ADC will be reduced to about 1/3.6*/
|
||||
ADC_ATTEN_DB_0 = 0, /*!<The input voltage of ADC will be reduced to about 1/1 */
|
||||
ADC_ATTEN_DB_2_5 = 1, /*!<The input voltage of ADC will be reduced to about 1/1.34 */
|
||||
ADC_ATTEN_DB_6 = 2, /*!<The input voltage of ADC will be reduced to about 1/2 */
|
||||
ADC_ATTEN_DB_11 = 3, /*!<The input voltage of ADC will be reduced to about 1/3.6*/
|
||||
ADC_ATTEN_MAX,
|
||||
} adc_atten_t;
|
||||
|
||||
typedef enum {
|
||||
ADC_WIDTH_9Bit = 0, /*!< ADC capture width is 9Bit*/
|
||||
ADC_WIDTH_10Bit = 1, /*!< ADC capture width is 10Bit*/
|
||||
ADC_WIDTH_11Bit = 2, /*!< ADC capture width is 11Bit*/
|
||||
ADC_WIDTH_12Bit = 3, /*!< ADC capture width is 12Bit*/
|
||||
ADC_WIDTH_BIT_9 = 0, /*!< ADC capture width is 9Bit*/
|
||||
ADC_WIDTH_BIT_10 = 1, /*!< ADC capture width is 10Bit*/
|
||||
ADC_WIDTH_BIT_11 = 2, /*!< ADC capture width is 11Bit*/
|
||||
ADC_WIDTH_BIT_12 = 3, /*!< ADC capture width is 12Bit*/
|
||||
ADC_WIDTH_MAX,
|
||||
} adc_bits_width_t;
|
||||
|
||||
//this definitions are only for being back-compatible
|
||||
#define ADC_ATTEN_0db ADC_ATTEN_DB_0
|
||||
#define ADC_ATTEN_2_5db ADC_ATTEN_DB_2_5
|
||||
#define ADC_ATTEN_6db ADC_ATTEN_DB_6
|
||||
#define ADC_ATTEN_11db ADC_ATTEN_DB_11
|
||||
//this definitions are only for being back-compatible
|
||||
#define ADC_WIDTH_9Bit ADC_WIDTH_BIT_9
|
||||
#define ADC_WIDTH_10Bit ADC_WIDTH_BIT_10
|
||||
#define ADC_WIDTH_11Bit ADC_WIDTH_BIT_11
|
||||
#define ADC_WIDTH_12Bit ADC_WIDTH_BIT_12
|
||||
|
||||
typedef enum {
|
||||
ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO36 */
|
||||
ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO37 */
|
||||
@ -64,11 +78,56 @@ typedef enum {
|
||||
ADC2_CHANNEL_MAX,
|
||||
} adc2_channel_t;
|
||||
|
||||
typedef enum {
|
||||
ADC_CHANNEL_0 = 0, /*!< ADC channel */
|
||||
ADC_CHANNEL_1, /*!< ADC channel */
|
||||
ADC_CHANNEL_2, /*!< ADC channel */
|
||||
ADC_CHANNEL_3, /*!< ADC channel */
|
||||
ADC_CHANNEL_4, /*!< ADC channel */
|
||||
ADC_CHANNEL_5, /*!< ADC channel */
|
||||
ADC_CHANNEL_6, /*!< ADC channel */
|
||||
ADC_CHANNEL_7, /*!< ADC channel */
|
||||
ADC_CHANNEL_8, /*!< ADC channel */
|
||||
ADC_CHANNEL_9, /*!< ADC channel */
|
||||
ADC_CHANNEL_MAX,
|
||||
} adc_channel_t;
|
||||
|
||||
typedef enum {
|
||||
ADC_UNIT_1 = 1, /*!< SAR ADC 1*/
|
||||
ADC_UNIT_2 = 2, /*!< SAR ADC 2, not supported yet*/
|
||||
ADC_UNIT_BOTH = 3, /*!< SAR ADC 1 and 2, not supported yet */
|
||||
ADC_UNIT_ALTER = 7, /*!< SAR ADC 1 and 2 alternative mode, not supported yet */
|
||||
ADC_UNIT_MAX,
|
||||
} adc_unit_t;
|
||||
|
||||
typedef enum {
|
||||
ADC_ENCODE_12BIT, /*!< ADC to I2S data format, [15:12]-channel [11:0]-12 bits ADC data */
|
||||
ADC_ENCODE_11BIT, /*!< ADC to I2S data format, [15]-1 [14:11]-channel [10:0]-11 bits ADC data */
|
||||
ADC_ENCODE_MAX,
|
||||
} adc_i2s_encode_t;
|
||||
|
||||
typedef enum {
|
||||
ADC_I2S_DATA_SRC_IO_SIG = 0, /*!< I2S data from GPIO matrix signal */
|
||||
ADC_I2S_DATA_SRC_ADC = 1, /*!< I2S data from ADC */
|
||||
ADC_I2S_DATA_SRC_MAX,
|
||||
} adc_i2s_source_t;
|
||||
|
||||
/**
|
||||
* @brief Configure ADC1 capture width.
|
||||
*
|
||||
* @brief Get the gpio number of a specific ADC1 channel.
|
||||
*
|
||||
* @param channel Channel to get the gpio number
|
||||
*
|
||||
* @param gpio_num output buffer to hold the gpio number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if success
|
||||
* - ESP_ERR_INVALID_ARG if channal not valid
|
||||
*/
|
||||
esp_err_t adc1_pad_get_io_num(adc1_channel_t channel, gpio_num_t *gpio_num);
|
||||
|
||||
/**
|
||||
* @brief Configure ADC1 capture width, meanwhile enable output invert for ADC1.
|
||||
* The configuration is for all channels of ADC1
|
||||
*
|
||||
* @param width_bit Bit capture width for ADC1
|
||||
*
|
||||
* @return
|
||||
@ -77,6 +136,16 @@ typedef enum {
|
||||
*/
|
||||
esp_err_t adc1_config_width(adc_bits_width_t width_bit);
|
||||
|
||||
/**
|
||||
* @brief Configure ADC capture width.
|
||||
* @param adc_unit ADC unit index
|
||||
* @param width_bit Bit capture width for ADC unit.
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t width_bit);
|
||||
|
||||
/**
|
||||
* @brief Configure the ADC1 channel, including setting attenuation.
|
||||
*
|
||||
@ -89,10 +158,10 @@ esp_err_t adc1_config_width(adc_bits_width_t width_bit);
|
||||
*
|
||||
* When VDD_A is 3.3V:
|
||||
*
|
||||
* - 0dB attenuaton (ADC_ATTEN_0db) gives full-scale voltage 1.1V
|
||||
* - 2.5dB attenuation (ADC_ATTEN_2_5db) gives full-scale voltage 1.5V
|
||||
* - 6dB attenuation (ADC_ATTEN_6db) gives full-scale voltage 2.2V
|
||||
* - 11dB attenuation (ADC_ATTEN_11db) gives full-scale voltage 3.9V (see note below)
|
||||
* - 0dB attenuaton (ADC_ATTEN_DB_0) gives full-scale voltage 1.1V
|
||||
* - 2.5dB attenuation (ADC_ATTEN_DB_2_5) gives full-scale voltage 1.5V
|
||||
* - 6dB attenuation (ADC_ATTEN_DB_6) gives full-scale voltage 2.2V
|
||||
* - 11dB attenuation (ADC_ATTEN_DB_11) gives full-scale voltage 3.9V (see note below)
|
||||
*
|
||||
* @note The full-scale voltage is the voltage corresponding to a maximum reading (depending on ADC1 configured
|
||||
* bit width, this value is: 4095 for 12-bits, 2047 for 11-bits, 1023 for 10-bits, 511 for 9 bits.)
|
||||
@ -134,6 +203,62 @@ int adc1_get_raw(adc1_channel_t channel);
|
||||
int adc1_get_voltage(adc1_channel_t channel) __attribute__((deprecated));
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* @brief Power on SAR ADC
|
||||
*/
|
||||
void adc_power_on();
|
||||
|
||||
/**
|
||||
* @brief Power off SAR ADC
|
||||
*/
|
||||
void adc_power_off();
|
||||
|
||||
/**
|
||||
* @brief Initialize ADC pad
|
||||
* @param adc_unit ADC unit index
|
||||
* @param channel ADC channel index
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc_gpio_init(adc_unit_t adc_unit, adc_channel_t channel);
|
||||
|
||||
/**
|
||||
* @brief Set ADC data invert
|
||||
* @param adc_unit ADC unit index
|
||||
* @param inv_en whether enable data invert
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc_set_data_inv(adc_unit_t adc_unit, bool inv_en);
|
||||
|
||||
/**
|
||||
* @brief Set ADC source clock
|
||||
* @param clk_div ADC clock divider, ADC clock is divided from APB clock
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t adc_set_clk_div(uint8_t clk_div);
|
||||
|
||||
/**
|
||||
* @brief Set I2S data source
|
||||
* @param src I2S DMA data source, I2S DMA can get data from digital signals or from ADC.
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src);
|
||||
|
||||
/**
|
||||
* @brief Initialize I2S ADC mode
|
||||
* @param adc_unit ADC unit index
|
||||
* @param channel ADC channel index
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel);
|
||||
|
||||
/**
|
||||
* @brief Configure ADC1 to be usable by the ULP
|
||||
*
|
||||
@ -161,6 +286,70 @@ void adc1_ulp_enable();
|
||||
*/
|
||||
int hall_sensor_read();
|
||||
|
||||
/**
|
||||
* @brief Get the gpio number of a specific ADC2 channel.
|
||||
*
|
||||
* @param channel Channel to get the gpio number
|
||||
*
|
||||
* @param gpio_num output buffer to hold the gpio number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if success
|
||||
* - ESP_ERR_INVALID_ARG if channal not valid
|
||||
*/
|
||||
esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num);
|
||||
|
||||
/**
|
||||
* @brief Configure the ADC2 channel, including setting attenuation.
|
||||
*
|
||||
* @note This function also configures the input GPIO pin mux to
|
||||
* connect it to the ADC2 channel. It must be called before calling
|
||||
* ``adc2_get_raw()`` for this channel.
|
||||
*
|
||||
* The default ADC full-scale voltage is 1.1V. To read higher voltages (up to the pin maximum voltage,
|
||||
* usually 3.3V) requires setting >0dB signal attenuation for that ADC channel.
|
||||
*
|
||||
* When VDD_A is 3.3V:
|
||||
*
|
||||
* - 0dB attenuaton (ADC_ATTEN_0db) gives full-scale voltage 1.1V
|
||||
* - 2.5dB attenuation (ADC_ATTEN_2_5db) gives full-scale voltage 1.5V
|
||||
* - 6dB attenuation (ADC_ATTEN_6db) gives full-scale voltage 2.2V
|
||||
* - 11dB attenuation (ADC_ATTEN_11db) gives full-scale voltage 3.9V (see note below)
|
||||
*
|
||||
* @note The full-scale voltage is the voltage corresponding to a maximum reading
|
||||
* (depending on ADC2 configured bit width, this value is: 4095 for 12-bits, 2047
|
||||
* for 11-bits, 1023 for 10-bits, 511 for 9 bits.)
|
||||
*
|
||||
* @note At 11dB attenuation the maximum voltage is limited by VDD_A, not the full scale voltage.
|
||||
*
|
||||
* @param channel ADC2 channel to configure
|
||||
* @param atten Attenuation level
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten);
|
||||
|
||||
/**
|
||||
* @brief Take an ADC2 reading on a single channel
|
||||
*
|
||||
* @note For a given channel, ``adc2_config_channel_atten()``
|
||||
* must be called before the first time this function is called. If Wi-Fi is started via ``esp_wifi_start()``, this
|
||||
* function will always fail with ``ESP_ERR_TIMEOUT``.
|
||||
*
|
||||
* @param channel ADC2 channel to read
|
||||
*
|
||||
* @param width_bit Bit capture width for ADC2
|
||||
*
|
||||
* @param raw_out the variable to hold the output data.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if success
|
||||
* - ESP_ERR_TIMEOUT the WIFI is started, using the ADC2
|
||||
*/
|
||||
esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int* raw_out);
|
||||
|
||||
/**
|
||||
* @brief Output ADC2 reference voltage to gpio 25 or 26 or 27
|
||||
*
|
||||
|
52
components/driver/include/driver/adc2_wifi_internal.h
Normal file
52
components/driver/include/driver/adc2_wifi_internal.h
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _DRIVER_ADC2_INTERNAL_H_
|
||||
#define _DRIVER_ADC2_INTERNAL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
/**
|
||||
* @brief For WIFI module to claim the usage of ADC2.
|
||||
*
|
||||
* Other tasks will be forbidden to use ADC2 between ``adc2_wifi_acquire`` and ``adc2_wifi_release``.
|
||||
* The WIFI module may have to wait for a short time for the current conversion (if exist) to finish.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_TIMEOUT reserved for future use. Currently the function will wait until success.
|
||||
*/
|
||||
esp_err_t adc2_wifi_acquire();
|
||||
|
||||
|
||||
/**
|
||||
* @brief For WIFI module to let other tasks use the ADC2 when WIFI is not work.
|
||||
*
|
||||
* Other tasks will be forbidden to use ADC2 between ``adc2_wifi_acquire`` and ``adc2_wifi_release``.
|
||||
* Call this function to release the occupation of ADC2 by WIFI.
|
||||
*
|
||||
* @return always return ESP_OK.
|
||||
*/
|
||||
esp_err_t adc2_wifi_release();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_DRIVER_ADC2_INTERNAL_H_*/
|
||||
|
@ -29,6 +29,19 @@ typedef enum {
|
||||
DAC_CHANNEL_MAX,
|
||||
} dac_channel_t;
|
||||
|
||||
/**
|
||||
* @brief Get the gpio number of a specific DAC channel.
|
||||
*
|
||||
* @param channel Channel to get the gpio number
|
||||
*
|
||||
* @param gpio_num output buffer to hold the gpio number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if success
|
||||
* - ESP_ERR_INVALID_ARG if channal not valid
|
||||
*/
|
||||
esp_err_t dac_pad_get_io_num(dac_channel_t channel, gpio_num_t *gpio_num);
|
||||
|
||||
/** @cond */
|
||||
/**
|
||||
* @brief Set DAC output voltage.
|
||||
|
@ -200,7 +200,7 @@ esp_err_t i2c_isr_free(intr_handle_t handle);
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_set_pin(i2c_port_t i2c_num, gpio_num_t sda_io_num, gpio_num_t scl_io_num,
|
||||
esp_err_t i2c_set_pin(i2c_port_t i2c_num, int sda_io_num, int scl_io_num,
|
||||
gpio_pullup_t sda_pullup_en, gpio_pullup_t scl_pullup_en, i2c_mode_t mode);
|
||||
|
||||
/**
|
||||
@ -341,7 +341,7 @@ esp_err_t i2c_master_stop(i2c_cmd_handle_t cmd_handle);
|
||||
* - ESP_ERR_INVALID_STATE I2C driver not installed or not in master mode.
|
||||
* - ESP_ERR_TIMEOUT Operation timeout because the bus is busy.
|
||||
*/
|
||||
esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, portBASE_TYPE ticks_to_wait);
|
||||
esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, TickType_t ticks_to_wait);
|
||||
|
||||
/**
|
||||
* @brief I2C slave write data to internal ringbuffer, when tx fifo empty, isr will fill the hardware
|
||||
@ -358,7 +358,7 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle,
|
||||
* - ESP_FAIL(-1) Parameter error
|
||||
* - Others(>=0) The number of data bytes that pushed to the I2C slave buffer.
|
||||
*/
|
||||
int i2c_slave_write_buffer(i2c_port_t i2c_num, uint8_t* data, int size, portBASE_TYPE ticks_to_wait);
|
||||
int i2c_slave_write_buffer(i2c_port_t i2c_num, uint8_t* data, int size, TickType_t ticks_to_wait);
|
||||
|
||||
/**
|
||||
* @brief I2C slave read data from internal buffer. When I2C slave receive data, isr will copy received data
|
||||
@ -375,7 +375,7 @@ int i2c_slave_write_buffer(i2c_port_t i2c_num, uint8_t* data, int size, portBASE
|
||||
* - ESP_FAIL(-1) Parameter error
|
||||
* - Others(>=0) The number of data bytes that read from I2C slave buffer.
|
||||
*/
|
||||
int i2c_slave_read_buffer(i2c_port_t i2c_num, uint8_t* data, size_t max_size, portBASE_TYPE ticks_to_wait);
|
||||
int i2c_slave_read_buffer(i2c_port_t i2c_num, uint8_t* data, size_t max_size, TickType_t ticks_to_wait);
|
||||
|
||||
/**
|
||||
* @brief set I2C master clock period
|
||||
@ -481,6 +481,25 @@ esp_err_t i2c_set_data_timing(i2c_port_t i2c_num, int sample_time, int hold_time
|
||||
*/
|
||||
esp_err_t i2c_get_data_timing(i2c_port_t i2c_num, int* sample_time, int* hold_time);
|
||||
|
||||
/**
|
||||
* @brief set I2C timeout value
|
||||
* @param i2c_num I2C port number
|
||||
* @param timeout timeout value for I2C bus (unit: APB 80Mhz clock cycle)
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_set_timeout(i2c_port_t i2c_num, int timeout);
|
||||
|
||||
/**
|
||||
* @brief get I2C timeout value
|
||||
* @param i2c_num I2C port number
|
||||
* @param timeout pointer to get timeout value
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2c_get_timeout(i2c_port_t i2c_num, int* timeout);
|
||||
/**
|
||||
* @brief set I2C data transfer mode
|
||||
*
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "esp_attr.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "driver/adc.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -118,10 +119,12 @@ typedef enum {
|
||||
I2S_MODE_TX = 4,
|
||||
I2S_MODE_RX = 8,
|
||||
I2S_MODE_DAC_BUILT_IN = 16, /*!< Output I2S data to built-in DAC, no matter the data format is 16bit or 32 bit, the DAC module will only take the 8bits from MSB*/
|
||||
//I2S_MODE_ADC_BUILT_IN = 32, /*!< Currently not supported yet, will be added for the next version*/
|
||||
I2S_MODE_ADC_BUILT_IN = 32, /*!< Input I2S data from built-in ADC, each data can be 12-bit width at most*/
|
||||
I2S_MODE_PDM = 64,
|
||||
} i2s_mode_t;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief I2S configuration parameters for i2s_param_config function
|
||||
*
|
||||
@ -135,6 +138,7 @@ typedef struct {
|
||||
int intr_alloc_flags; /*!< Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info */
|
||||
int dma_buf_count; /*!< I2S DMA Buffer Count */
|
||||
int dma_buf_len; /*!< I2S DMA Buffer Length */
|
||||
int use_apll; /*!< I2S using APLL as main I2S clock, enable it to get accurate clock */
|
||||
} i2s_config_t;
|
||||
|
||||
/**
|
||||
@ -402,6 +406,17 @@ esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num);
|
||||
*/
|
||||
esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t bits, i2s_channel_t ch);
|
||||
|
||||
/**
|
||||
* @brief Set built-in ADC mode for I2S DMA, this function will initialize ADC pad,
|
||||
* and set ADC parameters.
|
||||
* @param adc_unit SAR ADC unit index
|
||||
* @param adc_channel ADC channel index
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Parameter error
|
||||
*/
|
||||
esp_err_t i2s_set_adc_mode(adc_unit_t adc_unit, adc1_channel_t adc_channel);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -26,6 +26,7 @@ extern "C" {
|
||||
|
||||
#define LEDC_APB_CLK_HZ (APB_CLK_FREQ)
|
||||
#define LEDC_REF_CLK_HZ (1*1000000)
|
||||
#define LEDC_ERR_DUTY (0xFFFFFFFF)
|
||||
|
||||
typedef enum {
|
||||
LEDC_HIGH_SPEED_MODE = 0, /*!< LEDC high speed speed_mode */
|
||||
@ -206,10 +207,10 @@ esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t
|
||||
* @param channel LEDC channel(0-7), select from ledc_channel_t
|
||||
*
|
||||
* @return
|
||||
* - (-1) parameter error
|
||||
* - LEDC_ERR_DUTY if parameter error
|
||||
* - Others Current LEDC duty
|
||||
*/
|
||||
int ledc_get_duty(ledc_mode_t speed_mode, ledc_channel_t channel);
|
||||
uint32_t ledc_get_duty(ledc_mode_t speed_mode, ledc_channel_t channel);
|
||||
|
||||
/**
|
||||
* @brief LEDC set gradient
|
||||
@ -329,7 +330,7 @@ esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, uint32_t channel, uint
|
||||
* - ESP_ERR_INVALID_STATE Fade function not installed.
|
||||
* - ESP_FAIL Fade function init error
|
||||
*/
|
||||
esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, int target_duty, int scale, int cycle_num);
|
||||
esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int scale, int cycle_num);
|
||||
|
||||
/**
|
||||
* @brief Set LEDC fade function, with a limited time. Should call ledc_fade_func_install() before calling this function.
|
||||
@ -346,7 +347,7 @@ esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel
|
||||
* - ESP_ERR_INVALID_STATE Fade function not installed.
|
||||
* - ESP_FAIL Fade function init error
|
||||
*/
|
||||
esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, int target_duty, int max_fade_time_ms);
|
||||
esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int max_fade_time_ms);
|
||||
|
||||
/**
|
||||
* @brief Install ledc fade function. This function will occupy interrupt of LEDC module.
|
||||
|
@ -18,59 +18,76 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PCNT_PIN_NOT_USED (-1) /*!< Pin are not used */
|
||||
#define PCNT_PIN_NOT_USED (-1) /*!< When selected for a pin, this pin will not be used */
|
||||
|
||||
/**
|
||||
* @brief Selection of available modes that determine the counter's action depending on the state of the control signal's input GPIO
|
||||
* @note Configuration covers two actions, one for high, and one for low level on the control input
|
||||
*/
|
||||
typedef enum {
|
||||
PCNT_MODE_KEEP = 0, /*!< Control mode: won't change counter mode*/
|
||||
PCNT_MODE_REVERSE = 1, /*!< Control mode: invert counter mode(increase -> decrease, decrease -> increase);*/
|
||||
PCNT_MODE_DISABLE = 2, /*!< Control mode: Inhibit counter(counter value will not change in this condition)*/
|
||||
PCNT_MODE_REVERSE = 1, /*!< Control mode: invert counter mode(increase -> decrease, decrease -> increase) */
|
||||
PCNT_MODE_DISABLE = 2, /*!< Control mode: Inhibit counter(counter value will not change in this condition) */
|
||||
PCNT_MODE_MAX
|
||||
} pcnt_ctrl_mode_t;
|
||||
|
||||
/**
|
||||
* @brief Selection of available modes that determine the counter's action on the edge of the pulse signal's input GPIO
|
||||
* @note Configuration covers two actions, one for positive, and one for negative edge on the pulse input
|
||||
*/
|
||||
typedef enum {
|
||||
PCNT_COUNT_DIS = 0, /*!< Counter mode: Inhibit counter(counter value will not change in this condition)*/
|
||||
PCNT_COUNT_INC = 1, /*!< Counter mode: Increase counter value*/
|
||||
PCNT_COUNT_DEC = 2, /*!< Counter mode: Decrease counter value*/
|
||||
PCNT_COUNT_DIS = 0, /*!< Counter mode: Inhibit counter(counter value will not change in this condition) */
|
||||
PCNT_COUNT_INC = 1, /*!< Counter mode: Increase counter value */
|
||||
PCNT_COUNT_DEC = 2, /*!< Counter mode: Decrease counter value */
|
||||
PCNT_COUNT_MAX
|
||||
} pcnt_count_mode_t;
|
||||
|
||||
/**
|
||||
* @brief Selection of all available PCNT units
|
||||
*/
|
||||
typedef enum {
|
||||
PCNT_UNIT_0 = 0, /*!< PCNT unit0 */
|
||||
PCNT_UNIT_1 = 1, /*!< PCNT unit1 */
|
||||
PCNT_UNIT_2 = 2, /*!< PCNT unit2 */
|
||||
PCNT_UNIT_3 = 3, /*!< PCNT unit3 */
|
||||
PCNT_UNIT_4 = 4, /*!< PCNT unit4 */
|
||||
PCNT_UNIT_5 = 5, /*!< PCNT unit5 */
|
||||
PCNT_UNIT_6 = 6, /*!< PCNT unit6 */
|
||||
PCNT_UNIT_7 = 7, /*!< PCNT unit7 */
|
||||
PCNT_UNIT_0 = 0, /*!< PCNT unit 0 */
|
||||
PCNT_UNIT_1 = 1, /*!< PCNT unit 1 */
|
||||
PCNT_UNIT_2 = 2, /*!< PCNT unit 2 */
|
||||
PCNT_UNIT_3 = 3, /*!< PCNT unit 3 */
|
||||
PCNT_UNIT_4 = 4, /*!< PCNT unit 4 */
|
||||
PCNT_UNIT_5 = 5, /*!< PCNT unit 5 */
|
||||
PCNT_UNIT_6 = 6, /*!< PCNT unit 6 */
|
||||
PCNT_UNIT_7 = 7, /*!< PCNT unit 7 */
|
||||
PCNT_UNIT_MAX,
|
||||
} pcnt_unit_t;
|
||||
|
||||
/**
|
||||
* @brief Selection of channels available for a single PCNT unit
|
||||
*/
|
||||
typedef enum {
|
||||
PCNT_CHANNEL_0 = 0x00, /*!< PCNT channel0 */
|
||||
PCNT_CHANNEL_1 = 0x01, /*!< PCNT channel1 */
|
||||
PCNT_CHANNEL_0 = 0x00, /*!< PCNT channel 0 */
|
||||
PCNT_CHANNEL_1 = 0x01, /*!< PCNT channel 1 */
|
||||
PCNT_CHANNEL_MAX,
|
||||
} pcnt_channel_t;
|
||||
|
||||
/**
|
||||
* @brief Selection of counter's events the may trigger an interrupt
|
||||
*/
|
||||
typedef enum {
|
||||
PCNT_EVT_L_LIM = 0, /*!< PCNT watch point event: Minimum counter value */
|
||||
PCNT_EVT_H_LIM = 1, /*!< PCNT watch point event: Maximum counter value*/
|
||||
PCNT_EVT_THRES_0 = 2, /*!< PCNT watch point event: threshold0 value event*/
|
||||
PCNT_EVT_THRES_1 = 3, /*!< PCNT watch point event: threshold1 value event*/
|
||||
PCNT_EVT_ZERO = 4, /*!< PCNT watch point event: counter value zero event*/
|
||||
PCNT_EVT_H_LIM = 1, /*!< PCNT watch point event: Maximum counter value */
|
||||
PCNT_EVT_THRES_0 = 2, /*!< PCNT watch point event: threshold0 value event */
|
||||
PCNT_EVT_THRES_1 = 3, /*!< PCNT watch point event: threshold1 value event */
|
||||
PCNT_EVT_ZERO = 4, /*!< PCNT watch point event: counter value zero event */
|
||||
PCNT_EVT_MAX
|
||||
} pcnt_evt_type_t;
|
||||
|
||||
/**
|
||||
* @brief Pulse Counter configure struct
|
||||
* @brief Pulse Counter configuration for a single channel
|
||||
*/
|
||||
typedef struct {
|
||||
int pulse_gpio_num; /*!< Pulse input gpio_num, if you want to use gpio16, pulse_gpio_num = 16, a negative value will be ignored */
|
||||
int ctrl_gpio_num; /*!< Contol signal input gpio_num, a negative value will be ignored*/
|
||||
pcnt_ctrl_mode_t lctrl_mode; /*!< PCNT low control mode*/
|
||||
pcnt_ctrl_mode_t hctrl_mode; /*!< PCNT high control mode*/
|
||||
pcnt_count_mode_t pos_mode; /*!< PCNT positive edge count mode*/
|
||||
pcnt_count_mode_t neg_mode; /*!< PCNT negative edge count mode*/
|
||||
int pulse_gpio_num; /*!< Pulse input GPIO number, if you want to use GPIO16, enter pulse_gpio_num = 16, a negative value will be ignored */
|
||||
int ctrl_gpio_num; /*!< Control signal input GPIO number, a negative value will be ignored */
|
||||
pcnt_ctrl_mode_t lctrl_mode; /*!< PCNT low control mode */
|
||||
pcnt_ctrl_mode_t hctrl_mode; /*!< PCNT high control mode */
|
||||
pcnt_count_mode_t pos_mode; /*!< PCNT positive edge count mode */
|
||||
pcnt_count_mode_t neg_mode; /*!< PCNT negative edge count mode */
|
||||
int16_t counter_h_lim; /*!< Maximum counter value */
|
||||
int16_t counter_l_lim; /*!< Minimum counter value */
|
||||
pcnt_unit_t unit; /*!< PCNT unit number */
|
||||
@ -150,7 +167,7 @@ esp_err_t pcnt_counter_clear(pcnt_unit_t pcnt_unit);
|
||||
esp_err_t pcnt_intr_enable(pcnt_unit_t pcnt_unit);
|
||||
|
||||
/**
|
||||
* @brief Disable PCNT interrupt for PCNT uint
|
||||
* @brief Disable PCNT interrupt for PCNT unit
|
||||
*
|
||||
* @param pcnt_unit PCNT unit number
|
||||
*
|
||||
@ -219,10 +236,10 @@ esp_err_t pcnt_get_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16
|
||||
*
|
||||
* @param fn Interrupt handler function.
|
||||
* @param arg Parameter for handler function
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
|
||||
* be returned here.
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
|
||||
* be returned here.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
@ -236,11 +253,9 @@ esp_err_t pcnt_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags,
|
||||
* @param unit PCNT unit number
|
||||
* @param channel PCNT channel number
|
||||
* @param pulse_io Pulse signal input GPIO
|
||||
* @note
|
||||
* Set to PCNT_PIN_NOT_USED if unused.
|
||||
* @param ctrl_io Control signal input GPIO
|
||||
* @note
|
||||
* Set to PCNT_PIN_NOT_USED if unused.
|
||||
*
|
||||
* @note Set the signal input to PCNT_PIN_NOT_USED if unused.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
@ -329,8 +344,8 @@ esp_err_t pcnt_set_mode(pcnt_unit_t unit, pcnt_channel_t channel,
|
||||
* .pulse_gpio_num = 4, //set gpio4 as pulse input gpio
|
||||
* .ctrl_gpio_num = 5, //set gpio5 as control gpio
|
||||
* .channel = PCNT_CHANNEL_0, //use unit 0 channel 0
|
||||
* .lctrl_mode = PCNT_MODE_REVERSE, //when control signal is low ,reverse the primary counter mode(inc->dec/dec->inc)
|
||||
* .hctrl_mode = PCNT_MODE_KEEP, //when control signal is high,keep the primary counter mode
|
||||
* .lctrl_mode = PCNT_MODE_REVERSE, //when control signal is low, reverse the primary counter mode(inc->dec/dec->inc)
|
||||
* .hctrl_mode = PCNT_MODE_KEEP, //when control signal is high, keep the primary counter mode
|
||||
* .pos_mode = PCNT_COUNT_INC, //increment the counter
|
||||
* .neg_mode = PCNT_COUNT_DIS, //keep the counter value
|
||||
* .counter_h_lim = 10,
|
||||
|
@ -49,6 +49,10 @@ typedef enum {
|
||||
PERIPH_SDIO_SLAVE_MODULE,
|
||||
PERIPH_CAN_MODULE,
|
||||
PERIPH_EMAC_MODULE,
|
||||
PERIPH_RNG_MODULE,
|
||||
PERIPH_WIFI_MODULE,
|
||||
PERIPH_BT_MODULE,
|
||||
PERIPH_WIFI_BT_COMMON_MODULE,
|
||||
} periph_module_t;
|
||||
|
||||
/**
|
||||
@ -56,6 +60,7 @@ typedef enum {
|
||||
*
|
||||
* @param[in] periph : Peripheral module name
|
||||
*
|
||||
* Clock for the module will be ungated, and reset de-asserted.
|
||||
*
|
||||
* @return NULL
|
||||
*
|
||||
@ -67,12 +72,28 @@ void periph_module_enable(periph_module_t periph);
|
||||
*
|
||||
* @param[in] periph : Peripheral module name
|
||||
*
|
||||
* Clock for the module will be gated, reset asserted.
|
||||
*
|
||||
* @return NULL
|
||||
*
|
||||
*/
|
||||
void periph_module_disable(periph_module_t periph);
|
||||
|
||||
/**
|
||||
* @brief reset peripheral module
|
||||
*
|
||||
* @param[in] periph : Peripheral module name
|
||||
*
|
||||
* Reset will asserted then de-assrted for the peripheral.
|
||||
*
|
||||
* Calling this function does not enable or disable the clock for the module.
|
||||
*
|
||||
* @return NULL
|
||||
*
|
||||
*/
|
||||
void periph_module_reset(periph_module_t periph);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -102,6 +102,7 @@ typedef struct {
|
||||
#define SCF_RSP_R6 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
|
||||
#define SCF_RSP_R7 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
|
||||
esp_err_t error; /*!< error returned from transfer */
|
||||
int timeout_ms; /*!< response timeout, in milliseconds */
|
||||
} sdmmc_command_t;
|
||||
|
||||
/**
|
||||
@ -127,6 +128,7 @@ typedef struct {
|
||||
esp_err_t (*set_card_clk)(int slot, uint32_t freq_khz); /*!< host function to set card clock frequency */
|
||||
esp_err_t (*do_transaction)(int slot, sdmmc_command_t* cmdinfo); /*!< host function to do a transaction */
|
||||
esp_err_t (*deinit)(void); /*!< host function to deinitialize the driver */
|
||||
int command_timeout_ms; /*!< timeout, in milliseconds, of a single command. Set to 0 to use the default value. */
|
||||
} sdmmc_host_t;
|
||||
|
||||
/**
|
||||
|
@ -53,6 +53,7 @@ typedef struct {
|
||||
*/
|
||||
struct spi_slave_transaction_t {
|
||||
size_t length; ///< Total data length, in bits
|
||||
size_t trans_len; ///< Transaction data length, in bits
|
||||
const void *tx_buffer; ///< Pointer to transmit buffer, or NULL for no MOSI phase
|
||||
void *rx_buffer; ///< Pointer to receive buffer, or NULL for no MISO phase
|
||||
void *user; ///< User-defined variable. Can be used to store eg transaction ID.
|
||||
|
@ -26,7 +26,8 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define TIMER_BASE_CLK (APB_CLK_FREQ)
|
||||
#define TIMER_BASE_CLK (APB_CLK_FREQ) /*!< Frequency of the clock on the input of the timer groups */
|
||||
|
||||
/**
|
||||
* @brief Selects a Timer-Group out of 2 available groups
|
||||
*/
|
||||
@ -90,15 +91,15 @@ typedef enum {
|
||||
} timer_autoreload_t;
|
||||
|
||||
/**
|
||||
* @brief timer configure struct
|
||||
* @brief Data structure with timer's configuration settings
|
||||
*/
|
||||
typedef struct {
|
||||
bool alarm_en; /*!< Timer alarm enable */
|
||||
bool counter_en; /*!< Counter enable */
|
||||
bool alarm_en; /*!< Timer alarm enable */
|
||||
bool counter_en; /*!< Counter enable */
|
||||
timer_intr_mode_t intr_type; /*!< Interrupt mode */
|
||||
timer_count_dir_t counter_dir; /*!< Counter direction */
|
||||
bool auto_reload; /*!< Timer auto-reload */
|
||||
uint16_t divider; /*!< Counter clock divider*/
|
||||
bool auto_reload; /*!< Timer auto-reload */
|
||||
uint32_t divider; /*!< Counter clock divider. The divider's range is from from 2 to 65536. */
|
||||
} timer_config_t;
|
||||
|
||||
|
||||
@ -202,13 +203,13 @@ esp_err_t timer_set_auto_reload(timer_group_t group_num, timer_idx_t timer_num,
|
||||
*
|
||||
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
|
||||
* @param divider Timer clock divider value.
|
||||
* @param divider Timer clock divider value. The divider's range is from from 2 to 65536.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_set_divider(timer_group_t group_num, timer_idx_t timer_num, uint16_t divider);
|
||||
esp_err_t timer_set_divider(timer_group_t group_num, timer_idx_t timer_num, uint32_t divider);
|
||||
|
||||
/**
|
||||
* @brief Set timer alarm value.
|
||||
@ -249,27 +250,23 @@ esp_err_t timer_get_alarm_value(timer_group_t group_num, timer_idx_t timer_num,
|
||||
*/
|
||||
esp_err_t timer_set_alarm(timer_group_t group_num, timer_idx_t timer_num, timer_alarm_t alarm_en);
|
||||
|
||||
|
||||
/**
|
||||
* @brief register Timer interrupt handler, the handler is an ISR.
|
||||
* The handler will be attached to the same CPU core that this function is running on.
|
||||
* @brief Register Timer interrupt handler, the handler is an ISR.
|
||||
* The handler will be attached to the same CPU core that this function is running on.
|
||||
*
|
||||
* @param group_num Timer group number
|
||||
* @param timer_num Timer index of timer group
|
||||
* @param fn Interrupt handler function.
|
||||
* @note
|
||||
* In case the this is called with the INIRAM flag, code inside the handler function can
|
||||
* only call functions in IRAM, so it cannot call other timer APIs.
|
||||
* Use direct register access to access timers from inside the ISR in this case.
|
||||
*
|
||||
* @param arg Parameter for handler function
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
|
||||
* be returned here.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Function pointer error.
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
|
||||
* be returned here.
|
||||
*
|
||||
* @note If the intr_alloc_flags value ESP_INTR_FLAG_IRAM is set,
|
||||
* the handler function must be declared with IRAM_ATTR attribute
|
||||
* and can only call functions in IRAM or ROM. It cannot call other timer APIs.
|
||||
* Use direct register access to configure timers from inside the ISR in this case.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
|
@ -31,8 +31,8 @@ typedef enum {
|
||||
TOUCH_PAD_NUM5, /*!< Touch pad channel 5 is GPIO12*/
|
||||
TOUCH_PAD_NUM6, /*!< Touch pad channel 6 is GPIO14*/
|
||||
TOUCH_PAD_NUM7, /*!< Touch pad channel 7 is GPIO27*/
|
||||
TOUCH_PAD_NUM8, /*!< Touch pad channel 8 is GPIO32*/
|
||||
TOUCH_PAD_NUM9, /*!< Touch pad channel 9 is GPIO33*/
|
||||
TOUCH_PAD_NUM8, /*!< Touch pad channel 8 is GPIO33*/
|
||||
TOUCH_PAD_NUM9, /*!< Touch pad channel 9 is GPIO32*/
|
||||
TOUCH_PAD_MAX,
|
||||
} touch_pad_t;
|
||||
|
||||
|
@ -35,7 +35,7 @@ extern "C" {
|
||||
#include "soc/uart_channel.h"
|
||||
|
||||
#define UART_FIFO_LEN (128) /*!< Length of the hardware FIFO buffers */
|
||||
#define UART_INTR_MASK 0x1ff /*!< mask of all UART interrupts */
|
||||
#define UART_INTR_MASK 0x1ff /*!< Mask of all UART interrupts */
|
||||
#define UART_LINE_INV_MASK (0x3f << 19) /*!< TBD */
|
||||
#define UART_BITRATE_MAX 5000000 /*!< Max bit rate supported by UART */
|
||||
#define UART_PIN_NO_CHANGE (-1) /*!< Constant for uart_set_pin function which indicates that UART pin should not be changed */
|
||||
@ -73,7 +73,7 @@ typedef enum {
|
||||
typedef enum {
|
||||
UART_NUM_0 = 0x0, /*!< UART base address 0x3ff40000*/
|
||||
UART_NUM_1 = 0x1, /*!< UART base address 0x3ff50000*/
|
||||
UART_NUM_2 = 0x2, /*!< UART base address 0x3ff6E000*/
|
||||
UART_NUM_2 = 0x2, /*!< UART base address 0x3ff6e000*/
|
||||
UART_NUM_MAX,
|
||||
} uart_port_t;
|
||||
|
||||
@ -81,7 +81,7 @@ typedef enum {
|
||||
* @brief UART parity constants
|
||||
*/
|
||||
typedef enum {
|
||||
UART_PARITY_DISABLE = 0x0, /*!< Disable UART parity*/
|
||||
UART_PARITY_DISABLE = 0x0, /*!< Disable UART parity*/
|
||||
UART_PARITY_EVEN = 0x2, /*!< Enable UART even parity*/
|
||||
UART_PARITY_ODD = 0x3 /*!< Enable UART odd parity*/
|
||||
} uart_parity_t;
|
||||
@ -101,12 +101,13 @@ typedef enum {
|
||||
* @brief UART configuration parameters for uart_param_config function
|
||||
*/
|
||||
typedef struct {
|
||||
int baud_rate; /*!< UART baudrate*/
|
||||
int baud_rate; /*!< UART baud rate*/
|
||||
uart_word_length_t data_bits; /*!< UART byte size*/
|
||||
uart_parity_t parity; /*!< UART parity mode*/
|
||||
uart_stop_bits_t stop_bits; /*!< UART stop bits*/
|
||||
uart_hw_flowcontrol_t flow_ctrl; /*!< UART HW flow control mode(cts/rts)*/
|
||||
uint8_t rx_flow_ctrl_thresh ; /*!< UART HW RTS threshold*/
|
||||
uart_hw_flowcontrol_t flow_ctrl; /*!< UART HW flow control mode (cts/rts)*/
|
||||
uint8_t rx_flow_ctrl_thresh; /*!< UART HW RTS threshold*/
|
||||
bool use_ref_tick; /*!< Set to true if UART should be clocked from REF_TICK */
|
||||
} uart_config_t;
|
||||
|
||||
/**
|
||||
@ -114,13 +115,13 @@ typedef struct {
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t intr_enable_mask; /*!< UART interrupt enable mask, choose from UART_XXXX_INT_ENA_M under UART_INT_ENA_REG(i), connect with bit-or operator*/
|
||||
uint8_t rx_timeout_thresh; /*!< UART timeout interrupt threshold(unit: time of sending one byte)*/
|
||||
uint8_t rx_timeout_thresh; /*!< UART timeout interrupt threshold (unit: time of sending one byte)*/
|
||||
uint8_t txfifo_empty_intr_thresh; /*!< UART TX empty interrupt threshold.*/
|
||||
uint8_t rxfifo_full_thresh; /*!< UART RX full interrupt threshold.*/
|
||||
} uart_intr_config_t;
|
||||
|
||||
/**
|
||||
* @brief UART event types used in the ringbuffer
|
||||
* @brief UART event types used in the ring buffer
|
||||
*/
|
||||
typedef enum {
|
||||
UART_DATA, /*!< UART data event*/
|
||||
@ -181,7 +182,7 @@ esp_err_t uart_get_word_length(uart_port_t uart_num, uart_word_length_t* data_bi
|
||||
esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bits);
|
||||
|
||||
/**
|
||||
* @brief Set UART stop bits.
|
||||
* @brief Get UART stop bits.
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param stop_bits Pointer to accept value of UART stop bits.
|
||||
@ -193,7 +194,7 @@ esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bits);
|
||||
esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t* stop_bits);
|
||||
|
||||
/**
|
||||
* @brief Set UART parity.
|
||||
* @brief Set UART parity mode.
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param parity_mode the enum of uart parity configuration
|
||||
@ -230,7 +231,7 @@ esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode);
|
||||
esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baudrate);
|
||||
|
||||
/**
|
||||
* @brief Get UART bit-rate.
|
||||
* @brief Get UART baud rate.
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param baudrate Pointer to accept value of UART baud rate
|
||||
@ -247,7 +248,9 @@ esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate);
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param inverse_mask Choose the wires that need to be inverted.
|
||||
* Inverse_mask should be chosen from UART_INVERSE_RXD/UART_INVERSE_TXD/UART_INVERSE_RTS/UART_INVERSE_CTS, combine with OR operation.
|
||||
* Inverse_mask should be chosen from
|
||||
UART_INVERSE_RXD / UART_INVERSE_TXD / UART_INVERSE_RTS / UART_INVERSE_CTS,
|
||||
combined with OR operation.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
@ -260,8 +263,8 @@ esp_err_t uart_set_line_inverse(uart_port_t uart_num, uint32_t inverse_mask);
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param flow_ctrl Hardware flow control mode
|
||||
* @param rx_thresh Threshold of Hardware RX flow control(0 ~ UART_FIFO_LEN).
|
||||
* Only when UART_HW_FLOWCTRL_RTS is set, will the rx_thresh value be set.
|
||||
* @param rx_thresh Threshold of Hardware RX flow control (0 ~ UART_FIFO_LEN).
|
||||
* Only when UART_HW_FLOWCTRL_RTS is set, will the rx_thresh value be set.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
@ -298,9 +301,9 @@ esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t* flo
|
||||
/**
|
||||
* @brief Clear UART interrupt status
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param clr_mask Bit mask of the status that to be cleared.
|
||||
* enable_mask should be chosen from the fields of register UART_INT_CLR_REG.
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param clr_mask Bit mask of the interrupt status to be cleared.
|
||||
* The bit mask should be composed from the fields of register UART_INT_CLR_REG.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
@ -311,9 +314,9 @@ esp_err_t uart_clear_intr_status(uart_port_t uart_num, uint32_t clr_mask);
|
||||
/**
|
||||
* @brief Set UART interrupt enable
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param enable_mask Bit mask of the enable bits.
|
||||
* enable_mask should be chosen from the fields of register UART_INT_ENA_REG.
|
||||
* The bit mask should be composed from the fields of register UART_INT_ENA_REG.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
@ -324,9 +327,9 @@ esp_err_t uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask);
|
||||
/**
|
||||
* @brief Clear UART interrupt enable bits
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param disable_mask Bit mask of the disable bits.
|
||||
* disable_mask should be chosen from the fields of register UART_INT_ENA_REG.
|
||||
* The bit mask should be composed from the fields of register UART_INT_ENA_REG.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
@ -334,9 +337,8 @@ esp_err_t uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask);
|
||||
*/
|
||||
esp_err_t uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable UART RX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)
|
||||
* @brief Enable UART RX interrupt (RX_FULL & RX_TIMEOUT INTERRUPT)
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
*
|
||||
@ -347,7 +349,7 @@ esp_err_t uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask);
|
||||
esp_err_t uart_enable_rx_intr(uart_port_t uart_num);
|
||||
|
||||
/**
|
||||
* @brief Disable UART RX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)
|
||||
* @brief Disable UART RX interrupt (RX_FULL & RX_TIMEOUT INTERRUPT)
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
*
|
||||
@ -358,7 +360,7 @@ esp_err_t uart_enable_rx_intr(uart_port_t uart_num);
|
||||
esp_err_t uart_disable_rx_intr(uart_port_t uart_num);
|
||||
|
||||
/**
|
||||
* @brief Disable UART TX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)
|
||||
* @brief Disable UART TX interrupt (TX_FULL & TX_TIMEOUT INTERRUPT)
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
*
|
||||
@ -369,7 +371,7 @@ esp_err_t uart_disable_rx_intr(uart_port_t uart_num);
|
||||
esp_err_t uart_disable_tx_intr(uart_port_t uart_num);
|
||||
|
||||
/**
|
||||
* @brief Enable UART TX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT)
|
||||
* @brief Enable UART TX interrupt (TX_FULL & TX_TIMEOUT INTERRUPT)
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param enable 1: enable; 0: disable
|
||||
@ -382,15 +384,15 @@ esp_err_t uart_disable_tx_intr(uart_port_t uart_num);
|
||||
esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh);
|
||||
|
||||
/**
|
||||
* @brief register UART interrupt handler(ISR).
|
||||
* @brief Register UART interrupt handler (ISR).
|
||||
*
|
||||
* @note UART ISR handler will be attached to the same CPU core that this function is running on.
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param fn Interrupt handler function.
|
||||
* @param arg parameter for handler function
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
|
||||
* be returned here.
|
||||
*
|
||||
@ -400,7 +402,6 @@ esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh);
|
||||
*/
|
||||
esp_err_t uart_isr_register(uart_port_t uart_num, void (*fn)(void*), void * arg, int intr_alloc_flags, uart_isr_handle_t *handle);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Free UART interrupt handler registered by uart_isr_register. Must be called on the same core as
|
||||
* uart_isr_register was called.
|
||||
@ -417,13 +418,16 @@ esp_err_t uart_isr_free(uart_port_t uart_num);
|
||||
* @brief Set UART pin number
|
||||
*
|
||||
* @note Internal signal can be output to multiple GPIO pads.
|
||||
* Only one GPIO pad can connect with input signal.
|
||||
* Only one GPIO pad can connect with input signal.
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param tx_io_num UART TX pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.
|
||||
* @param rx_io_num UART RX pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.
|
||||
* @param rts_io_num UART RTS pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.
|
||||
* @param cts_io_num UART CTS pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin.
|
||||
* @note Instead of GPIO number a macro 'UART_PIN_NO_CHANGE' may be provided
|
||||
to keep the currently allocated pin.
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param tx_io_num UART TX pin GPIO number.
|
||||
* @param rx_io_num UART RX pin GPIO number.
|
||||
* @param rts_io_num UART RTS pin GPIO number.
|
||||
* @param cts_io_num UART CTS pin GPIO number.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
@ -432,11 +436,11 @@ esp_err_t uart_isr_free(uart_port_t uart_num);
|
||||
esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num);
|
||||
|
||||
/**
|
||||
* @brief UART set RTS level (before inverse)
|
||||
* UART rx hardware flow control should not be set.
|
||||
* @brief Manually set the UART RTS pin level.
|
||||
* @note UART must be configured with hardware flow control disabled.
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param level 1: RTS output low(active); 0: RTS output high(block)
|
||||
* @param level 1: RTS output low (active); 0: RTS output high (block)
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
@ -445,9 +449,9 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r
|
||||
esp_err_t uart_set_rts(uart_port_t uart_num, int level);
|
||||
|
||||
/**
|
||||
* @brief UART set DTR level (before inverse)
|
||||
* @brief Manually set the UART DTR pin level.
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param level 1: DTR output low; 0: DTR output high
|
||||
*
|
||||
* @return
|
||||
@ -457,9 +461,22 @@ esp_err_t uart_set_rts(uart_port_t uart_num, int level);
|
||||
esp_err_t uart_set_dtr(uart_port_t uart_num, int level);
|
||||
|
||||
/**
|
||||
* @brief UART parameter configure
|
||||
* @brief Set UART idle interval after tx FIFO is empty
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param idle_num idle interval after tx FIFO is empty(unit: the time it takes to send one bit
|
||||
* under current baudrate)
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Parameter error
|
||||
*/
|
||||
esp_err_t uart_set_tx_idle_num(uart_port_t uart_num, uint16_t idle_num);
|
||||
|
||||
/**
|
||||
* @brief Set UART configuration parameters.
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param uart_config UART parameter settings
|
||||
*
|
||||
* @return
|
||||
@ -469,9 +486,9 @@ esp_err_t uart_set_dtr(uart_port_t uart_num, int level);
|
||||
esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_config);
|
||||
|
||||
/**
|
||||
* @brief UART interrupt configure
|
||||
* @brief Configure UART interrupts.
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param intr_conf UART interrupt settings
|
||||
*
|
||||
* @return
|
||||
@ -485,18 +502,18 @@ esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_
|
||||
*
|
||||
* UART ISR handler will be attached to the same CPU core that this function is running on.
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param rx_buffer_size UART RX ring buffer size, rx_buffer_size should be greater than UART_FIFO_LEN.
|
||||
* @param tx_buffer_size UART TX ring buffer size.
|
||||
* If set to zero, driver will not use TX buffer, TX function will block task until all data have been sent out..
|
||||
* @note tx_buffer_size should be greater than UART_FIFO_LEN.
|
||||
* @note Rx_buffer_size should be greater than UART_FIFO_LEN. Tx_buffer_size should be either zero or greater than UART_FIFO_LEN.
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param rx_buffer_size UART RX ring buffer size.
|
||||
* @param tx_buffer_size UART TX ring buffer size.
|
||||
* If set to zero, driver will not use TX buffer, TX function will block task until all data have been sent out.
|
||||
* @param queue_size UART event queue size/depth.
|
||||
* @param uart_queue UART event queue handle (out param). On success, a new queue handle is written here to provide
|
||||
* access to UART events. If set to NULL, driver will not use an event queue.
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info. Do not set ESP_INTR_FLAG_IRAM here
|
||||
* (the driver's ISR handler is not located in IRAM)
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info. Do not set ESP_INTR_FLAG_IRAM here
|
||||
* (the driver's ISR handler is not located in IRAM)
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
@ -507,7 +524,7 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b
|
||||
/**
|
||||
* @brief Uninstall UART driver.
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
@ -516,9 +533,9 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b
|
||||
esp_err_t uart_driver_delete(uart_port_t uart_num);
|
||||
|
||||
/**
|
||||
* @brief Wait UART TX FIFO empty
|
||||
* @brief Wait until UART TX FIFO is empty.
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param ticks_to_wait Timeout, count in RTOS ticks
|
||||
*
|
||||
* @return
|
||||
@ -531,59 +548,59 @@ esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait);
|
||||
/**
|
||||
* @brief Send data to the UART port from a given buffer and length.
|
||||
*
|
||||
* This function will not wait for the space in TX FIFO, just fill the TX FIFO and return when the FIFO is full.
|
||||
* This function will not wait for enough space in TX FIFO. It will just fill the available TX FIFO and return when the FIFO is full.
|
||||
* @note This function should only be used when UART TX buffer is not enabled.
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param buffer data buffer address
|
||||
* @param len data length to send
|
||||
* @param buffer data buffer address
|
||||
* @param len data length to send
|
||||
*
|
||||
* @return
|
||||
* - (-1) Parameter error
|
||||
* - OTHERS(>=0) The number of data that pushed to the TX FIFO
|
||||
* - OTHERS (>=0) The number of bytes pushed to the TX FIFO
|
||||
*/
|
||||
int uart_tx_chars(uart_port_t uart_num, const char* buffer, uint32_t len);
|
||||
|
||||
/**
|
||||
* @brief Send data to the UART port from a given buffer and length,
|
||||
*
|
||||
* If parameter tx_buffer_size is set to zero:
|
||||
* If the UART driver's parameter 'tx_buffer_size' is set to zero:
|
||||
* This function will not return until all the data have been sent out, or at least pushed into TX FIFO.
|
||||
*
|
||||
* Otherwise, if tx_buffer_size > 0, this function will return after copying all the data to tx ringbuffer,
|
||||
* then, UART ISR will move data from ring buffer to TX FIFO gradually.
|
||||
* Otherwise, if the 'tx_buffer_size' > 0, this function will return after copying all the data to tx ring buffer,
|
||||
* UART ISR will then move data from the ring buffer to TX FIFO gradually.
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param src data buffer address
|
||||
* @param size data length to send
|
||||
* @param src data buffer address
|
||||
* @param size data length to send
|
||||
*
|
||||
* @return
|
||||
* - (-1) Parameter error
|
||||
* - OTHERS(>=0) The number of data that pushed to the TX FIFO
|
||||
* - OTHERS (>=0) The number of bytes pushed to the TX FIFO
|
||||
*/
|
||||
int uart_write_bytes(uart_port_t uart_num, const char* src, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Send data to the UART port from a given buffer and length,
|
||||
* @brief Send data to the UART port from a given buffer and length.
|
||||
*
|
||||
* If parameter tx_buffer_size is set to zero:
|
||||
* If the UART driver's parameter 'tx_buffer_size' is set to zero:
|
||||
* This function will not return until all the data and the break signal have been sent out.
|
||||
* After all data send out, send a break signal.
|
||||
* After all data is sent out, send a break signal.
|
||||
*
|
||||
* Otherwise, if tx_buffer_size > 0, this function will return after copying all the data to tx ringbuffer,
|
||||
* then, UART ISR will move data from ring buffer to TX FIFO gradually.
|
||||
* After all data send out, send a break signal.
|
||||
* Otherwise, if the 'tx_buffer_size' > 0, this function will return after copying all the data to tx ring buffer,
|
||||
* UART ISR will then move data from the ring buffer to TX FIFO gradually.
|
||||
* After all data sent out, send a break signal.
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param src data buffer address
|
||||
* @param size data length to send
|
||||
* @param brk_len break signal length (unit: time of one data bit at current_baudrate)
|
||||
* @param brk_len break signal length (unit: the time it takes to send a complete byte
|
||||
including start, stop and parity bits at current_baudrate)
|
||||
*
|
||||
* @return
|
||||
* - (-1) Parameter error
|
||||
* - OTHERS(>=0) The number of data that pushed to the TX FIFO
|
||||
* - OTHERS (>=0) The number of bytes pushed to the TX FIFO
|
||||
*/
|
||||
|
||||
int uart_write_bytes_with_break(uart_port_t uart_num, const char* src, size_t size, int brk_len);
|
||||
|
||||
/**
|
||||
@ -596,7 +613,7 @@ int uart_write_bytes_with_break(uart_port_t uart_num, const char* src, size_t si
|
||||
*
|
||||
* @return
|
||||
* - (-1) Error
|
||||
* - Others return a char data from uart fifo.
|
||||
* - OTHERS (>=0) The number of bytes read from UART FIFO
|
||||
*/
|
||||
int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickType_t ticks_to_wait);
|
||||
|
||||
@ -612,10 +629,10 @@ int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickTyp
|
||||
esp_err_t uart_flush(uart_port_t uart_num);
|
||||
|
||||
/**
|
||||
* @brief UART get RX ring buffer cached data length
|
||||
* @brief UART get RX ring buffer cached data length
|
||||
*
|
||||
* @param uart_num UART port number.
|
||||
* @param size Pointer of size_t to accept cached data length
|
||||
* @param uart_num UART port number.
|
||||
* @param size Pointer of size_t to accept cached data length
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
@ -624,11 +641,11 @@ esp_err_t uart_flush(uart_port_t uart_num);
|
||||
esp_err_t uart_get_buffered_data_len(uart_port_t uart_num, size_t* size);
|
||||
|
||||
/**
|
||||
* @brief UART disable pattern detect function.
|
||||
* Designed for applications like 'AT commands'.
|
||||
* When the hardware detect a series of one same character, the interrupt will be triggered.
|
||||
* @brief UART disable pattern detect function.
|
||||
* Designed for applications like 'AT commands'.
|
||||
* When the hardware detects a series of one same character, the interrupt will be triggered.
|
||||
*
|
||||
* @param uart_num UART port number.
|
||||
* @param uart_num UART port number.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
@ -637,183 +654,22 @@ esp_err_t uart_get_buffered_data_len(uart_port_t uart_num, size_t* size);
|
||||
esp_err_t uart_disable_pattern_det_intr(uart_port_t uart_num);
|
||||
|
||||
/**
|
||||
* @brief UART enable pattern detect function.
|
||||
* Designed for applications like 'AT commands'.
|
||||
* When the hardware detect a series of one same character, the interrupt will be triggered.
|
||||
* @brief UART enable pattern detect function.
|
||||
* Designed for applications like 'AT commands'.
|
||||
* When the hardware detect a series of one same character, the interrupt will be triggered.
|
||||
*
|
||||
* @param uart_num UART port number.
|
||||
* @param pattern_chr character of the pattern
|
||||
* @param chr_num number of the character, 8bit value.
|
||||
* @param chr_tout timeout of the interval between each pattern characters, 24bit value, unit is APB(80Mhz) clock cycle.
|
||||
* @param post_idle idle time after the last pattern character, 24bit value, unit is APB(80Mhz) clock cycle.
|
||||
* @param pre_idle idle time before the first pattern character, 24bit value, unit is APB(80Mhz) clock cycle.
|
||||
* @param chr_tout timeout of the interval between each pattern characters, 24bit value, unit is APB (80Mhz) clock cycle.
|
||||
* @param post_idle idle time after the last pattern character, 24bit value, unit is APB (80Mhz) clock cycle.
|
||||
* @param pre_idle idle time before the first pattern character, 24bit value, unit is APB (80Mhz) clock cycle.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Parameter error
|
||||
*/
|
||||
esp_err_t uart_enable_pattern_det_intr(uart_port_t uart_num, char pattern_chr, uint8_t chr_num, int chr_tout, int post_idle, int pre_idle);
|
||||
/***************************EXAMPLE**********************************
|
||||
*
|
||||
*
|
||||
* ----------------EXAMPLE OF UART SETTING ---------------------
|
||||
* @code{c}
|
||||
* //1. Setup UART
|
||||
* #include "freertos/queue.h"
|
||||
* //a. Set UART parameter
|
||||
* int uart_num = 0; //uart port number
|
||||
* uart_config_t uart_config = {
|
||||
* .baud_rate = 115200, //baudrate
|
||||
* .data_bits = UART_DATA_8_BITS, //data bit mode
|
||||
* .parity = UART_PARITY_DISABLE, //parity mode
|
||||
* .stop_bits = UART_STOP_BITS_1, //stop bit mode
|
||||
* .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, //hardware flow control(cts/rts)
|
||||
* .rx_flow_ctrl_thresh = 120, //flow control threshold
|
||||
* };
|
||||
* uart_param_config(uart_num, &uart_config);
|
||||
* //b1. Setup UART driver(with UART queue)
|
||||
* QueueHandle_t uart_queue;
|
||||
* //parameters here are just an example, tx buffer size is 2048
|
||||
* uart_driver_install(uart_num, 1024 * 2, 1024 * 2, 10, &uart_queue, 0);
|
||||
* //b2. Setup UART driver(without UART queue)
|
||||
* //parameters here are just an example, tx buffer size is 0
|
||||
* uart_driver_install(uart_num, 1024 * 2, 0, 10, NULL, 0);
|
||||
*@endcode
|
||||
*-----------------------------------------------------------------------------*
|
||||
* @code{c}
|
||||
* //2. Set UART pin
|
||||
* //set UART pin, not needed if use default pins.
|
||||
* uart_set_pin(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, 15, 13);
|
||||
* @endcode
|
||||
*-----------------------------------------------------------------------------*
|
||||
* @code{c}
|
||||
* //3. Read data from UART.
|
||||
* uint8_t data[128];
|
||||
* int length = 0;
|
||||
* length = uart_read_bytes(uart_num, data, sizeof(data), 100);
|
||||
* @endcode
|
||||
*-----------------------------------------------------------------------------*
|
||||
* @code{c}
|
||||
* //4. Write data to UART.
|
||||
* char* test_str = "This is a test string.\n"
|
||||
* uart_write_bytes(uart_num, (const char*)test_str, strlen(test_str));
|
||||
* @endcode
|
||||
*-----------------------------------------------------------------------------*
|
||||
* @code{c}
|
||||
* //5. Write data to UART, end with a break signal.
|
||||
* uart_write_bytes_with_break(0, "test break\n",strlen("test break\n"), 100);
|
||||
* @endcode
|
||||
*-----------------------------------------------------------------------------*
|
||||
* @code{c}
|
||||
* //6. an example of echo test with hardware flow control on UART1
|
||||
* void uart_loop_back_test()
|
||||
* {
|
||||
* int uart_num = 1;
|
||||
* uart_config_t uart_config = {
|
||||
* .baud_rate = 115200,
|
||||
* .data_bits = UART_DATA_8_BITS,
|
||||
* .parity = UART_PARITY_DISABLE,
|
||||
* .stop_bits = UART_STOP_BITS_1,
|
||||
* .flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS,
|
||||
* .rx_flow_ctrl_thresh = 122,
|
||||
* };
|
||||
* //Configure UART1 parameters
|
||||
* uart_param_config(uart_num, &uart_config);
|
||||
* //Set UART1 pins(TX: IO16, RX: IO17, RTS: IO18, CTS: IO19)
|
||||
* uart_set_pin(uart_num, 16, 17, 18, 19);
|
||||
* //Install UART driver( We don't need an event queue here)
|
||||
* uart_driver_install(uart_num, 1024 * 2, 1024*4, 0, NULL, 0);
|
||||
* uint8_t data[1000];
|
||||
* while(1) {
|
||||
* //Read data from UART
|
||||
* int len = uart_read_bytes(uart_num, data, sizeof(data), 10);
|
||||
* //Write data back to UART
|
||||
* uart_write_bytes(uart_num, (const char*)data, len);
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
*-----------------------------------------------------------------------------*
|
||||
* @code{c}
|
||||
* //7. An example of using UART event queue on UART0.
|
||||
* #include "freertos/queue.h"
|
||||
* //A queue to handle UART event.
|
||||
* QueueHandle_t uart0_queue;
|
||||
* static const char *TAG = "uart_example";
|
||||
* void uart_task(void *pvParameters)
|
||||
* {
|
||||
* int uart_num = (int)pvParameters;
|
||||
* uart_event_t event;
|
||||
* size_t size = 1024;
|
||||
* uint8_t* dtmp = (uint8_t*)malloc(size);
|
||||
* for(;;) {
|
||||
* //Waiting for UART event.
|
||||
* if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
|
||||
* ESP_LOGI(TAG, "uart[%d] event:", uart_num);
|
||||
* switch(event.type) {
|
||||
* memset(dtmp, 0, size);
|
||||
* //Event of UART receving data
|
||||
* case UART_DATA:
|
||||
* ESP_LOGI(TAG,"data, len: %d", event.size);
|
||||
* int len = uart_read_bytes(uart_num, dtmp, event.size, 10);
|
||||
* ESP_LOGI(TAG, "uart read: %d", len);
|
||||
* break;
|
||||
* //Event of HW FIFO overflow detected
|
||||
* case UART_FIFO_OVF:
|
||||
* ESP_LOGI(TAG, "hw fifo overflow\n");
|
||||
* break;
|
||||
* //Event of UART ring buffer full
|
||||
* case UART_BUFFER_FULL:
|
||||
* ESP_LOGI(TAG, "ring buffer full\n");
|
||||
* break;
|
||||
* //Event of UART RX break detected
|
||||
* case UART_BREAK:
|
||||
* ESP_LOGI(TAG, "uart rx break\n");
|
||||
* break;
|
||||
* //Event of UART parity check error
|
||||
* case UART_PARITY_ERR:
|
||||
* ESP_LOGI(TAG, "uart parity error\n");
|
||||
* break;
|
||||
* //Event of UART frame error
|
||||
* case UART_FRAME_ERR:
|
||||
* ESP_LOGI(TAG, "uart frame error\n");
|
||||
* break;
|
||||
* //Others
|
||||
* default:
|
||||
* ESP_LOGI(TAG, "uart event type: %d\n", event.type);
|
||||
* break;
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* free(dtmp);
|
||||
* dtmp = NULL;
|
||||
* vTaskDelete(NULL);
|
||||
* }
|
||||
*
|
||||
* void uart_queue_test()
|
||||
* {
|
||||
* int uart_num = 0;
|
||||
* uart_config_t uart_config = {
|
||||
* .baud_rate = 115200,
|
||||
* .data_bits = UART_DATA_8_BITS,
|
||||
* .parity = UART_PARITY_DISABLE,
|
||||
* .stop_bits = UART_STOP_BITS_1,
|
||||
* .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
* .rx_flow_ctrl_thresh = 122,
|
||||
* };
|
||||
* //Set UART parameters
|
||||
* uart_param_config(uart_num, &uart_config);
|
||||
* //Set UART pins,(-1: default pin, no change.)
|
||||
* uart_set_pin(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
||||
* //Set UART log level
|
||||
* esp_log_level_set(TAG, ESP_LOG_INFO);
|
||||
* //Install UART driver, and get the queue.
|
||||
* uart_driver_install(uart_num, 1024 * 2, 1024*4, 10, &uart0_queue, 0);
|
||||
* //Create a task to handler UART event from ISR
|
||||
* xTaskCreate(uart_task, "uTask", 1024, (void*)uart_num, 10, NULL);
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
***************************END OF EXAMPLE**********************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ static portMUX_TYPE ledc_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
typedef struct {
|
||||
uint16_t speed_mode;
|
||||
uint16_t direction;
|
||||
int target_duty;
|
||||
uint32_t target_duty;
|
||||
int cycle_num;
|
||||
int scale;
|
||||
ledc_fade_mode_t mode;
|
||||
@ -352,9 +352,9 @@ esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int ledc_get_duty(ledc_mode_t speed_mode, ledc_channel_t channel)
|
||||
uint32_t ledc_get_duty(ledc_mode_t speed_mode, ledc_channel_t channel)
|
||||
{
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, (-1));
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, (LEDC_ERR_DUTY));
|
||||
uint32_t duty = (LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> 4);
|
||||
return duty;
|
||||
}
|
||||
@ -418,7 +418,7 @@ void IRAM_ATTR ledc_fade_isr(void* arg)
|
||||
//fade object not initialized yet.
|
||||
continue;
|
||||
}
|
||||
int duty_cur = LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM;
|
||||
uint32_t duty_cur = LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM;
|
||||
if (duty_cur == s_ledc_fade_rec[speed_mode][channel]->target_duty) {
|
||||
if (s_ledc_fade_rec[speed_mode][channel]->mode == LEDC_FADE_WAIT_DONE) {
|
||||
xSemaphoreGiveFromISR(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem, &HPTaskAwoken);
|
||||
@ -428,7 +428,7 @@ void IRAM_ATTR ledc_fade_isr(void* arg)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
int duty_tar = s_ledc_fade_rec[speed_mode][channel]->target_duty;
|
||||
uint32_t duty_tar = s_ledc_fade_rec[speed_mode][channel]->target_duty;
|
||||
int scale = s_ledc_fade_rec[speed_mode][channel]->scale;
|
||||
if (scale == 0) {
|
||||
continue;
|
||||
@ -497,18 +497,18 @@ static esp_err_t ledc_fade_channel_init_check(ledc_mode_t speed_mode, ledc_chann
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, int target_duty, int max_fade_time_ms)
|
||||
esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int max_fade_time_ms)
|
||||
{
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(channel < LEDC_CHANNEL_MAX, LEDC_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK , LEDC_FADE_INIT_ERROR_STR, ESP_FAIL);
|
||||
|
||||
int timer_sel = LEDC.channel_group[speed_mode].channel[channel].conf0.timer_sel;
|
||||
int max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.bit_num)) - 1;
|
||||
uint32_t max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.bit_num)) - 1;
|
||||
LEDC_CHECK(target_duty <= max_duty, LEDC_FADE_TARGET_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
uint32_t freq = ledc_get_freq(speed_mode, timer_sel);
|
||||
int duty_cur = LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM;
|
||||
int duty_delta = target_duty > duty_cur ? target_duty - duty_cur : duty_cur - target_duty;
|
||||
uint32_t duty_cur = LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM;
|
||||
uint32_t duty_delta = target_duty > duty_cur ? target_duty - duty_cur : duty_cur - target_duty;
|
||||
|
||||
if (duty_delta == 0) {
|
||||
return ESP_OK;
|
||||
@ -528,21 +528,21 @@ esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel
|
||||
return ledc_set_fade_with_step(speed_mode, channel, target_duty, scale, cycle_num);
|
||||
}
|
||||
|
||||
esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, int target_duty, int scale, int cycle_num)
|
||||
esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int scale, int cycle_num)
|
||||
{
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(channel < LEDC_CHANNEL_MAX, LEDC_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK , LEDC_FADE_INIT_ERROR_STR, ESP_FAIL);
|
||||
|
||||
int timer_sel = LEDC.channel_group[speed_mode].channel[channel].conf0.timer_sel;
|
||||
int max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.bit_num)) - 1;
|
||||
uint32_t max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.bit_num)) - 1;
|
||||
LEDC_CHECK(target_duty <= max_duty, LEDC_FADE_TARGET_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
//disable the interrupt, so the operation will not mess up
|
||||
ledc_enable_intr_type(speed_mode, channel, LEDC_INTR_DISABLE);
|
||||
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
int duty_cur = LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM;
|
||||
int duty_delta = target_duty > duty_cur ? target_duty - duty_cur : duty_cur - target_duty;
|
||||
uint32_t duty_cur = LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM;
|
||||
uint32_t duty_delta = target_duty > duty_cur ? target_duty - duty_cur : duty_cur - target_duty;
|
||||
if (duty_delta == 0) {
|
||||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
return ESP_OK;
|
||||
|
@ -21,230 +21,194 @@
|
||||
|
||||
static portMUX_TYPE periph_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
/* Static functions to return register address & mask for clk_en / rst of each peripheral */
|
||||
static uint32_t get_clk_en_mask(periph_module_t periph);
|
||||
static uint32_t get_rst_en_mask(periph_module_t periph);
|
||||
static uint32_t get_clk_en_reg(periph_module_t periph);
|
||||
static uint32_t get_rst_en_reg(periph_module_t periph);
|
||||
|
||||
void periph_module_enable(periph_module_t periph)
|
||||
{
|
||||
portENTER_CRITICAL(&periph_spinlock);
|
||||
switch(periph) {
|
||||
case PERIPH_RMT_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_RMT_CLK_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_RMT_RST);
|
||||
break;
|
||||
case PERIPH_LEDC_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_LEDC_CLK_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_LEDC_RST);
|
||||
break;
|
||||
case PERIPH_UART0_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART_CLK_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART_RST);
|
||||
break;
|
||||
case PERIPH_UART1_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART1_CLK_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART1_RST);
|
||||
break;
|
||||
case PERIPH_UART2_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART2_CLK_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART2_RST);
|
||||
break;
|
||||
case PERIPH_I2C0_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2C_EXT0_CLK_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2C_EXT0_RST);
|
||||
break;
|
||||
case PERIPH_I2C1_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2C_EXT1_CLK_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2C_EXT1_RST);
|
||||
break;
|
||||
case PERIPH_I2S0_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);
|
||||
break;
|
||||
case PERIPH_I2S1_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S1_RST);
|
||||
break;
|
||||
case PERIPH_TIMG0_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_TIMERGROUP_CLK_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_TIMERGROUP_RST);
|
||||
break;
|
||||
case PERIPH_TIMG1_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_TIMERGROUP1_CLK_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_TIMERGROUP1_RST);
|
||||
break;
|
||||
case PERIPH_PWM0_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_PWM0_CLK_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_PWM0_RST);
|
||||
break;
|
||||
case PERIPH_PWM1_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_PWM1_CLK_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_PWM1_RST);
|
||||
break;
|
||||
case PERIPH_PWM2_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_PWM2_CLK_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_PWM2_RST);
|
||||
break;
|
||||
case PERIPH_PWM3_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_PWM3_CLK_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_PWM3_RST);
|
||||
break;
|
||||
case PERIPH_UHCI0_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UHCI0_CLK_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UHCI0_RST);
|
||||
break;
|
||||
case PERIPH_UHCI1_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UHCI1_CLK_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UHCI1_RST);
|
||||
break;
|
||||
case PERIPH_PCNT_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_PCNT_CLK_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_PCNT_RST);
|
||||
break;
|
||||
case PERIPH_SPI_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_1);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_1);
|
||||
break;
|
||||
case PERIPH_HSPI_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST);
|
||||
break;
|
||||
case PERIPH_VSPI_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_2);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_2);
|
||||
break;
|
||||
case PERIPH_SPI_DMA_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_DMA_CLK_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_DMA_RST);
|
||||
break;
|
||||
case PERIPH_SDMMC_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_SDIO_HOST_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_CORE_RST_EN_REG, DPORT_SDIO_HOST_RST);
|
||||
break;
|
||||
case PERIPH_SDIO_SLAVE_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_SDIOSLAVE_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_CORE_RST_EN_REG, DPORT_SDIO_RST);
|
||||
break;
|
||||
case PERIPH_CAN_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_CAN_CLK_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_CAN_RST);
|
||||
break;
|
||||
case PERIPH_EMAC_MODULE:
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_EMAC_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_CORE_RST_EN_REG, DPORT_EMAC_RST);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
DPORT_SET_PERI_REG_MASK(get_clk_en_reg(periph), get_clk_en_mask(periph));
|
||||
DPORT_CLEAR_PERI_REG_MASK(get_rst_en_reg(periph), get_rst_en_mask(periph));
|
||||
portEXIT_CRITICAL(&periph_spinlock);
|
||||
}
|
||||
|
||||
void periph_module_disable(periph_module_t periph)
|
||||
{
|
||||
portENTER_CRITICAL(&periph_spinlock);
|
||||
switch(periph) {
|
||||
case PERIPH_RMT_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_RMT_CLK_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_RMT_RST);
|
||||
break;
|
||||
case PERIPH_LEDC_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_LEDC_CLK_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_LEDC_RST);
|
||||
break;
|
||||
case PERIPH_UART0_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART_CLK_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART_RST);
|
||||
break;
|
||||
case PERIPH_UART1_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART1_CLK_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART1_RST);
|
||||
break;
|
||||
case PERIPH_UART2_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART2_CLK_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART2_RST);
|
||||
break;
|
||||
case PERIPH_I2C0_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2C_EXT0_CLK_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2C_EXT0_RST);
|
||||
break;
|
||||
case PERIPH_I2C1_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2C_EXT0_CLK_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2C_EXT1_RST);
|
||||
break;
|
||||
case PERIPH_I2S0_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);
|
||||
break;
|
||||
case PERIPH_I2S1_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S1_RST);
|
||||
break;
|
||||
case PERIPH_TIMG0_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_TIMERGROUP_CLK_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_TIMERGROUP_RST);
|
||||
break;
|
||||
case PERIPH_TIMG1_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_TIMERGROUP1_CLK_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_TIMERGROUP1_RST);
|
||||
break;
|
||||
case PERIPH_PWM0_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_PWM0_CLK_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_PWM0_RST);
|
||||
break;
|
||||
case PERIPH_PWM1_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_PWM1_CLK_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_PWM1_RST);
|
||||
break;
|
||||
case PERIPH_PWM2_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_PWM2_CLK_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_PWM2_RST);
|
||||
break;
|
||||
case PERIPH_PWM3_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_PWM3_CLK_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_PWM3_RST);
|
||||
break;
|
||||
case PERIPH_UHCI0_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UHCI0_CLK_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UHCI0_RST);
|
||||
break;
|
||||
case PERIPH_UHCI1_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UHCI1_CLK_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UHCI1_RST);
|
||||
break;
|
||||
case PERIPH_PCNT_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_PCNT_CLK_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_PCNT_RST);
|
||||
break;
|
||||
case PERIPH_SPI_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_1);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_1);
|
||||
break;
|
||||
case PERIPH_HSPI_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST);
|
||||
break;
|
||||
case PERIPH_VSPI_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_2);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_2);
|
||||
break;
|
||||
case PERIPH_SPI_DMA_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_DMA_CLK_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_DMA_RST);
|
||||
break;
|
||||
case PERIPH_SDMMC_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_SDIO_HOST_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_CORE_RST_EN_REG, DPORT_SDIO_HOST_RST);
|
||||
break;
|
||||
case PERIPH_SDIO_SLAVE_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_SDIOSLAVE_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_CORE_RST_EN_REG, DPORT_SDIO_RST);
|
||||
break;
|
||||
case PERIPH_CAN_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_CAN_CLK_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_CAN_RST);
|
||||
break;
|
||||
case PERIPH_EMAC_MODULE:
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_EMAC_EN);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_CORE_RST_EN_REG, DPORT_EMAC_RST);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
DPORT_CLEAR_PERI_REG_MASK(get_clk_en_reg(periph), get_clk_en_mask(periph));
|
||||
DPORT_SET_PERI_REG_MASK(get_rst_en_reg(periph), get_rst_en_mask(periph));
|
||||
portEXIT_CRITICAL(&periph_spinlock);
|
||||
}
|
||||
|
||||
void periph_module_reset(periph_module_t periph)
|
||||
{
|
||||
portENTER_CRITICAL(&periph_spinlock);
|
||||
DPORT_SET_PERI_REG_MASK(get_rst_en_reg(periph), get_rst_en_mask(periph));
|
||||
DPORT_CLEAR_PERI_REG_MASK(get_rst_en_reg(periph), get_rst_en_mask(periph));
|
||||
portEXIT_CRITICAL(&periph_spinlock);
|
||||
}
|
||||
|
||||
static uint32_t get_clk_en_mask(periph_module_t periph)
|
||||
{
|
||||
switch(periph) {
|
||||
case PERIPH_RMT_MODULE:
|
||||
return DPORT_RMT_CLK_EN;
|
||||
case PERIPH_LEDC_MODULE:
|
||||
return DPORT_LEDC_CLK_EN;
|
||||
case PERIPH_UART0_MODULE:
|
||||
return DPORT_UART_CLK_EN;
|
||||
case PERIPH_UART1_MODULE:
|
||||
return DPORT_UART1_CLK_EN;
|
||||
case PERIPH_UART2_MODULE:
|
||||
return DPORT_UART2_CLK_EN;
|
||||
case PERIPH_I2C0_MODULE:
|
||||
return DPORT_I2C_EXT0_CLK_EN;
|
||||
case PERIPH_I2C1_MODULE:
|
||||
return DPORT_I2C_EXT1_CLK_EN;
|
||||
case PERIPH_I2S0_MODULE:
|
||||
return DPORT_I2S0_CLK_EN;
|
||||
case PERIPH_I2S1_MODULE:
|
||||
return DPORT_I2S1_CLK_EN;
|
||||
case PERIPH_TIMG0_MODULE:
|
||||
return DPORT_TIMERGROUP_CLK_EN;
|
||||
case PERIPH_TIMG1_MODULE:
|
||||
return DPORT_TIMERGROUP1_CLK_EN;
|
||||
case PERIPH_PWM0_MODULE:
|
||||
return DPORT_PWM0_CLK_EN;
|
||||
case PERIPH_PWM1_MODULE:
|
||||
return DPORT_PWM1_CLK_EN;
|
||||
case PERIPH_PWM2_MODULE:
|
||||
return DPORT_PWM2_CLK_EN;
|
||||
case PERIPH_PWM3_MODULE:
|
||||
return DPORT_PWM3_CLK_EN;
|
||||
case PERIPH_UHCI0_MODULE:
|
||||
return DPORT_UHCI0_CLK_EN;
|
||||
case PERIPH_UHCI1_MODULE:
|
||||
return DPORT_UHCI1_CLK_EN;
|
||||
case PERIPH_PCNT_MODULE:
|
||||
return DPORT_PCNT_CLK_EN;
|
||||
case PERIPH_SPI_MODULE:
|
||||
return DPORT_SPI_CLK_EN_1;
|
||||
case PERIPH_HSPI_MODULE:
|
||||
return DPORT_SPI_CLK_EN;
|
||||
case PERIPH_VSPI_MODULE:
|
||||
return DPORT_SPI_CLK_EN_2;
|
||||
case PERIPH_SPI_DMA_MODULE:
|
||||
return DPORT_SPI_DMA_CLK_EN;
|
||||
case PERIPH_SDMMC_MODULE:
|
||||
return DPORT_WIFI_CLK_SDIO_HOST_EN;
|
||||
case PERIPH_SDIO_SLAVE_MODULE:
|
||||
return DPORT_WIFI_CLK_SDIOSLAVE_EN;
|
||||
case PERIPH_CAN_MODULE:
|
||||
return DPORT_CAN_CLK_EN;
|
||||
case PERIPH_EMAC_MODULE:
|
||||
return DPORT_WIFI_CLK_EMAC_EN;
|
||||
case PERIPH_RNG_MODULE:
|
||||
return DPORT_WIFI_CLK_RNG_EN;
|
||||
case PERIPH_WIFI_MODULE:
|
||||
return DPORT_WIFI_CLK_WIFI_EN_M;
|
||||
case PERIPH_BT_MODULE:
|
||||
return DPORT_WIFI_CLK_BT_EN_M;
|
||||
case PERIPH_WIFI_BT_COMMON_MODULE:
|
||||
return DPORT_WIFI_CLK_WIFI_BT_COMMON_M;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t get_rst_en_mask(periph_module_t periph)
|
||||
{
|
||||
switch(periph) {
|
||||
case PERIPH_RMT_MODULE:
|
||||
return DPORT_RMT_RST;
|
||||
case PERIPH_LEDC_MODULE:
|
||||
return DPORT_LEDC_RST;
|
||||
case PERIPH_UART0_MODULE:
|
||||
return DPORT_UART_RST;
|
||||
case PERIPH_UART1_MODULE:
|
||||
return DPORT_UART1_RST;
|
||||
case PERIPH_UART2_MODULE:
|
||||
return DPORT_UART2_RST;
|
||||
case PERIPH_I2C0_MODULE:
|
||||
return DPORT_I2C_EXT0_RST;
|
||||
case PERIPH_I2C1_MODULE:
|
||||
return DPORT_I2C_EXT1_RST;
|
||||
case PERIPH_I2S0_MODULE:
|
||||
return DPORT_I2S0_RST;
|
||||
case PERIPH_I2S1_MODULE:
|
||||
return DPORT_I2S1_RST;
|
||||
case PERIPH_TIMG0_MODULE:
|
||||
return DPORT_TIMERGROUP_RST;
|
||||
case PERIPH_TIMG1_MODULE:
|
||||
return DPORT_TIMERGROUP1_RST;
|
||||
case PERIPH_PWM0_MODULE:
|
||||
return DPORT_PWM0_RST;
|
||||
case PERIPH_PWM1_MODULE:
|
||||
return DPORT_PWM1_RST;
|
||||
case PERIPH_PWM2_MODULE:
|
||||
return DPORT_PWM2_RST;
|
||||
case PERIPH_PWM3_MODULE:
|
||||
return DPORT_PWM3_RST;
|
||||
case PERIPH_UHCI0_MODULE:
|
||||
return DPORT_UHCI0_RST;
|
||||
case PERIPH_UHCI1_MODULE:
|
||||
return DPORT_UHCI1_RST;
|
||||
case PERIPH_PCNT_MODULE:
|
||||
return DPORT_PCNT_RST;
|
||||
case PERIPH_SPI_MODULE:
|
||||
return DPORT_SPI_RST_1;
|
||||
case PERIPH_HSPI_MODULE:
|
||||
return DPORT_SPI_RST;
|
||||
case PERIPH_VSPI_MODULE:
|
||||
return DPORT_SPI_RST_2;
|
||||
case PERIPH_SPI_DMA_MODULE:
|
||||
return DPORT_SPI_DMA_RST;
|
||||
case PERIPH_SDMMC_MODULE:
|
||||
return DPORT_SDIO_HOST_RST;
|
||||
case PERIPH_SDIO_SLAVE_MODULE:
|
||||
return DPORT_SDIO_RST;
|
||||
case PERIPH_CAN_MODULE:
|
||||
return DPORT_CAN_RST;
|
||||
case PERIPH_EMAC_MODULE:
|
||||
return DPORT_EMAC_RST;
|
||||
case PERIPH_WIFI_MODULE:
|
||||
case PERIPH_BT_MODULE:
|
||||
case PERIPH_WIFI_BT_COMMON_MODULE:
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_wifi_clk_peripheral(periph_module_t periph)
|
||||
{
|
||||
/* A small subset of peripherals use WIFI_CLK_EN_REG and
|
||||
CORE_RST_EN_REG for their clock & reset registers */
|
||||
switch(periph) {
|
||||
case PERIPH_SDMMC_MODULE:
|
||||
case PERIPH_SDIO_SLAVE_MODULE:
|
||||
case PERIPH_EMAC_MODULE:
|
||||
case PERIPH_RNG_MODULE:
|
||||
case PERIPH_WIFI_MODULE:
|
||||
case PERIPH_BT_MODULE:
|
||||
case PERIPH_WIFI_BT_COMMON_MODULE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t get_clk_en_reg(periph_module_t periph)
|
||||
{
|
||||
return is_wifi_clk_peripheral(periph) ? DPORT_WIFI_CLK_EN_REG : DPORT_PERIP_CLK_EN_REG;
|
||||
}
|
||||
|
||||
static uint32_t get_rst_en_reg(periph_module_t periph)
|
||||
{
|
||||
return is_wifi_clk_peripheral(periph) ? DPORT_CORE_RST_EN_REG : DPORT_PERIP_RST_EN_REG;
|
||||
}
|
||||
|
||||
|
||||
|
@ -351,8 +351,10 @@ esp_err_t rmt_set_tx_thr_intr_en(rmt_channel_t channel, bool en, uint16_t evt_th
|
||||
{
|
||||
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
if(en) {
|
||||
RMT_CHECK(evt_thresh < 256, "RMT EVT THRESH ERR", ESP_ERR_INVALID_ARG);
|
||||
RMT_CHECK(evt_thresh <= 256, "RMT EVT THRESH ERR", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&rmt_spinlock);
|
||||
RMT.tx_lim_ch[channel].limit = evt_thresh;
|
||||
portEXIT_CRITICAL(&rmt_spinlock);
|
||||
rmt_set_tx_wrap_en(channel, true);
|
||||
rmt_set_intr_enable_mask(BIT(channel + 24));
|
||||
} else {
|
||||
@ -424,8 +426,6 @@ esp_err_t rmt_config(const rmt_config_t* rmt_param)
|
||||
/*Set idle level */
|
||||
RMT.conf_ch[channel].conf1.idle_out_en = rmt_param->tx_config.idle_output_en;
|
||||
RMT.conf_ch[channel].conf1.idle_out_lv = idle_level;
|
||||
portEXIT_CRITICAL(&rmt_spinlock);
|
||||
|
||||
/*Set carrier*/
|
||||
RMT.conf_ch[channel].conf0.carrier_en = carrier_en;
|
||||
if (carrier_en) {
|
||||
@ -441,6 +441,8 @@ esp_err_t rmt_config(const rmt_config_t* rmt_param)
|
||||
RMT.carrier_duty_ch[channel].high = 0;
|
||||
RMT.carrier_duty_ch[channel].low = 0;
|
||||
}
|
||||
portEXIT_CRITICAL(&rmt_spinlock);
|
||||
|
||||
ESP_LOGD(RMT_TAG, "Rmt Tx Channel %u|Gpio %u|Sclk_Hz %u|Div %u|Carrier_Hz %u|Duty %u",
|
||||
channel, gpio_num, rmt_source_clk_hz, clk_div, carrier_freq_hz, carrier_duty_percent);
|
||||
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include "soc/sens_struct.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/rtc_cntl_struct.h"
|
||||
#include "soc/syscon_reg.h"
|
||||
#include "soc/syscon_struct.h"
|
||||
#include "rtc_io.h"
|
||||
#include "touch_pad.h"
|
||||
#include "adc.h"
|
||||
@ -40,6 +42,18 @@
|
||||
#include "rom/queue.h"
|
||||
|
||||
|
||||
#define ADC_FSM_RSTB_WAIT_DEFAULT (8)
|
||||
#define ADC_FSM_START_WAIT_DEFAULT (5)
|
||||
#define ADC_FSM_STANDBY_WAIT_DEFAULT (100)
|
||||
#define ADC_FSM_TIME_KEEP (-1)
|
||||
#define ADC_MAX_MEAS_NUM_DEFAULT (255)
|
||||
#define ADC_MEAS_NUM_LIM_DEFAULT (1)
|
||||
#define SAR_ADC_CLK_DIV_DEFUALT (2)
|
||||
#define ADC_PATT_LEN_MAX (16)
|
||||
#define TOUCH_PAD_FILTER_FACTOR_DEFAULT (16)
|
||||
#define TOUCH_PAD_SHIFT_DEFAULT (4)
|
||||
#define DAC_ERR_STR_CHANNEL_ERROR "DAC channel error"
|
||||
|
||||
static const char *RTC_MODULE_TAG = "RTC_MODULE";
|
||||
|
||||
#define RTC_MODULE_CHECK(a, str, ret_val) if (!(a)) { \
|
||||
@ -52,16 +66,38 @@ static const char *RTC_MODULE_TAG = "RTC_MODULE";
|
||||
return (ret_val); \
|
||||
}
|
||||
|
||||
#define ADC_CHECK_UNIT(unit) RTC_MODULE_CHECK(adc_unit < ADC_UNIT_2, "ADC unit error, only support ADC1 for now", ESP_ERR_INVALID_ARG)
|
||||
|
||||
#define ADC1_CHECK_FUNCTION_RET(fun_ret) if(fun_ret!=ESP_OK){\
|
||||
ESP_LOGE(RTC_MODULE_TAG,"%s:%d\n",__FUNCTION__,__LINE__);\
|
||||
return ESP_FAIL;\
|
||||
}
|
||||
|
||||
#define DAC_ERR_STR_CHANNEL_ERROR "DAC channel error"
|
||||
#define ADC2_CHECK_FUNCTION_RET(fun_ret) do { if(fun_ret!=ESP_OK){\
|
||||
ESP_LOGE(RTC_MODULE_TAG,"%s:%d\n",__FUNCTION__,__LINE__);\
|
||||
return ESP_FAIL;\
|
||||
} }while (0)
|
||||
|
||||
portMUX_TYPE rtc_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
static SemaphoreHandle_t rtc_touch_mux = NULL;
|
||||
/*
|
||||
In ADC2, there're two locks used for different cases:
|
||||
1. lock shared with app and WIFI:
|
||||
when wifi using the ADC2, we assume it will never stop,
|
||||
so app checks the lock and returns immediately if failed.
|
||||
|
||||
2. lock shared between tasks:
|
||||
when several tasks sharing the ADC2, we want to guarantee
|
||||
all the requests will be handled.
|
||||
Since conversions are short (about 31us), app returns the lock very soon,
|
||||
we use a spinlock to stand there waiting to do conversions one by one.
|
||||
|
||||
adc2_spinlock should be acquired first, then adc2_wifi_lock or rtc_spinlock.
|
||||
*/
|
||||
//prevent ADC2 being used by wifi and other tasks at the same time.
|
||||
static _lock_t adc2_wifi_lock = NULL;
|
||||
//prevent ADC2 being used by tasks (regardless of WIFI)
|
||||
portMUX_TYPE adc2_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
typedef struct {
|
||||
TimerHandle_t timer;
|
||||
@ -72,6 +108,12 @@ typedef struct {
|
||||
} touch_pad_filter_t;
|
||||
static touch_pad_filter_t *s_touch_pad_filter = NULL;
|
||||
|
||||
typedef enum {
|
||||
ADC_FORCE_FSM = 0x0,
|
||||
ADC_FORCE_DISABLE = 0x2,
|
||||
ADC_FORCE_ENABLE = 0x3,
|
||||
} adc_force_mode_t;
|
||||
|
||||
//Reg,Mux,Fun,IE,Up,Down,Rtc_number
|
||||
const rtc_gpio_desc_t rtc_gpio_desc[GPIO_PIN_COUNT] = {
|
||||
{RTC_IO_TOUCH_PAD1_REG, RTC_IO_TOUCH_PAD1_MUX_SEL_M, RTC_IO_TOUCH_PAD1_FUN_SEL_S, RTC_IO_TOUCH_PAD1_FUN_IE_M, RTC_IO_TOUCH_PAD1_RUE_M, RTC_IO_TOUCH_PAD1_RDE_M, RTC_IO_TOUCH_PAD1_SLP_SEL_M, RTC_IO_TOUCH_PAD1_SLP_IE_M, RTC_IO_TOUCH_PAD1_HOLD_M, RTC_CNTL_TOUCH_PAD1_HOLD_FORCE_M, RTC_IO_TOUCH_PAD1_DRV_V, RTC_IO_TOUCH_PAD1_DRV_S, RTCIO_GPIO0_CHANNEL}, //0
|
||||
@ -412,8 +454,6 @@ static esp_err_t touch_pad_get_io_num(touch_pad_t touch_num, gpio_num_t *gpio_nu
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#define TOUCH_PAD_FILTER_FACTOR_DEFAULT (16)
|
||||
#define TOUCH_PAD_SHIFT_DEFAULT (4)
|
||||
static uint32_t _touch_filter_iir(uint32_t in_now, uint32_t out_last, uint32_t k)
|
||||
{
|
||||
if (k == 0) {
|
||||
@ -510,8 +550,16 @@ esp_err_t touch_pad_set_cnt_mode(touch_pad_t touch_num, touch_cnt_slope_t slope,
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
//set tie opt value, high or low level seem no difference for counter
|
||||
RTCIO.touch_pad[touch_num].tie_opt = opt;
|
||||
|
||||
//workaround for touch pad DAC mismatch on tp8 and tp9
|
||||
touch_pad_t touch_pad_wrap = touch_num;
|
||||
if (touch_num == TOUCH_PAD_NUM9) {
|
||||
touch_pad_wrap = TOUCH_PAD_NUM8;
|
||||
} else if (touch_num == TOUCH_PAD_NUM8) {
|
||||
touch_pad_wrap = TOUCH_PAD_NUM9;
|
||||
}
|
||||
//touch sensor set slope for charging and discharging.
|
||||
RTCIO.touch_pad[touch_num].dac = slope;
|
||||
RTCIO.touch_pad[touch_pad_wrap].dac = slope;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -521,7 +569,14 @@ esp_err_t touch_pad_get_cnt_mode(touch_pad_t touch_num, touch_cnt_slope_t *slope
|
||||
RTC_MODULE_CHECK((touch_num < TOUCH_PAD_MAX), "touch IO error", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
if (slope) {
|
||||
*slope = RTCIO.touch_pad[touch_num].dac;
|
||||
//workaround for touch pad DAC mismatch on tp8 and tp9
|
||||
touch_pad_t touch_pad_wrap = touch_num;
|
||||
if (touch_num == TOUCH_PAD_NUM9) {
|
||||
touch_pad_wrap = TOUCH_PAD_NUM8;
|
||||
} else if (touch_num == TOUCH_PAD_NUM8) {
|
||||
touch_pad_wrap = TOUCH_PAD_NUM9;
|
||||
}
|
||||
*slope = RTCIO.touch_pad[touch_pad_wrap].dac;
|
||||
}
|
||||
if (opt) {
|
||||
*opt = RTCIO.touch_pad[touch_num].tie_opt;
|
||||
@ -871,11 +926,269 @@ esp_err_t touch_pad_filter_delete()
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
ADC
|
||||
ADC Common
|
||||
---------------------------------------------------------------*/
|
||||
static esp_err_t adc1_pad_get_io_num(adc1_channel_t channel, gpio_num_t *gpio_num)
|
||||
static esp_err_t adc_set_fsm_time(int rst_wait, int start_wait, int standby_wait, int sample_cycle)
|
||||
{
|
||||
RTC_MODULE_CHECK(channel < ADC1_CHANNEL_MAX, "ADC Channel Err", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
// Internal FSM reset wait time
|
||||
if (rst_wait >= 0) {
|
||||
SYSCON.saradc_fsm.rstb_wait = rst_wait;
|
||||
}
|
||||
// Internal FSM start wait time
|
||||
if (start_wait >= 0) {
|
||||
SYSCON.saradc_fsm.start_wait = start_wait;
|
||||
}
|
||||
// Internal FSM standby wait time
|
||||
if (standby_wait >= 0) {
|
||||
SYSCON.saradc_fsm.standby_wait = standby_wait;
|
||||
}
|
||||
// Internal FSM standby sample cycle
|
||||
if (sample_cycle >= 0) {
|
||||
SYSCON.saradc_fsm.sample_cycle = sample_cycle;
|
||||
}
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t adc_set_data_format(adc_i2s_encode_t mode)
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
//data format:
|
||||
//0: ADC_ENCODE_12BIT [15:12]-channel [11:0]-12 bits ADC data
|
||||
//1: ADC_ENCODE_11BIT [15]-1 [14:11]-channel [10:0]-11 bits ADC data, the resolution should not be larger than 11 bits in this case.
|
||||
SYSCON.saradc_ctrl.data_sar_sel = mode;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t adc_set_measure_limit(uint8_t meas_num, bool lim_en)
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
// Set max measure number
|
||||
SYSCON.saradc_ctrl2.max_meas_num = meas_num;
|
||||
// Enable max measure number limit
|
||||
SYSCON.saradc_ctrl2.meas_num_limit = lim_en;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t adc_set_work_mode(adc_unit_t adc_unit)
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
if (adc_unit == ADC_UNIT_1) {
|
||||
// saradc mode sel : 0--single saradc; 1--double saradc; 2--alternative saradc
|
||||
SYSCON.saradc_ctrl.work_mode = 0;
|
||||
//ENABLE ADC 0: ADC1 1: ADC2, only work for single SAR mode
|
||||
SYSCON.saradc_ctrl.sar_sel = 0;
|
||||
} else if (adc_unit == ADC_UNIT_2) {
|
||||
// saradc mode sel : 0--single saradc; 1--double saradc; 2--alternative saradc
|
||||
SYSCON.saradc_ctrl.work_mode = 0;
|
||||
//ENABLE ADC1 0: SAR1 1: SAR2 only work for single SAR mode
|
||||
SYSCON.saradc_ctrl.sar_sel = 1;
|
||||
} else if (adc_unit == ADC_UNIT_BOTH) {
|
||||
// saradc mode sel : 0--single saradc; 1--double saradc; 2--alternative saradc
|
||||
SYSCON.saradc_ctrl.work_mode = 1;
|
||||
} else if (adc_unit == ADC_UNIT_ALTER) {
|
||||
// saradc mode sel : 0--single saradc; 1--double saradc; 2--alternative saradc
|
||||
SYSCON.saradc_ctrl.work_mode = 2;
|
||||
}
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t adc_set_atten(adc_unit_t adc_unit, adc_channel_t channel, adc_atten_t atten)
|
||||
{
|
||||
ADC_CHECK_UNIT(adc_unit);
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
RTC_MODULE_CHECK((adc1_channel_t)channel < ADC1_CHANNEL_MAX, "ADC Channel Err", ESP_ERR_INVALID_ARG);
|
||||
}
|
||||
RTC_MODULE_CHECK(atten < ADC_ATTEN_MAX, "ADC Atten Err", ESP_ERR_INVALID_ARG);
|
||||
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
//SAR1_atten
|
||||
SET_PERI_REG_BITS(SENS_SAR_ATTEN1_REG, SENS_SAR1_ATTEN_VAL_MASK, atten, (channel * 2));
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
//SAR2_atten
|
||||
SET_PERI_REG_BITS(SENS_SAR_ATTEN2_REG, SENS_SAR2_ATTEN_VAL_MASK, atten, (channel * 2));
|
||||
}
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void adc_power_on()
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
SENS.sar_meas_wait2.force_xpd_sar = ADC_FORCE_FSM;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
}
|
||||
|
||||
void adc_power_off()
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
//Bit1 0:Fsm 1: SW mode
|
||||
//Bit0 0:SW mode power down 1: SW mode power on
|
||||
SENS.sar_meas_wait2.force_xpd_sar = ADC_FORCE_DISABLE;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
}
|
||||
|
||||
esp_err_t adc_set_clk_div(uint8_t clk_div)
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
// ADC clock devided from APB clk, 80 / 2 = 40Mhz,
|
||||
SYSCON.saradc_ctrl.sar_clk_div = clk_div;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src)
|
||||
{
|
||||
RTC_MODULE_CHECK(src < ADC_I2S_DATA_SRC_MAX, "ADC i2s data source error", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
// 1: I2S input data is from SAR ADC (for DMA) 0: I2S input data is from GPIO matrix
|
||||
SYSCON.saradc_ctrl.data_to_i2s = src;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_gpio_init(adc_unit_t adc_unit, adc_channel_t channel)
|
||||
{
|
||||
ADC_CHECK_UNIT(adc_unit);
|
||||
gpio_num_t gpio_num = 0;
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
RTC_MODULE_CHECK((adc1_channel_t) channel < ADC1_CHANNEL_MAX, "ADC1 channel error", ESP_ERR_INVALID_ARG);
|
||||
ADC1_CHECK_FUNCTION_RET(adc1_pad_get_io_num((adc1_channel_t) channel, &gpio_num));
|
||||
ADC1_CHECK_FUNCTION_RET(rtc_gpio_init(gpio_num));
|
||||
ADC1_CHECK_FUNCTION_RET(rtc_gpio_output_disable(gpio_num));
|
||||
ADC1_CHECK_FUNCTION_RET(rtc_gpio_input_disable(gpio_num));
|
||||
ADC1_CHECK_FUNCTION_RET(gpio_set_pull_mode(gpio_num, GPIO_FLOATING));
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_set_data_inv(adc_unit_t adc_unit, bool inv_en)
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
// Enable ADC data invert
|
||||
SENS.sar_read_ctrl.sar1_data_inv = inv_en;
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
// Enable ADC data invert
|
||||
SENS.sar_read_ctrl2.sar2_data_inv = inv_en;
|
||||
}
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t bits)
|
||||
{
|
||||
ADC_CHECK_UNIT(adc_unit);
|
||||
RTC_MODULE_CHECK(bits < ADC_WIDTH_MAX, "ADC bit width error", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
SENS.sar_start_force.sar1_bit_width = bits;
|
||||
SENS.sar_read_ctrl.sar1_sample_bit = bits;
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
SENS.sar_start_force.sar2_bit_width = bits;
|
||||
SENS.sar_read_ctrl2.sar2_sample_bit = bits;
|
||||
}
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------
|
||||
* ADC I2S
|
||||
*------------------------------------------------------------------------------------*/
|
||||
static esp_err_t adc_set_i2s_data_len(adc_unit_t adc_unit, int patt_len)
|
||||
{
|
||||
ADC_CHECK_UNIT(adc_unit);
|
||||
RTC_MODULE_CHECK((patt_len < ADC_PATT_LEN_MAX) && (patt_len > 0), "ADC pattern length error", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
if(adc_unit & ADC_UNIT_1) {
|
||||
SYSCON.saradc_ctrl.sar1_patt_len = patt_len - 1;
|
||||
}
|
||||
if(adc_unit & ADC_UNIT_2) {
|
||||
SYSCON.saradc_ctrl.sar2_patt_len = patt_len - 1;
|
||||
}
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t adc_set_i2s_data_pattern(adc_unit_t adc_unit, int seq_num, adc_channel_t channel, adc_bits_width_t bits, adc_atten_t atten)
|
||||
{
|
||||
ADC_CHECK_UNIT(adc_unit);
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
RTC_MODULE_CHECK((adc1_channel_t) channel < ADC1_CHANNEL_MAX, "ADC1 channel error", ESP_ERR_INVALID_ARG);
|
||||
}
|
||||
RTC_MODULE_CHECK(bits < ADC_WIDTH_MAX, "ADC bit width error", ESP_ERR_INVALID_ARG);
|
||||
RTC_MODULE_CHECK(atten < ADC_ATTEN_MAX, "ADC Atten Err", ESP_ERR_INVALID_ARG);
|
||||
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
//Configure pattern table, each 8 bit defines one channel
|
||||
//[7:4]-channel [3:2]-bit width [1:0]- attenuation
|
||||
//BIT WIDTH: 3: 12BIT 2: 11BIT 1: 10BIT 0: 9BIT
|
||||
//ATTEN: 3: ATTEN = 11dB 2: 6dB 1: 2.5dB 0: 0dB
|
||||
uint8_t val = (channel << 4) | (bits << 2) | (atten << 0);
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
SYSCON.saradc_sar1_patt_tab[seq_num / 4] &= (~(0xff << ((3 - (seq_num % 4)) * 8)));
|
||||
SYSCON.saradc_sar1_patt_tab[seq_num / 4] |= (val << ((3 - (seq_num % 4)) * 8));
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
SYSCON.saradc_sar2_patt_tab[seq_num / 4] &= (~(0xff << ((3 - (seq_num % 4)) * 8)));
|
||||
SYSCON.saradc_sar2_patt_tab[seq_num / 4] |= (val << ((3 - (seq_num % 4)) * 8));
|
||||
}
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel)
|
||||
{
|
||||
ADC_CHECK_UNIT(adc_unit);
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
RTC_MODULE_CHECK((adc1_channel_t) channel < ADC1_CHANNEL_MAX, "ADC1 channel error", ESP_ERR_INVALID_ARG);
|
||||
}
|
||||
|
||||
uint8_t table_len = 1;
|
||||
//POWER ON SAR
|
||||
adc_power_on();
|
||||
adc_gpio_init(adc_unit, channel);
|
||||
adc_set_i2s_data_len(adc_unit, table_len);
|
||||
adc_set_i2s_data_pattern(adc_unit, 0, channel, ADC_WIDTH_BIT_12, ADC_ATTEN_DB_11);
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
//switch SARADC into DIG channel
|
||||
SENS.sar_read_ctrl.sar1_dig_force = 1;
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
//switch SARADC into DIG channel
|
||||
SENS.sar_read_ctrl2.sar2_dig_force = 1;
|
||||
//1: SAR ADC2 is controlled by DIG ADC2 CTRL 0: SAR ADC2 is controlled by PWDET CTRL
|
||||
SYSCON.saradc_ctrl.sar2_mux = 1;
|
||||
}
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
adc_set_i2s_data_source(ADC_I2S_DATA_SRC_ADC);
|
||||
adc_set_clk_div(SAR_ADC_CLK_DIV_DEFUALT);
|
||||
// Set internal FSM wait time.
|
||||
adc_set_fsm_time(ADC_FSM_RSTB_WAIT_DEFAULT, ADC_FSM_START_WAIT_DEFAULT, ADC_FSM_STANDBY_WAIT_DEFAULT,
|
||||
ADC_FSM_TIME_KEEP);
|
||||
adc_set_work_mode(adc_unit);
|
||||
adc_set_data_format(ADC_ENCODE_12BIT);
|
||||
adc_set_measure_limit(ADC_MAX_MEAS_NUM_DEFAULT, ADC_MEAS_NUM_LIM_DEFAULT);
|
||||
//Invert The Level, Invert SAR ADC1 data
|
||||
adc_set_data_inv(adc_unit, true);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------
|
||||
* ADC1
|
||||
*------------------------------------------------------------------------------------*/
|
||||
esp_err_t adc1_pad_get_io_num(adc1_channel_t channel, gpio_num_t *gpio_num)
|
||||
{
|
||||
RTC_MODULE_CHECK(channel < ADC1_CHANNEL_MAX, "ADC1 Channel Err", ESP_ERR_INVALID_ARG);
|
||||
|
||||
switch (channel) {
|
||||
case ADC1_CHANNEL_0:
|
||||
@ -909,69 +1222,51 @@ static esp_err_t adc1_pad_get_io_num(adc1_channel_t channel, gpio_num_t *gpio_nu
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t adc1_pad_init(adc1_channel_t channel)
|
||||
{
|
||||
gpio_num_t gpio_num = 0;
|
||||
ADC1_CHECK_FUNCTION_RET(adc1_pad_get_io_num(channel, &gpio_num));
|
||||
ADC1_CHECK_FUNCTION_RET(rtc_gpio_init(gpio_num));
|
||||
ADC1_CHECK_FUNCTION_RET(rtc_gpio_output_disable(gpio_num));
|
||||
ADC1_CHECK_FUNCTION_RET(rtc_gpio_input_disable(gpio_num));
|
||||
ADC1_CHECK_FUNCTION_RET(gpio_set_pull_mode(gpio_num, GPIO_FLOATING));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten)
|
||||
{
|
||||
RTC_MODULE_CHECK(channel < ADC1_CHANNEL_MAX, "ADC Channel Err", ESP_ERR_INVALID_ARG);
|
||||
RTC_MODULE_CHECK(atten <= ADC_ATTEN_11db, "ADC Atten Err", ESP_ERR_INVALID_ARG);
|
||||
adc1_pad_init(channel);
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
SET_PERI_REG_BITS(SENS_SAR_ATTEN1_REG, 3, atten, (channel * 2)); //SAR1_atten
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
|
||||
RTC_MODULE_CHECK(atten < ADC_ATTEN_MAX, "ADC Atten Err", ESP_ERR_INVALID_ARG);
|
||||
adc_gpio_init(ADC_UNIT_1, channel);
|
||||
adc_set_atten(ADC_UNIT_1, channel, atten);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc1_config_width(adc_bits_width_t width_bit)
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
SET_PERI_REG_BITS(SENS_SAR_START_FORCE_REG, SENS_SAR1_BIT_WIDTH_V, width_bit, SENS_SAR1_BIT_WIDTH_S); //SAR2_BIT_WIDTH[1:0]=0x3, SAR1_BIT_WIDTH[1:0]=0x3
|
||||
//Invert the adc value,the Output value is invert
|
||||
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_DATA_INV);
|
||||
//Set The adc sample width,invert adc value,must
|
||||
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_SAMPLE_BIT_V, width_bit, SENS_SAR1_SAMPLE_BIT_S); //digital sar1_bit_width[1:0]=3
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
|
||||
RTC_MODULE_CHECK(width_bit < ADC_WIDTH_MAX, "ADC bit width error", ESP_ERR_INVALID_ARG);
|
||||
adc_set_data_width(ADC_UNIT_1, width_bit);
|
||||
adc_set_data_inv(ADC_UNIT_1, true);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int adc1_get_raw(adc1_channel_t channel)
|
||||
{
|
||||
uint16_t adc_value;
|
||||
|
||||
RTC_MODULE_CHECK(channel < ADC1_CHANNEL_MAX, "ADC Channel Err", ESP_ERR_INVALID_ARG);
|
||||
|
||||
adc_power_on();
|
||||
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
//Adc Controler is Rtc module,not ulp coprocessor
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_START1_REG, 1, 1, SENS_MEAS1_START_FORCE_S); //force pad mux and force start
|
||||
//Bit1=0:Fsm Bit1=1(Bit0=0:PownDown Bit10=1:Powerup)
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 0, SENS_FORCE_XPD_SAR_S); //force XPD_SAR=0, use XPD_FSM
|
||||
SENS.sar_meas_start1.meas1_start_force = 1;
|
||||
//Disable Amp Bit1=0:Fsm Bit1=1(Bit0=0:PownDown Bit10=1:Powerup)
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_AMP, 0x2, SENS_FORCE_XPD_AMP_S); //force XPD_AMP=0
|
||||
SENS.sar_meas_wait2.force_xpd_amp = 0x2;
|
||||
//Open the ADC1 Data port Not ulp coprocessor
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_START1_REG, 1, 1, SENS_SAR1_EN_PAD_FORCE_S); //open the ADC1 data port
|
||||
SENS.sar_meas_start1.sar1_en_pad_force = 1;
|
||||
//Select channel
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_START1_REG, SENS_SAR1_EN_PAD, (1 << channel), SENS_SAR1_EN_PAD_S); //pad enable
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_CTRL_REG, 0xfff, 0x0, SENS_AMP_RST_FB_FSM_S); //[11:8]:short ref ground, [7:4]:short ref, [3:0]:rst fb
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT1_REG, SENS_SAR_AMP_WAIT1, 0x1, SENS_SAR_AMP_WAIT1_S);
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT1_REG, SENS_SAR_AMP_WAIT2, 0x1, SENS_SAR_AMP_WAIT2_S);
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_SAR_AMP_WAIT3, 0x1, SENS_SAR_AMP_WAIT3_S);
|
||||
while (GET_PERI_REG_BITS2(SENS_SAR_SLAVE_ADDR1_REG, 0x7, SENS_MEAS_STATUS_S) != 0); //wait det_fsm==0
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_START1_REG, 1, 0, SENS_MEAS1_START_SAR_S); //start force 0
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_START1_REG, 1, 1, SENS_MEAS1_START_SAR_S); //start force 1
|
||||
while (GET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DONE_SAR) == 0) {}; //read done
|
||||
adc_value = GET_PERI_REG_BITS2(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DATA_SAR, SENS_MEAS1_DATA_SAR_S);
|
||||
SENS.sar_meas_start1.sar1_en_pad = (1 << channel);
|
||||
SENS.sar_meas_ctrl.amp_rst_fb_fsm = 0;
|
||||
SENS.sar_meas_ctrl.amp_short_ref_fsm = 0;
|
||||
SENS.sar_meas_ctrl.amp_short_ref_gnd_fsm = 0;
|
||||
SENS.sar_meas_wait1.sar_amp_wait1 = 1;
|
||||
SENS.sar_meas_wait1.sar_amp_wait2 = 1;
|
||||
SENS.sar_meas_wait2.sar_amp_wait3 = 1;
|
||||
while (SENS.sar_slave_addr1.meas_status != 0);
|
||||
SENS.sar_meas_start1.meas1_start_sar = 0;
|
||||
SENS.sar_meas_start1.meas1_start_sar = 1;
|
||||
while (SENS.sar_meas_start1.meas1_done_sar == 0);
|
||||
adc_value = SENS.sar_meas_start1.meas1_data_sar;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
|
||||
return adc_value;
|
||||
}
|
||||
|
||||
@ -982,18 +1277,170 @@ int adc1_get_voltage(adc1_channel_t channel) //Deprecated. Use adc1_get_raw()
|
||||
|
||||
void adc1_ulp_enable(void)
|
||||
{
|
||||
adc_power_on();
|
||||
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_START_FORCE);
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_SAR1_EN_PAD_FORCE_M);
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_AMP, 0x2, SENS_FORCE_XPD_AMP_S);
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 0, SENS_FORCE_XPD_SAR_S);
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_CTRL_REG, 0xfff, 0x0, SENS_AMP_RST_FB_FSM_S); //[11:8]:short ref ground, [7:4]:short ref, [3:0]:rst fb
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT1_REG, SENS_SAR_AMP_WAIT1, 0x1, SENS_SAR_AMP_WAIT1_S);
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT1_REG, SENS_SAR_AMP_WAIT2, 0x1, SENS_SAR_AMP_WAIT2_S);
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_SAR_AMP_WAIT3, 0x1, SENS_SAR_AMP_WAIT3_S);
|
||||
SENS.sar_meas_start1.meas1_start_force = 0;
|
||||
SENS.sar_meas_start1.sar1_en_pad_force = 0;
|
||||
SENS.sar_meas_wait2.force_xpd_amp = 0x2;
|
||||
SENS.sar_meas_ctrl.amp_rst_fb_fsm = 0;
|
||||
SENS.sar_meas_ctrl.amp_short_ref_fsm = 0;
|
||||
SENS.sar_meas_ctrl.amp_short_ref_gnd_fsm = 0;
|
||||
SENS.sar_meas_wait1.sar_amp_wait1 = 0x1;
|
||||
SENS.sar_meas_wait1.sar_amp_wait2 = 0x1;
|
||||
SENS.sar_meas_wait2.sar_amp_wait3 = 0x1;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
ADC2
|
||||
---------------------------------------------------------------*/
|
||||
esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num)
|
||||
{
|
||||
RTC_MODULE_CHECK(channel < ADC2_CHANNEL_MAX, "ADC2 Channel Err", ESP_ERR_INVALID_ARG);
|
||||
|
||||
switch (channel) {
|
||||
case ADC2_CHANNEL_0:
|
||||
*gpio_num = ADC2_CHANNEL_0_GPIO_NUM;
|
||||
break;
|
||||
case ADC2_CHANNEL_1:
|
||||
*gpio_num = ADC2_CHANNEL_1_GPIO_NUM;
|
||||
break;
|
||||
case ADC2_CHANNEL_2:
|
||||
*gpio_num = ADC2_CHANNEL_2_GPIO_NUM;
|
||||
break;
|
||||
case ADC2_CHANNEL_3:
|
||||
*gpio_num = ADC2_CHANNEL_3_GPIO_NUM;
|
||||
break;
|
||||
case ADC2_CHANNEL_4:
|
||||
*gpio_num = ADC2_CHANNEL_4_GPIO_NUM;
|
||||
break;
|
||||
case ADC2_CHANNEL_5:
|
||||
*gpio_num = ADC2_CHANNEL_5_GPIO_NUM;
|
||||
break;
|
||||
case ADC2_CHANNEL_6:
|
||||
*gpio_num = ADC2_CHANNEL_6_GPIO_NUM;
|
||||
break;
|
||||
case ADC2_CHANNEL_7:
|
||||
*gpio_num = ADC2_CHANNEL_7_GPIO_NUM;
|
||||
break;
|
||||
case ADC2_CHANNEL_8:
|
||||
*gpio_num = ADC2_CHANNEL_8_GPIO_NUM;
|
||||
break;
|
||||
case ADC2_CHANNEL_9:
|
||||
*gpio_num = ADC2_CHANNEL_9_GPIO_NUM;
|
||||
break;
|
||||
default:
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc2_wifi_acquire()
|
||||
{
|
||||
//lazy initialization
|
||||
//for wifi, block until acquire the lock
|
||||
_lock_acquire( &adc2_wifi_lock );
|
||||
ESP_LOGD( RTC_MODULE_TAG, "Wi-Fi takes adc2 lock." );
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc2_wifi_release()
|
||||
{
|
||||
RTC_MODULE_CHECK((uint32_t*)adc2_wifi_lock != NULL, "wifi release called before acquire", ESP_ERR_INVALID_STATE );
|
||||
|
||||
_lock_release( &adc2_wifi_lock );
|
||||
ESP_LOGD( RTC_MODULE_TAG, "Wi-Fi returns adc2 lock." );
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t adc2_pad_init(adc2_channel_t channel)
|
||||
{
|
||||
gpio_num_t gpio_num = 0;
|
||||
ADC2_CHECK_FUNCTION_RET(adc2_pad_get_io_num(channel, &gpio_num));
|
||||
ADC2_CHECK_FUNCTION_RET(rtc_gpio_init(gpio_num));
|
||||
ADC2_CHECK_FUNCTION_RET(rtc_gpio_output_disable(gpio_num));
|
||||
ADC2_CHECK_FUNCTION_RET(rtc_gpio_input_disable(gpio_num));
|
||||
ADC2_CHECK_FUNCTION_RET(gpio_set_pull_mode(gpio_num, GPIO_FLOATING));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
|
||||
{
|
||||
RTC_MODULE_CHECK(channel < ADC2_CHANNEL_MAX, "ADC2 Channel Err", ESP_ERR_INVALID_ARG);
|
||||
RTC_MODULE_CHECK(atten <= ADC_ATTEN_11db, "ADC2 Atten Err", ESP_ERR_INVALID_ARG);
|
||||
|
||||
adc2_pad_init(channel);
|
||||
portENTER_CRITICAL( &adc2_spinlock );
|
||||
|
||||
//lazy initialization
|
||||
//avoid collision with other tasks
|
||||
if ( _lock_try_acquire( &adc2_wifi_lock ) == -1 ) {
|
||||
//try the lock, return if failed (wifi using).
|
||||
portEXIT_CRITICAL( &adc2_spinlock );
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
SENS.sar_atten2 = ( SENS.sar_atten2 & ~(3<<(channel*2)) ) | ((atten&3) << (channel*2));
|
||||
_lock_release( &adc2_wifi_lock );
|
||||
|
||||
portEXIT_CRITICAL( &adc2_spinlock );
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline void adc2_config_width(adc_bits_width_t width_bit)
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
//sar_start_force shared with ADC1
|
||||
SENS.sar_start_force.sar2_bit_width = width_bit;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
|
||||
//Invert the adc value,the Output value is invert
|
||||
SENS.sar_read_ctrl2.sar2_data_inv = 1;
|
||||
//Set The adc sample width,invert adc value,must digital sar2_bit_width[1:0]=3
|
||||
SENS.sar_read_ctrl2.sar2_sample_bit = width_bit;
|
||||
//Take the control from WIFI
|
||||
SENS.sar_read_ctrl2.sar2_pwdet_force = 0;
|
||||
}
|
||||
|
||||
//registers in critical section with adc1:
|
||||
//SENS_SAR_START_FORCE_REG,
|
||||
esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int* raw_out)
|
||||
{
|
||||
uint16_t adc_value = 0;
|
||||
RTC_MODULE_CHECK(channel < ADC2_CHANNEL_MAX, "ADC Channel Err", ESP_ERR_INVALID_ARG);
|
||||
|
||||
//in critical section with whole rtc module
|
||||
adc_power_on();
|
||||
|
||||
//avoid collision with other tasks
|
||||
portENTER_CRITICAL(&adc2_spinlock);
|
||||
//lazy initialization
|
||||
//try the lock, return if failed (wifi using).
|
||||
if ( _lock_try_acquire( &adc2_wifi_lock ) == -1 ) {
|
||||
portEXIT_CRITICAL( &adc2_spinlock );
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
//in critical section with whole rtc module
|
||||
adc2_config_width( width_bit );
|
||||
|
||||
//Adc Controler is Rtc module,not ulp coprocessor
|
||||
SENS.sar_meas_start2.meas2_start_force = 1; //force pad mux and force start
|
||||
//Open the ADC2 Data port Not ulp coprocessor
|
||||
SENS.sar_meas_start2.sar2_en_pad_force = 1; //open the ADC2 data port
|
||||
//Select channel
|
||||
SENS.sar_meas_start2.sar2_en_pad = 1 << channel; //pad enable
|
||||
SENS.sar_meas_start2.meas2_start_sar = 0; //start force 0
|
||||
SENS.sar_meas_start2.meas2_start_sar = 1; //start force 1
|
||||
while (SENS.sar_meas_start2.meas2_done_sar == 0) {}; //read done
|
||||
adc_value = SENS.sar_meas_start2.meas2_data_sar;
|
||||
_lock_release( &adc2_wifi_lock );
|
||||
portEXIT_CRITICAL(&adc2_spinlock);
|
||||
|
||||
*raw_out = (int)adc_value;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
|
||||
{
|
||||
int channel;
|
||||
@ -1014,19 +1461,19 @@ esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
|
||||
rtc_gpio_pullup_dis(gpio);
|
||||
rtc_gpio_pulldown_dis(gpio);
|
||||
|
||||
SET_PERI_REG_BITS(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN, 0, RTC_CNTL_DBG_ATTEN_S); //Check DBG effect outside sleep mode
|
||||
RTCCNTL.bias_conf.dbg_atten = 0; //Check DBG effect outside sleep mode
|
||||
//set dtest (MUX_SEL : 0 -> RTC; 1-> vdd_sar2)
|
||||
SET_PERI_REG_BITS(RTC_CNTL_TEST_MUX_REG, RTC_CNTL_DTEST_RTC, 1, RTC_CNTL_DTEST_RTC_S); //Config test mux to route v_ref to ADC2 Channels
|
||||
RTCCNTL.test_mux.dtest_rtc = 1; //Config test mux to route v_ref to ADC2 Channels
|
||||
//set ent
|
||||
SET_PERI_REG_MASK(RTC_CNTL_TEST_MUX_REG, RTC_CNTL_ENT_RTC_M);
|
||||
RTCCNTL.test_mux.ent_rtc = 1;
|
||||
//set sar2_en_test
|
||||
SET_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_SAR2_EN_TEST_M);
|
||||
SENS.sar_start_force.sar2_en_test = 1;
|
||||
//force fsm
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 3, SENS_FORCE_XPD_SAR_S); //Select power source of ADC
|
||||
SENS.sar_meas_wait2.force_xpd_sar = ADC_FORCE_ENABLE; //Select power source of ADC
|
||||
//set sar2 en force
|
||||
SET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_SAR2_EN_PAD_FORCE_M); //Pad bitmap controlled by SW
|
||||
SENS.sar_meas_start2.sar2_en_pad_force = 1; //Pad bitmap controlled by SW
|
||||
//set en_pad for channels 7,8,9 (bits 0x380)
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_START2_REG, SENS_SAR2_EN_PAD, 1<<channel, SENS_SAR2_EN_PAD_S);
|
||||
SENS.sar_meas_start2.sar2_en_pad = 1<<channel;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -1034,7 +1481,7 @@ esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
|
||||
/*---------------------------------------------------------------
|
||||
DAC
|
||||
---------------------------------------------------------------*/
|
||||
static esp_err_t dac_pad_get_io_num(dac_channel_t channel, gpio_num_t *gpio_num)
|
||||
esp_err_t dac_pad_get_io_num(dac_channel_t channel, gpio_num_t *gpio_num)
|
||||
{
|
||||
RTC_MODULE_CHECK((channel >= DAC_CHANNEL_1) && (channel < DAC_CHANNEL_MAX), DAC_ERR_STR_CHANNEL_ERROR, ESP_ERR_INVALID_ARG);
|
||||
RTC_MODULE_CHECK(gpio_num, "Param null", ESP_ERR_INVALID_ARG);
|
||||
@ -1177,20 +1624,23 @@ static int hall_sensor_get_value() //hall sensor without LNA
|
||||
int Sens_Vp1;
|
||||
int Sens_Vn1;
|
||||
int hall_value;
|
||||
|
||||
adc_power_on();
|
||||
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_XPD_HALL_FORCE_M); // hall sens force enable
|
||||
SET_PERI_REG_MASK(RTC_IO_HALL_SENS_REG, RTC_IO_XPD_HALL); // xpd hall
|
||||
SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_HALL_PHASE_FORCE_M); // phase force
|
||||
CLEAR_PERI_REG_MASK(RTC_IO_HALL_SENS_REG, RTC_IO_HALL_PHASE); // hall phase
|
||||
SENS.sar_touch_ctrl1.xpd_hall_force = 1; // hall sens force enable
|
||||
RTCIO.hall_sens.xpd_hall = 1; // xpd hall
|
||||
SENS.sar_touch_ctrl1.hall_phase_force = 1; // phase force
|
||||
|
||||
RTCIO.hall_sens.hall_phase = 0; // hall phase
|
||||
Sens_Vp0 = adc1_get_raw(ADC1_CHANNEL_0);
|
||||
Sens_Vn0 = adc1_get_raw(ADC1_CHANNEL_3);
|
||||
SET_PERI_REG_MASK(RTC_IO_HALL_SENS_REG, RTC_IO_HALL_PHASE);
|
||||
RTCIO.hall_sens.hall_phase = 1;
|
||||
Sens_Vp1 = adc1_get_raw(ADC1_CHANNEL_0);
|
||||
Sens_Vn1 = adc1_get_raw(ADC1_CHANNEL_3);
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 0, SENS_FORCE_XPD_SAR_S);
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_XPD_HALL_FORCE);
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_HALL_PHASE_FORCE);
|
||||
|
||||
SENS.sar_touch_ctrl1.xpd_hall_force = 0;
|
||||
SENS.sar_touch_ctrl1.hall_phase_force = 0;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
hall_value = (Sens_Vp1 - Sens_Vp0) - (Sens_Vn1 - Sens_Vn0);
|
||||
|
||||
@ -1199,10 +1649,10 @@ static int hall_sensor_get_value() //hall sensor without LNA
|
||||
|
||||
int hall_sensor_read()
|
||||
{
|
||||
adc1_pad_init(ADC1_CHANNEL_0);
|
||||
adc1_pad_init(ADC1_CHANNEL_3);
|
||||
adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_0db);
|
||||
adc1_config_channel_atten(ADC1_CHANNEL_3, ADC_ATTEN_0db);
|
||||
adc_gpio_init(ADC_UNIT_1, ADC1_CHANNEL_0);
|
||||
adc_gpio_init(ADC_UNIT_1, ADC1_CHANNEL_3);
|
||||
adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_DB_0);
|
||||
adc1_config_channel_atten(ADC1_CHANNEL_3, ADC_ATTEN_DB_0);
|
||||
return hall_sensor_get_value();
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <string.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_pm.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
@ -33,13 +34,6 @@
|
||||
*/
|
||||
#define SDMMC_DMA_DESC_CNT 4
|
||||
|
||||
/* Max delay value is mostly useful for cases when CD pin is not used, and
|
||||
* the card is removed. In this case, SDMMC peripheral may not always return
|
||||
* CMD_DONE / DATA_DONE interrupts after signaling the error. This delay works
|
||||
* as a safety net in such cases.
|
||||
*/
|
||||
#define SDMMC_MAX_EVT_WAIT_DELAY_MS 1000
|
||||
|
||||
static const char* TAG = "sdmmc_req";
|
||||
|
||||
typedef enum {
|
||||
@ -74,6 +68,9 @@ static sdmmc_desc_t s_dma_desc[SDMMC_DMA_DESC_CNT];
|
||||
static sdmmc_transfer_state_t s_cur_transfer = { 0 };
|
||||
static QueueHandle_t s_request_mutex;
|
||||
static bool s_is_app_cmd; // This flag is set if the next command is an APP command
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
static esp_pm_lock_handle_t s_pm_lock;
|
||||
#endif
|
||||
|
||||
static esp_err_t handle_idle_state_events();
|
||||
static sdmmc_hw_cmd_t make_hw_cmd(sdmmc_command_t* cmd);
|
||||
@ -90,12 +87,24 @@ esp_err_t sdmmc_host_transaction_handler_init()
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
s_is_app_cmd = false;
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_err_t err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "sdmmc", &s_pm_lock);
|
||||
if (err != ESP_OK) {
|
||||
vSemaphoreDelete(s_request_mutex);
|
||||
s_request_mutex = NULL;
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void sdmmc_host_transaction_handler_deinit()
|
||||
{
|
||||
assert(s_request_mutex);
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_lock_delete(s_pm_lock);
|
||||
s_pm_lock = NULL;
|
||||
#endif
|
||||
vSemaphoreDelete(s_request_mutex);
|
||||
s_request_mutex = NULL;
|
||||
}
|
||||
@ -103,6 +112,9 @@ void sdmmc_host_transaction_handler_deinit()
|
||||
esp_err_t sdmmc_host_do_transaction(int slot, sdmmc_command_t* cmdinfo)
|
||||
{
|
||||
xSemaphoreTake(s_request_mutex, portMAX_DELAY);
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_lock_acquire(s_pm_lock);
|
||||
#endif
|
||||
// dispose of any events which happened asynchronously
|
||||
handle_idle_state_events();
|
||||
// convert cmdinfo to hardware register value
|
||||
@ -148,6 +160,9 @@ esp_err_t sdmmc_host_do_transaction(int slot, sdmmc_command_t* cmdinfo)
|
||||
}
|
||||
}
|
||||
s_is_app_cmd = (ret == ESP_OK && cmdinfo->opcode == MMC_APP_CMD);
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_lock_release(s_pm_lock);
|
||||
#endif
|
||||
xSemaphoreGive(s_request_mutex);
|
||||
return ret;
|
||||
}
|
||||
@ -206,7 +221,7 @@ static esp_err_t handle_idle_state_events()
|
||||
static esp_err_t handle_event(sdmmc_command_t* cmd, sdmmc_req_state_t* state)
|
||||
{
|
||||
sdmmc_event_t evt;
|
||||
esp_err_t err = sdmmc_host_wait_for_event(SDMMC_MAX_EVT_WAIT_DELAY_MS / portTICK_PERIOD_MS, &evt);
|
||||
esp_err_t err = sdmmc_host_wait_for_event(cmd->timeout_ms / portTICK_PERIOD_MS, &evt);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "sdmmc_host_wait_for_event returned 0x%x", err);
|
||||
if (err == ESP_ERR_TIMEOUT) {
|
||||
|
@ -396,8 +396,7 @@ bool IRAM_ATTR spicommon_dmaworkaround_req_reset(int dmachan, dmaworkaround_cb_t
|
||||
ret = false;
|
||||
} else {
|
||||
//Reset DMA
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_DMA_RST);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_DMA_RST);
|
||||
periph_module_reset( PERIPH_SPI_DMA_MODULE );
|
||||
ret = true;
|
||||
}
|
||||
portEXIT_CRITICAL(&dmaworkaround_mux);
|
||||
@ -415,8 +414,7 @@ void IRAM_ATTR spicommon_dmaworkaround_idle(int dmachan)
|
||||
dmaworkaround_channels_busy[dmachan-1] = 0;
|
||||
if (dmaworkaround_waiting_for_chan == dmachan) {
|
||||
//Reset DMA
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_DMA_RST);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_DMA_RST);
|
||||
periph_module_reset( PERIPH_SPI_DMA_MODULE );
|
||||
dmaworkaround_waiting_for_chan = 0;
|
||||
//Call callback
|
||||
dmaworkaround_cb(dmaworkaround_cb_arg);
|
||||
|
@ -47,6 +47,7 @@ queue and re-enabling the interrupt will trigger the interrupt again, which can
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_pm.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
@ -84,6 +85,9 @@ typedef struct {
|
||||
bool no_gpio_matrix;
|
||||
int dma_chan;
|
||||
int max_transfer_sz;
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_lock_handle_t pm_lock;
|
||||
#endif
|
||||
} spi_host_t;
|
||||
|
||||
struct spi_device_t {
|
||||
@ -129,6 +133,13 @@ esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus
|
||||
spihost[host]=malloc(sizeof(spi_host_t));
|
||||
if (spihost[host]==NULL) goto nomem;
|
||||
memset(spihost[host], 0, sizeof(spi_host_t));
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_err_t err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "spi_master",
|
||||
&spihost[host]->pm_lock);
|
||||
if (err != ESP_OK) {
|
||||
goto nomem;
|
||||
}
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
spicommon_bus_initialize_io(host, bus_config, dma_chan, SPICOMMON_BUSFLAG_MASTER|SPICOMMON_BUSFLAG_QUAD, &native);
|
||||
spihost[host]->no_gpio_matrix=native;
|
||||
@ -180,9 +191,15 @@ nomem:
|
||||
if (spihost[host]) {
|
||||
free(spihost[host]->dmadesc_tx);
|
||||
free(spihost[host]->dmadesc_rx);
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
if (spihost[host]->pm_lock) {
|
||||
esp_pm_lock_delete(spihost[host]->pm_lock);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
free(spihost[host]);
|
||||
spicommon_periph_free(host);
|
||||
spicommon_dma_chan_free(dma_chan);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
@ -198,6 +215,9 @@ esp_err_t spi_bus_free(spi_host_device_t host)
|
||||
if ( spihost[host]->dma_chan > 0 ) {
|
||||
spicommon_dma_chan_free ( spihost[host]->dma_chan );
|
||||
}
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_lock_delete(spihost[host]->pm_lock);
|
||||
#endif
|
||||
spihost[host]->hw->slave.trans_inten=0;
|
||||
spihost[host]->hw->slave.trans_done=0;
|
||||
esp_intr_free(spihost[host]->intr);
|
||||
@ -411,6 +431,10 @@ static void IRAM_ATTR spi_intr(void *arg)
|
||||
if (i==NO_CS) {
|
||||
//No packet waiting. Disable interrupt.
|
||||
esp_intr_disable(host->intr);
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
//Release APB frequency lock
|
||||
esp_pm_lock_release(host->pm_lock);
|
||||
#endif
|
||||
} else {
|
||||
host->hw->slave.trans_done=0; //clear int bit
|
||||
//We have a transaction. Send it.
|
||||
@ -648,6 +672,9 @@ esp_err_t spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t *
|
||||
// else use the original buffer (forced-conversion) or assign to NULL
|
||||
trans_buf.buffer_to_send = (uint32_t*)txdata;
|
||||
}
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_lock_acquire(handle->host->pm_lock);
|
||||
#endif
|
||||
|
||||
r=xQueueSend(handle->trans_queue, (void*)&trans_buf, ticks_to_wait);
|
||||
if (!r) return ESP_ERR_TIMEOUT;
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_pm.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
@ -60,6 +61,9 @@ typedef struct {
|
||||
QueueHandle_t trans_queue;
|
||||
QueueHandle_t ret_queue;
|
||||
int dma_chan;
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_lock_handle_t pm_lock;
|
||||
#endif
|
||||
} spi_slave_t;
|
||||
|
||||
static spi_slave_t *spihost[3];
|
||||
@ -68,12 +72,21 @@ static void IRAM_ATTR spi_intr(void *arg);
|
||||
|
||||
esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *bus_config, const spi_slave_interface_config_t *slave_config, int dma_chan)
|
||||
{
|
||||
bool native, claimed;
|
||||
bool native, spi_chan_claimed, dma_chan_claimed;
|
||||
//We only support HSPI/VSPI, period.
|
||||
SPI_CHECK(VALID_HOST(host), "invalid host", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK( dma_chan >= 0 && dma_chan <= 2, "invalid dma channel", ESP_ERR_INVALID_ARG );
|
||||
|
||||
claimed = spicommon_periph_claim(host);
|
||||
SPI_CHECK(claimed, "host already in use", ESP_ERR_INVALID_STATE);
|
||||
spi_chan_claimed=spicommon_periph_claim(host);
|
||||
SPI_CHECK(spi_chan_claimed, "host already in use", ESP_ERR_INVALID_STATE);
|
||||
|
||||
if ( dma_chan != 0 ) {
|
||||
dma_chan_claimed=spicommon_dma_chan_claim(dma_chan);
|
||||
if ( !dma_chan_claimed ) {
|
||||
spicommon_periph_free( host );
|
||||
SPI_CHECK(dma_chan_claimed, "dma channel already in use", ESP_ERR_INVALID_STATE);
|
||||
}
|
||||
}
|
||||
|
||||
spihost[host] = malloc(sizeof(spi_slave_t));
|
||||
if (spihost[host] == NULL) goto nomem;
|
||||
@ -97,6 +110,15 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
|
||||
//We're limited to non-DMA transfers: the SPI work registers can hold 64 bytes at most.
|
||||
spihost[host]->max_transfer_sz = 16 * 4;
|
||||
}
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_err_t err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "spi_slave",
|
||||
&spihost[host]->pm_lock);
|
||||
if (err != ESP_OK) {
|
||||
goto nomem;
|
||||
}
|
||||
// Lock APB frequency while SPI slave driver is in use
|
||||
esp_pm_lock_acquire(spihost[host]->pm_lock);
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
//Create queues
|
||||
spihost[host]->trans_queue = xQueueCreate(slave_config->queue_size, sizeof(spi_slave_transaction_t *));
|
||||
@ -175,10 +197,17 @@ nomem:
|
||||
if (spihost[host]->ret_queue) vQueueDelete(spihost[host]->ret_queue);
|
||||
free(spihost[host]->dmadesc_tx);
|
||||
free(spihost[host]->dmadesc_rx);
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
if (spihost[host]->pm_lock) {
|
||||
esp_pm_lock_release(spihost[host]->pm_lock);
|
||||
esp_pm_lock_delete(spihost[host]->pm_lock);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
free(spihost[host]);
|
||||
spihost[host] = NULL;
|
||||
spicommon_periph_free(host);
|
||||
spicommon_dma_chan_free(dma_chan);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
@ -188,8 +217,15 @@ esp_err_t spi_slave_free(spi_host_device_t host)
|
||||
SPI_CHECK(spihost[host], "host not slave", ESP_ERR_INVALID_ARG);
|
||||
if (spihost[host]->trans_queue) vQueueDelete(spihost[host]->trans_queue);
|
||||
if (spihost[host]->ret_queue) vQueueDelete(spihost[host]->ret_queue);
|
||||
if ( spihost[host]->dma_chan > 0 ) {
|
||||
spicommon_dma_chan_free ( spihost[host]->dma_chan );
|
||||
}
|
||||
free(spihost[host]->dmadesc_tx);
|
||||
free(spihost[host]->dmadesc_rx);
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_lock_release(spihost[host]->pm_lock);
|
||||
esp_pm_lock_delete(spihost[host]->pm_lock);
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
free(spihost[host]);
|
||||
spihost[host] = NULL;
|
||||
spicommon_periph_free(host);
|
||||
@ -289,12 +325,20 @@ static void IRAM_ATTR spi_intr(void *arg)
|
||||
if (!host->hw->slave.trans_done) return;
|
||||
|
||||
if (host->cur_trans) {
|
||||
//when data of cur_trans->length are all sent, the slv_rdata_bit
|
||||
//will be the length sent-1 (i.e. cur_trans->length-1 ), otherwise
|
||||
//the length sent.
|
||||
host->cur_trans->trans_len = host->hw->slv_rd_bit.slv_rdata_bit;
|
||||
if ( host->cur_trans->trans_len == host->cur_trans->length - 1 ) {
|
||||
host->cur_trans->trans_len++;
|
||||
}
|
||||
|
||||
if (host->dma_chan == 0 && host->cur_trans->rx_buffer) {
|
||||
//Copy result out
|
||||
uint32_t *data = host->cur_trans->rx_buffer;
|
||||
for (int x = 0; x < host->cur_trans->length; x += 32) {
|
||||
for (int x = 0; x < host->cur_trans->trans_len; x += 32) {
|
||||
uint32_t word;
|
||||
int len = host->cur_trans->length - x;
|
||||
int len = host->cur_trans->trans_len - x;
|
||||
if (len > 32) len = 32;
|
||||
word = host->hw->data_buf[(x / 32)];
|
||||
memcpy(&data[x / 32], &word, (len + 7) / 8);
|
||||
|
115
components/driver/test/test_adc2.c
Normal file
115
components/driver/test/test_adc2.c
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
Tests for the adc2 device driver
|
||||
*/
|
||||
#include "esp_system.h"
|
||||
#include "driver/adc.h"
|
||||
#include "driver/dac.h"
|
||||
#include "unity.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_event_loop.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_log.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
static const char* TAG = "test_adc2";
|
||||
|
||||
#define DEFAULT_SSID "TEST_SSID"
|
||||
#define DEFAULT_PWD "TEST_PASS"
|
||||
|
||||
static esp_err_t event_handler(void *ctx, system_event_t *event)
|
||||
{
|
||||
printf("ev_handle_called.\n");
|
||||
switch(event->event_id) {
|
||||
case SYSTEM_EVENT_STA_START:
|
||||
ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START");
|
||||
//do not actually connect in test case
|
||||
//;
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_GOT_IP:
|
||||
ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP");
|
||||
ESP_LOGI(TAG, "got ip:%s\n",
|
||||
ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip));
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_DISCONNECTED:
|
||||
ESP_LOGI(TAG, "SYSTEM_EVENT_STA_DISCONNECTED");
|
||||
TEST_ESP_OK(esp_wifi_connect());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
TEST_CASE("adc2 work with wifi","[adc]")
|
||||
{
|
||||
int read_raw;
|
||||
int target_value;
|
||||
|
||||
//adc and dac init
|
||||
TEST_ESP_OK( dac_output_enable( DAC_CHANNEL_1 ));
|
||||
TEST_ESP_OK( dac_output_enable( DAC_CHANNEL_2 ));
|
||||
TEST_ESP_OK( dac_output_voltage( DAC_CHANNEL_1, 30 ));
|
||||
TEST_ESP_OK( dac_output_voltage( DAC_CHANNEL_2, 60 ));
|
||||
TEST_ESP_OK( adc2_config_channel_atten( ADC2_CHANNEL_8, ADC_ATTEN_0db ));
|
||||
TEST_ESP_OK( adc2_config_channel_atten( ADC2_CHANNEL_9, ADC_ATTEN_0db ));
|
||||
|
||||
//init wifi
|
||||
printf("nvs init\n");
|
||||
esp_err_t r = nvs_flash_init();
|
||||
if (r == ESP_ERR_NVS_NO_FREE_PAGES) {
|
||||
printf("no free pages, erase..\n");
|
||||
TEST_ESP_OK(nvs_flash_erase());
|
||||
r = nvs_flash_init();
|
||||
}
|
||||
TEST_ESP_OK( r);
|
||||
tcpip_adapter_init();
|
||||
TEST_ESP_OK(esp_event_loop_init(event_handler, NULL));
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
TEST_ESP_OK(esp_wifi_init(&cfg));
|
||||
wifi_config_t wifi_config = {
|
||||
.sta = {
|
||||
.ssid = DEFAULT_SSID,
|
||||
.password = DEFAULT_PWD
|
||||
},
|
||||
};
|
||||
TEST_ESP_OK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
TEST_ESP_OK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
|
||||
|
||||
//test read value
|
||||
TEST_ESP_OK( adc2_get_raw( ADC2_CHANNEL_8, ADC_WIDTH_12Bit, &read_raw ));
|
||||
target_value = 30*4096*3/256; //3 = 3.3/1.1
|
||||
printf("dac set: %d, adc read: %d (target_value: %d)\n", 30, read_raw, target_value );
|
||||
TEST_ASSERT_INT_WITHIN( 600, target_value, read_raw );
|
||||
TEST_ESP_OK( adc2_get_raw( ADC2_CHANNEL_9, ADC_WIDTH_12Bit, &read_raw ));
|
||||
target_value = 60*4096*3/256;
|
||||
printf("dac set: %d, adc read: %d (target_value: %d)\n", 60, read_raw, target_value );
|
||||
TEST_ASSERT_INT_WITHIN( 600, target_value, read_raw );
|
||||
|
||||
//now start wifi
|
||||
printf("wifi start...\n");
|
||||
TEST_ESP_OK(esp_wifi_start());
|
||||
|
||||
//test reading during wifi on
|
||||
TEST_ASSERT_EQUAL( adc2_get_raw( ADC2_CHANNEL_8, ADC_WIDTH_12Bit, &read_raw ), ESP_ERR_TIMEOUT );
|
||||
TEST_ASSERT_EQUAL( adc2_get_raw( ADC2_CHANNEL_9, ADC_WIDTH_12Bit, &read_raw ), ESP_ERR_TIMEOUT );
|
||||
|
||||
//wifi stop again
|
||||
printf("wifi stop...\n");
|
||||
TEST_ESP_OK( esp_wifi_stop() );
|
||||
TEST_ESP_OK(esp_wifi_deinit());
|
||||
nvs_flash_deinit();
|
||||
|
||||
//test read value
|
||||
TEST_ESP_OK( adc2_get_raw( ADC2_CHANNEL_8, ADC_WIDTH_12Bit, &read_raw ));
|
||||
target_value = 30*4096*3/256; //3 = 3.3/1.1
|
||||
printf("dac set: %d, adc read: %d (target_value: %d)\n", 30, read_raw, target_value );
|
||||
TEST_ASSERT_INT_WITHIN( 600, target_value, read_raw );
|
||||
TEST_ESP_OK( adc2_get_raw( ADC2_CHANNEL_9, ADC_WIDTH_12Bit, &read_raw ));
|
||||
target_value = 60*4096*3/256;
|
||||
printf("dac set: %d, adc read: %d (target_value: %d)\n", 60, read_raw, target_value );
|
||||
TEST_ASSERT_INT_WITHIN( 600, target_value, read_raw );
|
||||
|
||||
printf("test passed...\n");
|
||||
|
||||
TEST_IGNORE_MESSAGE("this test case is ignored due to the critical memory leak of tcpip_adapter and event_loop.");
|
||||
}
|
141
components/driver/test/test_spi_slave.c
Normal file
141
components/driver/test/test_spi_slave.c
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
Tests for the spi_slave device driver
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "unity.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "driver/spi_slave.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#define PIN_NUM_MISO 25
|
||||
#define PIN_NUM_MOSI 23
|
||||
#define PIN_NUM_CLK 19
|
||||
#define PIN_NUM_CS 22
|
||||
|
||||
static const char MASTER_TAG[] = "test_master";
|
||||
static const char SLAVE_TAG[] = "test_slave";
|
||||
|
||||
#define MASTER_SEND {0x93, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0xaa, 0xcc, 0xff, 0xee, 0x55, 0x77, 0x88, 0x43}
|
||||
#define SLAVE_SEND { 0xaa, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x13, 0x57, 0x9b, 0xdf, 0x24, 0x68, 0xac, 0xe0 }
|
||||
|
||||
static inline void int_connect( uint32_t gpio, uint32_t sigo, uint32_t sigi )
|
||||
{
|
||||
gpio_matrix_out( gpio, sigo, false, false );
|
||||
gpio_matrix_in( gpio, sigi, false );
|
||||
}
|
||||
|
||||
static void master_init_nodma( spi_device_handle_t* spi)
|
||||
{
|
||||
esp_err_t ret;
|
||||
spi_bus_config_t buscfg={
|
||||
.miso_io_num=PIN_NUM_MISO,
|
||||
.mosi_io_num=PIN_NUM_MOSI,
|
||||
.sclk_io_num=PIN_NUM_CLK,
|
||||
.quadwp_io_num=-1,
|
||||
.quadhd_io_num=-1
|
||||
};
|
||||
spi_device_interface_config_t devcfg={
|
||||
.clock_speed_hz=4*1000*1000, //currently only up to 4MHz for internel connect
|
||||
.mode=0, //SPI mode 0
|
||||
.spics_io_num=PIN_NUM_CS, //CS pin
|
||||
.queue_size=7, //We want to be able to queue 7 transactions at a time
|
||||
.pre_cb=NULL,
|
||||
.cs_ena_posttrans=1,
|
||||
};
|
||||
//Initialize the SPI bus
|
||||
ret=spi_bus_initialize(HSPI_HOST, &buscfg, 0);
|
||||
TEST_ASSERT(ret==ESP_OK);
|
||||
//Attach the LCD to the SPI bus
|
||||
ret=spi_bus_add_device(HSPI_HOST, &devcfg, spi);
|
||||
TEST_ASSERT(ret==ESP_OK);
|
||||
}
|
||||
|
||||
static void slave_init()
|
||||
{
|
||||
//Configuration for the SPI bus
|
||||
spi_bus_config_t buscfg={
|
||||
.mosi_io_num=PIN_NUM_MOSI,
|
||||
.miso_io_num=PIN_NUM_MISO,
|
||||
.sclk_io_num=PIN_NUM_CLK
|
||||
};
|
||||
//Configuration for the SPI slave interface
|
||||
spi_slave_interface_config_t slvcfg={
|
||||
.mode=0,
|
||||
.spics_io_num=PIN_NUM_CS,
|
||||
.queue_size=3,
|
||||
.flags=0,
|
||||
};
|
||||
//Enable pull-ups on SPI lines so we don't detect rogue pulses when no master is connected.
|
||||
gpio_set_pull_mode(PIN_NUM_MOSI, GPIO_PULLUP_ONLY);
|
||||
gpio_set_pull_mode(PIN_NUM_CLK, GPIO_PULLUP_ONLY);
|
||||
gpio_set_pull_mode(PIN_NUM_CS, GPIO_PULLUP_ONLY);
|
||||
//Initialize SPI slave interface
|
||||
TEST_ESP_OK( spi_slave_initialize(VSPI_HOST, &buscfg, &slvcfg, 2) );
|
||||
}
|
||||
|
||||
TEST_CASE("test slave startup","[spi]")
|
||||
{
|
||||
uint8_t master_txbuf[320]=MASTER_SEND;
|
||||
uint8_t master_rxbuf[320];
|
||||
uint8_t slave_txbuf[320]=SLAVE_SEND;
|
||||
uint8_t slave_rxbuf[320];
|
||||
|
||||
spi_device_handle_t spi;
|
||||
//initial master
|
||||
master_init_nodma( &spi );
|
||||
//initial slave
|
||||
slave_init();
|
||||
|
||||
//do internal connection
|
||||
int_connect( PIN_NUM_MOSI, HSPID_OUT_IDX, VSPIQ_IN_IDX );
|
||||
int_connect( PIN_NUM_MISO, VSPIQ_OUT_IDX, HSPID_IN_IDX );
|
||||
int_connect( PIN_NUM_CS, HSPICS0_OUT_IDX, VSPICS0_IN_IDX );
|
||||
int_connect( PIN_NUM_CLK, HSPICLK_OUT_IDX, VSPICLK_IN_IDX );
|
||||
|
||||
for ( int i = 0; i < 3; i ++ ) {
|
||||
//slave send
|
||||
spi_slave_transaction_t slave_t;
|
||||
spi_slave_transaction_t* out;
|
||||
memset(&slave_t, 0, sizeof(spi_slave_transaction_t));
|
||||
slave_t.length=8*32;
|
||||
slave_t.tx_buffer=slave_txbuf+2*i;
|
||||
slave_t.rx_buffer=slave_rxbuf;
|
||||
TEST_ESP_OK( spi_slave_queue_trans( VSPI_HOST, &slave_t, portMAX_DELAY ) );
|
||||
|
||||
//send
|
||||
spi_transaction_t t = {};
|
||||
t.length = 32*(i+1);
|
||||
if ( t.length != 0 ) {
|
||||
t.tx_buffer = master_txbuf+i;
|
||||
t.rx_buffer = master_rxbuf+i;
|
||||
}
|
||||
spi_device_transmit( spi, (spi_transaction_t*)&t );
|
||||
|
||||
//wait for end
|
||||
TEST_ESP_OK( spi_slave_get_trans_result( VSPI_HOST, &out, portMAX_DELAY ) );
|
||||
|
||||
//show result
|
||||
ESP_LOGI(SLAVE_TAG, "trans_len: %d", slave_t.trans_len);
|
||||
ESP_LOG_BUFFER_HEX( "master tx", t.tx_buffer, t.length/8 );
|
||||
ESP_LOG_BUFFER_HEX( "master rx", t.rx_buffer, t.length/8 );
|
||||
ESP_LOG_BUFFER_HEX( "slave tx", slave_t.tx_buffer, (slave_t.trans_len+7)/8);
|
||||
ESP_LOG_BUFFER_HEX( "slave rx", slave_t.rx_buffer, (slave_t.trans_len+7)/8);
|
||||
|
||||
TEST_ASSERT_EQUAL_HEX8_ARRAY( t.tx_buffer, slave_t.rx_buffer, t.length/8 );
|
||||
TEST_ASSERT_EQUAL_HEX8_ARRAY( slave_t.tx_buffer, t.rx_buffer, t.length/8 );
|
||||
|
||||
TEST_ASSERT_EQUAL( t.length, slave_t.trans_len );
|
||||
|
||||
//clean
|
||||
memset( master_rxbuf, 0x66, sizeof(master_rxbuf));
|
||||
memset( slave_rxbuf, 0x66, sizeof(slave_rxbuf));
|
||||
}
|
||||
|
||||
TEST_ASSERT(spi_slave_free(VSPI_HOST) == ESP_OK);
|
||||
|
||||
TEST_ASSERT(spi_bus_remove_device(spi) == ESP_OK);
|
||||
TEST_ASSERT(spi_bus_free(HSPI_HOST) == ESP_OK);
|
||||
|
||||
ESP_LOGI(MASTER_TAG, "test passed.");
|
||||
}
|
@ -35,6 +35,7 @@ static const char* TIMER_TAG = "timer_group";
|
||||
#define TIMER_AUTORELOAD_ERROR "HW TIMER AUTORELOAD ERROR"
|
||||
#define TIMER_SCALE_ERROR "HW TIMER SCALE ERROR"
|
||||
#define TIMER_ALARM_ERROR "HW TIMER ALARM ERROR"
|
||||
#define DIVIDER_RANGE_ERROR "HW TIMER divider outside of [2, 65536] range error"
|
||||
static timg_dev_t *TG[2] = {&TIMERG0, &TIMERG1};
|
||||
static portMUX_TYPE timer_spinlock[TIMER_GROUP_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED};
|
||||
|
||||
@ -123,14 +124,15 @@ esp_err_t timer_set_auto_reload(timer_group_t group_num, timer_idx_t timer_num,
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t timer_set_divider(timer_group_t group_num, timer_idx_t timer_num, uint16_t divider)
|
||||
esp_err_t timer_set_divider(timer_group_t group_num, timer_idx_t timer_num, uint32_t divider)
|
||||
{
|
||||
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
|
||||
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
|
||||
TIMER_CHECK(divider > 1 && divider < 65537, DIVIDER_RANGE_ERROR, ESP_ERR_INVALID_ARG);
|
||||
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
|
||||
int timer_en = TG[group_num]->hw_timer[timer_num].config.enable;
|
||||
TG[group_num]->hw_timer[timer_num].config.enable = 0;
|
||||
TG[group_num]->hw_timer[timer_num].config.divider = divider;
|
||||
TG[group_num]->hw_timer[timer_num].config.divider = (uint16_t) divider;
|
||||
TG[group_num]->hw_timer[timer_num].config.enable = timer_en;
|
||||
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
|
||||
return ESP_OK;
|
||||
@ -209,6 +211,7 @@ esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, const timer
|
||||
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
|
||||
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
|
||||
TIMER_CHECK(config != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);
|
||||
TIMER_CHECK(config->divider > 1 && config->divider < 65537, DIVIDER_RANGE_ERROR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
if(group_num == 0) {
|
||||
periph_module_enable(PERIPH_TIMG0_MODULE);
|
||||
@ -217,7 +220,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]);
|
||||
TG[group_num]->hw_timer[timer_num].config.autoreload = config->auto_reload;
|
||||
TG[group_num]->hw_timer[timer_num].config.divider = config->divider;
|
||||
TG[group_num]->hw_timer[timer_num].config.divider = (uint16_t) config->divider;
|
||||
TG[group_num]->hw_timer[timer_num].config.enable = config->counter_en;
|
||||
TG[group_num]->hw_timer[timer_num].config.increase = config->counter_dir;
|
||||
TG[group_num]->hw_timer[timer_num].config.alarm_en = config->alarm_en;
|
||||
@ -236,10 +239,11 @@ esp_err_t timer_get_config(timer_group_t group_num, timer_idx_t timer_num, timer
|
||||
config->alarm_en = TG[group_num]->hw_timer[timer_num].config.alarm_en;
|
||||
config->auto_reload = TG[group_num]->hw_timer[timer_num].config.autoreload;
|
||||
config->counter_dir = TG[group_num]->hw_timer[timer_num].config.increase;
|
||||
config->counter_dir = TG[group_num]->hw_timer[timer_num].config.divider;
|
||||
config->divider = (TG[group_num]->hw_timer[timer_num].config.divider == 0 ?
|
||||
65536 : TG[group_num]->hw_timer[timer_num].config.divider);
|
||||
config->counter_en = TG[group_num]->hw_timer[timer_num].config.enable;
|
||||
if(TG[group_num]->hw_timer[timer_num].config.level_int_en) {
|
||||
config->intr_type =TIMER_INTR_LEVEL;
|
||||
config->intr_type = TIMER_INTR_LEVEL;
|
||||
}
|
||||
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
|
||||
return ESP_OK;
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_clk.h"
|
||||
#include "malloc.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
@ -42,6 +43,7 @@ static const char* UART_TAG = "uart";
|
||||
#define UART_EMPTY_THRESH_DEFAULT (10)
|
||||
#define UART_FULL_THRESH_DEFAULT (120)
|
||||
#define UART_TOUT_THRESH_DEFAULT (10)
|
||||
#define UART_TX_IDLE_NUM_DEFAULT (0)
|
||||
#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)
|
||||
@ -172,13 +174,25 @@ esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode)
|
||||
esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baud_rate)
|
||||
{
|
||||
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
|
||||
UART_CHECK((baud_rate <= UART_BITRATE_MAX), "baud_rate error", ESP_FAIL);
|
||||
uint32_t clk_div = (((UART_CLK_FREQ) << 4) / baud_rate);
|
||||
esp_err_t ret = ESP_OK;
|
||||
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
|
||||
UART[uart_num]->clk_div.div_int = clk_div >> 4;
|
||||
UART[uart_num]->clk_div.div_frag = clk_div & 0xf;
|
||||
int uart_clk_freq;
|
||||
if (UART[uart_num]->conf0.tick_ref_always_on == 0) {
|
||||
/* this UART has been configured to use REF_TICK */
|
||||
uart_clk_freq = REF_CLK_FREQ;
|
||||
} else {
|
||||
uart_clk_freq = esp_clk_apb_freq();
|
||||
}
|
||||
uint32_t clk_div = (((uart_clk_freq) << 4) / baud_rate);
|
||||
if (clk_div < 16) {
|
||||
/* baud rate is too high for this clock frequency */
|
||||
ret = ESP_ERR_INVALID_ARG;
|
||||
} else {
|
||||
UART[uart_num]->clk_div.div_int = clk_div >> 4;
|
||||
UART[uart_num]->clk_div.div_frag = clk_div & 0xf;
|
||||
}
|
||||
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
|
||||
return ESP_OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate)
|
||||
@ -456,6 +470,17 @@ esp_err_t uart_set_dtr(uart_port_t uart_num, int level)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t uart_set_tx_idle_num(uart_port_t uart_num, uint16_t idle_num)
|
||||
{
|
||||
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
|
||||
UART_CHECK((idle_num <= UART_TX_IDLE_NUM_V), "uart idle num error", ESP_FAIL);
|
||||
|
||||
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
|
||||
UART[uart_num]->idle_conf.tx_idle_num = idle_num;
|
||||
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_config)
|
||||
{
|
||||
esp_err_t r;
|
||||
@ -468,17 +493,20 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf
|
||||
} else if(uart_num == UART_NUM_2) {
|
||||
periph_module_enable(PERIPH_UART2_MODULE);
|
||||
}
|
||||
r=uart_set_hw_flow_ctrl(uart_num, uart_config->flow_ctrl, uart_config->rx_flow_ctrl_thresh);
|
||||
if (r!=ESP_OK) return r;
|
||||
r=uart_set_baudrate(uart_num, uart_config->baud_rate);
|
||||
if (r!=ESP_OK) return r;
|
||||
r = uart_set_hw_flow_ctrl(uart_num, uart_config->flow_ctrl, uart_config->rx_flow_ctrl_thresh);
|
||||
if (r != ESP_OK) return r;
|
||||
|
||||
UART[uart_num]->conf0.val = (
|
||||
(uart_config->parity << UART_PARITY_S)
|
||||
| (uart_config->data_bits << UART_BIT_NUM_S)
|
||||
| ((uart_config->flow_ctrl & UART_HW_FLOWCTRL_CTS) ? UART_TX_FLOW_EN : 0x0)
|
||||
| UART_TICK_REF_ALWAYS_ON_M);
|
||||
r=uart_set_stop_bits(uart_num, uart_config->stop_bits);
|
||||
UART[uart_num]->conf0.val =
|
||||
(uart_config->parity << UART_PARITY_S)
|
||||
| (uart_config->data_bits << UART_BIT_NUM_S)
|
||||
| ((uart_config->flow_ctrl & UART_HW_FLOWCTRL_CTS) ? UART_TX_FLOW_EN : 0x0)
|
||||
| (uart_config->use_ref_tick ? 0 : UART_TICK_REF_ALWAYS_ON_M);
|
||||
|
||||
r = uart_set_baudrate(uart_num, uart_config->baud_rate);
|
||||
if (r != ESP_OK) return r;
|
||||
r = uart_set_tx_idle_num(uart_num, UART_TX_IDLE_NUM_DEFAULT);
|
||||
if (r != ESP_OK) return r;
|
||||
r = uart_set_stop_bits(uart_num, uart_config->stop_bits);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -874,7 +902,7 @@ int uart_write_bytes_with_break(uart_port_t uart_num, const char* src, size_t si
|
||||
int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickType_t ticks_to_wait)
|
||||
{
|
||||
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1));
|
||||
UART_CHECK((buf), "uart_num error", (-1));
|
||||
UART_CHECK((buf), "uart data null", (-1));
|
||||
UART_CHECK((p_uart_obj[uart_num]), "uart driver error", (-1));
|
||||
uint8_t* data = NULL;
|
||||
size_t size;
|
||||
@ -1111,5 +1139,15 @@ esp_err_t uart_driver_delete(uart_port_t uart_num)
|
||||
|
||||
free(p_uart_obj[uart_num]);
|
||||
p_uart_obj[uart_num] = NULL;
|
||||
|
||||
if (uart_num != CONFIG_CONSOLE_UART_NUM ) {
|
||||
if(uart_num == UART_NUM_0) {
|
||||
periph_module_disable(PERIPH_UART0_MODULE);
|
||||
} else if(uart_num == UART_NUM_1) {
|
||||
periph_module_disable(PERIPH_UART1_MODULE);
|
||||
} else if(uart_num == UART_NUM_2) {
|
||||
periph_module_disable(PERIPH_UART2_MODULE);
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -127,6 +127,13 @@ config SPIRAM_MALLOC_ALWAYSINTERNAL
|
||||
than this size in internal memory, while allocations larger than this will be done from external RAM.
|
||||
If allocation from the preferred region fails, an attempt is made to allocate from the non-preferred
|
||||
region instead, so malloc() will not suddenly fail when either internal or external memory is full.
|
||||
|
||||
config WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST
|
||||
bool "Try to allocate memories of WiFi and LWIP in SPIRAM firstly. If failed, allocate internal memory"
|
||||
depends on SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC
|
||||
default "n"
|
||||
help
|
||||
Try to allocate memories of WiFi and LWIP in SPIRAM firstly. If failed, try to allocate internal memory then.
|
||||
|
||||
config SPIRAM_MALLOC_RESERVE_INTERNAL
|
||||
int "Reserve this amount of bytes for data that specifically needs to be in DMA or internal memory"
|
||||
@ -527,11 +534,10 @@ config INT_WDT_CHECK_CPU1
|
||||
Also detect if interrupts on CPU 1 are disabled for too long.
|
||||
|
||||
config TASK_WDT
|
||||
bool "Initialize Task Watchdog on startup"
|
||||
bool "Task watchdog"
|
||||
default y
|
||||
help
|
||||
This watchdog timer can be used to make sure individual tasks are still running.
|
||||
The Task Watchdog timer can be initialized at run time as well
|
||||
|
||||
config TASK_WDT_PANIC
|
||||
bool "Invoke panic handler when Task Watchdog is triggered"
|
||||
@ -540,46 +546,33 @@ config TASK_WDT_PANIC
|
||||
help
|
||||
Normally, the Task Watchdog will only print out a warning if it detects it has not
|
||||
been fed. If this is enabled, it will invoke the panic handler instead, which
|
||||
can then halt or reboot the chip. This can also be configured at run time
|
||||
by reinitializing the task watchdog.
|
||||
can then halt or reboot the chip.
|
||||
|
||||
config TASK_WDT_TIMEOUT_S
|
||||
int "Task watchdog timeout (ms)"
|
||||
int "Task watchdog timeout (seconds)"
|
||||
depends on TASK_WDT
|
||||
range 1 60000
|
||||
default 5000
|
||||
range 1 60
|
||||
default 5
|
||||
help
|
||||
Timeout for the task WDT, in ms.
|
||||
Timeout for the task WDT, in seconds.
|
||||
|
||||
config TASK_WDT_CHECK_IDLE_TASK_CPU0
|
||||
bool "Add CPU0 idle task to task watchdog on startup"
|
||||
config TASK_WDT_CHECK_IDLE_TASK
|
||||
bool "Task watchdog watches CPU0 idle task"
|
||||
depends on TASK_WDT
|
||||
default y
|
||||
help
|
||||
With this turned on, the CPU0 idle task will be added to the task watchdog
|
||||
on startup. Adding the idle task to the task watchdog allows for the detection
|
||||
of CPU starvation. The idle task not being called is usually a symptom of another
|
||||
With this turned on, the task WDT can detect if the idle task is not called within the task
|
||||
watchdog timeout period. The idle task not being called usually is a symptom of another
|
||||
task hoarding the CPU. It is also a bad thing because FreeRTOS household tasks depend on the
|
||||
idle task getting some runtime every now and then.
|
||||
idle task getting some runtime every now and then. Take Care: With this disabled, this
|
||||
watchdog will trigger if no tasks register themselves within the timeout value.
|
||||
|
||||
config TASK_WDT_CHECK_IDLE_TASK_CPU1
|
||||
bool "Add CPU0 idle task to task watchdog on startup"
|
||||
depends on TASK_WDT && !FREERTOS_UNICORE
|
||||
bool "Task watchdog also watches CPU1 idle task"
|
||||
depends on TASK_WDT_CHECK_IDLE_TASK && !FREERTOS_UNICORE
|
||||
default y
|
||||
help
|
||||
With this turned on, the CPU1 idle task will also be added to the task watchdog
|
||||
on startup.
|
||||
|
||||
config TASK_WDT_LEGACY_BEHAVIOR
|
||||
bool "Use legacy behavior for task watchdog"
|
||||
depends on TASK_WDT
|
||||
default n
|
||||
help
|
||||
Task wdt legacy behavior will add a task to the wdt list on its first
|
||||
call to esp_task_wdt_feed(). Furthermore, tasks can only remove
|
||||
themselves from the wdt task list when calling esp_task_wdt_delete().
|
||||
Therefore esp_task_wdt_delete() should be called with no parameters
|
||||
when legacy behavior is enabled.
|
||||
Also check the idle task that runs on CPU1.
|
||||
|
||||
#The brownout detector code is disabled (by making it depend on a nonexisting symbol) because the current revision of ESP32
|
||||
#silicon has a bug in the brown-out detector, rendering it unusable for resetting the CPU.
|
||||
@ -791,44 +784,52 @@ config ESP32_WIFI_STATIC_RX_BUFFER_NUM
|
||||
range 2 25
|
||||
default 10
|
||||
help
|
||||
Set the number of WiFi static rx buffers. Each buffer takes approximately 1.6KB of RAM.
|
||||
Set the number of WiFi static RX buffers. Each buffer takes approximately 1.6KB of RAM.
|
||||
The static rx buffers are allocated when esp_wifi_init is called, they are not freed
|
||||
until esp_wifi_deinit is called.
|
||||
WiFi hardware use these buffers to receive packets, generally larger number for higher
|
||||
throughput but more memory, smaller number for lower throughput but less memory.
|
||||
until esp_wifi_deinit is called.
|
||||
|
||||
WiFi hardware use these buffers to receive all 802.11 frames.
|
||||
A higher number may allow higher throughput but increases memory use.
|
||||
|
||||
config ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM
|
||||
int "Max number of WiFi dynamic RX buffers"
|
||||
range 0 128
|
||||
default 32
|
||||
help
|
||||
Set the number of WiFi dynamic rx buffers, 0 means no limitation for dynamic rx buffer
|
||||
allocation. The size of dynamic rx buffers is not fixed.
|
||||
For each received packet in static rx buffers, WiFi driver makes a copy
|
||||
to dynamic rx buffers and then deliver it to high layer stack. The dynamic rx buffer
|
||||
is freed when the application, such as socket, successfully received the packet.
|
||||
For some applications, the WiFi driver receiving speed is faster than application
|
||||
consuming speed, we may run out of memory if no limitation for the dynamic rx buffer
|
||||
number. Generally the number of dynamic rx buffer should be no less than static
|
||||
rx buffer number if it is not 0.
|
||||
Set the number of WiFi dynamic RX buffers, 0 means unlimited RX buffers will be allocated
|
||||
(provided sufficient free RAM). The size of each dynamic RX buffer depends on the size of
|
||||
the received data frame.
|
||||
|
||||
For each received data frame, the WiFi driver makes a copy to an RX buffer and then delivers
|
||||
it to the high layer TCP/IP stack. The dynamic RX buffer is freed after the higher layer has
|
||||
successfully received the data frame.
|
||||
|
||||
For some applications, WiFi data frames may be received faster than the application can
|
||||
process them. In these cases we may run out of memory if RX buffer number is unlimited (0).
|
||||
|
||||
If a dynamic RX buffer limit is set, it should be at least the number of static RX buffers.
|
||||
|
||||
choice ESP32_WIFI_TX_BUFFER
|
||||
prompt "Type of WiFi TX buffers"
|
||||
default ESP32_WIFI_DYNAMIC_TX_BUFFER
|
||||
help
|
||||
Select type of WiFi tx buffers and show the submenu with the number of WiFi tx buffers choice.
|
||||
If "STATIC" is selected, WiFi tx buffers are allocated when WiFi is initialized and released
|
||||
when WiFi is de-initialized. If "DYNAMIC" is selected, WiFi tx buffer is allocated when tx
|
||||
data is delivered from LWIP to WiFi and released when tx data is sent out by WiFi.
|
||||
The size of each static tx buffers is fixed to about 1.6KB and the size of dynamic tx buffers is
|
||||
depend on the length of the data delivered from LWIP.
|
||||
If PSRAM is enabled, "STATIC" should be selected to guarantee enough WiFi tx buffers.
|
||||
If PSRAM is disabled, "DYNAMIC" should be selected to improve the utilization of RAM.
|
||||
Select type of WiFi TX buffers:
|
||||
|
||||
If "Static" is selected, WiFi TX buffers are allocated when WiFi is initialized and released
|
||||
when WiFi is de-initialized. The size of each static TX buffer is fixed to about 1.6KB.
|
||||
|
||||
If "Dynamic" is selected, each WiFi TX buffer is allocated as needed when a data frame is
|
||||
delivered to the Wifi driver from the TCP/IP stack. The buffer is freed after the data frame
|
||||
has been sent by the WiFi driver. The size of each dynamic TX buffer depends on the length
|
||||
of each data frame sent by the TCP/IP layer.
|
||||
|
||||
If PSRAM is enabled, "Static" should be selected to guarantee enough WiFi TX buffers.
|
||||
If PSRAM is disabled, "Dynamic" should be selected to improve the utilization of RAM.
|
||||
|
||||
config ESP32_WIFI_STATIC_TX_BUFFER
|
||||
bool "STATIC"
|
||||
bool "Static"
|
||||
config ESP32_WIFI_DYNAMIC_TX_BUFFER
|
||||
bool "DYNAMIC"
|
||||
bool "Dynamic"
|
||||
depends on !SPIRAM_USE_MALLOC
|
||||
endchoice
|
||||
|
||||
@ -840,27 +841,31 @@ config ESP32_WIFI_TX_BUFFER_TYPE
|
||||
config ESP32_WIFI_STATIC_TX_BUFFER_NUM
|
||||
int "Max number of WiFi static TX buffers"
|
||||
depends on ESP32_WIFI_STATIC_TX_BUFFER
|
||||
range 16 64
|
||||
default 32
|
||||
range 6 64
|
||||
default 16
|
||||
help
|
||||
Set the number of WiFi static tx buffers. Each buffer takes approximately 1.6KB of RAM.
|
||||
The static rx buffers are allocated when esp_wifi_init is called, they are not released
|
||||
until esp_wifi_deinit is called.
|
||||
For each tx packet from high layer stack, WiFi driver make a copy of it. For some applications,
|
||||
especially the UDP application, the high layer deliver speed is faster than the WiFi tx
|
||||
speed, we may run out of static tx buffers.
|
||||
Set the number of WiFi static TX buffers. Each buffer takes approximately 1.6KB of RAM.
|
||||
The static RX buffers are allocated when esp_wifi_init() is called, they are not released
|
||||
until esp_wifi_deinit() is called.
|
||||
|
||||
For each transmitted data frame from the higher layer TCP/IP stack, the WiFi driver makes a
|
||||
copy of it in a TX buffer. For some applications especially UDP applications, the upper
|
||||
layer can deliver frames faster than WiFi layer can transmit. In these cases, we may run out
|
||||
of TX buffers.
|
||||
|
||||
config ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM
|
||||
int "Max number of WiFi dynamic TX buffers"
|
||||
depends on ESP32_WIFI_DYNAMIC_TX_BUFFER
|
||||
range 16 64
|
||||
range 16 128
|
||||
default 32
|
||||
help
|
||||
Set the number of WiFi dynamic tx buffers, 0 means no limitation for dynamic tx buffer
|
||||
allocation. The size of dynamic tx buffers is not fixed.
|
||||
For each tx packet from high layer stack, WiFi driver make a copy of it. For some applications,
|
||||
especially the UDP application, the high layer deliver speed is faster than the WiFi tx
|
||||
speed, we may run out of memory if no limitation for the dynamic tx buffer number.
|
||||
Set the number of WiFi dynamic TX buffers. The size of each dynamic TX buffer is not fixed,
|
||||
it depends on the size of each transmitted data frame.
|
||||
|
||||
For each transmitted frame from the higher layer TCP/IP stack, the WiFi driver makes a copy
|
||||
of it in a TX buffer. For some applications, especially UDP applications, the upper layer
|
||||
can deliver frames faster than WiFi layer can transmit. In these cases, we may run out of TX
|
||||
buffers.
|
||||
|
||||
config ESP32_WIFI_AMPDU_ENABLED
|
||||
bool "WiFi AMPDU"
|
||||
@ -940,3 +945,68 @@ config ESP32_PHY_MAX_TX_POWER
|
||||
default ESP32_PHY_MAX_WIFI_TX_POWER
|
||||
|
||||
endmenu # PHY
|
||||
|
||||
|
||||
menu "Power Management"
|
||||
|
||||
config PM_ENABLE
|
||||
bool "Support for power management"
|
||||
default n
|
||||
help
|
||||
If enabled, application is compiled with support for power management.
|
||||
This option has run-time overhead (increased interrupt latency,
|
||||
longer time to enter idle state), and it also reduces accuracy of
|
||||
RTOS ticks and timers used for timekeeping.
|
||||
Enable this option if application uses power management APIs.
|
||||
|
||||
config PM_DFS_INIT_AUTO
|
||||
bool "Enable dynamic frequency scaling (DFS) at startup"
|
||||
depends on PM_ENABLE
|
||||
default n
|
||||
help
|
||||
If enabled, startup code configures dynamic frequency scaling.
|
||||
Max CPU frequency is set to CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ setting,
|
||||
min frequency is set to XTAL frequency.
|
||||
If disabled, DFS will not be active until the application
|
||||
configures it using esp_pm_configure function.
|
||||
|
||||
config PM_USE_RTC_TIMER_REF
|
||||
bool "Use RTC timer to prevent time drift (EXPERIMENTAL)"
|
||||
depends on PM_ENABLE && (ESP32_TIME_SYSCALL_USE_RTC || ESP32_TIME_SYSCALL_USE_RTC_FRC1)
|
||||
default n
|
||||
help
|
||||
When APB clock frequency changes, high-resolution timer (esp_timer)
|
||||
scale and base value need to be adjusted. Each adjustment may cause
|
||||
small error, and over time such small errors may cause time drift.
|
||||
If this option is enabled, RTC timer will be used as a reference to
|
||||
compensate for the drift.
|
||||
It is recommended that this option is only used if 32k XTAL is selected
|
||||
as RTC clock source.
|
||||
|
||||
config PM_PROFILING
|
||||
bool "Enable profiling counters for PM locks"
|
||||
depends on PM_ENABLE
|
||||
default n
|
||||
help
|
||||
If enabled, esp_pm_* functions will keep track of the amount of time
|
||||
each of the power management locks has been held, and esp_pm_dump_locks
|
||||
function will print this information.
|
||||
This feature can be used to analyze which locks are preventing the chip
|
||||
from going into a lower power state, and see what time the chip spends
|
||||
in each power saving mode. This feature does incur some run-time
|
||||
overhead, so should typically be disabled in production builds.
|
||||
|
||||
config PM_TRACE
|
||||
bool "Enable debug tracing of PM using GPIOs"
|
||||
depends on PM_ENABLE
|
||||
default n
|
||||
help
|
||||
If enabled, some GPIOs will be used to signal events such as RTOS ticks,
|
||||
frequency switching, entry/exit from idle state. Refer to pm_trace.c
|
||||
file for the list of GPIOs.
|
||||
This feature is intended to be used when analyzing/debugging behavior
|
||||
of power management implementation, and should be kept disabled in
|
||||
applications.
|
||||
|
||||
|
||||
endmenu # "Power Management"
|
||||
|
@ -15,10 +15,12 @@
|
||||
#include <stdint.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/param.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_clk.h"
|
||||
#include "esp_clk_internal.h"
|
||||
#include "rom/ets_sys.h"
|
||||
#include "rom/uart.h"
|
||||
#include "rom/rtc.h"
|
||||
@ -27,6 +29,7 @@
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/i2s_reg.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "xtensa/core-macros.h"
|
||||
|
||||
/* Number of cycles to wait from the 32k XTAL oscillator to consider it running.
|
||||
@ -40,14 +43,13 @@
|
||||
|
||||
static void select_rtc_slow_clk(rtc_slow_freq_t slow_clk);
|
||||
|
||||
// g_ticks_us defined in ROMs for PRO and APP CPU
|
||||
extern uint32_t g_ticks_per_us_pro;
|
||||
extern uint32_t g_ticks_per_us_app;
|
||||
|
||||
static const char* TAG = "clk";
|
||||
/*
|
||||
* This function is not exposed as an API at this point,
|
||||
* because FreeRTOS doesn't yet support dynamic changing of
|
||||
* CPU frequency. Also we need to implement hooks for
|
||||
* components which want to be notified of CPU frequency
|
||||
* changes.
|
||||
*/
|
||||
|
||||
|
||||
void esp_clk_init(void)
|
||||
{
|
||||
rtc_config_t cfg = RTC_CONFIG_DEFAULT();
|
||||
@ -90,10 +92,19 @@ void esp_clk_init(void)
|
||||
XTHAL_SET_CCOUNT( XTHAL_GET_CCOUNT() * freq_after / freq_before );
|
||||
}
|
||||
|
||||
int IRAM_ATTR esp_clk_cpu_freq(void)
|
||||
{
|
||||
return g_ticks_per_us_pro * 1000000;
|
||||
}
|
||||
|
||||
int IRAM_ATTR esp_clk_apb_freq(void)
|
||||
{
|
||||
return MIN(g_ticks_per_us_pro, 80) * 1000000;
|
||||
}
|
||||
|
||||
void IRAM_ATTR ets_update_cpu_frequency(uint32_t ticks_per_us)
|
||||
{
|
||||
extern uint32_t g_ticks_per_us_pro; // g_ticks_us defined in ROM for PRO CPU
|
||||
extern uint32_t g_ticks_per_us_app; // same defined for APP CPU
|
||||
/* Update scale factors used by ets_delay_us */
|
||||
g_ticks_per_us_pro = ticks_per_us;
|
||||
g_ticks_per_us_app = ticks_per_us;
|
||||
}
|
||||
@ -226,4 +237,7 @@ void esp_perip_clk_init(void)
|
||||
|
||||
/* Disable WiFi/BT/SDIO clocks. */
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, wifi_bt_sdio_clk);
|
||||
|
||||
/* Enable RNG clock. */
|
||||
periph_module_enable(PERIPH_RNG_MODULE);
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ COMPONENT_ADD_LDFLAGS += $(COMPONENT_PATH)/libhal.a \
|
||||
|
||||
#The cache workaround also needs a c++ standard library recompiled with the workaround.
|
||||
ifdef CONFIG_SPIRAM_CACHE_WORKAROUND
|
||||
COMPONENT_ADD_LDFLAGS += $(COMPONENT_PATH)/libstdcc++-cache-workaround.a
|
||||
COMPONENT_ADD_LDFLAGS += $(COMPONENT_PATH)/libstdc++-psram-workaround.a
|
||||
endif
|
||||
|
||||
ALL_LIB_FILES := $(patsubst %,$(COMPONENT_PATH)/lib/lib%.a,$(LIBS))
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include "esp_panic.h"
|
||||
#include "esp_partition.h"
|
||||
#include "esp_clk.h"
|
||||
|
||||
#if CONFIG_ESP32_ENABLE_COREDUMP
|
||||
#define LOG_LOCAL_LEVEL CONFIG_ESP32_CORE_DUMP_LOG_LEVEL
|
||||
@ -522,10 +523,11 @@ void esp_core_dump_to_uart(XtExcFrame *frame)
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_U0TXD);
|
||||
|
||||
ESP_COREDUMP_LOGI("Press Enter to print core dump to UART...");
|
||||
tm_end = xthal_get_ccount() / (XT_CLOCK_FREQ / 1000) + CONFIG_ESP32_CORE_DUMP_UART_DELAY;
|
||||
const int cpu_ticks_per_ms = esp_clk_cpu_freq() / 1000;
|
||||
tm_end = xthal_get_ccount() / cpu_ticks_per_ms + CONFIG_ESP32_CORE_DUMP_UART_DELAY;
|
||||
ch = esp_core_dump_uart_get_char();
|
||||
while (!(ch == '\n' || ch == '\r')) {
|
||||
tm_cur = xthal_get_ccount() / (XT_CLOCK_FREQ / 1000);
|
||||
tm_cur = xthal_get_ccount() / cpu_ticks_per_ms;
|
||||
if (tm_cur >= tm_end)
|
||||
break;
|
||||
ch = esp_core_dump_uart_get_char();
|
||||
|
@ -64,8 +64,10 @@
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_efuse.h"
|
||||
#include "esp_spiram.h"
|
||||
#include "esp_clk.h"
|
||||
#include "esp_clk_internal.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_pm.h"
|
||||
#include "pm_impl.h"
|
||||
#include "trax.h"
|
||||
|
||||
#define STRINGIFY(s) STRINGIFY2(s)
|
||||
@ -150,6 +152,7 @@ void IRAM_ATTR call_start_cpu0()
|
||||
}
|
||||
|
||||
#if CONFIG_SPIRAM_BOOT_INIT
|
||||
esp_spiram_init_cache();
|
||||
if (esp_spiram_init() != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to init external RAM!");
|
||||
abort();
|
||||
@ -286,9 +289,18 @@ void start_cpu0_default(void)
|
||||
esp_clk_init();
|
||||
esp_perip_clk_init();
|
||||
intr_matrix_clear();
|
||||
|
||||
#ifndef CONFIG_CONSOLE_UART_NONE
|
||||
uart_div_modify(CONFIG_CONSOLE_UART_NUM, (rtc_clk_apb_freq_get() << 4) / CONFIG_CONSOLE_UART_BAUDRATE);
|
||||
#endif
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
const int uart_clk_freq = REF_CLK_FREQ;
|
||||
/* When DFS is enabled, use REFTICK as UART clock source */
|
||||
CLEAR_PERI_REG_MASK(UART_CONF0_REG(CONFIG_CONSOLE_UART_NUM), UART_TICK_REF_ALWAYS_ON);
|
||||
#else
|
||||
const int uart_clk_freq = APB_CLK_FREQ;
|
||||
#endif // CONFIG_PM_DFS_ENABLE
|
||||
uart_div_modify(CONFIG_CONSOLE_UART_NUM, (uart_clk_freq << 4) / CONFIG_CONSOLE_UART_BAUDRATE);
|
||||
#endif // CONFIG_CONSOLE_UART_NONE
|
||||
|
||||
#if CONFIG_BROWNOUT_DET
|
||||
esp_brownout_init();
|
||||
#endif
|
||||
@ -323,6 +335,9 @@ void start_cpu0_default(void)
|
||||
do_global_ctors();
|
||||
#if CONFIG_INT_WDT
|
||||
esp_int_wdt_init();
|
||||
#endif
|
||||
#if CONFIG_TASK_WDT
|
||||
esp_task_wdt_init();
|
||||
#endif
|
||||
esp_cache_err_int_init();
|
||||
esp_crosscore_int_init();
|
||||
@ -333,6 +348,18 @@ void start_cpu0_default(void)
|
||||
spi_flash_init();
|
||||
/* init default OS-aware flash access critical section */
|
||||
spi_flash_guard_set(&g_flash_guard_default_ops);
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_impl_init();
|
||||
#ifdef CONFIG_PM_DFS_INIT_AUTO
|
||||
rtc_cpu_freq_t max_freq;
|
||||
rtc_clk_cpu_freq_from_mhz(CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ, &max_freq);
|
||||
esp_pm_config_esp32_t cfg = {
|
||||
.max_cpu_freq = max_freq,
|
||||
.min_cpu_freq = RTC_CPU_FREQ_XTAL
|
||||
};
|
||||
esp_pm_configure(&cfg);
|
||||
#endif //CONFIG_PM_DFS_INIT_AUTO
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
#if CONFIG_ESP32_ENABLE_COREDUMP
|
||||
esp_core_dump_init();
|
||||
@ -375,8 +402,10 @@ void start_cpu1_default(void)
|
||||
|
||||
static void do_global_ctors(void)
|
||||
{
|
||||
#ifdef CONFIG_CXX_EXCEPTIONS
|
||||
static struct object ob;
|
||||
__register_frame_info( __eh_frame, &ob );
|
||||
#endif
|
||||
|
||||
void (**p)(void);
|
||||
for (p = &__init_array_end - 1; p >= &__init_array_start; --p) {
|
||||
@ -397,30 +426,6 @@ static void main_task(void* args)
|
||||
#endif
|
||||
//Enable allocation in region where the startup stacks were located.
|
||||
heap_caps_enable_nonos_stack_heaps();
|
||||
|
||||
//Initialize task wdt
|
||||
#ifdef CONFIG_TASK_WDT
|
||||
#ifdef CONFIG_TASK_WDT_PANIC
|
||||
esp_task_wdt_init(CONFIG_TASK_WDT_TIMEOUT_S, true);
|
||||
#else
|
||||
esp_task_wdt_init(CONFIG_TASK_WDT_TIMEOUT_S, false);
|
||||
#endif
|
||||
#endif
|
||||
//Add IDLE 0 to task wdt
|
||||
#ifdef CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0
|
||||
TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0);
|
||||
if(idle_0 != NULL){
|
||||
esp_task_wdt_add(idle_0);
|
||||
}
|
||||
#endif
|
||||
//Add IDLE 1 to task wdt
|
||||
#ifdef CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1
|
||||
TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(1);
|
||||
if(idle_1 != NULL){
|
||||
esp_task_wdt_add(idle_1);
|
||||
}
|
||||
#endif
|
||||
|
||||
app_main();
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user