kopia lustrzana https://github.com/espressif/esp-idf
Porównaj commity
25 Commity
40d398199f
...
ea967cf2fb
Autor | SHA1 | Data |
---|---|---|
Roland Dobai | ea967cf2fb | |
Radim Karniš | b6b04bbeff | |
Island | 568b693493 | |
David Čermák | 806b14dd22 | |
Wang Meng Yang | 228f92211b | |
morris | 61210271a8 | |
Rahul Tank | 01902148da | |
luoxu | 9bd8d5f860 | |
morris | b60280e2cf | |
Jiang Jiang Jian | 8c52152369 | |
morris | f3ec76b75b | |
Ondrej Kosta | 5c53238853 | |
Xiao Xufeng | a255e67a84 | |
Sumeet Singh | 234ad8cd1e | |
Euripedes Rocha | 3ba9de778e | |
chenjianhua | 57de44f45b | |
baohongde | 41aa38ddf7 | |
chenjianhua | b69a5fe27c | |
baohongde | ee47bebfad | |
chenjianhua | 1265a44c17 | |
zhanghaipeng | 51f7ddc223 | |
Jin Cheng | 2377b40784 | |
gaoxu | 1df5f07eee | |
Song Ruo Jing | c55a07bf57 | |
xiongweichao | a5662dc290 |
|
@ -172,7 +172,7 @@ config BTDM_CTRL_PINNED_TO_CORE
|
|||
choice BTDM_CTRL_HCI_MODE_CHOICE
|
||||
prompt "HCI mode"
|
||||
help
|
||||
Speicify HCI mode as VHCI or UART(H4)
|
||||
Specify HCI mode as VHCI or UART(H4)
|
||||
|
||||
config BTDM_CTRL_HCI_MODE_VHCI
|
||||
bool "VHCI"
|
||||
|
@ -398,6 +398,14 @@ config BTDM_CTRL_FULL_SCAN_SUPPORTED
|
|||
The full scan function is mainly used to provide BLE scan performance.
|
||||
This is required for scenes with high scan performance requirements, such as BLE Mesh scenes.
|
||||
|
||||
config BTDM_CTRL_SCAN_BACKOFF_UPPERLIMITMAX
|
||||
bool "Disable active scan backoff"
|
||||
default n
|
||||
help
|
||||
Disable active scan backoff. The bluetooth spec requires that scanners should run a backoff procedure to
|
||||
minimize collision of scan request PDUs from nultiple scanners. If scan backoff is disabled, in active
|
||||
scanning, scan request PDU will be sent every time when HW receives scannable ADV PDU.
|
||||
|
||||
config BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP
|
||||
bool "BLE adv report flow control supported"
|
||||
depends on (BTDM_CTRL_MODE_BTDM || BTDM_CTRL_MODE_BLE_ONLY)
|
||||
|
|
|
@ -23,7 +23,7 @@ config BT_CTRL_BLE_STATIC_ACL_TX_BUF_NB
|
|||
default 0
|
||||
help
|
||||
BLE ACL buffer have two methods to be allocated. One is persistent allocating
|
||||
(alloate when controller initialise, never free until controller de-initialise)
|
||||
(allocate when controller initialise, never free until controller de-initialise)
|
||||
another is dynamically allocating (allocate before TX and free after TX).
|
||||
|
||||
choice BT_CTRL_PINNED_TO_CORE_CHOICE
|
||||
|
@ -72,11 +72,11 @@ config BT_CTRL_HCI_TL
|
|||
HCI mode as VHCI or UART(H4)
|
||||
|
||||
config BT_CTRL_ADV_DUP_FILT_MAX
|
||||
int "The maxinum number of 5.0 extend duplicate scan filter"
|
||||
int "The maximum number of 5.0 extend duplicate scan filter"
|
||||
range 1 500
|
||||
default 30
|
||||
help
|
||||
The maxinum number of suplicate scan filter
|
||||
The maximum number of suplicate scan filter
|
||||
|
||||
choice BT_BLE_CCA_MODE
|
||||
prompt "BLE CCA mode"
|
||||
|
@ -475,3 +475,17 @@ config BT_BLE_ADV_DATA_LENGTH_ZERO_AUX
|
|||
When this option is enabled, auxiliary packets will be present in the events of
|
||||
'Non-Connectable and Non-Scannable' regardless of whether the advertising length is 0.
|
||||
If this option is not enabled, auxiliary packets will only be present when the advertising length is not 0.
|
||||
|
||||
config BT_CTRL_CHAN_ASS_EN
|
||||
bool "Enable channel assessment"
|
||||
default y
|
||||
help
|
||||
If this option is enabled, The Controller will records the communication quality
|
||||
for each channel and then start a timer to check and update the channel map every 4 seconds.
|
||||
|
||||
config BT_CTRL_LE_PING_EN
|
||||
bool "Enable LE Ping procedure"
|
||||
default y
|
||||
help
|
||||
If this option is disabled, The Controller will not start the LE authenticated payload timer.
|
||||
This option is used for some compatibility problems related to LE ping procedure.
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
// wakeup request sources
|
||||
enum {
|
||||
BTDM_ASYNC_WAKEUP_SRC_VHCI = 0,
|
||||
BTDM_ASYNC_WAKEUP_REQ_COEX,
|
||||
BTDM_ASYNC_WAKEUP_SRC_DISA,
|
||||
BTDM_ASYNC_WAKEUP_SRC_TMR,
|
||||
BTDM_ASYNC_WAKEUP_SRC_MAX,
|
||||
|
@ -73,12 +74,12 @@ enum {
|
|||
typedef union {
|
||||
struct {
|
||||
uint32_t enable : 1; // whether low power mode is required
|
||||
uint32_t lpclk_sel : 2; // low power clock source
|
||||
uint32_t lpclk_sel : 3; // low power clock source
|
||||
uint32_t mac_bb_pd : 1; // whether hardware(MAC, BB) force-power-down is required during sleep
|
||||
uint32_t wakeup_timer_required : 1; // whether system timer is needed
|
||||
uint32_t no_light_sleep : 1; // do not allow system to enter light sleep after bluetooth is enabled
|
||||
uint32_t main_xtal_pu : 1; // power up main XTAL
|
||||
uint32_t reserved : 25; // reserved
|
||||
uint32_t reserved : 24; // reserved
|
||||
};
|
||||
uint32_t val;
|
||||
} btdm_lpcntl_t;
|
||||
|
@ -110,7 +111,7 @@ do{\
|
|||
} while(0)
|
||||
|
||||
#define OSI_FUNCS_TIME_BLOCKING 0xffffffff
|
||||
#define OSI_VERSION 0x00010007
|
||||
#define OSI_VERSION 0x00010008
|
||||
#define OSI_MAGIC_VALUE 0xFADEBEAD
|
||||
|
||||
/* Types definition
|
||||
|
@ -184,8 +185,12 @@ struct osi_funcs_t {
|
|||
void (* _btdm_sleep_exit_phase3)(void); /* called from task */
|
||||
void (* _coex_wifi_sleep_set)(bool sleep);
|
||||
int (* _coex_core_ble_conn_dyn_prio_get)(bool *low, bool *high);
|
||||
int (* _coex_schm_register_btdm_callback)(void *callback);
|
||||
void (* _coex_schm_status_bit_set)(uint32_t type, uint32_t status);
|
||||
void (* _coex_schm_status_bit_clear)(uint32_t type, uint32_t status);
|
||||
uint32_t (* _coex_schm_interval_get)(void);
|
||||
uint8_t (* _coex_schm_curr_period_get)(void);
|
||||
void *(* _coex_schm_curr_phase_get)(void);
|
||||
void (* _interrupt_on)(int intr_num);
|
||||
void (* _interrupt_off)(int intr_num);
|
||||
void (* _esp_hw_power_down)(void);
|
||||
|
@ -193,6 +198,8 @@ struct osi_funcs_t {
|
|||
void (* _ets_backup_dma_copy)(uint32_t reg, uint32_t mem_addr, uint32_t num, bool to_rem);
|
||||
void (* _ets_delay_us)(uint32_t us);
|
||||
void (* _btdm_rom_table_ready)(void);
|
||||
bool (* _coex_bt_wakeup_request)(void);
|
||||
void (* _coex_bt_wakeup_request_end)(void);
|
||||
};
|
||||
|
||||
|
||||
|
@ -306,14 +313,20 @@ static void btdm_sleep_enter_phase1_wrapper(uint32_t lpcycles);
|
|||
static void btdm_sleep_enter_phase2_wrapper(void);
|
||||
static void btdm_sleep_exit_phase3_wrapper(void);
|
||||
static void coex_wifi_sleep_set_hook(bool sleep);
|
||||
static int coex_schm_register_btdm_callback_wrapper(void *callback);
|
||||
static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status);
|
||||
static void coex_schm_status_bit_clear_wrapper(uint32_t type, uint32_t status);
|
||||
static uint32_t coex_schm_interval_get_wrapper(void);
|
||||
static uint8_t coex_schm_curr_period_get_wrapper(void);
|
||||
static void * coex_schm_curr_phase_get_wrapper(void);
|
||||
static void interrupt_on_wrapper(int intr_num);
|
||||
static void interrupt_off_wrapper(int intr_num);
|
||||
static void btdm_hw_mac_power_up_wrapper(void);
|
||||
static void btdm_hw_mac_power_down_wrapper(void);
|
||||
static void btdm_backup_dma_copy_wrapper(uint32_t reg, uint32_t mem_addr, uint32_t num, bool to_mem);
|
||||
static void btdm_funcs_table_ready_wrapper(void);
|
||||
static bool coex_bt_wakeup_request(void);
|
||||
static void coex_bt_wakeup_request_end(void);
|
||||
|
||||
static void btdm_slp_tmr_callback(void *arg);
|
||||
|
||||
|
@ -371,8 +384,12 @@ static const struct osi_funcs_t osi_funcs_ro = {
|
|||
._btdm_sleep_exit_phase3 = btdm_sleep_exit_phase3_wrapper,
|
||||
._coex_wifi_sleep_set = coex_wifi_sleep_set_hook,
|
||||
._coex_core_ble_conn_dyn_prio_get = NULL,
|
||||
._coex_schm_register_btdm_callback = coex_schm_register_btdm_callback_wrapper,
|
||||
._coex_schm_status_bit_set = coex_schm_status_bit_set_wrapper,
|
||||
._coex_schm_status_bit_clear = coex_schm_status_bit_clear_wrapper,
|
||||
._coex_schm_interval_get = coex_schm_interval_get_wrapper,
|
||||
._coex_schm_curr_period_get = coex_schm_curr_period_get_wrapper,
|
||||
._coex_schm_curr_phase_get = coex_schm_curr_phase_get_wrapper,
|
||||
._interrupt_on = interrupt_on_wrapper,
|
||||
._interrupt_off = interrupt_off_wrapper,
|
||||
._esp_hw_power_down = btdm_hw_mac_power_down_wrapper,
|
||||
|
@ -380,6 +397,8 @@ static const struct osi_funcs_t osi_funcs_ro = {
|
|||
._ets_backup_dma_copy = btdm_backup_dma_copy_wrapper,
|
||||
._ets_delay_us = esp_rom_delay_us,
|
||||
._btdm_rom_table_ready = btdm_funcs_table_ready_wrapper,
|
||||
._coex_bt_wakeup_request = coex_bt_wakeup_request,
|
||||
._coex_bt_wakeup_request_end = coex_bt_wakeup_request_end,
|
||||
};
|
||||
|
||||
static DRAM_ATTR struct osi_funcs_t *osi_funcs_p;
|
||||
|
@ -400,7 +419,7 @@ static DRAM_ATTR uint8_t btdm_lpcycle_us_frac = 0;
|
|||
// semaphore used for blocking VHCI API to wait for controller to wake up
|
||||
static DRAM_ATTR QueueHandle_t s_wakeup_req_sem = NULL;
|
||||
// wakeup timer
|
||||
static DRAM_ATTR esp_timer_handle_t s_btdm_slp_tmr;
|
||||
static DRAM_ATTR esp_timer_handle_t s_btdm_slp_tmr = NULL;
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock;
|
||||
|
@ -853,6 +872,22 @@ static bool async_wakeup_request(int event)
|
|||
semphr_take_wrapper(s_wakeup_req_sem, OSI_FUNCS_TIME_BLOCKING);
|
||||
}
|
||||
break;
|
||||
case BTDM_ASYNC_WAKEUP_REQ_COEX:
|
||||
if (!btdm_power_state_active()) {
|
||||
do_wakeup_request = true;
|
||||
#if CONFIG_PM_ENABLE
|
||||
if (s_lp_stat.pm_lock_released) {
|
||||
esp_pm_lock_acquire(s_pm_lock);
|
||||
s_lp_stat.pm_lock_released = 0;
|
||||
}
|
||||
#endif
|
||||
btdm_wakeup_request();
|
||||
|
||||
if (s_lp_cntl.wakeup_timer_required && s_lp_stat.wakeup_timer_started) {
|
||||
esp_timer_stop(s_btdm_slp_tmr);
|
||||
s_lp_stat.wakeup_timer_started = 0;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -872,6 +907,9 @@ static void async_wakeup_request_end(int event)
|
|||
case BTDM_ASYNC_WAKEUP_SRC_DISA:
|
||||
allow_to_sleep = true;
|
||||
break;
|
||||
case BTDM_ASYNC_WAKEUP_REQ_COEX:
|
||||
allow_to_sleep = false;
|
||||
break;
|
||||
default:
|
||||
allow_to_sleep = true;
|
||||
break;
|
||||
|
@ -891,18 +929,25 @@ static void btdm_funcs_table_ready_wrapper(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status)
|
||||
bool bt_async_wakeup_request(void)
|
||||
{
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
coex_schm_status_bit_set(type, status);
|
||||
#endif
|
||||
return async_wakeup_request(BTDM_ASYNC_WAKEUP_SRC_VHCI);
|
||||
}
|
||||
|
||||
static void coex_schm_status_bit_clear_wrapper(uint32_t type, uint32_t status)
|
||||
void bt_wakeup_request_end(void)
|
||||
{
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
coex_schm_status_bit_clear(type, status);
|
||||
#endif
|
||||
async_wakeup_request_end(BTDM_ASYNC_WAKEUP_SRC_VHCI);
|
||||
}
|
||||
|
||||
static bool coex_bt_wakeup_request(void)
|
||||
{
|
||||
return async_wakeup_request(BTDM_ASYNC_WAKEUP_REQ_COEX);
|
||||
}
|
||||
|
||||
static void coex_bt_wakeup_request_end(void)
|
||||
{
|
||||
async_wakeup_request_end(BTDM_ASYNC_WAKEUP_REQ_COEX);
|
||||
return;
|
||||
}
|
||||
|
||||
bool esp_vhci_host_check_send_available(void)
|
||||
|
@ -1112,6 +1157,147 @@ static void IRAM_ATTR btdm_mac_bb_power_up_cb(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
// init low-power control resources
|
||||
static esp_err_t btdm_low_power_mode_init(esp_bt_controller_config_t *cfg)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
do {
|
||||
// set default values for global states or resources
|
||||
s_lp_stat.val = 0;
|
||||
s_lp_cntl.val = 0;
|
||||
s_lp_cntl.main_xtal_pu = 0;
|
||||
s_wakeup_req_sem = NULL;
|
||||
s_btdm_slp_tmr = NULL;
|
||||
|
||||
// configure and initialize resources
|
||||
s_lp_cntl.enable = (cfg->sleep_mode == ESP_BT_SLEEP_MODE_1) ? 1 : 0;
|
||||
s_lp_cntl.lpclk_sel = (cfg->sleep_mode == ESP_BT_SLEEP_MODE_1) ? cfg->sleep_clock : ESP_BT_SLEEP_CLOCK_MAIN_XTAL;
|
||||
s_lp_cntl.no_light_sleep = 0;
|
||||
|
||||
if (s_lp_cntl.enable) {
|
||||
#if CONFIG_MAC_BB_PD
|
||||
if (!btdm_deep_sleep_mem_init()) {
|
||||
err = ESP_ERR_NO_MEM;
|
||||
break;
|
||||
}
|
||||
s_lp_cntl.mac_bb_pd = 1;
|
||||
#endif
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
s_lp_cntl.wakeup_timer_required = 1;
|
||||
#endif
|
||||
// async wakeup semaphore for VHCI
|
||||
s_wakeup_req_sem = semphr_create_wrapper(1, 0);
|
||||
if (s_wakeup_req_sem == NULL) {
|
||||
err = ESP_ERR_NO_MEM;
|
||||
break;
|
||||
}
|
||||
btdm_vnd_offload_task_register(BTDM_VND_OL_SIG_WAKEUP_TMR, btdm_sleep_exit_phase0);
|
||||
|
||||
if (s_lp_cntl.wakeup_timer_required) {
|
||||
esp_timer_create_args_t create_args = {
|
||||
.callback = btdm_slp_tmr_callback,
|
||||
.arg = NULL,
|
||||
.name = "btSlp",
|
||||
};
|
||||
if ((err = esp_timer_create(&create_args, &s_btdm_slp_tmr)) != ESP_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// set default bluetooth sleep clock cycle and its fractional bits
|
||||
btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
|
||||
btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac);
|
||||
|
||||
if (s_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL) { // External 32 kHz XTAL
|
||||
// check whether or not EXT_CRYS is working
|
||||
if (rtc_clk_slow_src_get() != SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
ESP_LOGW(BT_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock");
|
||||
s_lp_cntl.lpclk_sel = ESP_BT_SLEEP_CLOCK_MAIN_XTAL;
|
||||
#if !CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
|
||||
s_lp_cntl.no_light_sleep = 1;
|
||||
#endif
|
||||
}
|
||||
} else if (s_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_RTC_SLOW) { // Internal 136kHz RC oscillator
|
||||
if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) {
|
||||
ESP_LOGW(BT_LOG_TAG, "Internal 136kHz RC oscillator. The accuracy of this clock is a lot larger than 500ppm which is "
|
||||
"required in Bluetooth communication, so don't select this option in scenarios such as BLE connection state.");
|
||||
} else {
|
||||
ESP_LOGW(BT_LOG_TAG, "Internal 136kHz RC oscillator not detected.");
|
||||
assert(0);
|
||||
}
|
||||
} else if (s_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_MAIN_XTAL) {
|
||||
ESP_LOGI(BT_LOG_TAG, "Bluetooth will use main XTAL as Bluetooth sleep clock.");
|
||||
#if !CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
|
||||
s_lp_cntl.no_light_sleep = 1;
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
s_lp_cntl.no_light_sleep = 1;
|
||||
}
|
||||
|
||||
bool select_src_ret __attribute__((unused));
|
||||
bool set_div_ret __attribute__((unused));
|
||||
if (s_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_MAIN_XTAL) {
|
||||
#ifdef CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
|
||||
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON));
|
||||
s_lp_cntl.main_xtal_pu = 1;
|
||||
#endif
|
||||
select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL);
|
||||
set_div_ret = btdm_lpclk_set_div(esp_clk_xtal_freq() / MHZ);
|
||||
assert(select_src_ret && set_div_ret);
|
||||
btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
|
||||
btdm_lpcycle_us = 1 << (btdm_lpcycle_us_frac);
|
||||
} else if (s_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL) {
|
||||
select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL32K);
|
||||
set_div_ret = btdm_lpclk_set_div(0);
|
||||
assert(select_src_ret && set_div_ret);
|
||||
btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
|
||||
btdm_lpcycle_us = (RTC_CLK_CAL_FRACT > 15) ? (1000000 << (RTC_CLK_CAL_FRACT - 15)) :
|
||||
(1000000 >> (15 - RTC_CLK_CAL_FRACT));
|
||||
assert(btdm_lpcycle_us != 0);
|
||||
} else if (s_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_RTC_SLOW) {
|
||||
select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW);
|
||||
set_div_ret = btdm_lpclk_set_div(0);
|
||||
assert(select_src_ret && set_div_ret);
|
||||
btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
|
||||
btdm_lpcycle_us = esp_clk_slowclk_cal_get();
|
||||
} else {
|
||||
err = ESP_ERR_INVALID_ARG;
|
||||
break;
|
||||
}
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
coex_update_lpclk_interval();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
if (s_lp_cntl.no_light_sleep) {
|
||||
if ((err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "btLS", &s_light_sleep_pm_lock)) != ESP_OK) {
|
||||
break;
|
||||
}
|
||||
ESP_LOGW(BT_LOG_TAG, "light sleep mode will not be able to apply when bluetooth is enabled.");
|
||||
}
|
||||
if ((err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "bt", &s_pm_lock)) != ESP_OK) {
|
||||
break;
|
||||
} else {
|
||||
s_lp_stat.pm_lock_released = 1;
|
||||
}
|
||||
#endif
|
||||
} while (0);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_bt_sleep_clock_t esp_bt_get_lpclk_src(void)
|
||||
{
|
||||
if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_INITED &&
|
||||
btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) {
|
||||
return ESP_BT_SLEEP_CLOCK_NONE;
|
||||
}
|
||||
|
||||
return s_lp_cntl.lpclk_sel;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
||||
{
|
||||
esp_err_t err = ESP_FAIL;
|
||||
|
@ -1147,6 +1333,10 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
|||
ESP_LOGE(BT_LOG_TAG, "SLEEP_MODE_1 enabled but sleep clock not configured");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (cfg->sleep_clock > ESP_BT_SLEEP_CLOCK_RTC_SLOW) {
|
||||
ESP_LOGE(BT_LOG_TAG, "SLEEP_MODE_1 is enabled but this sleep clock is not supported");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
// overwrite some parameters
|
||||
|
@ -1172,133 +1362,10 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
|||
|
||||
ESP_LOGI(BT_LOG_TAG, "BT controller compile version [%s]", btdm_controller_get_compile_version());
|
||||
|
||||
// init low-power control resources
|
||||
do {
|
||||
// set default values for global states or resources
|
||||
s_lp_stat.val = 0;
|
||||
s_lp_cntl.val = 0;
|
||||
s_lp_cntl.main_xtal_pu = 0;
|
||||
s_wakeup_req_sem = NULL;
|
||||
s_btdm_slp_tmr = NULL;
|
||||
|
||||
// configure and initialize resources
|
||||
s_lp_cntl.enable = (cfg->sleep_mode == ESP_BT_SLEEP_MODE_1) ? 1 : 0;
|
||||
s_lp_cntl.no_light_sleep = 0;
|
||||
|
||||
if (s_lp_cntl.enable) {
|
||||
#if CONFIG_MAC_BB_PD
|
||||
if (!btdm_deep_sleep_mem_init()) {
|
||||
err = ESP_ERR_NO_MEM;
|
||||
goto error;
|
||||
}
|
||||
s_lp_cntl.mac_bb_pd = 1;
|
||||
#endif
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
s_lp_cntl.wakeup_timer_required = 1;
|
||||
#endif
|
||||
// async wakeup semaphore for VHCI
|
||||
s_wakeup_req_sem = semphr_create_wrapper(1, 0);
|
||||
if (s_wakeup_req_sem == NULL) {
|
||||
err = ESP_ERR_NO_MEM;
|
||||
goto error;
|
||||
}
|
||||
btdm_vnd_offload_task_register(BTDM_VND_OL_SIG_WAKEUP_TMR, btdm_sleep_exit_phase0);
|
||||
}
|
||||
|
||||
if (s_lp_cntl.wakeup_timer_required) {
|
||||
esp_timer_create_args_t create_args = {
|
||||
.callback = btdm_slp_tmr_callback,
|
||||
.arg = NULL,
|
||||
.name = "btSlp",
|
||||
};
|
||||
if ((err = esp_timer_create(&create_args, &s_btdm_slp_tmr)) != ESP_OK) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
// set default bluetooth sleep clock cycle and its fractional bits
|
||||
btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
|
||||
btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac);
|
||||
|
||||
// set default bluetooth sleep clock source
|
||||
s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value
|
||||
#if CONFIG_BT_CTRL_LPCLK_SEL_EXT_32K_XTAL
|
||||
// check whether or not EXT_CRYS is working
|
||||
if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL32K; // External 32 kHz XTAL
|
||||
} else {
|
||||
ESP_LOGW(BT_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock");
|
||||
#if !CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
|
||||
s_lp_cntl.no_light_sleep = 1;
|
||||
#endif
|
||||
}
|
||||
#elif (CONFIG_BT_CTRL_LPCLK_SEL_MAIN_XTAL)
|
||||
ESP_LOGI(BT_LOG_TAG, "Bluetooth will use main XTAL as Bluetooth sleep clock.");
|
||||
#if !CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
|
||||
s_lp_cntl.no_light_sleep = 1;
|
||||
#endif
|
||||
#elif (CONFIG_BT_CTRL_LPCLK_SEL_RTC_SLOW)
|
||||
// check whether or not internal 150 kHz RC oscillator is working
|
||||
if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) {
|
||||
s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_RTC_SLOW; // Internal 150 kHz RC oscillator
|
||||
ESP_LOGW(BT_LOG_TAG, "Internal 150kHz RC osciallator. The accuracy of this clock is a lot larger than 500ppm which is "
|
||||
"required in Bluetooth communication, so don't select this option in scenarios such as BLE connection state.");
|
||||
} else {
|
||||
ESP_LOGW(BT_LOG_TAG, "Internal 150kHz RC oscillator not detected.");
|
||||
assert(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool select_src_ret __attribute__((unused));
|
||||
bool set_div_ret __attribute__((unused));
|
||||
if (s_lp_cntl.lpclk_sel == BTDM_LPCLK_SEL_XTAL) {
|
||||
#ifdef CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
|
||||
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON));
|
||||
s_lp_cntl.main_xtal_pu = 1;
|
||||
#endif
|
||||
select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL);
|
||||
set_div_ret = btdm_lpclk_set_div(esp_clk_xtal_freq() / MHZ);
|
||||
assert(select_src_ret && set_div_ret);
|
||||
btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
|
||||
btdm_lpcycle_us = 1 << (btdm_lpcycle_us_frac);
|
||||
} else if (s_lp_cntl.lpclk_sel == BTDM_LPCLK_SEL_XTAL32K) {
|
||||
select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL32K);
|
||||
set_div_ret = btdm_lpclk_set_div(0);
|
||||
assert(select_src_ret && set_div_ret);
|
||||
btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
|
||||
btdm_lpcycle_us = (RTC_CLK_CAL_FRACT > 15) ? (1000000 << (RTC_CLK_CAL_FRACT - 15)) :
|
||||
(1000000 >> (15 - RTC_CLK_CAL_FRACT));
|
||||
assert(btdm_lpcycle_us != 0);
|
||||
} else if (s_lp_cntl.lpclk_sel == BTDM_LPCLK_SEL_RTC_SLOW) {
|
||||
select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW);
|
||||
set_div_ret = btdm_lpclk_set_div(0);
|
||||
assert(select_src_ret && set_div_ret);
|
||||
btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
|
||||
btdm_lpcycle_us = esp_clk_slowclk_cal_get();
|
||||
} else {
|
||||
err = ESP_ERR_INVALID_ARG;
|
||||
goto error;
|
||||
}
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
coex_update_lpclk_interval();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
if (s_lp_cntl.no_light_sleep) {
|
||||
if ((err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "btLS", &s_light_sleep_pm_lock)) != ESP_OK) {
|
||||
err = ESP_ERR_NO_MEM;
|
||||
goto error;
|
||||
}
|
||||
ESP_LOGW(BT_LOG_TAG, "light sleep mode will not be able to apply when bluetooth is enabled.");
|
||||
}
|
||||
if ((err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "bt", &s_pm_lock)) != ESP_OK) {
|
||||
err = ESP_ERR_NO_MEM;
|
||||
goto error;
|
||||
} else {
|
||||
s_lp_stat.pm_lock_released = 1;
|
||||
}
|
||||
#endif
|
||||
} while (0);
|
||||
if ((err = btdm_low_power_mode_init(cfg)) != ESP_OK) {
|
||||
ESP_LOGE(BT_LOG_TAG, "Low power module initialization failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
coex_init();
|
||||
|
@ -1336,69 +1403,70 @@ esp_err_t esp_bt_controller_deinit(void)
|
|||
return ESP_OK;
|
||||
}
|
||||
|
||||
// deinit low power control resources
|
||||
static void btdm_low_power_mode_deinit(void)
|
||||
{
|
||||
#if CONFIG_MAC_BB_PD
|
||||
if (s_lp_cntl.mac_bb_pd) {
|
||||
btdm_deep_sleep_mem_deinit();
|
||||
s_lp_cntl.mac_bb_pd = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
if (s_lp_cntl.no_light_sleep) {
|
||||
if (s_light_sleep_pm_lock != NULL) {
|
||||
esp_pm_lock_delete(s_light_sleep_pm_lock);
|
||||
s_light_sleep_pm_lock = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (s_pm_lock != NULL) {
|
||||
esp_pm_lock_delete(s_pm_lock);
|
||||
s_pm_lock = NULL;
|
||||
s_lp_stat.pm_lock_released = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (s_lp_cntl.wakeup_timer_required && s_btdm_slp_tmr != NULL) {
|
||||
if (s_lp_stat.wakeup_timer_started) {
|
||||
esp_timer_stop(s_btdm_slp_tmr);
|
||||
}
|
||||
s_lp_stat.wakeup_timer_started = 0;
|
||||
esp_timer_delete(s_btdm_slp_tmr);
|
||||
s_btdm_slp_tmr = NULL;
|
||||
}
|
||||
|
||||
if (s_lp_cntl.enable) {
|
||||
btdm_vnd_offload_task_deregister(BTDM_VND_OL_SIG_WAKEUP_TMR);
|
||||
if (s_wakeup_req_sem != NULL) {
|
||||
semphr_delete_wrapper(s_wakeup_req_sem);
|
||||
s_wakeup_req_sem = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (s_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_MAIN_XTAL) {
|
||||
#ifdef CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
|
||||
if (s_lp_cntl.main_xtal_pu) {
|
||||
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF));
|
||||
s_lp_cntl.main_xtal_pu = 0;
|
||||
}
|
||||
#endif
|
||||
btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW);
|
||||
btdm_lpclk_set_div(0);
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
coex_update_lpclk_interval();
|
||||
#endif
|
||||
}
|
||||
|
||||
btdm_lpcycle_us = 0;
|
||||
}
|
||||
|
||||
static void bt_controller_deinit_internal(void)
|
||||
{
|
||||
periph_module_disable(PERIPH_BT_MODULE);
|
||||
|
||||
// deinit low power control resources
|
||||
do {
|
||||
|
||||
#if CONFIG_MAC_BB_PD
|
||||
if (s_lp_cntl.mac_bb_pd) {
|
||||
btdm_deep_sleep_mem_deinit();
|
||||
s_lp_cntl.mac_bb_pd = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
if (s_lp_cntl.no_light_sleep) {
|
||||
if (s_light_sleep_pm_lock != NULL) {
|
||||
esp_pm_lock_delete(s_light_sleep_pm_lock);
|
||||
s_light_sleep_pm_lock = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (s_pm_lock != NULL) {
|
||||
esp_pm_lock_delete(s_pm_lock);
|
||||
s_pm_lock = NULL;
|
||||
s_lp_stat.pm_lock_released = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (s_lp_cntl.wakeup_timer_required) {
|
||||
if (s_lp_stat.wakeup_timer_started) {
|
||||
esp_timer_stop(s_btdm_slp_tmr);
|
||||
}
|
||||
s_lp_stat.wakeup_timer_started = 0;
|
||||
esp_timer_delete(s_btdm_slp_tmr);
|
||||
s_btdm_slp_tmr = NULL;
|
||||
}
|
||||
|
||||
if (s_lp_cntl.enable) {
|
||||
btdm_vnd_offload_task_deregister(BTDM_VND_OL_SIG_WAKEUP_TMR);
|
||||
if (s_wakeup_req_sem != NULL) {
|
||||
semphr_delete_wrapper(s_wakeup_req_sem);
|
||||
s_wakeup_req_sem = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (s_lp_cntl.lpclk_sel == BTDM_LPCLK_SEL_XTAL) {
|
||||
#ifdef CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
|
||||
if (s_lp_cntl.main_xtal_pu) {
|
||||
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF));
|
||||
s_lp_cntl.main_xtal_pu = 0;
|
||||
}
|
||||
#endif
|
||||
btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW);
|
||||
btdm_lpclk_set_div(0);
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
coex_update_lpclk_interval();
|
||||
#endif
|
||||
}
|
||||
|
||||
btdm_lpcycle_us = 0;
|
||||
} while (0);
|
||||
btdm_low_power_mode_deinit();
|
||||
|
||||
esp_bt_power_domain_off();
|
||||
#if CONFIG_MAC_BB_PD
|
||||
|
@ -1677,4 +1745,55 @@ static void coex_wifi_sleep_set_hook(bool sleep)
|
|||
{
|
||||
|
||||
}
|
||||
|
||||
static int coex_schm_register_btdm_callback_wrapper(void *callback)
|
||||
{
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
return coex_schm_register_callback(COEX_SCHM_CALLBACK_TYPE_BT, callback);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void coex_schm_status_bit_clear_wrapper(uint32_t type, uint32_t status)
|
||||
{
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
coex_schm_status_bit_clear(type, status);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status)
|
||||
{
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
coex_schm_status_bit_set(type, status);
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32_t coex_schm_interval_get_wrapper(void)
|
||||
{
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
return coex_schm_interval_get();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint8_t coex_schm_curr_period_get_wrapper(void)
|
||||
{
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
return coex_schm_curr_period_get();
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void * coex_schm_curr_phase_get_wrapper(void)
|
||||
{
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
return coex_schm_curr_phase_get();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 889c1149140d330ad173b863a91b667d9f62b853
|
||||
Subproject commit 44341b15e58792946cc65ed8d4483929194d182f
|
|
@ -1 +1 @@
|
|||
Subproject commit e5c0f7256ecf5b5f8eb28c1793051a6b88f95124
|
||||
Subproject commit 76ed4114ee7d081435a3c65793b4c8eb1dfaf199
|
|
@ -1 +1 @@
|
|||
Subproject commit 41bf5fc0926fd6d3fb39cb5107e97f2fc6aed7e5
|
||||
Subproject commit 4934ca903807dd74f7f808dadcd9a478e18fc6c3
|
|
@ -1 +1 @@
|
|||
Subproject commit 0a7f98cdf001a1f5d9be185f57d099bd5c852f31
|
||||
Subproject commit acbe4fe3219cb7ce677be1aa2c4142f308ea4958
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -50,7 +50,7 @@ extern "C" {
|
|||
|
||||
#endif //CONFIG_BT_ENABLED
|
||||
|
||||
#define ESP_BT_CONTROLLER_CONFIG_MAGIC_VAL 0x20221207
|
||||
#define ESP_BT_CONTROLLER_CONFIG_MAGIC_VAL 0x20240315
|
||||
|
||||
/**
|
||||
* @brief Bluetooth mode for controller enable/disable
|
||||
|
@ -167,6 +167,12 @@ the adv packet will be discarded until the memory is restored. */
|
|||
#define BTDM_CONTROLLER_SCO_DATA_PATH_HCI 0 // SCO data is routed to HCI
|
||||
#define BTDM_CONTROLLER_SCO_DATA_PATH_PCM 1 // SCO data path is PCM
|
||||
|
||||
#ifdef CONFIG_BTDM_CTRL_SCAN_BACKOFF_UPPERLIMITMAX
|
||||
#define BTDM_CTRL_SCAN_BACKOFF_UPPERLIMITMAX CONFIG_BTDM_CTRL_SCAN_BACKOFF_UPPERLIMITMAX
|
||||
#else
|
||||
#define BTDM_CTRL_SCAN_BACKOFF_UPPERLIMITMAX 0
|
||||
#endif
|
||||
|
||||
#define BT_CONTROLLER_INIT_CONFIG_DEFAULT() { \
|
||||
.controller_task_stack_size = ESP_TASK_BT_CONTROLLER_STACK, \
|
||||
.controller_task_prio = ESP_TASK_BT_CONTROLLER_PRIO, \
|
||||
|
@ -190,6 +196,7 @@ the adv packet will be discarded until the memory is restored. */
|
|||
.pcm_polar = CONFIG_BTDM_CTRL_PCM_POLAR_EFF, \
|
||||
.hli = BTDM_CTRL_HLI, \
|
||||
.dup_list_refresh_period = SCAN_DUPL_CACHE_REFRESH_PERIOD, \
|
||||
.ble_scan_backoff = BTDM_CTRL_SCAN_BACKOFF_UPPERLIMITMAX, \
|
||||
.magic = ESP_BT_CONTROLLER_CONFIG_MAGIC_VAL, \
|
||||
}
|
||||
|
||||
|
@ -233,6 +240,7 @@ typedef struct {
|
|||
uint8_t pcm_polar; /*!< PCM polar trig (falling clk edge & rising clk edge) */
|
||||
bool hli; /*!< Using high level interrupt or not */
|
||||
uint16_t dup_list_refresh_period; /*!< Duplicate scan list refresh period */
|
||||
bool ble_scan_backoff; /*!< BLE scan backoff */
|
||||
uint32_t magic; /*!< Magic number */
|
||||
} esp_bt_controller_config_t;
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#define ESP_BT_CTRL_CONFIG_MAGIC_VAL 0x5A5AA5A5
|
||||
#define ESP_BT_CTRL_CONFIG_VERSION 0x02401120
|
||||
#define ESP_BT_CTRL_CONFIG_VERSION 0x02404010
|
||||
|
||||
#define ESP_BT_HCI_TL_MAGIC_VALUE 0xfadebead
|
||||
#define ESP_BT_HCI_TL_VERSION 0x00010000
|
||||
|
@ -194,6 +194,18 @@ typedef void (* esp_bt_hci_tl_callback_t) (void *arg, uint8_t status);
|
|||
#define BT_BLE_ADV_DATA_LENGTH_ZERO_AUX (0)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_CTRL_CHAN_ASS_EN)
|
||||
#define BT_CTRL_CHAN_ASS_EN (CONFIG_BT_CTRL_CHAN_ASS_EN)
|
||||
#else
|
||||
#define BT_CTRL_CHAN_ASS_EN (0)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_CTRL_LE_PING_EN)
|
||||
#define BT_CTRL_LE_PING_EN (CONFIG_BT_CTRL_LE_PING_EN)
|
||||
#else
|
||||
#define BT_CTRL_LE_PING_EN (0)
|
||||
#endif
|
||||
|
||||
#define AGC_RECORRECT_EN ((BT_CTRL_AGC_RECORRECT_EN << 0) | (BT_CTRL_CODED_AGC_RECORRECT <<1) | (BT_CTRL_AGC_RECORRECT_NEW << 2))
|
||||
|
||||
#define CFG_MASK_BIT_SCAN_DUPLICATE_OPTION (1<<0)
|
||||
|
@ -241,6 +253,8 @@ typedef void (* esp_bt_hci_tl_callback_t) (void *arg, uint8_t status);
|
|||
.ble_50_feat_supp = BT_CTRL_50_FEATURE_SUPPORT, \
|
||||
.ble_cca_mode = BT_BLE_CCA_MODE, \
|
||||
.ble_data_lenth_zero_aux = BT_BLE_ADV_DATA_LENGTH_ZERO_AUX, \
|
||||
.ble_chan_ass_en = BT_CTRL_CHAN_ASS_EN, \
|
||||
.ble_ping_en = BT_CTRL_LE_PING_EN, \
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -289,7 +303,7 @@ typedef struct {
|
|||
uint8_t sleep_clock; /*!< controller sleep clock */
|
||||
uint8_t ble_st_acl_tx_buf_nb; /*!< controller static ACL TX BUFFER number */
|
||||
uint8_t ble_hw_cca_check; /*!< controller hardware triggered CCA check */
|
||||
uint16_t ble_adv_dup_filt_max; /*!< maxinum number of duplicate scan filter */
|
||||
uint16_t ble_adv_dup_filt_max; /*!< maximum number of duplicate scan filter */
|
||||
bool coex_param_en; /*!< deprecated */
|
||||
uint8_t ce_len_type; /*!< connection event length computation method */
|
||||
bool coex_use_hooks; /*!< deprecated */
|
||||
|
@ -312,7 +326,9 @@ typedef struct {
|
|||
uint16_t dup_list_refresh_period; /*!< duplicate scan list refresh time */
|
||||
bool ble_50_feat_supp; /*!< BLE 5.0 feature support */
|
||||
uint8_t ble_cca_mode; /*!< BLE CCA mode */
|
||||
uint8_t ble_data_lenth_zero_aux; /*!< Config ext adv aux option*/
|
||||
uint8_t ble_data_lenth_zero_aux; /*!< Config ext adv aux option */
|
||||
uint8_t ble_chan_ass_en; /*!< BLE channel assessment enable */
|
||||
uint8_t ble_ping_en; /*!< BLE ping procedure enable */
|
||||
} esp_bt_controller_config_t;
|
||||
|
||||
/**
|
||||
|
@ -600,6 +616,15 @@ void esp_wifi_bt_power_domain_on(void);
|
|||
*/
|
||||
void esp_wifi_bt_power_domain_off(void);
|
||||
|
||||
/**
|
||||
* @brief Get the Bluetooth module sleep clock source.
|
||||
*
|
||||
* Note that this function shall not be invoked before esp_bt_controller_init()
|
||||
*
|
||||
* @return clock source used in Bluetooth low power mode
|
||||
*/
|
||||
esp_bt_sleep_clock_t esp_bt_get_lpclk_src(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
# the component can be registered as WHOLE_ARCHIVE
|
||||
idf_component_register(
|
||||
SRCS "test_app_main.c" "test_uart.c"
|
||||
REQUIRES driver unity
|
||||
REQUIRES driver unity test_utils
|
||||
WHOLE_ARCHIVE
|
||||
)
|
||||
|
|
|
@ -1,29 +1,61 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include "unity.h"
|
||||
#include "driver/uart.h" // for the uart driver access
|
||||
#include "test_utils.h"
|
||||
#include "driver/uart.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h" // for uint32_t esp_random()
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "driver/lp_io.h"
|
||||
#include "soc/uart_periph.h"
|
||||
#include "soc/uart_pins.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
|
||||
#define UART_TAG "Uart"
|
||||
#define UART_NUM1 (UART_NUM_1)
|
||||
#define BUF_SIZE (100)
|
||||
#define UART1_RX_PIN (5)
|
||||
#define UART1_TX_PIN (4)
|
||||
#define UART_BAUD_11520 (11520)
|
||||
#define UART_BAUD_115200 (115200)
|
||||
#define TOLERANCE (0.02) //baud rate error tolerance 2%.
|
||||
|
||||
#define UART1_CTS_PIN (13)
|
||||
typedef struct {
|
||||
uart_port_t port_num;
|
||||
soc_module_clk_t default_src_clk;
|
||||
int tx_pin_num;
|
||||
int rx_pin_num;
|
||||
uint32_t rx_flow_ctrl_thresh;
|
||||
} uart_port_param_t;
|
||||
|
||||
static void uart_config(uint32_t baud_rate, uart_sclk_t source_clk)
|
||||
static bool port_select(uart_port_param_t *port_param)
|
||||
{
|
||||
char argv[10];
|
||||
unity_wait_for_signal_param("select to test 'uart' or 'lp_uart' port", argv, sizeof(argv));
|
||||
|
||||
if (strcmp(argv, "uart") == 0) {
|
||||
port_param->port_num = UART_NUM_1; // Test HP_UART with UART1 port
|
||||
port_param->default_src_clk = UART_SCLK_DEFAULT;
|
||||
port_param->tx_pin_num = 4;
|
||||
port_param->rx_pin_num = 5;
|
||||
port_param->rx_flow_ctrl_thresh = 120;
|
||||
return true;
|
||||
#if SOC_UART_LP_NUM > 0
|
||||
} else if (strcmp(argv, "lp_uart") == 0) {
|
||||
port_param->port_num = LP_UART_NUM_0;
|
||||
port_param->default_src_clk = LP_UART_SCLK_DEFAULT;
|
||||
port_param->tx_pin_num = LP_U0TXD_GPIO_NUM;
|
||||
port_param->rx_pin_num = LP_U0RXD_GPIO_NUM;
|
||||
port_param->rx_flow_ctrl_thresh = 12;
|
||||
return true;
|
||||
#endif
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void uart_config(uart_port_t uart_num, uint32_t baud_rate, uart_sclk_t source_clk)
|
||||
{
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = baud_rate,
|
||||
|
@ -34,49 +66,63 @@ static void uart_config(uint32_t baud_rate, uart_sclk_t source_clk)
|
|||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
};
|
||||
|
||||
uart_driver_install(UART_NUM1, BUF_SIZE * 2, BUF_SIZE * 2, 20, NULL, 0);
|
||||
uart_param_config(UART_NUM1, &uart_config);
|
||||
TEST_ESP_OK(uart_set_loop_back(UART_NUM1, true));
|
||||
TEST_ESP_OK(uart_driver_install(uart_num, BUF_SIZE * 2, BUF_SIZE * 2, 20, NULL, 0));
|
||||
TEST_ESP_OK(uart_param_config(uart_num, &uart_config));
|
||||
TEST_ESP_OK(uart_set_loop_back(uart_num, true));
|
||||
}
|
||||
|
||||
static volatile bool exit_flag, case_end;
|
||||
|
||||
typedef struct {
|
||||
uart_port_t port_num;
|
||||
SemaphoreHandle_t exit_sem;
|
||||
} uart_task1_param_t;
|
||||
|
||||
static void test_task1(void *pvParameters)
|
||||
{
|
||||
SemaphoreHandle_t *sema = (SemaphoreHandle_t *) pvParameters;
|
||||
uart_task1_param_t *param = (uart_task1_param_t *)pvParameters;
|
||||
char* data = (char *) malloc(256);
|
||||
|
||||
while (exit_flag == false) {
|
||||
uart_tx_chars(UART_NUM1, data, 256);
|
||||
uart_tx_chars(param->port_num, data, 256);
|
||||
// The uart_wait_tx_done() function does not block anything if ticks_to_wait = 0.
|
||||
uart_wait_tx_done(UART_NUM1, 0);
|
||||
uart_wait_tx_done(param->port_num, 0);
|
||||
}
|
||||
|
||||
free(data);
|
||||
xSemaphoreGive(*sema);
|
||||
xSemaphoreGive(param->exit_sem);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static void test_task2(void *pvParameters)
|
||||
{
|
||||
uart_port_t uart_num = (uart_port_t)pvParameters;
|
||||
while (exit_flag == false) {
|
||||
// This task obstruct a setting tx_done_sem semaphore in the UART interrupt.
|
||||
// It leads to waiting the ticks_to_wait time in uart_wait_tx_done() function.
|
||||
uart_disable_tx_intr(UART_NUM1);
|
||||
uart_disable_tx_intr(uart_num);
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static void test_task3(void *pvParameters)
|
||||
{
|
||||
uart_config(UART_BAUD_11520, UART_SCLK_DEFAULT);
|
||||
uart_port_param_t port_param = {};
|
||||
TEST_ASSERT(port_select(&port_param));
|
||||
|
||||
uart_port_t uart_num = port_param.port_num;
|
||||
uart_config(uart_num, UART_BAUD_11520, port_param.default_src_clk);
|
||||
|
||||
SemaphoreHandle_t exit_sema = xSemaphoreCreateBinary();
|
||||
uart_task1_param_t task1_param = {
|
||||
.port_num = uart_num,
|
||||
.exit_sem = exit_sema,
|
||||
};
|
||||
exit_flag = false;
|
||||
case_end = false;
|
||||
|
||||
xTaskCreate(test_task1, "tsk1", 2048, &exit_sema, 5, NULL);
|
||||
xTaskCreate(test_task2, "tsk2", 2048, NULL, 5, NULL);
|
||||
xTaskCreate(test_task1, "tsk1", 2048, (void *)&task1_param, 5, NULL);
|
||||
xTaskCreate(test_task2, "tsk2", 2048, (void *)uart_num, 5, NULL);
|
||||
|
||||
printf("Waiting for 5 sec\n");
|
||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||
|
@ -87,7 +133,7 @@ static void test_task3(void *pvParameters)
|
|||
} else {
|
||||
TEST_FAIL_MESSAGE("uart_wait_tx_done is blocked");
|
||||
}
|
||||
TEST_ESP_OK(uart_driver_delete(UART_NUM1));
|
||||
TEST_ESP_OK(uart_driver_delete(uart_num));
|
||||
|
||||
vTaskDelay(2); // wait for test_task1 to exit
|
||||
|
||||
|
@ -104,41 +150,70 @@ TEST_CASE("test uart_wait_tx_done is not blocked when ticks_to_wait=0", "[uart]"
|
|||
|
||||
TEST_CASE("test uart get baud-rate", "[uart]")
|
||||
{
|
||||
#if SOC_UART_SUPPORT_REF_TICK
|
||||
uint32_t baud_rate1 = 0;
|
||||
printf("init uart%d, use reftick, baud rate : %d\n", (int)UART_NUM1, (int)UART_BAUD_11520);
|
||||
uart_config(UART_BAUD_11520, UART_SCLK_REF_TICK);
|
||||
uart_get_baudrate(UART_NUM1, &baud_rate1);
|
||||
printf("get baud rate when use reftick: %d\n", (int)baud_rate1);
|
||||
TEST_ASSERT_UINT32_WITHIN(UART_BAUD_11520 * TOLERANCE, UART_BAUD_11520, baud_rate1);
|
||||
#endif
|
||||
uint32_t baud_rate2 = 0;
|
||||
printf("init uart%d, unuse reftick, baud rate : %d\n", (int)UART_NUM1, (int)UART_BAUD_115200);
|
||||
uart_config(UART_BAUD_115200, UART_SCLK_DEFAULT);
|
||||
uart_get_baudrate(UART_NUM1, &baud_rate2);
|
||||
printf("get baud rate when don't use reftick: %d\n", (int)baud_rate2);
|
||||
TEST_ASSERT_UINT32_WITHIN(UART_BAUD_115200 * TOLERANCE, UART_BAUD_115200, baud_rate2);
|
||||
uart_port_param_t port_param = {};
|
||||
TEST_ASSERT(port_select(&port_param));
|
||||
|
||||
uart_driver_delete(UART_NUM1);
|
||||
ESP_LOGI(UART_TAG, "get baud-rate test passed ....");
|
||||
uart_port_t uart_num = port_param.port_num;
|
||||
soc_module_clk_t uart_clk_srcs[] = SOC_UART_CLKS;
|
||||
uint32_t uart_clk_srcs_num = sizeof(uart_clk_srcs) / sizeof(uart_clk_srcs[0]);
|
||||
|
||||
soc_module_clk_t *clk_srcs = uart_clk_srcs;
|
||||
uint32_t clk_srcs_num = uart_clk_srcs_num;
|
||||
|
||||
#if SOC_UART_LP_NUM > 0
|
||||
soc_module_clk_t lp_uart_clk_srcs[] = SOC_LP_UART_CLKS;
|
||||
uint32_t lp_uart_clk_srcs_num = sizeof(lp_uart_clk_srcs) / sizeof(lp_uart_clk_srcs[0]);
|
||||
|
||||
if (uart_num >= SOC_UART_HP_NUM) {
|
||||
clk_srcs = lp_uart_clk_srcs;
|
||||
clk_srcs_num = lp_uart_clk_srcs_num;
|
||||
}
|
||||
#endif
|
||||
|
||||
uart_config(uart_num, UART_BAUD_115200, port_param.default_src_clk);
|
||||
|
||||
const uint32_t test_baudrate_vals[] = {UART_BAUD_11520, UART_BAUD_115200};
|
||||
for (size_t i = 0; i < sizeof(test_baudrate_vals) / sizeof(test_baudrate_vals[0]); i++) {
|
||||
for (size_t j = 0; j < clk_srcs_num; j++) {
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = test_baudrate_vals[i],
|
||||
.source_clk = clk_srcs[j],
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
};
|
||||
TEST_ESP_OK(uart_param_config(uart_num, &uart_config));
|
||||
|
||||
uint32_t actual_baudrate = 0;
|
||||
uart_get_baudrate(uart_num, &actual_baudrate);
|
||||
TEST_ASSERT_UINT32_WITHIN(test_baudrate_vals[i] * TOLERANCE, test_baudrate_vals[i], actual_baudrate);
|
||||
}
|
||||
}
|
||||
|
||||
uart_driver_delete(uart_num);
|
||||
}
|
||||
|
||||
TEST_CASE("test uart tx data with break", "[uart]")
|
||||
{
|
||||
uart_port_param_t port_param = {};
|
||||
TEST_ASSERT(port_select(&port_param));
|
||||
|
||||
uart_port_t uart_num = port_param.port_num;
|
||||
const int buf_len = 200;
|
||||
const int send_len = 128;
|
||||
const int brk_len = 10;
|
||||
char *psend = (char *)malloc(buf_len);
|
||||
TEST_ASSERT_NOT_NULL(psend);
|
||||
memset(psend, '0', buf_len);
|
||||
uart_config(UART_BAUD_115200, UART_SCLK_DEFAULT);
|
||||
printf("Uart%d send %d bytes with break\n", UART_NUM1, send_len);
|
||||
uart_write_bytes_with_break(UART_NUM1, (const char *)psend, send_len, brk_len);
|
||||
uart_wait_tx_done(UART_NUM1, portMAX_DELAY);
|
||||
uart_config(uart_num, UART_BAUD_115200, port_param.default_src_clk);
|
||||
printf("Uart%d send %d bytes with break\n", uart_num, send_len);
|
||||
uart_write_bytes_with_break(uart_num, (const char *)psend, send_len, brk_len);
|
||||
uart_wait_tx_done(uart_num, portMAX_DELAY);
|
||||
//If the code is running here, it means the test passed, otherwise it will crash due to the interrupt wdt timeout.
|
||||
printf("Send data with break test passed\n");
|
||||
free(psend);
|
||||
uart_driver_delete(UART_NUM1);
|
||||
uart_driver_delete(uart_num);
|
||||
}
|
||||
|
||||
static void uart_word_len_set_get_test(int uart_num)
|
||||
|
@ -210,14 +285,17 @@ static void uart_wakeup_set_get_test(int uart_num)
|
|||
|
||||
TEST_CASE("uart general API test", "[uart]")
|
||||
{
|
||||
const int uart_num = UART_NUM1;
|
||||
uart_port_param_t port_param = {};
|
||||
TEST_ASSERT(port_select(&port_param));
|
||||
|
||||
uart_port_t uart_num = port_param.port_num;
|
||||
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,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
.source_clk = port_param.default_src_clk,
|
||||
};
|
||||
uart_param_config(uart_num, &uart_config);
|
||||
uart_word_len_set_get_test(uart_num);
|
||||
|
@ -229,7 +307,7 @@ TEST_CASE("uart general API test", "[uart]")
|
|||
|
||||
static void uart_write_task(void *param)
|
||||
{
|
||||
int uart_num = (int)param;
|
||||
uart_port_t uart_num = (uart_port_t)param;
|
||||
uint8_t *tx_buf = (uint8_t *)malloc(1024);
|
||||
if(tx_buf == NULL) {
|
||||
TEST_FAIL_MESSAGE("tx buffer malloc fail");
|
||||
|
@ -241,25 +319,19 @@ static void uart_write_task(void *param)
|
|||
//d[0] and d[1023] are header
|
||||
tx_buf[0] = (i & 0xff);
|
||||
tx_buf[1023] = ((~i) & 0xff);
|
||||
uart_write_bytes(uart_num, (const char*)tx_buf, 1024);
|
||||
uart_write_bytes(uart_num, (const char *)tx_buf, 1024);
|
||||
uart_wait_tx_done(uart_num, portMAX_DELAY);
|
||||
}
|
||||
free(tx_buf);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* The following tests use loop back
|
||||
*
|
||||
* NOTE: In the following tests, because the internal loopback is enabled, the CTS signal is connected to
|
||||
* the RTS signal internally. However, On ESP32S3, they are not, and the CTS keeps the default level (which
|
||||
* is a high level). So the workaround is to map the CTS in_signal to a GPIO pin (here IO13 is used) and connect
|
||||
* the RTS output_signal to this IO.
|
||||
*/
|
||||
|
||||
TEST_CASE("uart read write test", "[uart]")
|
||||
{
|
||||
const int uart_num = UART_NUM1;
|
||||
uart_port_param_t port_param = {};
|
||||
TEST_ASSERT(port_select(&port_param));
|
||||
|
||||
uart_port_t uart_num = port_param.port_num;
|
||||
uint8_t *rd_data = (uint8_t *)malloc(1024);
|
||||
if(rd_data == NULL) {
|
||||
TEST_FAIL_MESSAGE("rx buffer malloc fail");
|
||||
|
@ -270,15 +342,13 @@ TEST_CASE("uart read write test", "[uart]")
|
|||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
.rx_flow_ctrl_thresh = 120
|
||||
.source_clk = port_param.default_src_clk,
|
||||
.rx_flow_ctrl_thresh = port_param.rx_flow_ctrl_thresh,
|
||||
};
|
||||
TEST_ESP_OK(uart_driver_install(uart_num, BUF_SIZE * 2, 0, 20, NULL, 0));
|
||||
TEST_ESP_OK(uart_param_config(uart_num, &uart_config));
|
||||
// Use loop back feature to connect TX signal to RX signal, CTS signal to RTS signal internally. Then no need to configure uart pins.
|
||||
TEST_ESP_OK(uart_set_loop_back(uart_num, true));
|
||||
TEST_ESP_OK(uart_set_pin(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART1_CTS_PIN));
|
||||
//Connect the RTS out_signal to the CTS pin (which is mapped to CTS in_signal)
|
||||
esp_rom_gpio_connect_out_signal(UART1_CTS_PIN, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RTS_PIN_IDX), 0, 0);
|
||||
|
||||
TEST_ESP_OK(uart_wait_tx_done(uart_num, portMAX_DELAY));
|
||||
vTaskDelay(pdMS_TO_TICKS(20)); // make sure last byte has flushed from TX FIFO
|
||||
|
@ -322,12 +392,15 @@ TEST_CASE("uart read write test", "[uart]")
|
|||
uart_driver_delete(uart_num);
|
||||
free(rd_data);
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // wait for uart_write_task to exit
|
||||
vTaskDelay(2); // wait for uart_write_task to exit
|
||||
}
|
||||
|
||||
TEST_CASE("uart tx with ringbuffer test", "[uart]")
|
||||
{
|
||||
const int uart_num = UART_NUM1;
|
||||
uart_port_param_t port_param = {};
|
||||
TEST_ASSERT(port_select(&port_param));
|
||||
|
||||
uart_port_t uart_num = port_param.port_num;
|
||||
uint8_t *rd_data = (uint8_t *)malloc(1024);
|
||||
uint8_t *wr_data = (uint8_t *)malloc(1024);
|
||||
if(rd_data == NULL || wr_data == NULL) {
|
||||
|
@ -339,16 +412,14 @@ TEST_CASE("uart tx with ringbuffer test", "[uart]")
|
|||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS,
|
||||
.rx_flow_ctrl_thresh = 120,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
.rx_flow_ctrl_thresh = port_param.rx_flow_ctrl_thresh,
|
||||
.source_clk = port_param.default_src_clk,
|
||||
};
|
||||
uart_wait_tx_idle_polling(uart_num);
|
||||
TEST_ESP_OK(uart_param_config(uart_num, &uart_config));
|
||||
TEST_ESP_OK(uart_driver_install(uart_num, 1024 * 2, 1024 *2, 20, NULL, 0));
|
||||
TEST_ESP_OK(uart_driver_install(uart_num, 1024 * 2, 1024 * 2, 20, NULL, 0));
|
||||
// Use loop back feature to connect TX signal to RX signal, CTS signal to RTS signal internally. Then no need to configure uart pins.
|
||||
TEST_ESP_OK(uart_set_loop_back(uart_num, true));
|
||||
TEST_ESP_OK(uart_set_pin(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART1_CTS_PIN));
|
||||
//Connect the RTS out_signal to the CTS pin (which is mapped to CTS in_signal)
|
||||
esp_rom_gpio_connect_out_signal(UART1_CTS_PIN, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RTS_PIN_IDX), 0, 0);
|
||||
|
||||
for (int i = 0; i < 1024; i++) {
|
||||
wr_data[i] = i;
|
||||
|
@ -358,7 +429,7 @@ TEST_CASE("uart tx with ringbuffer test", "[uart]")
|
|||
size_t tx_buffer_free_space;
|
||||
uart_get_tx_buffer_free_size(uart_num, &tx_buffer_free_space);
|
||||
TEST_ASSERT_EQUAL_INT(2048, tx_buffer_free_space); // full tx buffer space is free
|
||||
uart_write_bytes(uart_num, (const char*)wr_data, 1024);
|
||||
uart_write_bytes(uart_num, (const char *)wr_data, 1024);
|
||||
uart_get_tx_buffer_free_size(uart_num, &tx_buffer_free_space);
|
||||
TEST_ASSERT_LESS_THAN(2048, tx_buffer_free_space); // tx transmit in progress: tx buffer has content
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(1024, tx_buffer_free_space);
|
||||
|
@ -374,56 +445,72 @@ TEST_CASE("uart tx with ringbuffer test", "[uart]")
|
|||
|
||||
TEST_CASE("uart int state restored after flush", "[uart]")
|
||||
{
|
||||
/**
|
||||
* The first goal of this test is to make sure that when our RX FIFO is full,
|
||||
* we can continue receiving back data after flushing
|
||||
* For more details, check IDF-4374
|
||||
*/
|
||||
uart_port_param_t port_param = {};
|
||||
TEST_ASSERT(port_select(&port_param));
|
||||
|
||||
uart_port_t uart_num = port_param.port_num;
|
||||
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,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
.source_clk = port_param.default_src_clk,
|
||||
};
|
||||
|
||||
const uart_port_t uart_echo = UART_NUM_1;
|
||||
const int uart_tx_signal = uart_periph_signal[uart_echo].pins[SOC_UART_TX_PIN_IDX].signal;
|
||||
const int uart_tx = UART1_TX_PIN;
|
||||
const int uart_rx = UART1_RX_PIN;
|
||||
const int uart_tx_signal = uart_periph_signal[uart_num].pins[SOC_UART_TX_PIN_IDX].signal;
|
||||
const int uart_tx = port_param.tx_pin_num;
|
||||
const int uart_rx = port_param.rx_pin_num;
|
||||
const int buf_size = 256;
|
||||
const int intr_alloc_flags = 0;
|
||||
|
||||
TEST_ESP_OK(uart_driver_install(uart_echo, buf_size * 2, 0, 0, NULL, intr_alloc_flags));
|
||||
TEST_ESP_OK(uart_param_config(uart_echo, &uart_config));
|
||||
TEST_ESP_OK(uart_set_pin(uart_echo, uart_tx, uart_rx, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||
TEST_ESP_OK(uart_driver_install(uart_num, buf_size * 2, 0, 0, NULL, intr_alloc_flags));
|
||||
TEST_ESP_OK(uart_param_config(uart_num, &uart_config));
|
||||
TEST_ESP_OK(uart_set_pin(uart_num, uart_tx, uart_rx, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||
|
||||
/* Make sure UART2's RX signal is connected to TX pin
|
||||
/* Make sure UART's TX signal is connected to RX pin
|
||||
* This creates a loop that lets us receive anything we send on the UART */
|
||||
esp_rom_gpio_connect_out_signal(uart_rx, uart_tx_signal, false, false);
|
||||
if (uart_num < SOC_UART_HP_NUM) {
|
||||
esp_rom_gpio_connect_out_signal(uart_rx, uart_tx_signal, false, false);
|
||||
#if SOC_UART_LP_NUM > 0
|
||||
} else {
|
||||
// LP_UART
|
||||
#if SOC_LP_GPIO_MATRIX_SUPPORTED
|
||||
TEST_ESP_OK(lp_gpio_connect_out_signal(uart_rx, uart_tx_signal, false, false));
|
||||
#else
|
||||
// The only way is to use loop back feature
|
||||
TEST_ESP_OK(uart_set_loop_back(uart_num, true));
|
||||
#endif
|
||||
#endif // SOC_UART_LP_NUM > 0
|
||||
}
|
||||
|
||||
uint8_t *data = (uint8_t *) malloc(buf_size);
|
||||
uint8_t *data = (uint8_t *)malloc(buf_size);
|
||||
TEST_ASSERT_NOT_NULL(data);
|
||||
uart_write_bytes(uart_echo, (const char *) data, buf_size);
|
||||
uart_write_bytes(uart_num, (const char *)data, buf_size);
|
||||
|
||||
/* As we set up a loopback, we can read them back on RX */
|
||||
int len = uart_read_bytes(uart_echo, data, buf_size, pdMS_TO_TICKS(1000));
|
||||
int len = uart_read_bytes(uart_num, data, buf_size, pdMS_TO_TICKS(1000));
|
||||
printf("len is %d\n", len);
|
||||
TEST_ASSERT_EQUAL(len, buf_size);
|
||||
|
||||
/**
|
||||
* The first goal of this test is to make sure that when our RX FIFO is full,
|
||||
* we can continue receiving back data after flushing
|
||||
* For more details, check IDF-4374 */
|
||||
|
||||
/* Fill the RX buffer, this should disable the RX interrupts */
|
||||
int written = uart_write_bytes(uart_echo, (const char *) data, buf_size);
|
||||
int written = uart_write_bytes(uart_num, (const char *)data, buf_size);
|
||||
TEST_ASSERT_NOT_EQUAL(-1, written);
|
||||
written = uart_write_bytes(uart_echo, (const char *) data, buf_size);
|
||||
written = uart_write_bytes(uart_num, (const char *)data, buf_size);
|
||||
TEST_ASSERT_NOT_EQUAL(-1, written);
|
||||
written = uart_write_bytes(uart_echo, (const char *) data, buf_size);
|
||||
written = uart_write_bytes(uart_num, (const char *)data, buf_size);
|
||||
TEST_ASSERT_NOT_EQUAL(-1, written);
|
||||
|
||||
/* Flush the input buffer, RX interrupts should be re-enabled */
|
||||
uart_flush_input(uart_echo);
|
||||
written = uart_write_bytes(uart_echo, (const char *) data, buf_size);
|
||||
uart_flush_input(uart_num);
|
||||
written = uart_write_bytes(uart_num, (const char *)data, buf_size);
|
||||
TEST_ASSERT_NOT_EQUAL(-1, written);
|
||||
len = uart_read_bytes(uart_echo, data, buf_size, pdMS_TO_TICKS(1000));
|
||||
len = uart_read_bytes(uart_num, data, buf_size, pdMS_TO_TICKS(1000));
|
||||
/* len equals buf_size bytes if interrupts were indeed re-enabled */
|
||||
TEST_ASSERT_EQUAL(len, buf_size);
|
||||
|
||||
|
@ -433,14 +520,15 @@ TEST_CASE("uart int state restored after flush", "[uart]")
|
|||
* To do so, start by cleaning the RX FIFO, disable the RX interrupts,
|
||||
* flush again, send data to the UART and check that we haven't received
|
||||
* any of the bytes */
|
||||
uart_flush_input(uart_echo);
|
||||
uart_disable_rx_intr(uart_echo);
|
||||
uart_flush_input(uart_echo);
|
||||
written = uart_write_bytes(uart_echo, (const char *) data, buf_size);
|
||||
|
||||
uart_flush_input(uart_num);
|
||||
uart_disable_rx_intr(uart_num);
|
||||
uart_flush_input(uart_num);
|
||||
written = uart_write_bytes(uart_num, (const char *)data, buf_size);
|
||||
TEST_ASSERT_NOT_EQUAL(-1, written);
|
||||
len = uart_read_bytes(uart_echo, data, buf_size, pdMS_TO_TICKS(250));
|
||||
len = uart_read_bytes(uart_num, data, buf_size, pdMS_TO_TICKS(250));
|
||||
TEST_ASSERT_EQUAL(len, 0);
|
||||
|
||||
TEST_ESP_OK(uart_driver_delete(uart_echo));
|
||||
TEST_ESP_OK(uart_driver_delete(uart_num));
|
||||
free(data);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,17 @@
|
|||
# SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
import pytest
|
||||
|
||||
input_argv = {
|
||||
'esp32': ['uart'],
|
||||
'esp32s2': ['uart'],
|
||||
'esp32s3': ['uart'],
|
||||
'esp32c3': ['uart'],
|
||||
'esp32c2': ['uart'],
|
||||
'esp32c6': ['uart', 'lp_uart'],
|
||||
'esp32h2': ['uart'],
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.supported_targets
|
||||
@pytest.mark.generic
|
||||
|
@ -15,4 +24,14 @@ import pytest
|
|||
indirect=True,
|
||||
)
|
||||
def test_uart_single_dev(case_tester) -> None: # type: ignore
|
||||
case_tester.run_all_normal_cases(reset=True)
|
||||
dut = case_tester.dut
|
||||
chip_type = dut.app.target
|
||||
for uart_port in input_argv.get(chip_type, []):
|
||||
for case in case_tester.test_menu:
|
||||
dut.serial.hard_reset()
|
||||
dut._get_ready()
|
||||
dut.confirm_write(case.index, expect_str=f'Running {case.name}...')
|
||||
|
||||
dut.expect("select to test 'uart' or 'lp_uart' port", timeout=10)
|
||||
dut.write(f'{uart_port}')
|
||||
dut.expect_unity_test_output()
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
@ -20,6 +16,10 @@ extern "C" {
|
|||
#include "freertos/ringbuf.h"
|
||||
#include "hal/uart_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* @brief When calling `uart_set_pin`, instead of GPIO number, `UART_PIN_NO_CHANGE`
|
||||
* can be provided to keep the currently allocated pin.
|
||||
*/
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
static const char *UART_TAG = "uart";
|
||||
|
||||
#define UART_EMPTY_THRESH_DEFAULT (10)
|
||||
#define LP_UART_EMPTY_THRESH_DEFAULT (2)
|
||||
#define LP_UART_EMPTY_THRESH_DEFAULT (4)
|
||||
#define UART_FULL_THRESH_DEFAULT (120)
|
||||
#define LP_UART_FULL_THRESH_DEFAULT (10)
|
||||
#define UART_TOUT_THRESH_DEFAULT (10)
|
||||
|
|
|
@ -29,17 +29,18 @@
|
|||
|
||||
static const char *TAG = "dm9051.mac";
|
||||
|
||||
#define DM9051_SPI_LOCK_TIMEOUT_MS (50)
|
||||
#define DM9051_SPI_LOCK_TIMEOUT_MS (50)
|
||||
#define DM9051_PHY_OPERATION_TIMEOUT_US (1000)
|
||||
#define DM9051_RX_MEM_START_ADDR (3072)
|
||||
#define DM9051_RX_MEM_MAX_SIZE (16384)
|
||||
#define DM9051_RX_HDR_SIZE (4)
|
||||
#define DM9051_MULTI_REG_AXS_TIMEOUT_MS (50)
|
||||
#define DM9051_RX_MEM_START_ADDR (3072)
|
||||
#define DM9051_RX_MEM_MAX_SIZE (16384)
|
||||
#define DM9051_RX_HDR_SIZE (4)
|
||||
#define DM9051_ETH_MAC_RX_BUF_SIZE_AUTO (0)
|
||||
|
||||
typedef struct {
|
||||
uint32_t copy_len;
|
||||
uint32_t byte_cnt;
|
||||
}__attribute__((packed)) dm9051_auto_buf_info_t;
|
||||
} __attribute__((packed)) dm9051_auto_buf_info_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t flag;
|
||||
|
@ -66,6 +67,7 @@ typedef struct {
|
|||
esp_eth_mediator_t *eth;
|
||||
eth_spi_custom_driver_t spi;
|
||||
TaskHandle_t rx_task_hdl;
|
||||
SemaphoreHandle_t multi_reg_axs_mutex;
|
||||
uint32_t sw_reset_timeout_ms;
|
||||
int int_gpio_num;
|
||||
esp_timer_handle_t poll_timer;
|
||||
|
@ -92,7 +94,7 @@ static void *dm9051_spi_init(const void *spi_config)
|
|||
spi_devcfg.address_bits = 7;
|
||||
} else {
|
||||
ESP_GOTO_ON_FALSE(dm9051_config->spi_devcfg->command_bits == 1 && dm9051_config->spi_devcfg->address_bits == 7,
|
||||
NULL, err, TAG, "incorrect SPI frame format (command_bits/address_bits)");
|
||||
NULL, err, TAG, "incorrect SPI frame format (command_bits/address_bits)");
|
||||
}
|
||||
ESP_GOTO_ON_FALSE(spi_bus_add_device(dm9051_config->spi_host_id, &spi_devcfg, &spi->hdl) == ESP_OK,
|
||||
NULL, err, TAG, "adding device to SPI host #%d failed", dm9051_config->spi_host_id + 1);
|
||||
|
@ -179,12 +181,22 @@ static esp_err_t dm9051_spi_read(void *spi_ctx, uint32_t cmd, uint32_t addr, voi
|
|||
} else {
|
||||
ret = ESP_ERR_TIMEOUT;
|
||||
}
|
||||
if ((trans.flags&SPI_TRANS_USE_RXDATA) && len <= 4) {
|
||||
if ((trans.flags & SPI_TRANS_USE_RXDATA) && len <= 4) {
|
||||
memcpy(value, trans.rx_data, len); // copy register values to output
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline bool dm9051_mutex_lock(emac_dm9051_t *emac)
|
||||
{
|
||||
return xSemaphoreTake(emac->multi_reg_axs_mutex, pdMS_TO_TICKS(DM9051_MULTI_REG_AXS_TIMEOUT_MS)) == pdTRUE;
|
||||
}
|
||||
|
||||
static inline bool dm9051_mutex_unlock(emac_dm9051_t *emac)
|
||||
{
|
||||
return xSemaphoreGive(emac->multi_reg_axs_mutex) == pdTRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief write value to dm9051 internal register
|
||||
*/
|
||||
|
@ -378,7 +390,7 @@ static esp_err_t emac_dm9051_start(esp_eth_mac_t *mac)
|
|||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
|
||||
/* reset tx and rx memory pointer */
|
||||
/* reset tx and rx memory pointer */
|
||||
ESP_GOTO_ON_ERROR(dm9051_register_write(emac, DM9051_MPTRCR, MPTRCR_RST_RX | MPTRCR_RST_TX), err, TAG, "write MPTRCR failed");
|
||||
/* clear interrupt status */
|
||||
ESP_GOTO_ON_ERROR(dm9051_register_write(emac, DM9051_ISR, ISR_CLR_STATUS), err, TAG, "write ISR failed");
|
||||
|
@ -441,59 +453,65 @@ err:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t emac_dm9051_phy_access_compl(emac_dm9051_t *emac, uint32_t timeout_us)
|
||||
{
|
||||
uint8_t epcr = 0;
|
||||
ESP_RETURN_ON_ERROR(dm9051_register_read(emac, DM9051_EPCR, &epcr), TAG, "read EPCR failed");
|
||||
uint32_t to = 0;
|
||||
if (epcr & EPCR_ERRE) {
|
||||
do {
|
||||
esp_rom_delay_us(100);
|
||||
ESP_RETURN_ON_ERROR(dm9051_register_read(emac, DM9051_EPCR, &epcr), TAG, "read EPCR failed");
|
||||
to += 100;
|
||||
} while ((epcr & EPCR_ERRE) && to < timeout_us);
|
||||
ESP_RETURN_ON_FALSE(!(epcr & EPCR_ERRE), ESP_ERR_TIMEOUT, TAG, "wait for PHY/EEPROM access completion timeouted");
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t emac_dm9051_write_phy_reg(esp_eth_mac_t *mac, uint32_t phy_addr, uint32_t phy_reg, uint32_t reg_value)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
|
||||
/* check if phy access is in progress */
|
||||
uint8_t epcr = 0;
|
||||
ESP_GOTO_ON_ERROR(dm9051_register_read(emac, DM9051_EPCR, &epcr), err, TAG, "read EPCR failed");
|
||||
ESP_GOTO_ON_FALSE(!(epcr & EPCR_ERRE), ESP_ERR_INVALID_STATE, err, TAG, "phy is busy");
|
||||
|
||||
/* The following commands need to be performed in atomic manner */
|
||||
ESP_RETURN_ON_FALSE(dm9051_mutex_lock(emac), ESP_ERR_TIMEOUT, TAG, "multiple register access mutex timeout");
|
||||
/* check if no PHY/EEPROM access is in progress */
|
||||
ESP_GOTO_ON_ERROR(emac_dm9051_phy_access_compl(emac, DM9051_PHY_OPERATION_TIMEOUT_US), err, TAG, "PHY is busy");
|
||||
ESP_GOTO_ON_ERROR(dm9051_register_write(emac, DM9051_EPAR, (uint8_t)(((phy_addr << 6) & 0xFF) | phy_reg)), err, TAG, "write EPAR failed");
|
||||
ESP_GOTO_ON_ERROR(dm9051_register_write(emac, DM9051_EPDRL, (uint8_t)(reg_value & 0xFF)), err, TAG, "write EPDRL failed");
|
||||
ESP_GOTO_ON_ERROR(dm9051_register_write(emac, DM9051_EPDRH, (uint8_t)((reg_value >> 8) & 0xFF)), err, TAG, "write EPDRH failed");
|
||||
/* select PHY and select write operation */
|
||||
ESP_GOTO_ON_ERROR(dm9051_register_write(emac, DM9051_EPCR, EPCR_EPOS | EPCR_ERPRW), err, TAG, "write EPCR failed");
|
||||
/* polling the busy flag */
|
||||
uint32_t to = 0;
|
||||
do {
|
||||
esp_rom_delay_us(100);
|
||||
ESP_GOTO_ON_ERROR(dm9051_register_read(emac, DM9051_EPCR, &epcr), err, TAG, "read EPCR failed");
|
||||
to += 100;
|
||||
} while ((epcr & EPCR_ERRE) && to < DM9051_PHY_OPERATION_TIMEOUT_US);
|
||||
ESP_GOTO_ON_FALSE(!(epcr & EPCR_ERRE), ESP_ERR_TIMEOUT, err, TAG, "phy is busy");
|
||||
return ESP_OK;
|
||||
/* wait for PHY access completion */
|
||||
ESP_GOTO_ON_ERROR(emac_dm9051_phy_access_compl(emac, DM9051_PHY_OPERATION_TIMEOUT_US), err, TAG, "PHY access completion check failed");
|
||||
err:
|
||||
dm9051_mutex_unlock(emac);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t emac_dm9051_read_phy_reg(esp_eth_mac_t *mac, uint32_t phy_addr, uint32_t phy_reg, uint32_t *reg_value)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
ESP_GOTO_ON_FALSE(reg_value, ESP_ERR_INVALID_ARG, err, TAG, "can't set reg_value to null");
|
||||
ESP_RETURN_ON_FALSE(reg_value, ESP_ERR_INVALID_ARG, TAG, "can't set reg_value to null");
|
||||
emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
|
||||
/* check if phy access is in progress */
|
||||
uint8_t epcr = 0;
|
||||
ESP_GOTO_ON_ERROR(dm9051_register_read(emac, DM9051_EPCR, &epcr), err, TAG, "read EPCR failed");
|
||||
ESP_GOTO_ON_FALSE(!(epcr & 0x01), ESP_ERR_INVALID_STATE, err, TAG, "phy is busy");
|
||||
|
||||
/* The following commands need to be performed in atomic manner */
|
||||
ESP_RETURN_ON_FALSE(dm9051_mutex_lock(emac), ESP_ERR_TIMEOUT, TAG, "multiple register access mutex timeout");
|
||||
/* check if no PHY/EEPROM access is in progress */
|
||||
ESP_GOTO_ON_ERROR(emac_dm9051_phy_access_compl(emac, DM9051_PHY_OPERATION_TIMEOUT_US), err, TAG, "PHY is busy");
|
||||
ESP_GOTO_ON_ERROR(dm9051_register_write(emac, DM9051_EPAR, (uint8_t)(((phy_addr << 6) & 0xFF) | phy_reg)), err, TAG, "write EPAR failed");
|
||||
/* Select PHY and select read operation */
|
||||
ESP_GOTO_ON_ERROR(dm9051_register_write(emac, DM9051_EPCR, 0x0C), err, TAG, "write EPCR failed");
|
||||
/* polling the busy flag */
|
||||
uint32_t to = 0;
|
||||
do {
|
||||
esp_rom_delay_us(100);
|
||||
ESP_GOTO_ON_ERROR(dm9051_register_read(emac, DM9051_EPCR, &epcr), err, TAG, "read EPCR failed");
|
||||
to += 100;
|
||||
} while ((epcr & EPCR_ERRE) && to < DM9051_PHY_OPERATION_TIMEOUT_US);
|
||||
ESP_GOTO_ON_FALSE(!(epcr & EPCR_ERRE), ESP_ERR_TIMEOUT, err, TAG, "phy is busy");
|
||||
ESP_GOTO_ON_ERROR(dm9051_register_write(emac, DM9051_EPCR, EPCR_EPOS | EPCR_ERPRR), err, TAG, "write EPCR failed");
|
||||
/* wait for PHY access completion */
|
||||
ESP_GOTO_ON_ERROR(emac_dm9051_phy_access_compl(emac, DM9051_PHY_OPERATION_TIMEOUT_US), err, TAG, "PHY access completion check failed");
|
||||
uint8_t value_h = 0;
|
||||
uint8_t value_l = 0;
|
||||
ESP_GOTO_ON_ERROR(dm9051_register_read(emac, DM9051_EPDRH, &value_h), err, TAG, "read EPDRH failed");
|
||||
ESP_GOTO_ON_ERROR(dm9051_register_read(emac, DM9051_EPDRL, &value_l), err, TAG, "read EPDRL failed");
|
||||
*reg_value = (value_h << 8) | value_l;
|
||||
return ESP_OK;
|
||||
err:
|
||||
dm9051_mutex_unlock(emac);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -529,14 +547,14 @@ static esp_err_t emac_dm9051_set_link(esp_eth_mac_t *mac, eth_link_t link)
|
|||
ESP_GOTO_ON_ERROR(mac->start(mac), err, TAG, "dm9051 start failed");
|
||||
if (emac->poll_timer) {
|
||||
ESP_GOTO_ON_ERROR(esp_timer_start_periodic(emac->poll_timer, emac->poll_period_ms * 1000),
|
||||
err, TAG, "start poll timer failed");
|
||||
err, TAG, "start poll timer failed");
|
||||
}
|
||||
break;
|
||||
case ETH_LINK_DOWN:
|
||||
ESP_GOTO_ON_ERROR(mac->stop(mac), err, TAG, "dm9051 stop failed");
|
||||
if (emac->poll_timer) {
|
||||
ESP_GOTO_ON_ERROR(esp_timer_stop(emac->poll_timer),
|
||||
err, TAG, "stop poll timer failed");
|
||||
err, TAG, "stop poll timer failed");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -637,7 +655,7 @@ static esp_err_t emac_dm9051_transmit(esp_eth_mac_t *mac, uint8_t *buf, uint32_t
|
|||
int64_t wait_time = esp_timer_get_time();
|
||||
do {
|
||||
ESP_GOTO_ON_ERROR(dm9051_register_read(emac, DM9051_TCR, &tcr), err, TAG, "read TCR failed");
|
||||
} while((tcr & TCR_TXREQ) && ((esp_timer_get_time() - wait_time) < 100));
|
||||
} while ((tcr & TCR_TXREQ) && ((esp_timer_get_time() - wait_time) < 100));
|
||||
|
||||
if (tcr & TCR_TXREQ) {
|
||||
ESP_LOGE(TAG, "last transmit still in progress, cannot send.");
|
||||
|
@ -781,7 +799,7 @@ static esp_err_t emac_dm9051_receive(esp_eth_mac_t *mac, uint8_t *buf, uint32_t
|
|||
|
||||
/* dummy read, get the most updated data */
|
||||
ESP_GOTO_ON_ERROR(dm9051_register_read(emac, DM9051_MRCMDX, &rxbyte), err, TAG, "read MRCMDX failed");
|
||||
/* check for remaing packets */
|
||||
/* check for remaining packets */
|
||||
ESP_GOTO_ON_ERROR(dm9051_register_read(emac, DM9051_MRCMDX, &rxbyte), err, TAG, "read MRCMDX failed");
|
||||
emac->packets_remain = rxbyte > 0;
|
||||
return ESP_OK;
|
||||
|
@ -807,7 +825,7 @@ static esp_err_t emac_dm9051_init(esp_eth_mac_t *mac)
|
|||
/* reset dm9051 */
|
||||
ESP_GOTO_ON_ERROR(dm9051_reset(emac), err, TAG, "reset dm9051 failed");
|
||||
/* verify chip id */
|
||||
ESP_GOTO_ON_ERROR(dm9051_verify_id(emac), err, TAG, "vefiry chip ID failed");
|
||||
ESP_GOTO_ON_ERROR(dm9051_verify_id(emac), err, TAG, "verify chip ID failed");
|
||||
/* default setup of internal registers */
|
||||
ESP_GOTO_ON_ERROR(dm9051_setup_default(emac), err, TAG, "dm9051 default setup failed");
|
||||
/* clear multicast hash table */
|
||||
|
@ -849,7 +867,7 @@ static void emac_dm9051_task(void *arg)
|
|||
// check if the task receives any notification
|
||||
if (emac->int_gpio_num >= 0) { // if in interrupt mode
|
||||
if (ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(1000)) == 0 && // if no notification ...
|
||||
gpio_get_level(emac->int_gpio_num) == 0) { // ...and no interrupt asserted
|
||||
gpio_get_level(emac->int_gpio_num) == 0) { // ...and no interrupt asserted
|
||||
continue; // -> just continue to check again
|
||||
}
|
||||
} else {
|
||||
|
@ -908,6 +926,7 @@ static esp_err_t emac_dm9051_del(esp_eth_mac_t *mac)
|
|||
}
|
||||
vTaskDelete(emac->rx_task_hdl);
|
||||
emac->spi.deinit(emac->spi.ctx);
|
||||
vSemaphoreDelete(emac->multi_reg_axs_mutex);
|
||||
heap_caps_free(emac->rx_buffer);
|
||||
free(emac);
|
||||
return ESP_OK;
|
||||
|
@ -946,7 +965,7 @@ esp_eth_mac_t *esp_eth_mac_new_dm9051(const eth_dm9051_config_t *dm9051_config,
|
|||
emac->parent.receive = emac_dm9051_receive;
|
||||
|
||||
if (dm9051_config->custom_spi_driver.init != NULL && dm9051_config->custom_spi_driver.deinit != NULL
|
||||
&& dm9051_config->custom_spi_driver.read != NULL && dm9051_config->custom_spi_driver.write != NULL) {
|
||||
&& dm9051_config->custom_spi_driver.read != NULL && dm9051_config->custom_spi_driver.write != NULL) {
|
||||
ESP_LOGD(TAG, "Using user's custom SPI Driver");
|
||||
emac->spi.init = dm9051_config->custom_spi_driver.init;
|
||||
emac->spi.deinit = dm9051_config->custom_spi_driver.deinit;
|
||||
|
@ -964,13 +983,17 @@ esp_eth_mac_t *esp_eth_mac_new_dm9051(const eth_dm9051_config_t *dm9051_config,
|
|||
ESP_GOTO_ON_FALSE((emac->spi.ctx = emac->spi.init(dm9051_config)) != NULL, NULL, err, TAG, "SPI initialization failed");
|
||||
}
|
||||
|
||||
/* create mutex for accessing multiple registers in atomic manner */
|
||||
emac->multi_reg_axs_mutex = xSemaphoreCreateMutex();
|
||||
ESP_GOTO_ON_FALSE(emac->multi_reg_axs_mutex, NULL, err, TAG, "create multi registers access mutex failed");
|
||||
|
||||
/* create dm9051 task */
|
||||
BaseType_t core_num = tskNO_AFFINITY;
|
||||
if (mac_config->flags & ETH_MAC_FLAG_PIN_TO_CORE) {
|
||||
core_num = esp_cpu_get_core_id();
|
||||
}
|
||||
BaseType_t xReturned = xTaskCreatePinnedToCore(emac_dm9051_task, "dm9051_tsk", mac_config->rx_task_stack_size, emac,
|
||||
mac_config->rx_task_prio, &emac->rx_task_hdl, core_num);
|
||||
mac_config->rx_task_prio, &emac->rx_task_hdl, core_num);
|
||||
ESP_GOTO_ON_FALSE(xReturned == pdPASS, NULL, err, TAG, "create dm9051 task failed");
|
||||
|
||||
emac->rx_buffer = heap_caps_malloc(ETH_MAX_PACKET_SIZE + DM9051_RX_HDR_SIZE, MALLOC_CAP_DMA);
|
||||
|
@ -999,6 +1022,9 @@ err:
|
|||
if (emac->spi.ctx) {
|
||||
emac->spi.deinit(emac->spi.ctx);
|
||||
}
|
||||
if (emac->multi_reg_axs_mutex) {
|
||||
vSemaphoreDelete(emac->multi_reg_axs_mutex);
|
||||
}
|
||||
heap_caps_free(emac->rx_buffer);
|
||||
free(emac);
|
||||
}
|
||||
|
|
|
@ -65,7 +65,6 @@ r_lld_con_tx_prog_new_packet_coex = 0x40001b70;
|
|||
r_lld_per_adv_dynamic_pti_get = 0x40001b78;
|
||||
r_lld_per_adv_evt_start_chm_upd = 0x40001b7c;
|
||||
r_lld_ext_scan_dynamic_pti_get = 0x40001b80;
|
||||
r_lld_scan_try_sched = 0x40001b84;
|
||||
r_lld_sync_insert = 0x40001b88;
|
||||
r_sch_prog_ble_push = 0x40001b8c;
|
||||
r_sch_prog_bt_push = 0x40001b90;
|
||||
|
|
|
@ -116,7 +116,6 @@ r_lld_con_start_eco = 0x40001d10;
|
|||
r_lld_con_frm_isr_eco = 0x40001d14;
|
||||
r_lld_con_tx_eco = 0x40001d18;
|
||||
r_lld_scan_evt_start_cbk_eco = 0x40001d20;
|
||||
r_lld_scan_start_eco = 0x40001d24;
|
||||
r_lld_ext_scan_dynamic_pti_process_eco = 0x40001d28;
|
||||
r_lld_scan_frm_eof_isr_eco = 0x40001d2c;
|
||||
r_lld_sync_start_eco = 0x40001d30;
|
||||
|
@ -141,15 +140,9 @@ r_sch_plan_conflict_check = 0x40001d7c;
|
|||
r_rwble_isr_hw_fixed = 0x40001d80;
|
||||
r_bt_bb_recorrect_is_dead = 0x40001d84;
|
||||
r_bt_bb_restart_hw_recorrect = 0x40001d88;
|
||||
r_btdm_task_post_impl = 0x40001d8c;
|
||||
r_btdm_task_post_from_isr_impl = 0x40001d90;
|
||||
r_btdm_vnd_offload_post_from_isr = 0x40001d94;
|
||||
r_btdm_vnd_offload_post = 0x40001d98;
|
||||
r_btdm_vnd_offload_process = 0x40001d9c;
|
||||
r_ke_task_handler_pre = 0x40001da0;
|
||||
r_ke_task_handler_end = 0x40001da4;
|
||||
r_ke_task_handler_get_overwrite = 0x40001da8;
|
||||
r_lld_scan_try_sched_eco = 0x40001dac;
|
||||
r_lld_scan_frm_skip_isr_eco = 0x40001db0;
|
||||
r_lld_ext_scan_dynamic_pti_reset = 0x40001db4;
|
||||
r_llc_rem_phy_upd_proc_continue_eco = 0x40001db8;
|
||||
|
@ -220,6 +213,8 @@ r_lld_adv_ext_chain_none_construct = 0x40001b50;
|
|||
r_llc_llcp_send_eco = 0x40001cf4;
|
||||
r_llc_llcp_channel_map_ind_ack = 0x40001d68;
|
||||
r_rwble_isr = 0x40001464;
|
||||
r_lld_scan_start_eco = 0x40001d24;
|
||||
r_lld_scan_try_sched_eco = 0x40001dac;
|
||||
*/
|
||||
|
||||
|
||||
|
|
|
@ -922,7 +922,7 @@ r_llc_init_term_proc = 0x40000f1c;
|
|||
r_llc_iv_skd_rand_gen = 0x40000f20;
|
||||
r_llc_le_ping_proc_continue = 0x40000f24;
|
||||
r_llc_le_ping_proc_err_cb = 0x40000f28;
|
||||
r_llc_le_ping_restart = 0x40000f2c;
|
||||
/* r_llc_le_ping_restart = 0x40000f2c; */
|
||||
r_llc_le_ping_set = 0x40000f30;
|
||||
r_llc_ll_pause_enc_rsp_ack_handler = 0x40000f34;
|
||||
r_llc_ll_reject_ind_ack_handler = 0x40000f38;
|
||||
|
|
|
@ -1195,7 +1195,7 @@ r_llc_init_term_proc = 0x40003d38;
|
|||
r_llc_iv_skd_rand_gen = 0x40003d44;
|
||||
r_llc_le_ping_proc_continue = 0x40003d50;
|
||||
r_llc_le_ping_proc_err_cb = 0x40003d5c;
|
||||
r_llc_le_ping_restart = 0x40003d68;
|
||||
/* r_llc_le_ping_restart = 0x40003d68; */
|
||||
r_llc_le_ping_set = 0x40003d74;
|
||||
r_llc_ll_pause_enc_rsp_ack_handler = 0x40003d80;
|
||||
r_llc_ll_reject_ind_ack_handler = 0x40003d8c;
|
||||
|
@ -1609,7 +1609,6 @@ r_lld_con_tx_prog_new_packet_coex = 0x4000519c;
|
|||
r_lld_per_adv_dynamic_pti_get = 0x400051b4;
|
||||
r_lld_per_adv_evt_start_chm_upd = 0x400051c0;
|
||||
r_lld_ext_scan_dynamic_pti_get = 0x400051cc;
|
||||
r_lld_scan_try_sched = 0x400051d8;
|
||||
r_lld_sync_insert = 0x400051e4;
|
||||
r_sch_prog_ble_push = 0x400051f0;
|
||||
r_sch_prog_bt_push = 0x400051fc;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -211,15 +211,18 @@ static inline void lp_uart_ll_reset_register(int hw_id)
|
|||
*/
|
||||
FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num)
|
||||
{
|
||||
HAL_ASSERT(uart_num < SOC_UART_HP_NUM);
|
||||
uint32_t uart_clk_config_reg = ((uart_num == 0) ? PCR_UART0_CONF_REG :
|
||||
(uart_num == 1) ? PCR_UART1_CONF_REG : 0);
|
||||
uint32_t uart_rst_bit = ((uart_num == 0) ? PCR_UART0_RST_EN :
|
||||
(uart_num == 1) ? PCR_UART1_RST_EN : 0);
|
||||
uint32_t uart_en_bit = ((uart_num == 0) ? PCR_UART0_CLK_EN :
|
||||
(uart_num == 1) ? PCR_UART1_CLK_EN : 0);
|
||||
return REG_GET_BIT(uart_clk_config_reg, uart_rst_bit) == 0 &&
|
||||
REG_GET_BIT(uart_clk_config_reg, uart_en_bit) != 0;
|
||||
switch (uart_num) {
|
||||
case 0:
|
||||
return PCR.uart0_conf.uart0_clk_en && !PCR.uart0_conf.uart0_rst_en;
|
||||
case 1:
|
||||
return PCR.uart1_conf.uart1_clk_en && !PCR.uart1_conf.uart1_rst_en;
|
||||
case 2: // LP_UART
|
||||
return LPPERI.clk_en.lp_uart_ck_en && !LPPERI.reset_en.lp_uart_reset_en;
|
||||
default:
|
||||
// Unknown uart port number
|
||||
HAL_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -100,9 +100,9 @@ FORCE_INLINE_ATTR void lp_uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *sou
|
|||
case 1:
|
||||
*source_clk = (soc_module_clk_t)LP_UART_SCLK_XTAL_D2;
|
||||
break;
|
||||
case 2:
|
||||
*source_clk = (soc_module_clk_t)LP_UART_SCLK_LP_PLL;
|
||||
break;
|
||||
// case 2:
|
||||
// *source_clk = (soc_module_clk_t)LP_UART_SCLK_LP_PLL;
|
||||
// break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,9 +122,9 @@ static inline void lp_uart_ll_set_source_clk(uart_dev_t *hw, soc_periph_lp_uart_
|
|||
case LP_UART_SCLK_XTAL_D2:
|
||||
LPPERI.core_clk_sel.lp_uart_clk_sel = 1;
|
||||
break;
|
||||
case LP_UART_SCLK_LP_PLL:
|
||||
LPPERI.core_clk_sel.lp_uart_clk_sel = 2;
|
||||
break;
|
||||
// case LP_UART_SCLK_LP_PLL: // TODO: LP_PLL clock requires extra support
|
||||
// LPPERI.core_clk_sel.lp_uart_clk_sel = 2;
|
||||
// break;
|
||||
default:
|
||||
// Invalid LP_UART clock source
|
||||
HAL_ASSERT(false);
|
||||
|
@ -202,8 +202,7 @@ static inline void lp_uart_ll_reset_register(int hw_id)
|
|||
*/
|
||||
FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num)
|
||||
{
|
||||
HAL_ASSERT(uart_num < SOC_UART_HP_NUM);
|
||||
bool uart_rst_en = false;
|
||||
bool uart_rst_en = true;
|
||||
bool uart_apb_en = false;
|
||||
bool uart_sys_en = false;
|
||||
switch (uart_num) {
|
||||
|
@ -232,7 +231,14 @@ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num)
|
|||
uart_apb_en = HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart4_apb_clk_en;
|
||||
uart_sys_en = HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart4_sys_clk_en;
|
||||
break;
|
||||
case 5:
|
||||
uart_rst_en = LPPERI.reset_en.rst_en_lp_uart;
|
||||
uart_apb_en = LPPERI.clk_en.ck_en_lp_uart;
|
||||
uart_sys_en = true;
|
||||
break;
|
||||
default:
|
||||
// Unknown uart port number
|
||||
HAL_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
return (!uart_rst_en && uart_apb_en && uart_sys_en);
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit e6afdb4025fe018ae0add44e3c45249ea1974774
|
||||
Subproject commit aa6f889fb4f6f743b3a550aa587713aabbdca1fc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -202,6 +202,11 @@ typedef enum {
|
|||
|
||||
///////////////////////////////////////////////////UART/////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Array initializer for all supported clock sources of UART
|
||||
*/
|
||||
#define SOC_UART_CLKS {SOC_MOD_CLK_APB, SOC_MOD_CLK_REF_TICK}
|
||||
|
||||
/**
|
||||
* @brief Type of UART clock source, reserved for the legacy UART driver
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -175,6 +175,11 @@ typedef enum {
|
|||
|
||||
///////////////////////////////////////////////////UART/////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Array initializer for all supported clock sources of UART
|
||||
*/
|
||||
#define SOC_UART_CLKS {SOC_MOD_CLK_PLL_F40M, SOC_MOD_CLK_XTAL, SOC_MOD_CLK_RC_FAST}
|
||||
|
||||
/**
|
||||
* @brief Type of UART clock source, reserved for the legacy UART driver
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -201,6 +201,11 @@ typedef enum {
|
|||
|
||||
///////////////////////////////////////////////////UART/////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Array initializer for all supported clock sources of UART
|
||||
*/
|
||||
#define SOC_UART_CLKS {SOC_MOD_CLK_APB, SOC_MOD_CLK_XTAL, SOC_MOD_CLK_RC_FAST}
|
||||
|
||||
/**
|
||||
* @brief Type of UART clock source, reserved for the legacy UART driver
|
||||
*/
|
||||
|
|
|
@ -1179,6 +1179,10 @@ config SOC_UART_SUPPORT_WAKEUP_INT
|
|||
bool
|
||||
default y
|
||||
|
||||
config SOC_UART_HAS_LP_UART
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND
|
||||
bool
|
||||
default y
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -217,6 +217,11 @@ typedef enum {
|
|||
|
||||
///////////////////////////////////////////////////UART/////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Array initializer for all supported clock sources of UART
|
||||
*/
|
||||
#define SOC_UART_CLKS {SOC_MOD_CLK_PLL_F80M, SOC_MOD_CLK_XTAL, SOC_MOD_CLK_RC_FAST}
|
||||
|
||||
/**
|
||||
* @brief Type of UART clock source, reserved for the legacy UART driver
|
||||
*/
|
||||
|
@ -227,6 +232,11 @@ typedef enum {
|
|||
UART_SCLK_DEFAULT = SOC_MOD_CLK_PLL_F80M, /*!< UART source clock default choice is PLL_F80M */
|
||||
} soc_periph_uart_clk_src_legacy_t;
|
||||
|
||||
/**
|
||||
* @brief Array initializer for all supported clock sources of LP_UART
|
||||
*/
|
||||
#define SOC_LP_UART_CLKS {SOC_MOD_CLK_RTC_FAST, SOC_MOD_CLK_XTAL_D2}
|
||||
|
||||
/**
|
||||
* @brief Type of LP_UART clock source
|
||||
*/
|
||||
|
|
|
@ -477,6 +477,7 @@
|
|||
#define SOC_UART_SUPPORT_RTC_CLK (1) /*!< Support RTC clock as the clock source */
|
||||
#define SOC_UART_SUPPORT_XTAL_CLK (1) /*!< Support XTAL clock as the clock source */
|
||||
#define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */
|
||||
#define SOC_UART_HAS_LP_UART (1) /*!< Support LP UART */
|
||||
|
||||
// UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled
|
||||
#define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -224,6 +224,11 @@ typedef enum {
|
|||
|
||||
///////////////////////////////////////////////////UART/////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Array initializer for all supported clock sources of UART
|
||||
*/
|
||||
#define SOC_UART_CLKS {SOC_MOD_CLK_PLL_F48M, SOC_MOD_CLK_XTAL, SOC_MOD_CLK_RC_FAST}
|
||||
|
||||
/**
|
||||
* @brief Type of UART clock source, reserved for the legacy UART driver
|
||||
*/
|
||||
|
|
|
@ -1139,6 +1139,10 @@ config SOC_UART_SUPPORT_WAKEUP_INT
|
|||
bool
|
||||
default y
|
||||
|
||||
config SOC_UART_HAS_LP_UART
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND
|
||||
bool
|
||||
default y
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -258,6 +258,11 @@ typedef enum {
|
|||
|
||||
///////////////////////////////////////////////////UART/////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Array initializer for all supported clock sources of UART
|
||||
*/
|
||||
#define SOC_UART_CLKS {SOC_MOD_CLK_PLL_F80M, SOC_MOD_CLK_XTAL, SOC_MOD_CLK_RC_FAST}
|
||||
|
||||
/**
|
||||
* @brief Type of UART clock source, reserved for the legacy UART driver
|
||||
*/
|
||||
|
@ -265,26 +270,22 @@ typedef enum {
|
|||
UART_SCLK_PLL_F80M = SOC_MOD_CLK_PLL_F80M, /*!< UART source clock is PLL_F80M */
|
||||
UART_SCLK_RTC = SOC_MOD_CLK_RC_FAST, /*!< UART source clock is RC_FAST */
|
||||
UART_SCLK_XTAL = SOC_MOD_CLK_XTAL, /*!< UART source clock is XTAL */
|
||||
#if SOC_CLK_TREE_SUPPORTED
|
||||
UART_SCLK_DEFAULT = SOC_MOD_CLK_PLL_F80M, /*!< UART source clock default choice is PLL_F80M */
|
||||
#else
|
||||
UART_SCLK_DEFAULT = SOC_MOD_CLK_XTAL, /*!< UART source clock default choice is XTAL for FPGA environment */
|
||||
#endif
|
||||
} soc_periph_uart_clk_src_legacy_t;
|
||||
|
||||
/**
|
||||
* @brief Array initializer for all supported clock sources of LP_UART
|
||||
*/
|
||||
#define SOC_LP_UART_CLKS {SOC_MOD_CLK_RTC_FAST, SOC_MOD_CLK_XTAL_D2}
|
||||
|
||||
/**
|
||||
* @brief Type of LP_UART clock source
|
||||
*/
|
||||
typedef enum {
|
||||
LP_UART_SCLK_LP_FAST = SOC_MOD_CLK_RTC_FAST, /*!< LP_UART source clock is LP(RTC)_FAST */
|
||||
LP_UART_SCLK_XTAL_D2 = SOC_MOD_CLK_XTAL_D2, /*!< LP_UART source clock is XTAL_D2 */
|
||||
LP_UART_SCLK_LP_PLL = SOC_MOD_CLK_LP_PLL, /*!< LP_UART source clock is LP_PLL (8M PLL) */
|
||||
#if SOC_CLK_TREE_SUPPORTED
|
||||
LP_UART_SCLK_DEFAULT = SOC_MOD_CLK_RTC_FAST,
|
||||
#else
|
||||
LP_UART_SCLK_DEFAULT = SOC_MOD_CLK_XTAL_D2, /*!< LP_UART source clock default choice is XTAL_D2 */
|
||||
#endif
|
||||
|
||||
// LP_UART_SCLK_LP_PLL = SOC_MOD_CLK_LP_PLL, /*!< LP_UART source clock is LP_PLL (8M PLL) */ TODO: LP_PLL clock requires extra support
|
||||
LP_UART_SCLK_DEFAULT = SOC_MOD_CLK_RTC_FAST, /*!< LP_UART source clock default choice is LP(RTC)_FAST */
|
||||
} soc_periph_lp_uart_clk_src_t;
|
||||
|
||||
//////////////////////////////////////////////////MCPWM/////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -503,6 +503,7 @@
|
|||
#define SOC_UART_SUPPORT_RTC_CLK (1) /*!< Support RTC clock as the clock source */
|
||||
#define SOC_UART_SUPPORT_XTAL_CLK (1) /*!< Support XTAL clock as the clock source */
|
||||
#define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */
|
||||
#define SOC_UART_HAS_LP_UART (1) /*!< Support LP UART */
|
||||
|
||||
// UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled
|
||||
#define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -217,6 +217,11 @@ typedef enum {
|
|||
|
||||
///////////////////////////////////////////////////UART/////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Array initializer for all supported clock sources of UART
|
||||
*/
|
||||
#define SOC_UART_CLKS {SOC_MOD_CLK_APB, SOC_MOD_CLK_REF_TICK}
|
||||
|
||||
/**
|
||||
* @brief Type of UART clock source, reserved for the legacy UART driver
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -219,6 +219,11 @@ typedef enum {
|
|||
|
||||
///////////////////////////////////////////////////UART/////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Array initializer for all supported clock sources of UART
|
||||
*/
|
||||
#define SOC_UART_CLKS {SOC_MOD_CLK_APB, SOC_MOD_CLK_XTAL, SOC_MOD_CLK_RC_FAST}
|
||||
|
||||
/**
|
||||
* @brief Type of UART clock source, reserved for the legacy UART driver
|
||||
*/
|
||||
|
|
|
@ -97,7 +97,6 @@ api-reference/peripherals/dedic_gpio.rst
|
|||
api-reference/peripherals/sd_pullup_requirements.rst
|
||||
api-reference/peripherals/index.rst
|
||||
api-reference/peripherals/sdmmc_host.rst
|
||||
api-reference/peripherals/uart.rst
|
||||
api-reference/network/esp_openthread.rst
|
||||
api-reference/network/esp_eth.rst
|
||||
api-reference/network/esp_netif_driver.rst
|
||||
|
|
|
@ -120,6 +120,8 @@ This command automatically builds the project if necessary, and then flash it to
|
|||
|
||||
.. note:: The environment variables ``ESPPORT`` and ``ESPBAUD`` can be used to set default values for the ``-p`` and ``-b`` options, respectively. Providing these options on the command line overrides the default.
|
||||
|
||||
``idf.py`` uses the ``write_flash`` command of ``esptool.py`` under the hood to flash the target. You can pass additional arguments to configure the flash writing process using the ``--extra-args`` option. For example, to `write to an external SPI flash chip <https://docs.espressif.com/projects/esptool/en/latest/esptool/advanced-options.html#custom-spi-pin-configuration>`_, use the following command: ``idf.py flash --extra-args="--spi-connection <CLK>,<Q>,<D>,<HD>,<CS>"``. To see the full list of available arguments, run ``esptool.py write_flash --help`` or see the `esptool.py documentation <https://docs.espressif.com/projects/esptool/en/latest/esptool/index.html>`_.
|
||||
|
||||
Similarly to the ``build`` command, the command can be run with ``app``, ``bootloader`` and ``partition-table`` arguments to flash only the app, bootloader or partition table as applicable.
|
||||
|
||||
Hints on How to Resolve Errors
|
||||
|
|
|
@ -13,7 +13,7 @@ The SPI0/1 bus is shared between the instruction & data cache (for firmware exec
|
|||
|
||||
.. only:: SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND
|
||||
|
||||
On {IDF_TARGET_NAME}, the config option :ref:`CONFIG_SPI_FLASH_AUTO_SUSPEND` (enabled by default) allows the cache to read flash concurrently with SPI1 operations. See :ref:`auto-suspend` for more details.
|
||||
On {IDF_TARGET_NAME}, the config option :ref:`CONFIG_SPI_FLASH_AUTO_SUSPEND` allows the cache to read flash concurrently with SPI1 operations. This is an optional feature that depends on special SPI Flash models, hence disabled by default. See :ref:`auto-suspend` for more details.
|
||||
|
||||
If this option is disabled, the caches must be disabled while reading/writing/erasing operations. There are some constraints using driver on the SPI1 bus, see :ref:`impact_disabled_cache`. These constraints will cause more IRAM/DRAM usages.
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ The {IDF_TARGET_NAME} chip has {IDF_TARGET_SOC_UART_HP_NUM} UART controllers (al
|
|||
|
||||
Each UART controller is independently configurable with parameters such as baud rate, data bit length, bit ordering, number of stop bits, parity bit, etc. All the regular UART controllers are compatible with UART-enabled devices from various manufacturers and can also support Infrared Data Association (IrDA) protocols.
|
||||
|
||||
.. only:: SOC_UART_LP_NUM
|
||||
.. only:: SOC_UART_HAS_LP_UART
|
||||
|
||||
Additionally, the {IDF_TARGET_NAME} chip has one low-power (LP) UART controller. It is the cut-down version of regular UART. Usually, the LP UART controller only support basic UART functionality with a much smaller RAM size, and does not support IrDA or RS485 protocols. For a full list of difference between UART and LP UART, please refer to the **{IDF_TARGET_NAME} Technical Reference Manual** > **UART Controller (UART)** > **Features** [`PDF <{IDF_TARGET_TRM_EN_URL}#uart>`__]).
|
||||
|
||||
|
@ -30,6 +30,10 @@ The overview describes how to establish communication between an {IDF_TARGET_NAM
|
|||
|
||||
Steps 1 to 3 comprise the configuration stage. Step 4 is where the UART starts operating. Steps 5 and 6 are optional.
|
||||
|
||||
.. only:: SOC_UART_HAS_LP_UART
|
||||
|
||||
Additionally, when using the LP UART Controller you need to pay attention to :ref:`uart-api-lp-uart-driver`.
|
||||
|
||||
The UART driver's functions identify each of the UART controllers using :cpp:type:`uart_port_t`. This identification is needed for all the following function calls.
|
||||
|
||||
|
||||
|
@ -239,12 +243,6 @@ The API provides a convenient way to handle specific interrupts discussed in thi
|
|||
- Disable the interrupt using :cpp:func:`uart_disable_pattern_det_intr`
|
||||
|
||||
|
||||
Macros
|
||||
^^^^^^
|
||||
|
||||
The API also defines several macros. For example, :c:macro:`UART_HW_FIFO_LEN` defines the length of hardware FIFO buffers; :c:macro:`UART_BITRATE_MAX` gives the maximum baud rate supported by the UART controllers, etc.
|
||||
|
||||
|
||||
.. _uart-api-deleting-driver:
|
||||
|
||||
Deleting a Driver
|
||||
|
@ -253,6 +251,29 @@ Deleting a Driver
|
|||
If the communication established with :cpp:func:`uart_driver_install` is no longer required, the driver can be removed to free allocated resources by calling :cpp:func:`uart_driver_delete`.
|
||||
|
||||
|
||||
Macros
|
||||
^^^^^^
|
||||
|
||||
The API also defines several macros. For example, :c:macro:`UART_HW_FIFO_LEN` defines the length of hardware FIFO buffers; :c:macro:`UART_BITRATE_MAX` gives the maximum baud rate supported by the UART controllers, etc.
|
||||
|
||||
.. only:: SOC_UART_HAS_LP_UART
|
||||
|
||||
.. _uart-api-lp-uart-driver:
|
||||
|
||||
Use LP UART Controller with HP Core
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The UART driver also supports to control the LP UART controller when the chip is in active mode. The configuration steps for the LP UART are the same as the steps for a normal UART controller, except:
|
||||
|
||||
.. list::
|
||||
|
||||
- The port number for the LP UART controller is defined by :c:macro:`LP_UART_NUM_0`.
|
||||
- The available clock sources for the LP UART controller can be found in :cpp:type:`lp_uart_sclk_t`.
|
||||
- The size of the hardware FIFO for the LP UART controller is much smaller, which is defined in :c:macro:`SOC_LP_UART_FIFO_LEN`.
|
||||
:SOC_LP_GPIO_MATRIX_SUPPORTED: - The GPIO pins for the LP UART controller can only be selected from the LP GPIO pins.
|
||||
:not SOC_LP_GPIO_MATRIX_SUPPORTED: - The GPIO pins for the LP UART controller are unalterable, because there is no LP GPIO matrix on the target. Please see **{IDF_TARGET_NAME} Technical Reference Manual** > **IO MUX and GPIO Matrix (GPIO, IO MUX)** > **LP IO MUX Functions List** [`PDF <{IDF_TARGET_TRM_EN_URL}#lp-io-mux-func-list>`__] for the specific pin numbers.
|
||||
|
||||
|
||||
Overview of RS485 Specific Communication 0ptions
|
||||
------------------------------------------------
|
||||
|
||||
|
|
|
@ -85,6 +85,10 @@ To flash the image onto {IDF_TARGET_NAME} at offset 0x110000, run::
|
|||
|
||||
python esptool.py --chip {IDF_TARGET_PATH_NAME} --port [port] --baud [baud] write_flash -z 0x110000 spiffs.bin
|
||||
|
||||
.. note::
|
||||
|
||||
You can configure the ``write_flash`` command of ``esptool.py`` to `write the spiffs data to an external SPI flash chip <https://docs.espressif.com/projects/esptool/en/latest/esptool/advanced-options.html#custom-spi-pin-configuration>`_ using the ``--spi-connection <CLK>,<Q>,<D>,<HD>,<CS>`` option. Just specify the GPIO pins assigned to the external flash, e.g. ``python esptool.py write_flash --spi-connection 6,7,8,9,11 -z 0x110000 spiffs.bin``.
|
||||
|
||||
Notes on Which SPIFFS Tool to Use
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ SPI1 flash 并发约束
|
|||
|
||||
.. only:: SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND
|
||||
|
||||
在 {IDF_TARGET_NAME} 上,默认启用的配置选项 :ref:`CONFIG_SPI_FLASH_AUTO_SUSPEND` 允许 flash/PSRAM 的 cache 访问和 SPI1 的操作并发执行。请参阅 :ref:`auto-suspend`,查看详细信息。
|
||||
在 {IDF_TARGET_NAME} 上,配置选项 :ref:`CONFIG_SPI_FLASH_AUTO_SUSPEND` 允许 Flash 的 cache 访问和 SPI1 的操作并发执行。该选项是可选的,依赖于特定的 SPI Flash 型号,因此默认是关闭的。请参阅 :ref:`auto-suspend`,查看详细信息。
|
||||
|
||||
禁用该选项时,在读取/写入/擦除 flash 期间,必须禁用 cache。使用驱动访问 SPI1 的相关约束参见 :ref:`impact_disabled_cache`。这些约束会带来更多的 IRAM/DRAM 消耗。
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
每个 UART 控制器可以独立配置波特率、数据位长度、位顺序、停止位位数、奇偶校验位等参数。所有具备完整功能的 UART 控制器都能与不同制造商的 UART 设备兼容,并且支持红外数据协会 (IrDA) 定义的标准协议。
|
||||
|
||||
.. only:: SOC_UART_LP_NUM
|
||||
.. only:: SOC_UART_HAS_LP_UART
|
||||
|
||||
此外,{IDF_TARGET_NAME} 芯片还有一个满足低功耗需求的 LP UART 控制器。LP UART 是原 UART 的功能剪裁版本。它只支持基础 UART 功能,不支持 IrDA 或 RS485 协议,并且只有一块较小的 RAM 存储空间。想要全面了解的 UART 及 LP UART 功能区别,请参考 **{IDF_TARGET_NAME} 技术参考手册** > UART 控制器 (UART) > 主要特性 [`PDF <{IDF_TARGET_TRM_EN_URL}#uart>`__]。
|
||||
|
||||
|
@ -30,6 +30,10 @@
|
|||
|
||||
步骤 1 到 3 为配置阶段,步骤 4 为 UART 运行阶段,步骤 5 和 6 为可选步骤。
|
||||
|
||||
.. only:: SOC_UART_HAS_LP_UART
|
||||
|
||||
此外,LP UART 控制器的编程需要注意 :ref:`uart-api-lp-uart-driver`。
|
||||
|
||||
UART 驱动程序函数通过 :cpp:type:`uart_port_t` 识别不同的 UART 控制器。调用以下所有函数均需此标识。
|
||||
|
||||
|
||||
|
@ -239,12 +243,6 @@ API 提供了一种便利的方法来处理本文所讨论的特定中断,即
|
|||
- 禁用中断:调用 :cpp:func:`uart_disable_pattern_det_intr`
|
||||
|
||||
|
||||
宏指令
|
||||
^^^^^^^^^^^^
|
||||
|
||||
API 还定义了一些宏指令。例如,:c:macro:`UART_HW_FIFO_LEN` 定义了硬件 FIFO 缓冲区的长度,:c:macro:`UART_BITRATE_MAX` 定义了 UART 控制器支持的最大波特率。
|
||||
|
||||
|
||||
.. _uart-api-deleting-driver:
|
||||
|
||||
删除驱动程序
|
||||
|
@ -253,12 +251,35 @@ API 还定义了一些宏指令。例如,:c:macro:`UART_HW_FIFO_LEN` 定义了
|
|||
如不再需要与 :cpp:func:`uart_driver_install` 建立通信,则可调用 :cpp:func:`uart_driver_delete` 删除驱动程序,释放已分配的资源。
|
||||
|
||||
|
||||
宏指令
|
||||
^^^^^^^^^^^^
|
||||
|
||||
API 还定义了一些宏指令。例如,:c:macro:`UART_HW_FIFO_LEN` 定义了硬件 FIFO 缓冲区的长度,:c:macro:`UART_BITRATE_MAX` 定义了 UART 控制器支持的最大波特率。
|
||||
|
||||
.. only:: SOC_UART_HAS_LP_UART
|
||||
|
||||
.. _uart-api-lp-uart-driver:
|
||||
|
||||
使用主核驱动 LP UART 控制器
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
UART 驱动程序还适配了在 Active 模式下对 LP UART 控制器的驱动。LP UART 的配置流程和普通 UART 没有本质上的差别,除了有以下几点需要注意:
|
||||
|
||||
.. list::
|
||||
|
||||
- LP UART 控制器的端口号为 :c:macro:`LP_UART_NUM_0`。
|
||||
- LP UART 控制器的可选时钟源可以在 :cpp:type:`lp_uart_sclk_t` 中找到。
|
||||
- LP UART 控制器的硬件 FIFO 大小要远小于普通 UART 控制器的硬件 FIFO 大小,其值为 :c:macro:`SOC_LP_UART_FIFO_LEN`。
|
||||
:SOC_LP_GPIO_MATRIX_SUPPORTED: - LP UART 控制器的 GPIO 引脚只能从 LP GPIO 引脚中选择。
|
||||
:not SOC_LP_GPIO_MATRIX_SUPPORTED: - 由于该芯片没有 LP GPIO 交换矩阵,LP UART 控制器的 GPIO 引脚不可改变。具体的引脚号请查看 **{IDF_TARGET_NAME} 技术参考手册** > **IO MUX 和 GPIO 交换矩阵 (GPIO, IO MUX)** > **LP IO MUX 管脚功能列表** [`PDF <{IDF_TARGET_TRM_CN_URL}#lp-io-mux-func-list>`__]。
|
||||
|
||||
|
||||
RS485 特定通信模式简介
|
||||
----------------------------------------------
|
||||
|
||||
.. note::
|
||||
|
||||
下文将使用 ``[UART_REGISTER_NAME].[UART_FIELD_BIT]`` 指代 UART 寄存器字段/位。了解特定模式位的更多信息,请参考 **{IDF_TARGET_NAME} 技术参考手册** > UART 控制器 (UART) > 寄存器摘要 [`PDF <{IDF_TARGET_TRM_EN_URL}#uart-reg-summ>`__]。请搜索寄存器名称导航至寄存器描述,找到相应字段/位。
|
||||
下文将使用 ``[UART_REGISTER_NAME].[UART_FIELD_BIT]`` 指代 UART 寄存器字段/位。了解特定模式位的更多信息,请参考 **{IDF_TARGET_NAME} 技术参考手册** > UART 控制器 (UART) > 寄存器摘要 [`PDF <{IDF_TARGET_TRM_CN_URL}#uart-reg-summ>`__]。请搜索寄存器名称导航至寄存器描述,找到相应字段/位。
|
||||
|
||||
- ``UART_RS485_CONF_REG.UART_RS485_EN``:设置此位将启用 RS485 通信模式支持。
|
||||
- ``UART_RS485_CONF_REG.UART_RS485TX_RX_EN``:设置此位,发送器的输出信号将环回到接收器的输入信号。
|
||||
|
|
Ładowanie…
Reference in New Issue