Compare commits

..

207 Commits
v3.0 ... v3.0.7

Author SHA1 Message Date
Jiang Jiang Jian
7e0ea6b05d Merge branch 'bugfix/fix_some_wifi_bugs_1121_v3.0' into 'release/v3.0'
esp32: fix some wifi bugs (backport v3.0)

See merge request idf/esp-idf!3760
2018-11-23 17:08:59 +08:00
Liu Zhi Fu
1a2cb6e363 esp32: fix some wifi bugs
Fix some wifi bugs:
1. Enable RX BAR
2. Fix the bug that ESP32 AP negotiates with iphone to 11g
3. Fix the bug that ESP32 STA has ap_loss because CMCC AP contains two SSID
2018-11-21 15:15:11 +08:00
Jiang Jiang Jian
b7c4d9a9ea Merge branch 'bugfix/btdm_add_check_peer_addr_type_in_set_adv_params_v3.0' into 'release/v3.0'
Component/bt: add check peer addr type in set adv params (backport v3.0)

See merge request idf/esp-idf!3737
2018-11-20 20:03:22 +08:00
Jiang Jiang Jian
9ee965c784 Merge branch 'bugfix/btdm_controller_disable_v3.0' into 'release/v3.0'
Fix two bugs when disable bluetooth controller(backport v3.0)

See merge request idf/esp-idf!3694
2018-11-20 17:00:16 +08:00
Jiang Jiang Jian
3ad56faf94 Merge branch 'bugfix/aes_sha_mpi_shared_regs_add_for_single_core_v3.0' into 'release/v3.0'
aes/sha/mpi: Bugfix a use of shared registers. (add for single core) (backport v3.0)

See merge request idf/esp-idf!3738
2018-11-20 14:20:41 +08:00
Konstantin Kondrashov
7761b0f28b aes/sha/mpi: Bugfix a use of shared registers.
This commit resolves a blocking in esp_aes_block function.

Introduce:
The problem was in the fact that AES is switched off at the moment when he should give out the processed data. But because of the disabled, the operation can not be completed successfully, there is an infinite hang. The reason for this behavior is that the registers for controlling the inclusion of AES, SHA, MPI have shared registers and they were not protected from sharing.

Fix some related issue with shared using of AES SHA RSA accelerators.

Closes: https://github.com/espressif/esp-idf/issues/2295#issuecomment-432898137
2018-11-19 20:57:01 +08:00
zhiweijian
896d40609f Component/bt: add check peer addr type in set adv params 2018-11-19 19:46:41 +08:00
Angus Gratton
03533a79d9 Merge branch 'bugfix/aes_sha_mpi_shared_regs_v3.0' into 'release/v3.0'
aes/sha/mpi: Bugfix a use of shared registers. (backport v3.0)

See merge request idf/esp-idf!3641
2018-11-19 15:18:55 +08:00
wangmengyang
979c4c199c Fix two bugs when disable bluetooth controller
1. Fix the bug that disable controller suddenly cause crash when ble is working.
2. Fix the bug that when disable controller, it will cause wifi cannot RX, TX timeout, buffer lack and etc.
2018-11-16 10:25:21 +00:00
Ivan Grokhotkov
d990817814 Merge branch 'bugfix/app_template_build_v3.0' into 'release/v3.0'
esp-idf-template app: some fixes for the updated template app (backport v3.0)

See merge request idf/esp-idf!3702
2018-11-15 18:39:50 +08:00
Jiang Jiang Jian
820200e66b Merge branch 'bugfix/tw27096_fix_lwip_mbox_free_crash_v3.0' into 'release/v3.0'
fix the crash caused by sys_mbox_free (backport v3.0)

See merge request idf/esp-idf!3675
2018-11-15 10:32:21 +08:00
Anton Maklakov
725cd28007 ci: If there is no sdkconfig, we have to generate one 2018-11-15 01:13:47 +08:00
Jiang Jiang Jian
93530e676e Merge branch 'bugfix/iperf_bt_error_when_wifi_connect_v3.0' into 'release/v3.0'
components/bt: Point ACL RX buffer ptr to ACL RX buffer if ACL RX buffer ptr is null(backport 3.0)

See merge request idf/esp-idf!3644
2018-11-12 15:29:37 +08:00
Jiang Jiang Jian
f9f3870e02 Merge branch 'bugfix/wifi_do_not_load_phy_data_if_fail_to_open_nvs_v3.0' into 'release/v3.0'
esp32: do not try to load PHY data if fail to open NVS (backport v3.0)

See merge request idf/esp-idf!3650
2018-11-12 14:23:21 +08:00
Liu Zhi Fu
cb4b9041bd lwip: fix crash caused by sys_mbox_free
Fix lwip crashed bug caused by sys_mbox_free()
2018-11-11 11:53:01 +08:00
XiaXiaotian
ec5f7d6344 esp32: do not try to load PHY data if fail to open NVS 2018-11-06 21:57:23 +08:00
baohongde
0ee8db80ff components/bt: Point ACL RX buffer ptr to ACL RX buffer if ACL RX buffer ptr is null
When WIFI task or other high priority task blocks the Bluetooth task, ACL RX buffer will use up, ACL RX buffer ptr will point to null and will never point to a valid adress. Causing errors in Bluetooth.
2018-11-06 18:03:15 +08:00
Konstantin Kondrashov
8776290f73 aes/sha: Bugfix a filling of AES_KEY_BASE and eap_sha function
Fixed filling of AES_KEY_BASE.
Fixed esp_sha function.
2018-11-06 15:05:36 +08:00
Jiang Jiang Jian
09cc6d316f Merge branch 'bugfix/fix_some_wifi_bugs_1022_v3.0' into 'release/v3.0'
esp32: fix some wifi bugs (backport v3.0)

See merge request idf/esp-idf!3541
2018-11-02 15:37:59 +08:00
Angus Gratton
bb56d86fde Merge branch 'bugfix/bootloader_iram_overlap_check_v3.0' into 'release/v3.0'
bootloader: verify that loaded image does not overlap bootloader code (backport v3.0)

See merge request idf/esp-idf!3527
2018-11-01 14:01:49 +08:00
Ivan Grokhotkov
db2223818b bootloader: verify that loaded image does not overlap bootloader code
Fixes CVE-2018-18558
2018-10-30 17:35:23 +08:00
Liu Zhi Fu
b8e084c479 esp32: fix some wifi bugs
Fix following WiFi bugs:
1. Fix the bug that sniffer can't catch control packets
2. Fix crash bug in soft-AP mode
3. Fix ACM(Admission Control Management) bug
2018-10-25 12:10:54 +08:00
Angus Gratton
099ae5a1d9 Merge branch 'feature/ci_multi_python_v3.0' into 'release/v3.0'
CI: Support switching between various versions of Python (backport v3.0)

See merge request idf/esp-idf!3535
2018-10-25 07:20:38 +08:00
Jiang Jiang Jian
9b4e911359 Merge branch 'bugfix/tw26711_fix_wifi_memory_v3.0' into 'release/v3.0'
esp32: fix wifi memory leak (backport v3.0)

See merge request idf/esp-idf!3525
2018-10-22 21:20:32 +08:00
Roland Dobai
00fec53d76 CI: Support switching between various versions of Python 2018-10-22 13:08:18 +02:00
Liu Zhi Fu
ba5f0585af esp32: fix wifi memory leak
Fix a WiFi memory leak bug
2018-10-21 20:56:05 +08:00
Jiang Jiang Jian
bcaac485d3 Merge branch 'bugfix/btdm_fix_crash_when_BLE_do_SMP_con_discon_stress_test_v3.0' into 'release/v3.0'
component/bt: fix start adv crash(backport v3.0)

See merge request idf/esp-idf!3505
2018-10-19 20:21:24 +08:00
zwj
5ce10cb58c component/bt: fix start adv crash 2018-10-19 16:11:56 +08:00
Jiang Jiang Jian
cba7efc9d2 Merge branch 'bugfix/btdm_tx_power_level_v3.0' into 'release/v3.0'
fix bluetootm(dual-mode) tx power value corresponding to libphy.a

See merge request idf/esp-idf!3488
2018-10-18 15:44:09 +08:00
Jiang Jiang Jian
364c0c4ace Merge branch 'bugfix/tw26696_fix_wifi_timer_v3.0' into 'release/v3.0'
esp32: fix WiFi timer inaccurate bug (backport v3.0)

See merge request idf/esp-idf!3493
2018-10-17 17:30:56 +08:00
Liu Zhi Fu
be02f6b423 esp32: fix WiFi timer inaccurate bug
Fix the bug that WiFi timer is not accurate when sleep is on
2018-10-16 19:55:53 +08:00
Tian Hao
4522476e72 fix bluetootm(dual-mode) tx power value corresponding to libphy.a 2018-10-15 19:52:56 +08:00
Angus Gratton
6313ea0088 Merge branch 'bugfix/fix_psram_eid_v3.0' into 'release/v3.0'
psram: fix psram eid (backport v3.0)

See merge request idf/esp-idf!3463
2018-10-12 11:41:13 +08:00
Jiang Jiang Jian
735f02c4b7 Merge branch 'bugfix/btdm_bt_mux_active_after_deinit_v3.0' into 'release/v3.0'
component/bt : fix bug that bt mux module is still active even after disable

See merge request idf/esp-idf!3341
2018-10-11 18:49:52 +08:00
Jiang Jiang Jian
d6df10edaf Merge branch 'bugfix/several_bugfix_about_ba_session_setup_v3.0' into 'release/v3.0'
esp32: several fixes about BA session setup (backport v3.0)

See merge request idf/esp-idf!3455
2018-10-11 11:42:22 +08:00
Angus Gratton
d02d2d5170 Merge branch 'fix/spi_master_cmd_addr_lsbfirst_v3.0' into 'release/v3.0'
spi_master: fix the command and address field when LSB_FIRST enabled (Backport v3.0)

See merge request idf/esp-idf!3444
2018-10-11 06:28:38 +08:00
chenjianqiang
80c013ee5a bugfix(psram): fix the error that two macro definitions are undeclared
1. add definition of FLASH_ID_GD25LQ32C
2. modify DPORT_SPI3_CLK_EN as DPORT_SPI_CLK_EN_2
2018-10-10 20:21:01 +08:00
Tian Hao
f2347e5729 component/bt : fix bug that bt mux module is still active even after disable
Resolve the problem following:
    1. when wifi and bluetooth coex, after call esp_bt_controller_disable(), it may cause WiFi cannot TX/RX packets.
       Such as, it cause wifi disconnect, can't probe any SSIDs or etc.
2018-10-10 15:54:13 +08:00
chenjianqiang
8cfb0b207a bugfix(psram): fix psram driver
1. remove use EID to distinguish psram voltage
2. 1V8 64Mbit psram and 3V3 64Mbit psram use the same psram driver(standard spi interface)
3. set cs hold time register as 1
2018-10-10 15:51:18 +08:00
Wangjialin
6d253b4394 feature(psram): add support for 64MBit psram of 1.8v and 3.3v.
1. Add reading psram EID.
2. Configure different clock mode for different EID.
3. add API to get psram size and voltage.
4. Remove unnecessary VSPI claim.

For 32MBit@1.8V and 64MBit@3.3V psram, there should be 2 extra clock cycles after CS get high level.
For 64MBit@1.8 psram, we can just use standard SPI protocol to drive the psram. We also need to increase the HOLD time for CS in this case.

EID for psram:
32MBit 1.8v: 0x20
64MBit 1.8v: 0x26
64MBit 3.3v: 0x46
2018-10-10 15:43:30 +08:00
Angus Gratton
50dc31103f Merge branch 'bugfix/bootloader_gen_secure_boot_digest_v3.0' into 'release/v3.0'
bootloader: Fix secure boot digest generation for image length where (len%128 < 32) (backport v3.0)

See merge request idf/esp-idf!3426
2018-10-10 14:56:37 +08:00
Liu Zhi Fu
3af5384a24 esp32: several fixes about BA session setup
1. Fix the bug that ESP32 will reject the retry AddBA request frame
   if AddBA response frame is failed to sent by WiFi LMAC
2. Fix the bug that AddBA request retrys too frequently
3. Forbid BA session setup for VO queue related TID
2018-10-10 13:51:13 +08:00
Angus Gratton
283c47cbba bootloader: Fix secure boot digest generation for image length where (len%128 < 32) 2018-10-10 11:14:44 +11:00
michael
4ae01aed27 test: modify the command/address test a bit to test the LSBFIRST feature 2018-10-09 00:34:13 +08:00
michael
a5a692ef8c spi: move gpio direction config to common func for coinsistence
(MINOR CHANGE)
2018-10-08 19:04:38 +08:00
Michael (XIAO Xufeng)
3c532e4532 spi_master: fix the command and address field when LSB_FIRST enabled
Resolves https://github.com/espressif/esp-idf/issues/2444.
2018-10-08 19:04:37 +08:00
Angus Gratton
2e8d7fa36d Merge branch 'bugfix/disable_coding_scheme_security_features_v3.0' into 'release/v3.0'
bootloader: Don't enable secure boot or flash encryption for 3/4 Coding Scheme (v3.0)

See merge request idf/esp-idf!3422
2018-10-04 16:37:07 +08:00
Angus Gratton
674cf7520e esptool: Update to v2.5.1
Release notes: https://github.com/espressif/esptool/releases/tag/v2.5.1

Needed to no longer burn keys if 3/4 Coding Scheme is enabled.
2018-10-02 10:03:13 +10:00
Angus Gratton
c990ca4e20 bootloader: Don't enable secure boot or flash encryption for 3/4 Coding Scheme 2018-10-02 10:01:20 +10:00
Jiang Jiang Jian
5b061a0530 Merge branch 'bugfix/wifi_make_esptouch_channel_switch_thread_safe_v3.0' into 'release/v3.0'
esp32: make esp-touch channel switch thread safe

See merge request idf/esp-idf!3354
2018-09-26 19:55:14 +08:00
XiaXiaotian
43d2f940b2 esp32: make esp-touch channel switch thread safe
Fix the crash issue when esp-touch is in progress.
2018-09-25 11:20:29 +08:00
Jiang Jiang Jian
a5533a0b5d Merge branch 'bugfix/fix_the_bug_create_socket_fail_v3.0' into 'release/v3.0'
lwip: fix the bug that failed to create socket (backport v3.0)

See merge request idf/esp-idf!3312
2018-09-20 18:44:30 +08:00
Liu Zhi Fu
5f56d65405 lwip: fix the bug that failed to create socket
Fix the bug that failed to create nonblocking TCP or UDP socket after several times socket create/close
2018-09-19 16:50:39 +08:00
Angus Gratton
fcf9c3d882 Merge branch 'fix/spi_slave_free_cs_v3.0' into 'release/v3.0'
spi_slave: fix the issue rx dma get broken by master unexpected transaction (backport v3.0)

See merge request idf/esp-idf!3293
2018-09-18 08:08:17 +08:00
michael
a7ad8bc873 spi_slave: fix the issue rx dma get broken by master unexpected transaction 2018-09-18 00:49:25 +08:00
Jiang Jiang Jian
438c9bcb35 Merge branch 'bugfix/tw24884_fix_ampdu_sequence_compitable_issue_v3.0' into 'release/v3.0'
esp32: fix AMPDU RX sequence compitability issue (backport v3.0)

See merge request idf/esp-idf!3281
2018-09-17 18:58:52 +08:00
Liu Zhi Fu
328e689cf1 esp32: fix AMPDU RX sequence compitability issue
Fix AMPDU RX sequence compitability issue when connecting to some special APs, such as Mercury, Fast etc.
2018-09-17 14:51:00 +08:00
Jiang Jiang Jian
13732c5753 Merge branch 'bugfix/tw24694_dns_request_no_reply_v3.0' into 'release/v3.0'
lwip: add code for sending gratuitous ARP periodically (backport v3.0)

See merge request idf/esp-idf!3240
2018-09-16 15:18:44 +08:00
Angus Gratton
2544d737c5 Merge branch 'bugfix/ci_github_deploy_v30' into 'release/v3.0'
ci: Fix spurious pipeline failure when deploying a tag to GitHub (backport v3.0)

See merge request idf/esp-idf!3221
2018-09-13 15:36:39 +08:00
zhangyanjiao
8bd10b4808 lwip: add code for sending gratuitous ARP periodically 2018-09-11 15:24:21 +08:00
Jiang Jiang Jian
a975ba6cef Merge branch 'bugfix/fix_the_bug_when_gateway_zero_v3.0' into 'release/v3.0'
esp32: fix the bug that SYSTEM_EVENT_STA_GOT_IP is forbidden when gateway is 0.0.0.0 (backport v3.0)

See merge request idf/esp-idf!3239
2018-09-11 12:07:35 +08:00
zhangyanjiao
9189e1006d esp32: fix the bug that SYSTEM_EVENT_STA_GOT_IP is forbidden when gateway is 0.0.0.0 2018-09-11 11:05:51 +08:00
Angus Gratton
bc8a84e9e4 ci: Fix spurious pipeline failure when deploying a tag to GitHub
Everything succeeds, but because [ -z ${CI_COMMIT_TAG} ] on the last line returns non-zero, it
fails the job.
2018-09-07 15:24:23 +08:00
Jiang Jiang Jian
efe499113c Merge branch 'bugfix/btdm_discovery_ble_v3.0' into 'release/v3.0'
component/bt : fix bug that set discovery mode will stop ble adv

See merge request idf/esp-idf!3190
2018-09-06 14:19:40 +08:00
Jiang Jiang Jian
7331ee2af2 Merge branch 'bugfix/tw25969_esp_derive_local_mac_missing_v3.0' into 'release/v3.0'
defination: fix the bug that esp_derive_local_mac() defination missing (backport v3.0)

See merge request idf/esp-idf!3201
2018-09-05 17:21:36 +08:00
zhangyanjiao
f323fe5fee defination: fix the bug that esp_derive_local_mac() defination missing 2018-09-05 14:45:48 +08:00
Tian Hao
291c4a4fd3 component/bt : fix bug that set discovery mode will stop ble adv
As the bluedroid original implmentation of BR/EDR and BLE dual mode about discovery mode,
when set discovery mode for BR/EDR, it will stop ble advertising.

Reference to https://github.com/espressif/esp-idf/issues/2306
2018-09-04 20:30:43 +08:00
Jiang Jiang Jian
9b1bd0a09f Merge branch 'bugfix/btdm_find_remote_service_by_uuid_always_return_success_v3.0' into 'release/v3.0'
component/bt: Fix bug of SDP find services by uuid always return success (backport 3.0)

See merge request idf/esp-idf!3165
2018-09-04 19:21:47 +08:00
Jiang Jiang Jian
0ba566e0c6 Merge branch 'bugfix/btdm_update_private_address_v3.0' into 'release/v3.0'
component/bt: Update BLE private address after it's private address interval (backport 3.0)

See merge request idf/esp-idf!3171
2018-09-04 19:21:21 +08:00
Jiang Jiang Jian
405b1986c2 Merge branch 'bugfix/btdm_controller_deinit_v3.0' into 'release/v3.0'
bt : fix bug that bluetooth controller init/disable/enable/disable may cause exception

See merge request idf/esp-idf!3149
2018-09-04 15:07:08 +08:00
baohongde
7d2baa3c3d component/bt: Update BLE private address after it's private address interval (backport 3.0)
A cherry-pick of MR !2987
2018-09-03 14:31:40 +08:00
baohongde
530dedbc2d component/bt: Fix bug of SDP find services by uuid always return success (backport 3.0)
A cherry-pick of MR !3036
2018-09-03 11:57:53 +08:00
Jiang Jiang Jian
7c42b55e45 Merge branch 'bugfix/wifi_reorder_mpdu_as_ampdu_v3.0' into 'release/v3.0'
esp32: reorder MPDU as AMPDU (backport v3.0)

See merge request idf/esp-idf!3141
2018-08-31 02:02:14 +08:00
XiaXiaotian
f4022111c8 esp32: reorder MPDU as AMPDU
Some APs transmit AMPDU and MPDU by turns. Moreover, the sequence
    numbers of AMPDU and MPDU are out of order, e.g. MPDU(1253) -
    AMPDU(1251, 1252) - MPDU(1254) - AMPDU(1255, 1256). In order to
    receive both AMPDU and MPDU in order, MPDU must be reordered with
    AMPDU.
2018-08-30 11:59:31 +08:00
Jiang Jiang Jian
53dcd1202d Merge branch 'bugfix/fix_probable_mem_leak_v3.0' into 'release/v3.0'
components/bt: Fix a probable memory leak for BTA_GATTS_CONF_EVT event (backport v3.0)

See merge request idf/esp-idf!3105
2018-08-29 23:09:54 +08:00
Jiang Jiang Jian
ef2c0e8b3e Merge branch 'bugfix/autoip_compilation_backportv3.0' into 'release/v3.0'
LWIP AutoIP Compilation Fixed by defining IP_IS_V4_VAL() (backport v3.0)

See merge request idf/esp-idf!3122
2018-08-29 22:54:42 +08:00
Jiang Jiang Jian
7515dc97b6 Merge branch 'bugfix/btdm_a2dp_sink_pcm_buf_size_for_v3.0' into 'release/v3.0'
bugfix/btdm_a2dp_sink_pcm_buf_size_for_v3.0(backport v3.0)

See merge request idf/esp-idf!3118
2018-08-29 10:19:48 +08:00
Tian Hao
a9c1820385 bt : fix bug that bluetooth controller init/disable/enable/disable may cause exception
1. when one task do deinit/init/disable/enable, especially different cpu
core, it may cause controller crash in ISR handler
2. fix while BLE is scanning, bluetooth controller is disabled cause BLE
scan is not abort.
2018-08-28 21:10:17 +08:00
Jiang Jiang Jian
8fdf200932 Merge branch 'bugfix/btdm_fix_get_error_adv_sometimes_v3.0' into 'release/v3.0'
Component/bt: fix get error adv packet sometimes (backport v3.0)

See merge request idf/esp-idf!3084
2018-08-28 20:04:30 +08:00
Piyush Shah
4cde212817 LWIP AutoIP Compilation Fixed by defining IP_IS_V4_VAL() 2018-08-28 15:23:21 +05:30
zhiweijian
6751373411 Component/bt: fix get error adv packet sometimes 2018-08-28 14:05:44 +08:00
wangmengyang
27fd353752 component/bt: bugfix for incorrect computation of PCM data buffer size in A2DP sink 2018-08-28 11:16:33 +08:00
Jiang Jiang Jian
97603b1d59 Merge branch 'bugfix/btdm_check_slave_feature_before_set_afh_for_v3.0' into 'release/v3.0'
bugfix/btdm_check_slave_feature_before_set_afh_for_v3.0(backport v3.0)

See merge request idf/esp-idf!3104
2018-08-28 10:42:17 +08:00
Hrishikesh Dhayagude
32fd3a3215 components/bt: Fix a probable memory leak for BTA_GATTS_CONF_EVT event (backport v3.0)
Multiple modules register their callback BTA_GATTS_AppRegister().

If any of the callbacks do not free the allocated pointer in
BTA_GATTS_CONF_EVT event, then this can result in memory leak.

So, free the pointer after the callback function is called and remove
the calls to free in the callback functions as it is now not required

Signed-off-by: Hrishikesh Dhayagude <hrishi@espressif.com>
2018-08-27 11:57:14 +05:30
Jiang Jiang Jian
d1c6eb9574 Merge branch 'bugfix/fix_several_wifi_bugs_v3.0' into 'release/v3.0'
esp32: update wifi lib to fix several WiFi bugs (backport v3.0)

See merge request idf/esp-idf!3097
2018-08-27 14:24:11 +08:00
wangmengyang
5ee2d3b90d component/bt: check support of AFH in remote slave device's LM feature when determine whether to send LMP_set_AFH 2018-08-27 11:39:43 +08:00
Jiang Jiang Jian
8618b452f7 Merge branch 'bugfix/btdm_fix_memory_leak_in_security_server_v3.0' into 'release/v3.0'
component/bt: fix memory leak in security server (backport v3.0)

See merge request idf/esp-idf!3016
2018-08-27 10:20:13 +08:00
Angus Gratton
39fb5d7150 Merge branch 'fix/spi_dma_config_in_iram_v3.0' into 'release/v3.0'
spi: fix the issue that spi cannot be used when flash is disabled (backport v3.0)

See merge request idf/esp-idf!3076
2018-08-27 08:13:55 +08:00
Liu Zhi Fu
5dafcf9363 esp32: update wifi lib to fix several WiFi bugs
Fix following WiFi bugs:
1. Shouldn't scan when connect
2. Check beacon length in modem sleep
3. Fix the bug that AP may deauth wrong station when inactivity timer expires
4. Fix the bug that WiFi assert the system when receiving empty MCS in association response frame
2018-08-26 13:05:59 +08:00
Jiang Jiang Jian
3f72a12d97 Merge branch 'bugfix/btdm_fix_CI_scan_case_fail' into 'release/v3.0'
Component/bt: fix CI scan case failed in v3.0

See merge request idf/esp-idf!3074
2018-08-25 16:54:37 +08:00
Jiang Jiang Jian
af4f2ace84 Merge branch 'bugfix/fix_crash_for_http2_request_v3.0' into 'release/v3.0'
fix the crash when http2_request example send/recv fail (backport v3.0)

See merge request idf/esp-idf!3073
2018-08-24 14:01:26 +08:00
Jiang Jiang Jian
e8ad0415cc Merge branch 'bugfix/timer_oneshot_timeout_twice_v3.0' into 'release/v3.0'
component/bt: Some timer oneshot will timeout twice (backport v3.0)

See merge request idf/esp-idf!3064
2018-08-24 14:01:06 +08:00
Jiang Jiang Jian
ac253274a0 Merge branch 'bugfix/btdm_fix_sc_mitm_bond_failed_in_smp_for_iphones_v30' into 'release/v3.0'
Component/bt:  fix SC_MITM_BOND failed in smp for iphones (backport v3.0)

See merge request idf/esp-idf!3045
2018-08-24 11:37:00 +08:00
Jiang Jiang Jian
972107fbc9 Merge branch 'bugfix/sync_ap_loss_to_release_3_0' into 'release/v3.0'
wifi: bugfix of ap loss

See merge request idf/esp-idf!3072
2018-08-24 11:15:41 +08:00
Jiang Jiang Jian
5e9267f846 Merge branch 'bugfix/tw23404_dhcp_NAK_issue_v3.0' into 'release/v3.0'
lwip: optimize LWIP timer

See merge request idf/esp-idf!2964
2018-08-24 11:14:32 +08:00
Michael (XIAO Xufeng)
cfed7c84ce spi: fix the issue that spi cannot be used when flash is disabled
The dma configuration function called in the ISR should be put into the IRAM.

Fixes https://github.com/espressif/esp-idf/issues/2307.
2018-08-24 11:07:18 +08:00
zhiweijian
3870836a90 Component/bt: fix CI scan case failed in v3.0 2018-08-24 10:57:16 +08:00
zhangyanjiao
19f319a55d fix the crash when http2_request example send/recv fail 2018-08-24 10:06:45 +08:00
Deng Xin
0806617971 wifi: bugfix of ap loss 2018-08-23 21:54:15 +08:00
Jiang Jiang Jian
4f346169ff lwip: optimize LWIP timer
Port LWIP timer implementation in LWIP v2.0.3 to IDF v3.0
2018-08-23 20:20:24 +08:00
baohongde
00b895680e component/bt: Some timer oneshot will timeout twice (backport v3.0)
A cherry-pick of MR !2979
2018-08-23 11:02:59 +08:00
Jiang Jiang Jian
997d291d85 Merge branch 'bugfix/btdm_fix_get_bond_list_error_when_connection_with_no_bond_v30' into 'release/v3.0'
Component/bt: fix get bond list error when connection with no bond(backport v3.0)

See merge request idf/esp-idf!3042
2018-08-23 10:38:04 +08:00
Jiang Jiang Jian
5f2660e1f5 Merge branch 'bugfix/btdm_fix_version_excahnge_issue_v30' into 'release/v3.0'
Component/bt: fix version exchange issue(backport v3.0)

See merge request idf/esp-idf!3046
2018-08-23 10:36:39 +08:00
Jiang Jiang Jian
451e4cf3b0 Merge branch 'bugfix/btdm_fix_no_adv_packet_v30' into 'release/v3.0'
component/bt: fix no adv packets(backport v3.0)

See merge request idf/esp-idf!3043
2018-08-22 18:13:28 +08:00
Angus Gratton
132b439359 Merge branch 'bugfix/ulp_fixes_v3.0' into 'release/v3.0'
ULP fixes (backport v3.0)

See merge request idf/esp-idf!3002
2018-08-22 13:37:16 +08:00
Angus Gratton
04ce9050b6 Merge branch 'doc/versions_v3.0' into 'release/v3.0'
docs: Add version-specific include files, version documentation (backport v3.0)

See merge request idf/esp-idf!2975
2018-08-22 13:36:36 +08:00
zhiweijian
27f8ee6b97 Component/bt: fix memory leak in security server 2018-08-21 16:09:04 +08:00
zhiweijian
1c001ecd7a Component/bt: fix version exchange issue
- Android 7.0 version issue
- version exchange late in some phones
- can not get version in smp
2018-08-21 14:55:51 +08:00
zhiweijian
a961984f73 Component/bt: fix SC_MITM_BOND failed in smp for iphones 2018-08-21 14:46:20 +08:00
zwj
2d53799372 component/bt: fix no adv packets 2018-08-21 14:10:36 +08:00
zhiweijian
7275490322 Component/bt: fix get bond list error when connection with no bond 2018-08-21 14:05:14 +08:00
Jiang Jiang Jian
f6a7cda7b6 Merge branch 'bugfix/btdm_ecdh_public_key_not_check_v3.0' into 'release/v3.0'
Bugfix/btdm ecdh public key not check v3.0 (backport v3.0)

See merge request idf/esp-idf!2992
2018-08-14 09:54:10 +08:00
Ivan Grokhotkov
d88b74064d docs: update esp32ulp-binutils download link 2018-08-13 23:34:06 +03:00
Ivan Grokhotkov
b9f6b579f1 ulp: add documentation for JUMPS instruction conditions
Hardware implements conditions LE, LT, GE, and conditions EQ and GT
are implemented in the assembler by emitting two JUMPS instructions
with other conditions.
2018-08-13 23:34:06 +03:00
Ivan Grokhotkov
72ad5a142b ulp: add tests for jumps instruction 2018-08-13 23:34:06 +03:00
Ivan Grokhotkov
d07f9dfbb2 ulp: fix ULP binary format documentation
Fix incorrect offset value (4+2+2+2+2=12) of arbitrary data in ULP
binary format.

Closes https://github.com/espressif/esp-idf/issues/1705.
2018-08-13 23:34:06 +03:00
Ivan Grokhotkov
33250ea678 ulp: use += instead of := when setting component vars
Component which includes component_ulp_common.mk may also need to set
some of the same COMPONENT_XXX variables. Logically, we should combine
the lists of files to embed, ldflags, extra include dirs, etc.

Fixes https://github.com/espressif/esp-idf/issues/2157.
2018-08-13 23:34:06 +03:00
Ivan Grokhotkov
300657162b ulp: fix missing include in esp32/ulp.h header
ulp.h uses some register base addresses, so needs to include soc.h
2018-08-13 23:34:06 +03:00
Ivan Grokhotkov
7fcc76fa06 ulp: fix calculation or ulp_run argument
The argument to ulp_run should be expressed in 32-bit words. Both the
address of ulp_entry and RTC_SLOW_MEM already are uint32_t*, so their
difference is the difference in addresses divided by sizeof(uint32_t).
Therefore the extra division by sizeof(uint32_t) is not needed.
2018-08-13 23:34:06 +03:00
Ivan Grokhotkov
85fbaaf37a docs: fix line endings of ULP docs 2018-08-13 23:34:06 +03:00
Ivan Grokhotkov
da97846483 docs/ulp: fix instruction fetch and execution times 2018-08-13 23:30:07 +03:00
yulong
7aa29a0dbb component/bt: Fixed the vulnerability released by Bluetooth org when using public key not check in the process of ECDH encryption. 2018-08-13 19:46:04 +08:00
Angus Gratton
516d9f0eae Merge branch 'bugfix/spiffs_readdir_recursion_v3.0' into 'release/v3.0'
SPIFFS: fix stack overflow in readdir_r due to recursion (backport v3.0)

See merge request idf/esp-idf!2877
2018-08-13 16:26:31 +08:00
Angus Gratton
bb5789b6ee docs: Move version-related includes to run in sphinx-build not make
Means they show up on ReadTheDocs(!)
2018-08-13 17:32:44 +10:00
Ivan Grokhotkov
f206bc51ff spiffs: add test case for readdir_r with large number of files
Ref. https://esp32.com/viewtopic.php?f=13&t=6486
2018-08-12 16:53:04 +00:00
Konstantin Klitenik
ecc82a3c27 Fix stackoverflow due to recursion in vfs_spiffs_readdir_r 2018-08-12 16:53:04 +00:00
Jiang Jiang Jian
6746be5a09 Merge branch 'bugfix/wifi_fix_next_beacon_and_dtim_time_update_issue' into 'release/v3.0'
esp32: fix next beacon and dtim time update issue when beacon is not

See merge request idf/esp-idf!2970
2018-08-10 21:03:27 +08:00
XiaXiaotian
007d884a85 esp32: fix next beacon and dtim time update issue when beacon is not
received for more than one beacon interval
2018-08-10 11:36:59 +08:00
Angus Gratton
998416c54b README: Add version-specific links
Make it clearer how the README fits in with the docs.
2018-08-10 01:03:08 +00:00
Angus Gratton
873c515ee3 docs: Add version-specific include files, version documentation
* "git clone" command and a small version header are generated
  depending on git properties.
* Add Versions page with details about each version
* Make it clear using master branch is living on the "bleeding
  edge"
2018-08-10 01:03:08 +00:00
Jiang Jiang Jian
ee295c175b Merge branch 'feature/support_for_XM25QU64A_v3.0' into 'release/v3.0'
feature(flash): set QIO mode for XM25QU64A(1V8_8MB_flash) (backport v3.0)

See merge request idf/esp-idf!2813
2018-08-08 20:36:39 +08:00
Angus Gratton
25ed0aa9bb Merge branch 'bugfix/tw24252_fix_nonblocking_tcp_close_issue_v3.0' into 'release/v3.0'
lwip: fix nonblocking tcp close issue (backport v3.0)

See merge request idf/esp-idf!2943
2018-08-08 16:33:07 +08:00
chenjianqiang
4b4614ffb1 feature(flash): support for QIO mode of XM25QU64A 2018-08-08 03:39:19 +00:00
Angus Gratton
21adda8777 Merge branch 'bugfix/ci_github_deploy_v30' into 'release/v3.0'
ci: Simplify github deployment (backport v3.0)

See merge request idf/esp-idf!2875
2018-08-08 07:25:34 +08:00
Jiang Jiang Jian
8ff0f4a616 Merge branch 'bugfix/update_libphy_to_improve_11n_stability' into 'release/v3.0'
esp32: update libphy.a to v3663 to improve 11n TX stability (backport v3.0)

See merge request idf/esp-idf!2937
2018-08-07 20:51:29 +08:00
Liu Zhi Fu
08946da2db lwip: fix nonblocking tcp close issue
Fix assert issue causes by closing nonblocking tcp socket.
2018-08-07 14:31:49 +08:00
Jiang Jiang Jian
90b8a42349 Merge branch 'bugfix/btdm_lmp_trans_coll_state_uncleared_for_v3.0' into 'release/v3.0'
bugfix/btdm_lmp_trans_coll_state_uncleared(backport v3.0)

See merge request idf/esp-idf!2917
2018-08-06 18:39:08 +08:00
Liu Zhi Fu
3c92cd607b esp32: update libphy.a to v3663 to improve 11n TX stability
Fix the bug that WiFi 11n TX may fail in some AP or CMW500 3.5 version
This fix can improve the 11n stability
2018-08-06 17:32:10 +08:00
Angus Gratton
4f3008bfd8 ci: Simplify github deployment
CI_COMMIT_REF_NAME lets us use a single line to git push
2018-08-06 16:30:43 +10:00
Jiang Jiang Jian
dd1fa7c502 Merge branch 'bugfix/autoip_compilation' into 'release/v3.0'
LWIP AutoIP Compilation Fixed by defining IP_IS_V4_VAL()

See merge request idf/esp-idf!2926
2018-08-05 07:30:43 +08:00
wangmengyang
50556b8acb component/bt: bugfix for uncleared LMP transaction collision state after rejecting sniff request from slave
This bug will cause other following LMP transactions, such as (e)SCO link set up transaction to fail
2018-08-04 16:24:37 +00:00
zhangyanjiao
9da0541020 LWIP AutoIP Compilation Fixed by defining IP_IS_V4_VAL() 2018-08-04 15:25:05 +00:00
Jiang Jiang Jian
ab74be7abe Merge branch 'bugfix/btdm_a2dp_disconnect_reason_for_v3.0' into 'release/v3.0'
bugfix/btdm_a2dp_disconnect_reason(backport v3.0)

See merge request idf/esp-idf!2928
2018-08-04 11:58:26 +08:00
wangmengyang
b5c45a4d46 component/bt: retrieve disconnection reason in AVDT when ACL-U link is disconnected 2018-08-03 15:42:55 +08:00
Angus Gratton
225e98dcee Merge branch 'bugfix/py3_link_roles' into 'release/v3.0'
docs: Add build support for python3 (backport v3.0)

See merge request idf/esp-idf!2919
2018-08-03 15:31:12 +08:00
Anuj Deshpande
d66b227e07 docs: Add build support for python3 2018-08-02 12:59:31 +02:00
Jiang Jiang Jian
ce67428c56 Merge branch 'bugfix/add_compatible_of_ccmp_encryption_v_3_0' into 'release/v3.0'
wifi: add compatible to ccmp encryption (backport v3.0)

See merge request idf/esp-idf!2899
2018-08-02 17:47:48 +08:00
Angus Gratton
054e82b4b3 Merge branch 'test/workaround_ci_failures_v3.0' into 'release/v3.0'
CI: erase nvs partition before test (backport v3.0)

See merge request idf/esp-idf!2870
2018-08-01 17:02:50 +08:00
Jiang Jiang Jian
7d4a9db191 Merge branch 'bugfix/btdm_fix_slave_cant_receive_long_packets_in_smp_for_v3.0' into 'release/v3.0'
component/bt: fix slave cant receive long packets in smp for v3.0

See merge request idf/esp-idf!2857
2018-08-01 14:40:05 +08:00
Deng Xin
39f97bb4e8 wifi: add compatible to ccmp encryption 2018-07-31 21:07:46 +08:00
He Yin Ling
8f81157432 CI: add stage host_test:
1. Add `host_test` stage for test jobs running on host.
2. Rename stage `test` to `integration_test`.
2018-07-29 00:26:38 +08:00
He Yin Ling
5141570f24 CI: minor optimize of CI config file:
1. set shorter expire time for artifacts
2. set dependency for example test jobs, to limit the artifacts it downloads
2018-07-29 00:20:15 +08:00
He Yin Ling
f86d512672 CI: remove test report stage:
Test report is not used as expected:

1. we rarely download and use test report
2. current test report method doesn't handle large amount data well,
   need to be replaced by other methods

Test report also make test jobs allow to fail. It breaks the
original flow of Gitlab CI and make user confused.
2018-07-29 00:17:25 +08:00
Jiang Jiang Jian
ab341359f5 Merge branch 'bugfix/ampdu_duplicate_v3.0' into 'release/v3.0'
Wifi: fix ampdu duplicate issue (backport v3.0)

See merge request idf/esp-idf!2804
2018-07-28 17:56:25 +08:00
He Yin Ling
f98da26b38 CI: erase nvs partition before test:
Latest NVS partition bin can't be parsed by old IDF revision. Need to erase before test.
2018-07-28 15:18:10 +08:00
zwj
d0cd624d2b component/bt: fix slave cant receive long packets in smp 2018-07-26 11:39:47 +08:00
Ivan Grokhotkov
c8c4bd099e Merge branch 'bugfix/fix_uart_timeout_bug_when_enable_reftick_v3.0' into 'release/v3.0'
driver(uart): fix uart timeout bug when enable reftick for release v3.0

See merge request idf/esp-idf!2811
2018-07-24 13:16:54 +08:00
Angus Gratton
36c14cf214 Merge branch 'bugfix/add_queueset_critical_sections_v3.0' into 'release/v3.0'
freertos: Add critical sections to queue sets (backport v3.0)

See merge request idf/esp-idf!2788
2018-07-20 10:03:59 +08:00
hou wen xiang
a7c9cf3a6b driver(uart): Fix uart time_out bug when using ref_tick for release v3.0 2018-07-18 17:35:59 +08:00
Jiang Jiang Jian
9aee394dc6 Merge branch 'bugfix/tw23835_add_source_ip_route_for_unicast_v3.0' into 'release/v3.0'
lwip: add source ip based route for unicast packet (backport v3.0)

See merge request idf/esp-idf!2781
2018-07-18 17:34:19 +08:00
chenyudong
05eb9d155f Wifi: fix ampdu duplicate issue
fix ampdu duplicate issue
2018-07-18 14:51:29 +08:00
Jiang Jiang Jian
0669fe8f02 Merge branch 'bugfix/tw23835_add_source_ip_route_for_unicast_v3.0' into 'release/v3.0'
lwip: add source ip based route for unicast packet (backport v3.0)

See merge request idf/esp-idf!2781
2018-07-17 14:12:13 +08:00
Darian Leung
cabb97f9a9 freertos: Add critical sections to queue sets.
Queue sets are not SMP safe. This commit adds
critical sections to queue sets. Unit tests for
queue sets have also been added.
2018-07-16 19:30:46 +08:00
Liu Zhi Fu
41b1db4dc6 lwip: add source ip based route for unicast packet
Add source IP based route for unicast packets forwarding.
2018-07-16 17:11:01 +08:00
Jiang Jiang Jian
8bc76b3684 Merge branch 'bugfix/tw23667_tcp_pcb_purge_assert_v3.0' into 'release/v3.0'
lwip: fix the assertion in tcp_pcb_purge() (backport v3.0)

See merge request idf/esp-idf!2723
2018-07-15 14:53:58 +08:00
Jiang Jiang Jian
245b753904 Merge branch 'bugfix/disable_lwip_trust_ip_by_default_v3.0' into 'release/v3.0'
lwip: disable ETHARP_TRUST_IP_MAC by default (backport v3.0)

See merge request idf/esp-idf!2721
2018-07-15 14:53:46 +08:00
Liu Zhi Fu
86a6c21e79 lwip: fix the assertion in tcp_pcb_purge()
Fix the assertion in tcp_pcb_purge().
2018-07-14 09:59:59 +08:00
Liu Zhi Fu
8cc0379da1 lwip: disable ETHARP_TRUST_IP_MAC by default
Disable ETHARP_TRUST_IP_MAC by default because:
1. The LAN peer may not be trustful
2. The LAN peer may has problem to update its ARP entry
2018-07-14 09:57:47 +08:00
Jiang Jiang Jian
e56bfadc58 Merge branch 'feature/ble_mesh_idf_v3.0' into 'release/v3.0'
Component/bt: add scan duplicate for v3.0

See merge request idf/esp-idf!2445
2018-07-13 19:10:49 +08:00
Ivan Grokhotkov
583e80708b Merge branch 'bugfix/esp_timer_set_alarm_v3.0' into 'release/v3.0'
esp_timer: remove busy loop in esp_timer_impl_set_alarm (backport v3.0)

See merge request idf/esp-idf!2726
2018-07-13 15:00:23 +08:00
zhiweijian
5cf4d8a1ec Component/bt: add scan duplicate for ble mesh in idf3.0 2018-07-12 07:35:13 +00:00
Ivan Grokhotkov
ef3c6ac276 esp_timer: test for monotonic values of esp_timer_get_timer in CI
Reduce test time by increasing overflow rate, make test more robust.
2018-07-09 15:42:30 +08:00
Ivan Grokhotkov
4129436f7e esp_timer: add test for esp_timer_impl_set_alarm
Ref https://github.com/espressif/esp-idf/issues/1891
2018-07-09 15:42:30 +08:00
Ivan Grokhotkov
0808a04ee8 esp_timer: reduce overflow value in unit tests
This allows testing for race conditions which occur near timer
overflow point more effectively.
2018-07-09 12:06:11 +08:00
Ivan Grokhotkov
c99977b67c esp_timer: don’t busy loop in esp_timer_impl_set_alarm
Previously the loop in esp_timer_impl_set_alarm was necessary to catch
the case when timer count wraps around (goes from 2^32 - 1 to 0).
Since ALARM_OVERFLOW_VAL was reduced from 2^32 - 1 to 0xefffffff,
this is no longer necessary.

Fixes https://github.com/espressif/esp-idf/issues/1891
2018-07-09 12:06:11 +08:00
Ivan Grokhotkov
8d3d3fdd4a Merge branch 'doc/eclipse_setup_v3.0' into 'release/v3.0'
doc: Clarify some Eclipse setup steps

See merge request idf/esp-idf!2680
2018-07-02 18:41:02 +08:00
Angus Gratton
c4973908e4 doc: Clarify some Eclipse setup steps 2018-07-02 12:25:25 +10:00
Ivan Grokhotkov
3bb43d5f03 Merge branch 'cherry-pick-17ab60d6' into 'release/v3.0'
nvs: don’t expect items with bad CRC to be in cache (for release/3.0)

See merge request idf/esp-idf!2572
2018-06-25 14:06:37 +08:00
Jiang Jiang Jian
209d454b5f Merge branch 'bugfix/tw22828_fix_tcp_bug_when_ip_changed_v3.0' into 'release/v3.0'
fix the bug that TCP connections don't abort when IP changed

See merge request idf/esp-idf!2574
2018-06-21 14:51:58 +08:00
Jiang Jiang Jian
b385fe0586 Merge branch 'feature/optimize_wifi_memory' into 'release/v3.0'
esp32: optimize WiFi memory

See merge request idf/esp-idf!2527
2018-06-20 18:19:22 +08:00
Liu Zhi Fu
487c4b6725 esp32: optimize WiFi memory
Optimize WiFi memory:
1. Decrease WiFi task stack size by 512 Bytes
2. Modify WiFi NVS configuration array from static to dynamic
3. Move interrupt/RX relating variables from .bss segment to .data segment
4. Modify WiFi management short buffer from static to dynamic
5. Remove some useless WiFi buffer space
2018-06-19 19:36:49 +08:00
zhangyanjiao
667846cba1 fix the bug that TCP connections don't abort when IP changed 2018-06-19 16:07:50 +08:00
Ivan Grokhotkov
ccbb261c35 Merge branch 'bugfix/nvs_failed_crc_assert' into 'master'
nvs: don’t expect items with bad CRC to be in cache

See merge request idf/esp-idf!2239

(cherry picked from commit 17ab60d642)

2c3644a0 nvs: don’t expect items with bad CRC to be in cache
2018-06-19 11:20:09 +08:00
Jiang Jiang Jian
f35fd2a6b0 Merge branch 'cherry-pick-8e7dfb23' into 'release/v3.0'
Merge branch 'bugfix/crosscore_handle_yield_iram' into 'release/v3.0'

See merge request idf/esp-idf!2545
2018-06-14 16:16:50 +08:00
Jiang Jiang Jian
5682a5ef36 Merge branch 'bugfix/crosscore_handle_yield_iram' into 'master'
esp32: Move esp_crosscore_isr_handle_yield() to IRAM

See merge request idf/esp-idf!2544

(cherry picked from commit 8e7dfb230f)

f6442abd esp32: Move esp_crosscore_isr_handle_yield() to IRAM
2018-06-13 11:54:25 +08:00
Jiang Jiang Jian
b66af09b75 Merge branch 'bugfix/tw19454_tcp_cause_int_watchdog_v3.0' into 'release/v3.0'
esp32: optimize wifi lock

See merge request idf/esp-idf!2305
2018-06-06 17:37:41 +08:00
Jiang Jiang Jian
9b5841f17c Merge branch 'bugfix/tw20393_tcp_pcb_purge_assert_v3.0' into 'release/v3.0'
Bugfix/tw20393 tcp pcb purge assert v3.0

See merge request idf/esp-idf!2324
2018-06-06 16:04:03 +08:00
Liu Zhi Fu
103de7acdc esp32: WiFi lock refactor
WiFi lock refactor to fix interrupt watchdog issue
2018-06-06 11:57:46 +08:00
Jiang Jiang Jian
c2b39f4a5f Merge branch 'bugfix/btdm_malloc_fail_lead_to_crash' into 'release/v3.0'
component/bt: Fix malloc fail lead to crash

See merge request idf/esp-idf!2487
2018-06-01 10:24:07 +08:00
xiewenxiang
2bd198d180 component/bt: Fix malloc fail lead to crash 2018-05-31 17:14:59 +08:00
Angus Gratton
5b2fee13cd Merge branch 'bugfix/btdm_a2dp_disconn_state_when_connecting_with_iphone_v3.0' into 'release/v3.0'
component/bt: Fix bug a2dp have disconnect state when connecting with iphone 7

See merge request idf/esp-idf!2385
2018-05-31 13:38:33 +08:00
Jiang Jiang Jian
6ceedabb27 Merge branch 'bugfix/btdm_memleak_of_ble_set_security_param_v3.0' into 'release/v3.0'
component/bt: Fix mem leak of esp_ble_gap_set_security_param

See merge request idf/esp-idf!2476
2018-05-30 17:56:52 +08:00
baohongde
dac71d688a component/bt: Fix mem leak of esp_ble_gap_set_security_param
cherry-pick from MR !2458
2018-05-30 15:01:01 +08:00
Jiang Jiang Jian
dc304fb3af Merge branch 'bugfix/btdm_fix_notify_memory_leak_for_v30' into 'release/v3.0'
Component/bt: fix notify memory leak for v3.0

See merge request idf/esp-idf!2437
2018-05-28 10:23:16 +08:00
zhiweijian
6ae56b61cf Component/bt: fix notify memory leak for v3.0 2018-05-24 10:54:52 +08:00
Jiang Jiang Jian
6698be57c8 Merge branch 'bugfix/fix_uart_buffer_full_flg_error_bug_v3.0' into 'release/v3.0'
Bugfix/fix uart buffer full flg error bug for v3.0

See merge request idf/esp-idf!2419
2018-05-21 11:01:58 +08:00
kooho
ef9dbff112 driver(uart):Fix the bug that uart buffer_full flag is true all the time. 2018-05-18 16:35:32 +08:00
Angus Gratton
561f8ff513 Merge branch 'bugfix/adc_i2s_v3.0' into 'release/v3.0'
driver(i2s): fix broken i2s adc mode

See merge request idf/esp-idf!2405
2018-05-16 18:17:47 +08:00
Wangjialin
945d2e697c driver(i2s): fix broken i2s adc mode
1. Move i2s reset code from i2s_stop to i2s_start.
2. add RTC API to set sw mode for ADC
3. add description for adc_power_always_on()
4. add lock for i2s dma and RTC ADC functions.
5. add ADC read task in example

reported from bbs:  https://esp32.com/viewtopic.php?f=13&t=3490&p=17522#p17522
reported from github: https://github.com/espressif/esp-idf/issues/1333

Also update some deprecated APIs for ADC.
2018-05-16 11:42:53 +08:00
Jiang Jiang Jian
94c4f32df0 Merge branch 'bugfix/update_libphy_to_v3662' into 'release/v3.0'
esp32: update libphy.a to v3662

See merge request idf/esp-idf!2370
2018-05-14 20:56:38 +08:00
baohongde
ab62202eb9 component/bt: Fix bug a2dp have disconnect state when connecting with iphone 7 2018-05-11 16:03:33 +08:00
Liu Zhi Fu
063c23deff esp32: update libphy.a
Update lib phy to v3662, including two modifications:
1. Support PHY IRAM optimization
2. Remove some debug log in noisefloor api
2018-05-09 21:23:37 +08:00
Jiang Jiang Jian
3868307efd Merge branch 'bugfix/tw20575_fix_potential_phy_calibration_bug_v3.0' into 'release/v3.0'
esp32: fix potential PHY calibration bug

See merge request idf/esp-idf!2356
2018-05-07 20:02:10 +08:00
Jiang Jiang Jian
e0c834285f Merge branch 'bugfix/wifi_fix_a_few_wifi_bugs_v3.0' into 'release/v3.0'
Fix a few WiFi bugs

See merge request idf/esp-idf!2313
2018-05-07 17:27:41 +08:00
Liu Zhi Fu
e99b4e85b9 esp32: fix potential PHY calibration bug
1. Add error log if failed to store calibration version/mac/data
2. Change the NVS calibration version/mac/data store sequence
2018-05-07 09:53:30 +08:00
Liu Zhi Fu
20ab122f80 lwip: fix tcp_pcb_purge assert
Remove the assert in tcp_pcb_purge()
2018-04-27 14:15:18 +08:00
XiaXiaotian
98dd235819 Fix a few WiFi bugs
1. copy full TIM bitmap from pp task to pm task

2. allocate mimo packet to internal memory

3. remove rc when ap not found

    close github issue: https://github.com/espressif/esp-idf/issues/1797
2018-04-26 14:19:36 +08:00
153 changed files with 4513 additions and 2118 deletions

View File

@@ -1,9 +1,9 @@
stages:
- build
- assign_test
- host_test
- unit_test
- test
- test_report
- integration_test
- deploy
variables:
@@ -34,6 +34,7 @@ variables:
python $APPLY_BOT_FILTER_SCRIPT || exit 0
before_script:
- source tools/ci/setup_python.sh
# apply bot filter in before script
- *apply_bot_filter
# add gitlab ssh key
@@ -54,6 +55,7 @@ before_script:
.do_nothing_before:
before_script: &do_nothing_before
- source tools/ci/setup_python.sh
# apply bot filter in before script
- *apply_bot_filter
- echo "Not setting up GitLab key, not fetching submodules"
@@ -61,6 +63,7 @@ before_script:
.add_gitlab_key_before:
before_script: &add_gitlab_key_before
- source tools/ci/setup_python.sh
# apply bot filter in before script
- *apply_bot_filter
- echo "Not fetching submodules"
@@ -82,12 +85,15 @@ build_template_app:
BATCH_BUILD: "1"
IDF_CI_BUILD: "1"
script:
- git clone https://github.com/espressif/esp-idf-template.git
# Set the variable for 'esp-idf-template' testing
- ESP_IDF_TEMPLATE_GIT=${ESP_IDF_TEMPLATE_GIT:-"https://github.com/espressif/esp-idf-template.git"}
- git clone ${ESP_IDF_TEMPLATE_GIT}
- cd esp-idf-template
# Try to use the same branch name for esp-idf-template that we're
# using on esp-idf. If it doesn't exist then just stick to the default
# branch
- python $CHECKOUT_REF_SCRIPT esp-idf-template
- make defconfig
# Test debug build (default)
- make all V=1
# Now test release build
@@ -133,6 +139,8 @@ build_ssc_01:
build_ssc_02:
<<: *build_ssc_template
# If you want to add new build ssc jobs, please add it into dependencies of `assign_test` and `.test_template`
build_esp_idf_tests:
<<: *build_template
artifacts:
@@ -140,7 +148,7 @@ build_esp_idf_tests:
- tools/unit-test-app/output
- components/idf_test/unit_test/TestCaseAll.yml
- components/idf_test/unit_test/CIConfigs/*.yml
expire_in: 6 mos
expire_in: 1 mos
script:
- cd tools/unit-test-app
- make help # make sure kconfig tools are built in single process
@@ -199,6 +207,7 @@ build_examples_06:
build_examples_07:
<<: *build_examples_template
# If you want to add new build example jobs, please add it into dependencies of `.example_test_template`
build_docs:
stage: build
@@ -222,54 +231,44 @@ build_docs:
- make html
- ./check_doc_warnings.sh
test_nvs_on_host:
stage: test
image: $CI_DOCKER_REGISTRY/esp32-ci-env
.host_test_template: &host_test_template
stage: host_test
image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
tags:
- nvs_host_test
- host_test
dependencies: []
test_nvs_on_host:
<<: *host_test_template
script:
- cd components/nvs_flash/test_nvs_host
- make test
test_partition_table_on_host:
stage: test
image: $CI_DOCKER_REGISTRY/esp32-ci-env
<<: *host_test_template
tags:
- build
dependencies: []
script:
- cd components/partition_table/test_gen_esp32part_host
- ./gen_esp32part_tests.py
test_wl_on_host:
stage: test
image: $CI_DOCKER_REGISTRY/esp32-ci-env
tags:
- wl_host_test
<<: *host_test_template
artifacts:
paths:
- components/wear_levelling/test_wl_host/coverage_report.zip
dependencies: []
script:
- cd components/wear_levelling/test_wl_host
- make test
test_multi_heap_on_host:
stage: test
image: $CI_DOCKER_REGISTRY/esp32-ci-env
tags:
- wl_host_test
<<: *host_test_template
script:
- cd components/heap/test_multi_heap_host
- ./test_all_configs.sh
test_build_system:
stage: test
image: $CI_DOCKER_REGISTRY/esp32-ci-env
tags:
- build_test
dependencies: []
<<: *host_test_template
script:
- ${IDF_PATH}/tools/ci/test_configure_ci_environment.sh
- rm -rf test_build_system
@@ -277,61 +276,7 @@ test_build_system:
- cd test_build_system
- ${IDF_PATH}/tools/ci/test_build_system.sh
test_report:
stage: test_report
image: $CI_DOCKER_REGISTRY/esp32-ci-env
tags:
- report
only:
- master
- triggers
- /^release\/v/
- /^v\d+\.\d+(\.\d+)?($|-)/
variables:
LOG_PATH: "$CI_PROJECT_DIR/$CI_COMMIT_SHA"
TEST_CASE_FILE_PATH: "$CI_PROJECT_DIR/components/idf_test"
REPORT_PATH: "$CI_PROJECT_DIR/CI_Test_Report"
MODULE_UPDATE_FILE: "$CI_PROJECT_DIR/tools/unit-test-app/tools/ModuleDefinition.yml"
#dependencies:
#We need all UT* and IT* artifacts except for only a few other
artifacts:
when: always
paths:
- $REPORT_PATH
- $LOG_PATH
expire_in: 12 mos
script:
# calc log path
- VER_NUM=`git rev-list HEAD | wc -l | awk '{print $1}'`
- SHA_ID=`echo $CI_COMMIT_SHA | cut -c 1-7`
- REVISION="${VER_NUM}_${SHA_ID}"
# replace / to _ in branch name
- ESCAPED_BRANCH_NAME=`echo $CI_COMMIT_REF_NAME | sed 's/\//___/g'`
# result path and artifacts path
- RESULT_PATH="$CI_PROJECT_NAME/$ESCAPED_BRANCH_NAME/$REVISION"
- ARTIFACTS_PATH="$GITLAB_HTTP_SERVER/idf/esp-idf/builds/$CI_JOB_ID/artifacts/browse/$CI_COMMIT_SHA"
# clone test bench
- git clone $GITLAB_SSH_SERVER/yinling/auto_test_script.git
- cd auto_test_script
- python $CHECKOUT_REF_SCRIPT auto_test_script
# generate report
- TEST_RESULT=Pass
- python CITestReport.py -l $LOG_PATH -t $TEST_CASE_FILE_PATH -p $REPORT_PATH -r $RESULT_PATH -a $ARTIFACTS_PATH -m $MODULE_UPDATE_FILE || TEST_RESULT=Fail
# commit to CI-test-result project
- git clone $GITLAB_SSH_SERVER/qa/CI-test-result.git
- rm -rf "CI-test-result/RawData/$RESULT_PATH"
- cp -R $CI_PROJECT_NAME CI-test-result/RawData
- cd CI-test-result
# config git user
- git config --global user.email "ci-test-result@espressif.com"
- git config --global user.name "ci-test-result"
# commit test result
- git add .
- git commit . -m "update test result for $CI_PROJECT_NAME/$CI_COMMIT_REF_NAME/$CI_COMMIT_SHA, pipeline ID $CI_PIPELINE_ID" || exit 0
- git push origin master
- test "${TEST_RESULT}" = "Pass" || exit 1
push_master_to_github:
push_to_github:
stage: deploy
image: $CI_DOCKER_REGISTRY/esp32-ci-env
tags:
@@ -342,8 +287,6 @@ push_master_to_github:
- /^v\d+\.\d+(\.\d+)?($|-)/
when: on_success
dependencies: []
variables:
GITHUB_PUSH_REFS: refs/remotes/origin/release refs/remotes/origin/master
before_script: *do_nothing_before
script:
- mkdir -p ~/.ssh
@@ -354,16 +297,11 @@ push_master_to_github:
- echo -e "Host github.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
- git remote remove github &>/dev/null || true
- git remote add github git@github.com:espressif/esp-idf.git
# What the next line of script does: goes through the list of refs for all branches we push to github,
# generates a snippet of shell which is evaluated. The snippet checks CI_COMMIT_SHA against the SHA
# (aka objectname) at tip of each branch, and if any SHAs match then it checks out the local branch
# and then pushes that ref to a corresponding github branch
- eval $(git for-each-ref --shell bash --format 'if [ $CI_COMMIT_SHA == %(objectname) ]; then git checkout -B %(refname:strip=3); git push --follow-tags github %(refname:strip=3); fi;' $GITHUB_PUSH_REFS)
- tools/ci/push_to_github.sh
deploy_docs:
stage: deploy
image: $CI_DOCKER_REGISTRY/esp32-ci-env
stage: host_test
image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
tags:
- deploy
only:
@@ -389,8 +327,8 @@ deploy_docs:
- ssh $DOCS_SERVER -x "cd $DOCS_PATH && tar xzvf $GIT_VER.tar.gz && rm -f latest && ln -s $GIT_VER latest"
check_doc_links:
stage: test
image: $CI_DOCKER_REGISTRY/esp32-ci-env
stage: host_test
image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
tags:
- check_doc_links
only:
@@ -478,21 +416,28 @@ assign_test:
- python CIAssignTestCases.py -t $IDF_PATH/components/idf_test/integration_test -c $IDF_PATH/.gitlab-ci.yml -b $IDF_PATH/SSC/ssc_bin
.example_test_template: &example_test_template
stage: test
stage: integration_test
when: on_success
only:
- master
- /^release\/v/
- /^v\d+\.\d+(\.\d+)?($|-)/
- triggers
# gitlab ci do not support match job with RegEx or wildcard now in dependencies.
# we have a lot build example jobs and the binaries them exceed the limitation of artifacts.
# we can't artifact them in one job. For example test jobs, download all artifacts from previous stages.
dependencies:
- assign_test
- build_examples_00
- build_examples_01
- build_examples_02
- build_examples_03
- build_examples_04
- build_examples_05
- build_examples_06
- build_examples_07
artifacts:
when: always
paths:
- $LOG_PATH
expire_in: 6 mos
expire_in: 1 mos
variables:
TEST_FW_PATH: "$CI_PROJECT_DIR/tools/tiny-test-fw"
TEST_CASE_PATH: "$CI_PROJECT_DIR/examples"
@@ -506,14 +451,13 @@ assign_test:
- python Runner.py $TEST_CASE_PATH -c $CONFIG_FILE
.test_template: &test_template
stage: test
stage: integration_test
when: on_success
only:
- master
- /^release\/v/
- /^v\d+\.\d+(\.\d+)?($|-)/
- triggers
allow_failure: true
dependencies:
- assign_test
- build_ssc_00
@@ -523,7 +467,7 @@ assign_test:
when: always
paths:
- $LOG_PATH
expire_in: 6 mos
expire_in: 1 mos
variables:
LOCAL_ENV_CONFIG_PATH: "$CI_PROJECT_DIR/ci-test-runner-configs/$CI_RUNNER_DESCRIPTION/ESP32_IDF"
LOG_PATH: "$CI_PROJECT_DIR/$CI_COMMIT_SHA"
@@ -564,7 +508,7 @@ nvs_compatible_test:
paths:
- $LOG_PATH
- nvs_wifi.bin
expire_in: 6 mos
expire_in: 1 mos
tags:
- ESP32_IDF
- NVS_Compatible

View File

@@ -4,22 +4,27 @@
ESP-IDF is the official development framework for the [ESP32](https://espressif.com/en/products/hardware/esp32/overview) chip.
# Developing With the ESP-IDF
# Developing With ESP-IDF
## Setting Up ESP-IDF
See setup guides for detailed instructions to set up the ESP-IDF:
* [Windows Setup Guide](https://esp-idf.readthedocs.io/en/latest/get-started/windows-setup.html)
* [Mac OS Setup Guide](https://esp-idf.readthedocs.io/en/latest/get-started/macos-setup.html)
* [Linux Setup Guide](https://esp-idf.readthedocs.io/en/latest/get-started/linux-setup.html)
* [Getting Started Guide for the stable ESP-IDF version](https://docs.espressif.com/projects/esp-idf/en/stable/get-started/)
* [Getting Started Guide for the latest (master branch) ESP-IDF version](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/)
## Finding a Project
As well as the [esp-idf-template](https://github.com/espressif/esp-idf-template) project mentioned in the setup guide, ESP-IDF comes with some example projects in the [examples](examples) directory.
As well as the [esp-idf-template](https://github.com/espressif/esp-idf-template) project mentioned in Getting Started, ESP-IDF comes with some example projects in the [examples](examples) directory.
Once you've found the project you want to work with, change to its directory and you can configure and build it.
To start your own project based on an example, copy the example project directory outside of the ESP-IDF directory.
# Quick Reference
See the Getting Started guide links above for a detailed setup guide. This is a quick reference for common commands when working with ESP-IDF projects:
## Configuring the Project
`make menuconfig`
@@ -36,15 +41,17 @@ Once done configuring, press Escape multiple times to exit and say "Yes" to save
## Compiling the Project
`make all`
`make -j4 all`
... will compile app, bootloader and generate a partition table based on the config.
NOTE: The `-j4` option causes `make` to run 4 parallel jobs. This is much faster than the default single job. The recommended number to pass to this option is `-j(number of CPUs + 1)`.
## Flashing the Project
When `make all` finishes, it will print a command line to use esptool.py to flash the chip. However you can also do this from make by running:
`make flash`
`make -j4 flash`
This will flash the entire project (app, bootloader and partition table) to a new chip. The settings for serial port flashing can be configured with `make menuconfig`.
@@ -56,24 +63,24 @@ The `make monitor` target uses the [idf_monitor tool](https://esp-idf.readthedoc
Exit the monitor by typing Ctrl-].
To flash and monitor output in one pass, you can run:
To build, flash and monitor output in one pass, you can run:
`make flash monitor`
`make -j4 flash monitor`
## Compiling & Flashing Just the App
## Compiling & Flashing Only the App
After the initial flash, you may just want to build and flash just your app, not the bootloader and partition table:
* `make app` - build just the app.
* `make app-flash` - flash just the app.
`make app-flash` will automatically rebuild the app if it needs it.
`make app-flash` will automatically rebuild the app if any source files have changed.
(In normal development there's no downside to reflashing the bootloader and partition table each time, if they haven't changed.)
## Parallel Builds
ESP-IDF supports compiling multiple files in parallel, so all of the above commands can be run as `make -jN` where `N` is the number of parallel make processes to run (generally N should be equal to or one more than the number of CPU cores in your system.)
ESP-IDF supports compiling multiple files in parallel, so all of the above commands can be run as `make -jN` where `N` is the number of parallel make processes to run (generally N should be equal to the number of CPU cores in your system, plus one.)
Multiple make functions can be combined into one. For example: to build the app & bootloader using 5 jobs in parallel, then flash everything, and then display serial output from the ESP32 run:

View File

@@ -27,6 +27,7 @@ SECTIONS
.iram1.text :
{
. = ALIGN (16);
_loader_text_start = ABSOLUTE(.);
*(.entry.text)
*(.init.literal)
*(.init)
@@ -126,6 +127,7 @@ SECTIONS
*(.fini)
*(.gnu.version)
_text_end = ABSOLUTE(.);
_loader_text_end = ABSOLUTE(.);
_etext = .;
} > iram_seg

View File

@@ -35,6 +35,7 @@
#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";
@@ -65,6 +66,11 @@ static void write_status_8b_wrsr2(unsigned new_status);
/* Write 16 bit status using WRSR */
static void write_status_16b_wrsr(unsigned new_status);
/* Read 8 bit status of XM25QU64A */
static unsigned read_status_8b_xmc25qu64a();
/* Write 8 bit status of XM25QU64A */
static void write_status_8b_xmc25qu64a(unsigned new_status);
#define ESP32_D2WD_WP_GPIO 7 /* ESP32-D2WD has this GPIO wired to WP pin of flash */
#ifndef CONFIG_BOOTLOADER_SPI_WP_PIN // Set in menuconfig if SPI flasher config is set to a quad mode
@@ -84,11 +90,12 @@ static void write_status_16b_wrsr(unsigned new_status);
Searching of this table stops when the first match is found.
*/
const static qio_info_t chip_data[] = {
/* Manufacturer, mfg_id, flash_id, id mask, Read Status, Write Status, QIE Bit */
{ "MXIC", 0xC2, 0x2000, 0xFF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 },
{ "ISSI", 0x9D, 0x4000, 0xCF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 }, /* IDs 0x40xx, 0x70xx */
{ "WinBond", 0xEF, 0x4000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 },
{ "GD", 0xC8, 0x6000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 },
/* Manufacturer, mfg_id, flash_id, id mask, Read Status, Write Status, QIE Bit */
{ "MXIC", 0xC2, 0x2000, 0xFF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 },
{ "ISSI", 0x9D, 0x4000, 0xCF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 }, /* IDs 0x40xx, 0x70xx */
{ "WinBond", 0xEF, 0x4000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 },
{ "GD", 0xC8, 0x6000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 },
{ "XM25QU64A", 0x20, 0x3817, 0xFFFF, read_status_8b_xmc25qu64a, write_status_8b_xmc25qu64a, 6 },
/* Final entry is default entry, if no other IDs have matched.
@@ -96,7 +103,7 @@ const static qio_info_t chip_data[] = {
GigaDevice (mfg ID 0xC8, flash IDs including 4016),
FM25Q32 (QOUT mode only, mfg ID 0xA1, flash IDs including 4016)
*/
{ NULL, 0xFF, 0xFFFF, 0xFFFF, read_status_8b_rdsr2, write_status_8b_wrsr2, 1 },
{ NULL, 0xFF, 0xFFFF, 0xFFFF, read_status_8b_rdsr2, write_status_8b_wrsr2, 1 },
};
#define NUM_CHIPS (sizeof(chip_data) / sizeof(qio_info_t))
@@ -252,6 +259,24 @@ static void write_status_16b_wrsr(unsigned new_status)
execute_flash_command(CMD_WRSR, new_status, 16, 0);
}
static unsigned read_status_8b_xmc25qu64a()
{
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 */
return read_status;
}
static void write_status_8b_xmc25qu64a(unsigned new_status)
{
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);
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)
{
SPIFLASH.user2.usr_command_value = command;

View File

@@ -0,0 +1,34 @@
// Copyright 2018 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 <stddef.h>
/**
* @brief Check if half-open intervals overlap
*
* @param start1 interval 1 start
* @param end1 interval 1 end
* @param start2 interval 2 start
* @param end2 interval 2 end
* @return true iff [start1; end1) overlaps [start2; end2)
*/
static inline bool bootloader_util_regions_overlap(
const intptr_t start1, const intptr_t end1,
const intptr_t start2, const intptr_t end2)
{
return (end1 > start2 && end2 > start1) ||
!(end1 <= start2 || end2 <= start1);
}

View File

@@ -81,6 +81,8 @@ typedef struct {
_Static_assert(sizeof(esp_image_header_t) == 24, "binary image header should be 24 bytes");
#define ESP_IMAGE_HASH_LEN 32 /* Length of the appended SHA-256 digest */
/* Header of binary image segment */
typedef struct {
uint32_t load_addr;
@@ -142,6 +144,16 @@ esp_err_t esp_image_load(esp_image_load_mode_t mode, const esp_partition_pos_t *
*/
esp_err_t esp_image_verify_bootloader(uint32_t *length);
/**
* @brief Verify the bootloader image.
*
* @param[out] Metadata for the image. Only valid if result is ESP_OK.
*
* @return As per esp_image_load_metadata().
*/
esp_err_t esp_image_verify_bootloader_data(esp_image_metadata_t *data);
typedef struct {
uint32_t drom_addr;
uint32_t drom_load_addr;

View File

@@ -23,10 +23,11 @@
#include <bootloader_flash.h>
#include <bootloader_random.h>
#include <bootloader_sha.h>
#include "bootloader_util.h"
static const char *TAG = "esp_image";
#define HASH_LEN 32 /* SHA-256 digest length */
#define HASH_LEN ESP_IMAGE_HASH_LEN
#define SIXTEEN_MB 0x1000000
#define ESP_ROM_CHECKSUM_INITIAL 0xEF
@@ -42,6 +43,10 @@ static const char *TAG = "esp_image";
(Means loaded code isn't executable until after the secure boot check.)
*/
static uint32_t ram_obfs_value[2];
/* Range of IRAM used by the loader, defined in ld script */
extern int _loader_text_start;
extern int _loader_text_end;
#endif
/* Return true if load_addr is an address the bootloader should load into */
@@ -286,18 +291,41 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
(do_load)?"load":(is_mapping)?"map":"");
}
#ifdef BOOTLOADER_BUILD
/* Before loading segment, check it doesn't clobber bootloader RAM. */
if (do_load) {
/* Before loading segment, check it doesn't clobber bootloader RAM... */
uint32_t end_addr = load_addr + data_len;
if (end_addr < 0x40000000) {
const intptr_t load_end = load_addr + data_len;
if (load_end <= (intptr_t) SOC_DIRAM_DRAM_HIGH) {
/* Writing to DRAM */
intptr_t sp = (intptr_t)get_sp();
if (end_addr > sp - STACK_LOAD_HEADROOM) {
ESP_LOGE(TAG, "Segment %d end address 0x%08x too high (bootloader stack 0x%08x liimit 0x%08x)",
index, end_addr, sp, sp - STACK_LOAD_HEADROOM);
if (load_end > sp - STACK_LOAD_HEADROOM) {
/* Bootloader .data/.rodata/.bss is above the stack, so this
* also checks that we aren't overwriting these segments.
*
* TODO: This assumes specific arrangement of sections we have
* in the ESP32. Rewrite this in a generic way to support other
* layouts.
*/
ESP_LOGE(TAG, "Segment %d end address 0x%08x too high (bootloader stack 0x%08x limit 0x%08x)",
index, load_end, sp, sp - STACK_LOAD_HEADROOM);
return ESP_ERR_IMAGE_INVALID;
}
} else {
/* Writing to IRAM */
const intptr_t loader_iram_start = (intptr_t) &_loader_text_start;
const intptr_t loader_iram_end = (intptr_t) &_loader_text_end;
if (bootloader_util_regions_overlap(loader_iram_start, loader_iram_end,
load_addr, load_end)) {
ESP_LOGE(TAG, "Segment %d (0x%08x-0x%08x) overlaps bootloader IRAM (0x%08x-0x%08x)",
index, load_addr, load_end, loader_iram_start, loader_iram_end);
return ESP_ERR_IMAGE_INVALID;
}
}
}
#endif // BOOTLOADER_BUILD
#ifndef BOOTLOADER_BUILD
uint32_t free_page_count = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA);
ESP_LOGD(TAG, "free data page_count 0x%08x",free_page_count);
@@ -441,19 +469,28 @@ static bool should_load(uint32_t load_addr)
esp_err_t esp_image_verify_bootloader(uint32_t *length)
{
esp_image_metadata_t data;
const esp_partition_pos_t bootloader_part = {
.offset = ESP_BOOTLOADER_OFFSET,
.size = ESP_PARTITION_TABLE_OFFSET - ESP_BOOTLOADER_OFFSET,
};
esp_err_t err = esp_image_load(ESP_IMAGE_VERIFY,
&bootloader_part,
&data);
esp_err_t err = esp_image_verify_bootloader_data(&data);
if (length != NULL) {
*length = (err == ESP_OK) ? data.image_len : 0;
}
return err;
}
esp_err_t esp_image_verify_bootloader_data(esp_image_metadata_t *data)
{
if (data == NULL) {
return ESP_ERR_INVALID_ARG;
}
const esp_partition_pos_t bootloader_part = {
.offset = ESP_BOOTLOADER_OFFSET,
.size = ESP_PARTITION_TABLE_OFFSET - ESP_BOOTLOADER_OFFSET,
};
return esp_image_load(ESP_IMAGE_VERIFY,
&bootloader_part,
data);
}
static esp_err_t verify_checksum(bootloader_sha256_handle_t sha_handle, uint32_t checksum_word, esp_image_metadata_t *data)
{
uint32_t unpadded_length = data->image_len;

View File

@@ -62,6 +62,11 @@ esp_err_t esp_flash_encrypt_check_and_update(void)
static esp_err_t initialise_flash_encryption(void)
{
if (REG_READ(EFUSE_BLK0_RDATA6_REG) & EFUSE_CODING_SCHEME_M) {
ESP_LOGE(TAG, "Flash Encryption is currently not supported on hardware with 3/4 Coding Scheme (CODING_SCHEME efuse set)");
return ESP_ERR_NOT_SUPPORTED;
}
/* Before first flash encryption pass, need to initialise key & crypto config */
/* Generate key */

View File

@@ -50,7 +50,7 @@ static bool secure_boot_generate(uint32_t image_len){
const uint32_t *image;
/* hardware secure boot engine only takes full blocks, so round up the
image length. The additional data should all be 0xFF.
image length. The additional data should all be 0xFF (or the appended SHA, if it falls in the same block).
*/
if (image_len % sizeof(digest.iv) != 0) {
image_len = (image_len / sizeof(digest.iv) + 1) * sizeof(digest.iv);
@@ -104,14 +104,20 @@ static inline void burn_efuses()
esp_err_t esp_secure_boot_permanently_enable(void) {
esp_err_t err;
uint32_t image_len = 0;
if (esp_secure_boot_enabled())
{
ESP_LOGI(TAG, "bootloader secure boot is already enabled, continuing..");
return ESP_OK;
}
err = esp_image_verify_bootloader(&image_len);
if (REG_READ(EFUSE_BLK0_RDATA6_REG) & EFUSE_CODING_SCHEME_M) {
ESP_LOGE(TAG, "Secure Boot is currently not supported on hardware with 3/4 Coding Scheme (CODING_SCHEME efuse set)");
return ESP_ERR_NOT_SUPPORTED;
}
/* Verify the bootloader */
esp_image_metadata_t bootloader_data = { 0 };
err = esp_image_verify_bootloader_data(&bootloader_data);
if (err != ESP_OK) {
ESP_LOGE(TAG, "bootloader image appears invalid! error %d", err);
return err;
@@ -150,6 +156,11 @@ esp_err_t esp_secure_boot_permanently_enable(void) {
}
ESP_LOGI(TAG, "Generating secure boot digest...");
uint32_t image_len = bootloader_data.image_len;
if(bootloader_data.image.hash_appended) {
/* Secure boot digest doesn't cover the hash */
image_len -= ESP_IMAGE_HASH_LEN;
}
if (false == secure_boot_generate(image_len)){
ESP_LOGE(TAG, "secure boot generation failed");
return ESP_FAIL;

View File

@@ -13,6 +13,7 @@
#include "freertos/xtensa_api.h"
#include "unity.h"
#include "bootloader_util.h"
#include "esp_partition.h"
#include "esp_ota_ops.h"
#include "esp_image_format.h"
@@ -47,3 +48,21 @@ TEST_CASE("Verify unit test app image", "[bootloader_support]")
TEST_ASSERT_TRUE(data.image_len <= running->size);
}
TEST_CASE("Test regions_overlap", "[bootloader_support]")
{
TEST_ASSERT( bootloader_util_regions_overlap(1, 2, 1, 2) );
TEST_ASSERT( bootloader_util_regions_overlap(1, 2, 0, 2) );
TEST_ASSERT( bootloader_util_regions_overlap(1, 2, 1, 3) );
TEST_ASSERT( bootloader_util_regions_overlap(1, 2, 0, 3) );
TEST_ASSERT( bootloader_util_regions_overlap(0, 2, 1, 2) );
TEST_ASSERT( bootloader_util_regions_overlap(1, 3, 1, 2) );
TEST_ASSERT( bootloader_util_regions_overlap(0, 3, 1, 2) );
TEST_ASSERT( !bootloader_util_regions_overlap(2, 3, 1, 2) );
TEST_ASSERT( !bootloader_util_regions_overlap(1, 2, 2, 3) );
TEST_ASSERT( !bootloader_util_regions_overlap(3, 4, 1, 2) );
TEST_ASSERT( !bootloader_util_regions_overlap(1, 2, 3, 4) );
}

View File

@@ -156,6 +156,38 @@ config BT_ACL_CONNECTIONS
help
Maximum BT/BLE connection count
config BLE_SCAN_DUPLICATE
bool "BLE Scan Duplicate Options "
depends on BLUEDROID_ENABLED
default y
help
This select enables parameters setting of BLE scan duplicate.
config DUPLICATE_SCAN_CACHE_SIZE
int "Maximum number of devices in scan duplicate filter"
depends on BLE_SCAN_DUPLICATE
range 10 1000
default 500
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.
config BLE_MESH_SCAN_DUPLICATE_EN
bool "Special duplicate scan mechanism for BLE Mesh scan"
depends on BLE_SCAN_DUPLICATE
default n
help
This enables the BLE scan duplicate for special BLE Mesh scan.
config MESH_DUPLICATE_SCAN_CACHE_SIZE
int "Maximum number of Mesh adv packets in scan duplicate filter"
depends on BLE_MESH_SCAN_DUPLICATE_EN
range 10 200
default 50
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.
config SMP_ENABLE
bool
depends on BLUEDROID_ENABLED

View File

@@ -219,7 +219,7 @@ typedef struct {
esp_ble_adv_type_t adv_type; /*!< Advertising type */
esp_ble_addr_type_t own_addr_type; /*!< Owner bluetooth device address type */
esp_bd_addr_t peer_addr; /*!< Peer device bluetooth device address */
esp_ble_addr_type_t peer_addr_type; /*!< Peer device bluetooth device address type */
esp_ble_addr_type_t peer_addr_type; /*!< Peer device bluetooth device address type, only support public address type and random address type */
esp_ble_adv_channel_t channel_map; /*!< Advertising channel map */
esp_ble_adv_filter_t adv_filter_policy; /*!< Advertising filter policy */
} esp_ble_adv_params_t;
@@ -264,6 +264,13 @@ typedef enum {
3. directed advertising packets addressed to this device.*/
} esp_ble_scan_filter_t;
/// Ble scan duplicate type
typedef enum {
BLE_SCAN_DUPLICATE_DISABLE = 0x0, /*!< the Link Layer should generate advertising reports to the host for each packet received */
BLE_SCAN_DUPLICATE_ENABLE = 0x1, /*!< the Link Layer should filter out duplicate advertising reports to the Host */
BLE_SCAN_DUPLICATE_MAX = 0x2, /*!< 0x02 0xFF, Reserved for future use */
} esp_ble_scan_duplicate_t;
/// Ble scan parameters
typedef struct {
esp_ble_scan_type_t scan_type; /*!< Scan type */
@@ -279,6 +286,9 @@ typedef struct {
Range: 0x0004 to 0x4000 Default: 0x0010 (10 ms)
Time = N * 0.625 msec
Time Range: 2.5 msec to 10240 msec */
esp_ble_scan_duplicate_t scan_duplicate; /*!< The Scan_Duplicates parameter controls whether the Link Layer should filter out
duplicate advertising reports (BLE_SCAN_DUPLICATE_ENABLE) to the Host, or if the Link Layer should generate
advertising reports for each packet received */
} esp_ble_scan_params_t;
/// Connection update parameters

View File

@@ -4568,6 +4568,7 @@ void bta_dm_ble_set_scan_fil_params(tBTA_DM_MSG *p_data)
p_data->ble_set_scan_fil_params.scan_window,
p_data->ble_set_scan_fil_params.scan_mode,
p_data->ble_set_scan_fil_params.addr_type_own,
p_data->ble_set_scan_fil_params.scan_duplicate_filter,
p_data->ble_set_scan_fil_params.scan_filter_policy,
p_data->ble_set_scan_fil_params.scan_param_setup_cback);
}

View File

@@ -968,6 +968,7 @@ void BTA_DmSetBleScanParams(tGATT_IF client_if, UINT32 scan_interval,
** scan_interval - scan interval
** scan_window - scan window
** scan_mode - scan mode
** scan_duplicate_filter - scan duplicate filter
** scan_param_setup_status_cback - Set scan param status callback
**
** Returns void
@@ -975,7 +976,7 @@ void BTA_DmSetBleScanParams(tGATT_IF client_if, UINT32 scan_interval,
*******************************************************************************/
void BTA_DmSetBleScanFilterParams(tGATT_IF client_if, UINT32 scan_interval,
UINT32 scan_window, tBLE_SCAN_MODE scan_mode, UINT8 scan_fil_poilcy,
UINT8 addr_type_own, tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback)
UINT8 addr_type_own, UINT8 scan_duplicate_filter, tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback)
{
tBTA_DM_API_BLE_SCAN_FILTER_PARAMS *p_msg;
@@ -987,6 +988,7 @@ void BTA_DmSetBleScanFilterParams(tGATT_IF client_if, UINT32 scan_interval,
p_msg->scan_window = scan_window;
p_msg->scan_mode = scan_mode;
p_msg->addr_type_own = addr_type_own;
p_msg->scan_duplicate_filter = scan_duplicate_filter;
p_msg->scan_filter_policy = scan_fil_poilcy;
p_msg->scan_param_setup_cback = scan_param_setup_cback;

View File

@@ -485,6 +485,7 @@ typedef struct {
UINT32 scan_window;
tBLE_SCAN_MODE scan_mode;
UINT8 addr_type_own;
UINT8 scan_duplicate_filter;
UINT8 scan_filter_policy;
tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback;
} tBTA_DM_API_BLE_SCAN_FILTER_PARAMS;

View File

@@ -702,6 +702,10 @@ void bta_gatts_indicate_handle (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg)
APPL_TRACE_ERROR("%s, malloc failed", __func__);
}
(*p_rcb->p_cback)(BTA_GATTS_CONF_EVT, &cb_data);
if (cb_data.req_data.value != NULL) {
osi_free(cb_data.req_data.value);
cb_data.req_data.value = NULL;
}
}
} else {
APPL_TRACE_ERROR("Not an registered servce attribute ID: 0x%04x",

View File

@@ -1902,6 +1902,7 @@ extern void BTA_DmSetBleScanParams(tGATT_IF client_if, UINT32 scan_interval,
** scan_interval - scan interval
** scan_window - scan window
** scan_mode - scan mode
** scan_duplicate_filter - scan duplicate filter
** scan_param_setup_status_cback - Set scan param status callback
**
** Returns void
@@ -1909,7 +1910,7 @@ extern void BTA_DmSetBleScanParams(tGATT_IF client_if, UINT32 scan_interval,
*******************************************************************************/
extern void BTA_DmSetBleScanFilterParams(tGATT_IF client_if, UINT32 scan_interval,
UINT32 scan_window, tBLE_SCAN_MODE scan_mode, UINT8 scan_fil_poilcy,
UINT8 addr_type_own, tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback);
UINT8 addr_type_own, UINT8 scan_duplicate_filter, tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback);
/*******************************************************************************

View File

@@ -175,6 +175,10 @@ static void btc_dm_remove_ble_bonding_keys(void)
static void btc_dm_save_ble_bonding_keys(void)
{
if(!(pairing_cb.ble.is_penc_key_rcvd || pairing_cb.ble.is_pid_key_rcvd || pairing_cb.ble.is_pcsrk_key_rcvd ||
pairing_cb.ble.is_lenc_key_rcvd || pairing_cb.ble.is_lcsrk_key_rcvd || pairing_cb.ble.is_lidk_key_rcvd)) {
return ;
}
bt_bdaddr_t bd_addr;
bdcpy(bd_addr.address, pairing_cb.bd_addr);

View File

@@ -41,7 +41,9 @@ static void btc_enable_bluetooth(void)
static void btc_disable_bluetooth(void)
{
#if (SMP_INCLUDED)
btc_config_shut_down();
#endif /* #if (SMP_INCLUDED) */
if (BTA_DisableBluetooth() != BTA_SUCCESS) {
future_ready(*btc_main_get_future_p(BTC_MAIN_DISABLE_FUTURE), FUTURE_FAIL);
}

View File

@@ -208,7 +208,7 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
blufi_env.frag_size = p_data->req_data.p_data->mtu - BLUFI_MTU_RESERVED_SIZE;
break;
case BTA_GATTS_CONF_EVT:
LOG_DEBUG("CONIRM EVT\n");
LOG_DEBUG("CONFIRM EVT\n");
/* Nothing */
break;
case BTA_GATTS_CREATE_EVT:

View File

@@ -38,6 +38,7 @@
#include "bt_utils.h"
#include "btc_common.h"
#include "btc_manage.h"
#include "alarm.h"
#if BTC_AV_INCLUDED
@@ -80,7 +81,7 @@ typedef struct {
} btc_av_cb_t;
typedef struct {
bt_bdaddr_t *target_bda;
bt_bdaddr_t target_bda;
uint16_t uuid;
} btc_av_connect_req_t;
@@ -88,7 +89,8 @@ typedef struct {
** Static variables
******************************************************************************/
static btc_av_cb_t btc_av_cb = {0};
static TIMER_LIST_ENT tle_av_open_on_rc;
static osi_alarm_t *tle_av_open_on_rc = NULL;
/* both interface and media task needs to be ready to alloc incoming request */
#define CHECK_BTAV_INIT() do \
@@ -203,19 +205,18 @@ UNUSED_ATTR static const char *dump_av_sm_event_name(btc_av_sm_event_t event)
** Returns void
**
*******************************************************************************/
static void btc_initiate_av_open_tmr_hdlr(TIMER_LIST_ENT *tle)
static void btc_initiate_av_open_tmr_hdlr(void *arg)
{
UNUSED(arg);
BD_ADDR peer_addr;
UNUSED(tle);
btc_av_connect_req_t connect_req;
UNUSED(tle);
/* is there at least one RC connection - There should be */
if (btc_rc_get_connected_peer(peer_addr)) {
LOG_DEBUG("%s Issuing connect to the remote RC peer", __FUNCTION__);
/* In case of AVRCP connection request, we will initiate SRC connection */
connect_req.target_bda = (bt_bdaddr_t *)&peer_addr;
memcpy(connect_req.target_bda.address, peer_addr, sizeof(bt_bdaddr_t));
connect_req.uuid = UUID_SERVCLASS_AUDIO_SOURCE;
btc_sm_dispatch(btc_av_cb.sm_handle, BTC_AV_CONNECT_REQ_EVT, (char *)&connect_req);
btc_dispatch_sm_event(BTC_AV_CONNECT_REQ_EVT, &connect_req, sizeof(btc_av_connect_req_t));
} else {
LOG_ERROR("%s No connected RC peers", __FUNCTION__);
}
@@ -289,7 +290,7 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
case BTA_AV_PENDING_EVT:
case BTC_AV_CONNECT_REQ_EVT: {
if (event == BTC_AV_CONNECT_REQ_EVT) {
memcpy(&btc_av_cb.peer_bda, ((btc_av_connect_req_t *)p_data)->target_bda,
memcpy(&btc_av_cb.peer_bda, &((btc_av_connect_req_t *)p_data)->target_bda,
sizeof(bt_bdaddr_t));
BTA_AvOpen(btc_av_cb.peer_bda.address, btc_av_cb.bta_handle,
TRUE, BTA_SEC_AUTHENTICATE, ((btc_av_connect_req_t *)p_data)->uuid);
@@ -313,10 +314,8 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
*/
LOG_DEBUG("BTA_AV_RC_OPEN_EVT received w/o AV");
memset(&tle_av_open_on_rc, 0, sizeof(tle_av_open_on_rc));
tle_av_open_on_rc.param = (UINT32)btc_initiate_av_open_tmr_hdlr;
btu_start_timer(&tle_av_open_on_rc, BTU_TTYPE_USER_FUNC,
BTC_TIMEOUT_AV_OPEN_ON_RC_SECS);
tle_av_open_on_rc = osi_alarm_new("AVconn", btc_initiate_av_open_tmr_hdlr, NULL, BTC_TIMEOUT_AV_OPEN_ON_RC_SECS * 1000);
osi_alarm_set(tle_av_open_on_rc, BTC_TIMEOUT_AV_OPEN_ON_RC_SECS * 1000);
btc_rc_handler(event, p_data);
break;
@@ -329,9 +328,9 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
break;
case BTA_AV_RC_CLOSE_EVT:
if (tle_av_open_on_rc.in_use) {
LOG_DEBUG("BTA_AV_RC_CLOSE_EVT: Stopping AV timer.");
btu_stop_timer(&tle_av_open_on_rc);
if (tle_av_open_on_rc) {
osi_alarm_free(tle_av_open_on_rc);
tle_av_open_on_rc = NULL;
}
btc_rc_handler(event, p_data);
break;
@@ -616,7 +615,7 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
break;
case BTC_AV_CONNECT_REQ_EVT:
if (memcmp ((bt_bdaddr_t *)p_data, &(btc_av_cb.peer_bda),
if (memcmp (&((btc_av_connect_req_t *)p_data)->target_bda, &(btc_av_cb.peer_bda),
sizeof(btc_av_cb.peer_bda)) == 0) {
LOG_DEBUG("%s: Ignore BTC_AVCONNECT_REQ_EVT for same device\n", __func__);
} else {
@@ -972,7 +971,7 @@ bt_status_t btc_a2d_sink_init(void)
static bt_status_t connect_int(bt_bdaddr_t *bd_addr, uint16_t uuid)
{
btc_av_connect_req_t connect_req;
connect_req.target_bda = bd_addr;
memcpy(&connect_req.target_bda, bd_addr, sizeof(bt_bdaddr_t));
connect_req.uuid = uuid;
LOG_DEBUG("%s\n", __FUNCTION__);
@@ -1001,7 +1000,6 @@ bt_status_t btc_a2d_sink_connect(bt_bdaddr_t *remote_bda)
static void btc_a2d_sink_deinit(void)
{
LOG_DEBUG("%s\n", __FUNCTION__);
btc_dm_disable_service(BTA_A2DP_SOURCE_SERVICE_ID);
#if (BTA_AV_SINK_INCLUDED == TRUE)
btc_dm_disable_service(BTA_A2DP_SINK_SERVICE_ID);
@@ -1232,6 +1230,9 @@ void btc_a2dp_call_handler(btc_msg_t *msg)
btc_a2dp_sink_reg_data_cb(arg->data_cb);
break;
}
case BTC_AV_CONNECT_REQ_EVT:
btc_sm_dispatch(btc_av_cb.sm_handle, msg->act, (char *)msg->arg);
break;
default:
LOG_WARN("%s : unhandled event: %d\n", __FUNCTION__, msg->act);
}

View File

@@ -641,7 +641,7 @@ static void btc_media_task_handle_inc_media(tBT_SBC_HDR *p_msg)
OI_STATUS status;
int num_sbc_frames = p_msg->num_frames_to_be_processed;
UINT32 sbc_frame_len = p_msg->len - 1;
availPcmBytes = 2 * sizeof(pcmData);
availPcmBytes = sizeof(pcmData);
if ((btc_media_cb.peer_sep == AVDT_TSEP_SNK) || (btc_media_cb.rx_flush)) {
APPL_TRACE_DEBUG(" State Changed happened in this tick ");
@@ -671,7 +671,7 @@ static void btc_media_task_handle_inc_media(tBT_SBC_HDR *p_msg)
p_msg->len = sbc_frame_len + 1;
}
btc_a2d_data_cb_to_app((uint8_t *)pcmData, (2 * sizeof(pcmData) - availPcmBytes));
btc_a2d_data_cb_to_app((uint8_t *)pcmData, (sizeof(pcmData) - availPcmBytes));
}
/*******************************************************************************

View File

@@ -514,15 +514,20 @@ static void btc_ble_start_advertising (esp_ble_adv_params_t *ble_adv_params, tBT
status = ESP_BT_STATUS_PARM_INVALID;
LOG_ERROR("Invalid advertisting channel map parameters.\n");
}
if (!BLE_ISVALID_PARAM(ble_adv_params->peer_addr_type, BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_RANDOM)) {
status = ESP_BT_STATUS_PARM_INVALID;
LOG_ERROR("Invalid advertisting peer address type parameters.\n");
}
if(status != ESP_BT_STATUS_SUCCESS) {
if(start_adv_cback) {
start_adv_cback(status);
}
return;
}
LOG_DEBUG("API_Ble_AppStartAdvertising\n");
LOG_DEBUG("API_Ble_AppStartAdvertising\n");
memcpy(peer_addr.bda, ble_adv_params->peer_addr, ESP_BD_ADDR_LEN);
peer_addr.type = ble_adv_params->peer_addr_type;
BTA_DmSetBleAdvParamsAll(ble_adv_params->adv_int_min,
@@ -561,6 +566,7 @@ static void btc_ble_set_scan_params(esp_ble_scan_params_t *scan_params, tBLE_SCA
BLE_ISVALID_PARAM(scan_params->scan_window, BTM_BLE_SCAN_WIN_MIN, BTM_BLE_SCAN_WIN_MAX) &&
BLE_ISVALID_PARAM(scan_params->own_addr_type, BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_RPA_RANDOM) &&
BLE_ISVALID_PARAM(scan_params->scan_filter_policy, BLE_SCAN_FILTER_ALLOW_ALL, BLE_SCAN_FILTER_ALLOW_WLIST_PRA_DIR) &&
BLE_ISVALID_PARAM(scan_params->scan_duplicate, BLE_SCAN_DUPLICATE_DISABLE, BLE_SCAN_DUPLICATE_MAX -1) &&
(scan_params->scan_type == BTM_BLE_SCAN_MODE_ACTI || scan_params->scan_type == BTM_BLE_SCAN_MODE_PASS)) {
BTA_DmSetBleScanFilterParams(ESP_DEFAULT_GATT_IF, /*client_if*/
scan_params->scan_interval,
@@ -568,6 +574,7 @@ static void btc_ble_set_scan_params(esp_ble_scan_params_t *scan_params, tBLE_SCA
scan_params->scan_type,
scan_params->scan_filter_policy,
scan_params->own_addr_type,
scan_params->scan_duplicate,
scan_param_setup_cback);
} else {
btc_scan_params_callback(ESP_DEFAULT_GATT_IF, BTM_ILLEGAL_VALUE);
@@ -723,12 +730,12 @@ static void btc_add_whitelist_complete_callback(UINT8 status, tBTM_WL_OPERATION
}
}
static void btc_set_rand_addr_callback(UINT8 status)
static void btc_set_rand_addr_callback(UINT8 status)
{
esp_ble_gap_cb_param_t param;
bt_status_t ret;
btc_msg_t msg;
param.set_rand_addr_cmpl.status = btc_btm_status_to_esp_status(status); //todo status
param.set_rand_addr_cmpl.status = btc_btm_status_to_esp_status(status); //todo status
msg.sig = BTC_SIG_API_CB;
msg.pid = BTC_PID_GAP_BLE;
msg.act = ESP_GAP_BLE_SET_STATIC_RAND_ADDR_EVT;
@@ -1010,6 +1017,13 @@ void btc_gap_ble_arg_deep_free(btc_msg_t *msg)
}
break;
}
case BTC_GAP_BLE_SET_SECURITY_PARAM_EVT: {
uint8_t *value = ((btc_ble_gap_args_t *)msg->arg)->set_security_param.value;
if (value) {
osi_free(value);
}
break;
}
default:
LOG_DEBUG("Unhandled deep free %d\n", msg->act);
break;
@@ -1108,36 +1122,37 @@ void btc_gap_ble_call_handler(btc_msg_t *msg)
break;
}
case BTC_GAP_BLE_SET_SECURITY_PARAM_EVT: {
uint8_t *value = arg->set_security_param.value;
switch(arg->set_security_param.param_type) {
case ESP_BLE_SM_PASSKEY:
break;
case ESP_BLE_SM_AUTHEN_REQ_MODE: {
uint8_t authen_req = 0;
STREAM_TO_UINT8(authen_req, arg->set_security_param.value);
STREAM_TO_UINT8(authen_req, value);
bta_dm_co_ble_set_auth_req(authen_req);
break;
}
case ESP_BLE_SM_IOCAP_MODE: {
uint8_t iocap = 0;
STREAM_TO_UINT8(iocap, arg->set_security_param.value);
STREAM_TO_UINT8(iocap, value);
bta_dm_co_ble_set_io_cap(iocap);
break;
}
case ESP_BLE_SM_SET_INIT_KEY: {
uint8_t init_key = 0;
STREAM_TO_UINT8(init_key, arg->set_security_param.value);
STREAM_TO_UINT8(init_key, value);
bta_dm_co_ble_set_init_key_req(init_key);
break;
}
case ESP_BLE_SM_SET_RSP_KEY: {
uint8_t rsp_key = 0;
STREAM_TO_UINT8(rsp_key, arg->set_security_param.value);
STREAM_TO_UINT8(rsp_key, value);
bta_dm_co_ble_set_rsp_key_req(rsp_key);
break;
}
case ESP_BLE_SM_MAX_KEY_SIZE: {
uint8_t key_size = 0;
STREAM_TO_UINT8(key_size, arg->set_security_param.value);
STREAM_TO_UINT8(key_size, value);
bta_dm_co_ble_set_max_key_size(key_size);
break;
}

View File

@@ -671,7 +671,7 @@ void btc_gattc_call_handler(btc_msg_t *msg)
btc_ble_gattc_args_t *arg = (btc_ble_gattc_args_t *)(msg->arg);
switch (msg->act) {
case BTC_GATTC_ACT_APP_REGISTER:
LOG_ERROR("%s()", __func__);
LOG_DEBUG("%s()", __func__);
btc_gattc_app_register(arg);
break;
case BTC_GATTC_ACT_APP_UNREGISTER:

View File

@@ -506,6 +506,8 @@ static void btc_gatts_cb_param_copy_req(btc_msg_t *msg, void *p_dest, void *p_sr
if (p_dest_data->req_data.p_data != NULL) {
memcpy(p_dest_data->req_data.p_data, p_src_data->req_data.p_data,
sizeof(tBTA_GATTS_REQ_DATA));
} else {
LOG_ERROR("%s %d no mem\n", __func__, msg->act);
}
break;
@@ -528,9 +530,6 @@ static void btc_gatts_cb_param_copy_free(btc_msg_t *msg, tBTA_GATTS *p_data)
}
break;
case BTA_GATTS_CONF_EVT:
if (p_data && p_data->req_data.value){
osi_free(p_data->req_data.value);
}
break;
default:
break;
@@ -759,6 +758,9 @@ void btc_gatts_cb_handler(btc_msg_t *msg)
param.write.conn_id = BTC_GATT_GET_CONN_ID(p_data->req_data.conn_id);
param.write.trans_id = p_data->req_data.trans_id;
memcpy(param.write.bda, p_data->req_data.remote_bda, ESP_BD_ADDR_LEN);
if (p_data->req_data.p_data == NULL) {
break;
}
param.write.handle = p_data->req_data.p_data->write_req.handle;
param.write.offset = p_data->req_data.p_data->write_req.offset;
param.write.need_rsp = p_data->req_data.p_data->write_req.need_rsp;
@@ -775,6 +777,9 @@ void btc_gatts_cb_handler(btc_msg_t *msg)
param.exec_write.conn_id = BTC_GATT_GET_CONN_ID(p_data->req_data.conn_id);
param.exec_write.trans_id = p_data->req_data.trans_id;
memcpy(param.exec_write.bda, p_data->req_data.remote_bda, ESP_BD_ADDR_LEN);
if (p_data->req_data.p_data == NULL) {
break;
}
param.exec_write.exec_write_flag = p_data->req_data.p_data->exec_write;
btc_gatts_cb_to_app(ESP_GATTS_EXEC_WRITE_EVT, gatts_if, &param);

View File

@@ -92,6 +92,7 @@ static void hci_hal_env_init(
static void hci_hal_env_deinit(void)
{
fixed_queue_free(hci_hal_env.rx_q, hci_hal_env.allocator->free);
hci_hal_env.rx_q = NULL;
}
static bool hal_open(const hci_hal_callbacks_t *upper_callbacks)
@@ -260,6 +261,10 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len)
BT_HDR *pkt;
size_t pkt_size;
if (hci_hal_env.rx_q == NULL) {
return 0;
}
pkt_size = BT_HDR_SIZE + len;
pkt = (BT_HDR *)hci_hal_env.allocator->alloc(pkt_size);
if (!pkt) {

View File

@@ -412,6 +412,7 @@ void avdt_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed)
{
tAVDT_TC_TBL *p_tbl;
UINT16 disc_rsn = AVDT_DISC_RSN_NORMAL;
tAVDT_CCB *p_ccb;
AVDT_TRACE_DEBUG("avdt_l2c_disconnect_ind_cback lcid: %d, ack_needed: %d\n",
lcid, ack_needed);
/* look up info for this channel */
@@ -420,7 +421,13 @@ void avdt_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed)
/* send L2CAP disconnect response */
L2CA_DisconnectRsp(lcid);
} else {
disc_rsn = AVDT_DISC_RSN_ABNORMAL;
if ((p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx)) != NULL) {
UINT16 rsn = L2CA_GetDisconnectReason(p_ccb->peer_addr, BT_TRANSPORT_BR_EDR);
if (rsn != 0 && rsn != HCI_ERR_PEER_USER) {
disc_rsn = AVDT_DISC_RSN_ABNORMAL;
AVDT_TRACE_EVENT("avdt link disc rsn 0x%x", rsn);
}
}
}
avdt_ad_tc_close_ind(p_tbl, disc_rsn);

View File

@@ -335,7 +335,7 @@ void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, BD_NAME bdn,
btsnd_hcic_ble_read_remote_feat(p->hci_handle);
} else if (HCI_LE_SLAVE_INIT_FEAT_EXC_SUPPORTED(controller_get_interface()->get_features_ble()->as_array)
&& link_role == HCI_ROLE_SLAVE) {
btsnd_hcic_ble_read_remote_feat(p->hci_handle);
btsnd_hcic_rmt_ver_req (p->hci_handle);
} else {
btm_establish_continue(p);
}
@@ -906,12 +906,17 @@ void btm_read_remote_version_complete (UINT8 *p)
}
#if BLE_INCLUDED == TRUE
if (p_acl_cb->transport == BT_TRANSPORT_LE) {
if (HCI_LE_DATA_LEN_EXT_SUPPORTED(p_acl_cb->peer_le_features)) {
uint16_t data_length = controller_get_interface()->get_ble_default_data_packet_length();
uint16_t data_txtime = controller_get_interface()->get_ble_default_data_packet_txtime();
btsnd_hcic_ble_set_data_length(p_acl_cb->hci_handle, data_length, data_txtime);
if(p_acl_cb->link_role == HCI_ROLE_MASTER) {
if (HCI_LE_DATA_LEN_EXT_SUPPORTED(p_acl_cb->peer_le_features)) {
uint16_t data_length = controller_get_interface()->get_ble_default_data_packet_length();
uint16_t data_txtime = controller_get_interface()->get_ble_default_data_packet_txtime();
btsnd_hcic_ble_set_data_length(p_acl_cb->hci_handle, data_length, data_txtime);
}
l2cble_notify_le_connection (p_acl_cb->remote_addr);
} else {
//slave role, read remote feature
btsnd_hcic_ble_read_remote_feat(p_acl_cb->hci_handle);
}
l2cble_notify_le_connection (p_acl_cb->remote_addr);
}
#endif
break;

View File

@@ -1225,7 +1225,7 @@ void btm_sec_save_le_key(BD_ADDR bd_addr, tBTM_LE_KEY_TYPE key_type, tBTM_LE_KEY
/* Set that link key is known since this shares field with BTM_SEC_FLAG_LKEY_KNOWN flag in btm_api.h*/
p_rec->sec_flags |= BTM_SEC_LE_LINK_KEY_KNOWN;
if ( p_keys->pcsrk_key.sec_level == SMP_SEC_AUTHENTICATED) {
if ( p_keys->lenc_key.sec_level == SMP_SEC_AUTHENTICATED) {
p_rec->sec_flags |= BTM_SEC_LE_LINK_KEY_AUTHED;
} else {
p_rec->sec_flags &= ~BTM_SEC_LE_LINK_KEY_AUTHED;
@@ -1942,14 +1942,6 @@ void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len, BOOLEAN enhanced)
handle = HCID_GET_HANDLE (handle);
btm_ble_connected(bda, handle, HCI_ENCRYPT_MODE_DISABLED, role, bda_type, match);
if(role == HCI_ROLE_SLAVE) {
//clear p_cb->state, controller will stop adv when ble connected.
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
if(p_cb) {
p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
p_cb->state = BTM_BLE_STOP_ADV;
}
}
l2cble_conn_comp (handle, role, bda, bda_type, conn_interval,
conn_latency, conn_timeout);

View File

@@ -65,6 +65,23 @@ static void btm_gen_resolve_paddr_cmpl(tSMP_ENC *p)
p_cb->set_local_privacy_cback = NULL;
}
if (btm_cb.ble_ctr_cb.inq_var.adv_mode == BTM_BLE_ADV_ENABLE){
BTM_TRACE_DEBUG("Advertise with new resolvable private address, now.");
/**
* Restart advertising, using new resolvable private address
*/
btm_ble_stop_adv();
btm_ble_start_adv();
}
if (btm_cb.ble_ctr_cb.inq_var.state == BTM_BLE_SCANNING){
BTM_TRACE_DEBUG("Scan with new resolvable private address, now.");
/**
* Restart scaning, using new resolvable private address
*/
btm_ble_stop_scan();
btm_ble_start_scan();
}
/* start a periodical timer to refresh random addr */
btu_stop_timer_oneshot(&p_cb->raddr_timer_ent);
#if (BTM_BLE_CONFORMANCE_TESTING == TRUE)

View File

@@ -403,7 +403,6 @@ tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT32 duration,
BTM_BLE_DEFAULT_SFP);
}
p_inq->scan_duplicate_filter = BTM_BLE_DUPLICATE_DISABLE;
status = btm_ble_start_scan();
}
@@ -442,7 +441,6 @@ tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT32 duration,
tBTM_STATUS BTM_BleScan(BOOLEAN start, UINT32 duration,
tBTM_INQ_RESULTS_CB *p_results_cb, tBTM_CMPL_CB *p_cmpl_cb)
{
tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var;
tBTM_STATUS status = BTM_WRONG_MODE;
if (!controller_get_interface()->supports_ble()) {
@@ -467,7 +465,6 @@ tBTM_STATUS BTM_BleScan(BOOLEAN start, UINT32 duration,
/* enable resolving list */
btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_SCAN);
#endif
p_inq->scan_duplicate_filter = BTM_BLE_DUPLICATE_DISABLE;
status = btm_ble_start_scan();
}
@@ -1370,7 +1367,7 @@ void BTM_BleSetScanParams(tGATT_IF client_if, UINT32 scan_interval, UINT32 scan_
}
void BTM_BleSetScanFilterParams(tGATT_IF client_if, UINT32 scan_interval, UINT32 scan_window,
tBLE_SCAN_MODE scan_mode, UINT8 addr_type_own, tBTM_BLE_SFP scan_filter_policy,
tBLE_SCAN_MODE scan_mode, UINT8 addr_type_own, UINT8 scan_duplicate_filter, tBTM_BLE_SFP scan_filter_policy,
tBLE_SCAN_PARAM_SETUP_CBACK scan_setup_status_cback)
{
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
@@ -1407,12 +1404,14 @@ void BTM_BleSetScanFilterParams(tGATT_IF client_if, UINT32 scan_interval, UINT32
if (BTM_BLE_ISVALID_PARAM(scan_interval, BTM_BLE_SCAN_INT_MIN, max_scan_interval) &&
BTM_BLE_ISVALID_PARAM(scan_window, BTM_BLE_SCAN_WIN_MIN, max_scan_window) &&
(scan_mode == BTM_BLE_SCAN_MODE_ACTI || scan_mode == BTM_BLE_SCAN_MODE_PASS)) {
(scan_mode == BTM_BLE_SCAN_MODE_ACTI || scan_mode == BTM_BLE_SCAN_MODE_PASS) &&
(scan_duplicate_filter < BTM_BLE_SCAN_DUPLICATE_MAX)) {
p_cb->scan_type = scan_mode;
p_cb->scan_interval = scan_interval;
p_cb->scan_window = scan_window;
p_cb->sfp = scan_filter_policy;
p_cb->scan_params_set = TRUE;
p_cb->scan_duplicate_filter = scan_duplicate_filter;
btsnd_hcic_ble_set_scan_params(p_cb->scan_type, (UINT16)scan_interval,
(UINT16)scan_window,
@@ -2282,7 +2281,6 @@ tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration)
/* enable IRK list */
btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_SCAN);
#endif
p_ble_cb->inq_var.scan_duplicate_filter = BTM_BLE_DUPLICATE_DISABLE;
status = btm_ble_start_scan();
} else if ((p_ble_cb->inq_var.scan_interval != BTM_BLE_LOW_LATENCY_SCAN_INT) ||
(p_ble_cb->inq_var.scan_window != BTM_BLE_LOW_LATENCY_SCAN_WIN)) {
@@ -2573,7 +2571,7 @@ static void btm_ble_parse_adv_data(tBTM_INQ_INFO *p_info, UINT8 *p_data,
** Returns void
**
*******************************************************************************/
void btm_ble_cache_adv_data(tBTM_INQ_RESULTS *p_cur, UINT8 data_len, UINT8 *p, UINT8 evt_type)
void btm_ble_cache_adv_data(BD_ADDR bda, tBTM_INQ_RESULTS *p_cur, UINT8 data_len, UINT8 *p, UINT8 evt_type)
{
tBTM_BLE_INQ_CB *p_le_inq_cb = &btm_cb.ble_ctr_cb.inq_var;
UINT8 *p_cache;
@@ -2585,6 +2583,15 @@ void btm_ble_cache_adv_data(tBTM_INQ_RESULTS *p_cur, UINT8 data_len, UINT8 *p, U
memset(p_le_inq_cb->adv_data_cache, 0, BTM_BLE_CACHE_ADV_DATA_MAX);
p_cur->adv_data_len = 0;
p_cur->scan_rsp_len = 0;
}
//Clear the adv cache if the addresses are not equal
if(memcmp(bda, p_le_inq_cb->adv_addr, BD_ADDR_LEN) != 0) {
p_le_inq_cb->adv_len = 0;
memcpy(p_le_inq_cb->adv_addr, bda, BD_ADDR_LEN);
memset(p_le_inq_cb->adv_data_cache, 0, BTM_BLE_CACHE_ADV_DATA_MAX);
p_cur->adv_data_len = 0;
p_cur->scan_rsp_len = 0;
}
if (data_len > 0) {
@@ -2814,7 +2821,7 @@ static void btm_ble_appearance_to_cod(UINT16 appearance, UINT8 *dev_class)
** Returns void
**
*******************************************************************************/
BOOLEAN btm_ble_update_inq_result(tINQ_DB_ENT *p_i, UINT8 addr_type, UINT8 evt_type, UINT8 *p)
BOOLEAN btm_ble_update_inq_result(BD_ADDR bda, tINQ_DB_ENT *p_i, UINT8 addr_type, UINT8 evt_type, UINT8 *p)
{
BOOLEAN to_report = TRUE;
tBTM_INQ_RESULTS *p_cur = &p_i->inq_info.results;
@@ -2832,7 +2839,7 @@ BOOLEAN btm_ble_update_inq_result(tINQ_DB_ENT *p_i, UINT8 addr_type, UINT8 evt_t
BTM_TRACE_WARNING("EIR data too long %d. discard", data_len);
return FALSE;
}
btm_ble_cache_adv_data(p_cur, data_len, p, evt_type);
btm_ble_cache_adv_data(bda, p_cur, data_len, p, evt_type);
p1 = (p + data_len);
STREAM_TO_UINT8 (rssi, p1);
@@ -3056,6 +3063,71 @@ void btm_ble_process_adv_pkt (UINT8 *p_data)
}
}
/*******************************************************************************
**
** Function btm_ble_process_last_adv_pkt
**
** Description This function is called to report last adv packet
**
** Parameters
**
** Returns void
**
*******************************************************************************/
static void btm_ble_process_last_adv_pkt(void)
{
UINT8 result = 0;
UINT8 null_bda[6] = {0};
tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
tBTM_INQ_RESULTS_CB *p_inq_results_cb = p_inq->p_inq_results_cb;
tBTM_INQ_RESULTS_CB *p_obs_results_cb = btm_cb.ble_ctr_cb.p_obs_results_cb;
tBTM_INQ_RESULTS_CB *p_scan_results_cb = btm_cb.ble_ctr_cb.p_scan_results_cb;
tBTM_BLE_INQ_CB *p_le_inq_cb = &btm_cb.ble_ctr_cb.inq_var;
tINQ_DB_ENT *p_i = btm_inq_db_find (p_le_inq_cb->adv_addr);
if(memcmp(null_bda, p_le_inq_cb->adv_addr, BD_ADDR_LEN) == 0) {
return;
}
if(p_i == NULL) {
BTM_TRACE_DEBUG("no last adv");
return;
}
if ((result = btm_ble_is_discoverable(p_le_inq_cb->adv_addr, p_i->inq_info.results.ble_evt_type, NULL)) == 0) {
BTM_TRACE_WARNING("%s device is no longer discoverable so discarding advertising packet pkt",
__func__);
return;
}
/* background connection in selective connection mode */
if (btm_cb.ble_ctr_cb.bg_conn_type == BTM_BLE_CONN_SELECTIVE) {
//do nothing
} else {
if (p_inq_results_cb && (result & BTM_BLE_INQ_RESULT)) {
(p_inq_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);
p_le_inq_cb->adv_len = 0;
memset(p_le_inq_cb->adv_addr, 0, BD_ADDR_LEN);
p_i->inq_info.results.adv_data_len = 0;
p_i->inq_info.results.scan_rsp_len = 0;
}
if (p_obs_results_cb && (result & BTM_BLE_OBS_RESULT)) {
(p_obs_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);
p_le_inq_cb->adv_len = 0;
memset(p_le_inq_cb->adv_addr, 0, BD_ADDR_LEN);
p_i->inq_info.results.adv_data_len = 0;
p_i->inq_info.results.scan_rsp_len = 0;
}
if (p_scan_results_cb && (result & BTM_BLE_DISCO_RESULT)) {
(p_scan_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);
p_le_inq_cb->adv_len = 0;
memset(p_le_inq_cb->adv_addr, 0, BD_ADDR_LEN);
p_i->inq_info.results.adv_data_len = 0;
p_i->inq_info.results.scan_rsp_len = 0;
}
}
}
/*******************************************************************************
**
** Function btm_ble_process_adv_pkt_cont
@@ -3080,6 +3152,13 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt
BOOLEAN update = TRUE;
UINT8 result = 0;
//if scan duplicate is enabled, the adv packet without scan response is allowed to report to upper layer
if(p_le_inq_cb->scan_duplicate_filter == BTM_BLE_SCAN_DUPLICATE_ENABLE) {
if(memcmp(bda, p_le_inq_cb->adv_addr, BD_ADDR_LEN) != 0) {
btm_ble_process_last_adv_pkt();
}
}
p_i = btm_inq_db_find (bda);
/* Check if this address has already been processed for this inquiry */
@@ -3108,7 +3187,7 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt
p_inq->inq_cmpl_info.num_resp++;
}
/* update the LE device information in inquiry database */
if (!btm_ble_update_inq_result(p_i, addr_type, evt_type, p)) {
if (!btm_ble_update_inq_result(bda, p_i, addr_type, evt_type, p)) {
return;
}
@@ -3152,12 +3231,24 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt
} else {
if (p_inq_results_cb && (result & BTM_BLE_INQ_RESULT)) {
(p_inq_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);
p_le_inq_cb->adv_len = 0;
memset(p_le_inq_cb->adv_addr, 0, BD_ADDR_LEN);
p_i->inq_info.results.adv_data_len = 0;
p_i->inq_info.results.scan_rsp_len = 0;
}
if (p_obs_results_cb && (result & BTM_BLE_OBS_RESULT)) {
(p_obs_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);
p_le_inq_cb->adv_len = 0;
memset(p_le_inq_cb->adv_addr, 0, BD_ADDR_LEN);
p_i->inq_info.results.adv_data_len = 0;
p_i->inq_info.results.scan_rsp_len = 0;
}
if (p_scan_results_cb && (result & BTM_BLE_DISCO_RESULT)) {
(p_scan_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);
p_le_inq_cb->adv_len = 0;
memset(p_le_inq_cb->adv_addr, 0, BD_ADDR_LEN);
p_i->inq_info.results.adv_data_len = 0;
p_i->inq_info.results.scan_rsp_len = 0;
}
}
}
@@ -3196,6 +3287,9 @@ tBTM_STATUS btm_ble_start_scan(void)
tBTM_STATUS status = BTM_CMD_STARTED;
// recoverly the scan parameters to the controller before start scan
btm_ble_recover_scan_params();
if(p_inq->scan_duplicate_filter > BTM_BLE_DUPLICATE_MAX) {
p_inq->scan_duplicate_filter = BTM_BLE_DUPLICATE_DISABLE;
}
/* start scan, disable duplicate filtering */
if (!btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, p_inq->scan_duplicate_filter)) {
status = BTM_NO_RESOURCES;

View File

@@ -170,16 +170,6 @@ tBTM_STATUS BTM_SetDiscoverability (UINT16 inq_mode, UINT16 window, UINT16 inter
BOOLEAN cod_limited;
BTM_TRACE_API ("BTM_SetDiscoverability\n");
#if (BLE_INCLUDED == TRUE && BLE_INCLUDED == TRUE)
if (controller_get_interface()->supports_ble()) {
if (btm_ble_set_discoverability((UINT16)(inq_mode))
== BTM_SUCCESS) {
btm_cb.btm_inq_vars.discoverable_mode &= (~BTM_BLE_DISCOVERABLE_MASK);
btm_cb.btm_inq_vars.discoverable_mode |= (inq_mode & BTM_BLE_DISCOVERABLE_MASK);
}
}
inq_mode &= ~BTM_BLE_DISCOVERABLE_MASK;
#endif
/*** Check mode parameter ***/
if (inq_mode > BTM_MAX_DISCOVERABLE) {
@@ -601,17 +591,6 @@ tBTM_STATUS BTM_SetConnectability (UINT16 page_mode, UINT16 window, UINT16 inter
BTM_TRACE_API ("BTM_SetConnectability\n");
#if (BLE_INCLUDED == TRUE && BLE_INCLUDED == TRUE)
if (controller_get_interface()->supports_ble()) {
if (btm_ble_set_connectability(page_mode) != BTM_SUCCESS) {
return BTM_NO_RESOURCES;
}
p_inq->connectable_mode &= (~BTM_BLE_CONNECTABLE_MASK);
p_inq->connectable_mode |= (page_mode & BTM_BLE_CONNECTABLE_MASK);
}
page_mode &= ~BTM_BLE_CONNECTABLE_MASK;
#endif
/*** Check mode parameter ***/
if (page_mode != BTM_NON_CONNECTABLE && page_mode != BTM_CONNECTABLE) {
return (BTM_ILLEGAL_VALUE);

View File

@@ -1361,7 +1361,7 @@ tBTM_STATUS BTM_SetEncryption (BD_ADDR bd_addr, tBT_TRANSPORT transport, tBTM_SE
return (BTM_SUCCESS);
}
p_dev_rec->enc_init_by_we = TRUE;
/* enqueue security request if security is active */
if (p_dev_rec->p_callback || (p_dev_rec->sec_state != BTM_SEC_STATE_IDLE)) {
BTM_TRACE_WARNING ("Security Manager: BTM_SetEncryption busy, enqueue request\n");
@@ -4537,7 +4537,7 @@ void btm_sec_disconnected (UINT16 handle, UINT8 reason)
if (!p_dev_rec) {
return;
}
p_dev_rec->enc_init_by_we = FALSE;
transport = (handle == p_dev_rec->hci_handle) ? BT_TRANSPORT_BR_EDR : BT_TRANSPORT_LE;
p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */

View File

@@ -906,7 +906,30 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l
case HCI_BLE_CLEAR_WHITE_LIST:
btm_ble_clear_white_list_complete(p, evt_len);
break;
case HCI_BLE_WRITE_ADV_PARAMS: {
uint8_t status;
STREAM_TO_UINT8 (status, p);
if(status != HCI_SUCCESS) {
HCI_TRACE_ERROR("hci write adv params error 0x%x", status);
}
break;
}
case HCI_BLE_RC_PARAM_REQ_REPLY: {
uint8_t status;
STREAM_TO_UINT8 (status, p);
if(status != HCI_SUCCESS) {
HCI_TRACE_ERROR("hci connection params reply command error 0x%x", status);
}
break;
}
case HCI_BLE_RC_PARAM_REQ_NEG_REPLY: {
uint8_t status;
STREAM_TO_UINT8 (status, p);
if(status != HCI_SUCCESS) {
HCI_TRACE_ERROR("hci connection params neg reply command error 0x%x", status);
}
break;
}
case HCI_BLE_REMOVE_WHITE_LIST:
btm_ble_remove_from_white_list_complete(p, evt_len);
break;

View File

@@ -239,23 +239,6 @@ void btu_task_thread_handler(void *arg)
case SIG_BTU_ONESHOT_ALARM: {
TIMER_LIST_ENT *p_tle = (TIMER_LIST_ENT *)e.par;
btu_general_alarm_process(p_tle);
switch (p_tle->event) {
#if (defined(BLE_INCLUDED) && BLE_INCLUDED == TRUE)
case BTU_TTYPE_BLE_RANDOM_ADDR:
btm_ble_timeout(p_tle);
break;
#endif
case BTU_TTYPE_USER_FUNC: {
tUSER_TIMEOUT_FUNC *p_uf = (tUSER_TIMEOUT_FUNC *)p_tle->param;
(*p_uf)(p_tle);
break;
}
default:
// FAIL
LOG_ERROR("Received unexpected oneshot timer event:0x%x\n", p_tle->event);
break;
}
break;
}
case SIG_BTU_L2CAP_ALARM:

View File

@@ -1038,7 +1038,10 @@ BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb)
if (att_ret == GATT_SUCCESS || att_ret == GATT_CONGESTED) {
sent = TRUE;
p_cmd->to_send = FALSE;
p_cmd->p_cmd = NULL;
if(p_cmd->p_cmd) {
osi_free(p_cmd->p_cmd);
p_cmd->p_cmd = NULL;
}
/* dequeue the request if is write command or sign write */
if (p_cmd->op_code != GATT_CMD_WRITE && p_cmd->op_code != GATT_SIGN_CMD_WRITE) {

View File

@@ -2258,6 +2258,7 @@ void gatt_cleanup_upon_disc(BD_ADDR bda, UINT16 reason, tBT_TRANSPORT transport)
GATT_TRACE_DEBUG ("exit gatt_cleanup_upon_disc ");
BTM_Recovery_Pre_State();
}
gatt_delete_dev_from_srv_chg_clt_list(bda);
}
/*******************************************************************************
**

View File

@@ -573,6 +573,12 @@ typedef struct {
tBTM_BLE_REF_VALUE ref_value;
} tBTM_BLE_BATCH_SCAN_CB;
/// Ble scan duplicate type
enum {
BTM_BLE_SCAN_DUPLICATE_DISABLE = 0x0, /*!< the Link Layer should generate advertising reports to the host for each packet received */
BTM_BLE_SCAN_DUPLICATE_ENABLE = 0x1, /*!< the Link Layer should filter out duplicate advertising reports to the Host */
BTM_BLE_SCAN_DUPLICATE_MAX = 0x2, /*!< 0x02 0xFF, Reserved for future use */
};
/* filter selection bit index */
#define BTM_BLE_PF_ADDR_FILTER 0
#define BTM_BLE_PF_SRVC_DATA 1
@@ -1050,6 +1056,7 @@ void BTM_BleSetScanParams(tGATT_IF client_if, UINT32 scan_interval,
** scan_window - Scan window
** scan_type - Scan type
** addr_type_own - owner address type
** scan_duplicate_filter - scan duplicate filter
** scan_filter_policy - scan filter policy
** scan_setup_status_cback - Scan setup status callback
**
@@ -1057,7 +1064,7 @@ void BTM_BleSetScanParams(tGATT_IF client_if, UINT32 scan_interval,
**
*******************************************************************************/
void BTM_BleSetScanFilterParams(tGATT_IF client_if, UINT32 scan_interval, UINT32 scan_window,
tBLE_SCAN_MODE scan_mode, UINT8 addr_type_own, tBTM_BLE_SFP scan_filter_policy,
tBLE_SCAN_MODE scan_mode, UINT8 addr_type_own, UINT8 scan_duplicate_filter, tBTM_BLE_SFP scan_filter_policy,
tBLE_SCAN_PARAM_SETUP_CBACK scan_setup_status_cback);

View File

@@ -55,8 +55,9 @@
#define BTM_BLE_ENC_MASK 0x03
#define BTM_BLE_DUPLICATE_ENABLE 1
#define BTM_BLE_DUPLICATE_DISABLE 0
#define BTM_BLE_DUPLICATE_ENABLE 1
#define BTM_BLE_DUPLICATE_MAX BTM_BLE_DUPLICATE_ENABLE
#define BTM_BLE_GAP_DISC_SCAN_INT 18 /* Interval(scan_int) = 11.25 ms= 0x0010 * 0.625 ms */
#define BTM_BLE_GAP_DISC_SCAN_WIN 18 /* scan_window = 11.25 ms= 0x0010 * 0.625 ms */
@@ -161,7 +162,7 @@ typedef struct {
UINT8 adv_len;
UINT8 adv_data_cache[BTM_BLE_CACHE_ADV_DATA_MAX];
BD_ADDR adv_addr;
/* inquiry BD addr database */
UINT8 num_bd_entries;
UINT8 max_bd_entries;

View File

@@ -614,7 +614,7 @@ typedef struct {
// btla-specific --
#define BTM_SEC_NO_LAST_SERVICE_ID 0
UINT8 last_author_service_id; /* ID of last serviced authorized: Reset after each l2cap connection */
BOOLEAN enc_init_by_we;
} tBTM_SEC_DEV_REC;
#define BTM_SEC_IS_SM4(sm) ((BOOLEAN)(BTM_SM4_TRUE == ((sm)&BTM_SM4_TRUE)))

View File

@@ -1876,7 +1876,7 @@ BOOLEAN L2CA_RemoveFixedChnl (UINT16 fixed_cid, BD_ADDR rem_bda)
p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, transport);
if ( ((p_lcb) == NULL) || (!p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL]) ) {
L2CAP_TRACE_WARNING ("L2CA_RemoveFixedChnl() CID: 0x%04x BDA: %08x%04x not connected", fixed_cid,
L2CAP_TRACE_DEBUG ("L2CA_RemoveFixedChnl() CID: 0x%04x BDA: %08x%04x not connected", fixed_cid,
(rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3], (rem_bda[4] << 8) + rem_bda[5]);
return (FALSE);
}

View File

@@ -261,6 +261,15 @@ void l2cble_notify_le_connection (BD_ADDR bda)
tACL_CONN *p_acl = btm_bda_to_acl(bda, BT_TRANSPORT_LE) ;
if (p_lcb != NULL && p_acl != NULL && p_lcb->link_state != LST_CONNECTED) {
if(p_acl->link_role == HCI_ROLE_SLAVE) {
//clear p_cb->state, controller will stop adv when ble connected.
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
if(p_cb) {
p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
p_cb->state = BTM_BLE_STOP_ADV;
}
}
/* update link status */
btm_establish_continue(p_acl);
/* update l2cap link status and send callback */

View File

@@ -354,15 +354,17 @@ static void sdp_copy_raw_data (tCONN_CB *p_ccb, BOOLEAN offset)
type = *p++;
p = sdpu_get_len_from_type (p, type, &list_len);
}
if (list_len && list_len < cpy_len ) {
if (list_len < cpy_len ) {
cpy_len = list_len;
}
#if (SDP_DEBUG_RAW == TRUE)
SDP_TRACE_WARNING("list_len :%d cpy_len:%d raw_size:%d raw_used:%d\n",
SDP_TRACE_DEBUG("list_len :%d cpy_len:%d raw_size:%d raw_used:%d\n",
list_len, cpy_len, p_ccb->p_db->raw_size, p_ccb->p_db->raw_used);
#endif
memcpy (&p_ccb->p_db->raw_data[p_ccb->p_db->raw_used], p, cpy_len);
p_ccb->p_db->raw_used += cpy_len;
if (cpy_len != 0){
memcpy (&p_ccb->p_db->raw_data[p_ccb->p_db->raw_used], p, cpy_len);
p_ccb->p_db->raw_used += cpy_len;
}
}
}
#endif

View File

@@ -58,6 +58,8 @@ extern elliptic_curve_t curve_p256;
void ECC_PointMult_Bin_NAF(Point *q, Point *p, DWORD *n, uint32_t keyLength);
bool ECC_CheckPointIsInElliCur_P256(Point *p);
#define ECC_PointMult(q, p, n, keyLength) ECC_PointMult_Bin_NAF(q, p, n, keyLength)
void p_256_init_curve(UINT32 keyLength);

View File

@@ -240,4 +240,39 @@ void ECC_PointMult_Bin_NAF(Point *q, Point *p, DWORD *n, uint32_t keyLength)
multiprecision_mersenns_mult_mod(q->y, q->y, q->z, keyLength);
}
bool ECC_CheckPointIsInElliCur_P256(Point *p)
{
/* y^2 % q */
DWORD y_y_q[KEY_LENGTH_DWORDS_P256] = {0x0};
/* x^2 % q */
DWORD x_x_q[KEY_LENGTH_DWORDS_P256] = {0x0};
/* x % q */
DWORD x_q[KEY_LENGTH_DWORDS_P256] = {0x0};
/* x^2, To prevent overflow, the length of the x square here needs to
be expanded to two times the original one. */
DWORD x_x[2*KEY_LENGTH_DWORDS_P256] = {0x0};
/* y_y_q =(p->y)^2(mod q) */
multiprecision_mersenns_squa_mod(y_y_q, p->y, KEY_LENGTH_DWORDS_P256);
/* Calculate the value of p->x square, x_x = (p->x)^2 */
multiprecision_mult(x_x, p->x, p->x, KEY_LENGTH_DWORDS_P256);
/* The function of the elliptic curve is y^2 = x^3 - 3x + b (mod q) ==>
y^2 = (x^2 - 3)*x + b (mod q),
so we calculate the x^2 - 3 value here */
x_x[0] -= 3;
/* Using math relations. (a*b) % q = ((a%q)*(b%q)) % q ==>
(x^2 - 3)*x = (((x^2 - 3) % q) * x % q) % q */
multiprecision_fast_mod_P256(x_x_q, x_x);
/* x_x = x_x_q * x_q */
multiprecision_mult(x_x, x_x_q, p->x, KEY_LENGTH_DWORDS_P256);
/* x_q = x_x % q */
multiprecision_fast_mod_P256(x_q, x_x);
/* Save the result in x_x_q */
multiprecision_add_mod(x_x_q, x_q, curve_p256.b, KEY_LENGTH_DWORDS_P256);
/* compare the y_y_q and x_x_q, see if they are on a given elliptic curve. */
if (multiprecision_compare(y_y_q, x_x_q, KEY_LENGTH_DWORDS_P256)) {
return false;
} else {
return true;
}
}

View File

@@ -22,6 +22,7 @@
#include "btm_int.h"
#include "l2c_api.h"
#include "smp_int.h"
#include "p_256_ecc_pp.h"
//#include "utils/include/bt_utils.h"
#if SMP_INCLUDED == TRUE
@@ -58,7 +59,7 @@ static bool lmp_version_below(BD_ADDR bda, uint8_t version)
SMP_TRACE_WARNING("%s cannot retrieve LMP version...", __func__);
return false;
}
SMP_TRACE_WARNING("%s LMP version %d < %d", __func__, acl->lmp_version, version);
SMP_TRACE_DEBUG("%s LMP version %d < %d", __func__, acl->lmp_version, version);
return acl->lmp_version < version;
}
@@ -668,6 +669,12 @@ void smp_process_pairing_public_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
STREAM_TO_ARRAY(p_cb->peer_publ_key.x, p, BT_OCTET32_LEN);
STREAM_TO_ARRAY(p_cb->peer_publ_key.y, p, BT_OCTET32_LEN);
/* In order to prevent the x and y coordinates of the public key from being modified,
we need to check whether the x and y coordinates are on the given elliptic curve. */
if (!ECC_CheckPointIsInElliCur_P256((Point *)&p_cb->peer_publ_key)) {
SMP_TRACE_ERROR("%s, Invalid Public key.", __func__);
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
}
p_cb->flags |= SMP_PAIR_FLAG_HAVE_PEER_PUBL_KEY;
smp_wait_for_both_public_keys(p_cb, NULL);
@@ -1826,7 +1833,7 @@ void smp_set_local_oob_random_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
void smp_link_encrypted(BD_ADDR bda, UINT8 encr_enable)
{
tSMP_CB *p_cb = &smp_cb;
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bda);
SMP_TRACE_DEBUG("%s encr_enable=%d\n", __func__, encr_enable);
if (memcmp(&smp_cb.pairing_bda[0], bda, BD_ADDR_LEN) == 0) {
@@ -1837,6 +1844,16 @@ void smp_link_encrypted(BD_ADDR bda, UINT8 encr_enable)
btm_ble_update_sec_key_size(bda, p_cb->loc_enc_size);
}
smp_sm_event(&smp_cb, SMP_ENCRYPTED_EVT, &encr_enable);
} else if (p_dev_rec && !p_dev_rec->enc_init_by_we) {
/*
if enc_init_by_we is false, it means that client initiates encryption before slave calls esp_ble_set_encryption()
we need initiate pairing_bda and p_cb->role then encryption, for example iPhones
*/
memcpy(&smp_cb.pairing_bda[0], bda, BD_ADDR_LEN);
p_cb->state = SMP_STATE_ENCRYPTION_PENDING;
p_cb->role = HCI_ROLE_SLAVE;
p_dev_rec->enc_init_by_we = FALSE;
smp_sm_event(&smp_cb, SMP_ENCRYPTED_EVT, &encr_enable);
}
}

View File

@@ -105,7 +105,10 @@ static void smp_connect_callback (UINT16 channel, BD_ADDR bd_addr, BOOLEAN conne
if (transport == BT_TRANSPORT_BR_EDR || memcmp(bd_addr, dummy_bda, BD_ADDR_LEN) == 0) {
return;
}
if(!connected && &p_cb->rsp_timer_ent) {
//free timer
btu_free_timer(&p_cb->rsp_timer_ent);
}
if (memcmp(bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) == 0) {
SMP_TRACE_EVENT ("%s() for pairing BDA: %08x%04x Event: %s\n",
__FUNCTION__,

View File

@@ -50,14 +50,16 @@
#define BTDM_CFG_BT_DATA_RELEASE (1<<0)
#define BTDM_CFG_HCI_UART (1<<1)
#define BTDM_CFG_CONTROLLER_RUN_APP_CPU (1<<2)
#define BTDM_CFG_SCAN_DUPLICATE_OPTIONS (1<<3)
#define BTDM_CFG_SEND_ADV_RESERVED_SIZE (1<<4)
/* Other reserved for future */
/* not for user call, so don't put to include file */
extern void btdm_osi_funcs_register(void *osi_funcs);
extern int btdm_controller_init(uint32_t config_mask, esp_bt_controller_config_t *config_opts);
extern int btdm_controller_deinit(void);
extern void btdm_controller_deinit(void);
extern int btdm_controller_enable(esp_bt_mode_t mode);
extern int btdm_controller_disable(esp_bt_mode_t mode);
extern void btdm_controller_disable(void);
extern uint8_t btdm_controller_get_mode(void);
extern const char *btdm_controller_get_compile_version(void);
extern void btdm_rf_bb_init(void);
@@ -600,6 +602,10 @@ static uint32_t btdm_config_mask_load(void)
#if CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE == 1
mask |= BTDM_CFG_CONTROLLER_RUN_APP_CPU;
#endif
mask |= BTDM_CFG_SCAN_DUPLICATE_OPTIONS;
mask |= BTDM_CFG_SEND_ADV_RESERVED_SIZE;
return mask;
}
@@ -742,9 +748,7 @@ esp_err_t esp_bt_controller_deinit(void)
return ESP_ERR_INVALID_STATE;
}
if (btdm_controller_deinit() != 0) {
return ESP_ERR_NO_MEM;
}
btdm_controller_deinit();
periph_module_disable(PERIPH_BT_MODULE);
@@ -800,21 +804,14 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode)
esp_err_t esp_bt_controller_disable(void)
{
int ret;
if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
ret = btdm_controller_disable(btdm_controller_get_mode());
if (ret < 0) {
return ESP_ERR_INVALID_STATE;
}
btdm_controller_disable();
if (ret == ESP_BT_MODE_IDLE) {
esp_phy_rf_deinit();
btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
}
esp_phy_rf_deinit();
btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_release(s_pm_lock);

View File

@@ -35,9 +35,19 @@ typedef struct {
uint8_t controller_task_prio; /*!< Bluetooth controller task priority */
uint8_t hci_uart_no; /*!< If use UART1/2 as HCI IO interface, indicate UART number */
uint32_t hci_uart_baudrate; /*!< If use UART1/2 as HCI IO interface, indicate UART baudrate */
uint8_t scan_duplicate_mode; /*!< If use UART1/2 as HCI IO interface, indicate UART baudrate */
uint16_t normal_adv_size; /*!< Normal adv size for scan duplicate */
uint16_t mesh_adv_size; /*!< Mesh adv size for scan duplicate */
uint16_t send_adv_reserved_size; /*!< Controller minimum memory value */
uint32_t controller_debug_flag; /*!< Controller debug log flag */
} esp_bt_controller_config_t;
#ifdef CONFIG_BT_ENABLED
/* While scanning, if the free memory value in controller is less than SCAN_SEND_ADV_RESERVED_SIZE,
the adv packet will be discarded until the memory is restored. */
#define SCAN_SEND_ADV_RESERVED_SIZE 1000
/* open controller log debug when adv lost */
#define CONTROLLER_ADV_LOST_DEBUG_BIT (0<<0)
#ifdef CONFIG_BT_HCI_UART_NO
#define BT_HCI_UART_NO_DEFAULT CONFIG_BT_HCI_UART_NO
@@ -51,11 +61,42 @@ typedef struct {
#define BT_HCI_UART_BAUDRATE_DEFAULT 921600
#endif /* BT_HCI_UART_BAUDRATE_DEFAULT */
/* normal adv cache size */
#ifdef CONFIG_DUPLICATE_SCAN_CACHE_SIZE
#define NORMAL_SCAN_DUPLICATE_CACHE_SIZE CONFIG_DUPLICATE_SCAN_CACHE_SIZE
#else
#define NORMAL_SCAN_DUPLICATE_CACHE_SIZE 20
#endif
#ifndef CONFIG_BLE_MESH_SCAN_DUPLICATE_EN
#define CONFIG_BLE_MESH_SCAN_DUPLICATE_EN FALSE
#endif
#define SCAN_DUPLICATE_MODE_NORMAL_ADV_ONLY 0
#define SCAN_DUPLICATE_MODE_NORMAL_ADV_MESH_ADV 1
#if CONFIG_BLE_MESH_SCAN_DUPLICATE_EN
#define SCAN_DUPLICATE_MODE SCAN_DUPLICATE_MODE_NORMAL_ADV_MESH_ADV
#ifdef CONFIG_MESH_DUPLICATE_SCAN_CACHE_SIZE
#define MESH_DUPLICATE_SCAN_CACHE_SIZE CONFIG_MESH_DUPLICATE_SCAN_CACHE_SIZE
#else
#define MESH_DUPLICATE_SCAN_CACHE_SIZE 50
#endif
#else
#define SCAN_DUPLICATE_MODE SCAN_DUPLICATE_MODE_NORMAL_ADV_ONLY
#define MESH_DUPLICATE_SCAN_CACHE_SIZE 0
#endif
#define BT_CONTROLLER_INIT_CONFIG_DEFAULT() { \
.controller_task_stack_size = ESP_TASK_BT_CONTROLLER_STACK, \
.controller_task_prio = ESP_TASK_BT_CONTROLLER_PRIO, \
.hci_uart_no = BT_HCI_UART_NO_DEFAULT, \
.hci_uart_baudrate = BT_HCI_UART_BAUDRATE_DEFAULT, \
.scan_duplicate_mode = SCAN_DUPLICATE_MODE, \
.normal_adv_size = NORMAL_SCAN_DUPLICATE_CACHE_SIZE, \
.mesh_adv_size = MESH_DUPLICATE_SCAN_CACHE_SIZE, \
.send_adv_reserved_size = SCAN_SEND_ADV_RESERVED_SIZE, \
.controller_debug_flag = CONTROLLER_ADV_LOST_DEBUG_BIT, \
};
#else
#define BT_CONTROLLER_INIT_CONFIG_DEFAULT() {0}; _Static_assert(0, "please enable bluetooth in menuconfig to use bt.h");
@@ -90,7 +131,7 @@ typedef enum {
* ESP_BLE_PWR_TYPE_SCAN : for scan.
* ESP_BLE_PWR_TYPE_DEFAULT : if each connection's TX power is not set, it will use this default value.
* if neither in scan mode nor in adv mode, it will use this default value.
* If none of power type is set, system will use ESP_PWR_LVL_P1 as default for ADV/SCAN/CONN0-9.
* If none of power type is set, system will use ESP_PWR_LVL_P3 as default for ADV/SCAN/CONN0-9.
*/
typedef enum {
ESP_BLE_PWR_TYPE_CONN_HDL0 = 0, /*!< For connection handle 0 */
@@ -112,14 +153,22 @@ typedef enum {
* @brief Bluetooth TX power level(index), it's just a index corresponding to power(dbm).
*/
typedef enum {
ESP_PWR_LVL_N14 = 0, /*!< Corresponding to -14dbm */
ESP_PWR_LVL_N11 = 1, /*!< Corresponding to -11dbm */
ESP_PWR_LVL_N8 = 2, /*!< Corresponding to -8dbm */
ESP_PWR_LVL_N5 = 3, /*!< Corresponding to -5dbm */
ESP_PWR_LVL_N2 = 4, /*!< Corresponding to -2dbm */
ESP_PWR_LVL_P1 = 5, /*!< Corresponding to 1dbm */
ESP_PWR_LVL_P4 = 6, /*!< Corresponding to 4dbm */
ESP_PWR_LVL_P7 = 7, /*!< Corresponding to 7dbm */
ESP_PWR_LVL_N12 = 0, /*!< Corresponding to -12dbm */
ESP_PWR_LVL_N9 = 1, /*!< Corresponding to -9dbm */
ESP_PWR_LVL_N6 = 2, /*!< Corresponding to -6dbm */
ESP_PWR_LVL_N3 = 3, /*!< Corresponding to -3dbm */
ESP_PWR_LVL_N0 = 4, /*!< Corresponding to 0dbm */
ESP_PWR_LVL_P3 = 5, /*!< Corresponding to +3dbm */
ESP_PWR_LVL_P6 = 6, /*!< Corresponding to +6dbm */
ESP_PWR_LVL_P9 = 7, /*!< Corresponding to +9dbm */
ESP_PWR_LVL_N14 = ESP_PWR_LVL_N12, /*!< Backward compatibility! Setting to -14dbm will actually result to -12dbm */
ESP_PWR_LVL_N11 = ESP_PWR_LVL_N9, /*!< Backward compatibility! Setting to -11dbm will actually result to -9dbm */
ESP_PWR_LVL_N8 = ESP_PWR_LVL_N6, /*!< Backward compatibility! Setting to -8dbm will actually result to -6dbm */
ESP_PWR_LVL_N5 = ESP_PWR_LVL_N3, /*!< Backward compatibility! Setting to -5dbm will actually result to -3dbm */
ESP_PWR_LVL_N2 = ESP_PWR_LVL_N0, /*!< Backward compatibility! Setting to -2dbm will actually result to 0dbm */
ESP_PWR_LVL_P1 = ESP_PWR_LVL_P3, /*!< Backward compatibility! Setting to +1dbm will actually result to +3dbm */
ESP_PWR_LVL_P4 = ESP_PWR_LVL_P6, /*!< Backward compatibility! Setting to +4dbm will actually result to +6dbm */
ESP_PWR_LVL_P7 = ESP_PWR_LVL_P9, /*!< Backward compatibility! Setting to +7dbm will actually result to +9dbm */
} esp_power_level_t;
/**
@@ -139,7 +188,6 @@ esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_
*/
esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type);
/**
* @brief Initialize BT controller to allocate task and other resource.
* @param cfg: Initial configuration of BT controller.

View File

@@ -0,0 +1,73 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _DRIVER_ADC1_I2S_PRIVATE_H_
#define _DRIVER_ADC1_I2S_PRIVATE_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_err.h"
/**
* @brief Force power on for SAR ADC.
* This function should be called for the scenario in which ADC are controlled by digital function like DMA.
* When the ADC power is always on, RTC FSM can still be functional.
* This is an internal API for I2S module to call to enable I2S-ADC function.
* Note that adc_power_off() can still power down ADC.
*/
void adc_power_always_on();
/**
* @brief For I2S dma to claim the usage of ADC1.
*
* Other tasks will be forbidden to use ADC1 between ``adc1_i2s_mode_acquire`` and ``adc1_i2s_release``.
* The I2S module may have to wait for a short time for the current conversion (if exist) to finish.
*
* @return
* - ESP_OK success
* - ESP_ERR_TIMEOUT reserved for future use. Currently the function will wait until success.
*/
esp_err_t adc1_i2s_mode_acquire();
/**
* @brief For ADC1 to claim the usage of ADC1.
*
* Other tasks will be forbidden to use ADC1 between ``adc1_adc_mode_acquire`` and ``adc1_i2s_release``.
* The ADC1 may have to wait for some time for the I2S read operation to finish.
*
* @return
* - ESP_OK success
* - ESP_ERR_TIMEOUT reserved for future use. Currently the function will wait until success.
*/
esp_err_t adc1_adc_mode_acquire();
/**
* @brief to let other tasks use the ADC1 when I2S is not work.
*
* Other tasks will be forbidden to use ADC1 between ``adc1_adc/i2s_mode_acquire`` and ``adc1_i2s_release``.
* Call this function to release the occupation of ADC1
*
* @return always return ESP_OK.
*/
esp_err_t adc1_lock_release();
#ifdef __cplusplus
}
#endif
#endif /*_DRIVER_ADC1_I2S_PRIVATE_H_*/

View File

@@ -31,6 +31,7 @@
#include "driver/i2s.h"
#include "driver/rtc_io.h"
#include "driver/dac.h"
#include "adc1_i2s_private.h"
#include "esp_intr.h"
#include "esp_err.h"
@@ -84,12 +85,14 @@ typedef struct {
int bits_per_sample; /*!< Bits per sample*/
i2s_mode_t mode; /*!< I2S Working mode*/
int use_apll; /*!< I2S use APLL clock */
uint32_t sample_rate; /*!< I2S sample rate */
} i2s_obj_t;
static i2s_obj_t *p_i2s_obj[I2S_NUM_MAX] = {0};
static i2s_dev_t* I2S[I2S_NUM_MAX] = {&I2S0, &I2S1};
static portMUX_TYPE i2s_spinlock[I2S_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED};
static int _i2s_adc_unit = -1;
static int _i2s_adc_channel = -1;
/**
* @brief Pre define APLL parameters, save compute time
* | bits_per_sample | rate | sdm0 | sdm1 | sdm2 | odir
@@ -322,12 +325,11 @@ 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;
}
if (p_i2s_obj[i2s_num] == NULL) {
ESP_LOGE(I2S_TAG, "Not initialized yet");
return ESP_ERR_INVALID_ARG;
}
p_i2s_obj[i2s_num]->sample_rate = rate;
double clkmdiv = (double)I2S_BASE_CLK / (rate * factor);
if (clkmdiv > 256) {
@@ -652,6 +654,18 @@ esp_err_t i2s_start(i2s_port_t i2s_num)
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
//start DMA link
I2S_ENTER_CRITICAL();
i2s_reset_fifo(i2s_num);
//reset dma
I2S[i2s_num]->lc_conf.in_rst = 1;
I2S[i2s_num]->lc_conf.in_rst = 0;
I2S[i2s_num]->lc_conf.out_rst = 1;
I2S[i2s_num]->lc_conf.out_rst = 0;
I2S[i2s_num]->conf.tx_reset = 1;
I2S[i2s_num]->conf.tx_reset = 0;
I2S[i2s_num]->conf.rx_reset = 1;
I2S[i2s_num]->conf.rx_reset = 0;
esp_intr_disable(p_i2s_obj[i2s_num]->i2s_isr_handle);
I2S[i2s_num]->int_clr.val = 0xFFFFFFFF;
if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) {
@@ -685,17 +699,6 @@ esp_err_t i2s_stop(i2s_port_t i2s_num)
i2s_disable_rx_intr(i2s_num);
}
I2S[i2s_num]->int_clr.val = I2S[i2s_num]->int_st.val; //clear pending interrupt
i2s_reset_fifo(i2s_num);
//reset dma
I2S[i2s_num]->lc_conf.in_rst = 1;
I2S[i2s_num]->lc_conf.in_rst = 0;
I2S[i2s_num]->lc_conf.out_rst = 1;
I2S[i2s_num]->lc_conf.out_rst = 0;
I2S[i2s_num]->conf.tx_reset = 1;
I2S[i2s_num]->conf.tx_reset = 0;
I2S[i2s_num]->conf.rx_reset = 1;
I2S[i2s_num]->conf.rx_reset = 0;
I2S_EXIT_CRITICAL();
return ESP_OK;
}
@@ -722,10 +725,18 @@ esp_err_t i2s_set_dac_mode(i2s_dac_mode_t dac_mode)
return ESP_OK;
}
static esp_err_t _i2s_adc_mode_recover()
{
I2S_CHECK(((_i2s_adc_unit != -1) && (_i2s_adc_channel != -1)), "i2s ADC recover error, not initialized...", ESP_ERR_INVALID_ARG);
return adc_i2s_mode_init(_i2s_adc_unit, _i2s_adc_channel);
}
esp_err_t i2s_set_adc_mode(adc_unit_t adc_unit, adc1_channel_t adc_channel)
{
I2S_CHECK((adc_unit < ADC_UNIT_2), "i2s ADC unit error, only support ADC1 for now", ESP_ERR_INVALID_ARG);
// For now, we only support SAR ADC1.
_i2s_adc_unit = adc_unit;
_i2s_adc_channel = adc_channel;
return adc_i2s_mode_init(adc_unit, adc_channel);
}
@@ -864,7 +875,7 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co
//initialize the specific ADC channel.
//in the current stage, we only support ADC1 and single channel mode.
//In default data mode, the ADC data is in 12-bit resolution mode.
adc_power_on();
adc_power_always_on();
}
// configure I2S data port interface.
i2s_reset_fifo(i2s_num);
@@ -1171,6 +1182,27 @@ esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *by
return ESP_OK;
}
esp_err_t i2s_adc_enable(i2s_port_t i2s_num)
{
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
I2S_CHECK((p_i2s_obj[i2s_num] != NULL), "Not initialized yet", ESP_ERR_INVALID_STATE);
I2S_CHECK((p_i2s_obj[i2s_num]->mode & I2S_MODE_ADC_BUILT_IN), "i2s built-in adc not enabled", ESP_ERR_INVALID_STATE);
adc1_i2s_mode_acquire();
_i2s_adc_mode_recover();
return i2s_set_clk(i2s_num, p_i2s_obj[i2s_num]->sample_rate, p_i2s_obj[i2s_num]->bits_per_sample, p_i2s_obj[i2s_num]->channel_num);
}
esp_err_t i2s_adc_disable(i2s_port_t i2s_num)
{
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
I2S_CHECK((p_i2s_obj[i2s_num] != NULL), "Not initialized yet", ESP_ERR_INVALID_STATE);
I2S_CHECK((p_i2s_obj[i2s_num]->mode & I2S_MODE_ADC_BUILT_IN), "i2s built-in adc not enabled", ESP_ERR_INVALID_STATE);
adc1_lock_release();
return ESP_OK;
}
esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, size_t src_bits, size_t aim_bits, size_t *bytes_written, TickType_t ticks_to_wait)
{
char *data_ptr;

View File

@@ -204,12 +204,13 @@ int adc1_get_voltage(adc1_channel_t channel) __attribute__((deprecated));
/** @endcond */
/**
* @brief Power on SAR ADC
* @brief Enable ADC power
*/
void adc_power_on();
/**
* @brief Power off SAR ADC
* This function will force power down for ADC
*/
void adc_power_off();

View File

@@ -353,6 +353,8 @@ int i2s_read_bytes(i2s_port_t i2s_num, void *dest, size_t size, TickType_t ticks
*
* @note If the built-in ADC mode is enabled, we should call i2s_adc_start and i2s_adc_stop around the whole reading process,
* to prevent the data getting corrupted.
* @note If the built-in ADC mode is enabled, we should call i2s_adc_start and i2s_adc_stop around the whole reading process,
* to prevent the data getting corrupted.
*
* @return
* - ESP_OK Success
@@ -485,6 +487,31 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b
*/
esp_err_t i2s_set_adc_mode(adc_unit_t adc_unit, adc1_channel_t adc_channel);
/**
* @brief Start to use I2S built-in ADC mode
* @note This function would acquire the lock of ADC to prevent the data getting corrupted
* during the I2S peripheral is being used to do fully continuous ADC sampling.
*
* @param i2s_num i2s port index
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_INVALID_STATE driver state error
* - ESP_FAIL Internal driver error
*/
esp_err_t i2s_adc_enable(i2s_port_t i2s_num);
/**
* @brief Stop to use I2S built-in ADC mode
* @param i2s_num i2s port index
* @note This function would release the lock of ADC so that other tasks can use ADC.
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_INVALID_STATE driver state error
*/
esp_err_t i2s_adc_disable(i2s_port_t i2s_num);
#ifdef __cplusplus
}
#endif

View File

@@ -53,6 +53,9 @@ typedef enum {
PERIPH_WIFI_MODULE,
PERIPH_BT_MODULE,
PERIPH_WIFI_BT_COMMON_MODULE,
PERIPH_AES_MODULE,
PERIPH_SHA_MODULE,
PERIPH_RSA_MODULE,
} periph_module_t;
/**

View File

@@ -46,7 +46,7 @@ typedef enum {
* @brief This is a configuration structure for a SPI bus.
*
* You can use this structure to specify the GPIO pins of the bus. Normally, the driver will use the
* GPIO matrix to route the signals. An exception is made when all signals either can be routed through
* GPIO matrix to route the signals. An exception is made when all signals either can be routed through
* the IO_MUX or are -1. In that case, the IO_MUX is used, allowing for >40MHz speeds.
*
* @note Be advised that the slave driver does not use the quadwp/quadhd lines and fields in spi_bus_config_t refering to these lines will be ignored and can thus safely be left uninitialized.
@@ -81,20 +81,20 @@ bool spicommon_periph_free(spi_host_device_t host);
/**
* @brief Try to claim a SPI DMA channel
*
*
* Call this if your driver wants to use SPI with a DMA channnel.
*
*
* @param dma_chan channel to claim
*
*
* @return True if success; false otherwise.
*/
bool spicommon_dma_chan_claim(int dma_chan);
/**
* @brief Return the SPI DMA channel so other driver can claim it, or just to power down DMA.
*
*
* @param dma_chan channel to return
*
*
* @return True if success; false otherwise.
*/
bool spicommon_dma_chan_free(int dma_chan);
@@ -107,7 +107,7 @@ bool spicommon_dma_chan_free(int dma_chan);
* @brief Connect a SPI peripheral to GPIO pins
*
* This routine is used to connect a SPI peripheral to the IO-pads and DMA channel given in
* the arguments. Depending on the IO-pads requested, the routing is done either using the
* the arguments. Depending on the IO-pads requested, the routing is done either using the
* IO_mux or using the GPIO matrix.
*
* @param host SPI peripheral to be routed
@@ -116,7 +116,7 @@ bool spicommon_dma_chan_free(int dma_chan);
* @param flags Combination of SPICOMMON_BUSFLAG_* flags
* @param[out] is_native A value of 'true' will be written to this address if the GPIOs can be
* routed using the IO_mux, 'false' if the GPIO matrix is used.
* @return
* @return
* - ESP_ERR_INVALID_ARG if parameter is invalid
* - ESP_OK on success
*/
@@ -126,7 +126,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
* @brief Free the IO used by a SPI peripheral
*
* @param host SPI peripheral to be freed
* @return
* @return
* - ESP_ERR_INVALID_ARG if parameter is invalid
* - ESP_OK on success
*/
@@ -180,6 +180,26 @@ void spicommon_setup_dma_desc_links(lldesc_t *dmadesc, int len, const uint8_t *d
*/
spi_dev_t *spicommon_hw_for_host(spi_host_device_t host);
/** Temporarily connect CS signal input to high to avoid slave detecting unexpected transactions.
*
* @note Don't use this in the application.
*
* @param host The spi host.
*/
void spicommon_freeze_cs(spi_host_device_t host);
/** Use this function instead of cs_initial to avoid overwrite the output config
* This is used in test by internal gpio matrix connections
*
* @note Don't use this in the application.
*
* @param host The spi host.
* @param cs_io_num GPIO number of the CS pin.
* @param iomux The peripheral is using iomux pins.
*/
void spicommon_restore_cs(spi_host_device_t host, int cs_io_num, bool iomux);
/**
* @brief Get the IRQ source for a specific SPI host
*
@@ -201,10 +221,10 @@ typedef void(*dmaworkaround_cb_t)(void *arg);
* @note In some (well-defined) cases in the ESP32 (at least rev v.0 and v.1), a SPI DMA channel will get confused. This can be remedied
* by resetting the SPI DMA hardware in case this happens. Unfortunately, the reset knob used for thsi will reset _both_ DMA channels, and
* as such can only done safely when both DMA channels are idle. These functions coordinate this.
*
*
* Essentially, when a reset is needed, a driver can request this using spicommon_dmaworkaround_req_reset. This is supposed to be called
* with an user-supplied function as an argument. If both DMA channels are idle, this call will reset the DMA subsystem and return true.
* If the other DMA channel is still busy, it will return false; as soon as the other DMA channel is done, however, it will reset the
* with an user-supplied function as an argument. If both DMA channels are idle, this call will reset the DMA subsystem and return true.
* If the other DMA channel is still busy, it will return false; as soon as the other DMA channel is done, however, it will reset the
* DMA subsystem and call the callback. The callback is then supposed to be used to continue the SPI drivers activity.
*
* @param dmachan DMA channel associated with the SPI host that needs a reset

View File

@@ -23,7 +23,7 @@ static portMUX_TYPE periph_spinlock = portMUX_INITIALIZER_UNLOCKED;
/* Static functions to return register address & mask for clk_en / rst of each peripheral */
static uint32_t get_clk_en_mask(periph_module_t periph);
static uint32_t get_rst_en_mask(periph_module_t periph);
static uint32_t get_rst_en_mask(periph_module_t periph, bool enable);
static uint32_t get_clk_en_reg(periph_module_t periph);
static uint32_t get_rst_en_reg(periph_module_t periph);
@@ -31,7 +31,7 @@ void periph_module_enable(periph_module_t periph)
{
portENTER_CRITICAL(&periph_spinlock);
DPORT_SET_PERI_REG_MASK(get_clk_en_reg(periph), get_clk_en_mask(periph));
DPORT_CLEAR_PERI_REG_MASK(get_rst_en_reg(periph), get_rst_en_mask(periph));
DPORT_CLEAR_PERI_REG_MASK(get_rst_en_reg(periph), get_rst_en_mask(periph, true));
portEXIT_CRITICAL(&periph_spinlock);
}
@@ -39,15 +39,15 @@ void periph_module_disable(periph_module_t periph)
{
portENTER_CRITICAL(&periph_spinlock);
DPORT_CLEAR_PERI_REG_MASK(get_clk_en_reg(periph), get_clk_en_mask(periph));
DPORT_SET_PERI_REG_MASK(get_rst_en_reg(periph), get_rst_en_mask(periph));
DPORT_SET_PERI_REG_MASK(get_rst_en_reg(periph), get_rst_en_mask(periph, false));
portEXIT_CRITICAL(&periph_spinlock);
}
void periph_module_reset(periph_module_t periph)
{
portENTER_CRITICAL(&periph_spinlock);
DPORT_SET_PERI_REG_MASK(get_rst_en_reg(periph), get_rst_en_mask(periph));
DPORT_CLEAR_PERI_REG_MASK(get_rst_en_reg(periph), get_rst_en_mask(periph));
DPORT_SET_PERI_REG_MASK(get_rst_en_reg(periph), get_rst_en_mask(periph, false));
DPORT_CLEAR_PERI_REG_MASK(get_rst_en_reg(periph), get_rst_en_mask(periph, false));
portEXIT_CRITICAL(&periph_spinlock);
}
@@ -114,12 +114,18 @@ static uint32_t get_clk_en_mask(periph_module_t periph)
return DPORT_WIFI_CLK_BT_EN_M;
case PERIPH_WIFI_BT_COMMON_MODULE:
return DPORT_WIFI_CLK_WIFI_BT_COMMON_M;
case PERIPH_AES_MODULE:
return DPORT_PERI_EN_AES;
case PERIPH_SHA_MODULE:
return DPORT_PERI_EN_SHA;
case PERIPH_RSA_MODULE:
return DPORT_PERI_EN_RSA;
default:
return 0;
}
}
static uint32_t get_rst_en_mask(periph_module_t periph)
static uint32_t get_rst_en_mask(periph_module_t periph, bool enable)
{
switch(periph) {
case PERIPH_RMT_MODULE:
@@ -174,6 +180,30 @@ static uint32_t get_rst_en_mask(periph_module_t periph)
return DPORT_CAN_RST;
case PERIPH_EMAC_MODULE:
return DPORT_EMAC_RST;
case PERIPH_AES_MODULE:
if (enable == true) {
// Clear reset on digital signature & secure boot units, otherwise AES unit is held in reset also.
return (DPORT_PERI_EN_AES | DPORT_PERI_EN_DIGITAL_SIGNATURE | DPORT_PERI_EN_SECUREBOOT);
} else {
//Don't return other units to reset, as this pulls reset on RSA & SHA units, respectively.
return DPORT_PERI_EN_AES;
}
case PERIPH_SHA_MODULE:
if (enable == true) {
// Clear reset on secure boot, otherwise SHA is held in reset
return (DPORT_PERI_EN_SHA | DPORT_PERI_EN_SECUREBOOT);
} else {
// Don't assert reset on secure boot, otherwise AES is held in reset
return DPORT_PERI_EN_SHA;
}
case PERIPH_RSA_MODULE:
if (enable == true) {
// Also clear reset on digital signature, otherwise RSA is held in reset
return (DPORT_PERI_EN_RSA | DPORT_PERI_EN_DIGITAL_SIGNATURE);
} else {
// Don't reset digital signature unit, as this resets AES also
return DPORT_PERI_EN_RSA;
}
case PERIPH_WIFI_MODULE:
case PERIPH_BT_MODULE:
case PERIPH_WIFI_BT_COMMON_MODULE:
@@ -203,12 +233,20 @@ static bool is_wifi_clk_peripheral(periph_module_t periph)
static uint32_t get_clk_en_reg(periph_module_t periph)
{
return is_wifi_clk_peripheral(periph) ? DPORT_WIFI_CLK_EN_REG : DPORT_PERIP_CLK_EN_REG;
if (periph == PERIPH_AES_MODULE || periph == PERIPH_SHA_MODULE || periph == PERIPH_RSA_MODULE) {
return DPORT_PERI_CLK_EN_REG;
} else {
return is_wifi_clk_peripheral(periph) ? DPORT_WIFI_CLK_EN_REG : DPORT_PERIP_CLK_EN_REG;
}
}
static uint32_t get_rst_en_reg(periph_module_t periph)
{
return is_wifi_clk_peripheral(periph) ? DPORT_CORE_RST_EN_REG : DPORT_PERIP_RST_EN_REG;
if (periph == PERIPH_AES_MODULE || periph == PERIPH_SHA_MODULE || periph == PERIPH_RSA_MODULE) {
return DPORT_PERI_RST_EN_REG;
} else {
return is_wifi_clk_peripheral(periph) ? DPORT_CORE_RST_EN_REG : DPORT_PERIP_RST_EN_REG;
}
}

View File

@@ -34,6 +34,7 @@
#include "sys/lock.h"
#include "driver/rtc_cntl.h"
#include "driver/gpio.h"
#include "adc1_i2s_private.h"
#ifndef NDEBUG
// Enable built-in checks in queue.h in debug builds
@@ -99,6 +100,9 @@ static _lock_t adc2_wifi_lock = NULL;
//prevent ADC2 being used by tasks (regardless of WIFI)
portMUX_TYPE adc2_spinlock = portMUX_INITIALIZER_UNLOCKED;
//prevent ADC1 being used by I2S dma and other tasks at the same time.
static _lock_t adc1_i2s_lock = NULL;
typedef struct {
TimerHandle_t timer;
uint32_t filtered_val[TOUCH_PAD_MAX];
@@ -108,12 +112,6 @@ typedef struct {
} touch_pad_filter_t;
static touch_pad_filter_t *s_touch_pad_filter = NULL;
typedef enum {
ADC_FORCE_FSM = 0x0,
ADC_FORCE_DISABLE = 0x2,
ADC_FORCE_ENABLE = 0x3,
} adc_force_mode_t;
//Reg,Mux,Fun,IE,Up,Down,Rtc_number
const rtc_gpio_desc_t rtc_gpio_desc[GPIO_PIN_COUNT] = {
{RTC_IO_TOUCH_PAD1_REG, RTC_IO_TOUCH_PAD1_MUX_SEL_M, RTC_IO_TOUCH_PAD1_FUN_SEL_S, RTC_IO_TOUCH_PAD1_FUN_IE_M, RTC_IO_TOUCH_PAD1_RUE_M, RTC_IO_TOUCH_PAD1_RDE_M, RTC_IO_TOUCH_PAD1_SLP_SEL_M, RTC_IO_TOUCH_PAD1_SLP_IE_M, RTC_IO_TOUCH_PAD1_HOLD_M, RTC_CNTL_TOUCH_PAD1_HOLD_FORCE_M, RTC_IO_TOUCH_PAD1_DRV_V, RTC_IO_TOUCH_PAD1_DRV_S, RTCIO_GPIO0_CHANNEL}, //0
@@ -1025,10 +1023,21 @@ static esp_err_t adc_set_atten(adc_unit_t adc_unit, adc_channel_t channel, adc_a
return ESP_OK;
}
void adc_power_always_on()
{
portENTER_CRITICAL(&rtc_spinlock);
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
portEXIT_CRITICAL(&rtc_spinlock);
}
void adc_power_on()
{
portENTER_CRITICAL(&rtc_spinlock);
SENS.sar_meas_wait2.force_xpd_sar = ADC_FORCE_FSM;
if (SENS.sar_meas_wait2.force_xpd_sar & SENS_FORCE_XPD_SAR_SW_M) {
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
} else {
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_FSM;
}
portEXIT_CRITICAL(&rtc_spinlock);
}
@@ -1037,7 +1046,7 @@ void adc_power_off()
portENTER_CRITICAL(&rtc_spinlock);
//Bit1 0:Fsm 1: SW mode
//Bit0 0:SW mode power down 1: SW mode power on
SENS.sar_meas_wait2.force_xpd_sar = ADC_FORCE_DISABLE;
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PD;
portEXIT_CRITICAL(&rtc_spinlock);
}
@@ -1161,7 +1170,7 @@ esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel)
uint8_t table_len = 1;
//POWER ON SAR
adc_power_on();
adc_power_always_on();
adc_gpio_init(adc_unit, channel);
adc_set_i2s_data_len(adc_unit, table_len);
adc_set_i2s_data_pattern(adc_unit, 0, channel, ADC_WIDTH_BIT_12, ADC_ATTEN_DB_11);
@@ -1246,12 +1255,55 @@ esp_err_t adc1_config_width(adc_bits_width_t width_bit)
return ESP_OK;
}
esp_err_t adc1_i2s_mode_acquire()
{
//lazy initialization
//for i2s, block until acquire the lock
_lock_acquire( &adc1_i2s_lock );
ESP_LOGD( RTC_MODULE_TAG, "i2s mode takes adc1 lock." );
portENTER_CRITICAL(&rtc_spinlock);
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
//switch SARADC into DIG channel
SENS.sar_read_ctrl.sar1_dig_force = 1;
portEXIT_CRITICAL(&rtc_spinlock);
return ESP_OK;
}
esp_err_t adc1_adc_mode_acquire()
{
//lazy initialization
//for adc1, block until acquire the lock
_lock_acquire( &adc1_i2s_lock );
ESP_LOGD( RTC_MODULE_TAG, "adc mode takes adc1 lock." );
portENTER_CRITICAL(&rtc_spinlock);
// for now the WiFi would use ADC2 and set xpd_sar force on.
// so we can not reset xpd_sar to fsm mode directly.
// We should handle this after the synchronization mechanism is established.
//switch SARADC into RTC channel
SENS.sar_read_ctrl.sar1_dig_force = 0;
portEXIT_CRITICAL(&rtc_spinlock);
return ESP_OK;
}
esp_err_t adc1_lock_release()
{
RTC_MODULE_CHECK((uint32_t*)adc1_i2s_lock != NULL, "adc1 lock release called before acquire", ESP_ERR_INVALID_STATE );
// for now the WiFi would use ADC2 and set xpd_sar force on.
// so we can not reset xpd_sar to fsm mode directly.
// We should handle this after the synchronization mechanism is established.
_lock_release( &adc1_i2s_lock );
ESP_LOGD( RTC_MODULE_TAG, "returns adc1 lock." );
return ESP_OK;
}
int adc1_get_raw(adc1_channel_t channel)
{
uint16_t adc_value;
RTC_MODULE_CHECK(channel < ADC1_CHANNEL_MAX, "ADC Channel Err", ESP_ERR_INVALID_ARG);
adc_power_on();
adc1_adc_mode_acquire();
adc_power_on();
portENTER_CRITICAL(&rtc_spinlock);
//Adc Controler is Rtc module,not ulp coprocessor
@@ -1274,6 +1326,7 @@ int adc1_get_raw(adc1_channel_t channel)
while (SENS.sar_meas_start1.meas1_done_sar == 0);
adc_value = SENS.sar_meas_start1.meas1_data_sar;
portEXIT_CRITICAL(&rtc_spinlock);
adc1_lock_release();
return adc_value;
}
@@ -1467,6 +1520,8 @@ esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
rtc_gpio_input_disable(gpio);
rtc_gpio_pullup_dis(gpio);
rtc_gpio_pulldown_dis(gpio);
//force fsm
adc_power_always_on(); //Select power source of ADC
RTCCNTL.bias_conf.dbg_atten = 0; //Check DBG effect outside sleep mode
//set dtest (MUX_SEL : 0 -> RTC; 1-> vdd_sar2)
@@ -1475,8 +1530,6 @@ esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
RTCCNTL.test_mux.ent_rtc = 1;
//set sar2_en_test
SENS.sar_start_force.sar2_en_test = 1;
//force fsm
SENS.sar_meas_wait2.force_xpd_sar = ADC_FORCE_ENABLE; //Select power source of ADC
//set sar2 en force
SENS.sar_meas_start2.sar2_en_pad_force = 1; //Pad bitmap controlled by SW
//set en_pad for channels 7,8,9 (bits 0x380)

View File

@@ -329,6 +329,7 @@ void spicommon_cs_initialize(spi_host_device_t host, int cs_io_num, int cs_num,
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[cs_io_num], 1);
} else {
//Use GPIO matrix
gpio_set_direction(cs_io_num, GPIO_MODE_INPUT_OUTPUT);
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[cs_io_num], PIN_FUNC_GPIO);
gpio_matrix_out(cs_io_num, io_signal[host].spics_out[cs_num], false, false);
if (cs_num == 0) gpio_matrix_in(cs_io_num, io_signal[host].spics_in, false);
@@ -344,7 +345,7 @@ void spicommon_cs_free(spi_host_device_t host, int cs_io_num)
}
//Set up a list of dma descriptors. dmadesc is an array of descriptors. Data is the buffer to point to.
void spicommon_setup_dma_desc_links(lldesc_t *dmadesc, int len, const uint8_t *data, bool isrx)
void IRAM_ATTR spicommon_setup_dma_desc_links(lldesc_t *dmadesc, int len, const uint8_t *data, bool isrx)
{
int n = 0;
while (len) {
@@ -371,6 +372,26 @@ void spicommon_setup_dma_desc_links(lldesc_t *dmadesc, int len, const uint8_t *d
dmadesc[n - 1].qe.stqe_next = NULL;
}
void spicommon_freeze_cs(spi_host_device_t host)
{
gpio_matrix_in(0x38, io_signal[host].spics_in, false);
}
static void IOMUX_IN(uint32_t gpio, uint32_t signal_idx)
{
GPIO.func_in_sel_cfg[signal_idx].sig_in_sel = 0;
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[gpio]);
}
void spicommon_restore_cs(spi_host_device_t host, int cs_io_num, bool iomux)
{
if (iomux) {
IOMUX_IN(cs_io_num, io_signal[host].spics_in);
} else {
gpio_matrix_in(cs_io_num, io_signal[host].spics_in, false);
}
}
/*
Code for workaround for DMA issue in ESP32 v0/v1 silicon

View File

@@ -21,13 +21,13 @@ is a combination of SPI port and CS pin, plus some information about the specifi
The essence of the interface to a device is a set of queues; one per device. The idea is that to send something to a SPI
device, you allocate a transaction descriptor. It contains some information about the transfer like the lenghth, address,
command etc, plus pointers to transmit and receive buffer. The address of this block gets pushed into the transmit queue.
The SPI driver does its magic, and sends and retrieves the data eventually. The data gets written to the receive buffers,
command etc, plus pointers to transmit and receive buffer. The address of this block gets pushed into the transmit queue.
The SPI driver does its magic, and sends and retrieves the data eventually. The data gets written to the receive buffers,
if needed the transaction descriptor is modified to indicate returned parameters and the entire thing goes into the return
queue, where whatever software initiated the transaction can retrieve it.
The entire thing is run from the SPI interrupt handler. If SPI is done transmitting/receiving but nothing is in the queue,
it will not clear the SPI interrupt but just disable it. This way, when a new thing is sent, pushing the packet into the send
The entire thing is run from the SPI interrupt handler. If SPI is done transmitting/receiving but nothing is in the queue,
it will not clear the SPI interrupt but just disable it. This way, when a new thing is sent, pushing the packet into the send
queue and re-enabling the interrupt will trigger the interrupt again, which can then take care of the sending.
*/
@@ -67,8 +67,8 @@ typedef struct spi_device_t spi_device_t;
/// struct to hold private transaction data (like tx and rx buffer for DMA).
typedef struct {
spi_transaction_t *trans;
typedef struct {
spi_transaction_t *trans;
uint32_t *buffer_to_send; //equals to tx_data, if SPI_TRANS_USE_RXDATA is applied; otherwise if original buffer wasn't in DMA-capable memory, this gets the address of a temporary buffer that is;
//otherwise sets to the original buffer or NULL if no buffer is assigned.
uint32_t *buffer_to_rcv; // similar to buffer_to_send
@@ -140,10 +140,10 @@ esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus
goto nomem;
}
#endif //CONFIG_PM_ENABLE
spicommon_bus_initialize_io(host, bus_config, dma_chan, SPICOMMON_BUSFLAG_MASTER|SPICOMMON_BUSFLAG_QUAD, &native);
spihost[host]->no_gpio_matrix=native;
spihost[host]->dma_chan=dma_chan;
if (dma_chan == 0) {
spihost[host]->max_transfer_sz = 32;
@@ -180,7 +180,7 @@ esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus
spihost[host]->hw->slave.wr_sta_inten=0;
//Force a transaction done interrupt. This interrupt won't fire yet because we initialized the SPI interrupt as
//disabled. This way, we can just enable the SPI interrupt and the interrupt handler will kick in, handling
//disabled. This way, we can just enable the SPI interrupt and the interrupt handler will kick in, handling
//any transactions that are queued.
spihost[host]->hw->slave.trans_inten=1;
spihost[host]->hw->slave.trans_done=1;
@@ -271,7 +271,6 @@ esp_err_t spi_bus_add_device(spi_host_device_t host, spi_device_interface_config
//Set CS pin, CS options
if (dev_config->spics_io_num >= 0) {
gpio_set_direction(dev_config->spics_io_num, GPIO_MODE_OUTPUT);
spicommon_cs_initialize(host, dev_config->spics_io_num, freecs, spihost[host]->no_gpio_matrix == false);
}
if (dev_config->flags&SPI_DEVICE_CLK_AS_CS) {
@@ -397,7 +396,7 @@ static void IRAM_ATTR spi_intr(void *arg)
/*------------ deal with the in-flight transaction -----------------*/
if (host->cur_cs != NO_CS) {
spi_transaction_t *cur_trans = host->cur_trans_buf.trans;
//Okay, transaction is done.
//Okay, transaction is done.
if (host->cur_trans_buf.buffer_to_rcv && host->dma_chan == 0 ) {
//Need to copy from SPI regs to result buffer.
for (int x=0; x < cur_trans->rxlength; x+=32) {
@@ -411,7 +410,7 @@ static void IRAM_ATTR spi_intr(void *arg)
//Call post-transaction callback, if any
if (host->device[host->cur_cs]->cfg.post_cb) host->device[host->cur_cs]->cfg.post_cb(cur_trans);
//Return transaction descriptor.
xQueueSendFromISR(host->device[host->cur_cs]->ret_queue, &host->cur_trans_buf, &do_yield);
xQueueSendFromISR(host->device[host->cur_cs]->ret_queue, &host->cur_trans_buf, &do_yield);
prevCs=host->cur_cs;
host->cur_cs = NO_CS;
}
@@ -443,7 +442,7 @@ static void IRAM_ATTR spi_intr(void *arg)
host->cur_cs=i;
//We should be done with the transmission.
assert(host->hw->cmd.usr == 0);
//Reconfigure according to device settings, but only if we change CSses.
if (i!=prevCs) {
//Assumes a hardcoded 80MHz Fapb for now. ToDo: figure out something better once we have
@@ -453,7 +452,7 @@ static void IRAM_ATTR spi_intr(void *arg)
//Configure bit order
host->hw->ctrl.rd_bit_order=(dev->cfg.flags & SPI_DEVICE_RXBIT_LSBFIRST)?1:0;
host->hw->ctrl.wr_bit_order=(dev->cfg.flags & SPI_DEVICE_TXBIT_LSBFIRST)?1:0;
//Configure polarity
//SPI iface needs to be configured for a delay in some cases.
int nodelay=0;
@@ -548,7 +547,7 @@ static void IRAM_ATTR spi_intr(void *arg)
host->hw->dma_in_link.start=1;
}
} else {
//DMA temporary workaround: let RX DMA work somehow to avoid the issue in ESP32 v0/v1 silicon
//DMA temporary workaround: let RX DMA work somehow to avoid the issue in ESP32 v0/v1 silicon
if (host->dma_chan != 0 ) {
host->hw->dma_in_link.addr=0;
host->hw->dma_in_link.start=1;
@@ -601,17 +600,38 @@ static void IRAM_ATTR spi_intr(void *arg)
host->hw->user.usr_addr=addrlen?1:0;
host->hw->user.usr_command=cmdlen?1:0;
// output command will be sent from bit 7 to 0 of command_value, and then bit 15 to 8 of the same register field.
if ((dev->cfg.flags & SPI_DEVICE_TXBIT_LSBFIRST)==0) {
/* Output command will be sent from bit 7 to 0 of command_value, and
* then bit 15 to 8 of the same register field. Shift and swap to send
* more straightly.
*/
uint16_t command = trans->cmd << (16-cmdlen); //shift to MSB
host->hw->user2.usr_command_value = (command>>8)|(command<<8); //swap the first and second byte
// shift the address to MSB of addr (and maybe slv_wr_status) register.
// output address will be sent from MSB to LSB of addr register, then comes the MSB to LSB of slv_wr_status register.
if (addrlen>32) {
host->hw->addr = trans->addr >> (addrlen- 32);
// shift the address to MSB of addr (and maybe slv_wr_status) register.
// output address will be sent from MSB to LSB of addr register, then comes the MSB to LSB of slv_wr_status register.
if (addrlen > 32) {
host->hw->addr = trans->addr >> (addrlen - 32);
host->hw->slv_wr_status = trans->addr << (64 - addrlen);
} else {
host->hw->addr = trans->addr << (32 - addrlen);
}
} else {
/* The output command start from bit0 to bit 15, kept as is.
* The output address start from the LSB of the highest byte, i.e.
* addr[24] -> addr[31]
* ...
* addr[0] -> addr[7]
* slv_wr_status[24] -> slv_wr_status[31]
* ...
* slv_wr_status[0] -> slv_wr_status[7]
* So swap the byte order to let the LSB sent first.
*/
host->hw->user2.usr_command_value = trans->cmd;
uint64_t addr = __builtin_bswap64(trans->addr);
host->hw->addr = addr>>32;
host->hw->slv_wr_status = addr;
}
host->hw->user.usr_mosi=( (!(dev->cfg.flags & SPI_DEVICE_HALFDUPLEX) && trans_buf->buffer_to_rcv) || trans_buf->buffer_to_send)?1:0;
host->hw->user.usr_miso=(trans_buf->buffer_to_rcv)?1:0;
@@ -630,13 +650,13 @@ esp_err_t spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t *
esp_err_t ret = ESP_OK;
BaseType_t r;
SPI_CHECK(handle!=NULL, "invalid dev handle", ESP_ERR_INVALID_ARG);
//check transmission length
//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->length <= handle->host->max_transfer_sz*8, "txdata transfer > host maximum", ESP_ERR_INVALID_ARG);
SPI_CHECK(trans_desc->rxlength <= handle->host->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);
//check working mode
//check working mode
SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO|SPI_TRANS_MODE_QIO)) && (handle->cfg.flags & SPI_DEVICE_3WIRE)), "incompatible iface params", ESP_ERR_INVALID_ARG);
SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO|SPI_TRANS_MODE_QIO)) && (!(handle->cfg.flags & SPI_DEVICE_HALFDUPLEX))), "incompatible iface params", ESP_ERR_INVALID_ARG);
SPI_CHECK( !(handle->cfg.flags & SPI_DEVICE_HALFDUPLEX) || handle->host->dma_chan == 0 || !(trans_desc->flags & SPI_TRANS_USE_RXDATA || trans_desc->rx_buffer != NULL)
@@ -655,7 +675,7 @@ esp_err_t spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t *
// rx memory assign
if ( trans_desc->flags & SPI_TRANS_USE_RXDATA ) {
trans_buf.buffer_to_rcv = (uint32_t*)&trans_desc->rx_data[0];
} else {
} else {
//if not use RXDATA neither rx_buffer, buffer_to_rcv assigned to NULL
trans_buf.buffer_to_rcv = trans_desc->rx_buffer;
}
@@ -668,12 +688,12 @@ esp_err_t spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t *
goto clean_up;
}
}
const uint32_t *txdata;
// tx memory assign
if ( trans_desc->flags & SPI_TRANS_USE_TXDATA ) {
txdata = (uint32_t*)&trans_desc->tx_data[0];
} else {
} else {
//if not use TXDATA neither tx_buffer, tx data assigned to NULL
txdata = trans_desc->tx_buffer ;
}
@@ -686,11 +706,11 @@ esp_err_t spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t *
goto clean_up;
}
memcpy( trans_buf.buffer_to_send, txdata, (trans_desc->length+7)/8 );
} else {
} else {
// else use the original buffer (forced-conversion) or assign to NULL
trans_buf.buffer_to_send = (uint32_t*)txdata;
}
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_acquire(handle->host->pm_lock);
#endif
@@ -710,10 +730,10 @@ clean_up:
// free malloc-ed buffer (if needed) before return.
if ( (void*)trans_buf.buffer_to_rcv != trans_desc->rx_buffer && (void*)trans_buf.buffer_to_rcv != &trans_desc->rx_data[0] ) {
free( trans_buf.buffer_to_rcv );
}
}
if ( (void*)trans_buf.buffer_to_send!= trans_desc->tx_buffer && (void*)trans_buf.buffer_to_send != &trans_desc->tx_data[0] ) {
free( trans_buf.buffer_to_send );
}
}
assert( ret != ESP_OK );
return ret;
}
@@ -722,12 +742,12 @@ esp_err_t spi_device_get_trans_result(spi_device_handle_t handle, spi_transactio
{
BaseType_t r;
spi_trans_priv trans_buf;
SPI_CHECK(handle!=NULL, "invalid dev handle", ESP_ERR_INVALID_ARG);
r=xQueueReceive(handle->ret_queue, (void*)&trans_buf, ticks_to_wait);
if (!r) {
// The memory occupied by rx and tx DMA buffer destroyed only when receiving from the queue (transaction finished).
// If timeout, wait and retry.
// If timeout, wait and retry.
// Every on-flight transaction request occupies internal memory as DMA buffer if needed.
return ESP_ERR_TIMEOUT;
}
@@ -736,12 +756,12 @@ esp_err_t spi_device_get_trans_result(spi_device_handle_t handle, spi_transactio
if ( (void*)trans_buf.buffer_to_send != &(*trans_desc)->tx_data[0] && trans_buf.buffer_to_send != (*trans_desc)->tx_buffer ) {
free( trans_buf.buffer_to_send );
}
}
//copy data from temporary DMA-capable buffer back to IRAM buffer and free the temporary one.
if ( (void*)trans_buf.buffer_to_rcv != &(*trans_desc)->rx_data[0] && trans_buf.buffer_to_rcv != (*trans_desc)->rx_buffer ) {
if ( (*trans_desc)->flags & SPI_TRANS_USE_RXDATA ) {
memcpy( (uint8_t*)&(*trans_desc)->rx_data[0], trans_buf.buffer_to_rcv, ((*trans_desc)->rxlength+7)/8 );
memcpy( (uint8_t*)&(*trans_desc)->rx_data[0], trans_buf.buffer_to_rcv, ((*trans_desc)->rxlength+7)/8 );
} else {
memcpy( (*trans_desc)->rx_buffer, trans_buf.buffer_to_rcv, ((*trans_desc)->rxlength+7)/8 );
}

View File

@@ -50,6 +50,7 @@ static const char *SPI_TAG = "spi_slave";
#define VALID_HOST(x) (x>SPI_HOST && x<=VSPI_HOST)
typedef struct {
int id;
spi_slave_interface_config_t cfg;
intr_handle_t intr;
spi_dev_t *hw;
@@ -79,7 +80,7 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
spi_chan_claimed=spicommon_periph_claim(host);
SPI_CHECK(spi_chan_claimed, "host already in use", ESP_ERR_INVALID_STATE);
if ( dma_chan != 0 ) {
dma_chan_claimed=spicommon_dma_chan_claim(dma_chan);
if ( !dma_chan_claimed ) {
@@ -92,10 +93,12 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
if (spihost[host] == NULL) goto nomem;
memset(spihost[host], 0, sizeof(spi_slave_t));
memcpy(&spihost[host]->cfg, slave_config, sizeof(spi_slave_interface_config_t));
spihost[host]->id = host;
spicommon_bus_initialize_io(host, bus_config, dma_chan, SPICOMMON_BUSFLAG_SLAVE, &native);
gpio_set_direction(slave_config->spics_io_num, GPIO_MODE_INPUT);
spicommon_cs_initialize(host, slave_config->spics_io_num, 0, native == false);
spicommon_cs_initialize(host, slave_config->spics_io_num, 0, native==false);
// The slave DMA suffers from unexpected transactions. Forbid reading if DMA is enabled by disabling the CS line.
if (dma_chan != 0) spicommon_freeze_cs(host);
spihost[host]->no_gpio_matrix = native;
spihost[host]->dma_chan = dma_chan;
if (dma_chan != 0) {
@@ -239,9 +242,9 @@ esp_err_t spi_slave_queue_trans(spi_host_device_t host, const spi_slave_transact
BaseType_t r;
SPI_CHECK(VALID_HOST(host), "invalid host", ESP_ERR_INVALID_ARG);
SPI_CHECK(spihost[host], "host not slave", ESP_ERR_INVALID_ARG);
SPI_CHECK(spihost[host]->dma_chan == 0 || trans_desc->tx_buffer==NULL || esp_ptr_dma_capable(trans_desc->tx_buffer),
SPI_CHECK(spihost[host]->dma_chan == 0 || trans_desc->tx_buffer==NULL || esp_ptr_dma_capable(trans_desc->tx_buffer),
"txdata not in DMA-capable memory", ESP_ERR_INVALID_ARG);
SPI_CHECK(spihost[host]->dma_chan == 0 || trans_desc->rx_buffer==NULL || esp_ptr_dma_capable(trans_desc->rx_buffer),
SPI_CHECK(spihost[host]->dma_chan == 0 || trans_desc->rx_buffer==NULL || esp_ptr_dma_capable(trans_desc->rx_buffer),
"rxdata not in DMA-capable memory", ESP_ERR_INVALID_ARG);
SPI_CHECK(trans_desc->length <= spihost[host]->max_transfer_sz * 8, "data transfer > host maximum", ESP_ERR_INVALID_ARG);
@@ -325,8 +328,11 @@ static void IRAM_ATTR spi_intr(void *arg)
if (!host->hw->slave.trans_done) return;
if (host->cur_trans) {
// When DMA is enabled, the slave rx dma suffers from unexpected transactions. Forbid reading until transaction ready.
if (host->dma_chan != 0) spicommon_freeze_cs(host->id);
//when data of cur_trans->length are all sent, the slv_rdata_bit
//will be the length sent-1 (i.e. cur_trans->length-1 ), otherwise
//will be the length sent-1 (i.e. cur_trans->length-1 ), otherwise
//the length sent.
host->cur_trans->trans_len = host->hw->slv_rd_bit.slv_rdata_bit;
if ( host->cur_trans->trans_len == host->cur_trans->length - 1 ) {
@@ -433,6 +439,9 @@ static void IRAM_ATTR spi_intr(void *arg)
host->hw->user.usr_mosi = (trans->tx_buffer == NULL) ? 0 : 1;
host->hw->user.usr_miso = (trans->rx_buffer == NULL) ? 0 : 1;
//The slave rx dma get disturbed by unexpected transaction. Only connect the CS when slave is ready.
if (host->dma_chan != 0) spicommon_restore_cs(host->id, host->cfg.spics_io_num, host->no_gpio_matrix);
//Kick off transfer
host->hw->cmd.usr = 1;
if (host->cfg.post_setup_cb) host->cfg.post_setup_cb(trans);

View File

@@ -390,7 +390,7 @@ TEST_CASE("SPI Master DMA test, TX and RX in different regions", "[spi]")
trans[4].rxlength = 8*4;
trans[4].tx_buffer = data_drom;
trans[4].flags = SPI_TRANS_USE_RXDATA;
trans[5].length = 8*4;
trans[5].flags = SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA;
@@ -412,7 +412,7 @@ TEST_CASE("SPI Master DMA test, TX and RX in different regions", "[spi]")
}
static inline void int_connect( uint32_t gpio, uint32_t sigo, uint32_t sigi )
static inline void int_connect( uint32_t gpio, uint32_t sigo, uint32_t sigi )
{
gpio_matrix_out( gpio, sigo, false, false );
gpio_matrix_in( gpio, sigi, false );
@@ -430,7 +430,7 @@ TEST_CASE("SPI Master DMA test: length, start, not aligned", "[spi]")
esp_err_t ret;
spi_device_handle_t spi;
spi_bus_config_t buscfg={
.miso_io_num=PIN_NUM_MISO,
.miso_io_num=PIN_NUM_MISO,
.mosi_io_num=PIN_NUM_MOSI,
.sclk_io_num=PIN_NUM_CLK,
.quadwp_io_num=-1,
@@ -441,7 +441,7 @@ TEST_CASE("SPI Master DMA test: length, start, not aligned", "[spi]")
.mode=0, //SPI mode 0
.spics_io_num=PIN_NUM_CS, //CS pin
.queue_size=7, //We want to be able to queue 7 transactions at a time
.pre_cb=NULL,
.pre_cb=NULL,
};
//Initialize the SPI bus
ret=spi_bus_initialize(HSPI_HOST, &buscfg, 1);
@@ -454,14 +454,14 @@ TEST_CASE("SPI Master DMA test: length, start, not aligned", "[spi]")
int_connect( PIN_NUM_MOSI, HSPID_OUT_IDX, HSPIQ_IN_IDX );
memset(rx_buf, 0x66, 320);
for ( int i = 0; i < 8; i ++ ) {
memset( rx_buf, 0x66, sizeof(rx_buf));
spi_transaction_t t = {};
t.length = 8*(i+1);
t.rxlength = 0;
t.tx_buffer = tx_buf+2*i;
t.tx_buffer = tx_buf+2*i;
t.rx_buffer = rx_buf + i;
if ( i == 1 ) {
@@ -470,7 +470,7 @@ TEST_CASE("SPI Master DMA test: length, start, not aligned", "[spi]")
} else if ( i == 2 ) {
//test rx length != tx_length
t.rxlength = t.length - 8;
}
}
spi_device_transmit( spi, &t );
for( int i = 0; i < 16; i ++ ) {
@@ -486,7 +486,7 @@ TEST_CASE("SPI Master DMA test: length, start, not aligned", "[spi]")
} else {
//normal check
TEST_ASSERT( memcmp(t.tx_buffer, t.rx_buffer, t.length/8)==0 );
}
}
}
TEST_ASSERT(spi_bus_remove_device(spi) == ESP_OK);
@@ -495,14 +495,15 @@ TEST_CASE("SPI Master DMA test: length, start, not aligned", "[spi]")
static const char MASTER_TAG[] = "test_master";
static const char SLAVE_TAG[] = "test_slave";
DRAM_ATTR static uint8_t master_send[] = {0x93, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0xaa, 0xcc, 0xff, 0xee, 0x55, 0x77, 0x88, 0x43};
//DRAM_ATTR static uint8_t master_send[] = {0x93, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0xaa, 0xcc, 0xff, 0xee, 0x55, 0x77, 0x88, 0x43};
DRAM_ATTR static uint8_t slave_send[] = { 0xaa, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x13, 0x57, 0x9b, 0xdf, 0x24, 0x68, 0xac, 0xe0 };
/*
static void master_init( spi_device_handle_t* spi, int mode, uint32_t speed)
{
esp_err_t ret;
spi_bus_config_t buscfg={
.miso_io_num=PIN_NUM_MISO,
.miso_io_num=PIN_NUM_MISO,
.mosi_io_num=PIN_NUM_MOSI,
.sclk_io_num=PIN_NUM_CLK,
.quadwp_io_num=-1,
@@ -513,7 +514,7 @@ static void master_init( spi_device_handle_t* spi, int mode, uint32_t speed)
.mode=mode, //SPI mode 0
.spics_io_num=PIN_NUM_CS, //CS pin
.queue_size=16, //We want to be able to queue 7 transactions at a time
.pre_cb=NULL,
.pre_cb=NULL,
.cs_ena_pretrans = 0,
};
//Initialize the SPI bus
@@ -546,6 +547,7 @@ static void slave_init(int mode, int dma_chan)
//Initialize SPI slave interface
TEST_ESP_OK( spi_slave_initialize(VSPI_HOST, &buscfg, &slvcfg, dma_chan) );
}
*/
typedef struct {
uint32_t len;
@@ -604,6 +606,7 @@ static void task_slave(void* arg)
t.tx_buffer = txdata.start;
t.rx_buffer = recvbuf+4;
//loop until trans_len != 0 to skip glitches
memset(recvbuf, 0x66, sizeof(recvbuf));
do {
TEST_ESP_OK( spi_slave_transmit( VSPI_HOST, &t, portMAX_DELAY ) );
} while ( t.trans_len == 0 );
@@ -613,118 +616,177 @@ static void task_slave(void* arg)
}
}
TEST_CASE("SPI master variable cmd & addr test","[spi]")
#define TEST_SPI_HOST HSPI_HOST
#define TEST_SLAVE_HOST VSPI_HOST
static uint8_t bitswap(uint8_t in)
{
uint8_t *tx_buf=master_send;
uint8_t rx_buf[320];
uint8_t *rx_buf_ptr = rx_buf;
uint8_t out = 0;
for (int i = 0; i < 8; i++) {
out = out >> 1;
if (in&0x80) out |= 0x80;
in = in << 1;
}
return out;
}
spi_slave_task_context_t slave_context = {};
esp_err_t err = init_slave_context( &slave_context );
TEST_ASSERT( err == ESP_OK );
#define SPI_BUS_TEST_DEFAULT_CONFIG() {\
.miso_io_num=PIN_NUM_MISO, \
.mosi_io_num=PIN_NUM_MOSI,\
.sclk_io_num=PIN_NUM_CLK,\
.quadwp_io_num=-1,\
.quadhd_io_num=-1\
}
#define SPI_DEVICE_TEST_DEFAULT_CONFIG() {\
.clock_speed_hz=10*1000*1000,\
.mode=0,\
.spics_io_num=PIN_NUM_CS,\
.queue_size=16,\
.pre_cb=NULL, \
.cs_ena_pretrans = 0,\
.cs_ena_posttrans = 0,\
}
#define SPI_SLAVE_TEST_DEFAULT_CONFIG() {\
.mode=0,\
.spics_io_num=PIN_NUM_CS,\
.queue_size=3,\
.flags=0,\
}
void test_cmd_addr(spi_slave_task_context_t *slave_context, bool lsb_first)
{
spi_device_handle_t spi;
//initial master, mode 0, 1MHz
master_init( &spi, 0, 1*1000*1000 );
//initial slave, mode 0, no dma
slave_init(0, 0);
ESP_LOGI(MASTER_TAG, ">>>>>>>>> TEST %s FIRST <<<<<<<<<<<", lsb_first?"LSB":"MSB");
//do internal connection
//initial master, mode 0, 1MHz
spi_bus_config_t buscfg=SPI_BUS_TEST_DEFAULT_CONFIG();
TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &buscfg, 1));
spi_device_interface_config_t devcfg=SPI_DEVICE_TEST_DEFAULT_CONFIG();
devcfg.clock_speed_hz = 1*1000*1000;
if (lsb_first) devcfg.flags |= SPI_DEVICE_BIT_LSBFIRST;
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &spi));
//connecting pins to two peripherals breaks the output, fix it.
int_connect( PIN_NUM_MOSI, HSPID_OUT_IDX, VSPIQ_IN_IDX );
int_connect( PIN_NUM_MISO, VSPIQ_OUT_IDX, HSPID_IN_IDX );
int_connect( PIN_NUM_CS, HSPICS0_OUT_IDX, VSPICS0_IN_IDX );
int_connect( PIN_NUM_CLK, HSPICLK_OUT_IDX, VSPICLK_IN_IDX );
for (int i= 0; i < 8; i++) {
//prepare slave tx data
slave_txdata_t slave_txdata = (slave_txdata_t) {
.start = slave_send,
.len = 256,
};
xQueueSend(slave_context->data_to_send, &slave_txdata, portMAX_DELAY);
vTaskDelay(50);
//prepare master tx data
int cmd_bits = (i+1)*2;
int addr_bits = 56-8*i;
int round_up = (cmd_bits+addr_bits+7)/8*8;
addr_bits = round_up - cmd_bits;
spi_transaction_ext_t trans = (spi_transaction_ext_t) {
.base = {
.flags = SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR,
.addr = 0x456789abcdef0123,
.cmd = 0xcdef,
},
.command_bits = cmd_bits,
.address_bits = addr_bits,
};
ESP_LOGI( MASTER_TAG, "===== test%d =====", i );
ESP_LOGI(MASTER_TAG, "cmd_bits %d, addr_bits: %d", cmd_bits, addr_bits);
TEST_ESP_OK(spi_device_transmit(spi, (spi_transaction_t*)&trans));
//wait for both master and slave end
size_t rcv_len;
slave_rxdata_t *rcv_data = xRingbufferReceive(slave_context->data_received, &rcv_len, portMAX_DELAY);
rcv_len-=4;
uint8_t *buffer = rcv_data->data;
ESP_LOGI(SLAVE_TAG, "trans_len: %d", rcv_len);
TEST_ASSERT_EQUAL(rcv_len, (rcv_data->len+7)/8);
TEST_ASSERT_EQUAL(rcv_data->len, cmd_bits+addr_bits);
ESP_LOG_BUFFER_HEX("slave rx", buffer, rcv_len);
uint16_t cmd_expected = trans.base.cmd & (BIT(cmd_bits) - 1);
uint64_t addr_expected = trans.base.addr & ((1ULL<<addr_bits) - 1);
uint8_t *data_ptr = buffer;
uint16_t cmd_got = *(uint16_t*)data_ptr;
data_ptr += cmd_bits/8;
cmd_got = __builtin_bswap16(cmd_got);
cmd_got = cmd_got >> (16-cmd_bits);
int remain_bits = cmd_bits % 8;
uint64_t addr_got = *(uint64_t*)data_ptr;
data_ptr += 8;
addr_got = __builtin_bswap64(addr_got);
addr_got = (addr_got << remain_bits);
addr_got |= (*data_ptr >> (8-remain_bits));
addr_got = addr_got >> (64-addr_bits);
if (lsb_first) {
cmd_got = __builtin_bswap16(cmd_got);
addr_got = __builtin_bswap64(addr_got);
uint8_t *swap_ptr = (uint8_t*)&cmd_got;
swap_ptr[0] = bitswap(swap_ptr[0]);
swap_ptr[1] = bitswap(swap_ptr[1]);
cmd_got = cmd_got >> (16-cmd_bits);
swap_ptr = (uint8_t*)&addr_got;
for (int j = 0; j < 8; j++) swap_ptr[j] = bitswap(swap_ptr[j]);
addr_got = addr_got >> (64-addr_bits);
}
ESP_LOGI(SLAVE_TAG, "cmd_got: %04X, addr_got: %08X%08X", cmd_got, (uint32_t)(addr_got>>32), (uint32_t)addr_got);
TEST_ASSERT_EQUAL_HEX16(cmd_expected, cmd_got);
if (addr_bits > 0) {
TEST_ASSERT_EQUAL_HEX32(addr_expected, addr_got);
TEST_ASSERT_EQUAL_HEX32(addr_expected >> 8, addr_got >> 8);
}
//clean
vRingbufferReturnItem(slave_context->data_received, buffer);
}
TEST_ASSERT(spi_bus_remove_device(spi) == ESP_OK);
TEST_ASSERT(spi_bus_free(TEST_SPI_HOST) == ESP_OK);
}
TEST_CASE("SPI master variable cmd & addr test","[spi]")
{
spi_slave_task_context_t slave_context = {};
esp_err_t err = init_slave_context( &slave_context );
TEST_ASSERT( err == ESP_OK );
TaskHandle_t handle_slave;
xTaskCreate( task_slave, "spi_slave", 4096, &slave_context, 0, &handle_slave);
slave_txdata_t slave_txdata[16];
spi_transaction_ext_t trans[16];
for( int i= 0; i < 16; i ++ ) {
//prepare slave tx data
slave_txdata[i] = (slave_txdata_t) {
.start = slave_send + 4*(i%3),
.len = 256,
};
xQueueSend( slave_context.data_to_send, &slave_txdata[i], portMAX_DELAY );
//prepare master tx data
trans[i] = (spi_transaction_ext_t) {
.base = {
.flags = SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR,
.addr = 0x456789ab,
.cmd = 0xcdef,
//initial slave, mode 0, no dma
int dma_chan = 0;
int slave_mode = 0;
spi_bus_config_t slv_buscfg=SPI_BUS_TEST_DEFAULT_CONFIG();
spi_slave_interface_config_t slvcfg=SPI_SLAVE_TEST_DEFAULT_CONFIG();
slvcfg.mode = slave_mode;
//Initialize SPI slave interface
TEST_ESP_OK( spi_slave_initialize(TEST_SLAVE_HOST, &slv_buscfg, &slvcfg, dma_chan) );
.length = 8*i,
.tx_buffer = tx_buf+i,
.rx_buffer = rx_buf_ptr,
},
.command_bits = ((i+1)%3) * 8,
.address_bits = ((i/3)%5) * 8,
};
if ( trans[i].base.length == 0 ) {
trans[i].base.tx_buffer = NULL;
trans[i].base.rx_buffer = NULL;
} else {
rx_buf_ptr += (trans[i].base.length + 31)/32*4;
}
}
vTaskDelay(10);
for ( int i = 0; i < 16; i ++ ) {
TEST_ESP_OK (spi_device_queue_trans( spi, (spi_transaction_t*)&trans[i], portMAX_DELAY ) );
vTaskDelay(10);
}
for( int i= 0; i < 16; i ++ ) {
//wait for both master and slave end
ESP_LOGI( MASTER_TAG, "===== test%d =====", i );
spi_transaction_ext_t *t;
size_t rcv_len;
spi_device_get_trans_result( spi, (spi_transaction_t**)&t, portMAX_DELAY );
TEST_ASSERT( t == &trans[i] );
if ( trans[i].base.length != 0 ) {
ESP_LOG_BUFFER_HEX( "master tx", trans[i].base.tx_buffer, trans[i].base.length/8 );
ESP_LOG_BUFFER_HEX( "master rx", trans[i].base.rx_buffer, trans[i].base.length/8 );
} else {
ESP_LOGI( "master tx", "no data" );
ESP_LOGI( "master rx", "no data" );
}
slave_rxdata_t *rcv_data = xRingbufferReceive( slave_context.data_received, &rcv_len, portMAX_DELAY );
uint8_t *buffer = rcv_data->data;
rcv_len = rcv_data->len;
ESP_LOGI(SLAVE_TAG, "trans_len: %d", rcv_len);
ESP_LOG_BUFFER_HEX( "slave tx", slave_txdata[i].start, (rcv_len+7)/8);
ESP_LOG_BUFFER_HEX( "slave rx", buffer, (rcv_len+7)/8);
//check result
uint8_t *ptr_addr = (uint8_t*)&t->base.addr;
uint8_t *ptr_cmd = (uint8_t*)&t->base.cmd;
for ( int j = 0; j < t->command_bits/8; j ++ ) {
TEST_ASSERT_EQUAL( buffer[j], ptr_cmd[t->command_bits/8-j-1] );
}
for ( int j = 0; j < t->address_bits/8; j ++ ) {
TEST_ASSERT_EQUAL( buffer[t->command_bits/8+j], ptr_addr[t->address_bits/8-j-1] );
}
if ( t->base.length != 0) {
TEST_ASSERT_EQUAL_HEX8_ARRAY(t->base.tx_buffer, buffer + (t->command_bits + t->address_bits)/8, t->base.length/8);
TEST_ASSERT_EQUAL_HEX8_ARRAY(slave_txdata[i].start + (t->command_bits + t->address_bits)/8, t->base.rx_buffer, t->base.length/8);
}
TEST_ASSERT_EQUAL( t->base.length + t->command_bits + t->address_bits, rcv_len );
//clean
vRingbufferReturnItem( slave_context.data_received, buffer );
}
test_cmd_addr(&slave_context, false);
test_cmd_addr(&slave_context, true);
vTaskDelete( handle_slave );
handle_slave = 0;
deinit_slave_context(&slave_context);
TEST_ASSERT(spi_slave_free(VSPI_HOST) == ESP_OK);
TEST_ASSERT(spi_bus_remove_device(spi) == ESP_OK);
TEST_ASSERT(spi_bus_free(HSPI_HOST) == ESP_OK);
TEST_ASSERT(spi_slave_free(TEST_SLAVE_HOST) == ESP_OK);
ESP_LOGI(MASTER_TAG, "test passed.");
}

View File

@@ -43,6 +43,8 @@ static const char* UART_TAG = "uart";
#define UART_EMPTY_THRESH_DEFAULT (10)
#define UART_FULL_THRESH_DEFAULT (120)
#define UART_TOUT_THRESH_DEFAULT (10)
#define UART_CLKDIV_FRAG_BIT_WIDTH (3)
#define UART_TOUT_REF_FACTOR_DEFAULT (UART_CLK_FREQ/(REF_CLK_FREQ<<UART_CLKDIV_FRAG_BIT_WIDTH))
#define UART_TX_IDLE_NUM_DEFAULT (0)
#define UART_PATTERN_DET_QLEN_DEFAULT (10)
@@ -654,7 +656,13 @@ esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
UART[uart_num]->int_clr.val = UART_INTR_MASK;
if(intr_conf->intr_enable_mask & UART_RXFIFO_TOUT_INT_ENA_M) {
UART[uart_num]->conf1.rx_tout_thrhd = ((intr_conf->rx_timeout_thresh) & UART_RX_TOUT_THRHD_V);
//Hardware issue workaround: when using ref_tick, the rx timeout threshold needs increase to 10 times.
//T_ref = T_apb * APB_CLK/(REF_TICK << CLKDIV_FRAG_BIT_WIDTH)
if(UART[uart_num]->conf0.tick_ref_always_on == 0) {
UART[uart_num]->conf1.rx_tout_thrhd = ((intr_conf->rx_timeout_thresh * UART_TOUT_REF_FACTOR_DEFAULT) & UART_RX_TOUT_THRHD_V);
} else {
UART[uart_num]->conf1.rx_tout_thrhd = ((intr_conf->rx_timeout_thresh) & UART_RX_TOUT_THRHD_V);
}
UART[uart_num]->conf1.rx_tout_en = 1;
} else {
UART[uart_num]->conf1.rx_tout_en = 0;
@@ -1132,8 +1140,8 @@ int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickTyp
if(res == pdTRUE) {
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
p_uart_obj[uart_num]->rx_buffered_len += p_uart_obj[uart_num]->rx_stash_len;
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
p_uart_obj[uart_num]->rx_buffer_full_flg = false;
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num);
}
}
@@ -1178,6 +1186,14 @@ esp_err_t uart_flush_input(uart_port_t uart_num)
}
data = (uint8_t*) xRingbufferReceive(p_uart->rx_ring_buf, &size, (portTickType) 0);
if(data == NULL) {
if( p_uart_obj[uart_num]->rx_buffered_len != 0 ) {
ESP_LOGE(UART_TAG, "rx_buffered_len error");
p_uart_obj[uart_num]->rx_buffered_len = 0;
}
//We also need to clear the `rx_buffer_full_flg` here.
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
p_uart_obj[uart_num]->rx_buffer_full_flg = false;
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
break;
}
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
@@ -1190,8 +1206,8 @@ esp_err_t uart_flush_input(uart_port_t uart_num)
if(res == pdTRUE) {
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
p_uart_obj[uart_num]->rx_buffered_len += p_uart_obj[uart_num]->rx_stash_len;
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
p_uart_obj[uart_num]->rx_buffer_full_flg = false;
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
}
}
}

View File

@@ -38,3 +38,7 @@ CFLAGS+=-mfix-esp32-psram-cache-issue
CXXFLAGS+=-mfix-esp32-psram-cache-issue
endif
# Enable dynamic esp_timer overflow value if building unit tests
ifneq ("$(TEST_COMPONENTS_LIST)","")
CPPFLAGS += -DESP_TIMER_DYNAMIC_OVERFLOW_VAL
endif

View File

@@ -44,7 +44,7 @@ static volatile uint32_t reason[ portNUM_PROCESSORS ];
ToDo: There is a small chance the CPU already has yielded when this ISR is serviced. In that case, it's running the intended task but
the ISR will cause it to switch _away_ from it. portYIELD_FROM_ISR will probably just schedule the task again, but have to check that.
*/
static void esp_crosscore_isr_handle_yield()
static inline void IRAM_ATTR esp_crosscore_isr_handle_yield()
{
portYIELD_FROM_ISR();
}

View File

@@ -82,7 +82,18 @@
* ISR happens follow set_alarm, so change the ALARM_OVERFLOW_VAL to resolve this problem.
* Set it to 0xefffffffUL. The remain 0x10000000UL(about 3 second) is enough to handle ISR.
*/
#define ALARM_OVERFLOW_VAL 0xefffffffUL
#define DEFAULT_ALARM_OVERFLOW_VAL 0xefffffffUL
/* Provision to set lower overflow value for unit testing. Lowering the
* overflow value helps check for race conditions which occur near overflow
* moment.
*/
#ifndef ESP_TIMER_DYNAMIC_OVERFLOW_VAL
#define ALARM_OVERFLOW_VAL DEFAULT_ALARM_OVERFLOW_VAL
#else
static uint32_t s_alarm_overflow_val = DEFAULT_ALARM_OVERFLOW_VAL;
#define ALARM_OVERFLOW_VAL (s_alarm_overflow_val)
#endif
static const char* TAG = "esp_timer_impl";
@@ -206,18 +217,6 @@ void IRAM_ATTR esp_timer_impl_set_alarm(uint64_t timestamp)
// Adjust current time if overflow has happened
bool overflow = timer_overflow_happened();
uint64_t cur_count = REG_READ(FRC_TIMER_COUNT_REG(1));
uint32_t offset = s_timer_ticks_per_us * 2; //remain 2us for more safe
//If overflow is going to happen in 1us, let's wait until it happens,
//else we think it will not happen before new alarm set.
//And we should wait current timer count less than ALARM_OVERFLOW_VAL,
//maybe equals to 0.
if (cur_count + offset >= ALARM_OVERFLOW_VAL) {
do {
overflow = timer_overflow_happened();
cur_count = REG_READ(FRC_TIMER_COUNT_REG(1));
} while(!overflow || cur_count == ALARM_OVERFLOW_VAL);
}
if (overflow) {
assert(time_after_timebase_us > s_timer_us_per_overflow);
@@ -227,13 +226,17 @@ void IRAM_ATTR esp_timer_impl_set_alarm(uint64_t timestamp)
// Calculate desired timer compare value (may exceed 2^32-1)
uint64_t compare_val = time_after_timebase_us * s_timer_ticks_per_us;
uint32_t alarm_reg_val = ALARM_OVERFLOW_VAL;
// Use calculated alarm value if it is less than 2^32-1
// Use calculated alarm value if it is less than ALARM_OVERFLOW_VAL.
// Note that if by the time we update ALARM_REG, COUNT_REG value is higher,
// interrupt will not happen for another ALARM_OVERFLOW_VAL timer ticks,
// so need to check if alarm value is too close in the future (e.g. <2 us away).
const uint32_t offset = s_timer_ticks_per_us * 2;
if (compare_val < ALARM_OVERFLOW_VAL) {
// If we by the time we update ALARM_REG, COUNT_REG value is higher,
// interrupt will not happen for another 2^32 timer ticks, so need to
// check if alarm value is too close in the future (e.g. <1 us away).
if (compare_val < cur_count + offset) {
compare_val = cur_count + offset;
if (compare_val > ALARM_OVERFLOW_VAL) {
compare_val = ALARM_OVERFLOW_VAL;
}
}
alarm_reg_val = (uint32_t) compare_val;
}
@@ -361,3 +364,17 @@ uint64_t IRAM_ATTR esp_timer_impl_get_min_period_us()
{
return 50;
}
#ifdef ESP_TIMER_DYNAMIC_OVERFLOW_VAL
uint32_t esp_timer_impl_get_overflow_val()
{
return s_alarm_overflow_val;
}
void esp_timer_impl_set_overflow_val(uint32_t overflow_val)
{
s_alarm_overflow_val = overflow_val;
/* update alarm value */
esp_timer_impl_update_apb_freq(esp_clk_apb_freq() / 1000000);
}
#endif // ESP_TIMER_DYNAMIC_OVERFLOW_VAL

View File

@@ -103,7 +103,7 @@ esp_err_t system_event_eth_connected_handle_default(system_event_t *event)
tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, &eth_ip);
if (!(ip4_addr_isany_val(eth_ip.ip) || ip4_addr_isany_val(eth_ip.netmask) || ip4_addr_isany_val(eth_ip.gw))) {
if (!(ip4_addr_isany_val(eth_ip.ip) || ip4_addr_isany_val(eth_ip.netmask))) {
system_event_t evt;
//notify event
@@ -214,7 +214,7 @@ esp_err_t system_event_sta_connected_handle_default(system_event_t *event)
tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &sta_ip);
tcpip_adapter_get_old_ip_info(TCPIP_ADAPTER_IF_STA, &sta_old_ip);
if (!(ip4_addr_isany_val(sta_ip.ip) || ip4_addr_isany_val(sta_ip.netmask) || ip4_addr_isany_val(sta_ip.gw))) {
if (!(ip4_addr_isany_val(sta_ip.ip) || ip4_addr_isany_val(sta_ip.netmask))) {
system_event_t evt;
evt.event_id = SYSTEM_EVENT_STA_GOT_IP;

View File

@@ -36,6 +36,7 @@
#include "soc/cpu.h"
#include <stdio.h>
#include "driver/periph_ctrl.h"
/* AES uses a spinlock mux not a lock as the underlying block operation
@@ -50,9 +51,9 @@ static portMUX_TYPE aes_spinlock = portMUX_INITIALIZER_UNLOCKED;
void esp_aes_acquire_hardware( void )
{
/* newlib locks lazy initialize on ESP-IDF */
portENTER_CRITICAL(&aes_spinlock);
#if defined(DPORT_PROTECT_STALL_OTHER_CPU_USE)
DPORT_STALL_OTHER_CPU_START();
{
/* Enable AES hardware */
@@ -65,10 +66,15 @@ void esp_aes_acquire_hardware( void )
| DPORT_PERI_EN_SECUREBOOT);
}
DPORT_STALL_OTHER_CPU_END();
#else
/* Enable AES hardware */
periph_module_enable(PERIPH_AES_MODULE);
#endif
}
void esp_aes_release_hardware( void )
{
#if defined(DPORT_PROTECT_STALL_OTHER_CPU_USE)
DPORT_STALL_OTHER_CPU_START();
{
/* Disable AES hardware */
@@ -78,7 +84,10 @@ void esp_aes_release_hardware( void )
_DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_AES);
}
DPORT_STALL_OTHER_CPU_END();
#else
/* Disable AES hardware */
periph_module_disable(PERIPH_AES_MODULE);
#endif
portEXIT_CRITICAL(&aes_spinlock);
}
@@ -122,7 +131,10 @@ static inline void esp_aes_setkey_hardware( esp_aes_context *ctx, int mode)
const uint32_t MODE_DECRYPT_BIT = 4;
unsigned mode_reg_base = (mode == ESP_AES_ENCRYPT) ? 0 : MODE_DECRYPT_BIT;
memcpy((uint32_t *)AES_KEY_BASE, ctx->key, ctx->key_bytes);
for (int i = 0; i < ctx->key_bytes/4; ++i) {
DPORT_REG_WRITE(AES_KEY_BASE + i * 4, *(((uint32_t *)ctx->key) + i));
}
DPORT_REG_WRITE(AES_MODE_REG, mode_reg_base + ((ctx->key_bytes / 8) - 2));
}

View File

@@ -35,6 +35,7 @@
#include "rom/ets_sys.h"
#include "soc/dport_reg.h"
#include "soc/hwcrypto_reg.h"
#include "driver/periph_ctrl.h"
inline static uint32_t SHA_LOAD_REG(esp_sha_type sha_type) {
return SHA_1_LOAD_REG + sha_type * 0x10;
@@ -159,6 +160,7 @@ static void esp_sha_lock_engine_inner(sha_engine_state *engine)
_lock_acquire(&state_change_lock);
if (sha_engines_all_idle()) {
#if defined(DPORT_PROTECT_STALL_OTHER_CPU_USE)
DPORT_STALL_OTHER_CPU_START();
{
/* Enable SHA hardware */
@@ -170,6 +172,11 @@ static void esp_sha_lock_engine_inner(sha_engine_state *engine)
ets_sha_enable();
}
DPORT_STALL_OTHER_CPU_END();
#else
/* Enable SHA hardware */
periph_module_enable(PERIPH_SHA_MODULE);
ets_sha_enable();
#endif
}
assert( !engine->in_use && "in_use flag should be cleared" );
@@ -189,6 +196,7 @@ void esp_sha_unlock_engine(esp_sha_type sha_type)
engine->in_use = false;
if (sha_engines_all_idle()) {
#if defined(DPORT_PROTECT_STALL_OTHER_CPU_USE)
/* Disable SHA hardware */
/* Don't assert reset on secure boot, otherwise AES is held in reset */
DPORT_STALL_OTHER_CPU_START();
@@ -197,6 +205,9 @@ void esp_sha_unlock_engine(esp_sha_type sha_type)
_DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_SHA);
}
DPORT_STALL_OTHER_CPU_END();
#else
periph_module_disable(PERIPH_SHA_MODULE);
#endif
}
_lock_release(&state_change_lock);
@@ -288,9 +299,9 @@ void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, uns
SHA_CTX ctx;
ets_sha_init(&ctx);
esp_sha_lock_memory_block();
while(ilen > 0) {
size_t chunk_len = (ilen > block_len) ? block_len : ilen;
esp_sha_lock_memory_block();
esp_sha_wait_idle();
DPORT_STALL_OTHER_CPU_START();
{
@@ -298,11 +309,9 @@ void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, uns
ets_sha_update(&ctx, sha_type, input, chunk_len * 8);
}
DPORT_STALL_OTHER_CPU_END();
esp_sha_unlock_memory_block();
input += chunk_len;
ilen -= chunk_len;
}
esp_sha_lock_memory_block();
esp_sha_wait_idle();
DPORT_STALL_OTHER_CPU_START();
{

View File

@@ -35,6 +35,7 @@ void esp_dport_access_int_abort(void);
#define DPORT_STALL_OTHER_CPU_START()
#define DPORT_STALL_OTHER_CPU_END()
#else
#define DPORT_PROTECT_STALL_OTHER_CPU_USE
#define DPORT_STALL_OTHER_CPU_START() esp_dport_access_stall_other_cpu_start()
#define DPORT_STALL_OTHER_CPU_END() esp_dport_access_stall_other_cpu_end()
#endif

View File

@@ -18,8 +18,23 @@
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
typedef enum {
ESP_SPIRAM_SIZE_32MBITS = 0, /*!< SPI RAM size is 32 MBits */
ESP_SPIRAM_SIZE_64MBITS = 1, /*!< SPI RAM size is 64 MBits */
ESP_SPIRAM_SIZE_INVALID, /*!< SPI RAM size is invalid */
} esp_spiram_size_t;
/**
* @brief get SPI RAM size
* @return
* - ESP_SPIRAM_SIZE_INVALID if SPI RAM not enabled or not valid
* - SPI RAM size
*/
esp_spiram_size_t esp_spiram_get_chip_size();
/**
* @brief Initialize spiram interface/hardware. Normally called from cpu_start.c.
*

View File

@@ -290,7 +290,13 @@ esp_err_t esp_wifi_restore(void);
*
* @attention 1. This API only impact WIFI_MODE_STA or WIFI_MODE_APSTA mode
* @attention 2. If the ESP32 is connected to an AP, call esp_wifi_disconnect to disconnect.
*
* @attention 3. The scanning triggered by esp_wifi_start_scan() will not be effective until connection between ESP32 and the AP is established.
* If ESP32 is scanning and connecting at the same time, ESP32 will abort scanning and return a warning message and error
* number ESP_ERR_WIFI_STATE.
* If you want to do reconnection after ESP32 received disconnect event, remember to add the maximum retry time, otherwise the called
* scan will not work. This is especially true when the AP doesn't exist, and you still try reconnection after ESP32 received disconnect
* event with the reason code WIFI_REASON_NO_AP_FOUND.
*
* @return
* - ESP_OK: succeed
* - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
@@ -353,6 +359,7 @@ esp_err_t esp_wifi_deauth_sta(uint16_t aid);
* - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
* - ESP_ERR_WIFI_NOT_STARTED: WiFi was not started by esp_wifi_start
* - ESP_ERR_WIFI_TIMEOUT: blocking scan is timeout
* - ESP_ERR_WIFI_STATE: wifi still connecting when invoke esp_wifi_scan_start
* - others: refer to error code in esp_err.h
*/
esp_err_t esp_wifi_scan_start(const wifi_scan_config_t *config, bool block);

View File

@@ -35,6 +35,7 @@
#include "esp_err.h"
#include "esp_wifi_types.h"
#include "esp_event.h"
#include "esp_wifi.h"
#ifdef __cplusplus
extern "C" {
@@ -161,6 +162,15 @@ void *wifi_realloc( void *ptr, size_t size );
*/
void *wifi_calloc( size_t n, size_t size );
/**
* @brief Update WiFi MAC time
*
* @param uint32_t time_delta : time duration since the WiFi/BT common clock is disabled
*
* @return Always returns ESP_OK
*/
esp_err_t esp_wifi_internal_update_mac_time( uint32_t time_delta );
#ifdef __cplusplus
}
#endif

View File

@@ -117,6 +117,8 @@ extern "C" {
#define ESP_ROM_SPIFLASH_WR_PROTECT (ESP_ROM_SPIFLASH_BP0|ESP_ROM_SPIFLASH_BP1|ESP_ROM_SPIFLASH_BP2)
#define ESP_ROM_SPIFLASH_QE BIT9
#define FLASH_ID_GD25LQ32C 0xC86016
typedef enum {
ESP_ROM_SPIFLASH_QIO_MODE = 0,
ESP_ROM_SPIFLASH_QOUT_MODE,

View File

@@ -89,7 +89,6 @@ SECTIONS
*libesp32.a:core_dump.o(.literal .text .literal.* .text.*)
*libapp_trace.a:(.literal .text .literal.* .text.*)
*libxtensa-debug-module.a:eri.o(.literal .text .literal.* .text.*)
*libphy.a:(.literal .text .literal.* .text.*)
*librtc.a:(.literal .text .literal.* .text.*)
*libsoc.a:(.literal .text .literal.* .text.*)
*libhal.a:(.literal .text .literal.* .text.*)

View File

@@ -224,6 +224,7 @@ PROVIDE ( lld_evt_env = 0x3ffb9704 );
PROVIDE ( lld_evt_elt_wait_get = 0x400468e4 );
PROVIDE ( lld_evt_get_next_free_slot = 0x4004692c );
PROVIDE ( lld_pdu_adv_pk_desc_tab = 0x3ff98c70 );
PROVIDE ( lld_pdu_tx_flush_list = 0x4004a760 );
PROVIDE ( lld_pdu_llcp_pk_desc_tab = 0x3ff98b68 );
PROVIDE ( lld_pdu_pack = 0x4004ab14 );
PROVIDE ( LLM_AA_CT1 = 0x3ff98d8a );
@@ -761,6 +762,7 @@ PROVIDE ( lmp_io_cap_req_handler = 0x4002c7a4 );
PROVIDE ( ld_acl_tx_packet_type_select = 0x4002fb40 );
PROVIDE ( ld_acl_sched = 0x40033268 );
PROVIDE ( ld_acl_sniff_sched = 0x4003340c );
PROVIDE ( ld_acl_clk_isr = 0x40030cf8 );
PROVIDE ( lm_cmd_cmp_send = 0x40051838 );
PROVIDE ( r_ld_acl_active_hop_types_get = 0x40036e10 );
PROVIDE ( r_ld_acl_afh_confirm = 0x40036d40 );
@@ -1484,8 +1486,8 @@ PROVIDE ( esp_rom_spiflash_attach = 0x40062a6c );
PROVIDE ( esp_rom_spiflash_config_clk = 0x40062bc8 );
PROVIDE ( g_rom_spiflash_chip = 0x3ffae270 );
/*
These functions are xtos-related (or call xtos-related functions) and do not play well
/*
These functions are xtos-related (or call xtos-related functions) and do not play well
with multicore FreeRTOS. Where needed, we provide alternatives that are multicore
compatible. These functions also use a chunk of static RAM, by not using them we can
allocate that RAM for general use.

View File

@@ -36,6 +36,7 @@
#include "phy_init_data.h"
#include "esp_coexist.h"
#include "driver/periph_ctrl.h"
#include "esp_wifi_internal.h"
static const char* TAG = "phy_init";
@@ -44,6 +45,24 @@ static int s_phy_rf_init_count = 0;
static _lock_t s_phy_rf_init_lock;
static inline void phy_update_wifi_mac_time(bool en_clock_stopped)
{
static uint32_t s_common_clock_disable_time = 0;
if (en_clock_stopped) {
s_common_clock_disable_time = esp_timer_get_time();
} else {
if (s_common_clock_disable_time) {
uint64_t now = esp_timer_get_time();
uint32_t diff = now - s_common_clock_disable_time;
esp_wifi_internal_update_mac_time(diff);
s_common_clock_disable_time = 0;
ESP_LOGD(TAG, "wifi mac time delta: %u", diff);
}
}
}
esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data,
esp_phy_calibration_mode_t mode, esp_phy_calibration_data_t* calibration_data)
{
@@ -51,6 +70,8 @@ esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data,
_lock_acquire(&s_phy_rf_init_lock);
if (s_phy_rf_init_count == 0) {
// Update WiFi MAC time before WiFi/BT common clock is enabled
phy_update_wifi_mac_time( false );
// Enable WiFi/BT common peripheral clock
periph_module_enable(PERIPH_WIFI_BT_COMMON_MODULE);
ESP_LOGV(TAG, "register_chipv7_phy, init_data=%p, cal_data=%p, mode=%d",
@@ -76,6 +97,8 @@ esp_err_t esp_phy_rf_deinit(void)
if (s_phy_rf_init_count == 1) {
// Disable PHY and RF.
phy_close_rf();
// Update WiFi MAC time before disalbe WiFi/BT common peripheral clock
phy_update_wifi_mac_time(true);
// Disable WiFi/BT common peripheral clock. Do not disable clock for hardware RNG
periph_module_disable(PERIPH_WIFI_BT_COMMON_MODULE);
} else {
@@ -164,6 +187,7 @@ esp_err_t esp_phy_load_cal_data_from_nvs(esp_phy_calibration_data_t* out_cal_dat
if (err == ESP_ERR_NVS_NOT_INITIALIZED) {
ESP_LOGE(TAG, "%s: NVS has not been initialized. "
"Call nvs_flash_init before starting WiFi/BT.", __func__);
return err;
} else if (err != ESP_OK) {
ESP_LOGD(TAG, "%s: failed to open NVS namespace (0x%x)", __func__, err);
return err;
@@ -241,19 +265,34 @@ static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle,
const esp_phy_calibration_data_t* cal_data)
{
esp_err_t err;
uint32_t cal_format_version = phy_get_rf_cal_version() & (~BIT(16));
ESP_LOGV(TAG, "phy_get_rf_cal_version: %d\n", cal_format_version);
err = nvs_set_u32(handle, PHY_CAL_VERSION_KEY, cal_format_version);
err = nvs_set_blob(handle, PHY_CAL_DATA_KEY, cal_data, sizeof(*cal_data));
if (err != ESP_OK) {
ESP_LOGE(TAG, "%s: store calibration data failed(0x%x)\n", __func__, err);
return err;
}
uint8_t sta_mac[6];
esp_efuse_mac_get_default(sta_mac);
err = nvs_set_blob(handle, PHY_CAL_MAC_KEY, sta_mac, sizeof(sta_mac));
if (err != ESP_OK) {
ESP_LOGE(TAG, "%s: store calibration mac failed(0x%x)\n", __func__, err);
return err;
}
err = nvs_set_blob(handle, PHY_CAL_DATA_KEY, cal_data, sizeof(*cal_data));
uint32_t cal_format_version = phy_get_rf_cal_version() & (~BIT(16));
ESP_LOGV(TAG, "phy_get_rf_cal_version: %d\n", cal_format_version);
err = nvs_set_u32(handle, PHY_CAL_VERSION_KEY, cal_format_version);
if (err != ESP_OK) {
ESP_LOGE(TAG, "%s: store calibration version failed(0x%x)\n", __func__, err);
return err;
}
err = nvs_commit(handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "%s: store calibration nvs commit failed(0x%x)\n", __func__, err);
}
return err;
}

View File

@@ -23,6 +23,7 @@ we add more types of external RAM memory, this can be made into a more intellige
#include "sdkconfig.h"
#include "esp_attr.h"
#include "esp_err.h"
#include "esp_spiram.h"
#include "spiram_psram.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
@@ -102,6 +103,22 @@ void IRAM_ATTR esp_spiram_init_cache()
#endif
}
esp_spiram_size_t esp_spiram_get_chip_size()
{
if (!spiram_inited) {
ESP_LOGE(TAG, "SPI RAM not initialized");
return ESP_SPIRAM_SIZE_INVALID;
}
psram_size_t psram_size = psram_get_size();
switch (psram_size) {
case PSRAM_SIZE_32MBITS:
return ESP_SPIRAM_SIZE_32MBITS;
case PSRAM_SIZE_64MBITS:
return ESP_SPIRAM_SIZE_64MBITS;
default:
return ESP_SPIRAM_SIZE_INVALID;
}
}
esp_err_t esp_spiram_init()
{

View File

@@ -39,26 +39,39 @@
#if CONFIG_SPIRAM_SUPPORT
//Commands for PSRAM chip
#define PSRAM_READ 0x03
#define PSRAM_FAST_READ 0x0B
#define PSRAM_FAST_READ_DUMMY 0x3
#define PSRAM_FAST_READ_QUAD 0xEB
#define PSRAM_WRITE 0x02
#define PSRAM_QUAD_WRITE 0x38
#define PSRAM_ENTER_QMODE 0x35
#define PSRAM_EXIT_QMODE 0xF5
#define PSRAM_RESET_EN 0x66
#define PSRAM_RESET 0x99
#define PSRAM_SET_BURST_LEN 0xC0
#define PSRAM_DEVICE_ID 0x9F
#define PSRAM_READ 0x03
#define PSRAM_FAST_READ 0x0B
#define PSRAM_FAST_READ_DUMMY 0x3
#define PSRAM_FAST_READ_QUAD 0xEB
#define PSRAM_FAST_READ_QUAD_DUMMY 0x5
#define PSRAM_WRITE 0x02
#define PSRAM_QUAD_WRITE 0x38
#define PSRAM_ENTER_QMODE 0x35
#define PSRAM_EXIT_QMODE 0xF5
#define PSRAM_RESET_EN 0x66
#define PSRAM_RESET 0x99
#define PSRAM_SET_BURST_LEN 0xC0
#define PSRAM_DEVICE_ID 0x9F
#if CONFIG_SPIRAM_TYPE_ESPPSRAM32
typedef enum {
PSRAM_CLK_MODE_NORM = 0, /*!< Normal SPI mode */
PSRAM_CLK_MODE_DCLK = 1, /*!< Two extra clock cycles after CS is set high level */
} psram_clk_mode_t;
#define PSRAM_MFG_ID_M 0xff
#define PSRAM_MFG_ID_S 8
#define PSRAM_MFG_ID_V 0x5d
#define PSRAM_ID_KGD_M 0xff
#define PSRAM_ID_KGD_S 8
#define PSRAM_ID_KGD 0x5d
#define PSRAM_ID_EID_M 0xff
#define PSRAM_ID_EID_S 16
#endif
#define PSRAM_KGD(id) (((id) >> PSRAM_ID_KGD_S) & PSRAM_ID_KGD_M)
#define PSRAM_EID(id) (((id) >> PSRAM_ID_EID_S) & PSRAM_ID_EID_M)
#define PSRAM_IS_VALID(id) (PSRAM_KGD(id) == PSRAM_ID_KGD)
// PSRAM_EID = 0x26 or 0x4x ----> 64MBit psram
// PSRAM_EID = 0x20 ------------> 32MBit psram
#define PSRAM_IS_64MBIT(id) ((PSRAM_EID(id) == 0x26) || ((PSRAM_EID(id) & 0xf0) == 0x40))
#define PSRAM_IS_32MBIT_VER0(id) (PSRAM_EID(id) == 0x20)
// IO-pins for PSRAM. These need to be in the VDD_SIO power domain because all chips we
// currently support are 1.8V parts.
@@ -98,6 +111,8 @@ typedef enum {
} psram_spi_num_t;
static psram_cache_mode_t s_psram_mode = PSRAM_CACHE_MAX;
static psram_clk_mode_t s_clk_mode = PSRAM_CLK_MODE_DCLK;
static uint32_t s_psram_id = 0;
/* dummy_len_plus values defined in ROM for SPI flash configuration */
extern uint8_t g_rom_spiflash_dummy_len_plus[];
@@ -286,7 +301,7 @@ static int psram_cmd_config(psram_spi_num_t spi_num, psram_cmd_t* pInData)
return 0;
}
void psram_cmd_end(int spi_num) {
static void psram_cmd_end(int spi_num) {
while (READ_PERI_REG(SPI_CMD_REG(spi_num)) & SPI_USR);
WRITE_PERI_REG(SPI_USER_REG(spi_num), backup_usr[spi_num]);
WRITE_PERI_REG(SPI_USER1_REG(spi_num), backup_usr1[spi_num]);
@@ -298,17 +313,19 @@ static void psram_disable_qio_mode(psram_spi_num_t spi_num)
{
psram_cmd_t ps_cmd;
uint32_t cmd_exit_qpi;
switch (s_psram_mode) {
case PSRAM_CACHE_F80M_S80M:
cmd_exit_qpi = PSRAM_EXIT_QMODE;
ps_cmd.txDataBitLen = 8;
break;
case PSRAM_CACHE_F80M_S40M:
case PSRAM_CACHE_F40M_S40M:
default:
cmd_exit_qpi = PSRAM_EXIT_QMODE << 8;
ps_cmd.txDataBitLen = 16;
break;
cmd_exit_qpi = PSRAM_EXIT_QMODE;
ps_cmd.txDataBitLen = 8;
if (s_clk_mode == PSRAM_CLK_MODE_DCLK) {
switch (s_psram_mode) {
case PSRAM_CACHE_F80M_S80M:
break;
case PSRAM_CACHE_F80M_S40M:
case PSRAM_CACHE_F40M_S40M:
default:
cmd_exit_qpi = PSRAM_EXIT_QMODE << 8;
ps_cmd.txDataBitLen = 16;
break;
}
}
ps_cmd.txData = &cmd_exit_qpi;
ps_cmd.cmd = 0;
@@ -328,29 +345,34 @@ static void psram_read_id(uint32_t* dev_id)
{
psram_spi_num_t spi_num = PSRAM_SPI_1;
psram_disable_qio_mode(spi_num);
uint32_t addr = (PSRAM_DEVICE_ID << 24) | 0;
uint32_t dummy_bits = 0;
uint32_t dummy_bits = 0 + extra_dummy;
psram_cmd_t ps_cmd;
switch (s_psram_mode) {
case PSRAM_CACHE_F80M_S80M:
dummy_bits = 0 + extra_dummy;
ps_cmd.cmdBitLen = 0;
break;
case PSRAM_CACHE_F80M_S40M:
case PSRAM_CACHE_F40M_S40M:
default:
dummy_bits = 0 + extra_dummy;
ps_cmd.cmdBitLen = 2; //this two bits is used to delay 2 clock cycle
break;
uint32_t addr = 0;
ps_cmd.addrBitLen = 3 * 8;
ps_cmd.cmd = PSRAM_DEVICE_ID;
ps_cmd.cmdBitLen = 8;
if (s_clk_mode == PSRAM_CLK_MODE_DCLK) {
switch (s_psram_mode) {
case PSRAM_CACHE_F80M_S80M:
break;
case PSRAM_CACHE_F80M_S40M:
case PSRAM_CACHE_F40M_S40M:
default:
ps_cmd.cmdBitLen = 2; //this two bits is used to delay 2 clock cycle
ps_cmd.cmd = 0;
addr = (PSRAM_DEVICE_ID << 24) | 0;
ps_cmd.addrBitLen = 4 * 8;
break;
}
}
ps_cmd.cmd = 0;
ps_cmd.addr = &addr;
ps_cmd.addrBitLen = 4 * 8;
ps_cmd.txDataBitLen = 0;
ps_cmd.txData = NULL;
ps_cmd.rxDataBitLen = 4 * 8;
ps_cmd.rxData = dev_id;
ps_cmd.dummyBitLen = dummy_bits;
psram_cmd_config(spi_num, &ps_cmd);
psram_clear_spi_fifo(spi_num);
psram_cmd_recv_start(spi_num, ps_cmd.rxData, ps_cmd.rxDataBitLen / 8, PSRAM_CMD_SPI);
@@ -362,15 +384,18 @@ static esp_err_t IRAM_ATTR psram_enable_qio_mode(psram_spi_num_t spi_num)
{
psram_cmd_t ps_cmd;
uint32_t addr = (PSRAM_ENTER_QMODE << 24) | 0;
switch (s_psram_mode) {
case PSRAM_CACHE_F80M_S80M:
ps_cmd.cmdBitLen = 0;
break;
case PSRAM_CACHE_F80M_S40M:
case PSRAM_CACHE_F40M_S40M:
default:
ps_cmd.cmdBitLen = 2;
break;
ps_cmd.cmdBitLen = 0;
if (s_clk_mode == PSRAM_CLK_MODE_DCLK) {
switch (s_psram_mode) {
case PSRAM_CACHE_F80M_S80M:
break;
case PSRAM_CACHE_F80M_S40M:
case PSRAM_CACHE_F40M_S40M:
default:
ps_cmd.cmdBitLen = 2;
break;
}
}
ps_cmd.cmd = 0;
ps_cmd.addr = &addr;
@@ -473,6 +498,17 @@ static void IRAM_ATTR psram_gpio_config(psram_cache_mode_t mode)
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
}
psram_size_t psram_get_size()
{
if (PSRAM_IS_32MBIT_VER0(s_psram_id)) {
return PSRAM_SIZE_32MBITS;
} else if (PSRAM_IS_64MBIT(s_psram_id)) {
return PSRAM_SIZE_64MBITS;
} else {
return PSRAM_SIZE_MAX;
}
}
//psram gpio init , different working frequency we have different solutions
esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode) //psram init
{
@@ -489,17 +525,6 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad
return ESP_FAIL;
}
/* note: If the third mode(80Mhz+80Mhz) is enabled, VSPI port will be occupied by the system,
Application code should never touch VSPI hardware in this case. We try to stop applications
from doing this using the drivers by claiming the port for ourselves*/
if (mode == PSRAM_CACHE_F80M_S80M) {
periph_module_enable(PERIPH_VSPI_MODULE);
bool r=spicommon_periph_claim(VSPI_HOST);
if (!r) {
return ESP_ERR_INVALID_STATE;
}
}
WRITE_PERI_REG(GPIO_ENABLE_W1TC_REG, BIT(PSRAM_CLK_IO) | BIT(PSRAM_CS_IO)); //DISABLE OUPUT FOR IO16/17
assert(mode < PSRAM_CACHE_MAX && "we don't support any other mode for now.");
s_psram_mode = mode;
@@ -514,21 +539,7 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad
psram_spi_init(PSRAM_SPI_1, mode);
CLEAR_PERI_REG_MASK(SPI_USER_REG(PSRAM_SPI_1), SPI_CS_HOLD);
gpio_matrix_out(PSRAM_CS_IO, SPICS1_OUT_IDX, 0, 0);
gpio_matrix_out(PSRAM_CLK_IO, VSPICLK_OUT_IDX, 0, 0);
//use spi3 clock,but use spi1 data/cs wires
//We get a solid 80MHz clock from SPI3 by setting it up, starting a transaction, waiting until it
//is in progress, then cutting the clock (but not the reset!) to that peripheral.
WRITE_PERI_REG(SPI_ADDR_REG(PSRAM_SPI_3), 32 << 24);
WRITE_PERI_REG(SPI_CLOCK_REG(PSRAM_SPI_3), SPI_CLK_EQU_SYSCLK_M); //SET 80M AND CLEAR OTHERS
SET_PERI_REG_MASK(SPI_CMD_REG(PSRAM_SPI_3), SPI_FLASH_READ_M);
uint32_t spi_status;
while (1) {
spi_status = READ_PERI_REG(SPI_EXT2_REG(PSRAM_SPI_3));
if (spi_status != 0 && spi_status != 1) {
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_2);
break;
}
}
gpio_matrix_out(PSRAM_CLK_IO, SPICLK_OUT_IDX, 0, 0);
break;
case PSRAM_CACHE_F80M_S40M:
case PSRAM_CACHE_F40M_S40M:
@@ -554,13 +565,59 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad
WRITE_PERI_REG(GPIO_ENABLE_W1TS_REG, BIT(PSRAM_CS_IO)| BIT(PSRAM_CLK_IO));
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[PSRAM_CS_IO], PIN_FUNC_GPIO);
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], PIN_FUNC_GPIO);
uint32_t id;
psram_read_id(&id);
if (((id >> PSRAM_MFG_ID_S) & PSRAM_MFG_ID_M) != PSRAM_MFG_ID_V) {
psram_read_id(&s_psram_id);
if (!PSRAM_IS_VALID(s_psram_id)) {
return ESP_FAIL;
}
uint32_t flash_id = g_rom_flashchip.device_id;
if (flash_id == FLASH_ID_GD25LQ32C) {
// Set drive ability for 1.8v flash in 80Mhz.
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA0_U, FUN_DRV_V, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA1_U, FUN_DRV_V, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA2_U, FUN_DRV_V, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA3_U, FUN_DRV_V, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CMD_U, FUN_DRV_V, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV_V, 3, FUN_DRV_S);
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CS_IO], FUN_DRV_V, 3, FUN_DRV_S);
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], FUN_DRV_V, 3, FUN_DRV_S);
}
if (PSRAM_IS_64MBIT(s_psram_id)) {
// For this psram, we don't need any extra clock cycles after cs get back to high level
s_clk_mode = PSRAM_CLK_MODE_NORM;
gpio_matrix_out(PSRAM_INTERNAL_IO_28, SIG_GPIO_OUT_IDX, 0, 0);
gpio_matrix_out(PSRAM_INTERNAL_IO_29, SIG_GPIO_OUT_IDX, 0, 0);
gpio_matrix_out(PSRAM_CLK_IO, SPICLK_OUT_IDX, 0, 0);
} else if (PSRAM_IS_32MBIT_VER0(s_psram_id)) {
s_clk_mode = PSRAM_CLK_MODE_DCLK;
if (mode == PSRAM_CACHE_F80M_S80M) {
/* note: If the third mode(80Mhz+80Mhz) is enabled for 32MBit 1V8 psram, VSPI port will be
occupied by the system.
Application code should never touch VSPI hardware in this case. We try to stop applications
from doing this using the drivers by claiming the port for ourselves */
periph_module_enable(PERIPH_VSPI_MODULE);
bool r=spicommon_periph_claim(VSPI_HOST);
if (!r) {
return ESP_ERR_INVALID_STATE;
}
gpio_matrix_out(PSRAM_CLK_IO, VSPICLK_OUT_IDX, 0, 0);
//use spi3 clock,but use spi1 data/cs wires
//We get a solid 80MHz clock from SPI3 by setting it up, starting a transaction, waiting until it
//is in progress, then cutting the clock (but not the reset!) to that peripheral.
WRITE_PERI_REG(SPI_ADDR_REG(PSRAM_SPI_3), 32 << 24);
WRITE_PERI_REG(SPI_CLOCK_REG(PSRAM_SPI_3), SPI_CLK_EQU_SYSCLK_M); //SET 80M AND CLEAR OTHERS
SET_PERI_REG_MASK(SPI_CMD_REG(PSRAM_SPI_3), SPI_FLASH_READ_M);
uint32_t spi_status;
while (1) {
spi_status = READ_PERI_REG(SPI_EXT2_REG(PSRAM_SPI_3));
if (spi_status != 0 && spi_status != 1) {
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_2);
break;
}
}
}
}
psram_enable_qio_mode(PSRAM_SPI_1);
psram_cache_init(mode, vaddrmode);
return ESP_OK;
}
@@ -579,27 +636,15 @@ static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psra
CLEAR_PERI_REG_MASK(SPI_DATE_REG(0), BIT(31)); //flash 1 div clk,80+40;
CLEAR_PERI_REG_MASK(SPI_DATE_REG(0), BIT(30)); //pre clk div , ONLY IF SPI/SRAM@ DIFFERENT SPEED,JUST FOR SPI0. FLASH DIV 2+SRAM DIV4
WRITE_PERI_REG(SPI_CLOCK_REG(0), SPI_CLK_EQU_SYSCLK_M); //SET 1DIV CLOCK AND RESET OTHER PARAMS
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_RD_SRAM_DUMMY_M); //enable cache read dummy
SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_DUMMY_CYCLELEN_V, PSRAM_FAST_READ_DUMMY + extra_dummy,
SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache : 40m--+1dummy,80m--+2dummy
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_RCMD_M); //enable user mode for cache read command
break;
case PSRAM_CACHE_F80M_S40M:
SET_PERI_REG_MASK(SPI_DATE_REG(0), BIT(31)); //flash 1 div clk
CLEAR_PERI_REG_MASK(SPI_DATE_REG(0), BIT(30)); //pre clk div , ONLY IF SPI/SRAM@ DIFFERENT SPEED,JUST FOR SPI0.
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_RD_SRAM_DUMMY_M); //enable cache read dummy
SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_DUMMY_CYCLELEN_V, PSRAM_FAST_READ_DUMMY + extra_dummy,
SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache : 40m--+1dummy,80m--+2dummy
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_RCMD_M); //enable user mode for cache read command
break;
case PSRAM_CACHE_F40M_S40M:
default:
CLEAR_PERI_REG_MASK(SPI_DATE_REG(0), BIT(31)); //flash 1 div clk
CLEAR_PERI_REG_MASK(SPI_DATE_REG(0), BIT(30)); //pre clk div
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_RD_SRAM_DUMMY_M); //enable cache read dummy
SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_DUMMY_CYCLELEN_V, PSRAM_FAST_READ_DUMMY + extra_dummy,
SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache : 40m--+1dummy,80m--+2dummy
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_RCMD_M); //enable user mode for cache read command
break;
}
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_WCMD_M); // cache write command enable
@@ -607,30 +652,38 @@ static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psra
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_SRAM_QIO_M); //enable qio mode for cache command
CLEAR_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_SRAM_DIO_M); //disable dio mode for cache command
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_RD_SRAM_DUMMY_M); //enable cache read dummy
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_RCMD_M); //enable user mode for cache read command
SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_BITLEN, 7,
SPI_CACHE_SRAM_USR_WR_CMD_BITLEN_S);
SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_VALUE, PSRAM_QUAD_WRITE,
SPI_CACHE_SRAM_USR_WR_CMD_VALUE_S); //0x38
SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_V, 7,
SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_S);
SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_VALUE_V, PSRAM_FAST_READ_QUAD,
SPI_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0x0b
SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_DUMMY_CYCLELEN_V, PSRAM_FAST_READ_QUAD_DUMMY + extra_dummy,
SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache : 40m--+1dummy,80m--+2dummy
//config sram cache r/w command
switch (psram_cache_mode) {
case PSRAM_CACHE_F80M_S80M: //in this mode , no delay is needed
SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_BITLEN, 7,
SPI_CACHE_SRAM_USR_WR_CMD_BITLEN_S);
SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_VALUE, PSRAM_QUAD_WRITE,
SPI_CACHE_SRAM_USR_WR_CMD_VALUE_S); //0x38
SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_V, 7,
SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_S);
SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_VALUE_V, PSRAM_FAST_READ,
SPI_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0x0b
break;
case PSRAM_CACHE_F80M_S40M: //is sram is @40M, need 2 cycles of delay
case PSRAM_CACHE_F40M_S40M:
default:
SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_V, 15,
SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_S); //read command length, 2 bytes(1byte for delay),sending in qio mode in cache
SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_VALUE_V, ((PSRAM_FAST_READ) << 8),
SPI_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0x0b, read command value,(0x00 for delay,0x0b for cmd)
SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_BITLEN, 15,
SPI_CACHE_SRAM_USR_WR_CMD_BITLEN_S); //write command length,2 bytes(1byte for delay,send in qio mode in cache)
SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_VALUE, ((PSRAM_QUAD_WRITE) << 8),
SPI_CACHE_SRAM_USR_WR_CMD_VALUE_S); //0x38, write command value,(0x00 for delay)
if (s_clk_mode == PSRAM_CLK_MODE_DCLK) {
SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_V, 15,
SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_S); //read command length, 2 bytes(1byte for delay),sending in qio mode in cache
SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_VALUE_V, ((PSRAM_FAST_READ_QUAD) << 8),
SPI_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0x0b, read command value,(0x00 for delay,0x0b for cmd)
SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_BITLEN, 15,
SPI_CACHE_SRAM_USR_WR_CMD_BITLEN_S); //write command length,2 bytes(1byte for delay,send in qio mode in cache)
SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_VALUE, ((PSRAM_QUAD_WRITE) << 8),
SPI_CACHE_SRAM_USR_WR_CMD_VALUE_S); //0x38, write command value,(0x00 for delay)
SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_DUMMY_CYCLELEN_V, PSRAM_FAST_READ_QUAD_DUMMY + extra_dummy,
SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache : 40m--+1dummy,80m--+2dummy
}
break;
}
@@ -653,6 +706,11 @@ static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psra
CLEAR_PERI_REG_MASK(SPI_PIN_REG(0), SPI_CS1_DIS_M); //ENABLE SPI0 CS1 TO PSRAM(CS0--FLASH; CS1--SRAM)
if (s_clk_mode == PSRAM_CLK_MODE_NORM) { //different
SET_PERI_REG_MASK(SPI_USER_REG(0), SPI_CS_HOLD);
// Set cs time.
SET_PERI_REG_BITS(SPI_CTRL2_REG(0), SPI_HOLD_TIME_V, 1, SPI_HOLD_TIME_S);
}
}
#endif // CONFIG_SPIRAM_SUPPORT

View File

@@ -26,6 +26,11 @@ typedef enum {
PSRAM_CACHE_MAX,
} psram_cache_mode_t;
typedef enum {
PSRAM_SIZE_32MBITS = 0,
PSRAM_SIZE_64MBITS = 1,
PSRAM_SIZE_MAX,
} psram_size_t;
/*
See the TRM, chapter PID/MPU/MMU, header 'External RAM' for the definitions of these modes.
@@ -34,12 +39,21 @@ Important is that NORMAL works with the app CPU cache disabled, but gives huge c
issues when both app and pro CPU are enabled. LOWHIGH and EVENODD do not have these coherency
issues but cannot be used when the app CPU cache is disabled.
*/
typedef enum {
PSRAM_VADDR_MODE_NORMAL=0, ///< App and pro CPU use their own flash cache for external RAM access
PSRAM_VADDR_MODE_LOWHIGH, ///< App and pro CPU share external RAM caches: pro CPU has low 2M, app CPU has high 2M
PSRAM_VADDR_MODE_EVENODD, ///< App and pro CPU share external RAM caches: pro CPU does even 32yte ranges, app does odd ones.
} psram_vaddr_mode_t;
/**
* @brief get psram size
* @return
* - PSRAM_SIZE_MAX if psram not enabled or not valid
* - PSRAM size
*/
psram_size_t psram_get_size();
/**
* @brief psram cache enable function
*

View File

@@ -147,7 +147,7 @@ esp_err_t esp_efuse_mac_get_default(uint8_t* mac)
esp_err_t system_efuse_read_mac(uint8_t *mac) __attribute__((alias("esp_efuse_mac_get_default")));
esp_err_t esp_efuse_read_mac(uint8_t *mac) __attribute__((alias("esp_efuse_mac_get_default")));
esp_err_t esp_derive_mac(uint8_t* local_mac, const uint8_t* universal_mac)
esp_err_t esp_derive_local_mac(uint8_t* local_mac, const uint8_t* universal_mac)
{
uint8_t idx;
@@ -201,7 +201,7 @@ esp_err_t esp_read_mac(uint8_t* mac, esp_mac_type_t type)
mac[5] += 1;
}
else if (UNIVERSAL_MAC_ADDR_NUM == TWO_UNIVERSAL_MAC_ADDR) {
esp_derive_mac(mac, efuse_mac);
esp_derive_local_mac(mac, efuse_mac);
}
break;
case ESP_MAC_BT:
@@ -220,7 +220,7 @@ esp_err_t esp_read_mac(uint8_t* mac, esp_mac_type_t type)
}
else if (UNIVERSAL_MAC_ADDR_NUM == TWO_UNIVERSAL_MAC_ADDR) {
efuse_mac[5] += 1;
esp_derive_mac(mac, efuse_mac);
esp_derive_local_mac(mac, efuse_mac);
}
break;
default:

View File

@@ -0,0 +1,287 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "esp_types.h"
#include "esp_clk.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/xtensa_timer.h"
#include "soc/cpu.h"
#include "unity.h"
#include "rom/uart.h"
#include "rom/sha.h"
#include "soc/uart_reg.h"
#include "soc/dport_reg.h"
#include "soc/rtc.h"
#include "esp_log.h"
#include "mbedtls/sha256.h"
#include "hwcrypto/sha.h"
#include "hwcrypto/aes.h"
#include "mbedtls/rsa.h"
static const char *TAG = "test";
static volatile bool exit_flag = false;
#define TASK_STACK_SIZE (8*1024)
static void aes_task(void *pvParameters)
{
xSemaphoreHandle *sema = (xSemaphoreHandle *) pvParameters;
ESP_LOGI(TAG, "aes_task is started");
esp_aes_context ctx = {
.key_bytes = 16,
.key = {101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116}
};
const unsigned char input[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
unsigned char output[16];
unsigned char output2[16];
while (exit_flag == false) {
memset(output, 0, sizeof(output));
memset(output, 0, sizeof(output2));
esp_aes_encrypt(&ctx, input, output);
esp_aes_decrypt(&ctx, output, output2);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(input, output2, sizeof(input), "AES must match");
}
xSemaphoreGive(*sema);
vTaskDelete(NULL);
}
static void sha_task(void *pvParameters)
{
xSemaphoreHandle *sema = (xSemaphoreHandle *) pvParameters;
ESP_LOGI(TAG, "sha_task is started");
const char *input = "Space!#$%&()*+,-.0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz~DEL0123456789";
unsigned char output[64];
unsigned char output_origin[64];
esp_sha(SHA2_512, (const unsigned char *)input, sizeof(input), output);
memcpy(output_origin, output, sizeof(output));
while (exit_flag == false) {
memset(output, 0, sizeof(output));
esp_sha(SHA2_512, (const unsigned char *)input, sizeof(input), output);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(output, output_origin, sizeof(output), "SHA256 must match");
}
xSemaphoreGive(*sema);
vTaskDelete(NULL);
}
static void mbedtls_sha256_task(void *pvParameters)
{
xSemaphoreHandle *sema = (xSemaphoreHandle *) pvParameters;
ESP_LOGI(TAG, "mbedtls_sha256_task is started");
const char *input = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz~DEL0123456789Space!#$%&()*+,-.0123456789:;<=>?";
mbedtls_sha256_context sha256_ctx;
unsigned char output[32];
unsigned char output_origin[32];
mbedtls_sha256_init(&sha256_ctx);
memset(output, 0, sizeof(output));
mbedtls_sha256_starts(&sha256_ctx, false);
for (int i = 0; i < 3; ++i) {
mbedtls_sha256_update(&sha256_ctx, (unsigned char *)input, 100);
}
mbedtls_sha256_finish(&sha256_ctx, output);
memcpy(output_origin, output, sizeof(output));
while (exit_flag == false) {
mbedtls_sha256_init(&sha256_ctx);
memset(output, 0, sizeof(output));
mbedtls_sha256_starts(&sha256_ctx, false);
for (int i = 0; i < 3; ++i) {
mbedtls_sha256_update(&sha256_ctx, (unsigned char *)input, 100);
}
mbedtls_sha256_finish(&sha256_ctx, output);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(output, output_origin, sizeof(output), "MBEDTLS SHA256 must match");
}
xSemaphoreGive(*sema);
vTaskDelete(NULL);
}
TEST_CASE("Test shared using AES SHA512 SHA256", "[hw_crypto]")
{
#ifndef CONFIG_FREERTOS_UNICORE
const int max_tasks = 6;
#else
const int max_tasks = 3;
#endif
xSemaphoreHandle exit_sema[max_tasks];
for (int i = 0; i < max_tasks; ++i) {
exit_sema[i] = xSemaphoreCreateBinary();
}
exit_flag = false;
#ifndef CONFIG_FREERTOS_UNICORE
xTaskCreatePinnedToCore(&aes_task, "aes_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL, 1);
xTaskCreatePinnedToCore(&aes_task, "aes_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL, 0);
xTaskCreatePinnedToCore(&sha_task, "sha_task", TASK_STACK_SIZE, &exit_sema[2], UNITY_FREERTOS_PRIORITY - 1, NULL, 1);
xTaskCreatePinnedToCore(&sha_task, "sha_task", TASK_STACK_SIZE, &exit_sema[3], UNITY_FREERTOS_PRIORITY - 1, NULL, 0);
xTaskCreatePinnedToCore(&mbedtls_sha256_task, "mbedtls_sha256_task", TASK_STACK_SIZE, &exit_sema[4], UNITY_FREERTOS_PRIORITY - 1, NULL, 1);
xTaskCreatePinnedToCore(&mbedtls_sha256_task, "mbedtls_sha256_task", TASK_STACK_SIZE, &exit_sema[5], UNITY_FREERTOS_PRIORITY - 1, NULL, 0);
#else
xTaskCreate(&aes_task, "aes_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL);
xTaskCreate(&sha_task, "sha_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL);
xTaskCreate(&mbedtls_sha256_task, "mbedtls_sha256_task", TASK_STACK_SIZE, &exit_sema[2], UNITY_FREERTOS_PRIORITY - 1, NULL);
#endif
ESP_LOGI(TAG, "Waiting for 10s ...");
vTaskDelay(10000 / portTICK_PERIOD_MS);
// set exit flag to let thread exit
exit_flag = true;
for (int i = 0; i < max_tasks; ++i) {
if (!xSemaphoreTake(exit_sema[i], 2000/portTICK_PERIOD_MS)) {
TEST_FAIL_MESSAGE("exit_sema not released by test task");
}
vSemaphoreDelete(exit_sema[i]);
}
}
static void rsa_task(void *pvParameters)
{
xSemaphoreHandle *sema = (xSemaphoreHandle *) pvParameters;
ESP_LOGI(TAG, "rsa_task is started");
while (exit_flag == false) {
mbedtls_rsa_self_test(0);
}
xSemaphoreGive(*sema);
vTaskDelete(NULL);
}
TEST_CASE("Test shared using AES RSA", "[hw_crypto]")
{
#ifndef CONFIG_FREERTOS_UNICORE
const int max_tasks = 2;
#else
const int max_tasks = 2;
#endif
xSemaphoreHandle exit_sema[max_tasks];
for (int i = 0; i < max_tasks; ++i) {
exit_sema[i] = xSemaphoreCreateBinary();
}
exit_flag = false;
#ifndef CONFIG_FREERTOS_UNICORE
xTaskCreatePinnedToCore(&aes_task, "aes_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL, 1);
xTaskCreatePinnedToCore(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL, 0);
#else
xTaskCreate(&aes_task, "aes_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL);
xTaskCreate(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL);
#endif
ESP_LOGI(TAG, "Waiting for 10s ...");
vTaskDelay(10000 / portTICK_PERIOD_MS);
// set exit flag to let thread exit
exit_flag = true;
for (int i = 0; i < max_tasks; ++i) {
if (!xSemaphoreTake(exit_sema[i], 2000/portTICK_PERIOD_MS)) {
TEST_FAIL_MESSAGE("exit_sema not released by test task");
}
vSemaphoreDelete(exit_sema[i]);
}
}
TEST_CASE("Test shared using SHA512 RSA", "[hw_crypto]")
{
#ifndef CONFIG_FREERTOS_UNICORE
const int max_tasks = 2;
#else
const int max_tasks = 2;
#endif
xSemaphoreHandle exit_sema[max_tasks];
for (int i = 0; i < max_tasks; ++i) {
exit_sema[i] = xSemaphoreCreateBinary();
}
exit_flag = false;
#ifndef CONFIG_FREERTOS_UNICORE
xTaskCreatePinnedToCore(&sha_task, "sha_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 2, NULL, 1);
xTaskCreatePinnedToCore(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL, 0);
#else
xTaskCreate(&sha_task, "sha_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL);
xTaskCreate(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL);
#endif
ESP_LOGI(TAG, "Waiting for 10s ...");
vTaskDelay(10000 / portTICK_PERIOD_MS);
// set exit flag to let thread exit
exit_flag = true;
for (int i = 0; i < max_tasks; ++i) {
if (!xSemaphoreTake(exit_sema[i], 2000/portTICK_PERIOD_MS)) {
TEST_FAIL_MESSAGE("exit_sema not released by test task");
}
vSemaphoreDelete(exit_sema[i]);
}
}
TEST_CASE("Test shared using SHA256 RSA", "[hw_crypto]")
{
#ifndef CONFIG_FREERTOS_UNICORE
const int max_tasks = 2;
#else
const int max_tasks = 2;
#endif
xSemaphoreHandle exit_sema[max_tasks];
for (int i = 0; i < max_tasks; ++i) {
exit_sema[i] = xSemaphoreCreateBinary();
}
exit_flag = false;
#ifndef CONFIG_FREERTOS_UNICORE
xTaskCreatePinnedToCore(&mbedtls_sha256_task, "mbedtls_sha256_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL, 1);
xTaskCreatePinnedToCore(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL, 0);
#else
xTaskCreate(&mbedtls_sha256_task, "mbedtls_sha256_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL);
xTaskCreate(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL);
#endif
ESP_LOGI(TAG, "Waiting for 10s ...");
vTaskDelay(10000 / portTICK_PERIOD_MS);
// set exit flag to let thread exit
exit_flag = true;
for (int i = 0; i < max_tasks; ++i) {
if (!xSemaphoreTake(exit_sema[i], 2000/portTICK_PERIOD_MS)) {
TEST_FAIL_MESSAGE("exit_sema not released by test task");
}
vSemaphoreDelete(exit_sema[i]);
}
}
TEST_CASE("Test shared using AES SHA RSA", "[hw_crypto]")
{
#ifndef CONFIG_FREERTOS_UNICORE
const int max_tasks = 3;
#else
const int max_tasks = 3;
#endif
xSemaphoreHandle exit_sema[max_tasks];
for (int i = 0; i < max_tasks; ++i) {
exit_sema[i] = xSemaphoreCreateBinary();
}
exit_flag = false;
#ifndef CONFIG_FREERTOS_UNICORE
xTaskCreatePinnedToCore(&aes_task, "aes_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL, 0);
xTaskCreatePinnedToCore(&sha_task, "sha_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL, 0);
xTaskCreatePinnedToCore(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[2], UNITY_FREERTOS_PRIORITY - 1, NULL, 1);
#else
xTaskCreate(&aes_task, "aes_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL);
xTaskCreate(&sha_task, "sha_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL);
xTaskCreate(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[2], UNITY_FREERTOS_PRIORITY - 1, NULL);
#endif
ESP_LOGI(TAG, "Waiting for 10s ...");
vTaskDelay(10000 / portTICK_PERIOD_MS);
// set exit flag to let thread exit
exit_flag = true;
for (int i = 0; i < max_tasks; ++i) {
if (!xSemaphoreTake(exit_sema[i], 2000/portTICK_PERIOD_MS)) {
TEST_FAIL_MESSAGE("exit_sema not released by test task");
}
vSemaphoreDelete(exit_sema[i]);
}
}

View File

@@ -2,8 +2,10 @@
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <sys/param.h>
#include "unity.h"
#include "esp_timer.h"
#include "../esp_timer_impl.h"
#include "esp_heap_caps.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
@@ -14,6 +16,20 @@
#define WITH_PROFILING 1
#endif
extern uint32_t esp_timer_impl_get_overflow_val();
extern void esp_timer_impl_set_overflow_val(uint32_t overflow_val);
static uint32_t s_old_overflow_val;
static void setup_overflow()
{
s_old_overflow_val = esp_timer_impl_get_overflow_val();
esp_timer_impl_set_overflow_val(0x7fffff); /* overflow every ~0.1 sec */}
static void teardown_overflow()
{
esp_timer_impl_set_overflow_val(s_old_overflow_val);
}
TEST_CASE("esp_timer orders timers correctly", "[esp_timer]")
{
@@ -26,6 +42,7 @@ TEST_CASE("esp_timer orders timers correctly", "[esp_timer]")
const size_t num_timers = sizeof(timeouts)/sizeof(timeouts[0]);
esp_timer_handle_t handles[num_timers];
char* names[num_timers];
setup_overflow();
for (size_t i = 0; i < num_timers; ++i) {
asprintf(&names[i], "timer%d", i);
esp_timer_create_args_t args = {
@@ -35,6 +52,7 @@ TEST_CASE("esp_timer orders timers correctly", "[esp_timer]")
TEST_ESP_OK(esp_timer_create(&args, &handles[i]));
TEST_ESP_OK(esp_timer_start_once(handles[i], timeouts[i] * 100));
}
teardown_overflow();
char* stream_str[1024];
FILE* stream = fmemopen(stream_str, sizeof(stream_str), "r+");
TEST_ESP_OK(esp_timer_dump(stream));
@@ -67,6 +85,42 @@ TEST_CASE("esp_timer orders timers correctly", "[esp_timer]")
fclose(stream);
}
TEST_CASE("esp_timer_impl_set_alarm stress test", "[esp_timer]")
{
const int test_time_sec = 10;
void set_alarm_task(void* arg)
{
SemaphoreHandle_t done = (SemaphoreHandle_t) arg;
uint64_t start = esp_timer_impl_get_time();
uint64_t now = start;
int count = 0;
const int delays[] = {50, 5000, 10000000};
const int delays_count = sizeof(delays)/sizeof(delays[0]);
while (now - start < test_time_sec * 1000000) {
now = esp_timer_impl_get_time();
esp_timer_impl_set_alarm(now + delays[count % delays_count]);
++count;
}
xSemaphoreGive(done);
vTaskDelete(NULL);
}
SemaphoreHandle_t done = xSemaphoreCreateCounting(portNUM_PROCESSORS, 0);
setup_overflow();
xTaskCreatePinnedToCore(&set_alarm_task, "set_alarm_0", 4096, done, UNITY_FREERTOS_PRIORITY, NULL, 0);
#if portNUM_PROCESSORS == 2
xTaskCreatePinnedToCore(&set_alarm_task, "set_alarm_1", 4096, done, UNITY_FREERTOS_PRIORITY, NULL, 1);
#endif
TEST_ASSERT(xSemaphoreTake(done, test_time_sec * 2 * 1000 / portTICK_PERIOD_MS));
#if portNUM_PROCESSORS == 2
TEST_ASSERT(xSemaphoreTake(done, test_time_sec * 2 * 1000 / portTICK_PERIOD_MS));
#endif
teardown_overflow();
vSemaphoreDelete(done);
}
TEST_CASE("esp_timer produces correct delay", "[esp_timer]")
{
@@ -89,6 +143,7 @@ TEST_CASE("esp_timer produces correct delay", "[esp_timer]")
const size_t delays_count = sizeof(delays_ms)/sizeof(delays_ms[0]);
ref_clock_init();
setup_overflow();
for (size_t i = 0; i < delays_count; ++i) {
t_end = 0;
int64_t t_start = ref_clock_get();
@@ -102,6 +157,7 @@ TEST_CASE("esp_timer produces correct delay", "[esp_timer]")
TEST_ASSERT_INT32_WITHIN(portTICK_PERIOD_MS, delays_ms[i], ms_diff);
}
teardown_overflow();
ref_clock_deinit();
TEST_ESP_OK( esp_timer_dump(stdout) );
@@ -149,6 +205,7 @@ TEST_CASE("periodic esp_timer produces correct delays", "[esp_timer]")
};
TEST_ESP_OK(esp_timer_create(&create_args, &timer1));
ref_clock_init();
setup_overflow();
args.timer = timer1;
args.t_start = ref_clock_get();
args.done = xSemaphoreCreateBinary();
@@ -160,6 +217,7 @@ TEST_CASE("periodic esp_timer produces correct delays", "[esp_timer]")
for (size_t i = 0; i < NUM_INTERVALS; ++i) {
TEST_ASSERT_INT32_WITHIN(portTICK_PERIOD_MS, (i + 1) * delay_ms, args.intervals[i]);
}
teardown_overflow();
ref_clock_deinit();
TEST_ESP_OK( esp_timer_dump(stdout) );
@@ -316,6 +374,7 @@ TEST_CASE("esp_timer for very short intervals", "[esp_timer]")
esp_timer_handle_t timer1, timer2;
ESP_ERROR_CHECK( esp_timer_create(&timer_args, &timer1) );
ESP_ERROR_CHECK( esp_timer_create(&timer_args, &timer2) );
setup_overflow();
const int timeout_ms = 10;
for (int timeout_delta_us = -150; timeout_delta_us < 150; timeout_delta_us++) {
printf("delta=%d", timeout_delta_us);
@@ -328,6 +387,7 @@ TEST_CASE("esp_timer for very short intervals", "[esp_timer]")
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_timer_stop(timer2));
}
teardown_overflow();
vSemaphoreDelete(semaphore);
}
@@ -344,40 +404,75 @@ TEST_CASE("esp_timer_get_time call takes less than 1us", "[esp_timer]")
TEST_PERFORMANCE_LESS_THAN(ESP_TIMER_GET_TIME_PER_CALL, "%dns", ns_per_call);
}
/* This test runs for about 10 minutes and is disabled in CI.
* Such run time is needed to have FRC2 timer overflow a few times.
*/
TEST_CASE("esp_timer_get_time returns monotonic values", "[esp_timer][ignore]")
TEST_CASE("esp_timer_get_time returns monotonic values", "[esp_timer]")
{
void timer_test_task(void* arg) {
int64_t delta = esp_timer_get_time() - ref_clock_get();
typedef struct {
SemaphoreHandle_t done;
bool pass;
int test_cnt;
int error_cnt;
int64_t total_sq_error;
int64_t max_error;
} test_state_t;
const int iter_count = 1000000000;
for (int i = 0; i < iter_count; ++i) {
int64_t now = esp_timer_get_time();
int64_t ref_now = ref_clock_get();
int64_t diff = now - (ref_now + delta);
void timer_test_task(void* arg) {
test_state_t* state = (test_state_t*) arg;
state->pass = true;
int64_t start_time = ref_clock_get();
int64_t delta = esp_timer_get_time() - start_time;
int64_t now = start_time;
int error_repeat_cnt = 0;
while (now - start_time < 10000000) { /* 10 seconds */
int64_t hs_now = esp_timer_get_time();
now = ref_clock_get();
int64_t diff = hs_now - (now + delta);
/* Allow some difference due to rtos tick interrupting task between
* getting 'now' and 'ref_now'.
*/
TEST_ASSERT_INT32_WITHIN(100, 0, (int) diff);
if (abs(diff) > 100) {
error_repeat_cnt++;
state->error_cnt++;
} else {
error_repeat_cnt = 0;
}
if (error_repeat_cnt > 2) {
printf("diff=%lld\n", diff);
state->pass = false;
}
state->max_error = MAX(state->max_error, abs(diff));
state->test_cnt++;
state->total_sq_error += diff * diff;
}
xSemaphoreGive((SemaphoreHandle_t) arg);
xSemaphoreGive(state->done);
vTaskDelete(NULL);
}
ref_clock_init();
SemaphoreHandle_t done_1 = xSemaphoreCreateBinary();
SemaphoreHandle_t done_2 = xSemaphoreCreateBinary();
setup_overflow();
xTaskCreatePinnedToCore(&timer_test_task, "t1", 4096, (void*) done_1, 6, NULL, 0);
xTaskCreatePinnedToCore(&timer_test_task, "t2", 4096, (void*) done_2, 6, NULL, 1);
test_state_t states[portNUM_PROCESSORS] = {0};
SemaphoreHandle_t done = xSemaphoreCreateCounting(portNUM_PROCESSORS, 0);
for (int i = 0; i < portNUM_PROCESSORS; ++i) {
states[i].done = done;
xTaskCreatePinnedToCore(&timer_test_task, "test", 4096, &states[i], 6, NULL, i);
}
TEST_ASSERT_TRUE( xSemaphoreTake(done_1, portMAX_DELAY) );
TEST_ASSERT_TRUE( xSemaphoreTake(done_2, portMAX_DELAY) );
vSemaphoreDelete(done_1);
vSemaphoreDelete(done_2);
for (int i = 0; i < portNUM_PROCESSORS; ++i) {
TEST_ASSERT_TRUE( xSemaphoreTake(done, portMAX_DELAY) );
printf("CPU%d: %s test_cnt=%d error_cnt=%d std_error=%d |max_error|=%d\n",
i, states[i].pass ? "PASS" : "FAIL",
states[i].test_cnt, states[i].error_cnt,
(int) sqrt(states[i].total_sq_error / states[i].test_cnt), (int) states[i].max_error);
}
vSemaphoreDelete(done);
teardown_overflow();
ref_clock_deinit();
for (int i = 0; i < portNUM_PROCESSORS; ++i) {
TEST_ASSERT(states[i].pass);
}
}
TEST_CASE("Can dump esp_timer stats", "[esp_timer]")

View File

@@ -2458,8 +2458,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
{
BaseType_t xReturn;
//ToDo: figure out locking
// taskENTER_CRITICAL(&pxQueue->mux);
taskENTER_CRITICAL(&(((Queue_t * )xQueueOrSemaphore)->mux));
{
if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL )
{
@@ -2478,7 +2477,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
xReturn = pdPASS;
}
}
// taskEXIT_CRITICAL(&pxQueue->mux);
taskEXIT_CRITICAL(&(((Queue_t * )xQueueOrSemaphore)->mux));
return xReturn;
}
@@ -2507,12 +2506,12 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
}
else
{
// taskENTER_CRITICAL(&pxQueue->mux);
taskENTER_CRITICAL(&(pxQueueOrSemaphore->mux));
{
/* The queue is no longer contained in the set. */
pxQueueOrSemaphore->pxQueueSetContainer = NULL;
}
// taskEXIT_CRITICAL(&pxQueue->mux);
taskEXIT_CRITICAL(&(pxQueueOrSemaphore->mux));
xReturn = pdPASS;
}
@@ -2555,9 +2554,15 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
Queue_t *pxQueueSetContainer = pxQueue->pxQueueSetContainer;
BaseType_t xReturn = pdFALSE;
/* This function must be called form a critical section. */
/*
* This function is called with a Queue's / Semaphore's spinlock already
* acquired. Acquiring the Queue set's spinlock is still necessary.
*/
configASSERT( pxQueueSetContainer );
//Acquire the Queue set's spinlock
portENTER_CRITICAL(&(pxQueueSetContainer->mux));
configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength );
if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength )
@@ -2588,6 +2593,9 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
mtCOVERAGE_TEST_MARKER();
}
//Release the Queue set's spinlock
portEXIT_CRITICAL(&(pxQueueSetContainer->mux));
return xReturn;
}

View File

@@ -0,0 +1,137 @@
#include <stdio.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "unity.h"
/*
* Basic queue set tests. Multiple queues are added to a queue set then each
* queue is filled in a sequential order. The members returned from the queue
* set must adhered to the order in which the queues were filled.
*/
#define NO_OF_QUEUES 5
#define QUEUE_LEN 4
#define ITEM_SIZE sizeof(uint32_t)
static QueueHandle_t handles[NO_OF_QUEUES];
static QueueSetHandle_t set_handle;
TEST_CASE("Test Queue sets", "[freertos]")
{
//Create queue set, queues, and add queues to queue set
set_handle = xQueueCreateSet(NO_OF_QUEUES * QUEUE_LEN);
for (int i = 0; i < NO_OF_QUEUES; i++) {
handles[i] = xQueueCreate(QUEUE_LEN, ITEM_SIZE);
TEST_ASSERT_MESSAGE(handles[i] != NULL, "Failed to create queue");
TEST_ASSERT_MESSAGE(xQueueAddToSet(handles[i], set_handle) == pdPASS, "Failed to add to queue set");
}
//Fill queue set via filling each queue
for (int i = 0; i < NO_OF_QUEUES; i++) {
for (int j = 0; j < QUEUE_LEN; j++) {
uint32_t item_num = (i * QUEUE_LEN) + j;
TEST_ASSERT_MESSAGE(xQueueSendToBack(handles[i], &item_num, portMAX_DELAY) == pdTRUE, "Failed to send to queue");
}
}
//Check queue set is notified in correct order
for (int i = 0; i < NO_OF_QUEUES; i++) {
for (int j = 0; j < QUEUE_LEN; j++) {
QueueSetMemberHandle_t member = xQueueSelectFromSet(set_handle, portMAX_DELAY);
TEST_ASSERT_EQUAL_MESSAGE(handles[i], member, "Incorrect queue set member returned");
uint32_t item;
xQueueReceive((QueueHandle_t)member, &item, 0);
TEST_ASSERT_EQUAL_MESSAGE(((i * QUEUE_LEN) + j), item, "Incorrect item value");
}
}
//Remove queues from queue set and delete queues
for (int i = 0; i < NO_OF_QUEUES; i++) {
TEST_ASSERT_MESSAGE(xQueueRemoveFromSet(handles[i], set_handle), "Failed to remove from queue set");
vQueueDelete(handles[i]);
}
vQueueDelete(set_handle);
}
/*
* Queue set thread safety test. Test the SMP thread safety by adding two queues
* to a queue set and have a task on each core send to the queues simultaneously.
* Check returned queue set members are valid.
*/
#ifndef CONFIG_FREERTOS_UNICORE
static volatile bool sync_flags[portNUM_PROCESSORS];
static SemaphoreHandle_t sync_sem;
static void send_task(void *arg)
{
QueueHandle_t queue = (QueueHandle_t)arg;
//Wait until task on the other core starts running
xSemaphoreTake(sync_sem, portMAX_DELAY);
sync_flags[xPortGetCoreID()] = true;
while (!sync_flags[!xPortGetCoreID()]) {
;
}
//Fill queue
for (int i = 0; i < QUEUE_LEN; i++) {
uint32_t item = i;
xQueueSendToBack(queue, &item, portMAX_DELAY);
}
xSemaphoreGive(sync_sem);
vTaskDelete(NULL);
}
TEST_CASE("Test Queue sets thread safety", "[freertos]")
{
//Create queue set, queues, and a send task on each core
sync_sem = xSemaphoreCreateCounting(portNUM_PROCESSORS, 0);
QueueHandle_t queue_handles[portNUM_PROCESSORS];
QueueSetHandle_t queueset_handle = xQueueCreateSet(portNUM_PROCESSORS * QUEUE_LEN);
for (int i = 0; i < portNUM_PROCESSORS; i++) {
sync_flags[i] = false;
queue_handles[i] = xQueueCreate(QUEUE_LEN, ITEM_SIZE);
TEST_ASSERT_MESSAGE(xQueueAddToSet(queue_handles[i], queueset_handle) == pdPASS, "Failed to add to queue set");
xTaskCreatePinnedToCore(send_task, "send", 2048, (void *)queue_handles[i], 10, NULL, i);
}
//Start both send tasks
portDISABLE_INTERRUPTS();
for (int i = 0; i < portNUM_PROCESSORS; i++) {
xSemaphoreGive(sync_sem);
}
portENABLE_INTERRUPTS();
vTaskDelay(2);
//Check returned queue set members are valid
uint32_t expect_0 = 0;
uint32_t expect_1 = 0;
for (int i = 0; i < (portNUM_PROCESSORS * QUEUE_LEN); i++) {
QueueSetMemberHandle_t member = xQueueSelectFromSet(queueset_handle, portMAX_DELAY);
uint32_t item;
if (member == queue_handles[0]) {
xQueueReceive((QueueHandle_t)member, &item, 0);
TEST_ASSERT_EQUAL_MESSAGE(expect_0, item, "Incorrect item value");
expect_0++;
} else if (member == queue_handles[1]) {
xQueueReceive((QueueHandle_t)member, &item, 0);
TEST_ASSERT_EQUAL_MESSAGE(expect_1, item, "Incorrect item value");
expect_1++;
} else {
TEST_ASSERT_MESSAGE(0, "Incorrect queue set member returned");
}
}
for (int i = 0; i < portNUM_PROCESSORS; i++) {
xSemaphoreTake(sync_sem, portMAX_DELAY);
}
for (int i = 0; i < portNUM_PROCESSORS; i++) {
xQueueRemoveFromSet(queueset_handle, handles[i]);
vQueueDelete(queue_handles[i]);
}
vQueueDelete(queueset_handle);
}
#endif

View File

@@ -798,7 +798,7 @@ test cases:
- ['R PC_COM C +NIC_START:OK']
- - "SSC SSC1 bleadv -D -z stop"
- ["R SSC1 C +BLEADV"]
- - LOOP 2 2 "['0x20-0x40','0xA0-0xB0']" "['NPDU','PDU']"
- - LOOP 2 2 "['0x20-0x40','0xA0-0xB0']" "['PDU','PDU']"
- [""]
- - "SSC SSC1 bleadv -D -z start -t 2 -i {%s}"
- ["R SSC1 C +BLEADV:OK"]
@@ -842,7 +842,7 @@ test cases:
- ['R PC_COM C +NIC_START:OK']
- - "SSC SSC1 bleadv -D -z stop"
- ["R SSC1 C +BLEADV"]
- - LOOP 2 2 "['0x20-0x40','0xA0-0xB0']" "['NPDU','PDU']"
- - LOOP 2 2 "['0x20-0x40','0xA0-0xB0']" "['PDU','PDU']"
- [""]
- - "SSC SSC1 bleadv -D -z start -t 3 -i {%s}"
- ["R SSC1 C +BLEADV:OK"]
@@ -890,7 +890,7 @@ test cases:
- ["R SSC1 C +BLEADV:OK"]
- - "SSC SSC2 bleadv -D -z stop"
- ["R SSC2 C +BLEADV:OK"]
- - "SSC SSC2 blescan -L -c 0 -s 0"
- - "SSC SSC2 blescan -L -c 0 -s 0 -d 1"
- ["R SSC2 C +BLESCAN:SetScanParam,OK"]
- - "SSC SSC2 blescan -D -z start -t 3 -e 2"
- - 'P SSC2 RE "\+BTSCANEXT:%%s,man,0x1011121314151617181910111213141516171819"%%(<dut1_bt_mac>)'
@@ -944,7 +944,7 @@ test cases:
- ["R SSC2 C +BLEADV:OK"]
- - LOOP 4 2 "[0,1,2,3]"
- ['']
- - "SSC SSC2 blescan -L -c 0 -s 1 -o {%d}"
- - "SSC SSC2 blescan -L -c 0 -s 1 -o {%d} -d 1"
- ["R SSC2 C +BLESCAN:SetScanParam,OK"]
- - "SSC SSC2 blescan -D -z start -t 1"
- ['R SSC2 P <dut1_bt_mac> C Complete']
@@ -1075,7 +1075,7 @@ test cases:
- ["R SSC1 C +BLEADV:OK"]
- - "SSC SSC1 bleadv -D -z start"
- ["R SSC1 C +BLEADV:OK"]
- - "SSC SSC2 blescan -L -c 0"
- - "SSC SSC2 blescan -L -c 0 -d 1"
- ["R SSC2 C +BLESCAN:SetScanParam,OK"]
- - "SSC SSC2 blescan -D -z start -t 1"
- ["R SSC2 P <dut1_bt_mac> C Complete"]
@@ -1538,6 +1538,8 @@ test cases:
- ""
- - "SSC SSC1 bleadv -D -z stop"
- ["R SSC1 C +BLEADV"]
- - "SSC SSC2 blescan -L -c 0 -d 1"
- ['R SSC2 C +BLESCAN']
- - "SSC SSC1 bleadv -R -t 1 -r 0x020AEB06FF1112131415051220004000021901020106"
- ["R SSC1 C +BLEADV:OK"]
- - "SSC SSC1 bleadv -D -z start"
@@ -1584,6 +1586,8 @@ test cases:
- ["R SSC1 C +BLEADV"]
- - "SSC SSC2 bleadv -D -z stop"
- ["R SSC2 C +BLEADV:OK"]
- - "SSC SSC2 blescan -L -c 0 -d 1"
- ['R SSC2 C +BLESCAN']
- - LOOP 4 3 "['0302ABCD','0303ABCD','0504ABCDABCD','0505ABCDABCD',]" "['insrv16,0xABCD','srv16,0xABCD','insrv32,0xABCDABCD','srv32,0xABCDABCD']"
- - "SSC SSC1 bleadv -R -t 1 -r 0x{%s}"
- ["R SSC1 C +BLEADV:OK"]
@@ -1633,6 +1637,8 @@ test cases:
- ["R SSC1 C +BLEADV"]
- - "SSC SSC2 bleadv -D -z stop"
- ["R SSC2 C +BLEADV:OK"]
- - "SSC SSC2 blescan -L -c 0 -d 1"
- ['R SSC2 C +BLESCAN']
- - LOOP 3 3 "['0416ABCDEF','0620ABCDABCDEF','1221ABCDABCDABCDABCDABCDABCDABCDABCDEF',]" "['srvdata,0xABCDEF','srvdata32,0xABCDABCDEF','srvdata128,0xABCDABCDABCDABCDABCDABCDABCDABCDEF']"
- - "SSC SSC1 bleadv -R -t 1 -r 0x{%s}"
- ["R SSC1 C +BLEADV:OK"]
@@ -1671,6 +1677,8 @@ test cases:
- ""
- - "SSC SSC1 bleadv -D -z stop"
- ["R SSC1 C +BLEADV"]
- - "SSC SSC2 blescan -L -c 0 -d 1"
- ['R SSC2 C +BLESCAN']
- - "SSC SSC1 bleadv -R -t 1 -r 0x15FF1011121314151617181910111213141516171819"
- ["R SSC1 C +BLEADV:OK"]
- - "SSC SSC1 bleadv -R -t 2 -r 0x020AEB051220004000021901020106"

View File

@@ -83,7 +83,7 @@ config LWIP_STATS
config LWIP_ETHARP_TRUST_IP_MAC
bool "Enable LWIP ARP trust"
default y
default n
help
Enabling this option allows ARP table to be updated.
@@ -96,6 +96,34 @@ config LWIP_ETHARP_TRUST_IP_MAC
The peer *is* in the ARP table if it requested our address before.
Also notice that this slows down input processing of every IP packet!
There are two known issues in real application if this feature is enabled:
- The LAN peer may have bug to update the ARP table after the ARP entry is aged out.
If the ARP entry on the LAN peer is aged out but failed to be updated, all IP packets
sent from LWIP to the LAN peer will be dropped by LAN peer.
- The LAN peer may not be trustful, the LAN peer may send IP packets to LWIP with
two different MACs, but the same IP address. If this happens, the LWIP has problem
to receive IP packets from LAN peer.
So the recommendation is to disable this option.
Here the LAN peer means the other side to which the ESP station or soft-AP is connected.
config ESP_GRATUITOUS_ARP
bool "Send gratuitous ARP periodically"
default y
help
Enable this option allows to send gratuitous ARP periodically.
This option solve the compatibility issues.If the ARP table of the AP is old, and the AP
doesn't send ARP request to update it's ARP table, this will lead to the STA sending IP packet fail.
Thus we send gratuitous ARP periodically to let AP update it's ARP table.
config GARP_TMR_INTERVAL
int "GARP timer interval(seconds)"
default 60
depends on ESP_GRATUITOUS_ARP
help
Set the timer interval for gratuitous ARP. The default value is 60s
config TCPIP_RECVMBOX_SIZE
int "TCPIP task receive mail box size"
default 32
@@ -308,6 +336,16 @@ config TCP_QUEUE_OOSEQ
Disable this option to save some RAM during TCP sessions, at the expense
of increased retransmissions if segments arrive out of order.
config ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES
bool "Keep TCP connections when IP changed"
default n
help
This option is enabled when the following scenario happen:
network dropped and reconnected, IP changes is like: 192.168.0.2->0.0.0.0->192.168.0.2
Disable this option to keep consistent with the original LWIP code behavior.
choice TCP_OVERSIZE
prompt "Pre-allocate transmit PBUF size"
default TCP_OVERSIZE_MSS

View File

@@ -407,9 +407,9 @@ netconn_accept(struct netconn *conn, struct netconn **new_conn)
#if TCP_LISTEN_BACKLOG
/* Let the stack know that we have accepted the connection. */
API_MSG_VAR_ALLOC_DONTFAIL(msg);
API_MSG_VAR_REF(msg).msg.conn = conn;
/* don't care for the return value of lwip_netconn_do_recv */
TCPIP_APIMSG_NOERR(&API_MSG_VAR_REF(msg), lwip_netconn_do_recv);
API_MSG_VAR_REF(msg).msg.conn = newconn;
/* don't care for the return value of lwip_netconn_do_accepted */
TCPIP_APIMSG_NOERR(&API_MSG_VAR_REF(msg), lwip_netconn_do_accepted);
API_MSG_VAR_FREE(msg);
#endif /* TCP_LISTEN_BACKLOG */

View File

@@ -536,6 +536,9 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
to the application thread */
newconn->last_err = err;
/* handle backlog counter */
tcp_backlog_delayed(newpcb);
if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) {
ESP_STATS_DROP_INC(esp.acceptmbox_post_fail);
/* When returning != ERR_OK, the pcb is aborted in tcp_process(),
@@ -707,6 +710,14 @@ netconn_alloc(enum netconn_type t, netconn_callback callback)
}
#endif
#if ESP_THREAD_SAFE
conn->recvmbox_ref = conn->recvmbox;
sys_mbox_set_owner(&conn->recvmbox, conn);
#if LWIP_TCP
sys_mbox_set_invalid(&conn->acceptmbox_ref);
#endif
#endif
#if LWIP_TCP
sys_mbox_set_invalid(&conn->acceptmbox);
#endif
@@ -757,6 +768,18 @@ netconn_free(struct netconn *conn)
!sys_mbox_valid(&conn->acceptmbox));
#endif /* LWIP_TCP */
#if ESP_THREAD_SAFE
if (conn->recvmbox_ref) {
sys_mbox_free(&conn->recvmbox_ref);
}
#if LWIP_TCP
if (conn->acceptmbox_ref) {
sys_mbox_free(&conn->acceptmbox_ref);
}
#endif
#endif
#if !LWIP_NETCONN_SEM_PER_THREAD
sys_sem_free(&conn->op_completed);
sys_sem_set_invalid(&conn->op_completed);
@@ -942,38 +965,33 @@ lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM SIG_CLO
#endif /* LWIP_SO_LINGER */
} else {
if (err == ERR_MEM) {
/* Closing failed because of memory shortage */
if (netconn_is_nonblocking(conn)) {
/* Nonblocking close failed */
close_finished = 1;
err = ERR_WOULDBLOCK;
} else {
/* Blocking close, check the timeout */
/* Closing failed because of memory shortage, try again later. Even for
nonblocking netconns, we have to wait since no standard socket application
is prepared for close failing because of resource shortage.
Check the timeout: this is kind of an lwip addition to the standard sockets:
we wait for some time when failing to allocate a segment for the FIN */
#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER
s32_t close_timeout = LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT;
/* this is kind of an lwip addition to the standard sockets: we wait
for some time when failing to allocate a segment for the FIN */
s32_t close_timeout = LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT;
#if LWIP_SO_SNDTIMEO
if (conn->send_timeout > 0) {
close_timeout = conn->send_timeout;
}
if (conn->send_timeout > 0) {
close_timeout = conn->send_timeout;
}
#endif /* LWIP_SO_SNDTIMEO */
#if LWIP_SO_LINGER
if (conn->linger >= 0) {
/* use linger timeout (seconds) */
close_timeout = conn->linger * 1000U;
}
if (conn->linger >= 0) {
/* use linger timeout (seconds) */
close_timeout = conn->linger * 1000U;
}
#endif
if ((s32_t)(sys_now() - conn->current_msg->msg.sd.time_started) >= close_timeout) {
if ((s32_t)(sys_now() - conn->current_msg->msg.sd.time_started) >= close_timeout) {
#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
if (conn->current_msg->msg.sd.polls_left == 0) {
if (conn->current_msg->msg.sd.polls_left == 0) {
#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
close_finished = 1;
if (close) {
/* in this case, we want to RST the connection */
tcp_abort(tpcb);
err = ERR_OK;
}
close_finished = 1;
if (close) {
/* in this case, we want to RST the connection */
tcp_abort(tpcb);
err = ERR_OK;
}
}
} else {
@@ -1401,6 +1419,10 @@ lwip_netconn_do_listen(void *m)
msg->err = sys_mbox_new(&msg->conn->acceptmbox, DEFAULT_ACCEPTMBOX_SIZE);
}
if (msg->err == ERR_OK) {
#if ESP_THREAD_SAFE
msg->conn->acceptmbox_ref = msg->conn->acceptmbox;
sys_mbox_set_owner(&msg->conn->acceptmbox, msg->conn);
#endif
msg->conn->state = NETCONN_LISTEN;
msg->conn->pcb.tcp = lpcb;
tcp_arg(msg->conn->pcb.tcp, msg->conn);
@@ -1503,24 +1525,38 @@ lwip_netconn_do_recv(void *m)
msg->err = ERR_OK;
if (msg->conn->pcb.tcp != NULL) {
if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
#if TCP_LISTEN_BACKLOG
if (msg->conn->pcb.tcp->state == LISTEN) {
tcp_accepted(msg->conn->pcb.tcp);
} else
#endif /* TCP_LISTEN_BACKLOG */
{
u32_t remaining = msg->msg.r.len;
do {
u16_t recved = (remaining > 0xffff) ? 0xffff : (u16_t)remaining;
tcp_recved(msg->conn->pcb.tcp, recved);
remaining -= recved;
} while (remaining != 0);
}
u32_t remaining = msg->msg.r.len;
do {
u16_t recved = (remaining > 0xffff) ? 0xffff : (u16_t)remaining;
tcp_recved(msg->conn->pcb.tcp, recved);
remaining -= recved;
} while (remaining != 0);
}
}
TCPIP_APIMSG_ACK(msg);
}
#if TCP_LISTEN_BACKLOG
/** Indicate that a TCP pcb has been accepted
* Called from netconn_accept
*
* @param m the api_msg pointing to the connection
*/
void
lwip_netconn_do_accepted(void *m)
{
struct api_msg_msg *msg = (struct api_msg_msg *)m;
msg->err = ERR_OK;
if (msg->conn->pcb.tcp != NULL) {
if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
tcp_backlog_accepted(msg->conn->pcb.tcp);
}
}
TCPIP_APIMSG_ACK(msg);
}
#endif /* TCP_LISTEN_BACKLOG */
/**
* See if more data needs to be written from a previous call to netconn_write.
* Called initially from lwip_netconn_do_write. If the first call can't send all data

View File

@@ -66,6 +66,13 @@ sys_thread_t g_lwip_task = NULL;
sys_mutex_t lock_tcpip_core;
#endif /* LWIP_TCPIP_CORE_LOCKING */
#if LWIP_TIMERS
/* wait for a message, timeouts are processed while waiting */
#define TCPIP_MBOX_FETCH(mbox, msg) sys_timeouts_mbox_fetch(mbox, msg)
#else /* LWIP_TIMERS */
/* wait for a message with timers disabled (e.g. pass a timer-check trigger into tcpip_thread) */
#define TCPIP_MBOX_FETCH(mbox, msg) sys_mbox_fetch(mbox, msg)
#endif /* LWIP_TIMERS */
/**
* The main lwIP thread. This thread has exclusive access to lwIP core functions
@@ -99,7 +106,7 @@ tcpip_thread(void *arg)
UNLOCK_TCPIP_CORE();
LWIP_TCPIP_THREAD_ALIVE();
/* wait for a message, timeouts are processed while waiting */
sys_timeouts_mbox_fetch(&mbox, (void **)&msg);
TCPIP_MBOX_FETCH(&mbox, (void **)&msg);
LOCK_TCPIP_CORE();

View File

@@ -133,16 +133,14 @@ bool ip4_netif_exist(const ip4_addr_t *src, const ip4_addr_t *dest)
return false;
}
/**
* Source based IPv4 routing hook function. This function works only
* when destination IP is broadcast IP.
* Source based IPv4 routing hook function.
*/
struct netif *
ip4_route_src_hook(const ip4_addr_t *dest, const ip4_addr_t *src)
{
struct netif *netif = NULL;
/* destination IP is broadcast IP? */
if ((src != NULL) && (dest->addr == IPADDR_BROADCAST)) {
if ((src != NULL) && !ip4_addr_isany(src)) {
/* iterate through netifs */
for (netif = netif_list; netif != NULL; netif = netif->next) {
/* is the netif up, does it have a link and a valid address? */

View File

@@ -332,6 +332,16 @@ netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *
#endif /* LWIP_IPV4*/
/**
* Set the netif flags for GARP
*/
#if ESP_GRATUITOUS_ARP
void netif_set_garp_flag(struct netif *netif)
{
netif->flags |= NETIF_FLAG_GARP;
}
#endif
/**
* Remove a network interface from the list of lwIP netifs.
*
@@ -453,10 +463,10 @@ void
netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr)
{
ip4_addr_t new_addr = (ipaddr ? *ipaddr : *IP4_ADDR_ANY);
#if ESP_LWIP
#if ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES
ip4_addr_t *last_addr = ip_2_ip4(&netif->last_ip_addr);
#else
ip4_addr_t *last_addr = netif_ip4_addr(netif);
ip4_addr_t *last_addr = ip_2_ip4(&(netif->ip_addr));
#endif
/* address is actually being changed? */

View File

@@ -149,6 +149,22 @@ tcp_tmr(void)
}
}
#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
/** Called when a listen pcb is closed. Iterates one pcb list and removes the
* closed listener pcb from pcb->listener if matching.
*/
static void
tcp_remove_listener(struct tcp_pcb *list, struct tcp_pcb_listen *lpcb)
{
struct tcp_pcb *pcb;
for (pcb = list; pcb != NULL; pcb = pcb->next) {
if (pcb->listener == lpcb) {
pcb->listener = NULL;
}
}
}
#endif
void
tcp_set_fin_wait_1(struct tcp_pcb *pcb)
{
@@ -158,6 +174,70 @@ tcp_set_fin_wait_1(struct tcp_pcb *pcb)
#endif
}
/** Called when a listen pcb is closed. Iterates all pcb lists and removes the
* closed listener pcb from pcb->listener if matching.
*/
static void
tcp_listen_closed(struct tcp_pcb *pcb)
{
#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
size_t i;
LWIP_ASSERT("pcb != NULL", pcb != NULL);
LWIP_ASSERT("pcb->state == LISTEN", pcb->state == LISTEN);
for (i = 1; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) {
tcp_remove_listener(*tcp_pcb_lists[i], (struct tcp_pcb_listen *)pcb);
}
#endif
LWIP_UNUSED_ARG(pcb);
}
#if TCP_LISTEN_BACKLOG
/** @ingroup tcp_raw
* Delay accepting a connection in respect to the listen backlog:
* the number of outstanding connections is increased until
* tcp_backlog_accepted() is called.
*
* ATTENTION: the caller is responsible for calling tcp_backlog_accepted()
* or else the backlog feature will get out of sync!
*
* @param pcb the connection pcb which is not fully accepted yet
*/
void
tcp_backlog_delayed(struct tcp_pcb *pcb)
{
LWIP_ASSERT("pcb != NULL", pcb != NULL);
if ((pcb->flags & TF_BACKLOGPEND) == 0) {
if (pcb->listener != NULL) {
pcb->listener->accepts_pending++;
LWIP_ASSERT("accepts_pending != 0", pcb->listener->accepts_pending != 0);
pcb->flags |= TF_BACKLOGPEND;
}
}
}
/** @ingroup tcp_raw
* A delayed-accept a connection is accepted (or closed/aborted): decreases
* the number of outstanding connections after calling tcp_backlog_delayed().
*
* ATTENTION: the caller is responsible for calling tcp_backlog_accepted()
* or else the backlog feature will get out of sync!
*
* @param pcb the connection pcb which is now fully accepted (or closed/aborted)
*/
void
tcp_backlog_accepted(struct tcp_pcb *pcb)
{
LWIP_ASSERT("pcb != NULL", pcb != NULL);
if ((pcb->flags & TF_BACKLOGPEND) != 0) {
if (pcb->listener != NULL) {
LWIP_ASSERT("accepts_pending != 0", pcb->listener->accepts_pending != 0);
pcb->listener->accepts_pending--;
pcb->flags &= ~TF_BACKLOGPEND;
}
}
}
#endif /* TCP_LISTEN_BACKLOG */
/**
* Closes the TX side of a connection held by the PCB.
* For tcp_close(), a RST is sent if the application didn't receive all data
@@ -227,6 +307,7 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
break;
case LISTEN:
err = ERR_OK;
tcp_listen_closed(pcb);
tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb);
memp_free(MEMP_TCP_PCB_LISTEN, pcb);
pcb = NULL;
@@ -241,6 +322,7 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
case SYN_RCVD:
err = tcp_send_fin(pcb);
if (err == ERR_OK) {
tcp_backlog_accepted(pcb);
MIB2_STATS_INC(mib2.tcpattemptfails);
tcp_set_fin_wait_1(pcb);
}
@@ -408,6 +490,7 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
pcb->ooseq = NULL;
}
#endif /* TCP_QUEUE_OOSEQ */
tcp_backlog_accepted(pcb);
if (send_rst) {
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n"));
tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, local_port, pcb->remote_port);
@@ -1747,27 +1830,7 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n"));
#if TCP_LISTEN_BACKLOG
if (pcb->state == SYN_RCVD) {
/* Need to find the corresponding listen_pcb and decrease its accepts_pending */
struct tcp_pcb_listen *lpcb;
LWIP_ASSERT("tcp_pcb_purge: pcb->state == SYN_RCVD but tcp_listen_pcbs is NULL",
tcp_listen_pcbs.listen_pcbs != NULL);
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
if ((lpcb->local_port == pcb->local_port) &&
(IP_IS_V6_VAL(pcb->local_ip) == IP_IS_V6_VAL(lpcb->local_ip)) &&
(ip_addr_isany(&lpcb->local_ip) ||
ip_addr_cmp(&pcb->local_ip, &lpcb->local_ip))) {
/* port and address of the listen pcb match the timed-out pcb */
LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending",
lpcb->accepts_pending > 0);
lpcb->accepts_pending--;
break;
}
}
}
#endif /* TCP_LISTEN_BACKLOG */
tcp_backlog_accepted(pcb);
if (pcb->refused_data != NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n"));
@@ -1917,6 +1980,31 @@ tcp_eff_send_mss_impl(u16_t sendmss, const ip_addr_t *dest
}
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
/** Helper function for tcp_netif_ip4_addr_changed() that iterates a pcb list */
static void
tcp_netif_ip_addr_changed_pcblist(const ip4_addr_t* old_addr, struct tcp_pcb* pcb_list)
{
struct tcp_pcb *pcb;
pcb = pcb_list;
while (pcb != NULL) {
/* PCB bound to current local interface address? */
if (ip4_addr_cmp(ip_2_ip4(&pcb->local_ip), old_addr)
#if LWIP_AUTOIP
/* connections to link-local addresses must persist (RFC3927 ch. 1.9) */
&& (!IP_IS_V4_VAL(pcb->local_ip) || !ip4_addr_islinklocal(ip_2_ip4(&pcb->local_ip)))
#endif /* LWIP_AUTOIP */
) {
/* this connection must be aborted */
struct tcp_pcb *next = pcb->next;
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb));
tcp_abort(pcb);
pcb = next;
} else {
pcb = pcb->next;
}
}
}
#if LWIP_IPV4
/** This function is called from netif.c when address is changed or netif is removed
*
@@ -1927,18 +2015,29 @@ void tcp_netif_ipv4_addr_changed(const ip4_addr_t* old_addr, const ip4_addr_t* n
{
struct tcp_pcb_listen *lpcb, *next;
if (!ip4_addr_isany(new_addr)) {
/* PCB bound to current local interface address? */
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = next) {
next = lpcb->next;
/* Is this an IPv4 pcb? */
if (!IP_IS_V6_VAL(lpcb->local_ip)) {
/* PCB bound to current local interface address? */
if ((!(ip4_addr_isany(ip_2_ip4(&lpcb->local_ip)))) &&
(ip4_addr_cmp(ip_2_ip4(&lpcb->local_ip), old_addr))) {
/* The PCB is listening to the old ipaddr and
* is set to listen to the new one instead */
ip_addr_copy_from_ip4(lpcb->local_ip, *new_addr);
if (!ip4_addr_isany(old_addr)) {
#if ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES
if ((new_addr == NULL) || ((!ip4_addr_isany_val(*new_addr)) && (!ip4_addr_cmp(old_addr, new_addr)))) {
#endif
tcp_netif_ip_addr_changed_pcblist(old_addr, tcp_active_pcbs);
tcp_netif_ip_addr_changed_pcblist(old_addr, tcp_bound_pcbs);
#if ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES
}
#endif
if (!ip4_addr_isany(new_addr)) {
/* PCB bound to current local interface address? */
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = next) {
next = lpcb->next;
/* Is this an IPv4 pcb? */
if (!IP_IS_V6_VAL(lpcb->local_ip)) {
/* PCB bound to current local interface address? */
if ((!(ip4_addr_isany(ip_2_ip4(&lpcb->local_ip)))) &&
(ip4_addr_cmp(ip_2_ip4(&lpcb->local_ip), old_addr))) {
/* The PCB is listening to the old ipaddr and
* is set to listen to the new one instead */
ip_addr_copy_from_ip4(lpcb->local_ip, *new_addr);
}
}
}
}

View File

@@ -568,6 +568,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
}
#if TCP_LISTEN_BACKLOG
pcb->accepts_pending++;
npcb->flags |= TF_BACKLOGPEND;
#endif /* TCP_LISTEN_BACKLOG */
/* Set up the new PCB. */
ip_addr_copy(npcb->local_ip, *ip_current_dest_addr());
@@ -582,6 +583,10 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
#if LWIP_CALLBACK_API
npcb->accept = pcb->accept;
#endif /* LWIP_CALLBACK_API */
#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
npcb->listener = pcb;
#endif
/* inherit socket options */
npcb->so_options = pcb->so_options & SOF_INHERITED;
/* Register the new PCB so that we can begin receiving segments
@@ -785,11 +790,19 @@ tcp_process(struct tcp_pcb *pcb)
if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {
pcb->state = ESTABLISHED;
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
#if LWIP_CALLBACK_API
LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL);
#endif
/* Call the accept function. */
TCP_EVENT_ACCEPT(pcb, ERR_OK, err);
if (pcb->listener == NULL) {
err = ERR_VAL;
} else {
#endif
tcp_backlog_accepted(pcb);
/* Call the accept function. */
TCP_EVENT_ACCEPT(pcb, ERR_OK, err);
}
if (err != ERR_OK) {
/* If the accept function returns with an error, we abort
* the connection. */

View File

@@ -44,8 +44,6 @@
#include "lwip/timers.h"
#include "lwip/priv/tcp_priv.h"
#if LWIP_TIMERS
#include "lwip/def.h"
#include "lwip/memp.h"
#include "lwip/priv/tcpip_priv.h"
@@ -62,11 +60,71 @@
#include "lwip/sys.h"
#include "lwip/pbuf.h"
#if LWIP_DEBUG_TIMERNAMES
#define HANDLER(x) x, #x
#else /* LWIP_DEBUG_TIMERNAMES */
#define HANDLER(x) x
#endif /* LWIP_DEBUG_TIMERNAMES */
#if ESP_DHCP
extern void dhcps_coarse_tmr(void);
#endif
#if ESP_GRATUITOUS_ARP
extern void garp_tmr(void);
#endif
/** This array contains all stack-internal cyclic timers. To get the number of
* timers, use LWIP_ARRAYSIZE() */
const struct lwip_cyclic_timer lwip_cyclic_timers[] = {
#if LWIP_TCP
/* The TCP timer is a special case: it does not have to run always and
* is triggered to start from TCP using tcp_timer_needed() */
{TCP_TMR_INTERVAL, HANDLER(tcp_tmr)},
#endif /* LWIP_TCP */
#if LWIP_IPV4
#if IP_REASSEMBLY
{IP_TMR_INTERVAL, HANDLER(ip_reass_tmr)},
#endif /* IP_REASSEMBLY */
#if LWIP_ARP
{ARP_TMR_INTERVAL, HANDLER(etharp_tmr)},
#if ESP_GRATUITOUS_ARP
{GARP_TMR_INTERVAL, HANDLER(garp_tmr)},
#endif
#endif /* LWIP_ARP */
#if LWIP_DHCP
{DHCP_COARSE_TIMER_MSECS, HANDLER(dhcp_coarse_tmr)},
{DHCP_FINE_TIMER_MSECS, HANDLER(dhcp_fine_tmr)},
#if ESP_DHCP
{DHCP_COARSE_TIMER_MSECS, HANDLER(dhcps_coarse_tmr)},
#endif
#endif /* LWIP_DHCP */
#if LWIP_AUTOIP
{AUTOIP_TMR_INTERVAL, HANDLER(autoip_tmr)},
#endif /* LWIP_AUTOIP */
#if LWIP_IGMP
{IGMP_TMR_INTERVAL, HANDLER(igmp_tmr)},
#endif /* LWIP_IGMP */
#endif /* LWIP_IPV4 */
#if LWIP_DNS
{DNS_TMR_INTERVAL, HANDLER(dns_tmr)},
#endif /* LWIP_DNS */
#if LWIP_IPV6
{ND6_TMR_INTERVAL, HANDLER(nd6_tmr)},
#if LWIP_IPV6_REASS
{IP6_REASS_TMR_INTERVAL, HANDLER(ip6_reass_tmr)},
#endif /* LWIP_IPV6_REASS */
#if LWIP_IPV6_MLD
{MLD6_TMR_INTERVAL, HANDLER(mld6_tmr)},
#endif /* LWIP_IPV6_MLD */
#endif /* LWIP_IPV6 */
};
#if LWIP_TIMERS && !LWIP_TIMERS_CUSTOM
/** The one and only timeout list */
static struct sys_timeo *next_timeout;
#if NO_SYS
static u32_t timeouts_last_time;
#endif /* NO_SYS */
#if LWIP_TCP
/** global variable that shows if the tcp timer is currently scheduled or not */
@@ -111,213 +169,35 @@ tcp_timer_needed(void)
}
#endif /* LWIP_TCP */
#if LWIP_IPV4
#if IP_REASSEMBLY
/**
* Timer callback function that calls ip_reass_tmr() and reschedules itself.
*
* @param arg unused argument
*/
static void
ip_reass_timer(void *arg)
{
LWIP_UNUSED_ARG(arg);
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip_reass_tmr()\n"));
ip_reass_tmr();
sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
}
#endif /* IP_REASSEMBLY */
#if LWIP_ARP
/**
* Timer callback function that calls etharp_tmr() and reschedules itself.
*
* @param arg unused argument
*/
static void
arp_timer(void *arg)
{
LWIP_UNUSED_ARG(arg);
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: etharp_tmr()\n"));
etharp_tmr();
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
}
#endif /* LWIP_ARP */
#if LWIP_DHCP
/**
* Timer callback function that calls dhcp_coarse_tmr() and reschedules itself.
*
* @param arg unused argument
*/
static void
dhcp_timer_coarse(void *arg)
{
LWIP_UNUSED_ARG(arg);
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_coarse_tmr()\n"));
dhcp_coarse_tmr();
#if ESP_DHCP
extern void dhcps_coarse_tmr(void);
dhcps_coarse_tmr();
#endif
sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL);
}
/**
* Timer callback function that calls dhcp_fine_tmr() and reschedules itself.
*
* @param arg unused argument
*/
static void
dhcp_timer_fine(void *arg)
{
LWIP_UNUSED_ARG(arg);
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_fine_tmr()\n"));
dhcp_fine_tmr();
sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
}
#endif /* LWIP_DHCP */
#if LWIP_AUTOIP
/**
* Timer callback function that calls autoip_tmr() and reschedules itself.
*
* @param arg unused argument
*/
static void
autoip_timer(void *arg)
{
LWIP_UNUSED_ARG(arg);
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: autoip_tmr()\n"));
autoip_tmr();
sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL);
}
#endif /* LWIP_AUTOIP */
#if LWIP_IGMP
/**
* Timer callback function that calls igmp_tmr() and reschedules itself.
*
* @param arg unused argument
*/
static void
igmp_timer(void *arg)
{
LWIP_UNUSED_ARG(arg);
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: igmp_tmr()\n"));
igmp_tmr();
sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL);
}
#endif /* LWIP_IGMP */
#endif /* LWIP_IPV4 */
#if LWIP_DNS
/**
* Timer callback function that calls dns_tmr() and reschedules itself.
*
* @param arg unused argument
*/
static void
dns_timer(void *arg)
{
LWIP_UNUSED_ARG(arg);
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dns_tmr()\n"));
dns_tmr();
sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
}
#endif /* LWIP_DNS */
#if LWIP_IPV6
/**
* Timer callback function that calls nd6_tmr() and reschedules itself.
*
* @param arg unused argument
*/
static void
nd6_timer(void *arg)
{
LWIP_UNUSED_ARG(arg);
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: nd6_tmr()\n"));
nd6_tmr();
sys_timeout(ND6_TMR_INTERVAL, nd6_timer, NULL);
}
#if LWIP_IPV6_REASS
/**
* Timer callback function that calls ip6_reass_tmr() and reschedules itself.
*
* @param arg unused argument
*/
static void
ip6_reass_timer(void *arg)
{
LWIP_UNUSED_ARG(arg);
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip6_reass_tmr()\n"));
ip6_reass_tmr();
sys_timeout(IP6_REASS_TMR_INTERVAL, ip6_reass_timer, NULL);
}
#endif /* LWIP_IPV6_REASS */
#if LWIP_IPV6_MLD
/**
* Timer callback function that calls mld6_tmr() and reschedules itself.
*
* @param arg unused argument
*/
static void
mld6_timer(void *arg)
cyclic_timer(void *arg)
{
LWIP_UNUSED_ARG(arg);
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: mld6_tmr()\n"));
mld6_tmr();
sys_timeout(MLD6_TMR_INTERVAL, mld6_timer, NULL);
const struct lwip_cyclic_timer* cyclic = (const struct lwip_cyclic_timer*)arg;
#if LWIP_DEBUG_TIMERNAMES
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: %s()\n", cyclic->handler_name));
#endif
cyclic->handler();
sys_timeout(cyclic->interval_ms, cyclic_timer, arg);
}
#endif /* LWIP_IPV6_MLD */
#endif /* LWIP_IPV6 */
/** Initialize this module */
void sys_timeouts_init(void)
{
#if LWIP_IPV4
#if IP_REASSEMBLY
sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
#endif /* IP_REASSEMBLY */
#if LWIP_ARP
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
#endif /* LWIP_ARP */
#if LWIP_DHCP
size_t i;
/* tcp_tmr() at index 0 is started on demand */
for (i = (LWIP_TCP ? 1 : 0); i < LWIP_ARRAYSIZE(lwip_cyclic_timers); i++) {
/* we have to cast via size_t to get rid of const warning
* (this is OK as cyclic_timer() casts back to const* */
sys_timeout(lwip_cyclic_timers[i].interval_ms, cyclic_timer, LWIP_CONST_CAST(void*, &lwip_cyclic_timers[i]));
}
sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL);
sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
#endif /* LWIP_DHCP */
#if LWIP_AUTOIP
sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL);
#endif /* LWIP_AUTOIP */
#if LWIP_IGMP
sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL);
#endif /* LWIP_IGMP */
#endif /* LWIP_IPV4 */
#if LWIP_DNS
sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
#endif /* LWIP_DNS */
#if LWIP_IPV6
sys_timeout(ND6_TMR_INTERVAL, nd6_timer, NULL);
#if LWIP_IPV6_REASS
sys_timeout(IP6_REASS_TMR_INTERVAL, ip6_reass_timer, NULL);
#endif /* LWIP_IPV6_REASS */
#if LWIP_IPV6_MLD
sys_timeout(MLD6_TMR_INTERVAL, mld6_timer, NULL);
#endif /* LWIP_IPV6_MLD */
#endif /* LWIP_IPV6 */
#if NO_SYS
/* Initialise timestamp for sys_check_timeouts */
timeouts_last_time = sys_now();
#endif
}
/**
@@ -334,19 +214,12 @@ void sys_timeouts_init(void)
void
sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name)
#else /* LWIP_DEBUG_TIMERNAMES */
#if ESP_LIGHT_SLEEP
u32_t LwipTimOutLim = 0; // For light sleep. time out. limit is 3000ms
#endif
void
sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg)
#endif /* LWIP_DEBUG_TIMERNAMES */
{
struct sys_timeo *timeout, *t;
#if NO_SYS
u32_t now, diff;
#endif
timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT);
if (timeout == NULL) {
@@ -354,7 +227,6 @@ sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg)
return;
}
#if NO_SYS
now = sys_now();
if (next_timeout == NULL) {
diff = 0;
@@ -362,26 +234,15 @@ sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg)
} else {
diff = now - timeouts_last_time;
}
#endif
timeout->next = NULL;
timeout->h = handler;
timeout->arg = arg;
#if ESP_LIGHT_SLEEP
if(msecs < LwipTimOutLim)
msecs = LwipTimOutLim;
#endif
#if NO_SYS
timeout->time = msecs + diff;
#else
timeout->time = msecs;
#endif
#if LWIP_DEBUG_TIMERNAMES
timeout->handler_name = handler_name;
LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" handler=%s arg=%p\n",
(void *)timeout, msecs, handler_name, (void *)arg));
(void *)timeout, msecs, handler_name, (void *)arg));
#endif /* LWIP_DEBUG_TIMERNAMES */
if (next_timeout == NULL) {
@@ -399,6 +260,12 @@ sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg)
if (t->next == NULL || t->next->time > timeout->time) {
if (t->next != NULL) {
t->next->time -= timeout->time;
} else if (timeout->time > msecs) {
/* If this is the case, 'timeouts_last_time' and 'now' differs too much.
* This can be due to sys_check_timeouts() not being called at the right
* times, but also when stopping in a breakpoint. Anyway, let's assume
* this is not wanted, so add the first timer's time instead of 'diff' */
timeout->time = msecs + next_timeout->time;
}
timeout->next = t->next;
t->next = timeout;
@@ -415,7 +282,7 @@ sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg)
*
* @param handler callback function that would be called by the timeout
* @param arg callback argument that would be passed to handler
*/
*/
void
sys_untimeout(sys_timeout_handler handler, void *arg)
{
@@ -445,14 +312,17 @@ sys_untimeout(sys_timeout_handler handler, void *arg)
return;
}
#if NO_SYS
/** Handle timeouts for NO_SYS==1 (i.e. without using
/**
* @ingroup lwip_nosys
* Handle timeouts for NO_SYS==1 (i.e. without using
* tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout
* handler functions when timeouts expire.
*
* Must be called periodically from your main loop.
*/
#if !NO_SYS && !defined __DOXYGEN__
static
#endif /* !NO_SYS */
void
sys_check_timeouts(void)
{
@@ -468,9 +338,7 @@ sys_check_timeouts(void)
/* this cares for wraparounds */
diff = now - timeouts_last_time;
do {
#if PBUF_POOL_FREE_OOSEQ
PBUF_CHECK_FREE_OOSEQ();
#endif /* PBUF_POOL_FREE_OOSEQ */
had_one = 0;
tmptimeout = next_timeout;
if (tmptimeout && (tmptimeout->time <= diff)) {
@@ -483,16 +351,24 @@ sys_check_timeouts(void)
arg = tmptimeout->arg;
#if LWIP_DEBUG_TIMERNAMES
if (handler != NULL) {
LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n",
tmptimeout->handler_name, arg));
LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n",tmptimeout->handler_name, arg));
}
#endif /* LWIP_DEBUG_TIMERNAMES */
memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
if (handler != NULL) {
#if !NO_SYS
/* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the
* timeout handler function. */
LOCK_TCPIP_CORE();
#endif /* !NO_SYS */
handler(arg);
#if !NO_SYS
UNLOCK_TCPIP_CORE();
#endif /* !NO_SYS */
}
LWIP_TCPIP_THREAD_ALIVE();
}
/* repeat until all expired timers have been called */
/* repeat until all expired timers have been called */
} while (had_one);
}
}
@@ -511,6 +387,9 @@ sys_restart_timeouts(void)
/** Return the time left before the next timeout is due. If no timeouts are
* enqueued, returns 0xffffffff
*/
#if !NO_SYS
static
#endif /* !NO_SYS */
u32_t
sys_timeouts_sleeptime(void)
{
@@ -526,7 +405,7 @@ sys_timeouts_sleeptime(void)
}
}
#else /* NO_SYS */
#if !NO_SYS
/**
* Wait (forever) for a message to arrive in an mbox.
@@ -538,66 +417,30 @@ sys_timeouts_sleeptime(void)
void
sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg)
{
u32_t time_needed;
struct sys_timeo *tmptimeout;
sys_timeout_handler handler;
void *arg;
again:
u32_t sleeptime;
again:
if (!next_timeout) {
time_needed = sys_arch_mbox_fetch(mbox, msg, 0);
} else {
if (next_timeout->time > 0) {
time_needed = sys_arch_mbox_fetch(mbox, msg, next_timeout->time);
} else {
time_needed = SYS_ARCH_TIMEOUT;
}
sys_arch_mbox_fetch(mbox, msg, 0);
return;
}
if (time_needed == SYS_ARCH_TIMEOUT) {
/* If time == SYS_ARCH_TIMEOUT, a timeout occurred before a message
could be fetched. We should now call the timeout handler and
deallocate the memory allocated for the timeout. */
tmptimeout = next_timeout;
next_timeout = tmptimeout->next;
handler = tmptimeout->h;
arg = tmptimeout->arg;
#if LWIP_DEBUG_TIMERNAMES
if (handler != NULL) {
LWIP_DEBUGF(TIMERS_DEBUG, ("stmf calling h=%s arg=%p\n",
tmptimeout->handler_name, arg));
}
#endif /* LWIP_DEBUG_TIMERNAMES */
memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
if (handler != NULL) {
/* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the
timeout handler function. */
LOCK_TCPIP_CORE();
handler(arg);
UNLOCK_TCPIP_CORE();
}
LWIP_TCPIP_THREAD_ALIVE();
/* We try again to fetch a message from the mbox. */
goto again;
} else {
/* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
occured. The time variable is set to the number of
milliseconds we waited for the message. */
if (time_needed < next_timeout->time) {
next_timeout->time -= time_needed;
} else {
next_timeout->time = 0;
}
}
sleeptime = sys_timeouts_sleeptime();
if (sleeptime == 0 || sys_arch_mbox_fetch(mbox, msg, sleeptime) == SYS_ARCH_TIMEOUT) {
/* If a SYS_ARCH_TIMEOUT value is returned, a timeout occurred
* before a message could be fetched. */
sys_check_timeouts();
/* We try again to fetch a message from the mbox. */
goto again;
}
}
#endif /* NO_SYS */
#else /* LWIP_TIMERS */
#else /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */
/* Satisfy the TCP code which calls this function */
void
tcp_timer_needed(void)
{
}
#endif /* LWIP_TIMERS */
#endif /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */

View File

@@ -195,6 +195,15 @@ struct netconn {
by the application thread */
sys_mbox_t acceptmbox;
#endif /* LWIP_TCP */
#if ESP_THREAD_SAFE
/** point to the same mbox as recvmbox */
sys_mbox_t recvmbox_ref;
#if LWIP_TCP
/** point to the same mbox as acceptmbox */
sys_mbox_t acceptmbox_ref;
#endif
#endif
/** only used for socket layer */
#if LWIP_SOCKET
int socket;

View File

@@ -52,6 +52,11 @@
#define X8_F "02x"
#endif /* X8_F */
/** C++ const_cast<target_type>(val) equivalent to remove constness from a value (GCC -Wcast-qual) */
#ifndef LWIP_CONST_CAST
#define LWIP_CONST_CAST(target_type, val) ((target_type)((ptrdiff_t)val))
#endif
#ifdef __cplusplus
extern "C" {
#endif

View File

@@ -47,6 +47,8 @@ extern "C" {
#define IPADDR_TYPE_V6 6U
#define IPADDR_TYPE_ANY 46U
#define IP_IS_V4_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V4)
#if LWIP_IPV4 && LWIP_IPV6
/** A union struct for both IP version's addresses.
* ATTENTION: watch out for its size when adding IPv6 address scope!
@@ -67,6 +69,7 @@ extern const ip_addr_t ip_addr_any_type;
#define IP_IS_ANY_TYPE_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_ANY)
#define IPADDR_ANY_TYPE_INIT { { { { 0ul, 0ul, 0ul, 0ul } } }, IPADDR_TYPE_ANY }
#define IP_IS_V4_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V4)
#define IP_IS_V6_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V6)
#define IP_IS_V6(ipaddr) (((ipaddr) != NULL) && IP_IS_V6_VAL(*(ipaddr)))

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