Compare commits

..

223 Commits

Author SHA1 Message Date
Ivan Grokhotkov
f5e484fc79 versions: Update version to 4.2.4 2022-08-31 00:18:44 +02:00
Island
997844bbc3 Merge branch 'bugfix/vendor_model_send_message_no_memory_forv4.2' into 'release/v4.2'
ble_mesh:example: free the memory of malloc (v4.2)

See merge request espressif/esp-idf!19187
2022-08-08 12:25:38 +08:00
Yuan Hong Hui
10f0879fdb ble_mesh:the memory requested by malloc has not benn released 2022-08-05 12:13:47 +00:00
Jiang Jiang Jian
d016f69ffc Merge branch 'feat/make_property_idf_component_manager_root_level_v4.2' into 'release/v4.2'
Feat/make property idf component manager root level (v4.2)

See merge request espressif/esp-idf!19084
2022-08-05 19:58:57 +08:00
Jiang Jiang Jian
847d9631b9 Merge branch 'bugfix/restore_missing_ble_mesh_videos_v4.2' into 'release/v4.2'
ble_mesh: doc: Restore missing ble mesh videos(v4.2)

See merge request espressif/esp-idf!19405
2022-08-05 19:58:42 +08:00
wangjialiang
3c5eb41914 ble_mesh: doc: Restore missing ble mesh videos 2022-08-05 13:57:25 +08:00
Jiang Jiang Jian
be26894259 Merge branch 'bugfix/install_key_refactor_v4.2' into 'release/v4.2'
esp_wifi: backported some wifi fixes (19472381)

See merge request espressif/esp-idf!19385
2022-08-05 10:42:26 +08:00
Kapil Gupta
bdc671aee3 esp_wifi: backported some wifi fixes (19472381)
1. G1 rx drop from key install code refactoring
2. Remove group cipher check for PMF connection
2022-08-04 12:21:20 +05:30
Marius Vikhammer
ca1628b310 Merge branch 'bugfix/freertos_event_group_unblock_race_condition_v4.2' into 'release/v4.2'
FreeRTOS: Fix event group task list race condition (v4.2)

See merge request espressif/esp-idf!19105
2022-08-04 13:14:26 +08:00
Jiang Jiang Jian
2f634a82d5 Merge branch 'bugfix/wlan_fixes_backports_v4.2' into 'release/v4.2'
esp_wifi: Fix some wlan issues(backport v4.2)

See merge request espressif/esp-idf!19362
2022-08-04 11:33:57 +08:00
Jiang Jiang Jian
a46d166c49 Merge branch 'bugfix/combined_softap_pmf_fixes_v4.2' into 'release/v4.2'
Combined bugfixes for SoftAP and PMF (Backport v4.2)

See merge request espressif/esp-idf!19121
2022-08-04 11:05:10 +08:00
Nachiket Kukade
0c88beb9c4 esp_wifi: Update wifi libs
Update wifi libs with below fixes -
1. Improved error handling in SoftAP Rx path, fixed LoRa IE length
2. Handle low memory scenario, re-enabling PMF Capable flag in STA PMF
2022-08-03 18:16:37 +05:30
Jiang Jiang Jian
c5875e64b1 Merge branch 'docs/update_wifi_api_doc_v4.2' into 'release/v4.2'
DOC: update wifi api docs ( backport v4.2)

See merge request espressif/esp-idf!18083
2022-08-03 20:12:06 +08:00
Kapil Gupta
0efba69571 wpa_supplicant: Unicast key renew in TKIP mic failure
Currently we always request group key renew for during
TKIP mic failure. Add support for unicast/multicast
key renew as per packet.
2022-08-03 14:47:07 +05:30
Kapil Gupta
ec70ed86e0 esp_wifi: Changes to not use pmkid caching when SSID is changed 2022-08-03 14:38:05 +05:30
Kapil Gupta
064474fca6 wpa_supplicant: Fix issues reported by coverity 2022-08-03 14:37:43 +05:30
Jiang Jiang Jian
d98e2a3d5f Merge branch 'bugfix/fix_write_to_null_pointer_if_malloc_failed_issue_v4.2' into 'release/v4.2'
fix write to null pointer if malloc failed(Backport v4.2)

See merge request espressif/esp-idf!19350
2022-08-03 10:59:10 +08:00
Jiang Jiang Jian
8e8cf08d2d Merge branch 'bugfix/update_gpio_intr_enable_note_v4.2' into 'release/v4.2'
Update the note of the gpio_intr_enable function(v4.2)

See merge request espressif/esp-idf!18544
2022-08-03 10:58:42 +08:00
xueyunfei
3ffcb03f60 bugfix for backport wifi bugs to 4.2
- Bugfix for close sniffer mode when wifi stop

  - Bugfix for qos null update ba ssn

  - Bugfix for wrong configuration of static txbuf

  - Fix deep sleep can't reconnect to ap when pmf enable.

  - Fix some ap will ignore auth when rx deauth for a while.

  - update wifi header file
2022-08-03 10:45:36 +08:00
Oleg Savchenko
0a0ad4309f fix write to null pointer if malloc failed 2022-08-02 20:30:30 +08:00
zhangyanjiao
63324950fa modify API-reference using Sphinx directives 2022-08-02 20:23:37 +08:00
zhangyanjiao
0a7fedcbbd update wifi api docs 2022-08-02 20:23:37 +08:00
Jiang Jiang Jian
9d854cd6b0 Merge branch 'bugfix/set_ipv6_dns_error_v4.2' into 'release/v4.2'
lw ip: Fixed that ipv6 dns cannot work (v4.2)

See merge request espressif/esp-idf!19064
2022-08-02 20:21:39 +08:00
Jiang Jiang Jian
eddee33f98 Merge branch 'bugfix/fix_bluedroid_host_memory_overflow_v4.2' into 'release/v4.2'
Fixed bluedroid host memory overflow for v4.2

See merge request espressif/esp-idf!18905
2022-08-02 19:47:41 +08:00
Jiang Jiang Jian
510f86d451 Merge branch 'bugfix/memory_debug_not_work_v4.2' into 'release/v4.2'
bugfix/fix the dependency error of macro for memory debug (v4.2)

See merge request espressif/esp-idf!19234
2022-08-02 15:49:36 +08:00
Jiang Jiang Jian
4bdc7853cf Merge branch 'bugfix/put_sempher_and_queue_used_in_isr_into_DRAM_v4.2' into 'release/v4.2'
Make sure semphr/queue used in interrupt is in DRAM

See merge request espressif/esp-idf!18990
2022-08-02 11:32:18 +08:00
Michael (XIAO Xufeng)
7718c60d81 Merge branch 'bugfix/reserve_dma_ram_in_segments_v4.2' into 'release/v4.2'
psram: reserve dma pool in the step of heap max block (v4.2)

See merge request espressif/esp-idf!18861
2022-08-01 17:14:46 +08:00
Fu Hanxi
8b09f2f01f ci: pip install idf-component-manager inside CI 2022-08-01 10:44:50 +08:00
Sergei Silnov
ac8b720880 docs: Add IDF_COMPONENT_MANAGER build property 2022-08-01 10:44:50 +08:00
Sergei Silnov
fdc70f5b7f docs: Enable the component manager by default in CMake 2022-08-01 10:44:50 +08:00
Fu Hanxi
5d1864b7d7 build&config: lift property IDF_COMPONENT_MANAGER to root level 2022-08-01 10:44:50 +08:00
David Čermák
9003e6d1eb Merge branch 'bugfix/cxx_exception_pool_4.2' into 'release/v4.2'
startup: Make __cxx_eh_arena_size_get return 0 if exceptions disabled (v4.2)

See merge request espressif/esp-idf!18800
2022-07-29 13:14:45 +08:00
zhiweijian@espressif.com
029ed39579 Fixed bluedroid host memory overflow 2022-07-28 09:47:03 +00:00
wanlei
da340c02cc psram: fixed heap pool reservation for DMA/internal usage fail issue
As heap block may be allocated into multiple non-continuous chunks, to
reserve enough memory for dma/internal usage, we do the malloc in the
step of max available block.
2022-07-28 10:17:17 +08:00
xiongweichao
06d169e518 Update the note of the gpio_intr_enable function 2022-07-26 12:39:42 +00:00
baohongde
1af2a470dc components/coex: Make sure sempher and queue used in isr is in DRAM
Closes https://github.com/espressif/esp-idf/issues/9032
Closes https://github.com/espressif/esp-idf/issues/8928
Closes https://github.com/espressif/esp-idf/issues/9129
2022-07-25 13:50:43 +08:00
baohongde
6842dc1d2d components/bt: Make sure sempher and queue used in isr is in DRAM 2022-07-25 11:45:45 +08:00
Jiang Jiang Jian
1801a10828 Merge branch 'bugfix/schm_process_in_active_crash_v4.2' into 'release/v4.2'
Coex: fixed crash when calculating end transfer time(v4.2)

See merge request espressif/esp-idf!19192
2022-07-22 21:24:16 +08:00
jincheng
b7fe47292f fix the dependency error of macro for memory debug 2022-07-22 16:21:57 +08:00
xiongweichao
61af5f66a4 coex: fixed crash when calculating end transfer time 2022-07-22 16:15:58 +08:00
Jiang Jiang Jian
ad9395f74a Merge branch 'mesh/non_mesh_connections_access_v4.2' into 'release/v4.2'
esp_wifi_mesh: add non mesh connections access(v4.2)

See merge request espressif/esp-idf!18785
2022-07-21 19:19:14 +08:00
Darian Leung
c7c07c5fb2 freertos: Fix flakey event group unit test
The "FreeRTOS Event Groups" main task will only wait a single tick for the created
tasks to set their response bits. This short delay may not be sufficent if the tick
frequency is high.

This commit updates the test so that

- the main task waits indefinitely for all the response bits to be set.
- created tasks are cleaned up by the main task
2022-07-19 12:19:42 +08:00
Darian Leung
5e15bafd26 freertos: Fix event group task list race condition
FreeRTOS synchronization primitives (e.g., queues, eventgroups) use various event lists (i.e., task lists) to track what
tasks are blocked on a current primitive. Usually these event lists are accessed via one of the event lists functions
(such as vTask[PlaceOn|RemoveFrom]UnorderedEventList()), which in turn ensure that the global task list spinlock
(xTaskQueueMutex) is taken when accessing these lists.

However, some functions in event_groups.c manually traverse their event lists. Thus if a tick interrupt occurs on
another core during traversal and that tick interrupt unblocks a task on the event list being traversed, the event list
will be corrupted.

This commit modifies the following event_groups.c functions so that they take the global task list lock before
traversing their event list.

- xEventGroupSetBits()
- vEventGroupDelete()
2022-07-19 12:13:54 +08:00
Chen Wu
43f1c37458 lwip: Fixed that ipv6 dns cannot work 2022-07-15 16:20:37 +08:00
Jiang Jiang Jian
611493af37 Merge branch 'docs/update_wifi_multiple_antennas_doc_v4.2' into 'release/v4.2'
docs: update wifi multiple antennas docs (v4.2)

See merge request espressif/esp-idf!19048
2022-07-15 10:48:10 +08:00
Island
23a3f97af1 Merge branch 'bugfix/print_ready_after_init_transaction_forv4.2' into 'release/v4.2'
ble_mesh:change the location of print ready(v4.2)

See merge request espressif/esp-idf!19030
2022-07-14 17:28:19 +08:00
Krzysztof Budzynski
15480c49e3 Apply 1 suggestion(s) to 1 file(s) 2022-07-14 16:44:00 +08:00
muhaidong
6ceabe794e Apply 2 suggestions by Marius Vikhammer 2022-07-14 16:42:55 +08:00
muhaidong
758e185090 docs: update wifi multiple antennas docs 2022-07-14 16:36:46 +08:00
Yuan Hong Hui
770075609f ble_mesh:change the location of print ready 2022-07-13 18:13:08 +08:00
David Čermák
bef5f431d9 Merge branch 'bugfix/eth_icmp_dest_localhost_v4.2' into 'release/v4.2'
ci/esp_eth: Make the ICMP destination localhost (v4.2)

See merge request espressif/esp-idf!18753
2022-07-13 16:06:53 +08:00
Jiang Jiang Jian
7a1df44319 Merge branch 'bugfix/modbus_allow_master_slave_work_simultaneously_v42' into 'release/v4.2'
freemodbus: fix issues when modbus master and slave work simultaneously (backport v4.2)

See merge request espressif/esp-idf!14949
2022-07-13 15:37:20 +08:00
Alex Lisitsyn
bfac558b6f freemodbus: fix issues when modbus master and slave work simultaneously (backport v4.2) 2022-07-13 15:37:19 +08:00
Jiang Jiang Jian
e040cd1a68 Merge branch 'bugfix/fix_esp32_ke_mem_c_assert_v4.2' into 'release/v4.2'
Fixed ESP32 BLE ke_mem.c assert for v4.2

See merge request espressif/esp-idf!19004
2022-07-13 14:06:47 +08:00
zwj
6c4351908c Fixed ESP32 BLE ke_mem.c assert 2022-07-13 03:08:09 +00:00
Island
d69e42348f Merge branch 'bugfix/no_proxy_beacon_send_after_deinit_v4.2' into 'release/v4.2'
ble_mesh: stack: Bugfix for proxy beacon send after reinit mesh(v4.2)

See merge request espressif/esp-idf!18793
2022-07-13 10:51:36 +08:00
Jiang Jiang Jian
221993edd4 Merge branch 'bugfix/not_use_malloc_in_bluedroid_v4.2' into 'release/v4.2'
component/bt: use osi_malloc instead of malloc in bluedroid

See merge request espressif/esp-idf!18845
2022-07-12 10:43:44 +08:00
Jiang Jiang Jian
989a390798 Merge branch 'bugfix/enterprise_certs_ca_expired_v4.2' into 'release/v4.2'
esp_wifi: Fix issue of ca certificate expired.

See merge request espressif/esp-idf!18524
2022-07-11 16:45:50 +08:00
Jiang Jiang Jian
8f2659e2ad Merge branch 'bugfix/eap_method_selection_release_v4.2' into 'release/v4.2'
esp_wifi: Fix the negotiation of method with eap server.

See merge request espressif/esp-idf!18509
2022-07-11 16:45:22 +08:00
Jiang Jiang Jian
a07f18ff9f Merge branch 'bugfix/cpu_reset_perip_clk_disable_v4.2' into 'release/v4.2'
esp_system: Peripheral clocks faulty become disabled during cpu reset (backport v4.2)

See merge request espressif/esp-idf!15486
2022-07-11 16:44:32 +08:00
Jiang Jiang Jian
443d8a187b Merge branch 'bugfix/fix_esp_restart_does_not_reset_timer_groups_periph_v42' into 'release/v4.2'
modbus: fix esp restart does not reset timer groups periph (backport v4.2)

See merge request espressif/esp-idf!15506
2022-07-11 16:42:42 +08:00
Alex Lisitsyn
eaf03e06d5 modbus: fix esp restart does not reset timer groups periph (backport v4.2) 2022-07-11 16:42:42 +08:00
Jiang Jiang Jian
034c05c82e Merge branch 'bugfix/usb_hal_and_clk_v4.2' into 'release/v4.2'
Fix USB with swapped pins not working (backport v4.2)

See merge request espressif/esp-idf!17104
2022-07-11 16:42:13 +08:00
Wang Meng Yang
94fd4ffa2e Merge branch 'bugfix/fix_osi_men_dbg_xxx_not_defined_when_enable_mem_dbg_v4.2' into 'release/v4.2'
bugfix/fix the issue of functions not defined when enable memory debug (v4.2)

See merge request espressif/esp-idf!18817
2022-07-11 15:37:54 +08:00
morris
c9bc1943fa ci/esp_eth: Make the ICMP destination localhost
Original commit: 9fa06719fa
global: enable build uinit test for esp32-s3
2022-07-11 04:53:40 +00:00
baohongde
68612afa09 component/bt: use osi_malloc instead of malloc in bluedroid 2022-07-11 02:48:10 +00:00
Jiang Jiang Jian
25253b22cc Merge branch 'bugfix/do_not_allow_unauthenticated_encrypted_key_data_release_v4.2' into 'release/v4.2'
esp_wifi: Ignore unauthenticated encrypted EAPOL-Key data and fix

See merge request espressif/esp-idf!18316
2022-07-10 15:59:53 +08:00
Jiang Jiang Jian
c2090fc962 Merge branch 'bugfix/a2dp_source_not_stop_discovery_correctly_v4.2' into 'release/v4.2'
bugfix/avoid wrongly restart discovery in a2dp_source (v4.2)

See merge request espressif/esp-idf!18712
2022-07-10 15:52:21 +08:00
Jiang Jiang Jian
c811a2c2f4 Merge branch 'bugfix/restore_edr_en_and_protect_for_vhci_env_v4.2' into 'release/v4.2'
bugfix/restore edr_en and add protect for vhci_env (v4.2)

See merge request espressif/esp-idf!18813
2022-07-10 15:49:27 +08:00
Jiang Jiang Jian
3266c6a2d4 Merge branch 'bugfix/lower_a2dp_appT_prio_v4.2' into 'release/v4.2'
bugfix/lower the priority of application task of a2dp demo (v4.2)

See merge request espressif/esp-idf!18822
2022-07-10 15:48:03 +08:00
Jiang Jiang Jian
02c3414fc0 Merge branch 'bugfix/resolve_redefinition_in_spp_and_hid_v4.2' into 'release/v4.2'
bugfix/resolve redefinition in btc_spp.h and btc_hd.h/btc_hh.h (v4.2)

See merge request espressif/esp-idf!18826
2022-07-10 15:47:02 +08:00
Jiang Jiang Jian
6afad65ecb Merge branch 'bugfix/xtensa_sol_frame_saves_extra_registers_v4.2' into 'release/v4.2'
freertos: Xtensa solicited stack frame should save threadptr register (v4.2)

See merge request espressif/esp-idf!18855
2022-07-10 15:45:06 +08:00
Jiang Jiang Jian
f735dfa617 Merge branch 'docs/update_wifi_csi_sub_carrier_index_doc_v4.2' into 'release/v4.2'
docs:update wifi sci subcarrier index docs (v4.2)

See merge request espressif/esp-idf!18943
2022-07-10 15:40:14 +08:00
muhaidong
496b27eb0a docs:update wifi sci subcarrier index docs 2022-07-08 14:51:48 +08:00
jincheng
aeeb255d35 resolve redefinition in btc_spp.h and btc_hd.h/btc_hh.h
Closes https://github.com/espressif/esp-idf/issues/9199
2022-07-08 14:23:09 +08:00
jincheng
e2c29bf4db avoid wrongly restart discovery 2022-07-08 14:19:54 +08:00
jincheng
aae7b6e1ae restore edr_en which wrongly cleared by rsw
add critical protection for vhci_env_p->vhci_intr_st
ignore max_page when handle remote features
2022-07-08 14:13:08 +08:00
jincheng
37b9d3f886 lower the priority of application task of a2dp demo 2022-07-08 14:03:26 +08:00
Jiang Jiang Jian
5f5a2d9c5a Merge branch 'bugfix/auto_test_script_only_use_given_branch_v4.2' into 'release/v4.2'
CI: limit switching branches for auto_test_script (v4.2)

See merge request espressif/esp-idf!11144
2022-07-08 11:26:07 +08:00
jincheng
24fc73c4e0 fix the issue of functions not defined when enable memory debug 2022-07-08 11:00:59 +08:00
Mahavir Jain
b85c0ec352 Merge branch 'bugfix/efuse_esp_efuse_utility_burn_efuses_v4.2' into 'release/v4.2'
efuse: Fix burn operation when data was written directly to regs (v4.2)

See merge request espressif/esp-idf!18887
2022-07-07 22:30:33 +08:00
Chen Yu Dong
4620826c83 ci: limit switching branches for auto_test_script 2022-07-06 11:55:33 +08:00
KonstantinKondrashov
404979d71a efuse: Fix burn operation when data was written directly to regs
Closes https://github.com/espressif/esp-idf/issues/9290
2022-07-05 18:29:27 +08:00
Darian Leung
0a894c2b30 freertos: Xtensa FreeRTOS saves threadptr in solicited stack frame
The Xtensa FreeRTOS port does not save the threadptr register when
doing a voluntary yield. This can result in a crash when multiple
tasks used the threadptr register and call "taskYIELD()".

This commit adds the threadptr register to the solicited stack frame.
2022-07-04 18:26:16 +08:00
Jakob Hasse
2bcfeb612f startup: Make __cxx_eh_arena_size_get return 0 if exceptions disabled
This function is necessary to provide the emergency exception
memory pool size for C++ code.
Since our libstdc++ always has exceptions enabled, this function
must exist here even if -fno-exception is set for user code.
2022-07-01 08:32:37 +02:00
wangjialiang
3facb2dcfa ble_mesh: stack: Bugfix for proxy beacon send after reinit mesh 2022-07-01 11:50:43 +08:00
shenjun
b408043d7e esp_wifi_mesh: add non mesh connections access 2022-06-30 21:19:23 +08:00
Island
42ea9b7cb1 Merge branch 'feature/add_filter_seq_auth_config_v4.2' into 'release/v4.2'
ble_mesh: stack: Add filter old seq_auth packet menuconfig(v4.2)

See merge request espressif/esp-idf!18651
2022-06-24 11:15:22 +08:00
wangjialiang
aa42bb3355 ble_mesh: stack: Add filter old seq_auth packet menuconfig 2022-06-23 16:22:08 +08:00
Jiang Jiang Jian
372ae83fde Merge branch 'bugfix/avdtp_genreal_reject_format_error_v4.2' into 'release/v4.2'
component_bt: Fix AVDTP general reject format error(v4.2)

See merge request espressif/esp-idf!18558
2022-06-21 20:54:34 +08:00
Jiang Jiang Jian
46f777a254 Merge branch 'feature/update_hfp_ag_version_v4.2' into 'release/v4.2'
component_bt: update hfp_ag version to 1.7.2(v4.2)

See merge request espressif/esp-idf!18605
2022-06-21 19:40:59 +08:00
xiongweichao
90f464c671 update hfp_ag version to 1.7.2 2022-06-21 14:50:44 +08:00
Jiang Jiang Jian
32aa2ab24e Merge branch 'feat/epi_flash_api_iram_save_4.2' into 'release/v4.2'
spi_flash: partially move API functions out of IRAM (v4.2)

See merge request espressif/esp-idf!18304
2022-06-19 23:22:48 +08:00
Jiang Jiang Jian
8f9a3d508e Merge branch 'bugfix/idle_task_skipped_light_sleep_backport_v4.2' into 'release/v4.2'
pm_impl: fix neither enter light sleep nor enter waiti state in idle task(backport v4.2)

See merge request espressif/esp-idf!17849
2022-06-19 23:21:57 +08:00
xiongweichao
cec2713416 Fix AVDTP general reject format error. 2022-06-17 10:28:50 +08:00
aditi_lonkar
d8d32d71c9 esp_wifi: Fix issue of ca certificate expired. 2022-06-15 17:23:20 +05:30
Hrudaynath Dhabe
f66638c360 esp_wifi: Fix the negotiation of method with eap server. 2022-06-15 05:57:15 +00:00
Jiang Jiang Jian
14b204e201 Merge branch 'bugfix/pm_enabled_bt_build_fail_v4.2' into 'release/v4.2'
Bluetooth build fail when power management is enabled(v4.2)

See merge request espressif/esp-idf!18383
2022-06-15 11:07:08 +08:00
Hrudaynath Dhabe
8eb3c959dc esp_wifi: Ignore unauthenticated encrypted EAPOL-Key data and fix handling of key RSC.
Closes https://github.com/espressif/esp-idf/issues/8401
2022-06-14 18:33:27 +05:30
Michael (XIAO Xufeng)
ac6f45d290 bootloader: support unlock MXIC flash chips 2022-06-09 12:41:56 +08:00
Cao Sen Miao
168880fe7b spi_flash: move the unlock patch to bootloader and add support for GD 2022-06-09 12:41:56 +08:00
Michael (XIAO Xufeng)
e5ac1eb83f spi_flash: fix the corruption of ROM after calling bootloader_execute_flash_command
The user register, especially dummy related ones, needs to be restored, otherwise the ROM function will not work.

Introduced in dd40123129.
2022-06-09 12:41:56 +08:00
Michael (XIAO Xufeng)
33a8c60b2c bootloader: add xmc spi_flash startup flow to improve reliability 2022-06-09 12:41:56 +08:00
Michael (XIAO Xufeng)
e1bd7b9d8f bootloader: create public bootloader_flash.h header
Move non-public functions into bootloader_flash_priv.h header
2022-06-09 12:41:56 +08:00
Michael (XIAO Xufeng)
9582cbe5b8 bootloader: fix the WRSR format for ISSI flash chips
1. The 2nd bootloader always call `rom_spiflash_unlock()`, but never help to clear the WEL bit when exit. This may cause system unstability.

   This commit helps to clear WEL when flash configuration is done.

   **RISK:** When the app starts, it didn't have to clear the WEL before it actually write/erase. But now the very first write/erase operation should be done after a WEL clear. Though the risk is little (all the following write/erase also need to clear the WEL), we still have to test this carefully, especially for those functions used by the OTA.

2. The `rom_spiflash_unlock()` function in the patch of ESP32 may (1) trigger the QPI, (2) clear the QE or (3) fail to unlock the ISSI chips.

   Status register bitmap of ISSI chip and GD chip:

| SR | ISSI | GD25LQ32C |
| -- | ---- | --------- |
| 0  | WIP  | WIP       |
| 1  | WEL  | WEL       |
| 2  | BP0  | BP0       |
| 3  | BP1  | BP1       |
| 4  | BP2  | BP2       |
| 5  | BP3  | BP3       |
| 6  | QE   | BP4       |
| 7  | SRWD | SRP0      |
| 8  |      | SRP1      |
| 9  |      | QE        |
| 10 |      | SUS2      |
| 11 |      | LB1       |
| 12 |      | LB2       |
| 13 |      | LB3       |
| 14 |      | CMP       |
| 15 |      | SUS1      |

   QE bit of other chips are at the bit 9 of the status register (i.e. bit 1 of SR2), which should be read by RDSR2 command.

   However, the RDSR2 (35H, Read Status 2) command for chip of other vendors happens to be the QIOEN (Enter QPI mode) command of ISSI chips. When the `rom_spiflash_unlock()` function trys to read SR2, it may trigger the QPI of ISSI chips.

   Moreover, when `rom_spiflash_unlock()` try to clear the BP4 bit in the status register, QE (bit 6) of ISSI chip may be cleared by accident. Or if the ISSI chip doesn't accept WRSR command with argument of two bytes (since it only have status register of one byte), it may fail to clear the other protect bits (BP0~BP3) as expected.

   This commit makes the `rom_spiflash_unlock()` check whether the vendor is issi. if so, `rom_spiflash_unlock()` only send RDSR to read the status register, send WRSR with only 1 byte argument, and also avoid clearing the QE bit (bit 6).

3. `rom_spiflash_unlock()` always send WRSR command to clear protection bits even when there is no protection bit active. And the execution of clearing status registers, which takes about 700us, will also happen even when there's no bits cleared.

   This commit skips the clearing of status register if there is no protection bits active.

Also move the execute_flash_command to be a bootloader API; move
implementation of spi_flash_wrap_set to the bootloader
2022-06-09 12:41:56 +08:00
Michael (XIAO Xufeng)
a130dcd5ec test_spiffs: increase test case stack size 2022-06-09 12:41:56 +08:00
Michael (XIAO Xufeng)
51584d4f2a spi_flash: partially move API functions out of IRAM 2022-06-09 12:41:56 +08:00
Jiang Jiang Jian
a3374b2d2f Merge branch 'bugfix/fix_cannot_lslp_again_after_ulp_wakeup_backport_v4.2' into 'release/v4.2'
sleep: fix cannot lightsleep again after a wakeup from ULP(backport v4.2)

See merge request espressif/esp-idf!18218
2022-06-07 11:21:42 +08:00
xiongweichao
0cb13d47cc Bluetooth build fail when power management is enabled 2022-06-06 20:28:25 +08:00
Roland Dobai
087c72e8ea Merge branch 'bugfix/disable_extensions_idfpy_tests_v4.2' into 'release/v4.2'
Tools: Make idf.py tests independent on extra extensions (v4.2)

See merge request espressif/esp-idf!18284
2022-06-03 19:05:26 +08:00
Sergei Silnov
2e8e620d94 Tools: Make idf.py tests independent on extra extensions 2022-06-02 17:56:38 +02:00
Jiang Jiang Jian
59a66f90c7 Merge branch 'bugfix/add_bda_to_read_rmt_name_param_v4.2' into 'release/v4.2'
Bugfix/add bda to read rmt name param v4.2

See merge request espressif/esp-idf!18282
2022-06-02 11:46:51 +08:00
Jiang Jiang Jian
83b2a98682 Merge branch 'feature/docker_build_gh_actions_v4.2' into 'release/v4.2'
ci: move Docker image builds to Github, plus other improvements (v4.2)

See merge request espressif/esp-idf!18289
2022-06-02 11:45:20 +08:00
keymoon
c670dc6d14 assign value to uninitialized bt_addr field 2022-05-29 18:04:53 -07:00
keymoon
2bf87b0a53 add address field to read_rmt_name_param 2022-05-29 18:04:41 -07:00
Ivan Grokhotkov
7d9aff3913 tools/docker: add README.md file to be displayed on Docker Hub
Closes https://github.com/espressif/esp-idf/issues/7933
2022-05-27 14:15:51 +02:00
Ivan Grokhotkov
cf44cbfdc9 ci: build and push Docker images in Github actions
Replaces the previously used Docker Hub autobuild infrastructure.
This allows for more flexible configuration of the build process,
at the expense of some extra maintenance of CI workflow files
required.
2022-05-27 14:15:47 +02:00
Ivan Grokhotkov
a1eb5c77e9 docs: document build arguments of the Docker image 2022-05-27 14:01:34 +02:00
Ivan Grokhotkov
1e64f241f9 tools/docker: add IDF_CLONE_SHALLOW and IDF_INSTALL_TARGETS arguments
These two arguments can be used to reduce the size of the Docker
image:

- Setting IDF_CLONE_SHALLOW enables shallow cloning.
- Setting IDF_INSTALL_TARGETS to the comma separated list of targets
  results in toolchains being installed only for these targets.
2022-05-27 14:01:22 +02:00
jingli
57975000fe esp_hw_support/sleep: fix cannot lightsleep again after a wakeup from ULP
Since ulp wakeup signal are connected to ulp int raw(except esp32), we
need to clear ulp int raw before sleep when ulp wakeup enabled. Otherwise,
if the ulp int raw is already set, chip will not sleep properly.

Closes https://github.com/espressif/esp-idf/issues/6229
2022-05-23 01:00:28 +08:00
Jiang Jiang Jian
b6b7a59958 Merge branch 'bugfix/twai_esp32_errata_workarounds_backport_v4.2' into 'release/v4.2'
TWAI: Add FIFO overrun handling and ESP32 hardware errata workarounds + Refactor TWAI HAL to store state information  (backport v4.2)

See merge request espressif/esp-idf!17106
2022-05-19 10:55:59 +08:00
Jiang Jiang Jian
b74fc002f1 Merge branch 'bugfix/driver_uart_fix_tx_bytes_rts_assert_failure_v42' into 'release/v4.2'
driver: fixes context switch while sending cause rts reset before send (backport v4.2)

See merge request espressif/esp-idf!17942
2022-05-19 10:55:36 +08:00
Alex Lisitsyn
721e26019e driver: fixes context switch while sending cause rts reset before send (backport v4.2) 2022-05-19 10:55:35 +08:00
Jiang Jiang Jian
9cb1729107 Merge branch 'bugfix/fix_adc_calibration_light_sleep_issue_v4.2' into 'release/v4.2'
adc: fix calibration error when waking up from light sleep (v4.2)

See merge request espressif/esp-idf!16931
2022-05-19 10:55:10 +08:00
Jiang Jiang Jian
ea173fc189 Merge branch 'bugfix/ble_mesh_console_correct_repl_config_prompt_forv4.2' into 'release/v4.2'
ble mesh:example:correct repl config prompt in ble mesh console(v4.2)

See merge request espressif/esp-idf!17185
2022-05-19 10:54:52 +08:00
Yuan Hong Hui
886e846dc0 ble mesh:example:correct repl config prompt in ble mesh console(v4.2) 2022-05-19 10:54:51 +08:00
Jiang Jiang Jian
0fba64486a Merge branch 'bugfix/spi_lose_last_3_bytes_v4.2' into 'release/v4.2'
spi_master: fix an issue where master cannot correctly receive data when using DMA in halfduplex mode (v4.2)

See merge request espressif/esp-idf!17379
2022-05-19 10:54:36 +08:00
Jiang Jiang Jian
c71a9e5704 Merge branch 'feature/check_block_after_burn_v4.2' into 'release/v4.2'
efuse: Validates data after burning and re-burnes it if necessary (v4.2)

See merge request espressif/esp-idf!17704
2022-05-19 10:54:19 +08:00
morris
6c66b39221 Merge branch 'feature/modbus_master_fix_check_uart_set_pin_v42' into 'release/v4.2'
example/modbus_master: fix the assert for uart_set_pin (backport v4.2)

See merge request espressif/esp-idf!17626
2022-05-10 18:30:03 +08:00
Elbert van de Put
07c8e86987 example/modbus_master: fix the assert for uart_set_pin
Signed-off-by: aleks <aleks@espressif.com>

Closes https://github.com/espressif/esp-idf/pull/8607
2022-05-10 08:05:22 +00:00
Jiang Jiang Jian
d6a975f6b2 Merge branch 'bugfix/_rtc_slow_length_incorrectly_optimized_backport_v4.2' into 'release/v4.2'
sleep_power_domain: fix _rtc_slow_length being incorrectly optimized by compiler(backport v4.2)

See merge request espressif/esp-idf!17976
2022-05-10 01:04:37 +08:00
morris
d0db75899d Merge branch 'bugfix/ledc_consecutive_fade_v4.2' into 'release/v4.2'
ledc: Bugfixes for issues related to fade protection (backport v4.2)

See merge request espressif/esp-idf!16955
2022-05-07 18:24:45 +08:00
jingli
05b7db9cd8 fix _rtc_slow_length being incorrectly optimized by compiler 2022-05-01 23:26:52 +08:00
Jiang Jiang Jian
667f3dfbad Merge branch 'bugfix/ignore_pmf_capable_flag_v4.2' into 'release/v4.2'
Always connect Station in PMF mode if possible (Backport v4.2)

See merge request espressif/esp-idf!17538
2022-05-01 20:10:58 +08:00
Jiang Jiang Jian
bf7b430f55 Merge branch 'contrib/github_pr_8779_v4.2' into 'release/v4.2'
esp_wifi: fix clearing default wifi netif procedure(v4.2)

See merge request espressif/esp-idf!17940
2022-04-28 16:17:14 +08:00
Jiang Jiang Jian
00d2c3037a Merge branch 'bugfix/fix_disable_bt_log_ci_fail_v4.2' into 'release/v4.2'
component_bt: Fix CI failure when disable bluetooth debug log(v4.2)

See merge request espressif/esp-idf!17905
2022-04-27 18:20:27 +08:00
Jiang Jiang Jian
5c1d1c0f45 Merge branch 'bugfix/spp_crash_after_call_spp_deinit_v4.2' into 'release/v4.2'
Component_bt/Fix spp crash after call esp_spp_deinit(v4.2)

See merge request espressif/esp-idf!17933
2022-04-27 18:06:57 +08:00
Krzysztof Lewandowski
55b6ff6fbd esp_wifi: fix clearing default wifi netif procedure
Prior to this change "esp_wifi_clear_default_wifi_driver_and_handlers"
will not remove netif pointer from table when both AP and STA interfaces were
created and destroying default wifi interfaces is done in unfortunate
order. As a result there is dangling pointer left and it may cause crash in
later code (i.e. when esp_wifi_stop() is called).
2022-04-27 03:23:20 -04:00
xiongweichao
d59d373edc Fix spp initialization failure without free mutex 2022-04-27 14:49:39 +08:00
xiongweichao
9e2ae1271d Fix spp crash after calling esp_spp_deinit 2022-04-27 14:43:42 +08:00
xiongweichao
0825981026 Fix CI failure when disable bluetooth debug log 2022-04-26 15:06:50 +08:00
KonstantinKondrashov
83728f3832 efuse: fix 2022-04-26 00:08:51 +08:00
Island
8b422cd8b1 Merge branch 'bugfix/oversized_SegN_as_valid_v4.2' into 'release/v4.2'
ble_mesh: stack: Bugfix for oversized SegN as valid(v4.2)

See merge request espressif/esp-idf!17774
2022-04-25 18:52:04 +08:00
wangjialiang
7691b8effb ble_mesh: stack: Bugfix for oversized SegN as valid 2022-04-25 11:53:35 +08:00
Jiang Jiang Jian
c35cd9d0fe Merge branch 'bugfix/rrm_dpp_task_delete_v4.2' into 'release/v4.2'
Bugfix/rrm dpp task delete v4.2

See merge request espressif/esp-idf!17880
2022-04-25 10:52:26 +08:00
Jack
be2779818b fix build error 2022-04-23 01:11:29 +08:00
Jack
fdf79ce300 ESP_WIFI: Remove static analysis warnings 2022-04-23 00:54:30 +08:00
Kapil Gupta
dc87416df0 wpa_supplicant: static analysis fixes 2022-04-23 00:33:34 +08:00
Kapil Gupta
a26b0dbaab wpa_supplicant: Add BTM security checks 2022-04-23 00:26:08 +08:00
Jiang Jiang Jian
06837c7efa Merge branch 'bugfix/fix_phy_i2c_crash_v4.2' into 'release/v4.2'
esp_phy: Add IRAM_ATTR for phy i2c spinlock (v4.2)

See merge request espressif/esp-idf!17844
2022-04-21 15:47:04 +08:00
gaoxiaojie
5516dc7d0c pm_impl: fix neither enter light sleep nor enter waiti state in idle task 2022-04-21 14:40:57 +08:00
xiewenxiang
d976bbec08 esp_phy: Add IRAM_ATTR for phy i2c spinlock 2022-04-21 02:57:08 +08:00
Wang Meng Yang
d8105a565e Merge branch 'bugfix/fix_spp_initiator_connect_failed_v4.2' into 'release/v4.2'
Component_bt/Fix SPP initiator can not free resource when connection is failed[backport 4.2]

See merge request espressif/esp-idf!17746
2022-04-19 15:49:12 +08:00
morris
7cb3e99740 Merge branch 'fix/spi_master_use_data_flag_v4.2' into 'release/v4.2'
spi_master: fix the error log when use tx/rx_data with larger data (v4.2)

See merge request espressif/esp-idf!17800
2022-04-18 23:22:02 +08:00
Michael (XIAO Xufeng)
5edd6a4ddf spi_master: fix the error log when use tx/rx_data with larger data 2022-04-18 15:15:06 +08:00
Michael (XIAO Xufeng)
396159299c Merge branch 'bugfix/gpio_pin_num_fix_v4.2' into 'release/v4.2'
gpio: Fix some gpio pin num errors on esp32s2 (backport v4.2)

See merge request espressif/esp-idf!17110
2022-04-18 14:49:52 +08:00
Ivan Grokhotkov
34a326130a Merge branch 'bugfix/nvs_coverity_issues_4.2' into 'release/v4.2'
bugfix (nvs): Fixed issues found by Coverity (backport v4.2)

See merge request espressif/esp-idf!17764
2022-04-14 17:44:51 +08:00
Jakob Hasse
e5eccb409e bugfix (nvs): Fixed issues found by Coverity
*  Fixed potential memory leak
*  Fixed wrong strncpy usage
*  Fixed potential out of bounds access
2022-04-13 18:02:47 +08:00
Nachiket Kukade
154e579cfc esp_wifi: Always connect Station in PMF mode if possible
While using esp_wifi_set_config, flag pmf_capable defaults to 0.
Users may not bother to enable it, which prevents connection to a
WPA3 AP. Or the AP may reset into WPA3 mode failing the re-connection.
To ensure better security, deprecate the pmf_capable flag and set it to
true internally.
Additionally add API esp_wifi_disable_pmf_config to disable PMF for
debug purposes or to avoid PMF issues on AP side.
2022-04-12 18:40:51 +05:30
liqigan
0c2c192013 add missing unlock in btc_spp_cb_handler of BTA_JV_RFCOMM_WRITE_EVT 2022-04-12 15:37:07 +08:00
liqigan
95ad53153f fix SPP initiator can not free resource when connection is failed 2022-04-12 15:36:47 +08:00
Wang Meng Yang
43ee24a52e Merge branch 'bugfix/bt_add_some_debug_log_v4.2' into 'release/v4.2'
component_bt: Add some bluetooth debug log(v4.2)

See merge request espressif/esp-idf!17616
2022-04-11 10:53:40 +08:00
KonstantinKondrashov
dffcb3d0fb efuse: Fix 3/4 coding scheme UTs 2022-04-08 17:13:23 +08:00
morris
ffe304268d Merge branch 'bugfix/modbus_add_task_affinity_and_callbacks_v42' into 'release/v4.2'
freemodbus: add task affinity and callbacks (backport v4.2)

See merge request espressif/esp-idf!14542
2022-04-08 15:59:33 +08:00
KonstantinKondrashov
3a4cf61318 efuse: Improve messages during burn operation 2022-04-07 22:25:06 +08:00
Michael (XIAO Xufeng)
2ec7449c37 Merge branch 'bugfix/phy_regi2c_critical_section_v4.2' into 'release/v4.2'
esp_phy: use spinlock to avoid regi2c access conflicts (v4.2)

See merge request espressif/esp-idf!17693
2022-04-07 20:19:33 +08:00
morris
c226560f6b Merge branch 'bugfix/flash_mmap_output_psram_arg_v4.2' into 'release/v4.2'
mmap: fixed the issue mmap cannot be called with pointers to psram (v4.2)

See merge request espressif/esp-idf!17699
2022-04-07 10:54:08 +08:00
KonstantinKondrashov
08a06865ec efuse: Burn func can return an error
esp_efuse_utility_burn_chip()
2022-04-06 23:42:26 +08:00
KonstantinKondrashov
26619521fb efuse: Validates data after burning and re-burnes it if necessary
It checks the content of the written data and encoding errors.
2022-04-06 20:02:46 +08:00
Michael (XIAO Xufeng)
50b87ff953 mmap: fixed the issue mmap cannot be called with pointers to psram 2022-04-06 17:23:42 +08:00
Anton Maklakov
66d65e66fd Merge branch 'feature/add_component_manager_python_dependency_v4.2' into 'release/v4.2'
Build System: Add idf-component-manager python dependency (v4.2)

See merge request espressif/esp-idf!15986
2022-04-06 16:31:26 +08:00
Michael (XIAO Xufeng)
cb0b143cb3 esp_phy: use spinlock to avoid regi2c access conflicts 2022-04-06 15:01:35 +08:00
Michael (XIAO Xufeng)
171096e856 regi2c: use safe version of spinlock, instead of ISR ver 2022-04-06 14:47:10 +08:00
Michael (XIAO Xufeng)
69c95bf983 Merge branch 'bugfix/spi_free_crash_uninitialized_v4.2' into 'release/v4.2'
spi: fixed crash when calling spi_bus_free when not initialized (v4.2)

See merge request espressif/esp-idf!17610
2022-04-01 11:17:54 +08:00
Michael (XIAO Xufeng)
e7d95dc787 Merge branch 'bugfix/gpio_example_config_struct_zero_init_v4.2' into 'release/v4.2'
example: fixed the issue that config struct is not properly initialized (v4.2)

See merge request espressif/esp-idf!17589
2022-04-01 11:17:17 +08:00
Michael (XIAO Xufeng)
c7c7d5d01d Merge branch 'bugfix/fix_x32k_startup_slow_bug_v4.2' into 'release/v4.2'
bugfix: Fix xtal 32k not oscillate or oscillate too slowly issue for esp32 (v4.2)

See merge request espressif/esp-idf!17591
2022-03-30 17:54:41 +08:00
chaijie
b2e08332e3 ESP32: Fix xtal 32k not oscillate or oscillate too slowly issue
ESP32 in revision0 and revision1 uses touchpad to provide
current to oscillate xtal 32k. But revision2 and revision3
do not need to do that.
Note: touchpad can not work and toupad/ULP wakeup sources
are not available when toupad provides current to xtal 32k
2022-03-30 15:27:03 +08:00
songruojing
affb956da5 esp_system: fix the bug that some peripheral clocks are being disabled during cpu reset for esp32s2 2022-03-29 03:42:34 +00:00
songruojing
9e79d0e06f ledc: Fix FADE_NO_WAIT mode concurrency problem.
Add test cases for fade concurrency issue and fade timing check.

Closes https://github.com/espressif/esp-idf/issues/6710

(cherry picked from commit be2ab09832)
2022-03-29 03:42:06 +00:00
songruojing
01547c4bd8 ledc: Simplify the procedure to perform a one-time duty update
Avoid adding one extra fade cycle when performing a one-time duty update.
Add some notes to ledc_get_duty and ledc_update_duty APIs, so that users
are aware of when the new duty will be effective.

Closes https://github.com/espressif/esp-idf/issues/7288

(cherry picked from commit e175086226)
2022-03-29 03:42:06 +00:00
me-no-dev
198ce9095a Fix USB with swapped pins not working
(cherry picked from commit 0aa1c13027)
2022-03-29 03:41:28 +00:00
songruojing
4c267ef0a6 gpio: Fix some gpio pin num errors on esp32s2 2022-03-29 03:40:54 +00:00
xiongweichao
b8c9bb4247 Add some bluetooth debug log 2022-03-28 11:28:50 +08:00
Michael (XIAO Xufeng)
49231ae961 spi: fixed crash when calling spi_bus_free when not initialized
introduced in 49a48644e4

Closes: https://github.com/espressif/esp-idf/issues/8642
2022-03-27 02:41:09 +08:00
Michael (XIAO Xufeng)
75f856ac37 example: fixed the issue that config struct is not properly initialized 2022-03-25 01:11:55 +08:00
Michael (XIAO Xufeng)
680710df2f Merge branch 'test/remove_spi_flash_perf_thr_v4.2' into 'release/v4.2'
spi_flash_test: remove threshold from unit test (v4.2)

See merge request espressif/esp-idf!16824
2022-03-19 02:36:18 +08:00
morris
84effb1708 Merge branch 'bugfix/sleep_wrong_log_lvl_v4.2' into 'release/v4.2'
Sleep: fix wrong debug level (backport v4.2)

See merge request espressif/esp-idf!17300
2022-03-16 17:10:53 +08:00
Michael (XIAO Xufeng)
16629eaf99 Merge branch 'bugfix/bootloader_uart_custom_gpio_v4.2' into 'release/v4.2'
bootloader: fixed the issue custom_uart_gpio doesn't take effect (v4.2)

See merge request espressif/esp-idf!17309
2022-03-16 11:39:36 +08:00
Jiang Jiang Jian
550872d629 Merge branch 'bugfix/assoc_comeback_fail_issue_v4.2' into 'release/v4.2'
Fix assoc comeback causing invalid state (Backport v4.2)

See merge request espressif/esp-idf!17174
2022-03-16 10:47:48 +08:00
Jiang Jiang Jian
ebee6f3c3f Merge branch 'bugfix/dual_core_pm_lock_issue_backport_v4.2' into 'release/v4.2'
System: fix pm lock issue in dual core mode(backport v4.2)

See merge request espressif/esp-idf!17263
2022-03-16 10:33:29 +08:00
Michael (XIAO Xufeng)
26cf75cb44 spi_flash_test: remove threshold from unit test 2022-03-15 15:22:55 +00:00
Michael (XIAO Xufeng)
67fea1b6bf test_utils: allow printint multiple argument in the performance log 2022-03-15 15:22:55 +00:00
Michael (XIAO Xufeng)
c2d2d58ff1 Merge branch 'bugfix/esp_flash_write_temp_buffer_lifetime_v4.2' into 'release/v4.2'
esp_flash: fix write issue using buffer on stack out of lifetime (v4.2)

See merge request espressif/esp-idf!17206
2022-03-15 22:14:57 +08:00
Michael (XIAO Xufeng)
6c21202065 Merge branch 'fix/sdio_slave_recv_intr_unhandled_v4.2' into 'release/v4.2'
sdio_slave: fixed the issue that interrupt may be cleared with finished trans unhandled (v4.2)

See merge request espressif/esp-idf!17150
2022-03-15 22:06:19 +08:00
Michael (XIAO Xufeng)
608e189a53 Merge branch 'ci/enable_default_ut_s2' into 'release/v4.2'
ci: enable unit test for S2 by default

See merge request espressif/esp-idf!17114
2022-03-15 22:03:07 +08:00
Omar Chebib
ba3266e2ec Sleep: fix wrong debug level
Fix usage of ESP_LOGD in sleep_modes.c which triggers a panic when
used in debug log level.
2022-03-15 11:18:42 +00:00
Roland Dobai
cc230188ea Merge branch 'bugfix/flash_from_monitor_on_windows_v4.2' into 'release/v4.2'
Tools: IDF Monitor should flash with the unmodified port (v4.2)

See merge request espressif/esp-idf!17259
2022-03-12 23:19:06 +08:00
Wang Meng Yang
09a8221d31 Merge branch 'feature/update_hfp_hf_version_v4.2' into 'release/v4.2'
component_bt: Update HFP_HF version to 1.7.2(v4.2)

See merge request espressif/esp-idf!17393
2022-03-10 20:20:08 +08:00
Wang Meng Yang
093fc90b92 Merge branch 'bugfix/a2dp_sniff_v4.2' into 'release/v4.2'
Fix crash when host exit sniff mode(v4.2)

See merge request espressif/esp-idf!17342
2022-03-10 14:09:03 +08:00
Krzysztof Budzynski
219c579084 Merge branch 'docs/fix_broken_links_4.2' into 'release/v4.2'
docs: fix broken links in queue.h file (v4.2)

See merge request espressif/esp-idf!17182
2022-03-09 19:12:40 +08:00
morris
cc518c3d05 Merge branch 'bugfix/i2s_write_failed_in_32bit_slave_mode_v4.2' into 'release/v4.2'
i2s: fix write failure issue in slave mode (backport v4.2)

See merge request espressif/esp-idf!15082
2022-03-09 19:10:56 +08:00
xiongweichao
5e8b07bdea Update HFP_HF version to 1.7.2 2022-03-08 11:11:58 +08:00
Armando
e9bbe44d19 spi_master: fix master HD mode cannot correctly receive data issue when using DMA 2022-03-07 13:54:25 +08:00
Armando
e6c97308b9 sleep: restore analog calibration registers after waking up from light sleep 2022-03-07 11:18:21 +08:00
Jiang Jiang Jian
3c9cc070dd Merge branch 'update/version_4_2_3' into 'release/v4.2'
Update version to 4.2.3

See merge request espressif/esp-idf!17349
2022-03-04 19:00:02 +08:00
xiongweichao
306df682cc Fix crash when host exit sniff mode 2022-03-03 16:31:43 +08:00
laokaiyao
0c71604b80 i2s: fix write failure issue in slave mode (backport v4.2) 2022-03-03 15:16:53 +08:00
songruojing
3d13370968 uart: fixed incorrect channel number on ESP32S2, S3 and C3 2022-03-02 10:53:30 +08:00
Michael (XIAO Xufeng)
d87d385e6f bootloader: fixed the issue custom_uart_gpio doesn't take effect 2022-03-02 10:53:30 +08:00
jingli
8dd7662696 fix pm lock issue in dual core mode 2022-02-23 22:00:36 +08:00
Roland Dobai
95eb9626a4 Tools: IDF Monitor should flash with the unmodified port
Closes https://github.com/espressif/esp-idf/issues/8432
2022-02-23 13:50:18 +01:00
Michael (XIAO Xufeng)
ea6f4fd2ff esp_flash: fix write issue using buffer on stack out of lifetime 2022-02-20 03:24:59 +08:00
intern
e954c47abd docs: fix broken links 2022-02-16 14:24:22 +08:00
Nachiket Kukade
9f85fb2843 esp_wifi: Update wifi lib
Fix assoc comeback causing invalid state
2022-02-15 18:11:41 +05:30
Darian Leung
a0666b9be8 TWAI: FIFO overrun handling and errata workarounds
This commit adds handling for FIFO overruns and
adds workarounds for HW erratas on the ESP32.

Closes https://github.com/espressif/esp-idf/issues/2519
Closes https://github.com/espressif/esp-idf/issues/4276
2022-02-15 14:16:53 +08:00
Darian Leung
90ee294139 TWAI: Track HW state in HAL
This commit refactors the TWAI HAL such that it now tracks
the harwdare's state instead of at the driver layer.
Some HAL and LL cleanup was also done.
2022-02-15 14:16:53 +08:00
Michael (XIAO Xufeng)
aed907c728 sdio_slave: fixed the issue that interrupt may be cleared with finished trans unhandled 2022-02-15 00:01:46 +08:00
Michael (XIAO Xufeng)
067678bdf9 ci: enable unit test for S2 by default 2022-02-11 04:09:17 +00:00
Sergei Silnov
018524ec7e examples: Add the component manager example 2022-02-02 16:44:44 +01:00
Sergei Silnov
3a4218156c docs: Add component manager documentation 2022-02-02 16:44:43 +01:00
Sergei Silnov
5594a511c9 Build System: Don't track dependencies.lock 2022-02-02 16:44:43 +01:00
Sergei Silnov
d955043aea Add idf-component-manager python dependency 2022-02-02 16:44:43 +01:00
aleks
68e7ecec67 freemodbus: add affinity option for modbus stack tasks 2021-07-28 08:46:52 +02:00
271 changed files with 4683 additions and 2739 deletions

87
.github/workflows/docker.yml vendored Normal file
View File

@@ -0,0 +1,87 @@
name: docker
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
on:
push:
branches:
- 'master'
- 'release/*'
tags:
- 'v*.*'
env:
# Platforms to build the image for
BUILD_PLATFORMS: linux/amd64
DOCKERHUB_REPO: ${{ github.repository_owner }}/idf
jobs:
docker:
# Disable the job in forks
if: ${{ github.repository_owner == 'espressif' }}
runs-on: ubuntu-latest
steps:
# Depending on the branch/tag, set CLONE_BRANCH_OR_TAG variable (used in the Dockerfile
# as a build arg) and TAG_NAME (used when tagging the image).
#
# The following 3 steps cover the alternatives (tag, release branch, master branch):
- name: Set variables (tags)
if: ${{ github.ref_type == 'tag' }}
run: |
echo "CLONE_BRANCH_OR_TAG=$GITHUB_REF_NAME" >> $GITHUB_ENV
echo "TAG_NAME=$GITHUB_REF_NAME" >> $GITHUB_ENV
- name: Set variables (release branches)
if: ${{ github.ref_type == 'branch' && startsWith(github.ref_name, 'release/') }}
run: |
echo "CLONE_BRANCH_OR_TAG=$GITHUB_REF_NAME" >> $GITHUB_ENV
echo "TAG_NAME=release-${GITHUB_REF_NAME##release/}" >> $GITHUB_ENV
- name: Set variables (main branch)
if: ${{ github.ref_type == 'branch' && github.ref_name == 'master' }}
run: |
echo "CLONE_BRANCH_OR_TAG=master" >> $GITHUB_ENV
echo "TAG_NAME=latest" >> $GITHUB_ENV
# Display the variables set above, just in case.
- name: Check variables
run: |
echo "CLONE_BRANCH_OR_TAG: $CLONE_BRANCH_OR_TAG"
echo "CHECKOUT_REF: $CHECKOUT_REF"
echo "TAG_NAME: $TAG_NAME"
# The following steps are the standard boilerplate from
# https://github.com/marketplace/actions/build-and-push-docker-images
- name: Checkout
uses: actions/checkout@v3
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up QEMU for multiarch builds
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Build and push
uses: docker/build-push-action@v3
with:
context: tools/docker
push: true
tags: ${{ env.DOCKERHUB_REPO }}:${{ env.TAG_NAME }}
platforms: ${{ env.BUILD_PLATFORMS }}
build-args: |
IDF_CLONE_URL=${{ github.server_url }}/${{ github.repository }}.git
IDF_CLONE_BRANCH_OR_TAG=${{ env.CLONE_BRANCH_OR_TAG }}
- name: Update Docker Hub repository description (master branch)
if: ${{ github.ref_type == 'branch' && github.ref_name == 'master' }}
uses: peter-evans/dockerhub-description@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
# Token based authentication is not supported here:
# https://github.com/peter-evans/dockerhub-description/issues/10
# https://github.com/docker/roadmap/issues/115#issuecomment-891694974
password: ${{ secrets.DOCKERHUB_PASSWORD }}
repository: ${{ env.DOCKERHUB_REPO }}
readme-filepath: ./tools/docker/README.md

View File

@@ -9,7 +9,7 @@ entries:
SEGGER_SYSVIEW_Config_FreeRTOS (noflash)
SEGGER_SYSVIEW_FreeRTOS (noflash)
[mapping:driver]
[mapping:app_trace_driver]
archive: libdriver.a
entries:
if SYSVIEW_TS_SOURCE_TIMER_00 = y || SYSVIEW_TS_SOURCE_TIMER_01 = y

View File

@@ -23,7 +23,7 @@
#include "unity.h"
#include "bootloader_common.h"
#include "../include_bootloader/bootloader_flash.h"
#include "../include_bootloader/bootloader_flash_priv.h"
#include "esp_log.h"
#include "esp_ota_ops.h"

View File

@@ -309,6 +309,15 @@ menu "Bootloader config"
in this area of memory, you can increase it. It must be a multiple of 4 bytes.
This area (rtc_retain_mem_t) is reserved and has access from the bootloader and an application.
config BOOTLOADER_FLASH_XMC_SUPPORT
bool "Enable the support for flash chips of XMC (READ HELP FIRST)"
default y
help
Perform the startup flow recommended by XMC. Please consult XMC for the details of this flow.
XMC chips will be forbidden to be used, when this option is disabled.
DON'T DISABLE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.
endmenu # Bootloader

View File

@@ -0,0 +1,61 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <stdint.h>
#include <esp_err.h>
#include <esp_spi_flash.h> /* including in bootloader for error values */
#include "sdkconfig.h"
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Read flash ID by sending 0x9F command
* @return flash raw ID
* mfg_id = (ID >> 16) & 0xFF;
flash_id = ID & 0xffff;
*/
uint32_t bootloader_read_flash_id(void);
#if SOC_CACHE_SUPPORT_WRAP
/**
* @brief Set the burst mode setting command for specified wrap mode.
*
* @param mode The specified warp mode.
* @return always ESP_OK
*/
esp_err_t bootloader_flash_wrap_set(spi_flash_wrap_mode_t mode);
#endif
/**
* @brief Startup flow recommended by XMC. Call at startup before any erase/write operation.
*
* @return ESP_OK When startup successfully, otherwise ESP_FAIL (indiciating you should reboot before erase/write).
*/
esp_err_t bootloader_flash_xmc_startup(void);
/**
* @brief Unlock Flash write protect.
* Please do not call this function in SDK.
*
* @note This can be overridden because it's attribute weak.
*/
esp_err_t bootloader_flash_unlock(void);
#ifdef __cplusplus
}
#endif

View File

@@ -19,11 +19,28 @@
#include <stdint.h>
#include <esp_err.h>
#include <esp_spi_flash.h> /* including in bootloader for error values */
#include "sdkconfig.h"
#include "bootloader_flash.h"
#define FLASH_SECTOR_SIZE 0x1000
#define FLASH_BLOCK_SIZE 0x10000
#define MMAP_ALIGNED_MASK 0x0000FFFF
/* SPI commands (actual on-wire commands not SPI controller bitmasks)
Suitable for use with the bootloader_execute_flash_command static function.
*/
#define CMD_RDID 0x9F
#define CMD_WRSR 0x01
#define CMD_WRSR2 0x31 /* Not all SPI flash uses this command */
#define CMD_WREN 0x06
#define CMD_WRDI 0x04
#define CMD_RDSR 0x05
#define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */
#define CMD_OTPEN 0x3A /* Enable OTP mode, not all SPI flash uses this command */
#define CMD_RDSFDP 0x5A /* Read the SFDP of the flash */
#define CMD_WRAP 0x77 /* Set burst with wrap command */
/* Provide a Flash API for bootloader_support code,
that can be used from bootloader or app code.
@@ -136,4 +153,29 @@ static inline uint32_t bootloader_cache_pages_to_map(uint32_t size, uint32_t vad
return (size + (vaddr - (vaddr & MMU_FLASH_MASK)) + MMU_BLOCK_SIZE - 1) / MMU_BLOCK_SIZE;
}
/**
* @brief Execute a user command on the flash
*
* @param command The command value to execute.
* @param mosi_data MOSI data to send
* @param mosi_len Length of MOSI data, in bits
* @param miso_len Length of MISO data to receive, in bits
* @return Received MISO data
*/
uint32_t bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len);
/**
* @brief Read the SFDP of the flash
*
* @param sfdp_addr Address of the parameter to read
* @param miso_byte_num Bytes to read
* @return The read SFDP, little endian, 4 bytes at most
*/
uint32_t bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num);
/**
* @brief Enable the flash write protect (WEL bit).
*/
void bootloader_enable_wp(void);
#endif

View File

@@ -13,6 +13,8 @@
// limitations under the License.
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif

View File

@@ -28,7 +28,7 @@
#include "esp32s2/rom/gpio.h"
#endif
#include "esp_flash_partitions.h"
#include "bootloader_flash.h"
#include "bootloader_flash_priv.h"
#include "bootloader_common.h"
#include "bootloader_utility.h"
#include "soc/gpio_periph.h"

View File

@@ -13,13 +13,44 @@
// limitations under the License.
#include <stddef.h>
#include <bootloader_flash.h>
#include <bootloader_flash_priv.h>
#include <esp_log.h>
#include <esp_flash_encrypt.h>
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/spi_flash.h"
#include "sdkconfig.h"
#include "soc/soc_caps.h"
#if CONFIG_IDF_TARGET_ESP32
# include "soc/spi_struct.h"
# include "soc/spi_reg.h"
/* SPI flash controller */
# define SPIFLASH SPI1
#else
# include "soc/spi_mem_struct.h"
# include "soc/spi_mem_reg.h"
/* SPI flash controller */
# define SPIFLASH SPIMEM1
#endif
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/spi_flash.h"
#include "esp32/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/spi_flash.h" //For SPI_Encrypt_Write
#include "esp32s2/rom/ets_sys.h"
#endif
#define BYTESHIFT(VAR, IDX) (((VAR) >> ((IDX) * 8)) & 0xFF)
#define ISSI_ID 0x9D
#define MXIC_ID 0xC2
#define GD_Q_ID_HIGH 0xC8
#define GD_Q_ID_MID 0x40
#define GD_Q_ID_LOW 0x16
#define ESP_BOOTLOADER_SPIFLASH_BP_MASK_ISSI (BIT7 | BIT5 | BIT4 | BIT3 | BIT2)
#define ESP_BOOTLOADER_SPIFLASH_QE_GD_SR2 BIT1 // QE position when you write 8 bits(for SR2) at one time.
#define ESP_BOOTLOADER_SPIFLASH_QE_SR1_2BYTE BIT9 // QE position when you write 16 bits at one time.
#ifndef BOOTLOADER_BUILD
/* Normal app version maps to esp_spi_flash.h operations...
*/
@@ -89,7 +120,7 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
return spi_flash_erase_range(start_addr, size);
}
#else
#else //BOOTLOADER_BUILD
/* Bootloader version, uses ROM functions only */
#include "soc/dport_reg.h"
#if CONFIG_IDF_TARGET_ESP32
@@ -318,7 +349,7 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool
return ESP_FAIL;
}
err = spi_to_esp_err(esp_rom_spiflash_unlock());
err = bootloader_flash_unlock();
if (err != ESP_OK) {
return err;
}
@@ -364,4 +395,332 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
}
return spi_to_esp_err(rc);
}
#endif // BOOTLOADER_BUILD
FORCE_INLINE_ATTR bool is_issi_chip(const esp_rom_spiflash_chip_t* chip)
{
return BYTESHIFT(chip->device_id, 2) == ISSI_ID;
}
// For GD25Q32, GD25Q64, GD25Q127C, GD25Q128, which use single command to read/write different SR.
FORCE_INLINE_ATTR bool is_gd_q_chip(const esp_rom_spiflash_chip_t* chip)
{
return BYTESHIFT(chip->device_id, 2) == GD_Q_ID_HIGH && BYTESHIFT(chip->device_id, 1) == GD_Q_ID_MID && BYTESHIFT(chip->device_id, 0) >= GD_Q_ID_LOW;
}
FORCE_INLINE_ATTR bool is_mxic_chip(const esp_rom_spiflash_chip_t* chip)
{
return BYTESHIFT(chip->device_id, 2) == MXIC_ID;
}
esp_err_t IRAM_ATTR __attribute__((weak)) bootloader_flash_unlock(void)
{
// At the beginning status == new_status == status_sr2 == new_status_sr2 == 0.
// If the register doesn't need to be updated, keep them the same (0), so that no command will be actually sent.
uint16_t status = 0; // status for SR1 or SR1+SR2 if writing SR with 01H + 2Bytes.
uint16_t new_status = 0;
uint8_t status_sr2 = 0; // status_sr2 for SR2.
uint8_t new_status_sr2 = 0;
uint8_t sr1_bit_num = 0;
esp_err_t err = ESP_OK;
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
if (is_issi_chip(&g_rom_flashchip) || is_mxic_chip(&g_rom_flashchip)) {
// Currently ISSI & MXIC share the same command and register layout, which is different from the default model.
// If any code here needs to be modified, check both chips.
status = bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8);
/* Clear all bits in the mask.
(This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.)
*/
sr1_bit_num = 8;
new_status = status & (~ESP_BOOTLOADER_SPIFLASH_BP_MASK_ISSI);
} else if (is_gd_q_chip(&g_rom_flashchip)) {
/* The GD chips behaviour is to clear all bits in SR1 and clear bits in SR2 except QE bit.
Use 01H to write SR1 and 31H to write SR2.
*/
status = bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8);
sr1_bit_num = 8;
new_status = 0;
status_sr2 = bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8);
new_status_sr2 = status_sr2 & ESP_BOOTLOADER_SPIFLASH_QE_GD_SR2;
} else {
/* For common behaviour, like XMC chips, Use 01H+2Bytes to write both SR1 and SR2*/
status = bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8) | (bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8) << 8);
/* Clear all bits except QE, if it is set.
(This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.)
*/
sr1_bit_num = 16;
new_status = status & ESP_BOOTLOADER_SPIFLASH_QE_SR1_2BYTE;
}
// When SR is written, set to true to indicate that WRDI need to be sent to ensure the protection is ON before return.
bool status_written = false;
// Skip if nothing needs to be changed. Meaningless writing to SR increases the risk during write and wastes time.
if (status != new_status) {
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
bootloader_execute_flash_command(CMD_WREN, 0, 0, 0);
bootloader_execute_flash_command(CMD_WRSR, new_status, sr1_bit_num, 0);
status_written = true;
}
if (status_sr2 != new_status_sr2) {
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
bootloader_execute_flash_command(CMD_WREN, 0, 0, 0);
bootloader_execute_flash_command(CMD_WRSR2, new_status_sr2, 8, 0);
status_written = true;
}
if (status_written) {
//Call esp_rom_spiflash_wait_idle to make sure previous WRSR is completed.
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0);
}
return err;
}
/* dummy_len_plus values defined in ROM for SPI flash configuration */
extern uint8_t g_rom_spiflash_dummy_len_plus[];
IRAM_ATTR static uint32_t bootloader_flash_execute_command_common(
uint8_t command,
uint32_t addr_len, uint32_t address,
uint8_t dummy_len,
uint8_t mosi_len, uint32_t mosi_data,
uint8_t miso_len)
{
assert(mosi_len <= 32);
assert(miso_len <= 32);
uint32_t old_ctrl_reg = SPIFLASH.ctrl.val;
uint32_t old_user_reg = SPIFLASH.user.val;
uint32_t old_user1_reg = SPIFLASH.user1.val;
#if CONFIG_IDF_TARGET_ESP32
SPIFLASH.ctrl.val = SPI_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
#else
SPIFLASH.ctrl.val = SPI_MEM_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
#endif
//command phase
SPIFLASH.user.usr_command = 1;
SPIFLASH.user2.usr_command_bitlen = 7;
SPIFLASH.user2.usr_command_value = command;
//addr phase
SPIFLASH.user.usr_addr = addr_len > 0;
SPIFLASH.user1.usr_addr_bitlen = addr_len - 1;
#if CONFIG_IDF_TARGET_ESP32
SPIFLASH.addr = (addr_len > 0)? (address << (32-addr_len)) : 0;
#else
SPIFLASH.addr = address;
#endif
//dummy phase
if (miso_len > 0) {
uint32_t total_dummy = dummy_len + g_rom_spiflash_dummy_len_plus[1];
SPIFLASH.user.usr_dummy = total_dummy > 0;
SPIFLASH.user1.usr_dummy_cyclelen = total_dummy - 1;
} else {
SPIFLASH.user.usr_dummy = 0;
SPIFLASH.user1.usr_dummy_cyclelen = 0;
}
//output data
SPIFLASH.user.usr_mosi = mosi_len > 0;
#if CONFIG_IDF_TARGET_ESP32
SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0;
#else
SPIFLASH.mosi_dlen.usr_mosi_bit_len = mosi_len ? (mosi_len - 1) : 0;
#endif
SPIFLASH.data_buf[0] = mosi_data;
//input data
SPIFLASH.user.usr_miso = miso_len > 0;
#if CONFIG_IDF_TARGET_ESP32
SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0;
#else
SPIFLASH.miso_dlen.usr_miso_bit_len = miso_len ? (miso_len - 1) : 0;
#endif
SPIFLASH.cmd.usr = 1;
while (SPIFLASH.cmd.usr != 0) {
}
SPIFLASH.ctrl.val = old_ctrl_reg;
SPIFLASH.user.val = old_user_reg;
SPIFLASH.user1.val = old_user1_reg;
uint32_t ret = SPIFLASH.data_buf[0];
if (miso_len < 32) {
//set unused bits to 0
ret &= ~(UINT32_MAX << miso_len);
}
return ret;
}
uint32_t IRAM_ATTR bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len)
{
const uint8_t addr_len = 0;
const uint8_t address = 0;
const uint8_t dummy_len = 0;
return bootloader_flash_execute_command_common(command, addr_len, address,
dummy_len, mosi_len, mosi_data, miso_len);
}
// cmd(0x5A) + 24bit address + 8 cycles dummy
uint32_t IRAM_ATTR bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num)
{
assert(miso_byte_num <= 4);
const uint8_t command = CMD_RDSFDP;
const uint8_t addr_len = 24;
const uint8_t dummy_len = 8;
const uint8_t mosi_len = 0;
const uint32_t mosi_data = 0;
const uint8_t miso_len = miso_byte_num * 8;
return bootloader_flash_execute_command_common(command, addr_len, sfdp_addr,
dummy_len, mosi_len, mosi_data, miso_len);
}
void bootloader_enable_wp(void)
{
bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */
}
uint32_t IRAM_ATTR bootloader_read_flash_id(void)
{
uint32_t id = bootloader_execute_flash_command(CMD_RDID, 0, 0, 24);
id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00);
return id;
}
#if SOC_CACHE_SUPPORT_WRAP
esp_err_t bootloader_flash_wrap_set(spi_flash_wrap_mode_t mode)
{
uint32_t reg_bkp_ctrl = SPIFLASH.ctrl.val;
uint32_t reg_bkp_usr = SPIFLASH.user.val;
SPIFLASH.user.fwrite_dio = 0;
SPIFLASH.user.fwrite_dual = 0;
SPIFLASH.user.fwrite_qio = 1;
SPIFLASH.user.fwrite_quad = 0;
SPIFLASH.ctrl.fcmd_dual = 0;
SPIFLASH.ctrl.fcmd_quad = 0;
SPIFLASH.user.usr_dummy = 0;
SPIFLASH.user.usr_addr = 1;
SPIFLASH.user.usr_command = 1;
SPIFLASH.user2.usr_command_bitlen = 7;
SPIFLASH.user2.usr_command_value = CMD_WRAP;
SPIFLASH.user1.usr_addr_bitlen = 23;
SPIFLASH.addr = 0;
SPIFLASH.user.usr_miso = 0;
SPIFLASH.user.usr_mosi = 1;
SPIFLASH.mosi_dlen.usr_mosi_bit_len = 7;
SPIFLASH.data_buf[0] = (uint32_t) mode << 4;;
SPIFLASH.cmd.usr = 1;
while(SPIFLASH.cmd.usr != 0)
{ }
SPIFLASH.ctrl.val = reg_bkp_ctrl;
SPIFLASH.user.val = reg_bkp_usr;
return ESP_OK;
}
#endif //SOC_CACHE_SUPPORT_WRAP
/*******************************************************************************
* XMC startup flow
******************************************************************************/
#define XMC_SUPPORT CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT
#define XMC_VENDOR_ID 0x20
#if BOOTLOADER_BUILD
#define BOOTLOADER_FLASH_LOG(level, ...) ESP_LOG##level(TAG, ##__VA_ARGS__)
#else
static DRAM_ATTR char bootloader_flash_tag[] = "bootloader_flash";
#define BOOTLOADER_FLASH_LOG(level, ...) ESP_DRAM_LOG##level(bootloader_flash_tag, ##__VA_ARGS__)
#endif
#if XMC_SUPPORT
//strictly check the model
static IRAM_ATTR bool is_xmc_chip_strict(uint32_t rdid)
{
uint32_t vendor_id = BYTESHIFT(rdid, 2);
uint32_t mfid = BYTESHIFT(rdid, 1);
uint32_t cpid = BYTESHIFT(rdid, 0);
if (vendor_id != XMC_VENDOR_ID) {
return false;
}
bool matched = false;
if (mfid == 0x40) {
if (cpid >= 0x13 && cpid <= 0x20) {
matched = true;
}
} else if (mfid == 0x41) {
if (cpid >= 0x17 && cpid <= 0x20) {
matched = true;
}
} else if (mfid == 0x50) {
if (cpid >= 0x15 && cpid <= 0x16) {
matched = true;
}
}
return matched;
}
esp_err_t IRAM_ATTR bootloader_flash_xmc_startup(void)
{
// If the RDID value is a valid XMC one, may skip the flow
const bool fast_check = true;
if (fast_check && is_xmc_chip_strict(g_rom_flashchip.device_id)) {
BOOTLOADER_FLASH_LOG(D, "XMC chip detected by RDID (%08X), skip.", g_rom_flashchip.device_id);
return ESP_OK;
}
// Check the Manufacturer ID in SFDP registers (JEDEC standard). If not XMC chip, no need to run the flow
const int sfdp_mfid_addr = 0x10;
uint8_t mf_id = (bootloader_flash_read_sfdp(sfdp_mfid_addr, 1) & 0xff);
if (mf_id != XMC_VENDOR_ID) {
BOOTLOADER_FLASH_LOG(D, "non-XMC chip detected by SFDP Read (%02X), skip.", mf_id);
return ESP_OK;
}
BOOTLOADER_FLASH_LOG(I, "XM25QHxxC startup flow");
// Enter DPD
bootloader_execute_flash_command(0xB9, 0, 0, 0);
// Enter UDPD
bootloader_execute_flash_command(0x79, 0, 0, 0);
// Exit UDPD
bootloader_execute_flash_command(0xFF, 0, 0, 0);
// Delay tXUDPD
ets_delay_us(2000);
// Release Power-down
bootloader_execute_flash_command(0xAB, 0, 0, 0);
ets_delay_us(20);
// Read flash ID and check again
g_rom_flashchip.device_id = bootloader_read_flash_id();
if (!is_xmc_chip_strict(g_rom_flashchip.device_id)) {
BOOTLOADER_FLASH_LOG(E, "XMC flash startup fail");
return ESP_FAIL;
}
return ESP_OK;
}
#else
//only compare the vendor id
static IRAM_ATTR bool is_xmc_chip(uint32_t rdid)
{
uint32_t vendor_id = (rdid >> 16) & 0xFF;
return (vendor_id == XMC_VENDOR_ID);
}
esp_err_t IRAM_ATTR bootloader_flash_xmc_startup(void)
{
if (is_xmc_chip(g_rom_flashchip.device_id)) {
BOOTLOADER_FLASH_LOG(E, "XMC chip detected (%08X) while support disabled.", g_rom_flashchip.device_id);
return ESP_FAIL;
}
return ESP_OK;
}
#endif //XMC_SUPPORT

View File

@@ -17,7 +17,7 @@
#include "esp_attr.h"
#include "esp_log.h"
#include "bootloader_init.h"
#include "bootloader_flash.h"
#include "bootloader_flash_priv.h"
#include "bootloader_flash_config.h"
#include "bootloader_random.h"
#include "bootloader_clock.h"

View File

@@ -59,7 +59,7 @@
#include "esp_secure_boot.h"
#include "esp_flash_encrypt.h"
#include "esp_flash_partitions.h"
#include "bootloader_flash.h"
#include "bootloader_flash_priv.h"
#include "bootloader_random.h"
#include "bootloader_config.h"
#include "bootloader_common.h"

View File

@@ -23,6 +23,7 @@
#include "bootloader_common.h"
#include "bootloader_flash_config.h"
#include "bootloader_mem.h"
#include "bootloader_flash_priv.h"
#include "soc/cpu.h"
#include "soc/dport_reg.h"
@@ -259,7 +260,7 @@ static esp_err_t bootloader_init_spi_flash(void)
}
#endif
esp_rom_spiflash_unlock();
bootloader_flash_unlock();
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
bootloader_enable_qio_mode();
@@ -267,6 +268,8 @@ static esp_err_t bootloader_init_spi_flash(void)
print_flash_info(&bootloader_image_hdr);
update_flash_config(&bootloader_image_hdr);
//ensure the flash is write-protected
bootloader_enable_wp();
return ESP_OK;
}
@@ -305,11 +308,13 @@ static void bootloader_init_uart_console(void)
const uint32_t tx_idx = tx_idx_list[uart_num];
const uint32_t rx_idx = rx_idx_list[uart_num];
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[uart_rx_gpio], PIN_FUNC_GPIO);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[uart_rx_gpio]);
gpio_pad_pullup(uart_rx_gpio);
gpio_matrix_out(uart_tx_gpio, tx_idx, 0, 0);
gpio_matrix_in(uart_rx_gpio, rx_idx, 0);
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[uart_tx_gpio], PIN_FUNC_GPIO);
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
@@ -450,6 +455,11 @@ esp_err_t bootloader_init(void)
bootloader_print_banner();
// update flash ID
bootloader_flash_update_id();
// Check and run XMC startup flow
if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) {
ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!");
goto err;
}
// read bootloader header
if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
goto err;

View File

@@ -14,7 +14,7 @@
#include <strings.h>
#include "bootloader_flash.h"
#include "bootloader_flash_priv.h"
#include "esp_image_format.h"
#include "esp_flash_encrypt.h"
#include "esp_flash_partitions.h"

View File

@@ -29,7 +29,7 @@
#include "sdkconfig.h"
#include "bootloader_flash.h"
#include "bootloader_flash_priv.h"
#include "bootloader_random.h"
#include "esp_image_format.h"
#include "esp_secure_boot.h"

View File

@@ -13,7 +13,7 @@
// limitations under the License.
#include "sdkconfig.h"
#include "bootloader_flash.h"
#include "bootloader_flash_priv.h"
#include "bootloader_sha.h"
#include "bootloader_utility.h"
#include "esp_log.h"

View File

@@ -26,6 +26,7 @@
#include "bootloader_clock.h"
#include "bootloader_flash_config.h"
#include "bootloader_mem.h"
#include "bootloader_flash_priv.h"
#include "esp32s2/rom/cache.h"
#include "esp32s2/rom/ets_sys.h"
@@ -205,7 +206,7 @@ static esp_err_t bootloader_init_spi_flash(void)
}
#endif
esp_rom_spiflash_unlock();
bootloader_flash_unlock();
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
bootloader_enable_qio_mode();
@@ -213,6 +214,8 @@ static esp_err_t bootloader_init_spi_flash(void)
print_flash_info(&bootloader_image_hdr);
update_flash_config(&bootloader_image_hdr);
//ensure the flash is write-protected
bootloader_enable_wp();
return ESP_OK;
}
@@ -251,11 +254,13 @@ static void bootloader_init_uart_console(void)
const uint32_t tx_idx = tx_idx_list[uart_num];
const uint32_t rx_idx = rx_idx_list[uart_num];
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[uart_rx_gpio], PIN_FUNC_GPIO);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[uart_rx_gpio]);
gpio_pad_pullup(uart_rx_gpio);
gpio_matrix_out(uart_tx_gpio, tx_idx, 0, 0);
gpio_matrix_in(uart_rx_gpio, rx_idx, 0);
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[uart_tx_gpio], PIN_FUNC_GPIO);
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
@@ -372,6 +377,11 @@ esp_err_t bootloader_init(void)
bootloader_print_banner();
// update flash ID
bootloader_flash_update_id();
// Check and run XMC startup flow
if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) {
ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!");
goto err;
}
// read bootloader header
if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
goto err;

View File

@@ -14,7 +14,7 @@
#include <strings.h>
#include "bootloader_flash.h"
#include "bootloader_flash_priv.h"
#include "bootloader_random.h"
#include "bootloader_utility.h"
#include "esp_image_format.h"
@@ -303,8 +303,8 @@ static esp_err_t encrypt_bootloader(void)
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to encrypt bootloader in place: 0x%x", err);
return err;
}
}
ESP_LOGI(TAG, "bootloader encrypted successfully");
return err;
}

View File

@@ -17,7 +17,7 @@
#include "esp_secure_boot.h"
#include "soc/efuse_reg.h"
#include "bootloader_flash.h"
#include "bootloader_flash_priv.h"
#include "bootloader_sha.h"
#include "bootloader_utility.h"

View File

@@ -15,7 +15,7 @@
#include <string.h>
#include "esp_fault.h"
#include "bootloader_flash.h"
#include "bootloader_flash_priv.h"
#include "bootloader_sha.h"
#include "bootloader_utility.h"
#include "esp_log.h"

View File

@@ -20,7 +20,7 @@
#include <esp_log.h>
#include <esp_attr.h>
#include <esp_spi_flash.h>
#include <bootloader_flash.h>
#include <bootloader_flash_priv.h>
#include <bootloader_random.h>
#include <bootloader_sha.h>
#include "bootloader_util.h"

View File

@@ -15,6 +15,7 @@
#include <stdint.h>
#include "bootloader_flash_config.h"
#include "flash_qio_mode.h"
#include "bootloader_flash_priv.h"
#include "esp_log.h"
#include "esp_err.h"
#if CONFIG_IDF_TARGET_ESP32
@@ -25,30 +26,10 @@
#include "esp32s2/rom/efuse.h"
#include "soc/spi_mem_struct.h"
#endif
#include "soc/spi_struct.h"
#include "soc/spi_reg.h"
#include "soc/efuse_periph.h"
#include "soc/io_mux_reg.h"
#include "sdkconfig.h"
/* SPI flash controller */
#if CONFIG_IDF_TARGET_ESP32
#define SPIFLASH SPI1
#elif CONFIG_IDF_TARGET_ESP32S2
#define SPIFLASH SPIMEM1
#endif
/* SPI commands (actual on-wire commands not SPI controller bitmasks)
Suitable for use with the execute_flash_command static function.
*/
#define CMD_RDID 0x9F
#define CMD_WRSR 0x01
#define CMD_WRSR2 0x31 /* Not all SPI flash uses this command */
#define CMD_WREN 0x06
#define CMD_WRDI 0x04
#define CMD_RDSR 0x05
#define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */
#define CMD_OTPEN 0x3A /* Enable OTP mode, not all SPI flash uses this command */
static const char *TAG = "qio_mode";
@@ -126,56 +107,6 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
The command passed here is always the on-the-wire command given to the SPI flash unit.
*/
static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len);
/* dummy_len_plus values defined in ROM for SPI flash configuration */
extern uint8_t g_rom_spiflash_dummy_len_plus[];
uint32_t bootloader_read_flash_id(void)
{
uint32_t id = execute_flash_command(CMD_RDID, 0, 0, 24);
id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00);
return id;
}
#if CONFIG_IDF_TARGET_ESP32S2
#define FLASH_WRAP_CMD 0x77
typedef enum {
FLASH_WRAP_MODE_8B = 0,
FLASH_WRAP_MODE_16B = 2,
FLASH_WRAP_MODE_32B = 4,
FLASH_WRAP_MODE_64B = 6,
FLASH_WRAP_MODE_DISABLE = 1
} spi_flash_wrap_mode_t;
static esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode)
{
uint32_t reg_bkp_ctrl = SPIFLASH.ctrl.val;
uint32_t reg_bkp_usr = SPIFLASH.user.val;
SPIFLASH.user.fwrite_dio = 0;
SPIFLASH.user.fwrite_dual = 0;
SPIFLASH.user.fwrite_qio = 1;
SPIFLASH.user.fwrite_quad = 0;
SPIFLASH.ctrl.fcmd_dual = 0;
SPIFLASH.ctrl.fcmd_quad = 0;
SPIFLASH.user.usr_dummy = 0;
SPIFLASH.user.usr_addr = 1;
SPIFLASH.user.usr_command = 1;
SPIFLASH.user2.usr_command_bitlen = 7;
SPIFLASH.user2.usr_command_value = FLASH_WRAP_CMD;
SPIFLASH.user1.usr_addr_bitlen = 23;
SPIFLASH.addr = 0;
SPIFLASH.user.usr_miso = 0;
SPIFLASH.user.usr_mosi = 1;
SPIFLASH.mosi_dlen.usr_mosi_bit_len = 7;
SPIFLASH.data_buf[0] = (uint32_t) mode << 4;;
SPIFLASH.cmd.usr = 1;
while (SPIFLASH.cmd.usr != 0) {
}
SPIFLASH.ctrl.val = reg_bkp_ctrl;
SPIFLASH.user.val = reg_bkp_usr;
return ESP_OK;
}
#endif
void bootloader_enable_qio_mode(void)
{
@@ -208,8 +139,8 @@ void bootloader_enable_qio_mode(void)
enable_qio_mode(chip_data[i].read_status_fn,
chip_data[i].write_status_fn,
chip_data[i].status_qio_bit);
#if CONFIG_IDF_TARGET_ESP32S2
spi_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
#if SOC_CACHE_SUPPORT_WRAP
bootloader_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
#endif
}
@@ -226,7 +157,7 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
ESP_LOGD(TAG, "Initial flash chip status 0x%x", status);
if ((status & (1 << status_qio_bit)) == 0) {
execute_flash_command(CMD_WREN, 0, 0, 0);
bootloader_execute_flash_command(CMD_WREN, 0, 0, 0);
write_status_fn(status | (1 << status_qio_bit));
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
@@ -264,95 +195,48 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
static unsigned read_status_8b_rdsr(void)
{
return execute_flash_command(CMD_RDSR, 0, 0, 8);
return bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8);
}
static unsigned read_status_8b_rdsr2(void)
{
return execute_flash_command(CMD_RDSR2, 0, 0, 8);
return bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8);
}
static unsigned read_status_16b_rdsr_rdsr2(void)
{
return execute_flash_command(CMD_RDSR, 0, 0, 8) | (execute_flash_command(CMD_RDSR2, 0, 0, 8) << 8);
return bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8) | (bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8) << 8);
}
static void write_status_8b_wrsr(unsigned new_status)
{
execute_flash_command(CMD_WRSR, new_status, 8, 0);
bootloader_execute_flash_command(CMD_WRSR, new_status, 8, 0);
}
static void write_status_8b_wrsr2(unsigned new_status)
{
execute_flash_command(CMD_WRSR2, new_status, 8, 0);
bootloader_execute_flash_command(CMD_WRSR2, new_status, 8, 0);
}
static void write_status_16b_wrsr(unsigned new_status)
{
execute_flash_command(CMD_WRSR, new_status, 16, 0);
bootloader_execute_flash_command(CMD_WRSR, new_status, 16, 0);
}
static unsigned read_status_8b_xmc25qu64a(void)
{
execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */
bootloader_execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
uint32_t read_status = execute_flash_command(CMD_RDSR, 0, 0, 8);
execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */
uint32_t read_status = bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8);
bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */
return read_status;
}
static void write_status_8b_xmc25qu64a(unsigned new_status)
{
execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */
bootloader_execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
execute_flash_command(CMD_WRSR, new_status, 8, 0);
bootloader_execute_flash_command(CMD_WRSR, new_status, 8, 0);
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */
}
static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len)
{
uint32_t old_ctrl_reg = SPIFLASH.ctrl.val;
#if CONFIG_IDF_TARGET_ESP32
SPIFLASH.ctrl.val = SPI_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
#elif CONFIG_IDF_TARGET_ESP32S2
SPIFLASH.ctrl.val = SPI_MEM_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
#endif
SPIFLASH.user.usr_dummy = 0;
SPIFLASH.user.usr_addr = 0;
SPIFLASH.user.usr_command = 1;
SPIFLASH.user2.usr_command_bitlen = 7;
SPIFLASH.user2.usr_command_value = command;
SPIFLASH.user.usr_miso = miso_len > 0;
#if CONFIG_IDF_TARGET_ESP32
SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0;
#elif CONFIG_IDF_TARGET_ESP32S2
SPIFLASH.miso_dlen.usr_miso_bit_len = miso_len ? (miso_len - 1) : 0;
#endif
SPIFLASH.user.usr_mosi = mosi_len > 0;
#if CONFIG_IDF_TARGET_ESP32
SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0;
#elif CONFIG_IDF_TARGET_ESP32S2
SPIFLASH.mosi_dlen.usr_mosi_bit_len = mosi_len ? (mosi_len - 1) : 0;
#endif
SPIFLASH.data_buf[0] = mosi_data;
if (g_rom_spiflash_dummy_len_plus[1]) {
/* When flash pins are mapped via GPIO matrix, need a dummy cycle before reading via MISO */
if (miso_len > 0) {
SPIFLASH.user.usr_dummy = 1;
SPIFLASH.user1.usr_dummy_cyclelen = g_rom_spiflash_dummy_len_plus[1] - 1;
} else {
SPIFLASH.user.usr_dummy = 0;
SPIFLASH.user1.usr_dummy_cyclelen = 0;
}
}
SPIFLASH.cmd.usr = 1;
while (SPIFLASH.cmd.usr != 0) {
}
SPIFLASH.ctrl.val = old_ctrl_reg;
return SPIFLASH.data_buf[0];
bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */
}

View File

@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "bootloader_sha.h"
#include "bootloader_flash.h"
#include "bootloader_flash_priv.h"
#include <stdbool.h>
#include <string.h>
#include <assert.h>

View File

@@ -13,7 +13,7 @@
// limitations under the License.
#include "sdkconfig.h"
#include "bootloader_flash.h"
#include "bootloader_flash_priv.h"
#include "bootloader_sha.h"
#include "bootloader_utility.h"
#include "esp_log.h"
@@ -325,7 +325,7 @@ esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signa
break;
}
}
free(sig_be);
free(buf);
#if CONFIG_IDF_TARGET_ESP32

View File

@@ -365,7 +365,7 @@ menu "Bluetooth"
int "Maximum number of devices in scan duplicate filter"
depends on BTDM_BLE_SCAN_DUPL
range 10 1000
default 200
default 100
help
Maximum number of devices which can be recorded in scan duplicate filter.
When the maximum amount of device in the filter is reached, the cache will be refreshed.
@@ -381,7 +381,7 @@ menu "Bluetooth"
int "Maximum number of Mesh adv packets in scan duplicate filter"
depends on BTDM_BLE_MESH_SCAN_DUPL_EN
range 10 1000
default 200
default 100
help
Maximum number of adv packets which can be recorded in duplicate scan cache for BLE Mesh.
When the maximum amount of device in the filter is reached, the cache will be refreshed.

View File

@@ -42,6 +42,12 @@
#define BTC_DYNAMIC_MEMORY FALSE
#endif
#if UC_BT_BLUEDROID_MEM_DEBUG
#define HEAP_MEMORY_DEBUG TRUE
#else
#define HEAP_MEMORY_DEBUG FALSE
#endif
#ifndef BT_BLE_DYNAMIC_ENV_MEMORY
#define BT_BLE_DYNAMIC_ENV_MEMORY FALSE
#endif

View File

@@ -80,4 +80,11 @@
#define UC_BT_LOG_OSI_TRACE_LEVEL UC_TRACE_LEVEL_WARNING
#endif
//MEMORY DEBUG
#ifdef CONFIG_BT_BLUEDROID_MEM_DEBUG
#define UC_BT_BLUEDROID_MEM_DEBUG TRUE
#else
#define UC_BT_BLUEDROID_MEM_DEBUG FALSE
#endif
#endif /* __BT_USER_CONFIG_H__ */

View File

@@ -37,6 +37,7 @@
#include "esp_err.h"
#include "esp_log.h"
#include "esp_pm.h"
#include "esp_timer.h"
#include "driver/periph_ctrl.h"
#include "soc/rtc.h"
#include "soc/soc_memory_layout.h"
@@ -93,11 +94,6 @@ do{\
#define OSI_VERSION 0x00010003
#define OSI_MAGIC_VALUE 0xFADEBEAD
/* SPIRAM Configuration */
#if CONFIG_SPIRAM_USE_MALLOC
#define BTDM_MAX_QUEUE_NUM (5)
#endif
/* Types definition
************************************************************************
*/
@@ -115,14 +111,10 @@ typedef struct {
intptr_t end;
} btdm_dram_available_region_t;
/* PSRAM configuration */
#if CONFIG_SPIRAM_USE_MALLOC
typedef struct {
QueueHandle_t handle;
void *handle;
void *storage;
void *buffer;
} btdm_queue_item_t;
#endif
/* OSI function */
struct osi_funcs_t {
@@ -268,10 +260,6 @@ extern uint32_t _btdm_data_end;
/* Local Function Declare
*********************************************************************
*/
#if CONFIG_SPIRAM_USE_MALLOC
static bool btdm_queue_generic_register(const btdm_queue_item_t *queue);
static bool btdm_queue_generic_deregister(btdm_queue_item_t *queue);
#endif /* CONFIG_SPIRAM_USE_MALLOC */
static void IRAM_ATTR interrupt_disable(void);
static void IRAM_ATTR interrupt_restore(void);
static void IRAM_ATTR task_yield(void);
@@ -414,11 +402,6 @@ SOC_RESERVE_MEMORY_REGION(SOC_MEM_BT_DATA_START, SOC_MEM_BT_DATA_END,
static DRAM_ATTR struct osi_funcs_t *osi_funcs_p;
#if CONFIG_SPIRAM_USE_MALLOC
static DRAM_ATTR btdm_queue_item_t btdm_queue_table[BTDM_MAX_QUEUE_NUM];
static DRAM_ATTR SemaphoreHandle_t btdm_queue_table_mux = NULL;
#endif /* #if CONFIG_SPIRAM_USE_MALLOC */
/* Static variable declare */
// timestamp when PHY/RF was switched on
static DRAM_ATTR int64_t s_time_phy_rf_just_enabled = 0;
@@ -458,52 +441,6 @@ static inline void btdm_check_and_init_bb(void)
}
}
#if CONFIG_SPIRAM_USE_MALLOC
static bool btdm_queue_generic_register(const btdm_queue_item_t *queue)
{
if (!btdm_queue_table_mux || !queue) {
return NULL;
}
bool ret = false;
btdm_queue_item_t *item;
xSemaphoreTake(btdm_queue_table_mux, portMAX_DELAY);
for (int i = 0; i < BTDM_MAX_QUEUE_NUM; ++i) {
item = &btdm_queue_table[i];
if (item->handle == NULL) {
memcpy(item, queue, sizeof(btdm_queue_item_t));
ret = true;
break;
}
}
xSemaphoreGive(btdm_queue_table_mux);
return ret;
}
static bool btdm_queue_generic_deregister(btdm_queue_item_t *queue)
{
if (!btdm_queue_table_mux || !queue) {
return false;
}
bool ret = false;
btdm_queue_item_t *item;
xSemaphoreTake(btdm_queue_table_mux, portMAX_DELAY);
for (int i = 0; i < BTDM_MAX_QUEUE_NUM; ++i) {
item = &btdm_queue_table[i];
if (item->handle == queue->handle) {
memcpy(queue, item, sizeof(btdm_queue_item_t));
memset(item, 0, sizeof(btdm_queue_item_t));
ret = true;
break;
}
}
xSemaphoreGive(btdm_queue_table_mux);
return ret;
}
#endif /* CONFIG_SPIRAM_USE_MALLOC */
static void IRAM_ATTR interrupt_disable(void)
{
if (xPortInIsrContext()) {
@@ -534,148 +471,74 @@ static void IRAM_ATTR task_yield_from_isr(void)
static void *semphr_create_wrapper(uint32_t max, uint32_t init)
{
btdm_queue_item_t *semphr = heap_caps_calloc(1, sizeof(btdm_queue_item_t), MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
assert(semphr);
#if !CONFIG_SPIRAM_USE_MALLOC
return (void *)xSemaphoreCreateCounting(max, init);
semphr->handle = (void *)xSemaphoreCreateCounting(max, init);
#else
StaticQueue_t *queue_buffer = NULL;
QueueHandle_t handle = NULL;
queue_buffer = heap_caps_malloc(sizeof(StaticQueue_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
if (!queue_buffer) {
goto error;
}
semphr->storage = heap_caps_malloc(sizeof(StaticQueue_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
assert(semphr->storage);
handle = xSemaphoreCreateCountingStatic(max, init, queue_buffer);
if (!handle) {
goto error;
}
btdm_queue_item_t item = {
.handle = handle,
.storage = NULL,
.buffer = queue_buffer,
};
if (!btdm_queue_generic_register(&item)) {
goto error;
}
return handle;
error:
if (handle) {
vSemaphoreDelete(handle);
}
if (queue_buffer) {
free(queue_buffer);
}
return NULL;
semphr->handle = (void *)xSemaphoreCreateCountingStatic(max, init, semphr->storage);
#endif
assert(semphr->handle);
return semphr;
}
static void semphr_delete_wrapper(void *semphr)
{
#if !CONFIG_SPIRAM_USE_MALLOC
vSemaphoreDelete(semphr);
#else
btdm_queue_item_t item = {
.handle = semphr,
.storage = NULL,
.buffer = NULL,
};
if (btdm_queue_generic_deregister(&item)) {
vSemaphoreDelete(item.handle);
free(item.buffer);
if (semphr == NULL) {
return;
}
return;
btdm_queue_item_t *semphr_item = (btdm_queue_item_t *)semphr;
if (semphr_item->handle) {
vSemaphoreDelete(semphr_item->handle);
}
#ifdef CONFIG_SPIRAM_USE_MALLOC
if (semphr_item->storage) {
free(semphr_item->storage);
}
#endif
free(semphr);
}
static int32_t IRAM_ATTR semphr_take_from_isr_wrapper(void *semphr, void *hptw)
{
return (int32_t)xSemaphoreTakeFromISR(semphr, hptw);
return (int32_t)xSemaphoreTakeFromISR(((btdm_queue_item_t *)semphr)->handle, hptw);
}
static int32_t IRAM_ATTR semphr_give_from_isr_wrapper(void *semphr, void *hptw)
{
return (int32_t)xSemaphoreGiveFromISR(semphr, hptw);
return (int32_t)xSemaphoreGiveFromISR(((btdm_queue_item_t *)semphr)->handle, hptw);
}
static int32_t semphr_take_wrapper(void *semphr, uint32_t block_time_ms)
{
if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) {
return (int32_t)xSemaphoreTake(semphr, portMAX_DELAY);
return (int32_t)xSemaphoreTake(((btdm_queue_item_t *)semphr)->handle, portMAX_DELAY);
} else {
return (int32_t)xSemaphoreTake(semphr, block_time_ms / portTICK_PERIOD_MS);
return (int32_t)xSemaphoreTake(((btdm_queue_item_t *)semphr)->handle, block_time_ms / portTICK_PERIOD_MS);
}
}
static int32_t semphr_give_wrapper(void *semphr)
{
return (int32_t)xSemaphoreGive(semphr);
return (int32_t)xSemaphoreGive(((btdm_queue_item_t *)semphr)->handle);
}
static void *mutex_create_wrapper(void)
{
#if CONFIG_SPIRAM_USE_MALLOC
StaticQueue_t *queue_buffer = NULL;
QueueHandle_t handle = NULL;
queue_buffer = heap_caps_malloc(sizeof(StaticQueue_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
if (!queue_buffer) {
goto error;
}
handle = xSemaphoreCreateMutexStatic(queue_buffer);
if (!handle) {
goto error;
}
btdm_queue_item_t item = {
.handle = handle,
.storage = NULL,
.buffer = queue_buffer,
};
if (!btdm_queue_generic_register(&item)) {
goto error;
}
return handle;
error:
if (handle) {
vSemaphoreDelete(handle);
}
if (queue_buffer) {
free(queue_buffer);
}
return NULL;
#else
return (void *)xSemaphoreCreateMutex();
#endif
}
static void mutex_delete_wrapper(void *mutex)
{
#if !CONFIG_SPIRAM_USE_MALLOC
vSemaphoreDelete(mutex);
#else
btdm_queue_item_t item = {
.handle = mutex,
.storage = NULL,
.buffer = NULL,
};
if (btdm_queue_generic_deregister(&item)) {
vSemaphoreDelete(item.handle);
free(item.buffer);
}
return;
#endif
}
static int32_t mutex_lock_wrapper(void *mutex)
@@ -690,102 +553,71 @@ static int32_t mutex_unlock_wrapper(void *mutex)
static void *queue_create_wrapper(uint32_t queue_len, uint32_t item_size)
{
btdm_queue_item_t *queue = NULL;
queue = (btdm_queue_item_t*)heap_caps_malloc(sizeof(btdm_queue_item_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
assert(queue);
#if CONFIG_SPIRAM_USE_MALLOC
StaticQueue_t *queue_buffer = NULL;
uint8_t *queue_storage = NULL;
QueueHandle_t handle = NULL;
queue_buffer = heap_caps_malloc(sizeof(StaticQueue_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
if (!queue_buffer) {
goto error;
}
queue->storage = heap_caps_calloc(1, sizeof(StaticQueue_t) + (queue_len*item_size), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
assert(queue->storage);
queue_storage = heap_caps_malloc((queue_len*item_size), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
if (!queue_storage ) {
goto error;
}
queue->handle = xQueueCreateStatic( queue_len, item_size, ((uint8_t*)(queue->storage)) + sizeof(StaticQueue_t), (StaticQueue_t*)(queue->storage));
assert(queue->handle);
handle = xQueueCreateStatic(queue_len, item_size, queue_storage, queue_buffer);
if (!handle) {
goto error;
}
btdm_queue_item_t item = {
.handle = handle,
.storage = queue_storage,
.buffer = queue_buffer,
};
if (!btdm_queue_generic_register(&item)) {
goto error;
}
return handle;
error:
if (handle) {
vQueueDelete(handle);
}
if (queue_storage) {
free(queue_storage);
}
if (queue_buffer) {
free(queue_buffer);
}
return NULL;
#else
return (void *)xQueueCreate(queue_len, item_size);
queue->handle = xQueueCreate( queue_len, item_size);
assert(queue->handle);
#endif
return queue;
}
static void queue_delete_wrapper(void *queue)
{
#if !CONFIG_SPIRAM_USE_MALLOC
vQueueDelete(queue);
#else
btdm_queue_item_t item = {
.handle = queue,
.storage = NULL,
.buffer = NULL,
};
btdm_queue_item_t *queue_item = (btdm_queue_item_t *)queue;
if (queue_item) {
if(queue_item->handle){
vQueueDelete(queue_item->handle);
}
if (btdm_queue_generic_deregister(&item)) {
vQueueDelete(item.handle);
free(item.storage);
free(item.buffer);
}
return;
#if CONFIG_SPIRAM_USE_MALLOC
if (queue_item->storage) {
free(queue_item->storage);
}
#endif
free(queue_item);
}
}
static int32_t queue_send_wrapper(void *queue, void *item, uint32_t block_time_ms)
{
if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) {
return (int32_t)xQueueSend(queue, item, portMAX_DELAY);
return (int32_t)xQueueSend(((btdm_queue_item_t*)queue)->handle, item, portMAX_DELAY);
} else {
return (int32_t)xQueueSend(queue, item, block_time_ms / portTICK_PERIOD_MS);
return (int32_t)xQueueSend(((btdm_queue_item_t*)queue)->handle, item, block_time_ms / portTICK_PERIOD_MS);
}
}
static int32_t IRAM_ATTR queue_send_from_isr_wrapper(void *queue, void *item, void *hptw)
{
return (int32_t)xQueueSendFromISR(queue, item, hptw);
return (int32_t)xQueueSendFromISR(((btdm_queue_item_t*)queue)->handle, item, hptw);
}
static int32_t queue_recv_wrapper(void *queue, void *item, uint32_t block_time_ms)
{
if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) {
return (int32_t)xQueueReceive(queue, item, portMAX_DELAY);
return (int32_t)xQueueReceive(((btdm_queue_item_t*)queue)->handle, item, portMAX_DELAY);
} else {
return (int32_t)xQueueReceive(queue, item, block_time_ms / portTICK_PERIOD_MS);
return (int32_t)xQueueReceive(((btdm_queue_item_t*)queue)->handle, item, block_time_ms / portTICK_PERIOD_MS);
}
}
static int32_t IRAM_ATTR queue_recv_from_isr_wrapper(void *queue, void *item, void *hptw)
{
return (int32_t)xQueueReceiveFromISR(queue, item, hptw);
return (int32_t)xQueueReceiveFromISR(((btdm_queue_item_t*)queue)->handle, item, hptw);
}
static int32_t task_create_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id)
@@ -1377,14 +1209,6 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
ESP_LOGI(BTDM_LOG_TAG, "BT controller compile version [%s]", btdm_controller_get_compile_version());
#if CONFIG_SPIRAM_USE_MALLOC
btdm_queue_table_mux = xSemaphoreCreateMutex();
if (btdm_queue_table_mux == NULL) {
return ESP_ERR_NO_MEM;
}
memset(btdm_queue_table, 0, sizeof(btdm_queue_item_t) * BTDM_MAX_QUEUE_NUM);
#endif
s_wakeup_req_sem = semphr_create_wrapper(1, 0);
if (s_wakeup_req_sem == NULL) {
err = ESP_ERR_NO_MEM;
@@ -1534,12 +1358,6 @@ esp_err_t esp_bt_controller_deinit(void)
semphr_delete_wrapper(s_wakeup_req_sem);
s_wakeup_req_sem = NULL;
#if CONFIG_SPIRAM_USE_MALLOC
vSemaphoreDelete(btdm_queue_table_mux);
btdm_queue_table_mux = NULL;
memset(btdm_queue_table, 0, sizeof(btdm_queue_item_t) * BTDM_MAX_QUEUE_NUM);
#endif
free(osi_funcs_p);
osi_funcs_p = NULL;

View File

@@ -1087,6 +1087,13 @@ if BLE_MESH
lets the state to be changed at any time.
If IV Update test mode is going to be used, this option should be enabled.
config BLE_MESH_DISCARD_OLD_SEQ_AUTH
bool
default y
help
This option is used to decide whether discarding the old SeqAuth when
receiving a segmented message.
menu "BLE Mesh specific test option"
config BLE_MESH_SELF_TEST

View File

@@ -74,6 +74,7 @@
#define START_PAYLOAD_MAX 20
#define CONT_PAYLOAD_MAX 23
#define START_LAST_SEG_MAX 2
#define START_LAST_SEG(gpc) (gpc >> 2)
#define CONT_SEG_INDEX(gpc) (gpc >> 2)
@@ -1563,6 +1564,12 @@ static void gen_prov_start(struct prov_rx *rx, struct net_buf_simple *buf)
return;
}
if (START_LAST_SEG(rx->gpc) > START_LAST_SEG_MAX) {
BT_ERR("Invalid SegN 0x%02x", START_LAST_SEG(rx->gpc));
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
return;
}
if (link.rx.buf->len > link.rx.buf->size) {
BT_ERR("Too large provisioning PDU (%u bytes)",
link.rx.buf->len);

View File

@@ -82,6 +82,7 @@ _Static_assert(BLE_MESH_MAX_CONN >= CONFIG_BLE_MESH_PBG_SAME_TIME,
#define START_PAYLOAD_MAX 20
#define CONT_PAYLOAD_MAX 23
#define START_LAST_SEG_MAX 2
#define START_LAST_SEG(gpc) (gpc >> 2)
#define CONT_SEG_INDEX(gpc) (gpc >> 2)
@@ -2988,6 +2989,12 @@ static void gen_prov_start(const uint8_t idx, struct prov_rx *rx, struct net_buf
return;
}
if (START_LAST_SEG(rx->gpc) > START_LAST_SEG_MAX) {
BT_ERR("Invalid SegN 0x%02x", START_LAST_SEG(rx->gpc));
close_link(idx, CLOSE_REASON_FAILED);
return;
}
if (link[idx].rx.buf->len > link[idx].rx.buf->size) {
BT_ERR("Too large provisioning PDU (%u bytes)",
link[idx].rx.buf->len);

View File

@@ -92,13 +92,7 @@ static struct bt_mesh_proxy_client {
#endif
struct k_delayed_work sar_timer;
struct net_buf_simple buf;
} clients[BLE_MESH_MAX_CONN] = {
[0 ... (BLE_MESH_MAX_CONN - 1)] = {
#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER)
.send_beacons = _K_WORK_INITIALIZER(proxy_send_beacons),
#endif
},
};
} clients[BLE_MESH_MAX_CONN];
static uint8_t client_buf_data[CLIENT_BUF_SIZE * BLE_MESH_MAX_CONN];
@@ -1433,7 +1427,9 @@ int bt_mesh_proxy_server_init(void)
client->buf.size = CLIENT_BUF_SIZE;
client->buf.__buf = client_buf_data + (i * CLIENT_BUF_SIZE);
#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER)
k_work_init(&client->send_beacons, proxy_send_beacons);
#endif
k_delayed_work_init(&client->sar_timer, proxy_sar_timeout);
}

View File

@@ -1396,13 +1396,14 @@ static struct seg_rx *seg_rx_find(struct bt_mesh_net_rx *net_rx,
continue;
}
/* Return newer RX context in addition to an exact match, so
* the calling function can properly discard an old SeqAuth.
* Note: in Zephyr v1.14.0, ">=" is used here which does not
* seem to be a right operation, hence we still use the original
* "==" here.
/* When ">=" is used, return newer RX context in addition to an exact match,
* so the calling function can properly discard an old SeqAuth.
*/
#if CONFIG_BLE_MESH_DISCARD_OLD_SEQ_AUTH
if (rx->seq_auth >= *seq_auth) {
#else
if (rx->seq_auth == *seq_auth) {
#endif
return rx;
}

View File

@@ -13,6 +13,7 @@
#include "btc_gatt_util.h"
#include "stack/l2cdefs.h"
#include "stack/l2c_api.h"
#include "gatt_int.h"
#if (GATTC_INCLUDED == TRUE)
@@ -327,6 +328,12 @@ esp_err_t esp_ble_gattc_read_char (esp_gatt_if_t gattc_if,
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
LOG_WARN("%s, The connection not created.", __func__);
return ESP_ERR_INVALID_STATE;
}
if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) {
LOG_DEBUG("%s, the l2cap chanel is congest.", __func__);
return ESP_FAIL;
@@ -358,6 +365,12 @@ esp_err_t esp_ble_gattc_read_by_type (esp_gatt_if_t gattc_if,
return ESP_GATT_ILLEGAL_PARAMETER;
}
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
LOG_WARN("%s, The connection not created.", __func__);
return ESP_ERR_INVALID_STATE;
}
if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) {
LOG_DEBUG("%s, the l2cap chanel is congest.", __func__);
return ESP_FAIL;
@@ -384,6 +397,12 @@ esp_err_t esp_ble_gattc_read_multiple(esp_gatt_if_t gattc_if,
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
LOG_WARN("%s, The connection not created.", __func__);
return ESP_ERR_INVALID_STATE;
}
if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) {
LOG_DEBUG("%s, the l2cap chanel is congest.", __func__);
return ESP_FAIL;
@@ -415,6 +434,12 @@ esp_err_t esp_ble_gattc_read_char_descr (esp_gatt_if_t gattc_if,
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
LOG_WARN("%s, The connection not created.", __func__);
return ESP_ERR_INVALID_STATE;
}
if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) {
LOG_DEBUG("%s, the l2cap chanel is congest.", __func__);
return ESP_FAIL;
@@ -442,6 +467,12 @@ esp_err_t esp_ble_gattc_write_char(esp_gatt_if_t gattc_if,
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
LOG_WARN("%s, The connection not created.", __func__);
return ESP_ERR_INVALID_STATE;
}
if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) {
LOG_DEBUG("%s, the l2cap chanel is congest.", __func__);
return ESP_FAIL;
@@ -474,6 +505,12 @@ esp_err_t esp_ble_gattc_write_char_descr (esp_gatt_if_t gattc_if,
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
LOG_WARN("%s, The connection not created.", __func__);
return ESP_ERR_INVALID_STATE;
}
if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) {
LOG_DEBUG("%s, the l2cap chanel is congest.", __func__);
return ESP_FAIL;
@@ -506,6 +543,12 @@ esp_err_t esp_ble_gattc_prepare_write(esp_gatt_if_t gattc_if,
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
LOG_WARN("%s, The connection not created.", __func__);
return ESP_ERR_INVALID_STATE;
}
if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) {
LOG_DEBUG("%s, the l2cap chanel is congest.", __func__);
return ESP_FAIL;
@@ -536,6 +579,12 @@ esp_err_t esp_ble_gattc_prepare_write_char_descr(esp_gatt_if_t gattc_if,
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
LOG_WARN("%s, The connection not created.", __func__);
return ESP_ERR_INVALID_STATE;
}
if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) {
LOG_DEBUG("%s, the l2cap chanel is congest.", __func__);
return ESP_FAIL;

View File

@@ -14,6 +14,7 @@
#include "common/bt_target.h"
#include "stack/l2cdefs.h"
#include "stack/l2c_api.h"
#include "gatt_int.h"
#if (GATTS_INCLUDED == TRUE)
#define COPY_TO_GATTS_ARGS(_gatt_args, _arg, _arg_type) memcpy(_gatt_args, _arg, sizeof(_arg_type))
@@ -251,7 +252,13 @@ esp_err_t esp_ble_gatts_send_indicate(esp_gatt_if_t gatts_if, uint16_t conn_id,
btc_ble_gatts_args_t arg;
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
LOG_WARN("%s, The connection not created.", __func__);
return ESP_ERR_INVALID_STATE;
}
if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) {
LOG_DEBUG("%s, the l2cap chanel is congest.", __func__);
return ESP_FAIL;
@@ -279,7 +286,13 @@ esp_err_t esp_ble_gatts_send_response(esp_gatt_if_t gatts_if, uint16_t conn_id,
btc_ble_gatts_args_t arg;
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id);
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
LOG_WARN("%s, The connection not created.", __func__);
return ESP_ERR_INVALID_STATE;
}
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_GATTS;
msg.act = BTC_GATTS_ACT_SEND_RESPONSE;

View File

@@ -336,6 +336,7 @@ typedef union {
struct read_rmt_name_param {
esp_bt_status_t stat; /*!< read Remote Name status */
uint8_t rmt_name[ESP_BT_GAP_MAX_BDNAME_LEN + 1]; /*!< Remote device name */
esp_bd_addr_t bda; /*!< remote bluetooth device address*/
} read_rmt_name; /*!< read Remote Name parameter struct */
/**

View File

@@ -34,6 +34,10 @@ extern "C" {
#define ESP_HF_PEER_FEAT_ECC 0x80 /* Enhanced Call Control */
#define ESP_HF_PEER_FEAT_EXTERR 0x100 /* Extended error codes */
#define ESP_HF_PEER_FEAT_CODEC 0x200 /* Codec Negotiation */
/* HFP 1.7+ */
#define ESP_HF_PEER_FEAT_HF_IND 0x400 /* HF Indicators */
#define ESP_HF_PEER_FEAT_ESCO_S4 0x800 /* eSCO S4 Setting Supported */
/* CHLD feature masks of HF AG */
#define ESP_HF_CHLD_FEAT_REL 0x01 /* 0 Release waiting call or held calls */

View File

@@ -60,6 +60,9 @@ typedef enum {
#define ESP_HF_CLIENT_PEER_FEAT_ECC 0x80 /* Enhanced Call Control */
#define ESP_HF_CLIENT_PEER_FEAT_EXTERR 0x100 /* Extended error codes */
#define ESP_HF_CLIENT_PEER_FEAT_CODEC 0x200 /* Codec Negotiation */
/* HFP 1.7+ */
#define ESP_HF_CLIENT_PEER_FEAT_HF_IND 0x400 /* HF Indicators */
#define ESP_HF_CLIENT_PEER_FEAT_ESCO_S4 0x800 /* eSCO S4 Setting Supported */
/* CHLD feature masks of AG */
#define ESP_HF_CLIENT_CHLD_FEAT_REL 0x01 /* 0 Release waiting call or held calls */

View File

@@ -272,7 +272,7 @@ const tBTA_AG_ST_TBL bta_ag_st_tbl[] =
/*****************************************************************************
** Global data
*****************************************************************************/
const char *bta_ag_version = "1.6";
const uint16_t bta_ag_version = HFP_VERSION_1_7;
/* AG control block */
#if BTA_DYNAMIC_MEMORY == FALSE
tBTA_AG_CB bta_ag_cb;
@@ -758,7 +758,7 @@ static void bta_ag_api_enable(tBTA_AG_DATA *p_data)
bta_ag_cb.p_cback = p_data->api_enable.p_cback;
bta_ag_cb.parse_mode = p_data->api_enable.parse_mode;
/* check if mSBC support enabled */
if (strcmp(bta_ag_version, "1.6") == 0) {
if (bta_ag_version >= HFP_VERSION_1_6) {
bta_ag_cb.msbc_enabled = TRUE;
bta_ag_cb.scb->negotiated_codec = BTM_SCO_CODEC_MSBC;
} else{

View File

@@ -70,10 +70,11 @@ enum
};
#if (BTM_WBS_INCLUDED == TRUE)
#define BTA_AG_NUM_CODECS 3
#define BTA_AG_ESCO_SETTING_IDX_CVSD 0 /* eSCO setting for CVSD */
#define BTA_AG_NUM_CODECS 4
#define BTA_AG_ESCO_SETTING_IDX_CVSD 0 /* eSCO setting for CVSD */
#define BTA_AG_ESCO_SETTING_IDX_T1 1 /* eSCO setting for mSBC T1 */
#define BTA_AG_ESCO_SETTING_IDX_T2 2 /* eSCO setting for mSBC T2 */
#define BTA_AG_ESCO_SETTING_IDX_S4 3 /* eSCO setting for CVSD S4 */
static const tBTM_ESCO_PARAMS bta_ag_esco_params[BTA_AG_NUM_CODECS] =
{
@@ -81,9 +82,9 @@ static const tBTM_ESCO_PARAMS bta_ag_esco_params[BTA_AG_NUM_CODECS] =
{
BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec) */
BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec) */
0x000a, /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3) */
10, /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3) */
BTM_VOICE_SETTING_CVSD, /* Inp Linear, Air CVSD, 2s Comp, 16bit */
(BTM_SCO_PKT_TYPES_MASK_HV1 + /* Packet Types */
(BTM_SCO_PKT_TYPES_MASK_HV1 + /* Packet Types */
BTM_SCO_PKT_TYPES_MASK_HV2 +
BTM_SCO_PKT_TYPES_MASK_HV3 +
BTM_SCO_PKT_TYPES_MASK_EV3 +
@@ -91,7 +92,7 @@ static const tBTM_ESCO_PARAMS bta_ag_esco_params[BTA_AG_NUM_CODECS] =
BTM_SCO_PKT_TYPES_MASK_EV5 +
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 +
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
BTM_ESCO_RETRANS_POWER /* Retransmission effort */
BTM_ESCO_RETRANS_POWER /* Retransmission effort */
},
/* mSBC T1 */
{
@@ -104,7 +105,7 @@ static const tBTM_ESCO_PARAMS bta_ag_esco_params[BTA_AG_NUM_CODECS] =
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5 |
BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 ),
BTM_ESCO_RETRANS_QUALITY /* Retransmission effort */
BTM_ESCO_RETRANS_QUALITY /* Retransmission effort */
},
/* mSBC T2*/
{
@@ -116,26 +117,56 @@ static const tBTM_ESCO_PARAMS bta_ag_esco_params[BTA_AG_NUM_CODECS] =
BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
BTM_ESCO_RETRANS_QUALITY /* Retransmission effort */
BTM_ESCO_RETRANS_QUALITY /* Retransmission effort */
},
/* HFP 1.7+ */
/* eSCO CVSD S4 */
{
BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec) */
BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec) */
12, /* 12 ms (HS/HF can use EV3, 2-EV3) */
BTM_VOICE_SETTING_CVSD, /* Inp Linear, Air CVSD, 2s Comp, 16bit */
(BTM_SCO_LINK_ALL_PKT_MASK |
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
BTM_ESCO_RETRANS_QUALITY /* Retransmission effort */
}
};
#else
#define BTA_AG_NUM_CODECS 2
#define BTA_AG_ESCO_SETTING_IDX_CVSD 0 /* eSCO setting for CVSD S3 */
#define BTA_AG_ESCO_SETTING_IDX_S4 1 /* eSCO setting for CVSD S4 */
/* WBS not included, CVSD by default */
static const tBTM_ESCO_PARAMS bta_ag_esco_params =
static const tBTM_ESCO_PARAMS bta_ag_esco_params[] =
{
BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec) */
BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec) */
0x000a, /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3) */
0x0060, /* Inp Linear, Air CVSD, 2s Comp, 16bit */
(BTM_SCO_PKT_TYPES_MASK_HV1 + /* Packet Types */
BTM_SCO_PKT_TYPES_MASK_HV2 +
BTM_SCO_PKT_TYPES_MASK_HV3 +
BTM_SCO_PKT_TYPES_MASK_EV3 +
BTM_SCO_PKT_TYPES_MASK_EV4 +
BTM_SCO_PKT_TYPES_MASK_EV5 +
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 +
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
BTM_ESCO_RETRANS_POWER /* Retransmission effort */
{
BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec) */
BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec) */
10, /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3) */
BTM_VOICE_SETTING_CVSD, /* Inp Linear, Air CVSD, 2s Comp, 16bit */
(BTM_SCO_PKT_TYPES_MASK_HV1 + /* Packet Types */
BTM_SCO_PKT_TYPES_MASK_HV2 +
BTM_SCO_PKT_TYPES_MASK_HV3 +
BTM_SCO_PKT_TYPES_MASK_EV3 +
BTM_SCO_PKT_TYPES_MASK_EV4 +
BTM_SCO_PKT_TYPES_MASK_EV5 +
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 +
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
BTM_ESCO_RETRANS_POWER /* Retransmission effort */
},
/* HFP 1.7+ */
/* eSCO CVSD S4 */
{
BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec) */
BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec) */
12, /* 12 ms (HS/HF can use EV3, 2-EV3) */
BTM_VOICE_SETTING_CVSD, /* Inp Linear, Air CVSD, 2s Comp, 16bit */
(BTM_SCO_LINK_ALL_PKT_MASK |
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
BTM_ESCO_RETRANS_QUALITY /* Retransmission effort */
}
};
#endif
@@ -470,9 +501,9 @@ static void bta_ag_create_sco(tBTA_AG_SCB *p_scb, BOOLEAN is_orig)
tBTM_STATUS status;
UINT8 *p_bd_addr = NULL;
tBTM_ESCO_PARAMS params;
UINT8 codec_index = BTA_AG_ESCO_SETTING_IDX_CVSD;
#if (BTM_WBS_INCLUDED == TRUE)
tBTA_AG_PEER_CODEC esco_codec = BTM_SCO_CODEC_CVSD;
int codec_index = 0;
#endif
#if (BTM_SCO_HCI_INCLUDED == TRUE)
tBTM_SCO_ROUTE_TYPE sco_route;
@@ -513,11 +544,20 @@ static void bta_ag_create_sco(tBTA_AG_SCB *p_scb, BOOLEAN is_orig)
codec_index = BTA_AG_ESCO_SETTING_IDX_T1;
}
}
params = bta_ag_esco_params[codec_index];
/* If eSCO codec is CVSD and eSC0 S4 is supported, index is S4 */
else if ((esco_codec == BTM_SCO_CODEC_CVSD) && (p_scb->features & BTA_AG_FEAT_ESCO_S4)
&& (p_scb->peer_features & BTA_AG_PEER_FEAT_ESCO_S4))
{
codec_index = BTA_AG_ESCO_SETTING_IDX_S4;
}
#else
/* When WBS is not included, use CVSD by default */
params = bta_ag_esco_params;
if ((p_scb->features & BTA_AG_FEAT_ESCO_S4) && (p_scb->peer_features & BTA_AG_PEER_FEAT_ESCO_S4))
{
codec_index = BTA_AG_ESCO_SETTING_IDX_S4;
}
#endif
params = bta_ag_esco_params[codec_index];
if(bta_ag_cb.sco.param_updated) /* If we do not use the default parameters */
params = bta_ag_cb.sco.params;
@@ -528,10 +568,13 @@ static void bta_ag_create_sco(tBTA_AG_SCB *p_scb, BOOLEAN is_orig)
if (esco_codec == BTM_SCO_CODEC_CVSD) /* For CVSD */
#endif
{
/* Use the application packet types (5 slot EV packets not allowed) */
params.packet_types = p_bta_ag_cfg->sco_pkt_types |
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5;
if (codec_index == BTA_AG_ESCO_SETTING_IDX_CVSD)
{
/* Use the application packet types (5 slot EV packets not allowed) */
params.packet_types = p_bta_ag_cfg->sco_pkt_types |
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5;
}
}
}
@@ -1608,6 +1651,7 @@ void bta_ag_sco_conn_rsp(tBTA_AG_SCB *p_scb, tBTM_ESCO_CONN_REQ_EVT_DATA *p_data
if (p_data->link_type == BTM_LINK_TYPE_SCO)
{
resp.retrans_effort = BTM_ESCO_RETRANS_OFF;
resp.packet_types = (BTM_SCO_LINK_ONLY_MASK |
BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 |
BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
@@ -1616,6 +1660,13 @@ void bta_ag_sco_conn_rsp(tBTA_AG_SCB *p_scb, tBTM_ESCO_CONN_REQ_EVT_DATA *p_data
}
else /* Allow controller to use all types available except 5-slot EDR */
{
if ((p_scb->features & BTA_AG_FEAT_ESCO_S4) &&
(p_scb->peer_features & BTA_AG_PEER_FEAT_ESCO_S4))
{
resp.max_latency = 12;
resp.retrans_effort = BTM_ESCO_RETRANS_QUALITY;
}
resp.packet_types = (BTM_SCO_LINK_ALL_PKT_MASK |
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5);

View File

@@ -157,7 +157,7 @@ BOOLEAN bta_ag_add_record(UINT16 service_uuid, char *p_service_name, UINT8 scn,
/* add profile descriptor list */
if (service_uuid == UUID_SERVCLASS_AG_HANDSFREE) {
profile_uuid = UUID_SERVCLASS_HF_HANDSFREE;
version = HFP_VERSION_1_6;
version = HFP_VERSION_1_7;
} else {
profile_uuid = UUID_SERVCLASS_HEADSET;
version = HSP_VERSION_1_2;

View File

@@ -48,6 +48,7 @@
#define HFP_VERSION_1_1 0x0101
#define HFP_VERSION_1_5 0x0105
#define HFP_VERSION_1_6 0x0106
#define HFP_VERSION_1_7 0x0107
#define HSP_VERSION_1_0 0x0100
#define HSP_VERSION_1_2 0x0102
@@ -75,12 +76,12 @@
#define BTA_AG_INT 1 /* initiating connection */
/* feature mask that matches spec */
#define BTA_AG_BSRF_FEAT_SPEC (BTA_AG_FEAT_3WAY | BTA_AG_FEAT_ECNR | \
BTA_AG_FEAT_VREC | BTA_AG_FEAT_INBAND | \
BTA_AG_FEAT_VTAG | BTA_AG_FEAT_REJECT | \
BTA_AG_FEAT_ECS | BTA_AG_FEAT_ECC | \
BTA_AG_FEAT_EXTERR | BTA_AG_FEAT_CODEC | \
BTA_AG_FEAT_VOIP)
#define BTA_AG_BSRF_FEAT_SPEC (BTA_AG_FEAT_3WAY | BTA_AG_FEAT_ECNR | \
BTA_AG_FEAT_VREC | BTA_AG_FEAT_INBAND | \
BTA_AG_FEAT_VTAG | BTA_AG_FEAT_REJECT | \
BTA_AG_FEAT_ECS | BTA_AG_FEAT_ECC | \
BTA_AG_FEAT_EXTERR | BTA_AG_FEAT_CODEC | \
BTA_AG_FEAT_ESCO_S4| BTA_AG_FEAT_VOIP)
#define BTA_AG_SDP_FEAT_SPEC (BTA_AG_FEAT_3WAY | BTA_AG_FEAT_ECNR | \
BTA_AG_FEAT_VREC | BTA_AG_FEAT_INBAND | \

View File

@@ -232,7 +232,7 @@ const tBTA_HF_CLIENT_ST_TBL bta_hf_client_st_tbl[] = {
bta_hf_client_st_closing
};
const char *bta_hf_client_version = "1.6";
const int bta_hf_client_version = HFP_HF_VERSION_1_7;
/* HF Client control block */
#if BTA_DYNAMIC_MEMORY == FALSE
@@ -387,7 +387,7 @@ static void bta_hf_client_api_enable(tBTA_HF_CLIENT_DATA *p_data)
bta_hf_client_cb.p_cback = p_data->api_enable.p_cback;
/* check if mSBC support enabled */
if (strcmp(bta_hf_client_version, "1.6") == 0) {
if (bta_hf_client_version >= HFP_HF_VERSION_1_6) {
bta_hf_client_cb.msbc_enabled = TRUE;
} else{
bta_hf_client_cb.msbc_enabled = FALSE;

View File

@@ -18,6 +18,7 @@
******************************************************************************/
#include "bta_hf_client_int.h"
#include "bta/bta_hf_client_api.h"
#include "common/bt_trace.h"
#include <string.h>
#include "common/bt_defs.h"
@@ -34,6 +35,11 @@
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | \
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5)
#define BTA_HF_CLIENT_SCO_PARAM_IDX_CVSD 0 /* SCO setting for CVSD */
#define BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S3 1 /* eSCO setting for CVSD S3 */
#define BTA_HF_CLIENT_ESCO_PARAM_IDX_MSBC_T2 2 /* eSCO setting for mSBC T2 */
#define BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S4 3 /* eSCO setting for CVSD S4 */
static const tBTM_ESCO_PARAMS bta_hf_client_esco_params[] = {
/* SCO CVSD */
{
@@ -72,6 +78,19 @@ static const tBTM_ESCO_PARAMS bta_hf_client_esco_params[] = {
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
.retrans_effort = BTM_ESCO_RETRANS_QUALITY,
},
/* HFP 1.7+ */
/* ESCO CVSD S4 */
{
.rx_bw = BTM_64KBITS_RATE,
.tx_bw = BTM_64KBITS_RATE,
.max_latency = 12,
.voice_contfmt = BTM_VOICE_SETTING_CVSD,
/* Allow controller to use all types available except 5-slot EDR */
.packet_types = (BTM_SCO_LINK_ALL_PKT_MASK |
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
.retrans_effort = BTM_ESCO_RETRANS_QUALITY,
}
};
@@ -178,18 +197,27 @@ static void bta_hf_client_sco_conn_rsp(tBTM_ESCO_CONN_REQ_EVT_DATA *p_data)
{
tBTM_ESCO_PARAMS resp;
UINT8 hci_status = HCI_SUCCESS;
UINT8 index = BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S3;
#if (BTM_SCO_HCI_INCLUDED == TRUE )
tBTA_HFP_CODEC_INFO codec_info = {BTA_HFP_SCO_CODEC_PCM};
UINT32 pcm_sample_rate;
#endif
APPL_TRACE_DEBUG("%s", __FUNCTION__);
APPL_TRACE_DEBUG("%s: negotiated codec = %d", __FUNCTION__, bta_hf_client_cb.scb.negotiated_codec);
if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_LISTEN_ST) {
if (p_data->link_type == BTM_LINK_TYPE_SCO) {
resp = bta_hf_client_esco_params[0];
index = BTA_HF_CLIENT_SCO_PARAM_IDX_CVSD;
} else {
resp = bta_hf_client_esco_params[bta_hf_client_cb.scb.negotiated_codec];
if ((bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_CVSD) &&
(bta_hf_client_cb.scb.features && BTA_HF_CLIENT_FEAT_ESCO_S4) &&
(bta_hf_client_cb.scb.peer_features && BTA_HF_CLIENT_PEER_ESCO_S4)) {
index = BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S4;
} else if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC) {
index = BTA_HF_CLIENT_ESCO_PARAM_IDX_MSBC_T2;
}
}
resp = bta_hf_client_esco_params[index];
/* tell sys to stop av if any */
bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
@@ -350,6 +378,7 @@ static void bta_hf_client_sco_create(BOOLEAN is_orig)
tBTM_STATUS status;
UINT8 *p_bd_addr = NULL;
tBTM_ESCO_PARAMS params;
UINT8 index = BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S3;
#if (BTM_SCO_HCI_INCLUDED == TRUE )
tBTM_SCO_ROUTE_TYPE sco_route;
tBTA_HFP_CODEC_INFO codec_info = {BTA_HFP_SCO_CODEC_PCM};
@@ -364,7 +393,15 @@ static void bta_hf_client_sco_create(BOOLEAN is_orig)
return;
}
params = bta_hf_client_esco_params[1];
if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_CVSD) {
if ((bta_hf_client_cb.scb.features && BTA_HF_CLIENT_FEAT_ESCO_S4) &&
(bta_hf_client_cb.scb.peer_features && BTA_HF_CLIENT_PEER_ESCO_S4)) {
index = BTA_HF_CLIENT_ESCO_PARAM_IDX_CVSD_S4;
}
} else if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC) {
index = BTA_HF_CLIENT_ESCO_PARAM_IDX_MSBC_T2;
}
params = bta_hf_client_esco_params[index];
/* if initiating set current scb and peer bd addr */
if (is_orig) {

View File

@@ -114,7 +114,7 @@ BOOLEAN bta_hf_client_add_record(char *p_service_name, UINT8 scn,
/* add profile descriptor list */
profile_uuid = UUID_SERVCLASS_HF_HANDSFREE;
version = HFP_VERSION_1_6;
version = HFP_VERSION_1_7;
result &= SDP_AddProfileDescriptorList(sdp_handle, profile_uuid, version);

View File

@@ -29,6 +29,7 @@
#define HFP_VERSION_1_1 0x0101
#define HFP_VERSION_1_5 0x0105
#define HFP_VERSION_1_6 0x0106
#define HFP_VERSION_1_7 0x0107
/* RFCOMM MTU SIZE */
#define BTA_HF_CLIENT_MTU 256

View File

@@ -45,12 +45,16 @@
#define BTA_AG_FEAT_ECC 0x00000080 /* Enhanced Call Control */
#define BTA_AG_FEAT_EXTERR 0x00000100 /* Extended error codes */
#define BTA_AG_FEAT_CODEC 0x00000200 /* Codec Negotiation */
#define BTA_AG_FEAT_VOIP 0x00000400 /* VoIP call */
/* HFP 1.7+ */
#define BTA_AG_FEAT_HF_IND 0x00000400 /* HF Indicators */
#define BTA_AG_FEAT_ESCO_S4 0x00000800 /* eSCO S4 Setting Supported */
/* Proprietary features: using 31 ~ 16 bits */
#define BTA_AG_FEAT_BTRH 0x00010000 /* CCAP incoming call hold */
#define BTA_AG_FEAT_UNAT 0x00020000 /* Pass unknown AT commands to application */
#define BTA_AG_FEAT_NOSCO 0x00040000 /* No SCO control performed by BTA AG */
#define BTA_AG_FEAT_NO_ESCO 0x00080000 /* Do not allow or use eSCO */
#define BTA_AG_FEAT_VOIP 0x00100000 /* VoIP call */
typedef UINT32 tBTA_AG_FEAT;
/* HFP peer features */
@@ -62,9 +66,16 @@ typedef UINT32 tBTA_AG_FEAT;
#define BTA_AG_PEER_FEAT_ECS 0x0020 /* Enhanced Call Status */
#define BTA_AG_PEER_FEAT_ECC 0x0040 /* Enhanced Call Control */
#define BTA_AG_PEER_FEAT_CODEC 0x0080 /* Codec Negotiation */
#define BTA_AG_PEER_FEAT_VOIP 0x0100 /* VoIP call */
/* HFP 1.7+ */
#define BTA_AG_PEER_FEAT_HF_IND 0x0100 /* HF Indicators */
#define BTA_AG_PEER_FEAT_ESCO_S4 0x0200 /* eSCO S4 Setting Supported */
typedef UINT16 tBTA_AG_PEER_FEAT;
/* Proprietary features: using bits after 12 */
/* Pass unknown AT command responses to application */
#define BTA_AG_PEER_FEAT_UNAT 0x1000
#define BTA_AG_PEER_FEAT_VOIP 0x2000 /* VoIP call */
/* AG extended call handling - masks not related to any spec */
#define BTA_AG_CLIENT_CHLD_REL 0x00000001 /* 0 Release waiting call or held calls */
#define BTA_AG_CLIENT_CHLD_REL_ACC 0x00000002 /* 1 Release active calls and accept other (waiting or held) cal */

View File

@@ -33,6 +33,10 @@
** Constants and data types
*****************************************************************************/
/* Hands-Free unit(HF) version */
#define HFP_HF_VERSION_1_6 0x0106 /* v1.6 */
#define HFP_HF_VERSION_1_7 0x0107 /* v1.7 */
/* HFP peer (AG) features*/
#define BTA_HF_CLIENT_PEER_FEAT_3WAY 0x00000001 /* Three-way calling */
#define BTA_HF_CLIENT_PEER_FEAT_ECNR 0x00000002 /* Echo cancellation and/or noise reduction */
@@ -44,6 +48,9 @@
#define BTA_HF_CLIENT_PEER_ECC 0x00000080 /* Enhanced Call Control */
#define BTA_HF_CLIENT_PEER_EXTERR 0x00000100 /* Extended error codes */
#define BTA_HF_CLIENT_PEER_CODEC 0x00000200 /* Codec Negotiation */
/* HFP 1.7+ */
#define BTA_HF_CLIENT_PEER_HF_IND 0x00000400 /* HF Indicators */
#define BTA_HF_CLIENT_PEER_ESCO_S4 0x00000800 /* eSCO S4 Setting Supported */
typedef UINT16 tBTA_HF_CLIENT_PEER_FEAT;
@@ -56,6 +63,8 @@ typedef UINT16 tBTA_HF_CLIENT_PEER_FEAT;
#define BTA_HF_CLIENT_FEAT_ECS 0x00000020 /* Enhanced Call Status */
#define BTA_HF_CLIENT_FEAT_ECC 0x00000040 /* Enhanced Call Control */
#define BTA_HF_CLIENT_FEAT_CODEC 0x00000080 /* Codec Negotiation */
#define BTA_HF_CLIENT_FEAT_HF_IND 0x00000100 /* HF indicators */
#define BTA_HF_CLIENT_FEAT_ESCO_S4 0x00000200 /* eSCO S4 Setting Supported */
/* HFP HF extended call handling - masks not related to any spec */
#define BTA_HF_CLIENT_CHLD_REL 0x00000001 /* 0 Release waiting call or held calls */

View File

@@ -110,12 +110,18 @@ typedef struct {
UINT32 sample_rate;
} tBTC_A2DP_SINK_CB;
typedef struct {
uint16_t expected_seq_num;
bool seq_num_recount;
} a2dp_sink_media_pkt_seq_num_t;
typedef struct {
tBTC_A2DP_SINK_CB btc_aa_snk_cb;
osi_thread_t *btc_aa_snk_task_hdl;
OI_CODEC_SBC_DECODER_CONTEXT context;
OI_UINT32 contextData[CODEC_DATA_WORDS(2, SBC_CODEC_FAST_FILTER_BUFFERS)];
OI_INT16 pcmData[15 * SBC_MAX_SAMPLES_PER_FRAME * SBC_MAX_CHANNELS];
a2dp_sink_media_pkt_seq_num_t media_pkt_seq_num;
} a2dp_sink_local_param_t;
static void btc_a2dp_sink_thread_init(UNUSED_ATTR void *context);
@@ -319,6 +325,10 @@ static BOOLEAN btc_a2dp_sink_clear_track(void)
void btc_a2dp_sink_set_rx_flush(BOOLEAN enable)
{
APPL_TRACE_EVENT("## DROP RX %d ##\n", enable);
if (enable == FALSE) {
a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num = 0x1;
a2dp_sink_local_param.media_pkt_seq_num.seq_num_recount = true;
}
a2dp_sink_local_param.btc_aa_snk_cb.rx_flush = enable;
}
@@ -549,6 +559,18 @@ static void btc_a2dp_sink_handle_inc_media(tBT_SBC_HDR *p_msg)
return;
}
if (p_msg->layer_specific != a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num) {
/* Because the sequence number of some devices is not recounted */
if (!a2dp_sink_local_param.media_pkt_seq_num.seq_num_recount ||
a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num != 0x1) {
APPL_TRACE_WARNING("Sequence numbers error, recv:0x%x, expect:0x%x, recount:0x%x",
p_msg->layer_specific, a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num,
a2dp_sink_local_param.media_pkt_seq_num.seq_num_recount);
}
}
a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num = p_msg->layer_specific + 1;
a2dp_sink_local_param.media_pkt_seq_num.seq_num_recount = false;
APPL_TRACE_DEBUG("Number of sbc frames %d, frame_len %d\n", num_sbc_frames, sbc_frame_len);
for (count = 0; count < num_sbc_frames && sbc_frame_len != 0; count ++) {

View File

@@ -743,6 +743,7 @@ static void btc_gap_bt_read_remote_name_cmpl_callback(void *p_data)
msg.pid = BTC_PID_GAP_BT;
msg.act = BTC_GAP_BT_READ_REMOTE_NAME_EVT;
memcpy(param.read_rmt_name.bda,result->bd_addr,BD_ADDR_LEN);
param.read_rmt_name.stat = btc_btm_status_to_esp_status(result->status);
memcpy(param.read_rmt_name.rmt_name,result->remote_bd_name,ESP_BT_GAP_MAX_BDNAME_LEN);

View File

@@ -1,20 +1,8 @@
/******************************************************************************
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* Copyright (C) 2009-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
* SPDX-License-Identifier: Apache-2.0
*/
/************************************************************************************
*
@@ -68,6 +56,7 @@ static hf_local_param_t *hf_local_param;
BTA_AG_FEAT_VREC | \
BTA_AG_FEAT_INBAND | \
BTA_AG_FEAT_CODEC | \
BTA_AG_FEAT_ESCO_S4| \
BTA_AG_FEAT_UNAT)
#endif
#else
@@ -78,6 +67,7 @@ static hf_local_param_t *hf_local_param;
BTA_AG_FEAT_EXTERR | \
BTA_AG_FEAT_VREC | \
BTA_AG_FEAT_INBAND | \
BTA_AG_FEAT_ESCO_S4| \
BTA_AG_FEAT_UNAT)
#endif
#endif

View File

@@ -51,13 +51,13 @@
#endif
#ifndef BTC_HF_CLIENT_FEATURES
#define BTC_HF_CLIENT_FEATURES ( BTA_HF_CLIENT_FEAT_ECNR | \
BTA_HF_CLIENT_FEAT_3WAY | \
BTA_HF_CLIENT_FEAT_CLI | \
BTA_HF_CLIENT_FEAT_VREC | \
BTA_HF_CLIENT_FEAT_VOL | \
BTA_HF_CLIENT_FEAT_ECS | \
BTA_HF_CLIENT_FEAT_ECC | \
#define BTC_HF_CLIENT_FEATURES ( BTA_HF_CLIENT_FEAT_ECNR | \
BTA_HF_CLIENT_FEAT_3WAY | \
BTA_HF_CLIENT_FEAT_CLI | \
BTA_HF_CLIENT_FEAT_VREC | \
BTA_HF_CLIENT_FEAT_VOL | \
BTA_HF_CLIENT_FEAT_ECS | \
BTA_HF_CLIENT_FEAT_ECC | \
BTA_HF_CLIENT_FEAT_CODEC)
#endif
@@ -66,7 +66,7 @@
/************************************************************************************
** Static variables
************************************************************************************/
const char *btc_hf_client_version = "1.6";
const int btc_hf_client_version = HFP_HF_VERSION_1_7;
#if HFP_DYNAMIC_MEMORY == FALSE
static hf_client_local_param_t hf_client_local_param;
@@ -200,7 +200,7 @@ static bt_status_t connect_int( bt_bdaddr_t *bd_addr, uint16_t uuid )
bt_status_t btc_hf_client_connect( bt_bdaddr_t *bd_addr )
{
BTC_TRACE_EVENT("HFP Client version is %s", btc_hf_client_version);
BTC_TRACE_EVENT("HFP Client version is 0x%04x", btc_hf_client_version);
CHECK_HF_CLIENT_INIT();
return btc_queue_connect(UUID_SERVCLASS_HF_HANDSFREE, bd_addr, connect_int);
}
@@ -690,33 +690,36 @@ bt_status_t btc_hf_client_execute_service(BOOLEAN b_enable)
{
BTC_TRACE_EVENT("%s enable:%d", __FUNCTION__, b_enable);
if (b_enable)
{
/* Enable and register with BTA-HFClient */
BTA_HfClientEnable(bte_hf_client_evt);
if (strcmp(btc_hf_client_version, "1.6") == 0)
{
BTC_TRACE_EVENT("Support Codec Nego. %d ", BTC_HF_CLIENT_FEATURES);
BTA_HfClientRegister(BTC_HF_CLIENT_SECURITY, BTC_HF_CLIENT_FEATURES,
BTC_HF_CLIENT_SERVICE_NAME);
}
else
{
BTC_TRACE_EVENT("No Codec Nego Supported");
hf_client_local_param.btc_hf_client_features = BTC_HF_CLIENT_FEATURES;
hf_client_local_param.btc_hf_client_features = hf_client_local_param.btc_hf_client_features & (~BTA_HF_CLIENT_FEAT_CODEC);
BTC_TRACE_EVENT("hf_client_local_param.btc_hf_client_features is %d", hf_client_local_param.btc_hf_client_features);
BTA_HfClientRegister(BTC_HF_CLIENT_SECURITY, hf_client_local_param.btc_hf_client_features,
BTC_HF_CLIENT_SERVICE_NAME);
}
if (b_enable)
{
/* Enable and register with BTA-HFClient */
BTA_HfClientEnable(bte_hf_client_evt);
hf_client_local_param.btc_hf_client_features = BTC_HF_CLIENT_FEATURES;
if (btc_hf_client_version >= HFP_HF_VERSION_1_7)
{
hf_client_local_param.btc_hf_client_features |= BTA_HF_CLIENT_FEAT_ESCO_S4;
BTC_TRACE_EVENT("eSCO S4 Setting Supported");
}
else
{
BTA_HfClientDeregister(hf_client_local_param.btc_hf_client_cb.handle);
BTA_HfClientDisable();
}
return BT_STATUS_SUCCESS;
}
else if (btc_hf_client_version >= HFP_HF_VERSION_1_6)
{
BTC_TRACE_EVENT("No eSCO S4 Setting Supported");
}
else
{
BTC_TRACE_EVENT("No Codec Nego Supported");
hf_client_local_param.btc_hf_client_features = hf_client_local_param.btc_hf_client_features & (~BTA_HF_CLIENT_FEAT_CODEC);
}
BTC_TRACE_EVENT("hf_client_local_param.btc_hf_client_features is %d", hf_client_local_param.btc_hf_client_features);
BTA_HfClientRegister(BTC_HF_CLIENT_SECURITY, hf_client_local_param.btc_hf_client_features,
BTC_HF_CLIENT_SERVICE_NAME);
}
else
{
BTA_HfClientDeregister(hf_client_local_param.btc_hf_client_cb.handle);
BTA_HfClientDisable();
}
return BT_STATUS_SUCCESS;
}
static void process_ind_evt(tBTA_HF_CLIENT_IND *ind)

View File

@@ -58,14 +58,14 @@ typedef union {
tSDP_UUID *p_uuid_list;
} start_discovery;
//BTC_SPP_ACT_CONNECT
struct connect_arg {
struct conn_arg {
esp_spp_sec_t sec_mask;
esp_spp_role_t role;
UINT8 remote_scn;
esp_bd_addr_t peer_bd_addr;
} connect;
//BTC_SPP_ACT_DISCONNECT
struct disconnect_arg {
struct disconn_arg {
UINT32 handle;
} disconnect;
//BTC_SPP_ACT_START_SRV

View File

@@ -352,6 +352,20 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u
}
new_user_data = (void *)(uintptr_t)slot->id;
break;
case BTA_JV_RFCOMM_CL_INIT_EVT:
slot = spp_find_slot_by_id(id);
if (!slot) {
BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event);
p_data->rfc_cl_init.status = ESP_SPP_FAILURE;
break;
}
if (p_data->rfc_cl_init.status == BTA_JV_SUCCESS) {
slot->rfc_handle = p_data->rfc_cl_init.handle;
} else {
spp_free_slot(slot);
}
break;
case BTA_JV_RFCOMM_OPEN_EVT:
slot = spp_find_slot_by_id(id);
if (!slot) {
@@ -359,7 +373,7 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u
p_data->rfc_open.status = ESP_SPP_NO_CONNECTION;
break;
}
slot->connected = TRUE;
slot->connected = true;
slot->rfc_handle = p_data->rfc_open.handle;
slot->rfc_port_handle = BTA_JvRfcommGetPortHdl(p_data->rfc_open.handle);
BTA_JvSetPmProfile(p_data->rfc_open.handle, BTA_JV_PM_ID_1, BTA_JV_CONN_OPEN);
@@ -371,7 +385,7 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u
p_data->rfc_close.status = ESP_SPP_NO_CONNECTION;
break;
}
if (slot->connected && p_data->rfc_close.port_status != PORT_LOCAL_CLOSED) {
if (slot->rfc_handle && p_data->rfc_close.port_status != PORT_LOCAL_CLOSED) {
BTA_JvRfcommClose(slot->rfc_handle, NULL, (void *)slot->id);
}
p_data->rfc_close.status = BTA_JV_SUCCESS;
@@ -505,6 +519,7 @@ static void btc_spp_init(btc_spp_args_t *arg)
}
if ((spp_local_param.tx_event_group = xEventGroupCreate()) == NULL) {
BTC_TRACE_ERROR("%s create tx_event_group failed\n", __func__);
osi_mutex_free(&spp_local_param.spp_slot_mutex);
ret = ESP_SPP_NO_RESOURCE;
break;
}
@@ -568,11 +583,6 @@ static void btc_spp_uninit(void)
osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
} while(0);
if (spp_local_param.tx_event_group) {
vEventGroupDelete(spp_local_param.tx_event_group);
spp_local_param.tx_event_group = NULL;
}
if (ret != ESP_SPP_SUCCESS) {
esp_spp_cb_param_t param;
param.uninit.status = ret;
@@ -1037,7 +1047,7 @@ void btc_spp_cb_handler(btc_msg_t *msg)
}
break;
case BTA_JV_RFCOMM_WRITE_EVT:
osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
slot = spp_find_slot_by_handle(p_data->rfc_write.handle);
if (!slot) {
BTC_TRACE_ERROR("%s unable to find RFCOMM slot!, handle:%d", __func__, p_data->rfc_write.handle);
@@ -1056,6 +1066,7 @@ void btc_spp_cb_handler(btc_msg_t *msg)
BT_HDR *p_buf;
serial = slot->serial;
if ((p_buf = fixed_queue_try_peek_first(slot->tx.queue)) == NULL) {
osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
break;
}
if (p_data->rfc_write.status == BTA_JV_SUCCESS) {
@@ -1121,7 +1132,7 @@ void btc_spp_cb_handler(btc_msg_t *msg)
// if rx still has data, delay free slot
if (slot->close_alarm == NULL && slot->rx.queue && fixed_queue_length(slot->rx.queue) > 0) {
tBTA_JV *p_arg = NULL;
if ((p_arg = malloc(sizeof(tBTA_JV))) == NULL) {
if ((p_arg = osi_malloc(sizeof(tBTA_JV))) == NULL) {
param.close.status = ESP_SPP_NO_RESOURCE;
osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
BTC_TRACE_ERROR("%s unable to malloc slot close_alarm arg!", __func__);
@@ -1241,6 +1252,10 @@ void btc_spp_cb_handler(btc_msg_t *msg)
param.uninit.status = ESP_SPP_SUCCESS;
BTA_JvFree();
osi_mutex_free(&spp_local_param.spp_slot_mutex);
if (spp_local_param.tx_event_group) {
vEventGroupDelete(spp_local_param.tx_event_group);
spp_local_param.tx_event_group = NULL;
}
#if SPP_DYNAMIC_MEMORY == TRUE
osi_free(spp_local_param_ptr);
spp_local_param_ptr = NULL;

View File

@@ -2085,12 +2085,6 @@ The maximum number of payload octets that the local device can receive in a sing
#define BTSNOOP_MEM FALSE
#endif
#if UC_BT_BLUEDROID_MEM_DEBUG
#define HEAP_MEMORY_DEBUG TRUE
#else
#define HEAP_MEMORY_DEBUG FALSE
#endif
#if UC_HEAP_ALLOCATION_FROM_SPIRAM_FIRST
#define HEAP_ALLOCATION_FROM_SPIRAM_FIRST TRUE
#else

View File

@@ -1586,8 +1586,8 @@ void avdt_msg_send_grej(tAVDT_CCB *p_ccb, UINT8 sig_id, tAVDT_MSG *p_params)
p_buf->len = (UINT16) (p - p_start);
/* stash sig, label, and message type in buf */
p_buf->event = 0;
AVDT_BLD_LAYERSPEC(p_buf->layer_specific, 0, p_params->hdr.label);
p_buf->event = sig_id;
AVDT_BLD_LAYERSPEC(p_buf->layer_specific, AVDT_MSG_TYPE_GRJ, p_params->hdr.label);
AVDT_TRACE_DEBUG("avdt_msg_send_grej");
/* queue message and trigger ccb to send it */

View File

@@ -2306,6 +2306,7 @@ void btm_process_remote_name (BD_ADDR bda, BD_NAME bdn, UINT16 evt_len, UINT8 hc
rem_name.length = 0;
rem_name.remote_bd_name[0] = 0;
}
memcpy(rem_name.bd_addr, p_inq->remname_bda, BD_ADDR_LEN);
/* Reset the remote BAD to zero and call callback if possible */
memset(p_inq->remname_bda, 0, BD_ADDR_LEN);

View File

@@ -111,12 +111,15 @@ static void btu_hcif_rem_oob_request_evt (UINT8 *p);
#if (SMP_INCLUDED == TRUE)
static void btu_hcif_simple_pair_complete_evt (UINT8 *p);
#endif ///SMP_INCLUDED == TRUE
static void btu_hcif_link_supv_to_changed_evt (UINT8 *p);
#if L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE
static void btu_hcif_enhanced_flush_complete_evt (void);
#endif
#if (BTM_SSR_INCLUDED == TRUE)
static void btu_hcif_ssr_evt (UINT8 *p, UINT16 evt_len);
#else
static void btu_hcif_ssr_evt_dump (UINT8 *p, UINT16 evt_len);
#endif /* BTM_SSR_INCLUDED == TRUE */
#if BLE_INCLUDED == TRUE
@@ -289,11 +292,13 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg)
case HCI_ESCO_CONNECTION_CHANGED_EVT:
btu_hcif_esco_connection_chg_evt (p);
break;
#if (BTM_SSR_INCLUDED == TRUE)
case HCI_SNIFF_SUB_RATE_EVT:
#if (BTM_SSR_INCLUDED == TRUE)
btu_hcif_ssr_evt (p, hci_evt_len);
break;
#else
btu_hcif_ssr_evt_dump (p, hci_evt_len);
#endif /* BTM_SSR_INCLUDED == TRUE */
break;
case HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT:
btu_hcif_host_support_evt (p);
break;
@@ -327,6 +332,9 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg)
btu_hcif_keypress_notif_evt (p);
break;
#endif ///SMP_INCLUDED == TRUE
case HCI_LINK_SUPER_TOUT_CHANGED_EVT:
btu_hcif_link_supv_to_changed_evt (p);
break;
#if L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE
case HCI_ENHANCED_FLUSH_COMPLETE_EVT:
btu_hcif_enhanced_flush_complete_evt ();
@@ -565,6 +573,7 @@ static void btu_hcif_connection_comp_evt (UINT8 *p)
btm_sco_connected (status, bda, handle, &esco_data);
}
#endif /* BTM_SCO_INCLUDED */
HCI_TRACE_WARNING("hcif conn complete: hdl 0x%x, st 0x%x", handle, status);
}
@@ -621,6 +630,8 @@ static void btu_hcif_disconnection_comp_evt (UINT8 *p)
handle = HCID_GET_HANDLE (handle);
HCI_TRACE_WARNING("hcif disc complete: hdl 0x%x, rsn 0x%x", handle, reason);
#if BTM_SCO_INCLUDED == TRUE
/* If L2CAP doesn't know about it, send it to SCO */
if (!l2c_link_hci_disc_comp (handle, reason)) {
@@ -1411,6 +1422,8 @@ static void btu_hcif_mode_change_evt (UINT8 *p)
btm_sco_chk_pend_unpark (status, handle);
#endif
btm_pm_proc_mode_change (status, handle, current_mode, interval);
HCI_TRACE_WARNING("hcif mode change: hdl 0x%x, mode %d, intv %d, status 0x%x",
handle, current_mode, interval, status);
/*
#if (HID_DEV_INCLUDED == TRUE) && (HID_DEV_PM_INCLUDED == TRUE)
@@ -1433,6 +1446,26 @@ static void btu_hcif_ssr_evt (UINT8 *p, UINT16 evt_len)
{
btm_pm_proc_ssr_evt(p, evt_len);
}
#else
static void btu_hcif_ssr_evt_dump (UINT8 *p, UINT16 evt_len)
{
UINT8 status;
UINT16 handle;
UINT16 max_tx_lat;
UINT16 max_rx_lat;
STREAM_TO_UINT8 (status, p);
STREAM_TO_UINT16 (handle, p);
STREAM_TO_UINT16 (max_tx_lat, p);
STREAM_TO_UINT16 (max_rx_lat, p);
UNUSED(status);
UNUSED(handle);
UNUSED(max_tx_lat);
UNUSED(max_rx_lat);
HCI_TRACE_WARNING("hcif ssr evt: st 0x%x, hdl 0x%x, tx_lat %d rx_lat %d", status, handle, max_tx_lat, max_rx_lat);
}
#endif
/*******************************************************************************
@@ -1777,6 +1810,30 @@ static void btu_hcif_simple_pair_complete_evt (UINT8 *p)
btm_simple_pair_complete(p);
}
#endif ///SMP_INCLUDED == TRUE
/*******************************************************************************
**
** Function btu_hcif_link_supv_to_changed_evt
**
** Description Process event HCI_LINK_SUPER_TOUT_CHANGED_EVT
**
** Returns void
**
*******************************************************************************/
static void btu_hcif_link_supv_to_changed_evt (UINT8 *p)
{
UINT16 handle;
UINT16 supv_to;
STREAM_TO_UINT16(handle, p);
STREAM_TO_UINT16(supv_to, p);
UNUSED(handle);
UNUSED(supv_to);
HCI_TRACE_WARNING("hcif link supv_to changed: hdl 0x%x, supv_to %d", handle, supv_to);
}
/*******************************************************************************
**
** Function btu_hcif_enhanced_flush_complete_evt

View File

@@ -312,6 +312,12 @@ BT_HDR *attp_build_value_cmd (UINT16 payload_size, UINT8 op_code, UINT16 handle,
p_buf->len += 2;
}
if(payload_size < GATT_DEF_BLE_MTU_SIZE || payload_size > GATT_MAX_MTU_SIZE) {
GATT_TRACE_ERROR("invalid payload_size %d", payload_size);
osi_free(p_buf);
return NULL;
}
if (len > 0 && p_data != NULL) {
/* ensure data not exceed MTU size */
if (payload_size - p_buf->len < len) {

View File

@@ -583,6 +583,11 @@ tGATT_STATUS GATTS_HandleValueIndication (UINT16 conn_id, UINT16 attr_handle, U
return (tGATT_STATUS) GATT_INVALID_CONN_ID;
}
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
GATT_TRACE_ERROR("connection not established\n");
return GATT_WRONG_STATE;
}
if (! GATT_HANDLE_IS_VALID (attr_handle)) {
return GATT_ILLEGAL_PARAMETER;
}
@@ -650,6 +655,11 @@ tGATT_STATUS GATTS_HandleValueNotification (UINT16 conn_id, UINT16 attr_handle,
return (tGATT_STATUS) GATT_INVALID_CONN_ID;
}
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
GATT_TRACE_ERROR("connection not established\n");
return GATT_WRONG_STATE;
}
if (GATT_HANDLE_IS_VALID (attr_handle)) {
notif.handle = attr_handle;
notif.len = val_len;
@@ -697,6 +707,11 @@ tGATT_STATUS GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id,
return (tGATT_STATUS) GATT_INVALID_CONN_ID;
}
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
GATT_TRACE_ERROR("connection not established\n");
return GATT_WRONG_STATE;
}
if (p_tcb->sr_cmd.trans_id != trans_id) {
GATT_TRACE_ERROR ("GATTS_SendRsp conn_id: %u waiting for op_code = %02x\n",
conn_id, p_tcb->sr_cmd.op_code);
@@ -818,6 +833,11 @@ tGATT_STATUS GATTC_ConfigureMTU (UINT16 conn_id)
return GATT_ILLEGAL_PARAMETER;
}
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
GATT_TRACE_ERROR("connection not established\n");
return GATT_ERROR;
}
/* Validate that the link is BLE, not BR/EDR */
if (p_tcb->transport != BT_TRANSPORT_LE) {
return GATT_ERROR;
@@ -870,6 +890,10 @@ tGATT_STATUS GATTC_Discover (UINT16 conn_id, tGATT_DISC_TYPE disc_type,
return GATT_ILLEGAL_PARAMETER;
}
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
GATT_TRACE_ERROR("connection not established\n");
return GATT_ERROR;
}
if (gatt_is_clcb_allocated(conn_id)) {
GATT_TRACE_ERROR("GATTC_Discover GATT_BUSY conn_id = %d", conn_id);
@@ -932,6 +956,11 @@ tGATT_STATUS GATTC_Read (UINT16 conn_id, tGATT_READ_TYPE type, tGATT_READ_PARAM
return GATT_ILLEGAL_PARAMETER;
}
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
GATT_TRACE_ERROR("connection not established\n");
return GATT_ERROR;
}
if (gatt_is_clcb_allocated(conn_id)) {
GATT_TRACE_ERROR("GATTC_Read GATT_BUSY conn_id = %d", conn_id);
return GATT_BUSY;
@@ -1010,6 +1039,11 @@ tGATT_STATUS GATTC_Write (UINT16 conn_id, tGATT_WRITE_TYPE type, tGATT_VALUE *p_
return GATT_ILLEGAL_PARAMETER;
}
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
GATT_TRACE_ERROR("connection not established\n");
return GATT_ERROR;
}
if (gatt_is_clcb_allocated(conn_id)) {
GATT_TRACE_ERROR("GATTC_Write GATT_BUSY conn_id = %d", conn_id);
return GATT_BUSY;
@@ -1076,6 +1110,11 @@ tGATT_STATUS GATTC_ExecuteWrite (UINT16 conn_id, BOOLEAN is_execute)
return GATT_ILLEGAL_PARAMETER;
}
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
GATT_TRACE_ERROR("connection not established\n");
return GATT_ERROR;
}
if (gatt_is_clcb_allocated(conn_id)) {
GATT_TRACE_ERROR("GATTC_Write GATT_BUSY conn_id = %d", conn_id);
return GATT_BUSY;

View File

@@ -896,6 +896,26 @@ BOOLEAN gatt_is_bda_connected(BD_ADDR bda)
return connected;
}
/*******************************************************************************
**
** Function gatt_check_connection_state_by_tcb
**
** Description
**
** Returns TRUE if connected. Otherwise connection not established.
**
*******************************************************************************/
BOOLEAN gatt_check_connection_state_by_tcb(tGATT_TCB *p_tcb)
{
BOOLEAN connected = FALSE;
if(p_tcb && gatt_get_ch_state(p_tcb) == GATT_CH_OPEN) {
connected = TRUE;
}
return connected;
}
/*******************************************************************************
**
** Function gatt_find_i_tcb_by_addr

View File

@@ -751,6 +751,8 @@ extern tGATT_STATUS gatts_read_attr_perm_check(tGATT_SVC_DB *p_db, BOOLEAN is_lo
extern void gatts_update_srv_list_elem(UINT8 i_sreg, UINT16 handle, BOOLEAN is_primary);
extern tBT_UUID *gatts_get_service_uuid (tGATT_SVC_DB *p_db);
extern BOOLEAN gatt_check_connection_state_by_tcb(tGATT_TCB *p_tcb);
extern void gatt_reset_bgdev_list(void);
extern uint16_t gatt_get_local_mtu(void);
extern void gatt_set_local_mtu(uint16_t mtu);

View File

@@ -191,6 +191,7 @@ BOOLEAN btsnd_hcic_disconnect (UINT16 handle, UINT8 reason)
UINT8_TO_STREAM (pp, reason);
btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
HCI_TRACE_WARNING("hci cmd send: disconnect: hdl 0x%x, rsn:0x%x", handle, reason);
return (TRUE);
}
@@ -776,6 +777,8 @@ BOOLEAN btsnd_hcic_sniff_mode (UINT16 handle, UINT16 max_sniff_period,
UINT16_TO_STREAM (pp, sniff_timeout);
btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
HCI_TRACE_WARNING("hci cmd send: sniff: hdl 0x%x, intv(%d %d)",
handle, min_sniff_period, max_sniff_period);
return (TRUE);
}
@@ -799,6 +802,7 @@ BOOLEAN btsnd_hcic_exit_sniff_mode (UINT16 handle)
UINT16_TO_STREAM (pp, handle);
btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
HCI_TRACE_WARNING("hci cmd send: unsniff: hdl 0x%x", handle);
return TRUE;
}

View File

@@ -2331,6 +2331,13 @@ void l2ble_update_att_acl_pkt_num(UINT8 type, tl2c_buff_param_t *param)
xSemaphoreGive(buff_semaphore);
break;
}
if (!gatt_check_connection_state_by_tcb(p_tcb)) {
L2CAP_TRACE_ERROR("connection not established\n");
xSemaphoreGive(buff_semaphore);
break;
}
tL2C_LCB * p_lcb = l2cu_find_lcb_by_bd_addr (p_tcb->peer_bda, BT_TRANSPORT_LE);
if (p_lcb == NULL){
L2CAP_TRACE_ERROR("%s not found p_lcb", __func__);

View File

@@ -51,7 +51,8 @@ idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS ${includes}
PRIV_INCLUDE_DIRS "include/driver"
PRIV_REQUIRES efuse esp_timer esp_ipc
REQUIRES esp_ringbuf freertos soc) #cannot totally hide soc headers, since there are a lot arguments in the driver are chip-dependent
REQUIRES esp_ringbuf freertos soc #cannot totally hide soc headers, since there are a lot arguments in the driver are chip-dependent
LDFRAGMENTS linker.lf)
# uses C11 atomic feature
set_source_files_properties(spi_master.c PROPERTIES COMPILE_FLAGS -std=gnu11)

View File

@@ -92,6 +92,48 @@ menu "Driver configurations"
- Alert logging (i.e., setting of the TWAI_ALERT_AND_LOG flag)
will have no effect.
config TWAI_ERRATA_FIX_BUS_OFF_REC
bool "Add SW workaround for REC change during bus-off"
depends on IDF_TARGET_ESP32
default n
help
When the bus-off condition is reached, the REC should be reset to 0 and frozen (via LOM) by the
driver's ISR. However on the ESP32, there is an edge case where the REC will increase before the
driver's ISR can respond in time (e.g., due to the rapid occurrence of bus errors), thus causing the
REC to be non-zero after bus-off. A non-zero REC can prevent bus-off recovery as the bus-off recovery
condition is that both TEC and REC become 0. Enabling this option will add a workaround in the driver
to forcibly reset REC to zero on reaching bus-off.
config TWAI_ERRATA_FIX_TX_INTR_LOST
bool "Add SW workaround for TX interrupt lost errata"
depends on IDF_TARGET_ESP32
default n
help
On the ESP32, when a transmit interrupt occurs, and interrupt register is read on the same APB clock
cycle, the transmit interrupt could be lost. Enabling this option will add a workaround that checks the
transmit buffer status bit to recover any lost transmit interrupt.
config TWAI_ERRATA_FIX_RX_FRAME_INVALID
bool "Add SW workaround for invalid RX frame errata"
depends on IDF_TARGET_ESP32
default n
help
On the ESP32, when receiving a data or remote frame, if a bus error occurs in the data or CRC field,
the data of the next received frame could be invalid. Enabling this option will add a workaround that
will reset the peripheral on detection of this errata condition. Note that if a frame is transmitted on
the bus whilst the reset is ongoing, the message will not be receive by the peripheral sent on the bus
during the reset, the message will be lost.
config TWAI_ERRATA_FIX_RX_FIFO_CORRUPT
bool "Add SW workaround for RX FIFO corruption errata"
depends on IDF_TARGET_ESP32
default n
help
On the ESP32, when the RX FIFO overruns and the RX message counter maxes out at 64 messages, the entire
RX FIFO is no longer recoverable. Enabling this option will add a workaround that resets the peripheral
on detection of this errata condition. Note that if a frame is being sent on the bus during the reset
bus during the reset, the message will be lost.
endmenu # TWAI Configuration
menu "UART configuration"

View File

@@ -289,6 +289,10 @@ esp_err_t touch_pad_config(touch_pad_t touch_num, uint16_t threshold)
esp_err_t touch_pad_init(void)
{
#ifdef CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2
ESP_LOGE(TOUCH_TAG, "Touch Pad can't work because it provides current to external XTAL");
return ESP_ERR_NOT_SUPPORTED;
#endif // CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2
if (rtc_touch_mux == NULL) {
rtc_touch_mux = xSemaphoreCreateMutex();
}

View File

@@ -318,6 +318,14 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b
return ESP_ERR_INVALID_ARG;
}
p_i2s_obj[i2s_num]->sample_rate = rate;
/**
* Due to hardware issue, bck division on ESP32/ESP32-S2 should be greater than 8 in slave mode
* So the factor need to be an appropriate value
*/
if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_SLAVE)) {
factor = 16 * bits;
}
double clkmdiv = (double)I2S_BASE_CLK / (rate * factor);
if (clkmdiv > 256) {
@@ -498,7 +506,7 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg)
//Avoid spurious interrupt
return;
}
i2s_event_t i2s_event;
int dummy;
@@ -917,7 +925,7 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config,
}
memset(p_i2s_obj[i2s_num], 0, sizeof(i2s_obj_t));
portMUX_TYPE i2s_spinlock_unlocked[1] = {portMUX_INITIALIZER_UNLOCKED};
portMUX_TYPE i2s_spinlock_unlocked[1] = {portMUX_INITIALIZER_UNLOCKED};
for (int x = 0; x < I2S_NUM_MAX; x++) {
i2s_spinlock[x] = i2s_spinlock_unlocked[0];
}

View File

@@ -81,7 +81,7 @@ esp_err_t gpio_set_intr_type(gpio_num_t gpio_num, gpio_int_type_t intr_type);
/**
* @brief Enable GPIO module interrupt signal
*
* @note Please do not use the interrupt of GPIO36 and GPIO39 when using ADC or Wi-Fi with sleep mode enabled.
* @note Please do not use the interrupt of GPIO36 and GPIO39 when using ADC or Wi-Fi and Bluetooth with sleep mode enabled.
* Please refer to the comments of `adc1_get_raw`.
* Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue.
* As a workaround, call adc_power_acquire() in the app. This will result in higher power consumption (by ~1mA),

View File

@@ -61,6 +61,7 @@ esp_err_t ledc_timer_config(const ledc_timer_config_t* timer_conf);
* @brief LEDC update channel parameters
* @note Call this function to activate the LEDC updated parameters.
* After ledc_set_duty, we need to call this function to update the settings.
* And the new LEDC parameters don't take effect until the next PWM cycle.
* @note ledc_set_duty, ledc_set_duty_with_hpoint and ledc_update_duty are not thread-safe, do not call these functions to
* control one LEDC channel in different tasks at the same time.
* A thread-safe version of API is ledc_set_duty_and_update
@@ -178,6 +179,9 @@ esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t
/**
* @brief LEDC get duty
* This function returns the duty at the present PWM cycle.
* You shouldn't expect the function to return the new duty in the same cycle of calling ledc_update_duty,
* because duty update doesn't take effect until the next cycle.
*
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel (0-7), select from ledc_channel_t
@@ -360,7 +364,8 @@ void ledc_fade_func_uninstall(void);
* Other duty operations will have to wait until the fade operation has finished.
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel number
* @param fade_mode Whether to block until fading done.
* @param fade_mode Whether to block until fading done. See ledc_types.h ledc_fade_mode_t for more info.
* Note that this function will not return until fading to the target duty if LEDC_FADE_WAIT_DONE mode is selected.
*
* @return
* - ESP_OK Success

View File

@@ -133,7 +133,7 @@ esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *
* @param host_id SPI peripheral to free
* @return
* - ESP_ERR_INVALID_ARG if parameter is invalid
* - ESP_ERR_INVALID_STATE if not all devices on the bus are freed
* - ESP_ERR_INVALID_STATE if bus hasn't been initialized before, or not all devices on the bus are freed
* - ESP_OK on success
*/
esp_err_t spi_bus_free(spi_host_device_t host_id);

View File

@@ -28,6 +28,7 @@ extern "C" {
* @return
* - ESP_OK Success
* - ESP_ERR_NO_MEM Touch pad init error
* - ESP_ERR_NOT_SUPPORTED Touch pad is providing current to external XTAL
*/
esp_err_t touch_pad_init(void);

View File

@@ -40,9 +40,9 @@ extern "C" {
* configured. The other members of the general configuration structure are
* assigned default values.
*/
#define TWAI_GENERAL_CONFIG_DEFAULT(tx_io_num, rx_io_num, op_mode) {.mode = op_mode, .tx_io = tx_io_num, .rx_io = rx_io_num, \
.clkout_io = TWAI_IO_UNUSED, .bus_off_io = TWAI_IO_UNUSED, \
.tx_queue_len = 5, .rx_queue_len = 5, \
#define TWAI_GENERAL_CONFIG_DEFAULT(tx_io_num, rx_io_num, op_mode) {.mode = op_mode, .tx_io = tx_io_num, .rx_io = rx_io_num, \
.clkout_io = TWAI_IO_UNUSED, .bus_off_io = TWAI_IO_UNUSED, \
.tx_queue_len = 5, .rx_queue_len = 5, \
.alerts_enabled = TWAI_ALERT_NONE, .clkout_divider = 0, \
.intr_flags = ESP_INTR_FLAG_LEVEL1}
@@ -56,22 +56,25 @@ extern "C" {
* @note The TWAI_ALERT_AND_LOG flag is not an actual alert, but will configure
* the TWAI driver to log to UART when an enabled alert occurs.
*/
#define TWAI_ALERT_TX_IDLE 0x0001 /**< Alert(1): No more messages to transmit */
#define TWAI_ALERT_TX_SUCCESS 0x0002 /**< Alert(2): The previous transmission was successful */
#define TWAI_ALERT_BELOW_ERR_WARN 0x0004 /**< Alert(4): Both error counters have dropped below error warning limit */
#define TWAI_ALERT_ERR_ACTIVE 0x0008 /**< Alert(8): TWAI controller has become error active */
#define TWAI_ALERT_RECOVERY_IN_PROGRESS 0x0010 /**< Alert(16): TWAI controller is undergoing bus recovery */
#define TWAI_ALERT_BUS_RECOVERED 0x0020 /**< Alert(32): TWAI controller has successfully completed bus recovery */
#define TWAI_ALERT_ARB_LOST 0x0040 /**< Alert(64): The previous transmission lost arbitration */
#define TWAI_ALERT_ABOVE_ERR_WARN 0x0080 /**< Alert(128): One of the error counters have exceeded the error warning limit */
#define TWAI_ALERT_BUS_ERROR 0x0100 /**< Alert(256): A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus */
#define TWAI_ALERT_TX_FAILED 0x0200 /**< Alert(512): The previous transmission has failed (for single shot transmission) */
#define TWAI_ALERT_RX_QUEUE_FULL 0x0400 /**< Alert(1024): The RX queue is full causing a frame to be lost */
#define TWAI_ALERT_ERR_PASS 0x0800 /**< Alert(2048): TWAI controller has become error passive */
#define TWAI_ALERT_BUS_OFF 0x1000 /**< Alert(4096): Bus-off condition occurred. TWAI controller can no longer influence bus */
#define TWAI_ALERT_ALL 0x1FFF /**< Bit mask to enable all alerts during configuration */
#define TWAI_ALERT_NONE 0x0000 /**< Bit mask to disable all alerts during configuration */
#define TWAI_ALERT_AND_LOG 0x2000 /**< Bit mask to enable alerts to also be logged when they occur. Note that logging from the ISR is disabled if CONFIG_TWAI_ISR_IN_IRAM is enabled (see docs). */
#define TWAI_ALERT_TX_IDLE 0x00000001 /**< Alert(1): No more messages to transmit */
#define TWAI_ALERT_TX_SUCCESS 0x00000002 /**< Alert(2): The previous transmission was successful */
#define TWAI_ALERT_BELOW_ERR_WARN 0x00000004 /**< Alert(4): Both error counters have dropped below error warning limit */
#define TWAI_ALERT_ERR_ACTIVE 0x00000008 /**< Alert(8): TWAI controller has become error active */
#define TWAI_ALERT_RECOVERY_IN_PROGRESS 0x00000010 /**< Alert(16): TWAI controller is undergoing bus recovery */
#define TWAI_ALERT_BUS_RECOVERED 0x00000020 /**< Alert(32): TWAI controller has successfully completed bus recovery */
#define TWAI_ALERT_ARB_LOST 0x00000040 /**< Alert(64): The previous transmission lost arbitration */
#define TWAI_ALERT_ABOVE_ERR_WARN 0x00000080 /**< Alert(128): One of the error counters have exceeded the error warning limit */
#define TWAI_ALERT_BUS_ERROR 0x00000100 /**< Alert(256): A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus */
#define TWAI_ALERT_TX_FAILED 0x00000200 /**< Alert(512): The previous transmission has failed (for single shot transmission) */
#define TWAI_ALERT_RX_QUEUE_FULL 0x00000400 /**< Alert(1024): The RX queue is full causing a frame to be lost */
#define TWAI_ALERT_ERR_PASS 0x00000800 /**< Alert(2048): TWAI controller has become error passive */
#define TWAI_ALERT_BUS_OFF 0x00001000 /**< Alert(4096): Bus-off condition occurred. TWAI controller can no longer influence bus */
#define TWAI_ALERT_RX_FIFO_OVERRUN 0x00002000 /**< Alert(8192): An RX FIFO overrun has occurred */
#define TWAI_ALERT_TX_RETRIED 0x00004000 /**< Alert(16384): An message transmission was cancelled and retried due to an errata workaround */
#define TWAI_ALERT_PERIPH_RESET 0x00008000 /**< Alert(32768): The TWAI controller was reset */
#define TWAI_ALERT_ALL 0x0000FFFF /**< Bit mask to enable all alerts during configuration */
#define TWAI_ALERT_NONE 0x00000000 /**< Bit mask to disable all alerts during configuration */
#define TWAI_ALERT_AND_LOG 0x00010000 /**< Bit mask to enable alerts to also be logged when they occur. Note that logging from the ISR is disabled if CONFIG_TWAI_ISR_IN_IRAM is enabled (see docs). */
/** @endcond */
@@ -117,7 +120,8 @@ typedef struct {
uint32_t tx_error_counter; /**< Current value of Transmit Error Counter */
uint32_t rx_error_counter; /**< Current value of Receive Error Counter */
uint32_t tx_failed_count; /**< Number of messages that failed transmissions */
uint32_t rx_missed_count; /**< Number of messages that were lost due to a full RX queue */
uint32_t rx_missed_count; /**< Number of messages that were lost due to a full RX queue (or errata workaround if enabled) */
uint32_t rx_overrun_count; /**< Number of messages that were lost due to a RX FIFO overrun */
uint32_t arb_lost_count; /**< Number of instances arbitration was lost */
uint32_t bus_error_count; /**< Number of instances a bus error has occurred */
} twai_status_info_t;
@@ -168,9 +172,9 @@ esp_err_t twai_driver_uninstall(void);
*
* This function starts the TWAI driver, putting the TWAI driver into the running
* state. This allows the TWAI driver to participate in TWAI bus activities such
* as transmitting/receiving messages. The RX queue is reset in this function,
* clearing any unread messages. This function can only be called when the TWAI
* driver is in the stopped state.
* as transmitting/receiving messages. The TX and RX queue are reset in this function,
* clearing any messages that are unread or pending transmission. This function
* can only be called when the TWAI driver is in the stopped state.
*
* @return
* - ESP_OK: TWAI driver is now running

View File

@@ -199,7 +199,7 @@ esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_
static IRAM_ATTR esp_err_t ledc_duty_config(ledc_mode_t speed_mode, ledc_channel_t channel, int hpoint_val, int duty_val,
ledc_duty_direction_t duty_direction, uint32_t duty_num, uint32_t duty_cycle, uint32_t duty_scale)
{
portENTER_CRITICAL(&ledc_spinlock);
portENTER_CRITICAL_SAFE(&ledc_spinlock);
if (hpoint_val >= 0) {
ledc_hal_set_hpoint(&(p_ledc_obj[speed_mode]->ledc_hal), channel, hpoint_val);
}
@@ -211,7 +211,7 @@ static IRAM_ATTR esp_err_t ledc_duty_config(ledc_mode_t speed_mode, ledc_channel
ledc_hal_set_duty_cycle(&(p_ledc_obj[speed_mode]->ledc_hal), channel, duty_cycle);
ledc_hal_set_duty_scale(&(p_ledc_obj[speed_mode]->ledc_hal), channel, duty_scale);
ledc_ls_channel_update(speed_mode, channel);
portEXIT_CRITICAL(&ledc_spinlock);
portEXIT_CRITICAL_SAFE(&ledc_spinlock);
return ESP_OK;
}
@@ -472,8 +472,8 @@ esp_err_t ledc_set_duty_with_hpoint(ledc_mode_t speed_mode, ledc_channel_t chann
hpoint, //uint32_t hpoint_val,
duty, //uint32_t duty_val,
1, //uint32_t increase,
1, //uint32_t duty_num,
1, //uint32_t duty_cycle,
0, //uint32_t duty_num,
0, //uint32_t duty_cycle,
0 //uint32_t duty_scale
);
_ledc_fade_hw_release(speed_mode, channel);
@@ -492,8 +492,8 @@ esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t
LEDC_VAL_NO_CHANGE,
duty, //uint32_t duty_val,
1, //uint32_t increase,
1, //uint32_t duty_num,
1, //uint32_t duty_cycle,
0, //uint32_t duty_num,
0, //uint32_t duty_cycle,
0 //uint32_t duty_scale
);
_ledc_fade_hw_release(speed_mode, channel);
@@ -573,9 +573,9 @@ void IRAM_ATTR ledc_fade_isr(void* arg)
ledc_calc_fade_end_channel(&intr_status, &channel);
// clear interrupt
portENTER_CRITICAL(&ledc_spinlock);
portENTER_CRITICAL_ISR(&ledc_spinlock);
ledc_hal_clear_fade_end_intr_status(&(p_ledc_obj[speed_mode]->ledc_hal), channel);
portEXIT_CRITICAL(&ledc_spinlock);
portEXIT_CRITICAL_ISR(&ledc_spinlock);
if (s_ledc_fade_rec[speed_mode][channel] == NULL) {
//fade object not initialized yet.
@@ -621,9 +621,9 @@ void IRAM_ATTR ledc_fade_isr(void* arg)
1,
0);
}
portENTER_CRITICAL(&ledc_spinlock);
portENTER_CRITICAL_ISR(&ledc_spinlock);
ledc_hal_set_duty_start(&(p_ledc_obj[speed_mode]->ledc_hal), channel, true);
portEXIT_CRITICAL(&ledc_spinlock);
portEXIT_CRITICAL_ISR(&ledc_spinlock);
}
}
}
@@ -763,7 +763,10 @@ static void _ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, led
ledc_enable_intr_type(speed_mode, channel, LEDC_INTR_FADE_END);
ledc_update_duty(speed_mode, channel);
if (fade_mode == LEDC_FADE_WAIT_DONE) {
xSemaphoreTake(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem, portMAX_DELAY);
// Waiting for fade done
_ledc_fade_hw_acquire(speed_mode, channel);
// Release hardware to support next time fade configure
_ledc_fade_hw_release(speed_mode, channel);
}
}
@@ -805,7 +808,6 @@ esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_f
LEDC_CHECK(p_ledc_obj[speed_mode] != NULL, LEDC_NOT_INIT, ESP_ERR_INVALID_STATE);
_ledc_fade_hw_acquire(speed_mode, channel);
_ledc_fade_start(speed_mode, channel, fade_mode);
_ledc_fade_hw_release(speed_mode, channel);
return ESP_OK;
}
@@ -842,14 +844,13 @@ esp_err_t ledc_set_duty_and_update(ledc_mode_t speed_mode, ledc_channel_t channe
LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode");
LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel");
LEDC_ARG_CHECK(duty <= ledc_get_max_duty(speed_mode, channel), "target_duty");
LEDC_ARG_CHECK(hpoint <= LEDC_HPOINT_VAL_MAX, "hpoint");
LEDC_CHECK(p_ledc_obj[speed_mode] != NULL, LEDC_NOT_INIT, ESP_ERR_INVALID_STATE);
LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK , LEDC_FADE_INIT_ERROR_STR, ESP_FAIL);
_ledc_op_lock_acquire(speed_mode, channel);
LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK, LEDC_FADE_INIT_ERROR_STR, ESP_FAIL);
_ledc_fade_hw_acquire(speed_mode, channel);
_ledc_set_fade_with_step(speed_mode, channel, duty, 0, 1);
_ledc_fade_start(speed_mode, channel, LEDC_FADE_WAIT_DONE);
ledc_duty_config(speed_mode, channel, hpoint, duty, 1, 0, 0, 0);
ledc_update_duty(speed_mode, channel);
_ledc_fade_hw_release(speed_mode, channel);
_ledc_op_lock_release(speed_mode, channel);
return ESP_OK;
}
@@ -865,9 +866,6 @@ esp_err_t ledc_set_fade_time_and_start(ledc_mode_t speed_mode, ledc_channel_t ch
_ledc_fade_hw_acquire(speed_mode, channel);
_ledc_set_fade_with_time(speed_mode, channel, target_duty, max_fade_time_ms);
_ledc_fade_start(speed_mode, channel, fade_mode);
if (fade_mode == LEDC_FADE_WAIT_DONE) {
_ledc_fade_hw_release(speed_mode, channel);
}
_ledc_op_lock_release(speed_mode, channel);
return ESP_OK;
}
@@ -886,9 +884,6 @@ esp_err_t ledc_set_fade_step_and_start(ledc_mode_t speed_mode, ledc_channel_t ch
_ledc_fade_hw_acquire(speed_mode, channel);
_ledc_set_fade_with_step(speed_mode, channel, target_duty, scale, cycle_num);
_ledc_fade_start(speed_mode, channel, fade_mode);
if (fade_mode == LEDC_FADE_WAIT_DONE) {
_ledc_fade_hw_release(speed_mode, channel);
}
_ledc_op_lock_release(speed_mode, channel);
return ESP_OK;
}

View File

@@ -0,0 +1,9 @@
[mapping:driver]
archive: libdriver.a
entries:
# TWAI workarounds that require periph_module_reset() won't work if cache is disabled due to the use of switch jump
# tables in periph_module_reset(). We prevent any part of periph_module_reset() (either text or RO data) from being
# placed in flash.
if TWAI_ISR_IN_IRAM = y && (TWAI_ERRATA_FIX_RX_FRAME_INVALID = y || TWAI_ERRATA_FIX_RX_FIFO_CORRUPT = y):
periph_ctrl: periph_module_reset (noflash)

View File

@@ -13,6 +13,7 @@
// limitations under the License.
#include "freertos/FreeRTOS.h"
#include "hal/clk_gate_ll.h"
#include "esp_attr.h"
#include "driver/periph_ctrl.h"
static portMUX_TYPE periph_spinlock = portMUX_INITIALIZER_UNLOCKED;

View File

@@ -661,7 +661,8 @@ static esp_err_t recv_flush_data(void)
static void sdio_intr_recv(void* arg)
{
portBASE_TYPE yield = 0;
while (sdio_slave_hal_recv_done(context.hal)) {
bool triggered = sdio_slave_hal_recv_done(context.hal);
while (triggered) {
portENTER_CRITICAL_ISR(&context.recv_spinlock);
bool has_next_item = sdio_slave_hal_recv_has_next_item(context.hal);
portEXIT_CRITICAL_ISR(&context.recv_spinlock);
@@ -670,8 +671,9 @@ static void sdio_intr_recv(void* arg)
xSemaphoreGiveFromISR(context.recv_event, &yield);
continue; //check the linked list again skip the interrupt checking
}
// if no more items on the list, go back and check again the interrupt,
// if no more items on the list, check the interrupt again,
// will loop until the interrupt bit is kept cleared.
triggered = sdio_slave_hal_recv_done(context.hal);
}
if (yield) portYIELD_FROM_ISR();
}

View File

@@ -567,6 +567,10 @@ const spi_bus_attr_t* spi_bus_get_attr(spi_host_device_t host_id)
esp_err_t spi_bus_free(spi_host_device_t host_id)
{
if (bus_ctx[host_id] == NULL) {
return ESP_ERR_INVALID_STATE;
}
esp_err_t err = ESP_OK;
spicommon_bus_context_t* ctx = bus_ctx[host_id];
spi_bus_attr_t* bus_attr = &ctx->bus_attr;

View File

@@ -662,8 +662,8 @@ static SPI_MASTER_ISR_ATTR esp_err_t check_trans_valid(spi_device_handle_t handl
spi_host_t *host = handle->host;
const spi_bus_attr_t* bus_attr = host->bus_attr;
//check transmission length
SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_RXDATA)==0 ||trans_desc->rxlength <= 32, "rxdata transfer > 32 bits without configured DMA", ESP_ERR_INVALID_ARG);
SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_TXDATA)==0 ||trans_desc->length <= 32, "txdata transfer > 32 bits without configured DMA", ESP_ERR_INVALID_ARG);
SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_RXDATA)==0 || trans_desc->rxlength <= 32, "SPI_TRANS_USE_RXDATA only available for rxdata transfer <= 32 bits", ESP_ERR_INVALID_ARG);
SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_TXDATA)==0 || trans_desc->length <= 32, "SPI_TRANS_USE_TXDATA only available for txdata transfer <= 32 bits", ESP_ERR_INVALID_ARG);
SPI_CHECK(trans_desc->length <= bus_attr->max_transfer_sz*8, "txdata transfer > host maximum", ESP_ERR_INVALID_ARG);
SPI_CHECK(trans_desc->rxlength <= bus_attr->max_transfer_sz*8, "rxdata transfer > host maximum", ESP_ERR_INVALID_ARG);
SPI_CHECK((handle->cfg.flags & SPI_DEVICE_HALFDUPLEX) || trans_desc->rxlength <= trans_desc->length, "rx length > tx length in full duplex mode", ESP_ERR_INVALID_ARG);

View File

@@ -728,11 +728,11 @@ TEST_CASE("GPIO ISR service test", "[gpio][ignore]")
{
const int test_io18 = GPIO_NUM_18;
const int test_io19 = GPIO_NUM_19;
static gpio_isr_param_t io18_param = {
gpio_isr_param_t io18_param = {
.gpio_num = GPIO_NUM_18,
.isr_cnt = 0,
};
static gpio_isr_param_t io19_param = {
gpio_isr_param_t io19_param = {
.gpio_num = GPIO_NUM_19,
.isr_cnt = 0,
};

View File

@@ -31,6 +31,12 @@
#define HIGHEST_LIMIT 10000
#define LOWEST_LIMIT -10000
#ifdef CONFIG_IDF_TARGET_ESP32
#define TEST_SPEED_MODE LEDC_HIGH_SPEED_MODE
#elif defined CONFIG_IDF_TARGET_ESP32S2
#define TEST_SPEED_MODE LEDC_LOW_SPEED_MODE
#endif
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2)
//no runners
@@ -99,12 +105,39 @@ static void timer_frequency_test(ledc_channel_t channel, ledc_timer_bit_t timer_
frequency_set_get(ledc_ch_config.speed_mode, ledc_ch_config.timer_sel, 9000, 9025, 5);
}
static void fade_setup(void)
{
ledc_channel_config_t ledc_ch_config = {
.gpio_num = PULSE_IO,
.speed_mode = TEST_SPEED_MODE,
.channel = LEDC_CHANNEL_0,
.intr_type = LEDC_INTR_DISABLE,
.timer_sel = LEDC_TIMER_0,
.duty = 0,
.hpoint = 0,
};
ledc_timer_config_t ledc_time_config = {
.speed_mode = TEST_SPEED_MODE,
.duty_resolution = LEDC_TIMER_13_BIT,
.timer_num = LEDC_TIMER_0,
.freq_hz = 2000,
.clk_cfg = LEDC_USE_APB_CLK,
};
TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
vTaskDelay(5 / portTICK_PERIOD_MS);
//initialize fade service
TEST_ESP_OK(ledc_fade_func_install(0));
}
static void timer_duty_set_get(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty)
{
TEST_ESP_OK(ledc_set_duty(speed_mode, channel, duty));
TEST_ESP_OK(ledc_update_duty(speed_mode, channel));
vTaskDelay(1000 / portTICK_RATE_MS);
TEST_ASSERT_EQUAL_INT32(ledc_get_duty(speed_mode, channel), duty);
vTaskDelay(100 / portTICK_RATE_MS);
TEST_ASSERT_EQUAL_INT32(duty, ledc_get_duty(speed_mode, channel));
}
// use logic analyzer to view
@@ -277,9 +310,9 @@ TEST_CASE("LEDC set and get frequency", "[ledc][test_env=UT_T1_LEDC][timeout=60]
timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_3, LEDC_LOW_SPEED_MODE);
}
// the duty need to be detected by waveform given by the logic analyzer
// can't get it directly, so set it "ignore"
TEST_CASE("LEDC set and get dut(with logic analyzer)", "[ledc][ignore]")
// duty should be manually checked from the waveform using a logic analyzer
// this test is enabled only for testting the settings
TEST_CASE("LEDC set and get duty", "[ledc]")
{
ledc_timer_t timer_list[4] = {LEDC_TIMER_0, LEDC_TIMER_1, LEDC_TIMER_2, LEDC_TIMER_3};
#ifdef CONFIG_IDF_TARGET_ESP32
@@ -331,7 +364,7 @@ TEST_CASE("LEDC timer set", "[ledc][test_env=UT_T1_LEDC]")
count = wave_count(1000);
TEST_ASSERT_UINT32_WITHIN(10, count, freq_get);
//set timer 3 as 500Hz, use APB_CLK
//set timer 0 as 500Hz, use APB_CLK
TEST_ESP_OK(ledc_timer_set(test_speed_mode, LEDC_TIMER_0, 5000, 13, LEDC_APB_CLK));
TEST_ESP_OK(ledc_timer_rst(test_speed_mode, LEDC_TIMER_0));
TEST_ASSERT_EQUAL_INT32(ledc_get_freq(test_speed_mode, LEDC_TIMER_0), 500);
@@ -403,102 +436,111 @@ TEST_CASE("LEDC timer pause and resume", "[ledc][test_env=UT_T1_LEDC]")
TEST_ASSERT_UINT32_WITHIN(5, count, 5000);
}
TEST_CASE("LEDC fade with time(logic analyzer)", "[ledc][test_env=UT_T1_LEDC]")
TEST_CASE("LEDC fade with time", "[ledc]")
{
#ifdef CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE
return;
#endif
const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
fade_setup();
#ifdef CONFIG_IDF_TARGET_ESP32
const ledc_mode_t test_speed_mode = LEDC_HIGH_SPEED_MODE;
#elif defined CONFIG_IDF_TARGET_ESP32S2
const ledc_mode_t test_speed_mode = LEDC_LOW_SPEED_MODE;
#endif
ledc_channel_config_t ledc_ch_config = {
.gpio_num = PULSE_IO,
.speed_mode = test_speed_mode,
.channel = LEDC_CHANNEL_0,
.intr_type = LEDC_INTR_DISABLE,
.timer_sel = LEDC_TIMER_0,
.duty = 0,
.hpoint = 0,
};
TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
ledc_timer_config_t ledc_time_config = {
.speed_mode = test_speed_mode,
.duty_resolution = LEDC_TIMER_13_BIT,
.timer_num = LEDC_TIMER_0,
.freq_hz = 5000,
.clk_cfg = LEDC_USE_APB_CLK,
};
TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
//initialize fade service
TEST_ESP_OK(ledc_fade_func_install(0));
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 1000));
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 200));
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE));
vTaskDelay(1000 / portTICK_RATE_MS);
TEST_ASSERT_EQUAL_INT32(ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0), 4000);
TEST_ASSERT_EQUAL_INT32(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 0, 1000));
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 0, 200));
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));
vTaskDelay(1000 / portTICK_RATE_MS);
TEST_ASSERT_EQUAL_INT32(ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0), 0);
// duty should not be too far from initial value
TEST_ASSERT_INT32_WITHIN(20, 4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
vTaskDelay(210 / portTICK_PERIOD_MS);
TEST_ASSERT_EQUAL_INT32(0, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
//deinitial fade service
//deinitialize fade service
ledc_fade_func_uninstall();
}
TEST_CASE("LEDC fade with step(logic analyzer)", "[ledc][test_env=UT_T1_LEDC]")
TEST_CASE("LEDC fade with step", "[ledc]")
{
#ifdef CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE
return;
#endif
const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
fade_setup();
#ifdef CONFIG_IDF_TARGET_ESP32
const ledc_mode_t test_speed_mode = LEDC_HIGH_SPEED_MODE;
#elif defined CONFIG_IDF_TARGET_ESP32S2
const ledc_mode_t test_speed_mode = LEDC_LOW_SPEED_MODE;
#endif
ledc_channel_config_t ledc_ch_config = {
.gpio_num = PULSE_IO,
.speed_mode = test_speed_mode,
.channel = LEDC_CHANNEL_0,
.intr_type = LEDC_INTR_DISABLE,
.timer_sel = LEDC_TIMER_0,
.duty = 0,
.hpoint = 0,
};
TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
ledc_timer_config_t ledc_time_config = {
.speed_mode = test_speed_mode,
.duty_resolution = LEDC_TIMER_13_BIT,
.timer_num = LEDC_TIMER_0,
.freq_hz = 5000,
.clk_cfg = LEDC_USE_APB_CLK,
};
TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
//initialize fade service.
TEST_ESP_OK(ledc_fade_func_install(0));
TEST_ESP_OK(ledc_set_fade_with_step(test_speed_mode, LEDC_CHANNEL_0, 4000, 2, 1));
TEST_ESP_OK(ledc_set_fade_with_step(test_speed_mode, LEDC_CHANNEL_0, 4000, 4, 1));
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE));
vTaskDelay(1000 / portTICK_RATE_MS);
TEST_ASSERT_EQUAL_INT32(ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0), 4000);
TEST_ASSERT_EQUAL_INT32(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
TEST_ESP_OK(ledc_set_fade_with_step(test_speed_mode, LEDC_CHANNEL_0, 0, 4, 2));
TEST_ESP_OK(ledc_set_fade_with_step(test_speed_mode, LEDC_CHANNEL_0, 0, 4, 1));
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));
vTaskDelay(1000 / portTICK_RATE_MS);
TEST_ASSERT_EQUAL_INT32(ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0), 0);
// duty should not be too far from initial value
TEST_ASSERT_INT32_WITHIN(20, 4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
vTaskDelay(525 / portTICK_PERIOD_MS);
TEST_ASSERT_EQUAL_INT32(0, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
//scaler=0 check
TEST_ASSERT(ledc_set_fade_with_step(test_speed_mode, LEDC_CHANNEL_0, 4000, 0, 1) == ESP_ERR_INVALID_ARG);
//deinitial fade service
//deinitialize fade service
ledc_fade_func_uninstall();
}
TEST_CASE("LEDC fast switching duty with fade_wait_done", "[ledc]")
{
const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
fade_setup();
// fade function will block until fading to the target duty
int64_t fade_start, fade_stop;
fade_start = esp_timer_get_time();
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 200));
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE));
TEST_ASSERT_EQUAL_INT32(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 1000, 150));
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE));
TEST_ASSERT_EQUAL_INT32(1000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
fade_stop = esp_timer_get_time();
int time_ms = (fade_stop - fade_start) / 1000;
TEST_ASSERT_TRUE(fabs(time_ms - 350) < 20);
// next duty update will not take place until last fade reaches its target duty
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 200));
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE));
TEST_ASSERT_EQUAL_INT32(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
TEST_ESP_OK(ledc_set_duty(test_speed_mode, LEDC_CHANNEL_0, 500));
TEST_ESP_OK(ledc_update_duty(test_speed_mode, LEDC_CHANNEL_0));
vTaskDelay(5 / portTICK_PERIOD_MS);
TEST_ASSERT_EQUAL_INT32(500, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
//deinitialize fade service
ledc_fade_func_uninstall();
}
TEST_CASE("LEDC fast switching duty with fade_no_wait", "[ledc]")
{
const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
fade_setup();
// fade function returns immediately, but next fade still needs to wait for last fade ends
int64_t fade_start, first_fade_complete;
fade_start = esp_timer_get_time();
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 200));
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));
TEST_ASSERT_LESS_THAN(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 1000, 150));
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));
first_fade_complete = esp_timer_get_time();
// duty should not be too far from first fade target duty
TEST_ASSERT_INT32_WITHIN(20, 4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
int time_ms = (first_fade_complete - fade_start) / 1000;
TEST_ASSERT_TRUE(fabs(time_ms - 200) < 20);
vTaskDelay(158 / portTICK_PERIOD_MS);
TEST_ASSERT_EQUAL_INT32(1000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
// next duty update will not take place until last fade reaches its target duty
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 200));
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));
TEST_ASSERT_LESS_THAN(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
TEST_ESP_OK(ledc_set_duty(test_speed_mode, LEDC_CHANNEL_0, 500));
TEST_ESP_OK(ledc_update_duty(test_speed_mode, LEDC_CHANNEL_0));
vTaskDelay(5 / portTICK_PERIOD_MS);
TEST_ASSERT_EQUAL_INT32(500, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
//deinitialize fade service
ledc_fade_func_uninstall();
}

View File

@@ -843,8 +843,8 @@ TEST_CASE("Timer interrupt register", "[hw_timer]")
// This case will check under this fix, whether the interrupt status is cleared after timer_group initialization.
static void timer_group_test_init(void)
{
static const uint32_t time_ms = 100; //Alarm value 100ms.
static const uint16_t timer_div = 10; //Timer prescaler
static const uint32_t time_ms = 100; // Alarm value 100ms.
static const uint16_t timer_div = TIMER_DIVIDER; // Timer prescaler
static const uint32_t ste_val = time_ms * (TIMER_BASE_CLK / timer_div / 1000);
timer_config_t config = {
.divider = timer_div,
@@ -882,11 +882,45 @@ static void timer_group_test_second_stage(void)
{
TEST_ASSERT_EQUAL(ESP_RST_SW, esp_reset_reason());
timer_group_test_init();
TEST_ASSERT_EQUAL(0, timer_group_get_intr_status_in_isr(TIMER_GROUP_0) & TIMER_INTR_T0);
// After enable the interrupt, timer alarm should not trigger immediately
TEST_ESP_OK(timer_enable_intr(TIMER_GROUP_0, TIMER_0));
//After the timer_group is initialized, TIMERG0.int_raw.t0 should be cleared.
TEST_ASSERT_EQUAL(0, timer_group_get_intr_status_in_isr(TIMER_GROUP_0) & TIMER_INTR_T0);
}
TEST_CASE_MULTIPLE_STAGES("timer_group software reset test",
"[intr_status][intr_status = 0]",
timer_group_test_first_stage,
timer_group_test_second_stage);
"[intr_status][intr_status = 0]",
timer_group_test_first_stage,
timer_group_test_second_stage);
//
// Timer check reinitialization sequence
//
TEST_CASE("Timer check reinitialization sequence", "[hw_timer]")
{
// 1. step - install driver
timer_group_test_init();
// 2 - register interrupt and start timer
TEST_ESP_OK(timer_enable_intr(TIMER_GROUP_0, TIMER_0));
TEST_ESP_OK(timer_start(TIMER_GROUP_0, TIMER_0));
// Do some work
vTaskDelay(80 / portTICK_PERIOD_MS);
// 3 - deinit timer driver
TEST_ESP_OK(timer_deinit(TIMER_GROUP_0, TIMER_0));
timer_config_t config = {
.divider = TIMER_DIVIDER,
.counter_dir = TIMER_COUNT_UP,
.counter_en = TIMER_START,
.alarm_en = TIMER_ALARM_EN,
.intr_type = TIMER_INTR_LEVEL,
.auto_reload = TIMER_AUTORELOAD_EN,
};
// 4 - reinstall driver
TEST_ESP_OK(timer_init(TIMER_GROUP_0, TIMER_0, &config));
// 5 - enable interrupt
TEST_ESP_OK(timer_enable_intr(TIMER_GROUP_0, TIMER_0));
vTaskDelay(30 / portTICK_PERIOD_MS);
// The pending timer interrupt should not be triggered
TEST_ASSERT_EQUAL(0, timer_group_get_intr_status_in_isr(TIMER_GROUP_0) & TIMER_INTR_T0);
}

View File

@@ -320,7 +320,7 @@ esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, const timer
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
timer_hal_init(&(p_timer_obj[group_num][timer_num]->hal), group_num, timer_num);
timer_hal_intr_disable(&(p_timer_obj[group_num][timer_num]->hal));
timer_hal_reset_periph(&(p_timer_obj[group_num][timer_num]->hal));
timer_hal_clear_intr_status(&(p_timer_obj[group_num][timer_num]->hal));
timer_hal_set_auto_reload(&(p_timer_obj[group_num][timer_num]->hal), config->auto_reload);
timer_hal_set_divider(&(p_timer_obj[group_num][timer_num]->hal), config->divider);

View File

@@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "soc/soc_caps.h"
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
@@ -28,6 +27,7 @@
#include "driver/gpio.h"
#include "driver/periph_ctrl.h"
#include "driver/twai.h"
#include "soc/soc_caps.h"
#include "soc/twai_periph.h"
#include "hal/twai_hal.h"
@@ -57,14 +57,6 @@
#define DRIVER_DEFAULT_INTERRUPTS 0xE7 //Exclude data overrun (bit[3]) and brp_div (bit[4])
//Control flags
#define CTRL_FLAG_STOPPED 0x001 //TWAI peripheral in stopped state
#define CTRL_FLAG_RECOVERING 0x002 //Bus is undergoing bus recovery
#define CTRL_FLAG_ERR_WARN 0x004 //TEC or REC is >= error warning limit
#define CTRL_FLAG_ERR_PASSIVE 0x008 //TEC or REC is >= 128
#define CTRL_FLAG_BUS_OFF 0x010 //Bus-off due to TEC >= 256
#define CTRL_FLAG_TX_BUFF_OCCUPIED 0x020 //Transmit buffer is occupied
#define ALERT_LOG_LEVEL_WARNING TWAI_ALERT_ARB_LOST //Alerts above and including this level use ESP_LOGW
#define ALERT_LOG_LEVEL_ERROR TWAI_ALERT_TX_FAILED //Alerts above and including this level use ESP_LOGE
@@ -73,9 +65,10 @@
//Control structure for TWAI driver
typedef struct {
//Control and status members
uint32_t control_flags;
twai_state_t state;
twai_mode_t mode;
uint32_t rx_missed_count;
uint32_t rx_overrun_count;
uint32_t tx_failed_count;
uint32_t arb_lost_count;
uint32_t bus_error_count;
@@ -129,102 +122,55 @@ TWAI_ISR_ATTR static void twai_alert_handler(uint32_t alert_code, int *alert_req
ESP_EARLY_LOGI(TWAI_TAG, "Alert %d", alert_code);
}
}
#endif
#endif //CONFIG_TWAI_ISR_IN_IRAM
}
}
static inline void twai_handle_bus_off(int *alert_req)
{
//Bus-Off condition. TEC should set and held at 127, REC should be 0, reset mode entered
TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_BUS_OFF);
/* Note: REC is still allowed to increase during bus-off. REC > err_warn
can prevent "bus recovery complete" interrupt from occurring. Set to
listen only mode to freeze REC. */
twai_hal_handle_bus_off(&twai_context);
twai_alert_handler(TWAI_ALERT_BUS_OFF, alert_req);
}
static inline void twai_handle_recovery_complete(int *alert_req)
{
//Bus recovery complete.
bool recov_cplt = twai_hal_handle_bus_recov_cplt(&twai_context);
assert(recov_cplt);
//Reset and set flags to the equivalent of the stopped state
TWAI_RESET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_RECOVERING | CTRL_FLAG_ERR_WARN |
CTRL_FLAG_ERR_PASSIVE | CTRL_FLAG_BUS_OFF |
CTRL_FLAG_TX_BUFF_OCCUPIED);
TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_STOPPED);
twai_alert_handler(TWAI_ALERT_BUS_RECOVERED, alert_req);
}
static inline void twai_handle_recovery_in_progress(int * alert_req)
{
//Bus-recovery in progress. TEC has dropped below error warning limit
twai_alert_handler(TWAI_ALERT_RECOVERY_IN_PROGRESS, alert_req);
}
static inline void twai_handle_above_ewl(int *alert_req)
{
//TEC or REC surpassed error warning limit
TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_ERR_WARN);
twai_alert_handler(TWAI_ALERT_ABOVE_ERR_WARN, alert_req);
}
static inline void twai_handle_below_ewl(int *alert_req)
{
//TEC and REC are both below error warning
TWAI_RESET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_ERR_WARN);
twai_alert_handler(TWAI_ALERT_BELOW_ERR_WARN, alert_req);
}
static inline void twai_handle_error_passive(int *alert_req)
{
//Entered error passive
TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_ERR_PASSIVE);
twai_alert_handler(TWAI_ALERT_ERR_PASS, alert_req);
}
static inline void twai_handle_error_active(int *alert_req)
{
//Returned to error active
TWAI_RESET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_ERR_PASSIVE);
twai_alert_handler(TWAI_ALERT_ERR_ACTIVE, alert_req);
}
static inline void twai_handle_bus_error(int *alert_req)
{
// ECC register is read to re-arm bus error interrupt. ECC is not used
twai_hal_handle_bus_error(&twai_context);
p_twai_obj->bus_error_count++;
twai_alert_handler(TWAI_ALERT_BUS_ERROR, alert_req);
}
static inline void twai_handle_arb_lost(int *alert_req)
{
//ALC register is read to re-arm arb lost interrupt. ALC is not used
twai_hal_handle_arb_lost(&twai_context);
p_twai_obj->arb_lost_count++;
twai_alert_handler(TWAI_ALERT_ARB_LOST, alert_req);
}
static inline void twai_handle_rx_buffer_frames(BaseType_t *task_woken, int *alert_req)
{
#ifdef TWAI_SUPPORTS_RX_STATUS
uint32_t msg_count = twai_hal_get_rx_msg_count(&twai_context);
for (int i = 0; i < msg_count; i++) {
for (uint32_t i = 0; i < msg_count; i++) {
twai_hal_frame_t frame;
twai_hal_read_rx_buffer_and_clear(&twai_context, &frame);
//Copy frame into RX Queue
if (xQueueSendFromISR(p_twai_obj->rx_queue, &frame, task_woken) == pdTRUE) {
p_twai_obj->rx_msg_count++;
} else {
p_twai_obj->rx_missed_count++;
twai_alert_handler(TWAI_ALERT_RX_QUEUE_FULL, alert_req);
if (twai_hal_read_rx_buffer_and_clear(&twai_context, &frame)) {
//Valid frame copied from RX buffer
if (xQueueSendFromISR(p_twai_obj->rx_queue, &frame, task_woken) == pdTRUE) {
p_twai_obj->rx_msg_count++;
} else { //Failed to send to queue
p_twai_obj->rx_missed_count++;
twai_alert_handler(TWAI_ALERT_RX_QUEUE_FULL, alert_req);
}
} else { //Failed to read from RX buffer because message is overrun
p_twai_obj->rx_overrun_count++;
twai_alert_handler(TWAI_ALERT_RX_FIFO_OVERRUN, alert_req);
}
}
//Todo: Add Software Filters
//Todo: Check for data overrun of RX FIFO, then trigger alert
#else //TWAI_SUPPORTS_RX_STATUS
uint32_t msg_count = twai_hal_get_rx_msg_count(&twai_context);
bool overrun = false;
//Clear all valid RX frames
for (int i = 0; i < msg_count; i++) {
twai_hal_frame_t frame;
if (twai_hal_read_rx_buffer_and_clear(&twai_context, &frame)) {
//Valid frame copied from RX buffer
if (xQueueSendFromISR(p_twai_obj->rx_queue, &frame, task_woken) == pdTRUE) {
p_twai_obj->rx_msg_count++;
} else {
p_twai_obj->rx_missed_count++;
twai_alert_handler(TWAI_ALERT_RX_QUEUE_FULL, alert_req);
}
} else {
overrun = true;
break;
}
}
//All remaining frames are treated as overrun. Clear them all
if (overrun) {
p_twai_obj->rx_overrun_count += twai_hal_clear_rx_fifo_overrun(&twai_context);
twai_alert_handler(TWAI_ALERT_RX_FIFO_OVERRUN, alert_req);
}
#endif //TWAI_SUPPORTS_RX_STATUS
}
static inline void twai_handle_tx_buffer_frame(BaseType_t *task_woken, int *alert_req)
@@ -252,7 +198,6 @@ static inline void twai_handle_tx_buffer_frame(BaseType_t *task_woken, int *aler
}
} else {
//No more frames to transmit
TWAI_RESET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_TX_BUFF_OCCUPIED);
twai_alert_handler(TWAI_ALERT_TX_IDLE, alert_req);
}
}
@@ -261,49 +206,69 @@ TWAI_ISR_ATTR static void twai_intr_handler_main(void *arg)
{
BaseType_t task_woken = pdFALSE;
int alert_req = 0;
uint32_t event;
uint32_t events;
TWAI_ENTER_CRITICAL_ISR();
if (p_twai_obj == NULL) { //Incase intr occurs whilst driver is being uninstalled
if (p_twai_obj == NULL) { //In case intr occurs whilst driver is being uninstalled
TWAI_EXIT_CRITICAL_ISR();
return;
}
event = twai_hal_decode_interrupt_events(&twai_context, p_twai_obj->control_flags & CTRL_FLAG_RECOVERING);
events = twai_hal_get_events(&twai_context); //Get the events that triggered the interrupt
if (event & TWAI_HAL_EVENT_BUS_OFF) {
twai_handle_bus_off(&alert_req);
#if defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || defined(CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT)
if (events & TWAI_HAL_EVENT_NEED_PERIPH_RESET) {
twai_hal_prepare_for_reset(&twai_context);
periph_module_reset(PERIPH_TWAI_MODULE);
twai_hal_recover_from_reset(&twai_context);
p_twai_obj->rx_missed_count += twai_hal_get_reset_lost_rx_cnt(&twai_context);
twai_alert_handler(TWAI_ALERT_PERIPH_RESET, &alert_req);
}
if (event & TWAI_HAL_EVENT_BUS_RECOV_CPLT) {
twai_handle_recovery_complete(&alert_req);
}
if (event & TWAI_HAL_EVENT_BUS_RECOV_PROGRESS) {
twai_handle_recovery_in_progress(&alert_req);
}
if (event & TWAI_HAL_EVENT_ABOVE_EWL) {
twai_handle_above_ewl(&alert_req);
}
if (event & TWAI_HAL_EVENT_BELOW_EWL) {
twai_handle_below_ewl(&alert_req);
}
if (event & TWAI_HAL_EVENT_ERROR_PASSIVE) {
twai_handle_error_passive(&alert_req);
}
if (event & TWAI_HAL_EVENT_ERROR_ACTIVE) {
twai_handle_error_active(&alert_req);
}
if (event & TWAI_HAL_EVENT_BUS_ERR) {
twai_handle_bus_error(&alert_req);
}
if (event & TWAI_HAL_EVENT_ARB_LOST) {
twai_handle_arb_lost(&alert_req);
}
if (event & TWAI_HAL_EVENT_RX_BUFF_FRAME) {
#endif
if (events & TWAI_HAL_EVENT_RX_BUFF_FRAME) {
//Note: This event will never occur if there is a periph reset event
twai_handle_rx_buffer_frames(&task_woken, &alert_req);
}
//TX command related handlers should be called last, so that other commands
//do not overwrite the TX command related bits in the command register.
if (event & TWAI_HAL_EVENT_TX_BUFF_FREE) {
if (events & TWAI_HAL_EVENT_TX_BUFF_FREE) {
twai_handle_tx_buffer_frame(&task_woken, &alert_req);
}
//Handle events that only require alerting (i.e. no handler)
if (events & TWAI_HAL_EVENT_BUS_OFF) {
p_twai_obj->state = TWAI_STATE_BUS_OFF;
twai_alert_handler(TWAI_ALERT_BUS_OFF, &alert_req);
}
if (events & TWAI_HAL_EVENT_BUS_RECOV_CPLT) {
p_twai_obj->state = TWAI_STATE_STOPPED;
twai_alert_handler(TWAI_ALERT_BUS_RECOVERED, &alert_req);
}
if (events & TWAI_HAL_EVENT_BUS_ERR) {
p_twai_obj->bus_error_count++;
twai_alert_handler(TWAI_ALERT_BUS_ERROR, &alert_req);
}
if (events & TWAI_HAL_EVENT_ARB_LOST) {
p_twai_obj->arb_lost_count++;
twai_alert_handler(TWAI_ALERT_ARB_LOST, &alert_req);
}
if (events & TWAI_HAL_EVENT_BUS_RECOV_PROGRESS) {
//Bus-recovery in progress. TEC has dropped below error warning limit
twai_alert_handler(TWAI_ALERT_RECOVERY_IN_PROGRESS, &alert_req);
}
if (events & TWAI_HAL_EVENT_ERROR_PASSIVE) {
//Entered error passive
twai_alert_handler(TWAI_ALERT_ERR_PASS, &alert_req);
}
if (events & TWAI_HAL_EVENT_ERROR_ACTIVE) {
//Returned to error active
twai_alert_handler(TWAI_ALERT_ERR_ACTIVE, &alert_req);
}
if (events & TWAI_HAL_EVENT_ABOVE_EWL) {
//TEC or REC surpassed error warning limit
twai_alert_handler(TWAI_ALERT_ABOVE_ERR_WARN, &alert_req);
}
if (events & TWAI_HAL_EVENT_BELOW_EWL) {
//TEC and REC are both below error warning
twai_alert_handler(TWAI_ALERT_BELOW_ERR_WARN, &alert_req);
}
TWAI_EXIT_CRITICAL_ISR();
if (p_twai_obj->alert_semphr != NULL && alert_req) {
@@ -335,6 +300,7 @@ static void twai_configure_gpio(gpio_num_t tx, gpio_num_t rx, gpio_num_t clkout,
gpio_set_pull_mode(clkout, GPIO_FLOATING);
gpio_matrix_out(clkout, TWAI_CLKOUT_IDX, false, false);
gpio_pad_select_gpio(clkout);
}
//Configure bus status pin (Optional)
@@ -433,6 +399,8 @@ cleanup:
return NULL;
}
/* ---------------------------- Public Functions ---------------------------- */
esp_err_t twai_driver_install(const twai_general_config_t *g_config, const twai_timing_config_t *t_config, const twai_filter_config_t *f_config)
@@ -464,7 +432,7 @@ esp_err_t twai_driver_install(const twai_general_config_t *g_config, const twai_
TWAI_CHECK(p_twai_obj_dummy != NULL, ESP_ERR_NO_MEM);
//Initialize flags and variables. All other members are already set to zero by twai_alloc_driver_obj()
p_twai_obj_dummy->control_flags = CTRL_FLAG_STOPPED;
p_twai_obj_dummy->state = TWAI_STATE_STOPPED;
p_twai_obj_dummy->mode = g_config->mode;
p_twai_obj_dummy->alerts_enabled = g_config->alerts_enabled;
@@ -483,7 +451,6 @@ esp_err_t twai_driver_install(const twai_general_config_t *g_config, const twai_
bool init = twai_hal_init(&twai_context);
assert(init);
twai_hal_configure(&twai_context, t_config, f_config, DRIVER_DEFAULT_INTERRUPTS, g_config->clkout_divider);
//Todo: Allow interrupt to be registered to specified CPU
TWAI_EXIT_CRITICAL();
//Allocate GPIO and Interrupts
@@ -496,7 +463,6 @@ esp_err_t twai_driver_install(const twai_general_config_t *g_config, const twai_
return ESP_OK; //TWAI module is still in reset mode, users need to call twai_start() afterwards
err:
//Free can driver object
twai_free_driver_obj(p_twai_obj_dummy);
return ret;
}
@@ -508,8 +474,7 @@ esp_err_t twai_driver_uninstall(void)
TWAI_ENTER_CRITICAL();
//Check state
TWAI_CHECK_FROM_CRIT(p_twai_obj != NULL, ESP_ERR_INVALID_STATE);
TWAI_CHECK_FROM_CRIT(p_twai_obj->control_flags & (CTRL_FLAG_STOPPED | CTRL_FLAG_BUS_OFF), ESP_ERR_INVALID_STATE);
//Todo: Add check to see if in reset mode. //Enter reset mode to stop any TWAI bus activity
TWAI_CHECK_FROM_CRIT(p_twai_obj->state == TWAI_STATE_STOPPED || p_twai_obj->state == TWAI_STATE_BUS_OFF, ESP_ERR_INVALID_STATE);
//Clear registers by reading
twai_hal_deinit(&twai_context);
periph_module_disable(PERIPH_TWAI_MODULE); //Disable TWAI peripheral
@@ -533,18 +498,18 @@ esp_err_t twai_start(void)
//Check state
TWAI_ENTER_CRITICAL();
TWAI_CHECK_FROM_CRIT(p_twai_obj != NULL, ESP_ERR_INVALID_STATE);
TWAI_CHECK_FROM_CRIT(p_twai_obj->control_flags & CTRL_FLAG_STOPPED, ESP_ERR_INVALID_STATE);
TWAI_CHECK_FROM_CRIT(p_twai_obj->state == TWAI_STATE_STOPPED, ESP_ERR_INVALID_STATE);
//Reset RX queue, and RX message count
//Reset RX queue, RX message count, amd TX queue
xQueueReset(p_twai_obj->rx_queue);
if (p_twai_obj->tx_queue != NULL) {
xQueueReset(p_twai_obj->tx_queue);
}
p_twai_obj->rx_msg_count = 0;
//Todo: Add assert to see if in reset mode. //Should already be in bus-off mode, set again to make sure
p_twai_obj->tx_msg_count = 0;
twai_hal_start(&twai_context, p_twai_obj->mode);
//Currently in listen only mode, need to set to mode specified by configuration
bool started = twai_hal_start(&twai_context, p_twai_obj->mode);
assert(started);
TWAI_RESET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_STOPPED);
p_twai_obj->state = TWAI_STATE_RUNNING;
TWAI_EXIT_CRITICAL();
return ESP_OK;
}
@@ -554,19 +519,16 @@ esp_err_t twai_stop(void)
//Check state
TWAI_ENTER_CRITICAL();
TWAI_CHECK_FROM_CRIT(p_twai_obj != NULL, ESP_ERR_INVALID_STATE);
TWAI_CHECK_FROM_CRIT(!(p_twai_obj->control_flags & (CTRL_FLAG_STOPPED | CTRL_FLAG_BUS_OFF)), ESP_ERR_INVALID_STATE);
TWAI_CHECK_FROM_CRIT(p_twai_obj->state == TWAI_STATE_RUNNING, ESP_ERR_INVALID_STATE);
bool stopped = twai_hal_stop(&twai_context);
assert(stopped);
TWAI_RESET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_TX_BUFF_OCCUPIED);
TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_STOPPED);
twai_hal_stop(&twai_context);
//Reset TX Queue and message count
if (p_twai_obj->tx_queue != NULL) {
xQueueReset(p_twai_obj->tx_queue);
}
p_twai_obj->tx_msg_count = 0;
p_twai_obj->state = TWAI_STATE_STOPPED;
TWAI_EXIT_CRITICAL();
@@ -583,18 +545,17 @@ esp_err_t twai_transmit(const twai_message_t *message, TickType_t ticks_to_wait)
TWAI_ENTER_CRITICAL();
//Check State
TWAI_CHECK_FROM_CRIT(!(p_twai_obj->mode == TWAI_MODE_LISTEN_ONLY), ESP_ERR_NOT_SUPPORTED);
TWAI_CHECK_FROM_CRIT(!(p_twai_obj->control_flags & (CTRL_FLAG_STOPPED | CTRL_FLAG_BUS_OFF)), ESP_ERR_INVALID_STATE);
TWAI_CHECK_FROM_CRIT(p_twai_obj->state == TWAI_STATE_RUNNING, ESP_ERR_INVALID_STATE);
//Format frame
esp_err_t ret = ESP_FAIL;
twai_hal_frame_t tx_frame;
twai_hal_format_frame(message, &tx_frame);
//Check if frame can be sent immediately
if ((p_twai_obj->tx_msg_count == 0) && !(p_twai_obj->control_flags & CTRL_FLAG_TX_BUFF_OCCUPIED)) {
if (p_twai_obj->tx_msg_count == 0) {
//No other frames waiting to transmit. Bypass queue and transmit immediately
twai_hal_set_tx_buffer_and_transmit(&twai_context, &tx_frame);
p_twai_obj->tx_msg_count++;
TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_TX_BUFF_OCCUPIED);
ret = ESP_OK;
}
TWAI_EXIT_CRITICAL();
@@ -606,19 +567,19 @@ esp_err_t twai_transmit(const twai_message_t *message, TickType_t ticks_to_wait)
} else if (xQueueSend(p_twai_obj->tx_queue, &tx_frame, ticks_to_wait) == pdTRUE) {
//Copied to TX Queue
TWAI_ENTER_CRITICAL();
if (p_twai_obj->control_flags & (CTRL_FLAG_STOPPED | CTRL_FLAG_BUS_OFF)) {
//TX queue was reset (due to stop/bus_off), remove copied frame from queue to prevent transmission
int res = xQueueReceive(p_twai_obj->tx_queue, &tx_frame, 0);
assert(res == pdTRUE);
ret = ESP_ERR_INVALID_STATE;
} else if ((p_twai_obj->tx_msg_count == 0) && !(p_twai_obj->control_flags & CTRL_FLAG_TX_BUFF_OCCUPIED)) {
//TX buffer was freed during copy, manually trigger transmission
int res = xQueueReceive(p_twai_obj->tx_queue, &tx_frame, 0);
assert(res == pdTRUE);
twai_hal_set_tx_buffer_and_transmit(&twai_context, &tx_frame);
p_twai_obj->tx_msg_count++;
TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_TX_BUFF_OCCUPIED);
ret = ESP_OK;
if ((!twai_hal_check_state_flags(&twai_context, TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED)) && uxQueueMessagesWaiting(p_twai_obj->tx_queue) > 0) {
//If the TX buffer is free but the TX queue is not empty. Check if we need to manually start a transmission
if (twai_hal_check_state_flags(&twai_context, TWAI_HAL_STATE_FLAG_BUS_OFF) || !twai_hal_check_state_flags(&twai_context, TWAI_HAL_STATE_FLAG_RUNNING)) {
//TX buffer became free due to bus-off or is no longer running. No need to start a transmission
ret = ESP_ERR_INVALID_STATE;
} else {
//Manually start a transmission
int res = xQueueReceive(p_twai_obj->tx_queue, &tx_frame, 0);
assert(res == pdTRUE);
twai_hal_set_tx_buffer_and_transmit(&twai_context, &tx_frame);
p_twai_obj->tx_msg_count++;
ret = ESP_OK;
}
} else {
//Frame was copied to queue, waiting to be transmitted
p_twai_obj->tx_msg_count++;
@@ -694,20 +655,17 @@ esp_err_t twai_initiate_recovery(void)
TWAI_ENTER_CRITICAL();
//Check state
TWAI_CHECK_FROM_CRIT(p_twai_obj != NULL, ESP_ERR_INVALID_STATE);
TWAI_CHECK_FROM_CRIT(p_twai_obj->control_flags & CTRL_FLAG_BUS_OFF, ESP_ERR_INVALID_STATE);
TWAI_CHECK_FROM_CRIT(!(p_twai_obj->control_flags & CTRL_FLAG_RECOVERING), ESP_ERR_INVALID_STATE);
TWAI_CHECK_FROM_CRIT(p_twai_obj->state == TWAI_STATE_BUS_OFF, ESP_ERR_INVALID_STATE);
//Reset TX Queue/Counters
if (p_twai_obj->tx_queue != NULL) {
xQueueReset(p_twai_obj->tx_queue);
}
p_twai_obj->tx_msg_count = 0;
TWAI_RESET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_TX_BUFF_OCCUPIED);
TWAI_SET_FLAG(p_twai_obj->control_flags, CTRL_FLAG_RECOVERING);
//Trigger start of recovery process
bool started = twai_hal_start_bus_recovery(&twai_context);
assert(started);
twai_hal_start_bus_recovery(&twai_context);
p_twai_obj->state = TWAI_STATE_RECOVERING;
TWAI_EXIT_CRITICAL();
return ESP_OK;
@@ -726,17 +684,10 @@ esp_err_t twai_get_status_info(twai_status_info_t *status_info)
status_info->msgs_to_rx = p_twai_obj->rx_msg_count;
status_info->tx_failed_count = p_twai_obj->tx_failed_count;
status_info->rx_missed_count = p_twai_obj->rx_missed_count;
status_info->rx_overrun_count = p_twai_obj->rx_overrun_count;
status_info->arb_lost_count = p_twai_obj->arb_lost_count;
status_info->bus_error_count = p_twai_obj->bus_error_count;
if (p_twai_obj->control_flags & CTRL_FLAG_RECOVERING) {
status_info->state = TWAI_STATE_RECOVERING;
} else if (p_twai_obj->control_flags & CTRL_FLAG_BUS_OFF) {
status_info->state = TWAI_STATE_BUS_OFF;
} else if (p_twai_obj->control_flags & CTRL_FLAG_STOPPED) {
status_info->state = TWAI_STATE_STOPPED;
} else {
status_info->state = TWAI_STATE_RUNNING;
}
status_info->state = p_twai_obj->state;
TWAI_EXIT_CRITICAL();
return ESP_OK;
@@ -750,7 +701,7 @@ esp_err_t twai_clear_transmit_queue(void)
TWAI_ENTER_CRITICAL();
//If a message is currently undergoing transmission, the tx interrupt handler will decrement tx_msg_count
p_twai_obj->tx_msg_count = (p_twai_obj->control_flags & CTRL_FLAG_TX_BUFF_OCCUPIED) ? 1 : 0;
p_twai_obj->tx_msg_count = twai_hal_check_state_flags(&twai_context, TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED) ? 1 : 0;
xQueueReset(p_twai_obj->tx_queue);
TWAI_EXIT_CRITICAL();

View File

@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string.h>
#include <sys/param.h>
#include "esp_types.h"
#include "esp_attr.h"
#include "esp_intr_alloc.h"
@@ -68,6 +69,9 @@ static const char *UART_TAG = "uart";
| (UART_INTR_BRK_DET) \
| (UART_INTR_PARITY_ERR))
#define UART_ENTER_CRITICAL_SAFE(mux) portENTER_CRITICAL_SAFE(mux)
#define UART_EXIT_CRITICAL_SAFE(mux) portEXIT_CRITICAL_SAFE(mux)
#define UART_ENTER_CRITICAL_ISR(mux) portENTER_CRITICAL_ISR(mux)
#define UART_EXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL_ISR(mux)
#define UART_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux)
@@ -695,6 +699,19 @@ static int UART_ISR_ATTR uart_find_pattern_from_last(uint8_t *buf, int length, u
return len;
}
static uint32_t UART_ISR_ATTR uart_enable_tx_write_fifo(uart_port_t uart_num, const uint8_t *pbuf, uint32_t len)
{
uint32_t sent_len = 0;
UART_ENTER_CRITICAL_SAFE(&(uart_context[uart_num].spinlock));
if (UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX)) {
uart_hal_set_rts(&(uart_context[uart_num].hal), 0);
uart_hal_ena_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
}
uart_hal_write_txfifo(&(uart_context[uart_num].hal), pbuf, len, &sent_len);
UART_EXIT_CRITICAL_SAFE(&(uart_context[uart_num].spinlock));
return sent_len;
}
//internal isr handler for default driver code.
static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
{
@@ -764,19 +781,9 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
}
}
if (p_uart->tx_len_tot > 0 && p_uart->tx_ptr && p_uart->tx_len_cur > 0) {
//To fill the TX FIFO.
uint32_t send_len = 0;
// Set RS485 RTS pin before transmission if the half duplex mode is enabled
if (UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX)) {
UART_ENTER_CRITICAL_ISR(&(uart_context[uart_num].spinlock));
uart_hal_set_rts(&(uart_context[uart_num].hal), 0);
uart_hal_ena_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
UART_EXIT_CRITICAL_ISR(&(uart_context[uart_num].spinlock));
}
uart_hal_write_txfifo(&(uart_context[uart_num].hal),
(const uint8_t *)p_uart->tx_ptr,
(p_uart->tx_len_cur > tx_fifo_rem) ? tx_fifo_rem : p_uart->tx_len_cur,
&send_len);
// To fill the TX FIFO.
uint32_t send_len = uart_enable_tx_write_fifo(uart_num, (const uint8_t *) p_uart->tx_ptr,
MIN(p_uart->tx_len_cur, tx_fifo_rem));
p_uart->tx_ptr += send_len;
p_uart->tx_len_tot -= send_len;
p_uart->tx_len_cur -= send_len;
@@ -980,6 +987,7 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
// Workaround for RS485: If the RS485 half duplex mode is active
// and transmitter is in idle state then reset received buffer and reset RTS pin
// skip this behavior for other UART modes
uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
UART_ENTER_CRITICAL_ISR(&(uart_context[uart_num].spinlock));
uart_hal_disable_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
if (UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX)) {
@@ -987,7 +995,6 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
uart_hal_set_rts(&(uart_context[uart_num].hal), 1);
}
UART_EXIT_CRITICAL_ISR(&(uart_context[uart_num].spinlock));
uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
xSemaphoreGiveFromISR(p_uart_obj[uart_num]->tx_done_sem, &HPTaskAwoken);
}
} else {
@@ -1056,13 +1063,7 @@ int uart_tx_chars(uart_port_t uart_num, const char *buffer, uint32_t len)
}
int tx_len = 0;
xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY);
if (UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX)) {
UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock));
uart_hal_set_rts(&(uart_context[uart_num].hal), 0);
uart_hal_ena_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock));
}
uart_hal_write_txfifo(&(uart_context[uart_num].hal), (const uint8_t *) buffer, len, (uint32_t *)&tx_len);
tx_len = (int)uart_enable_tx_write_fifo(uart_num, (const uint8_t *) buffer, len);
xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);
return tx_len;
}
@@ -1100,14 +1101,7 @@ static int uart_tx_all(uart_port_t uart_num, const char *src, size_t size, bool
while (size) {
//semaphore for tx_fifo available
if (pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_fifo_sem, (portTickType)portMAX_DELAY)) {
uint32_t sent = 0;
if (UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX)) {
UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock));
uart_hal_set_rts(&(uart_context[uart_num].hal), 0);
uart_hal_ena_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock));
}
uart_hal_write_txfifo(&(uart_context[uart_num].hal), (const uint8_t *)src, size, &sent);
uint32_t sent = uart_enable_tx_write_fifo(uart_num, (const uint8_t *) src, size);
if (sent < size) {
p_uart_obj[uart_num]->tx_waiting_fifo = true;
uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT);

View File

@@ -18,6 +18,9 @@
extern "C" {
#endif
#define ESP_EFUSE_LEN_OF_3_4_SCHEME_BLOCK_IN_BYTES (24)
#define ESP_EFUSE_LEN_OF_REPEAT_BLOCK_IN_BYTES (16)
#define COUNT_EFUSE_REG_PER_BLOCK 8 /* The number of registers per block. */
#define ESP_EFUSE_SECURE_VERSION_NUM_BLOCK EFUSE_BLK3

View File

@@ -97,8 +97,12 @@ esp_err_t esp_efuse_utility_fill_buff(unsigned int num_reg, esp_efuse_block_t ef
*
* If CONFIG_EFUSE_VIRTUAL is set, writing will not be performed.
* After the function is completed, the writing registers are cleared.
*
* @return
* - ESP_OK: The operation was successfully completed.
* - ESP_FAIL: The operation was not successfully completed.
*/
void esp_efuse_utility_burn_efuses(void);
esp_err_t esp_efuse_utility_burn_efuses(void);
/**
* @brief Returns the number of array elements for placing these "bits" in an array with the length of each element equal to "size_of_base".
@@ -151,6 +155,19 @@ esp_err_t esp_efuse_utility_apply_new_coding_scheme(void);
*/
void esp_efuse_utility_clear_program_registers(void);
/**
* @brief Checks the correctness of burned data in the given block.
*
* @note Internal use. Do not call it.
*
* @param[in] block Index of efuse block.
* @param[in] r_data_len Block length for reading data in bytes (multiple of 4).
*
* @return True - written data are correct.
* False - written data are incorrect.
*/
bool esp_efuse_utility_is_correct_written_data(esp_efuse_block_t block, unsigned r_data_len);
#ifdef __cplusplus
}
#endif

View File

@@ -22,6 +22,8 @@
static const char *TAG = "efuse";
#define ESP_EFUSE_BLOCK_ERROR_BITS(error_reg, block) ((error_reg) & (0x0F << (4 * (block))))
#ifdef CONFIG_EFUSE_VIRTUAL
extern uint32_t virt_blocks[EFUSE_BLK_MAX][COUNT_EFUSE_REG_PER_BLOCK];
#endif // CONFIG_EFUSE_VIRTUAL
@@ -34,12 +36,14 @@ const esp_efuse_range_addr_t range_read_addr_blocks[] = {
{EFUSE_BLK3_RDATA0_REG, EFUSE_BLK3_RDATA7_REG} // range address of EFUSE_BLK3
};
/*Range addresses to write blocks*/
static uint32_t write_mass_blocks[EFUSE_BLK_MAX][COUNT_EFUSE_REG_PER_BLOCK] = { 0 };
/*Range addresses to write blocks (it is not real regs, it is a buffer) */
const esp_efuse_range_addr_t range_write_addr_blocks[] = {
{EFUSE_BLK0_WDATA0_REG, EFUSE_BLK0_WDATA6_REG}, // range address of EFUSE_BLK0
{EFUSE_BLK1_WDATA0_REG, EFUSE_BLK1_WDATA7_REG}, // range address of EFUSE_BLK1
{EFUSE_BLK2_WDATA0_REG, EFUSE_BLK2_WDATA7_REG}, // range address of EFUSE_BLK2
{EFUSE_BLK3_WDATA0_REG, EFUSE_BLK3_WDATA7_REG} // range address of EFUSE_BLK3
{(uint32_t) &write_mass_blocks[EFUSE_BLK0][0], (uint32_t) &write_mass_blocks[EFUSE_BLK0][6]},
{(uint32_t) &write_mass_blocks[EFUSE_BLK1][0], (uint32_t) &write_mass_blocks[EFUSE_BLK1][7]},
{(uint32_t) &write_mass_blocks[EFUSE_BLK2][0], (uint32_t) &write_mass_blocks[EFUSE_BLK2][7]},
{(uint32_t) &write_mass_blocks[EFUSE_BLK3][0], (uint32_t) &write_mass_blocks[EFUSE_BLK3][7]},
};
#define EFUSE_CONF_WRITE 0x5A5A /* eFuse_pgm_op_ena, force no rd/wr disable. */
@@ -48,6 +52,17 @@ const esp_efuse_range_addr_t range_write_addr_blocks[] = {
#define EFUSE_CMD_READ 0x01 /* Command to read. */
#ifndef CONFIG_EFUSE_VIRTUAL
/* Addresses to write blocks*/
const uint32_t start_write_addr[] = {
EFUSE_BLK0_WDATA0_REG,
EFUSE_BLK1_WDATA0_REG,
EFUSE_BLK2_WDATA0_REG,
EFUSE_BLK3_WDATA0_REG,
};
static void apply_repeat_encoding(const uint8_t *in_bytes, uint32_t *out_words, size_t in_bytes_len);
static void unite_write_mass_blocks_and_wr_regs(void);
// Update Efuse timing configuration
static esp_err_t esp_efuse_set_timing(void)
{
@@ -71,52 +86,149 @@ static esp_err_t esp_efuse_set_timing(void)
REG_SET_FIELD(EFUSE_CLK_REG, EFUSE_CLK_SEL1, clk_sel1);
return ESP_OK;
}
__attribute__((always_inline)) static inline bool efuse_ll_get_dec_warnings(unsigned block)
{
if (block == 0 || block > 4) {
return false;
}
uint32_t error_reg = REG_GET_FIELD(EFUSE_DEC_STATUS_REG, EFUSE_DEC_WARNINGS);
return ESP_EFUSE_BLOCK_ERROR_BITS(error_reg, block - 1) != 0;
}
bool efuse_hal_is_coding_error_in_block(unsigned block)
{
return block > 0 &&
esp_efuse_get_coding_scheme(block) == EFUSE_CODING_SCHEME_3_4 &&
efuse_ll_get_dec_warnings(block);
}
#endif // ifndef CONFIG_EFUSE_VIRTUAL
static void efuse_hal_clear_program_registers(void)
{
for (uint32_t r = EFUSE_BLK0_WDATA0_REG; r <= EFUSE_BLK0_WDATA6_REG; r += 4) {
REG_WRITE(r, 0);
}
for (uint32_t r = EFUSE_BLK1_WDATA0_REG; r <= EFUSE_BLK1_WDATA7_REG; r += 4) {
REG_WRITE(r, 0);
}
for (uint32_t r = EFUSE_BLK2_WDATA0_REG; r <= EFUSE_BLK2_WDATA7_REG; r += 4) {
REG_WRITE(r, 0);
}
for (uint32_t r = EFUSE_BLK3_WDATA0_REG; r <= EFUSE_BLK3_WDATA7_REG; r += 4) {
REG_WRITE(r, 0);
}
}
// Efuse read operation: copies data from physical efuses to efuse read registers.
void esp_efuse_utility_clear_program_registers(void)
{
REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_READ);
efuse_hal_clear_program_registers();
}
// Burn values written to the efuse write registers
void esp_efuse_utility_burn_efuses(void)
esp_err_t esp_efuse_utility_burn_efuses(void)
{
esp_err_t error = ESP_OK;
#ifdef CONFIG_EFUSE_VIRTUAL
ESP_LOGW(TAG, "Virtual efuses enabled: Not really burning eFuses");
for (int num_block = EFUSE_BLK0; num_block < EFUSE_BLK_MAX; num_block++) {
esp_efuse_coding_scheme_t scheme = esp_efuse_get_coding_scheme(num_block);
if (scheme == EFUSE_CODING_SCHEME_3_4) {
uint8_t buf[COUNT_EFUSE_REG_PER_BLOCK * 4] = { 0 };
int i = 0;
for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4, ++i) {
*((uint32_t*)buf + i) = REG_READ(addr_wr_block);
}
int j = 0;
uint32_t out_buf[COUNT_EFUSE_REG_PER_BLOCK] = { 0 };
for (int k = 0; k < 4; ++k, ++j) {
memcpy((uint8_t*)out_buf + j * 6, &buf[k * 8], 6);
}
for (int k = 0; k < COUNT_EFUSE_REG_PER_BLOCK; ++k) {
REG_WRITE(range_write_addr_blocks[num_block].start + k * 4, out_buf[k]);
}
}
for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) {
int subblock = 0;
for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) {
virt_blocks[num_block][subblock++] |= REG_READ(addr_wr_block);
}
}
#else
esp_efuse_set_timing();
// Permanently update values written to the efuse write registers
REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_WRITE);
REG_WRITE(EFUSE_CMD_REG, EFUSE_CMD_PGM);
while (REG_READ(EFUSE_CMD_REG) != 0) {};
REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_READ);
REG_WRITE(EFUSE_CMD_REG, EFUSE_CMD_READ);
while (REG_READ(EFUSE_CMD_REG) != 0) {};
#else // CONFIG_EFUSE_VIRTUAL
if (esp_efuse_set_timing() != ESP_OK) {
ESP_LOGE(TAG, "Efuse fields are not burnt");
} else {
// Support the (old) use case where data is written directly to EFUSE_BLKx_WDATA0_REG without using the eFuse API.
unite_write_mass_blocks_and_wr_regs();
// Permanently update values written to the efuse write registers
// It is necessary to process blocks in the order from MAX-> EFUSE_BLK0, because EFUSE_BLK0 has protection bits for other blocks.
for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) {
esp_efuse_coding_scheme_t scheme = esp_efuse_get_coding_scheme(num_block);
bool need_burn_block = false;
for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) {
if (REG_READ(addr_wr_block) != 0) {
need_burn_block = true;
break;
}
}
if (!need_burn_block) {
continue;
}
if (error) {
// It is done for a use case: BLOCK2 (Flash encryption key) could have an error (incorrect written data)
// in this case we can not burn any data into BLOCK0 because it might set read/write protections of BLOCK2.
ESP_LOGE(TAG, "BLOCK%d can not be burned because a previous block got an error, skipped.", num_block);
continue;
}
efuse_hal_clear_program_registers();
unsigned w_data_len;
unsigned r_data_len;
if (scheme == EFUSE_CODING_SCHEME_3_4) {
esp_efuse_utility_apply_34_encoding((void *)range_write_addr_blocks[num_block].start, (uint32_t *)start_write_addr[num_block], ESP_EFUSE_LEN_OF_3_4_SCHEME_BLOCK_IN_BYTES);
r_data_len = ESP_EFUSE_LEN_OF_3_4_SCHEME_BLOCK_IN_BYTES;
w_data_len = 32;
} else if (scheme == EFUSE_CODING_SCHEME_REPEAT) {
apply_repeat_encoding((void *)range_write_addr_blocks[num_block].start, (uint32_t *)start_write_addr[num_block], ESP_EFUSE_LEN_OF_REPEAT_BLOCK_IN_BYTES);
r_data_len = ESP_EFUSE_LEN_OF_REPEAT_BLOCK_IN_BYTES;
w_data_len = 32;
} else {
r_data_len = (range_read_addr_blocks[num_block].end - range_read_addr_blocks[num_block].start) + sizeof(uint32_t);
w_data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t);
memcpy((void *)start_write_addr[num_block], (void *)range_write_addr_blocks[num_block].start, w_data_len);
}
uint32_t backup_write_data[8];
memcpy(backup_write_data, (void *)start_write_addr[num_block], w_data_len);
int repeat_burn_op = 1;
bool correct_written_data;
bool coding_error_before = efuse_hal_is_coding_error_in_block(num_block);
if (coding_error_before) {
ESP_LOGW(TAG, "BLOCK%d already has a coding error", num_block);
}
bool coding_error_occurred;
do {
ESP_LOGI(TAG, "BURN BLOCK%d", num_block);
// BURN a block
REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_WRITE);
REG_WRITE(EFUSE_CMD_REG, EFUSE_CMD_PGM);
while (REG_READ(EFUSE_CMD_REG) != 0) {};
REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_READ);
REG_WRITE(EFUSE_CMD_REG, EFUSE_CMD_READ);
while (REG_READ(EFUSE_CMD_REG) != 0) {};
bool coding_error_after = efuse_hal_is_coding_error_in_block(num_block);
coding_error_occurred = (coding_error_before != coding_error_after) && coding_error_before == false;
if (coding_error_occurred) {
ESP_LOGW(TAG, "BLOCK%d got a coding error", num_block);
}
correct_written_data = esp_efuse_utility_is_correct_written_data(num_block, r_data_len);
if (!correct_written_data || coding_error_occurred) {
ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op);
memcpy((void *)start_write_addr[num_block], (void *)backup_write_data, w_data_len);
}
} while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3);
if (coding_error_occurred) {
ESP_LOGW(TAG, "Coding error was not fixed");
}
if (!correct_written_data) {
ESP_LOGE(TAG, "Written data are incorrect");
error = ESP_FAIL;
}
}
}
#endif // CONFIG_EFUSE_VIRTUAL
esp_efuse_utility_reset();
return error;
}
esp_err_t esp_efuse_utility_apply_34_encoding(const uint8_t *in_bytes, uint32_t *out_words, size_t in_bytes_len)
@@ -148,20 +260,27 @@ esp_err_t esp_efuse_utility_apply_34_encoding(const uint8_t *in_bytes, uint32_t
return ESP_OK;
}
static bool read_w_data_and_check_fill(esp_efuse_block_t num_block, uint32_t *buf_w_data)
#ifndef CONFIG_EFUSE_VIRTUAL
static void unite_write_mass_blocks_and_wr_regs(void)
{
bool blk_is_filled = false;
int i = 0;
for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4, ++i) {
buf_w_data[i] = REG_READ(addr_wr_block);
if (buf_w_data[i] != 0) {
REG_WRITE(addr_wr_block, 0);
blk_is_filled = true;
for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) {
uint32_t wr_reg = start_write_addr[num_block];
for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) {
REG_WRITE(addr_wr_block, REG_READ(addr_wr_block) | REG_READ(wr_reg));
wr_reg += 4;
}
}
return blk_is_filled;
esp_efuse_utility_clear_program_registers();
}
static void apply_repeat_encoding(const uint8_t *in_bytes, uint32_t *out_words, size_t in_bytes_len)
{
for (unsigned i = 0; i < 2; i++) {
memcpy(&out_words[i * 4], (uint32_t *)in_bytes, in_bytes_len);
}
}
#endif // CONFIG_EFUSE_VIRTUAL
static void read_r_data(esp_efuse_block_t num_block, uint32_t* buf_r_data)
{
int i = 0;
@@ -170,27 +289,30 @@ static void read_r_data(esp_efuse_block_t num_block, uint32_t* buf_r_data)
}
}
// After esp_efuse_write.. functions EFUSE_BLKx_WDATAx_REG were filled is not coded values.
// This function reads EFUSE_BLKx_WDATAx_REG registers, applies coding scheme and writes encoded values back to EFUSE_BLKx_WDATAx_REG.
// This function just checkes that given data for blocks will not rise a coding issue during the burn operation.
// Encoded data will be set during the burn operation.
esp_err_t esp_efuse_utility_apply_new_coding_scheme()
{
uint8_t buf_w_data[COUNT_EFUSE_REG_PER_BLOCK * 4];
uint8_t buf_r_data[COUNT_EFUSE_REG_PER_BLOCK * 4];
uint32_t reg[COUNT_EFUSE_REG_PER_BLOCK];
// start with EFUSE_BLK1. EFUSE_BLK0 - always uses EFUSE_CODING_SCHEME_NONE.
for (int num_block = EFUSE_BLK1; num_block < EFUSE_BLK_MAX; num_block++) {
esp_efuse_coding_scheme_t scheme = esp_efuse_get_coding_scheme(num_block);
// check and apply a new coding scheme.
if (scheme != EFUSE_CODING_SCHEME_NONE) {
memset(buf_w_data, 0, sizeof(buf_w_data));
memset((uint8_t*)reg, 0, sizeof(reg));
if (read_w_data_and_check_fill(num_block, (uint32_t*)buf_w_data) == true) {
bool is_write_data = false;
for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) {
if (REG_READ(addr_wr_block)) {
is_write_data = true;
break;
}
}
if (is_write_data) {
read_r_data(num_block, (uint32_t*)buf_r_data);
uint8_t* buf_w_data = (uint8_t*)range_write_addr_blocks[num_block].start;
if (scheme == EFUSE_CODING_SCHEME_3_4) {
if (*((uint32_t*)buf_w_data + 6) != 0 || *((uint32_t*)buf_w_data + 7) != 0) {
return ESP_ERR_CODING;
}
for (int i = 0; i < 24; ++i) {
for (int i = 0; i < ESP_EFUSE_LEN_OF_3_4_SCHEME_BLOCK_IN_BYTES; ++i) {
if (buf_w_data[i] != 0) {
int st_offset_buf = (i / 6) * 6;
// check that place is free.
@@ -200,32 +322,14 @@ esp_err_t esp_efuse_utility_apply_new_coding_scheme()
return ESP_ERR_CODING;
}
}
esp_err_t err = esp_efuse_utility_apply_34_encoding(&buf_w_data[st_offset_buf], reg, 6);
if (err != ESP_OK) {
return err;
}
int num_reg = (st_offset_buf / 6) * 2;
for (int r = 0; r < 2; r++) {
REG_WRITE(range_write_addr_blocks[num_block].start + (num_reg + r) * 4, reg[r]);
}
i = st_offset_buf + 5;
}
}
} else if (scheme == EFUSE_CODING_SCHEME_REPEAT) {
uint32_t* buf_32 = (uint32_t*)buf_w_data;
for (int i = 4; i < 8; ++i) {
if (*(buf_32 + i) != 0) {
if (*((uint32_t*)buf_w_data + i) != 0) {
return ESP_ERR_CODING;
}
}
for (int i = 0; i < 4; ++i) {
if (buf_32[i] != 0) {
REG_WRITE(range_write_addr_blocks[num_block].start + i * 4, buf_32[i]);
REG_WRITE(range_write_addr_blocks[num_block].start + (i + 4) * 4, buf_32[i]);
}
}
}
}
}

View File

@@ -23,6 +23,8 @@
static const char *TAG = "efuse";
#define ESP_EFUSE_BLOCK_ERROR_BITS(error_reg, block) ((error_reg) & (0x0F << (4 * (block))))
#ifdef CONFIG_EFUSE_VIRTUAL
extern uint32_t virt_blocks[EFUSE_BLK_MAX][COUNT_EFUSE_REG_PER_BLOCK];
#endif // CONFIG_EFUSE_VIRTUAL
@@ -66,6 +68,25 @@ static esp_err_t esp_efuse_set_timing(void)
uint32_t clock_hz = esp_clk_apb_freq();
return ets_efuse_set_timing(clock_hz) ? ESP_FAIL : ESP_OK;
}
static bool efuse_hal_is_coding_error_in_block(unsigned block)
{
if (block == 0) {
for (unsigned i = 0; i < 5; i++) {
if (REG_READ(EFUSE_RD_REPEAT_ERR0_REG + i * 4)) {
return true;
}
}
} else if (block <= 10) {
// EFUSE_RD_RS_ERR0_REG: (hi) BLOCK8, BLOCK7, BLOCK6, BLOCK5, BLOCK4, BLOCK3, BLOCK2, BLOCK1 (low)
// EFUSE_RD_RS_ERR1_REG: BLOCK10, BLOCK9
block--;
uint32_t error_reg = REG_READ(EFUSE_RD_RS_ERR0_REG + (block / 8) * 4);
return ESP_EFUSE_BLOCK_ERROR_BITS(error_reg, block % 8) != 0;
}
return false;
}
#endif // ifndef CONFIG_EFUSE_VIRTUAL
// Efuse read operation: copies data from physical efuses to efuse read registers.
@@ -76,8 +97,9 @@ void esp_efuse_utility_clear_program_registers(void)
}
// Burn values written to the efuse write registers
void esp_efuse_utility_burn_efuses(void)
esp_err_t esp_efuse_utility_burn_efuses(void)
{
esp_err_t error = ESP_OK;
#ifdef CONFIG_EFUSE_VIRTUAL
ESP_LOGW(TAG, "Virtual efuses enabled: Not really burning eFuses");
for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) {
@@ -86,30 +108,90 @@ void esp_efuse_utility_burn_efuses(void)
virt_blocks[num_block][subblock++] |= REG_READ(addr_wr_block);
}
}
#else
#else // CONFIG_EFUSE_VIRTUAL
if (esp_efuse_set_timing() != ESP_OK) {
ESP_LOGE(TAG, "Efuse fields are not burnt");
} else {
// Permanently update values written to the efuse write registers
// It is necessary to process blocks in the order from MAX-> EFUSE_BLK0, because EFUSE_BLK0 has protection bits for other blocks.
for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) {
bool need_burn_block = false;
for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) {
if (REG_READ(addr_wr_block) != 0) {
if (esp_efuse_get_coding_scheme(num_block) == EFUSE_CODING_SCHEME_RS) {
uint8_t block_rs[12];
ets_efuse_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs);
memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs));
}
int data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t);
memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)range_write_addr_blocks[num_block].start, data_len);
ets_efuse_program(num_block);
need_burn_block = true;
break;
}
}
if (!need_burn_block) {
continue;
}
if (error) {
// It is done for a use case: BLOCK2 (Flash encryption key) could have an error (incorrect written data)
// in this case we can not burn any data into BLOCK0 because it might set read/write protections of BLOCK2.
ESP_LOGE(TAG, "BLOCK%d can not be burned because a previous block got an error, skipped.", num_block);
continue;
}
ets_efuse_clear_program_registers();
if (esp_efuse_get_coding_scheme(num_block) == EFUSE_CODING_SCHEME_RS) {
uint8_t block_rs[12];
ets_efuse_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs);
memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs));
}
unsigned r_data_len = (range_read_addr_blocks[num_block].end - range_read_addr_blocks[num_block].start) + sizeof(uint32_t);
unsigned data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t);
memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)range_write_addr_blocks[num_block].start, data_len);
uint32_t backup_write_data[8 + 3]; // 8 words are data and 3 words are RS coding data
memcpy(backup_write_data, (void *)EFUSE_PGM_DATA0_REG, sizeof(backup_write_data));
int repeat_burn_op = 1;
bool correct_written_data;
bool coding_error_before = efuse_hal_is_coding_error_in_block(num_block);
if (coding_error_before) {
ESP_LOGW(TAG, "BLOCK%d already has a coding error", num_block);
}
bool coding_error_occurred;
do {
ESP_LOGI(TAG, "BURN BLOCK%d", num_block);
ets_efuse_program(num_block); // BURN a block
bool coding_error_after;
for (unsigned i = 0; i < 5; i++) {
ets_efuse_read();
coding_error_after = efuse_hal_is_coding_error_in_block(num_block);
if (coding_error_after == true) {
break;
}
}
coding_error_occurred = (coding_error_before != coding_error_after) && coding_error_before == false;
if (coding_error_occurred) {
ESP_LOGW(TAG, "BLOCK%d got a coding error", num_block);
}
correct_written_data = esp_efuse_utility_is_correct_written_data(num_block, r_data_len);
if (!correct_written_data || coding_error_occurred) {
ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op);
memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data));
}
} while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3);
if (coding_error_occurred) {
ESP_LOGW(TAG, "Coding error was not fixed");
if (num_block == 0) {
ESP_LOGE(TAG, "BLOCK0 got a coding error, which might be critical for security");
error = ESP_FAIL;
}
}
if (!correct_written_data) {
ESP_LOGE(TAG, "Written data are incorrect");
error = ESP_FAIL;
}
}
}
#endif // CONFIG_EFUSE_VIRTUAL
esp_efuse_utility_reset();
return error;
}
// After esp_efuse_write.. functions EFUSE_BLKx_WDATAx_REG were filled is not coded values.

View File

@@ -94,7 +94,7 @@ esp_err_t esp_efuse_write_field_blob(const esp_efuse_desc_t* field[], const void
if (err == ESP_OK) {
err = esp_efuse_utility_apply_new_coding_scheme();
if (err == ESP_OK) {
esp_efuse_utility_burn_efuses();
err = esp_efuse_utility_burn_efuses();
}
}
esp_efuse_utility_reset();
@@ -129,7 +129,7 @@ esp_err_t esp_efuse_write_field_cnt(const esp_efuse_desc_t* field[], size_t cnt)
if (err == ESP_OK) {
err = esp_efuse_utility_apply_new_coding_scheme();
if (err == ESP_OK) {
esp_efuse_utility_burn_efuses();
err = esp_efuse_utility_burn_efuses();
}
}
esp_efuse_utility_reset();
@@ -193,7 +193,7 @@ esp_err_t esp_efuse_write_reg(esp_efuse_block_t blk, unsigned int num_reg, uint3
if (err == ESP_OK) {
err = esp_efuse_utility_apply_new_coding_scheme();
if (err == ESP_OK) {
esp_efuse_utility_burn_efuses();
err = esp_efuse_utility_burn_efuses();
}
}
esp_efuse_utility_reset();
@@ -271,7 +271,7 @@ esp_err_t esp_efuse_batch_write_commit(void)
} else {
esp_err_t err = esp_efuse_utility_apply_new_coding_scheme();
if (err == ESP_OK) {
esp_efuse_utility_burn_efuses();
err = esp_efuse_utility_burn_efuses();
}
esp_efuse_batch_write_cancel();
return err;

View File

@@ -48,7 +48,7 @@ void esp_efuse_reset(void)
#ifdef CONFIG_BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE
#include "../include_bootloader/bootloader_flash.h"
#include "../include_bootloader/bootloader_flash_priv.h"
#include "esp_flash_encrypt.h"
static uint32_t esp_efuse_flash_offset = 0;

View File

@@ -354,3 +354,29 @@ static bool check_range_of_bits(esp_efuse_block_t blk, int offset_in_bits, int s
}
return true;
}
bool esp_efuse_utility_is_correct_written_data(esp_efuse_block_t block, unsigned r_data_len)
{
uint32_t* w_data = (uint32_t*)range_write_addr_blocks[block].start;
uint32_t* r_data = (uint32_t*)range_read_addr_blocks[block].start;
bool correct_written_data = memcmp(w_data, r_data, r_data_len) == 0;
if (correct_written_data) {
ESP_LOGI(TAG, "BURN BLOCK%d - OK (write block == read block)", block);
return true;
}
correct_written_data = true;
for (unsigned i = 0; i < r_data_len / 4; i++) {
if ((*(r_data + i) & *(w_data + i)) != *(w_data + i)) {
correct_written_data = false;
break;
}
}
if (correct_written_data) {
ESP_LOGI(TAG, "BURN BLOCK%d - OK (all write block bits are set)", block);
} else {
ESP_LOGE(TAG, "BURN BLOCK%d - ERROR (written bits != read bits)", block);
}
return correct_written_data;
}

View File

@@ -169,7 +169,7 @@ TEST_CASE("Test Coding Scheme for efuse manager", "[efuse]")
}
printf("\n");
#endif
TEST_ASSERT_EQUAL_HEX32_ARRAY(encoded, w_data_after_coding, 8);
TEST_ASSERT_EQUAL_HEX32_ARRAY(buf, w_data_after_coding, 8);
}
esp_efuse_utility_reset();
bootloader_random_disable();
@@ -193,7 +193,7 @@ TEST_CASE("Test data does not match the coding scheme", "[efuse]")
esp_efuse_utility_reset();
for (int i = 0; i < count_useful_reg; ++i) {
REG_WRITE(EFUSE_BLK2_WDATA0_REG + i * 4, 0xABCDEF01 + i);
TEST_ESP_OK(esp_efuse_utility_write_reg(2, i, 0xABCDEF01 + i));
}
if (coding_scheme == EFUSE_CODING_SCHEME_NONE) {

View File

@@ -564,18 +564,35 @@ menu "ESP32-specific"
bool "Internal 8.5MHz oscillator, divided by 256 (~33kHz)"
endchoice
config ESP32_RTC_EXT_CRYST_ADDIT_CURRENT
bool "Additional current for external 32kHz crystal"
choice ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_METHOD
prompt "Additional current for external 32kHz crystal"
depends on ESP32_RTC_CLK_SRC_EXT_CRYS
default "n"
depends on ESP32_REV_MIN <= 1
default ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_NONE
help
Choose which additional current is used for rtc external crystal.
With some 32kHz crystal configurations, the X32N and X32P pins may not have enough
drive strength to keep the crystal oscillating. Choose the method to provide
additional current from touchpad 9 to the external 32kHz crystal. Note that
the deep sleep current is slightly high (4-5uA) and the touchpad and the
wakeup sources of both touchpad and ULP are not available in method 1 and method 2.
- With some 32kHz crystal configurations, the X32N and X32P pins may not
have enough drive strength to keep the crystal oscillating during deep sleep.
If this option is enabled, additional current from touchpad 9 is provided
internally to drive the 32kHz crystal. If this option is enabled, deep sleep current
is slightly higher (4-5uA) and the touchpad and ULP wakeup sources are not available.
This problem is fixed in ESP32 ECO 3, so this workaround is not needed. Setting the
project configuration to minimum revision ECO3 will disable this option, , allow
all wakeup sources, and save some code size.
- "None" option will not provide additional current to external crystal
- "Method 1" option can't ensure 100% to solve the external 32k crystal start failed
issue, but the touchpad can work in this method.
- "Method 2" option can solve the external 32k issue, but the touchpad can't work
in this method.
config ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_NONE
bool "None"
config ESP32_RTC_EXT_CRYST_ADDIT_CURRENT
bool "Method 1"
config ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2
bool "Method 2"
endchoice
config ESP32_RTC_CLK_CAL_CYCLES
int "Number of cycles for RTC_SLOW_CLK calibration"

View File

@@ -263,9 +263,9 @@ void esp_perip_clk_init(void)
/* For reason that only reset CPU, do not disable the clocks
* that have been enabled before reset.
*/
if ((rst_reas[0] >= TGWDT_CPU_RESET && rst_reas[0] <= RTCWDT_CPU_RESET)
if ((rst_reas[0] == TGWDT_CPU_RESET || rst_reas[0] == SW_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET)
#if !CONFIG_FREERTOS_UNICORE
|| (rst_reas[1] >= TGWDT_CPU_RESET && rst_reas[1] <= RTCWDT_CPU_RESET)
|| (rst_reas[1] == TGWDT_CPU_RESET || rst_reas[1] == SW_CPU_RESET || rst_reas[1] == RTCWDT_CPU_RESET)
#endif
) {
common_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN_REG);

View File

@@ -70,6 +70,7 @@
#include "esp_ota_ops.h"
#include "esp_efuse.h"
#include "bootloader_flash_config.h"
#include "bootloader_flash.h"
#include "bootloader_mem.h"
#ifdef CONFIG_APP_BUILD_TYPE_ELF_RAM
@@ -439,7 +440,7 @@ void start_cpu0_default(void)
extern void esp_rom_spiflash_attach(uint32_t, bool);
esp_rom_spiflash_attach(ets_efuse_get_spiconfig(), false);
esp_rom_spiflash_unlock();
bootloader_flash_unlock();
#else
// This assumes that DROM is the first segment in the application binary, i.e. that we can read
// the binary header through cache by accessing SOC_DROM_LOW address.
@@ -531,12 +532,20 @@ void start_cpu1_default(void)
}
#endif //!CONFIG_FREERTOS_UNICORE
#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
/**
* This function overwrites a the same function of libsupc++ (part of libstdc++).
* Consequently, libsupc++ will then follow our configured exception emergency pool size.
*
* It will be called even with -fno-exception for user code since the stdlib still uses exceptions.
*/
size_t __cxx_eh_arena_size_get(void)
{
#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
return CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE;
}
#else
return 0;
#endif
}
static void do_global_ctors(void)
{

View File

@@ -68,8 +68,6 @@ static portMUX_TYPE s_switch_lock = portMUX_INITIALIZER_UNLOCKED;
static pm_mode_t s_mode = PM_MODE_CPU_MAX;
/* True when switch is in progress */
static volatile bool s_is_switching;
/* When switch is in progress, this is the mode we are switching into */
static pm_mode_t s_new_mode = PM_MODE_CPU_MAX;
/* Number of times each mode was locked */
static size_t s_mode_lock_counts[PM_MODE_COUNT];
/* Bit mask of locked modes. BIT(i) is set iff s_mode_lock_counts[i] > 0. */
@@ -301,7 +299,7 @@ void IRAM_ATTR esp_pm_impl_switch_mode(pm_mode_t mode,
#endif // WITH_PROFILING
}
portEXIT_CRITICAL_SAFE(&s_switch_lock);
if (need_switch && new_mode != s_mode) {
if (need_switch) {
do_switch(new_mode);
}
}
@@ -372,16 +370,15 @@ static void IRAM_ATTR do_switch(pm_mode_t new_mode)
if (!s_is_switching) {
break;
}
if (s_new_mode <= new_mode) {
portEXIT_CRITICAL_ISR(&s_switch_lock);
return;
}
if (s_need_update_ccompare[core_id]) {
s_need_update_ccompare[core_id] = false;
}
portEXIT_CRITICAL_ISR(&s_switch_lock);
} while (true);
s_new_mode = new_mode;
if (new_mode == s_mode) {
portEXIT_CRITICAL_ISR(&s_switch_lock);
return;
}
s_is_switching = true;
bool config_changed = s_config_changed;
s_config_changed = false;
@@ -495,8 +492,8 @@ void esp_pm_impl_waiti(void)
* the lock so that vApplicationSleep can attempt to enter light sleep.
*/
esp_pm_impl_idle_hook();
s_skipped_light_sleep[core_id] = false;
}
s_skipped_light_sleep[core_id] = true;
#else
asm("waiti 0");
#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE

View File

@@ -419,7 +419,8 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source)
esp_err_t esp_sleep_enable_ulp_wakeup(void)
{
#ifdef CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT
#if ((defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT) || (defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2))
ESP_LOGE(TAG, "Failed to enable wakeup when provide current to external 32kHz crystal");
return ESP_ERR_NOT_SUPPORTED;
#endif
#ifdef CONFIG_ESP32_ULP_COPROC_ENABLED
@@ -455,7 +456,8 @@ static void timer_wakeup_prepare(void)
esp_err_t esp_sleep_enable_touchpad_wakeup(void)
{
#ifdef CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT
#if ((defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT) || (defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2))
ESP_LOGE(TAG, "Failed to enable wakeup when provide current to external 32kHz crystal");
return ESP_ERR_NOT_SUPPORTED;
#endif
if (s_config.wakeup_triggers & (RTC_EXT0_TRIG_EN)) {
@@ -660,10 +662,14 @@ static uint32_t get_power_down_flags(void)
// Labels are defined in the linker script, see esp32.ld.
extern int _rtc_slow_length;
/**
* Compiler considers "(size_t) &_rtc_slow_length > 0" to always be true.
* So use a volatile variable to prevent compiler from doing this optimization.
*/
volatile size_t rtc_slow_mem_used = (size_t)&_rtc_slow_length;
if ((s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] == ESP_PD_OPTION_AUTO) &&
((size_t) &_rtc_slow_length > 0 ||
(s_config.wakeup_triggers & RTC_ULP_TRIG_EN))) {
(rtc_slow_mem_used > 0 || (s_config.wakeup_triggers & RTC_ULP_TRIG_EN))) {
s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] = ESP_PD_OPTION_ON;
}
@@ -696,10 +702,11 @@ static uint32_t get_power_down_flags(void)
}
const char* option_str[] = {"OFF", "ON", "AUTO(OFF)" /* Auto works as OFF */};
ESP_LOGD(TAG, "RTC_PERIPH: %s, RTC_SLOW_MEM: %s, RTC_FAST_MEM: %s",
option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH]],
option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM]],
option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM]]);
/* This function is called from a critical section, log with ESP_EARLY_LOGD. */
ESP_EARLY_LOGD(TAG, "RTC_PERIPH: %s, RTC_SLOW_MEM: %s, RTC_FAST_MEM: %s",
option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH]],
option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM]],
option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM]]);
// Prepare flags based on the selected options
uint32_t pd_flags = 0;

View File

@@ -189,10 +189,11 @@ esp_err_t esp_spiram_add_to_heapalloc(void)
#endif
}
static uint8_t *dma_heap;
esp_err_t esp_spiram_reserve_dma_pool(size_t size) {
if (size == 0) {
return ESP_OK;
}
ESP_EARLY_LOGI(TAG, "Reserving pool of %dK of internal memory for DMA/internal allocations", size/1024);
/* Pool may be allocated in multiple non-contiguous chunks, depending on available RAM */
while (size > 0) {
@@ -200,7 +201,8 @@ esp_err_t esp_spiram_reserve_dma_pool(size_t size) {
next_size = MIN(next_size, size);
ESP_EARLY_LOGD(TAG, "Allocating block of size %d bytes", next_size);
dma_heap = heap_caps_malloc(next_size, MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL);
uint8_t *dma_heap = heap_caps_malloc(next_size, MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL);
if (!dma_heap || next_size == 0) {
return ESP_ERR_NO_MEM;
}

View File

@@ -229,9 +229,10 @@ void esp_perip_clk_init(void)
/* For reason that only reset CPU, do not disable the clocks
* that have been enabled before reset.
*/
if (rst_reas[0] >= TG0WDT_CPU_RESET &&
rst_reas[0] <= TG0WDT_CPU_RESET &&
rst_reas[0] != RTCWDT_BROWN_OUT_RESET) {
if (rst_reas[0] == TG0WDT_CPU_RESET ||
rst_reas[0] == RTC_SW_CPU_RESET ||
rst_reas[0] == RTCWDT_CPU_RESET ||
rst_reas[0] == TG1WDT_CPU_RESET) {
common_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN_REG);
hwcrypto_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN1_REG);
wifi_bt_sdio_clk = ~DPORT_READ_PERI_REG(DPORT_WIFI_CLK_EN_REG);

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