Compare commits

..

128 Commits

Author SHA1 Message Date
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
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
Deng Xin
39f97bb4e8 wifi: add compatible to ccmp encryption 2018-07-31 21:07:46 +08:00
96 changed files with 2857 additions and 1699 deletions

View File

@@ -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"
@@ -270,7 +273,7 @@ test_build_system:
- cd test_build_system
- ${IDF_PATH}/tools/ci/test_build_system.sh
push_master_to_github:
push_to_github:
stage: deploy
image: $CI_DOCKER_REGISTRY/esp32-ci-env
tags:
@@ -281,8 +284,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
@@ -293,12 +294,7 @@ 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: host_test

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

@@ -166,8 +166,8 @@ config BLE_SCAN_DUPLICATE
config DUPLICATE_SCAN_CACHE_SIZE
int "Maximum number of devices in scan duplicate filter"
depends on BLE_SCAN_DUPLICATE
range 10 200
default 20
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.

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

@@ -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

@@ -208,10 +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");
if (p_data && p_data->req_data.value){
osi_free(p_data->req_data.value);
}
LOG_DEBUG("CONFIRM EVT\n");
/* Nothing */
break;
case BTA_GATTS_CREATE_EVT:

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

@@ -530,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;

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

@@ -1404,7 +1404,8 @@ 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;
@@ -2570,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;
@@ -2582,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) {
@@ -2811,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;
@@ -2829,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);
@@ -3053,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
@@ -3077,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 */
@@ -3105,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;
}
@@ -3149,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;
}
}
}

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

@@ -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

View File

@@ -162,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

@@ -57,9 +57,9 @@
/* 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);
@@ -748,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);
@@ -806,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

@@ -131,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 */
@@ -153,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;
/**
@@ -180,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

@@ -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

@@ -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

@@ -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

@@ -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

@@ -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 );

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 {

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

@@ -107,6 +107,23 @@ config LWIP_ETHARP_TRUST_IP_MAC
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

View File

@@ -945,38 +945,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 {

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

@@ -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.
*

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

@@ -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)))

View File

@@ -99,6 +99,11 @@ extern "C" {
* Set by the netif driver in its init function. */
#define NETIF_FLAG_MLD6 0x40U
#if ESP_GRATUITOUS_ARP
/** If set, the netif will send gratuitous ARP periodically */
#define NETIF_FLAG_GARP 0x80U
#endif
#if LWIP_CHECKSUM_CTRL_PER_NETIF
#define NETIF_CHECKSUM_GEN_IP 0x0001
#define NETIF_CHECKSUM_GEN_UDP 0x0002
@@ -362,6 +367,11 @@ struct netif *netif_add(struct netif *netif,
void netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask,
const ip4_addr_t *gw);
#endif /* LWIP_IPV4 */
#if ESP_GRATUITOUS_ARP
void netif_set_garp_flag(struct netif *netif);
#endif
void netif_remove(struct netif * netif);
/* Returns a network interface given its name. The name is of the form

View File

@@ -69,11 +69,16 @@
#endif
/**
* NO_SYS_NO_TIMERS==1: Drop support for sys_timeout when NO_SYS==1
* Mainly for compatibility to old versions.
* LWIP_TIMERS==0: Drop support for sys_timeout and lwip-internal cyclic timers.
* (the array of lwip-internal cyclic timers is still provided)
* (check NO_SYS_NO_TIMERS for compatibility to old versions)
*/
#ifndef NO_SYS_NO_TIMERS
#define NO_SYS_NO_TIMERS 0
#if !defined LWIP_TIMERS || defined __DOXYGEN__
#ifdef NO_SYS_NO_TIMERS
#define LWIP_TIMERS (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS))
#else
#define LWIP_TIMERS 1
#endif
#endif
/**
@@ -313,8 +318,12 @@
* The formula expects settings to be either '0' or '1'.
*/
#ifndef MEMP_NUM_SYS_TIMEOUT
#if ESP_LWIP
#define MEMP_NUM_SYS_TIMEOUT (LWIP_TCP + IP_REASSEMBLY + (LWIP_ARP + (ESP_GRATUITOUS_ARP ? 1 : 0)) + (2*LWIP_DHCP + (ESP_DHCPS_TIMER ? 1 : 0)) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + (PPP_SUPPORT*6*MEMP_NUM_PPP_PCB) + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0))
#else
#define MEMP_NUM_SYS_TIMEOUT (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + (PPP_SUPPORT*6*MEMP_NUM_PPP_PCB) + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0))
#endif
#endif
/**
* MEMP_NUM_NETBUF: the number of struct netbufs.

View File

@@ -169,12 +169,12 @@ struct pbuf_custom {
};
#endif /* LWIP_SUPPORT_CUSTOM_PBUF */
#if LWIP_TCP && TCP_QUEUE_OOSEQ
/** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */
#ifndef PBUF_POOL_FREE_OOSEQ
#define PBUF_POOL_FREE_OOSEQ 1
#endif /* PBUF_POOL_FREE_OOSEQ */
#if NO_SYS && PBUF_POOL_FREE_OOSEQ
#if LWIP_TCP && TCP_QUEUE_OOSEQ && NO_SYS && PBUF_POOL_FREE_OOSEQ
extern volatile u8_t pbuf_free_ooseq_pending;
void pbuf_free_ooseq(void);
/** When not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ()
@@ -184,8 +184,10 @@ void pbuf_free_ooseq(void);
/* pbuf_alloc() reported PBUF_POOL to be empty -> try to free some \
ooseq queued pbufs now */ \
pbuf_free_ooseq(); }}while(0)
#endif /* NO_SYS && PBUF_POOL_FREE_OOSEQ*/
#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ */
#else /* LWIP_TCP && TCP_QUEUE_OOSEQ && NO_SYS && PBUF_POOL_FREE_OOSEQ */
/* Otherwise declare an empty PBUF_CHECK_FREE_OOSEQ */
#define PBUF_CHECK_FREE_OOSEQ()
#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && NO_SYS && PBUF_POOL_FREE_OOSEQ*/
/* Initializes the pbuf module. This call is empty for now, but may not be in future. */
#define pbuf_init()

View File

@@ -34,12 +34,6 @@
#define LWIP_HDR_TIMERS_H
#include "lwip/opt.h"
/* Timers are not supported when NO_SYS==1 and NO_SYS_NO_TIMERS==1 */
#define LWIP_TIMERS (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS))
#if LWIP_TIMERS
#include "lwip/err.h"
#if !NO_SYS
#include "lwip/sys.h"
@@ -57,6 +51,26 @@ extern "C" {
#endif /* LWIP_DEBUG*/
#endif
/** Function prototype for a stack-internal timer function that has to be
* called at a defined interval */
typedef void (* lwip_cyclic_timer_handler)(void);
/** This struct contains information about a stack-internal timer function
* that has to be called at a defined interval */
struct lwip_cyclic_timer {
u32_t interval_ms;
lwip_cyclic_timer_handler handler;
#if LWIP_DEBUG_TIMERNAMES
const char* handler_name;
#endif /* LWIP_DEBUG_TIMERNAMES */
};
/** This array contains all stack-internal cyclic timers. To get the number of
* timers, use LWIP_ARRAYSIZE() */
extern const struct lwip_cyclic_timer lwip_cyclic_timers[];
#if LWIP_TIMERS
/** Function prototype for a timeout callback function. Register such a function
* using sys_timeout().
*
@@ -84,18 +98,20 @@ void sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg);
#endif /* LWIP_DEBUG_TIMERNAMES */
void sys_untimeout(sys_timeout_handler handler, void *arg);
void sys_restart_timeouts(void);
#if NO_SYS
void sys_check_timeouts(void);
void sys_restart_timeouts(void);
u32_t sys_timeouts_sleeptime(void);
#else /* NO_SYS */
void sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg);
#endif /* NO_SYS */
#endif /* LWIP_TIMERS */
#ifdef __cplusplus
}
#endif
#endif /* LWIP_TIMERS */
#endif /* LWIP_HDR_TIMERS_H */

View File

@@ -102,6 +102,11 @@ struct etharp_q_entry {
};
#endif /* ARP_QUEUEING */
#if ESP_GRATUITOUS_ARP
#define GARP_TMR_INTERVAL (CONFIG_GARP_TMR_INTERVAL*1000UL)
void garp_tmr(void);
#endif
#define etharp_init() /* Compatibility define, no init needed. */
void etharp_tmr(void);
s8_t etharp_find_addr(struct netif *netif, const ip4_addr_t *ipaddr,

View File

@@ -732,6 +732,7 @@
#define ESP_DHCP_TIMER 1
#define ESP_LWIP_LOGI(...) ESP_LOGI("lwip", __VA_ARGS__)
#define ESP_PING 1
#define ESP_GRATUITOUS_ARP CONFIG_ESP_GRATUITOUS_ARP
#define TCP_WND_DEFAULT CONFIG_TCP_WND_DEFAULT
#define TCP_SND_BUF_DEFAULT CONFIG_TCP_SND_BUF_DEFAULT

View File

@@ -52,6 +52,7 @@
#include "lwip/snmp.h"
#include "lwip/dhcp.h"
#include "lwip/autoip.h"
#include "lwip/netif.h"
#include <string.h>
@@ -129,6 +130,20 @@ static u8_t etharp_cached_entry;
static err_t etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr* hw_dst_addr);
#if ESP_GRATUITOUS_ARP
void garp_tmr(void)
{
struct netif* garp_netif = NULL;
for (garp_netif = netif_list; garp_netif != NULL; garp_netif = garp_netif->next) {
if (netif_is_up(garp_netif) && netif_is_link_up(garp_netif) && !ip4_addr_isany_val(*netif_ip4_addr(garp_netif))) {
if ((garp_netif->flags & NETIF_FLAG_ETHARP) && (garp_netif->flags & NETIF_FLAG_GARP)) {
etharp_gratuitous(garp_netif);
}
}
}
}
#endif
#if ARP_QUEUEING
/**

View File

@@ -697,20 +697,23 @@ static int vfs_spiffs_readdir_r(void* ctx, DIR* pdir, struct dirent* entry,
esp_spiffs_t * efs = (esp_spiffs_t *)ctx;
vfs_spiffs_dir_t * dir = (vfs_spiffs_dir_t *)pdir;
struct spiffs_dirent out;
if (SPIFFS_readdir(&dir->d, &out) == 0) {
errno = spiffs_res_to_errno(SPIFFS_errno(efs->fs));
SPIFFS_clearerr(efs->fs);
if (!errno) {
*out_dirent = NULL;
size_t plen;
char * item_name;
do {
if (SPIFFS_readdir(&dir->d, &out) == 0) {
errno = spiffs_res_to_errno(SPIFFS_errno(efs->fs));
SPIFFS_clearerr(efs->fs);
if (!errno) {
*out_dirent = NULL;
}
return errno;
}
return errno;
}
const char * item_name = (const char *)out.name;
size_t plen = strlen(dir->path);
item_name = (char *)out.name;
plen = strlen(dir->path);
} while ((plen > 1) && (strncasecmp(dir->path, (const char*)out.name, plen) || out.name[plen] != '/' || !out.name[plen + 1]));
if (plen > 1) {
if (strncasecmp(dir->path, (const char *)out.name, plen) || out.name[plen] != '/' || !out.name[plen+1]) {
return vfs_spiffs_readdir_r(ctx, pdir, entry, out_dirent);
}
item_name += plen + 1;
} else if (item_name[0] == '/') {
item_name++;

View File

@@ -275,6 +275,63 @@ void test_spiffs_opendir_readdir_rewinddir(const char* dir_prefix)
TEST_ASSERT_EQUAL(0, closedir(dir));
}
void test_spiffs_readdir_many_files(const char* dir_prefix)
{
const int n_files = 40;
const int n_folders = 4;
unsigned char file_count[n_files * n_folders];
memset(file_count, 0, sizeof(file_count)/sizeof(file_count[0]));
char file_name[ESP_VFS_PATH_MAX + CONFIG_SPIFFS_OBJ_NAME_LEN];
/* clean stale files before the test */
DIR* dir = opendir(dir_prefix);
if (dir) {
while (true) {
struct dirent* de = readdir(dir);
if (!de) {
break;
}
snprintf(file_name, sizeof(file_name), "%s/%s", dir_prefix, de->d_name);
unlink(file_name);
}
}
/* create files */
for (int d = 0; d < n_folders; ++d) {
printf("filling directory %d\n", d);
for (int f = 0; f < n_files; ++f) {
snprintf(file_name, sizeof(file_name), "%s/%d/%d.txt", dir_prefix, d, f);
test_spiffs_create_file_with_text(file_name, file_name);
}
}
/* list files */
for (int d = 0; d < n_folders; ++d) {
printf("listing files in directory %d\n", d);
snprintf(file_name, sizeof(file_name), "%s/%d", dir_prefix, d);
dir = opendir(file_name);
TEST_ASSERT_NOT_NULL(dir);
while (true) {
struct dirent* de = readdir(dir);
if (!de) {
break;
}
int file_id;
TEST_ASSERT_EQUAL(1, sscanf(de->d_name, "%d.txt", &file_id));
file_count[file_id + d * n_files]++;
}
closedir(dir);
}
/* check that all created files have been seen */
for (int d = 0; d < n_folders; ++d) {
printf("checking that all files have been found in directory %d\n", d);
for (int f = 0; f < n_files; ++f) {
TEST_ASSERT_EQUAL(1, file_count[f + d * n_files]);
}
}
}
typedef struct {
const char* filename;
@@ -499,6 +556,13 @@ TEST_CASE("opendir, readdir, rewinddir, seekdir work as expected", "[spiffs]")
test_teardown();
}
TEST_CASE("readdir with large number of files", "[spiffs][timeout=15]")
{
test_setup();
test_spiffs_readdir_many_files("/spiffs/dir2");
test_teardown();
}
TEST_CASE("multiple tasks can use same volume", "[spiffs]")
{
test_setup();

View File

@@ -26,6 +26,7 @@
#include "lwip/ip6_addr.h"
#include "lwip/nd6.h"
#include "lwip/priv/tcpip_priv.h"
#include "lwip/netif.h"
#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
#include "lwip/dns.h"
#endif
@@ -175,6 +176,11 @@ esp_err_t tcpip_adapter_start(tcpip_adapter_if_t tcpip_if, uint8_t *mac, tcpip_a
netif_init = tcpip_if_to_netif_init_fn(tcpip_if);
assert(netif_init != NULL);
netif_add(esp_netif[tcpip_if], &ip_info->ip, &ip_info->netmask, &ip_info->gw, NULL, netif_init, tcpip_input);
#if ESP_GRATUITOUS_ARP
if (tcpip_if == TCPIP_ADAPTER_IF_STA || tcpip_if == TCPIP_ADAPTER_IF_ETH) {
netif_set_garp_flag(esp_netif[tcpip_if]);
}
#endif
}
if (tcpip_if == TCPIP_ADAPTER_IF_AP) {

View File

@@ -81,7 +81,7 @@ build: $(COMPONENT_BUILD_DIR)/$(ULP_EXPORTS_HEADER) \
$(ULP_EXP_DEP_OBJECTS) : $(ULP_EXPORTS_HEADER) $(ULP_SYM)
# Finally, set all the variables processed by the build system.
COMPONENT_EXTRA_CLEAN := $(ULP_OBJECTS) \
COMPONENT_EXTRA_CLEAN += $(ULP_OBJECTS) \
$(ULP_LD_SCRIPT) \
$(ULP_PREPROCESSED) \
$(ULP_ELF) $(ULP_BIN) \
@@ -91,6 +91,6 @@ COMPONENT_EXTRA_CLEAN := $(ULP_OBJECTS) \
$(ULP_DEP) \
$(ULP_LISTINGS)
COMPONENT_EMBED_FILES := $(COMPONENT_BUILD_DIR)/$(ULP_BIN)
COMPONENT_ADD_LDFLAGS := -l$(COMPONENT_NAME) -T $(COMPONENT_BUILD_DIR)/$(ULP_EXPORTS_LD)
COMPONENT_EXTRA_INCLUDES := $(COMPONENT_BUILD_DIR)
COMPONENT_EMBED_FILES += $(COMPONENT_BUILD_DIR)/$(ULP_BIN)
COMPONENT_ADD_LDFLAGS += -l$(COMPONENT_NAME) -T $(COMPONENT_BUILD_DIR)/$(ULP_EXPORTS_LD)
COMPONENT_EXTRA_INCLUDES += $(COMPONENT_BUILD_DIR)

View File

@@ -17,6 +17,7 @@
#include <stddef.h>
#include <stdlib.h>
#include "esp_err.h"
#include "soc/soc.h"
#ifdef __cplusplus
extern "C" {
@@ -857,7 +858,7 @@ esp_err_t ulp_process_macros_and_load(uint32_t load_addr, const ulp_insn_t* prog
* 3. TEXT_SIZE, size of .text section (2 bytes)
* 4. DATA_SIZE, size of .data section (2 bytes)
* 5. BSS_SIZE, size of .bss section (2 bytes)
* 6. (TEXT_OFFSET - 16) bytes of arbitrary data (will not be loaded into RTC memory)
* 6. (TEXT_OFFSET - 12) bytes of arbitrary data (will not be loaded into RTC memory)
* 7. .text section
* 8. .data section
*

View File

@@ -1 +1,11 @@
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
ULP_APP_NAME = ulp_test
ULP_S_SOURCES = $(addprefix $(COMPONENT_PATH)/ulp/, \
test_jumps.S \
)
ULP_EXP_DEP_OBJECTS := test_ulp_as.o
include $(IDF_PATH)/components/ulp/component_ulp_common.mk
COMPONENT_ADD_LDFLAGS += -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

View File

@@ -0,0 +1,25 @@
#include <unistd.h>
#include "unity.h"
#include "soc/rtc_cntl_reg.h"
#include "esp32/ulp.h"
#include "ulp_test.h"
extern const uint8_t ulp_test_bin_start[] asm("_binary_ulp_test_bin_start");
extern const uint8_t ulp_test_bin_end[] asm("_binary_ulp_test_bin_end");
TEST_CASE("jumps condition", "[ulp]")
{
esp_err_t err = ulp_load_binary(0, ulp_test_bin_start,
(ulp_test_bin_end - ulp_test_bin_start) / sizeof(uint32_t));
TEST_ESP_OK(err);
REG_CLR_BIT(RTC_CNTL_INT_RAW_REG, RTC_CNTL_ULP_CP_INT_RAW);
TEST_ESP_OK(ulp_run(&ulp_test_jumps - RTC_SLOW_MEM));
usleep(10000);
TEST_ASSERT_NOT_EQUAL(0, REG_GET_BIT(RTC_CNTL_INT_RAW_REG, RTC_CNTL_ULP_CP_INT_RAW));
TEST_ASSERT_EQUAL(0, ulp_jumps_fail & UINT16_MAX);
TEST_ASSERT_EQUAL(1, ulp_jumps_pass & UINT16_MAX);
}

View File

@@ -0,0 +1,101 @@
#include "soc/rtc_cntl_reg.h"
#include "soc/rtc_io_reg.h"
#include "soc/soc_ulp.h"
.bss
.global jumps_pass
jumps_pass:
.long 0
.global jumps_fail
jumps_fail:
.long 0
.text
.global test_jumps
test_jumps:
/* tests for LT (less than) condition */
stage_rst /* cnt = 0 */
jumps test_fail, 0, LT /* 0 < 0: false, should not jump */
jumps 1f, 1, LT /* 0 < 1: true, should jump */
jump test_fail
1:
stage_inc 2 /* cnt = 2 */
jumps 1f, 3, LT /* 2 < 1: true */
jump test_fail
1:
jumps test_fail, 1, LT /* 2 < 1: false */
jumps test_fail, 2, LT /* 2 < 2: false */
/* tests for LE (less or equal) condition */
stage_rst /* cnt = 0 */
jumps 1f, 0, LE /* 0 <= 0: true */
jump test_fail
1:
jumps 1f, 1, LE /* 0 <= 1: true */
jump test_fail
1:
stage_inc 2 /* cnt = 2 */
jumps test_fail, 1, LE /* 2 <= 1: false */
/* tests for EQ (equal) condition */
stage_rst /* cnt = 0 */
jumps 1f, 0, EQ /* 0 = 0: true */
jump test_fail
1:
jumps test_fail, 1, EQ /* 0 = 1: false */
stage_inc 1 /* cnt = 1 */
jumps test_fail, 0, EQ /* 1 = 0: false */
jumps test_fail, 2, EQ /* 1 = 2: false */
jumps 1f, 1, EQ /* 1 = 1: true */
1:
/* tests for GE (greater or equal) condition */
stage_rst /* cnt = 0 */
jumps 1f, 0, GE /* 0 >= 0: true */
jump test_fail
1:
jumps test_fail, 1, GE /* 0 >= 1: false */
stage_inc 1 /* cnt = 1 */
jumps 1f, 0, GE /* 1 >= 0: true */
jump test_fail
1:
jumps 1f, 1, GE /* 1 >= 1: true */
jump test_fail
1:
jumps test_fail, 2, GE /* 1 >= 2: false */
/* tests for GT (greater than) condition */
stage_rst /* cnt = 0 */
jumps test_fail, 0, GT /* 0 > 0: false */
jumps test_fail, 1, GE /* 0 > 1: false */
stage_inc 1 /* cnt = 1 */
jumps 1f, 0, GT /* 1 > 0: true */
jump test_fail
1:
jumps test_fail, 1, GT /* 1 > 1: false */
jumps test_fail, 2, GT /* 1 > 2: false */
jump test_pass
test_fail:
move r0, jumps_fail
move r1, 1
st r1, r0, 0
jump done
test_pass:
move r0, jumps_pass
move r1, 1
st r1, r0, 0
jump done
.global done
done:
wake
halt

View File

@@ -1,6 +1,14 @@
# Makefile for Sphinx documentation
#
# ************ IMPORTANT *****************
#
# ReadTheDocs DOES NOT USE THIS MAKEFILE,
# so any behaviour additions must be
# done via Sphinx Config not here
#
# ****************************************
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
@@ -9,7 +17,7 @@ BUILDDIR = _build
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don\'t have Sphinx installed, grab it from http://sphinx-doc.org/)
endif
# Internal variables.
@@ -19,10 +27,10 @@ ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) -w
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext dependencies version-specific-includes
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo "Please use \`make <target>\' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@@ -44,7 +52,7 @@ help:
@echo " xml to make Docutils-native XML files"
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@echo " doctest to run all doctests embedded in the documentation (if enabled) "
clean:
rm -rf $(BUILDDIR)/*

BIN
docs/_static/choose_version.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -15,8 +15,8 @@ Installing the toolchain
ULP coprocessor code is written in assembly and compiled using the `binutils-esp32ulp toolchain`_.
1. Download the toolchain using the links listed on this page:
https://github.com/espressif/binutils-esp32ulp/wiki#downloads
1. Download pre-built binaries of the latest toolchain release from:
https://github.com/espressif/binutils-esp32ulp/releases.
2. Extract the toolchain into a directory, and add the path to the ``bin/`` directory of the toolchain to the ``PATH`` environment variable.
@@ -134,7 +134,7 @@ Each ULP program is embedded into the ESP-IDF application as a binary blob. Appl
Once the program is loaded into RTC memory, application can start it, passing the address of the entry point to ``ulp_run`` function::
ESP_ERROR_CHECK( ulp_run((&ulp_entry - RTC_SLOW_MEM) / sizeof(uint32_t)) );
ESP_ERROR_CHECK( ulp_run(&ulp_entry - RTC_SLOW_MEM) );
.. doxygenfunction:: ulp_run

1830
docs/api-guides/ulp_instruction_set.rst Executable file → Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -32,6 +32,15 @@ os.system("python gen-dxd.py")
# Generate 'kconfig.inc' file from components' Kconfig files
os.system("python gen-kconfig-doc.py > _build/inc/kconfig.inc")
# Generate version-related includes
#
# (Note: this is in a function as it needs to access configuration to get the language)
def generate_version_specific_includes(app):
print("Generating version-specific includes...")
if os.system('python gen-version-specific-includes.py en _build/inc'):
raise RuntimeError('gen-version-specific-includes.py failed')
# http://stackoverflow.com/questions/12772927/specifying-an-online-image-in-sphinx-restructuredtext-format
#
suppress_warnings = ['image.nonlocal_uri']
@@ -314,3 +323,9 @@ if not on_rtd: # only import and set the theme if we're building docs locally
# otherwise, readthedocs.org uses their theme by default, so no need to specify it
# Override RTD CSS theme to introduce the theme corrections
# https://github.com/rtfd/sphinx_rtd_theme/pull/432
def setup(app):
app.add_stylesheet('theme_overrides.css')
generate_version_specific_includes(app)

View File

@@ -0,0 +1,140 @@
#!/usr/bin/env python
#
# Python script to generate ReSTructured Text .inc snippets
# with version-based content for this IDF version
import subprocess
import os
import sys
import re
TEMPLATES = {
"en" : {
"git-clone" : {
"template" : """
To obtain a local copy: open terminal, navigate to the directory you want to put ESP-IDF, and clone the repository using ``git clone`` command::
cd ~/esp
git clone %(clone_args)s--recursive https://github.com/espressif/esp-idf.git
ESP-IDF will be downloaded into ``~/esp/esp-idf``.
.. note::
%(extra_note)s
.. note::
%(zipfile_note)s
"""
,"master" : 'This command will clone the master branch, which has the latest development ("bleeding edge") version of ESP-IDF. It is fully functional and updated on weekly basis with the most recent features and bugfixes.'
,"branch" : 'The ``git clone`` option ``-b %s`` tells git to clone the %s in the ESP-IDF repository corresponding to this version of the documentation.'
,"zipfile" : {
"stable" : 'As a fallback, it is also possible to download a zip file of this stable release from the `Releases page`_. Do not download the "Source code" zip file(s) generated automatically by GitHub, they do not work with ESP-IDF.'
,"unstable" : 'GitHub\'s "Download zip file" feature does not work with ESP-IDF, a ``git clone`` is required. As a fallback, `Stable version`_ can be installed without Git.'
}, # zipfile
}, # git-clone
"version-note" : {
"master" : """
.. note::
This is documentation for the master branch (latest version) of ESP-IDF. This version is under continual development. `Stable version`_ documentation is available, as well as other :doc:`/versions`.
"""
,"stable" : """
.. note::
This is documentation for stable version %s of ESP-IDF. Other :doc:`/versions` are also available.
"""
,"branch" : """
.. note::
This is documentation for %s ``%s`` of ESP-IDF. Other :doc:`/versions` are also available.
"""
}, # version-note
}, # en
}
def main():
if len(sys.argv) != 3:
print("Usage: gen-git-clone.py <language> <output file path>")
sys.exit(1)
language = sys.argv[1]
out_dir = sys.argv[2]
if not os.path.exists(out_dir):
print("Creating directory %s" % out_dir)
os.mkdir(out_dir)
template = TEMPLATES[language]
version, ver_type, is_stable = get_version()
write_git_clone_inc(template["git-clone"], out_dir, version, ver_type, is_stable)
write_version_note(template["version-note"], out_dir, version, ver_type, is_stable)
print("Done")
def write_git_clone_inc(template, out_dir, version, ver_type, is_stable):
zipfile = template["zipfile"]
if version == "master":
args = {
"clone_args" : "",
"extra_note" : template["master"],
"zipfile_note" : zipfile["unstable"]
}
else:
args = {
"clone_args" : "-b %s " % version,
"extra_note" : template["branch"] % (version, ver_type),
"zipfile_note" : zipfile["stable"] if is_stable else zipfile["unstable"]
}
out_file = os.path.join(out_dir, "git-clone.inc")
with open(out_file, "w") as f:
f.write(template["template"] % args)
print("%s written" % out_file)
def write_version_note(template, out_dir, version, ver_type, is_stable):
if version == "master":
content = template["master"]
elif ver_type == "tag" and is_stable:
content = template["stable"] % version
else:
content = template["branch"] % (ver_type, version)
out_file = os.path.join(out_dir, "version-note.inc")
with open(out_file, "w") as f:
f.write(content)
print("%s written" % out_file)
def get_version():
"""
Returns a tuple of (name of branch/tag, type branch/tag, is_stable)
"""
# Trust what RTD says our version is, if it is set
version = os.environ.get("READTHEDOCS_VERSION", None)
if version == "latest":
return ("master", "branch", False)
# Otherwise, use git to look for a tag
try:
tag = subprocess.check_output(["git", "describe", "--tags", "--exact-match"]).strip()
is_stable = re.match(r"v[0-9\.]+$", tag) is not None
return (tag, "tag", is_stable)
except subprocess.CalledProcessError:
pass
# No tag, look for a branch
refs = subprocess.check_output(["git", "for-each-ref", "--points-at", "HEAD", "--format", "%(refname)"])
print("refs:\n%s" % refs)
refs = refs.split("\n")
# Note: this looks for branches in 'origin' because GitLab CI doesn't check out a local branch
branches = [ r.replace("refs/remotes/origin/","").strip() for r in refs if r.startswith("refs/remotes/origin/") ]
if len(branches) == 0:
# last resort, return the commit (may happen on Gitlab CI sometimes, unclear why)
return (subprocess.check_output(["git", "rev-parse", "--short", "HEAD"]).strip(), "commit", False)
if "master" in branches:
return ("master", "branch", False)
else:
return (branches[0], "branch", False) # take whatever the first branch is
if __name__ == "__main__":
main()

View File

@@ -4,6 +4,7 @@ Get Started
This document is intended to help users set up the software environment for developement of applications using hardware based on the Espressif ESP32. Through a simple example we would like to illustrate how to use ESP-IDF (Espressif IoT Development Framework), including the menu based configuration, compiling the ESP-IDF and firmware download to ESP32 boards.
.. include:: /_build/inc/version-note.inc
Introduction
============
@@ -113,19 +114,18 @@ Get ESP-IDF
.. highlight:: bash
Besides the toolchain (that contains programs to compile and build the application), you also need ESP32 specific API / libraries. They are provided by Espressif in `ESP-IDF repository <https://github.com/espressif/esp-idf>`_. To get it, open terminal, navigate to the directory you want to put ESP-IDF, and clone it using ``git clone`` command::
Besides the toolchain (that contains programs to compile and build the application), you also need ESP32 specific API / libraries. They are provided by Espressif in `ESP-IDF repository <https://github.com/espressif/esp-idf>`_.
cd ~/esp
git clone --recursive https://github.com/espressif/esp-idf.git
.. include:: /_build/inc/git-clone.inc
ESP-IDF will be downloaded into ``~/esp/esp-idf``.
Consult :doc:`/versions` for information about which version of ESP-IDF to use in a given situation.
.. note::
Do not miss the ``--recursive`` option. If you have already cloned ESP-IDF without this option, run another command to get all the submodules::
cd ~/esp/esp-idf
git submodule update --init
git submodule update --init --recursive
.. _get-started-setup-path:
@@ -299,23 +299,9 @@ Updating ESP-IDF
After some time of using ESP-IDF, you may want to update it to take advantage of new features or bug fixes. The simplest way to do so is by deleting existing ``esp-idf`` folder and cloning it again, exactly as when doing initial installation described in sections :ref:`get-started-get-esp-idf`.
Another solution is to update only what has changed. This method is useful if you have slow connection to the GiHub. To do the update run the following commands::
If downloading to a new path, remember to :doc:`add-idf_path-to-profile` so that the toolchain scripts know where to find the ESP-IDF in its release specific location.
cd ~/esp/esp-idf
git pull
git submodule update --init --recursive
The ``git pull`` command is fetching and merging changes from ESP-IDF repository on GitHub. Then ``git submodule update --init --recursive`` is updating existing submodules or getting a fresh copy of new ones. On GitHub the submodules are represented as links to other repositories and require this additional command to get them onto your PC.
If you would like to use specific release of ESP-IDF, e.g. `v2.1`, run::
cd ~/esp
git clone https://github.com/espressif/esp-idf.git esp-idf-v2.1
cd esp-idf-v2.1/
git checkout v2.1
git submodule update --init --recursive
After that remember to :doc:`add-idf_path-to-profile`, so the toolchain scripts know where to find the ESP-IDF in it's release specific location.
Another solution is to update only what has changed. :ref:`The update procedure depends on the version of ESP-IDF you are using <updating>`.
Related Documents
@@ -330,3 +316,7 @@ Related Documents
eclipse-setup
idf-monitor
toolchain-setup-scratch
.. _Stable version: https://docs.espressif.com/projects/esp-idf/en/stable/
.. _Releases page: https://github.com/espressif/esp-idf/releases

View File

@@ -41,6 +41,7 @@ This is the documentation for Espressif IoT Development Framework (`esp-idf <htt
H/W Reference <hw-reference/index>
API Guides <api-guides/index>
Contribute <contribute/index>
Versions <versions>
Resources <resources>
Copyrights <COPYRIGHT>
About <about>

View File

@@ -6,9 +6,9 @@ from repo_util import run_cmd_get_output
def get_github_rev():
path = run_cmd_get_output('git rev-parse --short HEAD')
tag = run_cmd_get_output('git describe --exact-match')
print 'Git commit ID: ', path
print ('Git commit ID: ', path)
if len(tag):
print 'Git tag: ', tag
print ('Git tag: ', tag)
path = tag
return path

178
docs/versions.rst Normal file
View File

@@ -0,0 +1,178 @@
ESP-IDF Versions
================
The ESP-IDF GitHub repository is updated regularly, especially on the "master branch" where new development happens. There are also stable releases which are recommended for production use.
Releases
--------
Documentation for the current stable version can always be found at this URL:
https://docs.espressif.com/projects/esp-idf/en/stable/
Documentation for the latest version ("master branch") can always be found at this URL:
https://docs.espressif.com/projects/esp-idf/en/latest/
The full history of releases can be found on the GitHub repository `Releases page`_. There you can find release notes, links to each version of the documentation, and instructions for obtaining each version.
Documentation for all releases can also be found in the HTML documentation by clicking the "versions" pop up in the bottom-left corner of the page. You can use this popup to switch between versions of the documentation.
.. image:: _static/choose_version.png
Which Version Should I Start With?
----------------------------------
- For production purposes, use the `current stable version`_. Stable versions have been manually tested, and are updated with "bugfix releases" which fix bugs without changing other functionality (see `Versioning Scheme`_ for more details).
- For prototyping, experimentation or for developing new ESP-IDF features, use the `latest version (master branch in Git) <https://docs.espressif.com/projects/esp-idf/en/latest/>`_. The latest version in the master branch has all the latest features and has passed automated testing, but has not been completely manually tested ("bleeding edge").
- If a required feature is not yet available in a stable release, but you don't want to use the master branch, it is possible to check out a pre-release version or a release branch. It is recommended to start from a stable version and then follow the instructions for :ref:`updating-pre-release` or :ref:`updating-release-branch`.
See :ref:`updating` if you already have a local copy of ESP-IDF and wish to update it.
Versioning Scheme
-----------------
ESP-IDF uses `Semantic Versioning <http://semver.org/>`_. This means:
- Major Releases like ``v3.0`` add new functionality and may change functionality. This includes removing deprecated functionality.
When updating to a new major release (for example, from ``v2.1`` to ``v3.0``), some of your project's code may need updating and functionality will need to be re-tested. The release notes on the `Releases page`_ include lists of Breaking Changes to refer to.
- Minor Releases like ``v3.1`` add new functionality and fix bugs but will not change or remove documented functionality, or make incompatible changes to public APIs.
If updating to a new minor release (for example, from ``v3.0`` to ``v3.1``) then none of your project's code should need updating, but you should re-test your project. Pay particular attention to items mentioned in the release notes on the `Releases page`_.
- Bugfix Releases like ``v3.0.1`` only fix bugs and do not add new functionality.
If updating to a new bugfix release (for example, from ``v3.0`` to ``v3.0.1``), you should not need to change any code in your project and should only need to re-test functionality relating directly to bugs listed in the release notes on the `Releases page`_.
Checking The Current Version
----------------------------
The local ESP-IDF version can be checked using git::
cd $IDF_PATH
git describe --tags --dirty
The version is also compiled into the firmware and can be accessed (as a string) via the macro ``IDF_VER``. The default ESP-IDF bootloader will print the version on boot (these versions in code will not always update, it only changes if that particular source file is recompiled).
Examples of ESP-IDF versions:
============================ ==================================================
Version String Meaning
============================ ==================================================
``v3.2-dev-306-gbeb3611ca`` Master branch pre-release, in development for
version 3.2. 306 commits after v3.2 development
started. Commit identifier ``beb3611ca``.
``v3.0.2`` Stable release, tagged ``v3.0.2``.
``v3.1-beta1-75-g346d6b0ea`` Beta version in development (on a
:ref:`release branch <updating-release-branch>`).
75 commits after ``v3.1-beta1`` pre-release tag.
Commit identifier ``346d6b0ea``.
``v3.0.1-dirty`` Stable release, tagged ``v3.0.1``.
There are modifications in the local ESP-IDF
directory ("``dirty``").
============================ ==================================================
Git Workflow
------------
The development (Git) workflow of the Espressif ESP-IDF team is:
- New work is always added on the master branch (latest version) first. The ESP-IDF version on ``master`` is always tagged with ``-dev`` (for "in development"), for example ``v3.1-dev``.
- Changes are first added to an internal Git repository for code review and testing, but are pushed to GitHub after automated testing passes.
- When a new version (developed on ``master``) becomes feature complete and "beta" quality, a new branch is made for the release, for example ``release/v3.1``. A pre-release tag is also created, for example ``v3.1-beta1``. You can see a full `list of branches`_ and a `list of tags`_ on GitHub. Beta pre-releases have release notes which may include a significant number of Known Issues.
- As testing of the beta version progresses, bug fixes will be added to both the ``master`` branch and the release branch. New features (for the next release) may start being added to ``master`` at the same time.
- Once testing is nearly complete a new release candidate is tagged on the release branch, for example ``v3.1-rc1``. This is still a pre-release version.
- If no more significant bugs are found or reported then the final Major or Minor Version is tagged, for example ``v3.1``. This version appears on the `Releases page`_.
- As bugs are reported in released versions, the fixes will continue to be committed to the same release branch.
- Regular bugfix releases are made from the same release branch. After manual testing is complete, a bugfix release is tagged (i.e. ``v3.1.1``) and appears on the `Releases page`_.
.. _updating:
Updating ESP-IDF
----------------
Updating ESP-IDF depends on which version(s) you wish to follow:
- :ref:`updating-stable-releases` is recommended for production use.
- :ref:`updating-master` is recommended for latest features, development use, and testing.
- :ref:`updating-release-branch` is a compromise between these two.
.. note:: These guides assume you already have a local copy of ESP-IDF. To get one, follow the :doc:`Getting Started </get-started/index>` guide for any ESP-IDF version.
.. _`updating-stable-releases`:
Updating to Stable Release
^^^^^^^^^^^^^^^^^^^^^^^^^^
To update to new ESP-IDF releases (recommended for production use), this is the process to follow:
- Check the `Releases page`_ regularly for new releases.
- When a bugfix release for a version you are using is released (for example if using ``v3.0.1`` and ``v3.0.2`` is available), check out the new bugfix version into the existing ESP-IDF directory::
cd $IDF_PATH
git fetch
git checkout vX.Y.Z
git submodule update --init --recursive
- When major or minor updates are released, check the Release Notes on the releases page and decide if you would like to update or to stay with your existing release. Updating is via the same Git commands shown above.
.. note:: If you installed the stable release via zip file rather than using git, it may not be possible to change versions this way. In this case, update by downloading a new zip file and replacing the entire ``IDF_PATH`` directory with its contents.
.. _`updating-pre-release`:
Updating to a Pre-Release Version
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
It is also possible to ``git checkout`` a tag corresponding to a pre-release version or release candidate, the process is the same as :ref:`updating-stable-releases`.
Pre-release tags are not always found on the `Releases page`_. Consult the `list of tags`_ on GitHub for a full list. Caveats for using a pre-release are similar to :ref:`updating-release-branch`.
.. _`updating-master`:
Updating to Master Branch
^^^^^^^^^^^^^^^^^^^^^^^^^
.. note:: Using Master branch means living "on the bleeding edge" with the latest ESP-IDF code.
To use the latest version on the ESP-IDF master branch, this is the process to follow:
- Check out the master branch locally::
cd $IDF_PATH
git checkout master
git pull
git submodule update --init --recursive
- Periodically, re-run ``git pull`` to pull the latest version of master. Note that you may need to change your project or report bugs after updating master branch.
- To switch from ``master`` to a release branch or stable version, run ``git checkout`` as shown in the other sections.
.. important:: It is strongly recommended to regularly run ``git pull`` and then ``git submodule update --init --recursive`` so a local copy of ``master`` does not get too old. Arbitrary old master branch revisions are effectively unsupportable "snapshots" that may have undocumented bugs. For a semi-stable version, try :ref:`updating-release-branch` instead.
.. _`updating-release-branch`:
Updating to a Release Branch
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In stability terms, using a release branch is part-way between using ``master`` branch and only using stable releases. A release branch is always beta quality or better, and receives bug fixes before they appear in each stable release.
You can find a `list of branches`_ on GitHub.
For example, to follow the branch for ESP-IDF v3.1, including any bugfixes for future releases like ``v3.1.1``, etc::
cd $IDF_PATH
git fetch
git checkout release/v3.1
git pull
git submodule --update --init --recursive
Each time you ``git pull`` this branch, ESP-IDF will be updated with fixes for this release.
.. note:: The is no dedicated documentation for release branches. It is recommended to use the documentation for the closest version to the branch which is currently checked out.
.. _`Releases page`: http://github.com/espressif/esp-idf/releases
.. _`list of branches`: https://github.com/espressif/esp-idf/branches
.. _`list of tags`: https://github.com/espressif/esp-idf/tags
.. _`current stable version`: https://docs.espressif.com/projects/esp-idf/en/stable/

View File

@@ -324,6 +324,9 @@ static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param
(bd_addr[4] << 8) + bd_addr[5]);
ESP_LOGI(GATTS_TABLE_TAG, "address type = %d", param->ble_security.auth_cmpl.addr_type);
ESP_LOGI(GATTS_TABLE_TAG, "pair status = %s",param->ble_security.auth_cmpl.success ? "success" : "fail");
if(!param->ble_security.auth_cmpl.success) {
ESP_LOGI(GATTS_TABLE_TAG, "fail reason = 0x%x",param->ble_security.auth_cmpl.fail_reason);
}
show_bonded_devices();
break;
}

View File

@@ -145,6 +145,7 @@ static void http2_task(void *args)
}
sh2lib_free(&hd);
vTaskDelete(NULL);
}
static esp_err_t event_handler(void *ctx, system_event_t *event)

View File

@@ -80,7 +80,7 @@ static void init_ulp_program()
REG_SET_FIELD(SENS_ULP_CP_SLEEP_CYC0_REG, SENS_SLEEP_CYCLES_S0, 3095);
/* Start the program */
err = ulp_run((&ulp_entry - RTC_SLOW_MEM) / sizeof(uint32_t));
err = ulp_run(&ulp_entry - RTC_SLOW_MEM);
ESP_ERROR_CHECK(err);
}

View File

@@ -87,6 +87,6 @@ static void start_ulp_program()
ulp_sample_counter = 0;
/* Start the program */
esp_err_t err = ulp_run((&ulp_entry - RTC_SLOW_MEM) / sizeof(uint32_t));
esp_err_t err = ulp_run(&ulp_entry - RTC_SLOW_MEM);
ESP_ERROR_CHECK(err);
}

14
tools/ci/push_to_github.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/bin/bash
# gitlab-ci script to push current tested revision (tag or branch) to github
set -ex
if [ -n "${CI_COMMIT_TAG}" ]; then
# for tags
git push github "${CI_COMMIT_TAG}"
else
# for branches
git push github "${CI_COMMIT_SHA}:refs/heads/${CI_COMMIT_REF_NAME}"
fi

49
tools/ci/setup_python.sh Normal file
View File

@@ -0,0 +1,49 @@
#! /bin/bash
# Regexp for matching job names which are incompatible with Python 3
py3_incomp='assign_test|UT|IT'
if [ -z ${PYTHON_VER+x} ] || [[ $CI_JOB_NAME =~ $py3_incomp ]]; then
# Use this version of the Python interpreter if it was not defined before or
# the given job is not compatible with Python 3
PYTHON_VER=2.7.15
fi
if [ -f /opt/pyenv/activate ];
then
source /opt/pyenv/activate
pyenv global $PYTHON_VER || {
echo 'Python' $PYTHON_VER 'is not installed.'
INSTALLED_PY_VERS=$(pyenv versions --bare)
while [ ${#PYTHON_VER} -gt 0 ]
do
echo 'Tring to locate a match for' $PYTHON_VER
for ver in ${INSTALLED_PY_VERS[@]}
do
if [[ $ver == $PYTHON_VER* ]];
then
pyenv global $ver
break 2
fi
done
# Removing last character and trying to find some match.
# For example, if 3.4.8 was selected but isn't installed then it will try to
# find some other installed 3.4.X version, and then some 3.X.X version.
PYTHON_VER=${PYTHON_VER: : -1}
done
}
python --version || {
echo 'No matching Python interpreter is found!'
exit 1
}
elif command -v python -V 1>/dev/null 2>&1;
then
python --version
echo 'No /opt/pyenv/activate exists and Python from path is used.'
else
echo 'No /opt/pyenv/activate exists and no Python interpreter is found!'
exit 1
fi