Compare commits

...

281 Commits

Author SHA1 Message Date
e9cf9e2978 Merge branch 'bugfix/e8192_and_assert_param_bt1551' into 'release/v4.3'
Modify E8192 ELx 200 ELx40 log level to LOGD

See merge request espressif/esp-idf!12977
2021-04-14 16:23:57 +00:00
6463dd9630 Merge branch 'bugfix/esp32c3_deep_sleep_gpio_wakeup_issue_v4.3' into 'release/v4.3'
backport v4.3: fix deep sleep gpio wakeup fail issue

See merge request espressif/esp-idf!13140
2021-04-14 16:02:32 +00:00
c9f1b55287 Merge branch 'bugfix/fix_wifi_issue_for_pm_disconnected_v4.3' into 'release/v4.3'
esp_wifi: fix some issue about wifi pm (backport to v4.3)

See merge request espressif/esp-idf!13138
2021-04-14 14:36:56 +00:00
e16ec9a574 modify E8192 ELx200 ELx40 log level to LOGD 2021-04-14 19:33:03 +08:00
16cf160d57 deep sleep: fix sleep gpio wakeup fail issue 2021-04-14 15:40:13 +08:00
58160d46c6 esp_wifi: fix some issue about wifi pm (backport to v4.3) 2021-04-14 14:44:19 +08:00
776906dc84 Merge branch 'bugfix/fix_some_pm_issue_v4.3' into 'release/v4.3'
esp_pm: fix an issue and add an interface (backport to v4.3)

See merge request espressif/esp-idf!13123
2021-04-14 06:43:17 +00:00
bd03a0e66a esp_pm: fix an issue and add an interface (backport to v4.3) 2021-04-13 17:16:23 +08:00
693aaef039 Merge branch 'bugfix/enable_gpio18_gpio19_esp32c3_v4.3' into 'release/v4.3'
gpio: Disable USB JTAG when setting pins 18 and 19 as GPIOs on ESP32C3 (backport v4.3)

See merge request espressif/esp-idf!13112
2021-04-13 07:40:00 +00:00
7703fcbd8d Merge branch 'bugfix/silent_asserts_v4.3' into 'release/v4.3'
freertos/lw ip: Support silent assertions (v4.3)

See merge request espressif/esp-idf!13011
2021-04-13 04:30:09 +00:00
9a7deae742 Merge branch 'bugfix/reduce_the_consumption_of_touch_sensor_during_deep_sleep_backport_v4.3' into 'release/v4.3'
bugfix: reduce the consumption of touch sensor during deep sleep (backport v4.3)

See merge request espressif/esp-idf!12869
2021-04-13 04:16:01 +00:00
84dc42c4b0 gpio: Disable USB JTAG when setting pins 18 and 19 as GPIOs on ESP32C3
When `DIS_USB_JTAG` eFuse is NOT burned (`False`), it is not possible
to set pins 18 and 19 as GPIOs. This commit solves this by manually
disabling USB JTAG when using pins 18 or 19.
The functions shall use `gpio_hal_iomux_func_sel` instead of
`PIN_FUNC_SELELECT`.
2021-04-12 17:45:06 +08:00
d7e680828a Merge branch 'feature/seperate_ipv6_function_from_ipv4_v4.3' into 'release/v4.3'
Add LWIP_IPV6 macro to strip IPv6 function (backport v4.3)

See merge request espressif/esp-idf!12998
2021-04-12 08:38:45 +00:00
da47503c14 Merge branch 'bugfix/deep_sleep_skip_verify_rtc_mem_heap_v4.3' into 'release/v4.3'
Fix bootloader "skip validate on exiting deep sleep" option if "use RTC memory as heap" is enabled (v4.3)

See merge request espressif/esp-idf!13096
2021-04-12 08:18:21 +00:00
e490fdafbe doc: Add description for CONFIG_LWIP_IPV6 in api-guides 2021-04-12 05:42:50 +00:00
94e3141a32 examples: Make tcp_server example support tcp keepalive function 2021-04-12 05:42:50 +00:00
fd34406960 examples: Use CONFIG_LWIP_IPV6 to strip tcp_server example 2021-04-12 05:42:50 +00:00
4544b709e5 lwip: Fix spelling issues in lwip_debug.c 2021-04-12 05:42:50 +00:00
a95c1c302d examples: Strip IPv6 function in example and use sockaddr_storage to replace sockaddr_in6 2021-04-12 05:42:50 +00:00
1ef91c72e2 components: Use CONFIG_LWIP_IPV6 to strip IPv6 function in components 2021-04-12 05:42:50 +00:00
90696dad89 lwip: Add LWIP_IPV6 macro to strip IPv6 function in LWIP component 2021-04-12 05:42:50 +00:00
e310fb1393 fix: reduce the consumption of touch sensor during deep sleep 2021-04-12 12:24:53 +08:00
71de11e89d Merge branch 'feature/esp32c3_memprot_test3_v4.3' into 'release/v4.3'
ESP32C3/ESP32S2: memprot API upgrade and test application (v4.3)

See merge request espressif/esp-idf!12942
2021-04-12 03:29:29 +00:00
bda9e1fda7 Merge branch 'bugfix/doxygen_input_file_bug_v4.3' into 'release/v4.3'
docs: fix doxygen compile warnings for doxygen 1.9.1 (v4.3)

See merge request espressif/esp-idf!13075
2021-04-12 00:46:11 +00:00
97df333a3b docs: fix doxygen compile warnings for doxygen 1.9.1
Newer versions of doxygen will give warnings for comments in
INPUT lists

Delete all comment lines to fix these warnings, our folder structure
stil gives an OK overview of what we are including
2021-04-12 08:46:06 +08:00
6dfff2fdbd esp32c3: memprot API upgrade and test application
Closes IDF-2641
2021-04-12 10:21:58 +10:00
2ed3e8b344 Merge branch 'bugfix/prefetch_invalid_v4.3' into 'release/v4.3'
soc: add dummy bytes to ensure instr prefetch always valid (v4.3)

See merge request espressif/esp-idf!12993
2021-04-09 14:49:07 +00:00
e4dd9053c2 Merge branch 'feature/secure_bootv2_c3_v4.3' into 'release/v4.3'
secure_boot_v2: Support SB_V2 for ESP32-C3 ECO3 (v4.3)

See merge request espressif/esp-idf!13062
2021-04-09 13:06:46 +00:00
ff5e0d0d38 Merge branch 'bugfix/calc_8m_freq_test_v4.3' into 'release/v4.3'
rtc: increase CI acceptance range for calc 8M test (v4.3)

See merge request espressif/esp-idf!13085
2021-04-09 13:06:36 +00:00
03b0540bc6 esp32s3: Reserve RTC memory in bootloader in the app linker script 2021-04-09 19:15:43 +10:00
17e30c9e89 esp32c3: Reserve RTC memory from bootloader in the app linker script 2021-04-09 19:15:43 +10:00
00cfcde385 bootloader: Fix "skip validate on exit deep sleep" when "Use RTC fast memory as heap" is enabled
RTC region used to store boot partition needs to remain reserved in the app.
2021-04-09 19:15:43 +10:00
0839fd08dd Merge branch 'bugfix/dport_init_min_stack_size_v4.3' into 'release/v4.3'
freertos: Increase minimum task stack size when stack smashing checker is enabled (backport v4.3)

See merge request espressif/esp-idf!12797
2021-04-09 09:14:25 +00:00
220f3d2198 rtc: increase CI acceptance range for calc 8M test 2021-04-09 15:06:11 +08:00
904933745b Merge branch 'bugfix/fix_esp_restart_crash_v4.3' into 'release/v4.3'
esp_hw_support: fix esp_restart crash (v4.3)

See merge request espressif/esp-idf!13072
2021-04-09 03:44:09 +00:00
ea4a8d5e4f esp_hw_support: fix esp_restart crash
Closes https://github.com/espressif/esp-idf/issues/6836
2021-04-09 09:30:03 +08:00
10cce6b74a unit-test-app(config): esp32c3 uses eco0 for UTs 2021-04-09 00:02:40 +08:00
e36e433519 Merge branch 'bugfix/fix_uart_handler_call_inline_func_v43' into 'release/v4.3'
Bugfix/fix uart handler call inline func (backport v4.3)

See merge request espressif/esp-idf!13003
2021-04-08 09:38:51 +00:00
76ff1724b3 Merge branch 'feature/remove_hspi_macor_on_chips_later_than_s2_v4.3' into 'release/v4.3'
spi: remove hspi macor on chips later than s2 (v4.3)

See merge request espressif/esp-idf!12956
2021-04-08 09:37:07 +00:00
9f1ae278e0 Merge branch 'feature/vdd_sdio_pd_configurable_v4.3' into 'release/v4.3'
system: add VDD_SDIO power domain configuration for light sleep (backport v4.3)

See merge request espressif/esp-idf!13028
2021-04-08 09:27:57 +00:00
54908d3a42 esp32c3: Default supported ESP32-C3 Revision ECO3 2021-04-08 15:09:14 +08:00
19b90e8ba9 docs: Adds secure_boot_v2 for ESP32-C3 ECO3 2021-04-08 14:35:35 +08:00
a5e27d73a5 secure_boot_v2: Adds support SB_V2 for ESP32-C3 ECO3 2021-04-08 14:35:35 +08:00
1e6a6ffa0d Merge branch 'bugfix/check_a_time_after_deepsleep_v4.3' into 'release/v4.3'
Fix esp32s2 timekeeping on deep sleep issue (v4.3)

See merge request espressif/esp-idf!13046
2021-04-08 01:14:44 +00:00
dbf2a64adb esp_hw_support: add test for rtc clk compensation 2021-04-07 06:40:28 +08:00
11970e65a1 newlib: persist rtc clk corrections 2021-04-07 06:40:28 +08:00
670b057b04 spi: remove HSPI macro on esp32c3 and esp32s3 2021-04-06 15:30:28 +08:00
ae3b4819da esp_system: add VDD_SDIO power domain configuration to documentation
Add a warning in `sleep_modes` doc page to explain how to keep
VDD_SDIO power domain ON.
2021-04-06 14:04:22 +08:00
b0684e8b3c esp_system: add VDD_SDIO power domain configuration for light sleep
VDD_SDIO power domain can now be configured for light sleep
by the application. It is now possible to keep the power domain
ON during light sleep, keeping the GPIOs connected to it powered.
The power domain will, by default be:
- Kept ON if CONFIG_ESP_SYSTEM_PD_FLASH is not set
- Turned OFF if not set

The application can still force it to be ON by calling
`esp_sleep_pd_config(ESP_PD_DOMAIN_VDDSDIO, ESP_PD_OPTION_ON);`
2021-04-06 14:01:38 +08:00
322cba0bf0 freertos: Add a small additional stack when optimization set to None
Fix for occasional crash on startup when DPORT task overwrites its stack during
context switch, otherwise.
2021-04-06 02:43:24 +00:00
f5c6595cb4 freertos: Increase minimum task stack size when stack smashing checker is enabled
Fixes issue with DPORT init task, this task uses minimum stack size and may not be
enough if stack smashing detection is set to Overall mode.

Also reworks the way we calculate minimum stack to allow for adding multiple
contributing factors.

Closes https://github.com/espressif/esp-idf/issues/6403
2021-04-06 02:43:24 +00:00
e9e2b68587 freertos: Use the standard assert() function for configASSERT
Unless the option for "assert and keep running" is enabled.

This means that silent asserts now work for FreeRTOS, and disabling asserts
now also disables them in FreeRTOS without needing a separate config change.

Related to https://github.com/espressif/esp-idf/issues/6306
2021-04-02 11:07:23 +11:00
73d40cb813 lwip: Support silent assertion configuration
If silent assert configuration is enabled, LWIP asserts are now 'silent' also.

Also updates KConfig to note that LWIP asserts are also disabled when asserts
are disabled globally (this was already the behaviour, but the config item
suggested otherwise.)

Progress towards https://github.com/espressif/esp-idf/issues/5873
2021-04-02 11:03:44 +11:00
bf6ddf2557 bootloader: Allow 'silent assert' config to work in bootloader
Requires adding the 'newlib' component to the bootloader project, for
platform_include header.
2021-04-02 11:03:21 +11:00
d761226f36 driver: fix uart handler in iram calls inline uart_ll_is_tx_idle 2021-04-01 09:56:56 +02:00
5036ec363b soc: add dummy bytes to ensure instr prefetch always valid
The CPU might prefetch instructions, which means it in some cases
will try to fetch instruction located after the last instruction in
flash.text.

Add dummy bytes to ensure fetching these wont result in an error,
 e.g. MMU exceptions
2021-04-01 10:23:44 +08:00
c724236623 Merge branch 'bugfix/close_tsen_when_close_phy_v4.3' into 'release/v4.3'
esp_wifi: close tsen when close phy (backport to v4.3)

See merge request espressif/esp-idf!12986
2021-04-01 02:17:57 +00:00
f7034e7767 Merge branch 'bugfix/dirent-riscv-header-4.3' into 'release/v4.3'
vfs: use sys/dirent.h from newlib (backport v4.3)

See merge request espressif/esp-idf!12752
2021-04-01 02:16:59 +00:00
7e75d7f748 Merge branch 'bugfix/aes_dma_completion_v4.3' into 'release/v4.3'
mbedtls: Fix AES dma completion race condition (v4.3)

See merge request espressif/esp-idf!12903
2021-04-01 02:15:30 +00:00
e5437afa7f Merge branch 'bugfix/ds_invalidate_assert_v4.3' into 'release/v4.3'
esp32s2 ds: Fix invalidating Digital Signature key from HMAC peripheral if assertions are disabled (v4.3)

See merge request espressif/esp-idf!12905
2021-03-31 22:56:13 +00:00
319eecc793 Merge branch 'doc/c3_system_api_v4.3' into 'release/v4.3'
docs: updated system api-reference chapters for C3 (v.4.3)

See merge request espressif/esp-idf!12892
2021-03-31 17:57:41 +00:00
d17923151b Merge branch 'bugfix/fix_esp32c3_hardware_bug_before_ECO3_v4.3' into 'release/v4.3'
backport v4.3: fix c3 hardware bug before ECO3 and optimizate bbpll config:

See merge request espressif/esp-idf!12988
2021-03-31 17:44:01 +00:00
0a0b3bb23f Merge branch 'bugfix/assert_when_tcp_send_data_for_v4.3' into 'release/v4.3'
lw-ip:bugfix for assert when tcp send data(backport4.3)

See merge request espressif/esp-idf!12980
2021-03-31 17:40:43 +00:00
2a5cf2c3e0 esp_wifi: close tsens when close phy (backport v4.3) 2021-03-31 21:04:29 +08:00
ae15a0cab8 Merge branch 'bugfix/add_beacon_timeout_event_v4.3' into 'release/v4.3'
esp_wifi: Add beacon timeout event (backport v4.3)

See merge request espressif/esp-idf!12974
2021-03-31 13:01:41 +00:00
0c7f286a87 fix c3 hardware bug before ECO3 and optimizate bbpll config:
1. deepsleep poweron reset bug in high temperature before ECO3;
2. brownout reset bug before ECO2;
3. bbpll voltage low bug before ECO3;
4. need xpd iph for xtal before ECO3;
2021-03-31 20:17:54 +08:00
3e26049a05 bugfix for assert when tcp send data 2021-03-31 16:45:45 +08:00
dece3abd9c esp_wifi: Fix some wifi bugs
1.Add beacon timeout event.
2.Update TBTT when rx probe respones after beacon timeout.
3.Fix ESPTouch v2 issues.
2021-03-31 14:21:49 +08:00
1af5bc2f7d Merge branch 'bugfix/esp32c3_light_sleep_gpio_reset_issue_v4.3' into 'release/v4.3'
backport v4.3: add software workaround for esp32c3 gpio reset issue

See merge request espressif/esp-idf!12751
2021-03-31 03:12:09 +00:00
278cfc2047 Merge branch 'doc/embed_example_v4.3' into 'release/v4.3'
doc: Update the link to an example that embeds a file (v4.3)

See merge request espressif/esp-idf!12655
2021-03-31 01:31:12 +00:00
1790aa6bc6 Merge branch 'bugfix/spi_slv_dual_boad_test_slv_fail_issue_4.3' into 'release/v4.3'
spi: spi slv dual boad test slv fail issue (4.3)

See merge request espressif/esp-idf!12958
2021-03-30 17:16:33 +00:00
b75a5fd03a Merge branch 'bugfix/adc_power_issue_4.3' into 'release/v4.3'
adc: fix adc power issue (v4.3)

See merge request espressif/esp-idf!12921
2021-03-30 17:15:09 +00:00
cbf2858450 Merge branch 'bugfix/support_esp32c3eco3_v4.3' into 'release/v4.3'
Bugfix/support esp32c3eco3 v4.3

See merge request espressif/esp-idf!12931
2021-03-30 15:15:06 +00:00
868c96c59f Merge branch 'bugfix/flash_suspend_restriction_v4.3' into 'release/v4.3'
spi_flash: make suspend off by default and add more information for using suspend(backport v4.3)

See merge request espressif/esp-idf!12932
2021-03-30 11:00:53 +00:00
60d5dcb000 spi_slave: enable spi slave dual board test on esp32c3 2021-03-30 17:16:16 +08:00
62787fc277 spi: update slv dual board test for ci due to no pullup resistor on io10 on c3 2021-03-30 17:11:23 +08:00
9e97133481 Support new section addr and wifi lib for ESP32C3-ECO3. 2021-03-30 16:05:13 +08:00
c9087c205b docs: updated system api-reference chapters for C3 2021-03-30 14:28:02 +08:00
736b87db6d Merge branch 'ci/ignore_check_link_result_v4.3' into 'release/v4.3'
CI: ignore result from check_doc_links (v4.3)

See merge request espressif/esp-idf!12782
2021-03-30 03:11:00 +00:00
c2eaa3d844 Merge branch 'bugfix/esp32c3_gdbinit_v4.3' into 'release/v4.3'
.gdbinit generation fix (ESP32C3) (v4.3)

See merge request espressif/esp-idf!12750
2021-03-30 03:10:22 +00:00
2a715c811b Merge branch 'bugfix/extern_c_decl_4.3' into 'release/v4.3'
[cxx]: fixed extern "C" declarations (backport v4.3)

See merge request espressif/esp-idf!12741
2021-03-30 03:09:46 +00:00
17aa9c5ec4 Merge branch 'bugfix/broken_virtualenv_v4.3' into 'release/v4.3'
tools: Reinstall virtualenv if it is broken (v4.3)

See merge request espressif/esp-idf!12951
2021-03-30 03:08:08 +00:00
c93211db62 tools: Reinstall virtualenv if it is broken
Closes https://github.com/espressif/esp-idf/issues/6656
2021-03-29 15:05:42 +02:00
be56456add light sleep: add software workaround for esp32c3 gpio reset issue 2021-03-29 15:06:23 +08:00
413bbe4de4 Merge branch 'bugfix/btdm_incorrectly_spelled_v4.3' into 'release/v4.3'
component/bt: fix Spelling mistakes(release v4.3)

See merge request espressif/esp-idf!12815
2021-03-29 05:07:57 +00:00
4906779d50 spi_flash: make suspend off by default and add more information for using suspend 2021-03-29 12:02:43 +08:00
7d5d57ec03 esptool: update to support flashing esp32c3 eco 3 2021-03-26 18:42:41 +08:00
67a1858bb1 esp32c3: Add support for building image with a minimum target revision 2021-03-26 18:29:53 +08:00
fb9de62f74 bugfix: keep wakeup state during csa 2021-03-26 18:29:10 +08:00
f48346f22f adc: apply adc power API to adc driver 2021-03-26 17:41:20 +08:00
79ce133ed7 Merge branch 'feature/support_esp32c3_aligenie_demo_v4.3' into 'release/v4.3'
ble_mesh: aligenie_demo: Add sdkconfig.defaults for esp32c3 (backport V4.3)

See merge request espressif/esp-idf!12428
2021-03-26 06:02:55 +00:00
a59a5cb2cc ble_mesh: aligenie_demo: Add sdkconfig.defaults for esp32c3 (backport V4.3) 2021-03-26 14:02:49 +08:00
2d26c24e3a Merge branch 'bugfix/clear_interrupt_in_touch_sensor_initialization_backport_v4.3' into 'release/v4.3'
fix: clear interrupt in touch sensor initialization (backport v4.3)

See merge request espressif/esp-idf!12758
2021-03-26 05:55:18 +00:00
2792c333bc Merge branch 'bugfix/freemodbus_fix_mbm_event_processing_v43' into 'release/v4.3'
freemodbuss: fix event processing after merge (backport v4.3)

See merge request espressif/esp-idf!12821
2021-03-26 05:52:59 +00:00
7c5e920c37 Merge branch 'feature/temp_v4.3' into 'release/v4.3'
temp_sensor: add calibration for esp32c3(backport v4.3)

See merge request espressif/esp-idf!12703
2021-03-26 05:51:47 +00:00
d4ac30a978 Merge branch 'fix/dont_disable_uart_dl_mode_by_default_v4.3' into 'release/v4.3'
bootloader/ ESP32_ECO3: Do not disable UART download mode by default (v4.3)

See merge request espressif/esp-idf!12907
2021-03-26 05:50:48 +00:00
2596c7e2cc Merge branch 'nimble/mbedtls_aes_free_dma_v4.3' into 'release/v4.3'
NimBLE: Free AES context after use by calling `mbedtls_free_aes` (Needed for C3) (v4.3)

See merge request espressif/esp-idf!12917
2021-03-26 05:47:50 +00:00
e6b7c933d5 adc: rename adc examples according to hw feature and usage 2021-03-26 13:26:19 +08:00
8fe99aff96 adc: add implementation of missed public API
Added ``adc1_pad_get_io_num``, ``adc2_pad_get_io_num`` and
``adc_vref_to_gpio``.
2021-03-26 13:26:19 +08:00
4866027391 adc: update adc programming guide to avoid build fail 2021-03-26 13:26:19 +08:00
a6ed4611a2 adc: update lock scope on esp32c3 2021-03-26 13:26:19 +08:00
d457641f90 adc: rename adc related examples 2021-03-26 13:26:19 +08:00
1509264f2e adc: add pm_lock to adc driver on esp32c3 2021-03-26 13:26:19 +08:00
271b84f5b6 adc: update adc header files on c3 2021-03-26 13:26:19 +08:00
f1be501271 adc: refactor adc single read api on esp32c3 2021-03-26 13:26:19 +08:00
ea20966c29 adc: seperate hal layer and driver layer 2021-03-26 13:26:18 +08:00
f25c996b06 adc: remove unused functions on esp32c3 2021-03-26 13:26:18 +08:00
745bb2123f Merge branch 'bugfix/btdm_add_controller_support_RPA_4.3' into 'release/v4.3'
Add option to enable/disable esp32 controller RPA (backport v4.3)

See merge request espressif/esp-idf!12886
2021-03-26 04:21:04 +00:00
143bb1edf4 Merge branch 'bugfix/btdm_fix_multi-con_pair_failed_v4.3' into 'release/v4.3'
fix multi-connection pair failed (backport v4.3)

See merge request espressif/esp-idf!12885
2021-03-26 04:19:28 +00:00
f1737a630d Merge branch 'bugfix/btdm_synchronize_multiple_branch_of_bt_lib_v4.3' into 'release/v4.3'
Bugfix/btdm synchronize multiple branch of bt lib v4.3

See merge request espressif/esp-idf!12872
2021-03-26 04:15:52 +00:00
83087f15fa Merge branch 'feature/on_update_no_secure_boot_verify_only_one_sign_v4.3' into 'release/v4.3'
secure_boot: Only the first position of signature blocks is used to verify any update (v4.3)

See merge request espressif/esp-idf!12908
2021-03-26 03:18:42 +00:00
a9d1d44d4d NimBLE: Free AES context after use by calling mbedtls_free_aes
- Update NimBLE submodule to resolve issue observed while using mbedTLS as
  crypto stack during security exchanges.

Closes BT-1435, BT-1434
2021-03-25 18:43:49 +05:30
72b27f1782 components/bt: Synchronize multiple branch of bt lib 2021-03-25 15:58:42 +08:00
8e482c9423 components/bt: Fix assert without sw coexist enabled 2021-03-25 15:58:42 +08:00
1fb45977fa component/coex: Decouple Wi-Fi and bluetooth with coexist to reduce binary file size 2021-03-25 15:58:42 +08:00
257728feab Fix the bug of modem sleep which may lead to the crash issue "assert(-218959118,0)" 2021-03-25 15:58:22 +08:00
26d362040e secure_boot/SIGNED_ON_UPDATE_NO_SECURE_BOOT: Only the first position of signature blocks is used to verify any update 2021-03-25 15:40:24 +08:00
f6a794cf51 bootloader/ ESP32_ECO3: Do not disable UART download mode by default 2021-03-25 10:32:37 +05:30
974db3016b esp32s2 ds: Fix invalidating Digital Signature key from HMAC peripheral if assertions are disabled 2021-03-25 15:34:26 +11:00
9c4c377f2d mbedtls tests: Add optional debug log output to AES stream tests 2021-03-25 15:28:45 +11:00
e6b8bc6ecb mbedtls aes dma: Fix bug where DMA would complete when the first output descriptor was done, not the last 2021-03-25 15:28:45 +11:00
718f296587 Merge branch 'bugfix/revert_esp_log_issue_4.3' into 'release/v4.3'
efuse: revert ESP_LOG to ESP_EARLY_LOG in src/esp_efuse_utility.c (4.3)

See merge request espressif/esp-idf!12794
2021-03-25 03:56:02 +00:00
6c74618bff Merge branch 'bugfix/fix_wrong_bit_order_of_ksz8041_v4.3' into 'release/v4.3'
eth_phy: fix wrong register bit order in ksz8041

See merge request espressif/esp-idf!12735
2021-03-24 18:08:37 +00:00
974f345316 * fixed generation of .gdbinit file (esp32c3 dbg issue) 2021-03-24 11:39:30 +00:00
zwj
f2ca74b139 add option to enable/disable esp32 controller RPA 2021-03-24 16:45:58 +08:00
zwj
ac8ea9e9e5 fix multi-connection pair failed 2021-03-24 16:44:45 +08:00
48890daab1 Merge branch 'bugfix/idf_size_total_size_without_bss_v4.3' into 'release/v4.3'
tools: Don't count BSS into the total image size (v4.3)

See merge request espressif/esp-idf!12575
2021-03-24 08:12:27 +00:00
f1aabb2894 Merge branch 'bugfix/ble_tx_power_mapping_for_v4.3' into 'release/v4.3'
Bugfix/ble tx power mapping for v4.3

See merge request espressif/esp-idf!12870
2021-03-24 08:07:23 +00:00
cc8ef3660a components/bt: shorten some log messages for bluedroid 2021-03-24 03:38:56 +00:00
67402f035f component/bt: [ESP32S3] fix missing IRAM_ATTR for function in libbtdm_app.a 2021-03-24 03:38:56 +00:00
7dd5568cb7 fixed incorrect Tx power mappings for ESP32C3 chip 2021-03-24 03:38:56 +00:00
f00d7ee9d0 Merge branch 'bugfix/fix_wdt_timeout_when_enable_rf_v4.3' into 'release/v4.3'
esp_wifi: fix wdt timeout when enable rf (backport v4.3)

See merge request espressif/esp-idf!12833
2021-03-23 16:32:29 +00:00
dba5597edf component/bt: Modify some ambiguous descriptions(release v4.3) 2021-03-23 23:02:18 +08:00
5019a6571e Merge branch 'bugfix/nvs_encryption_keys_v4.3' into 'release/v4.3'
NVS: fix nvs_flash_generate_keys to generate random keys (Github PR) (v4.3)

See merge request espressif/esp-idf!12781
2021-03-23 04:41:01 +00:00
4f8d784753 esp_wifi: fix wdt timeout when enable rf 2021-03-23 10:26:56 +08:00
a697377871 [doc]: elaborated nvs encryption comments in nvs 2021-03-22 13:02:35 +00:00
6ceee165b5 Fix nvs_flash_generate_keys
Merges https://github.com/espressif/esp-idf/pull/6478
2021-03-22 13:02:35 +00:00
4a20f68f5c Merge branch 'feature/update_wifi_provisioning_readme_v4.3' into 'release/v4.3'
provisioning: Update README.md to explain QR code format [backport v4.3]

See merge request espressif/esp-idf!12802
2021-03-22 12:57:05 +00:00
8ec0ffe751 Merge branch 'bugfix/fix_rtc_memory_region_name_v4.3' into 'release/v4.3'
esp32c3: correct name for RTC memory region in heap (v4.3)

See merge request espressif/esp-idf!12820
2021-03-22 12:54:07 +00:00
5d0ce8b52f Merge branch 'bugfix/crash_on_enabling_verbose_logs_v4.3' into 'release/v4.3'
esp_wifi: Fixes issue of crashing when verbose logs are enabled. (v4.3)

See merge request espressif/esp-idf!12495
2021-03-22 12:52:37 +00:00
2313683b58 Merge branch 'bugfix/fix_l2cap_repeat_cid_v4.3' into 'release/v4.3'
Bugfix/Fix L2CAP Repeat Cid[backport v4.3]

See merge request espressif/esp-idf!12613
2021-03-22 12:49:03 +00:00
c41822dc7c Merge branch 'mesh/support_for_chain_topology_backport_v4.3' into 'release/v4.3'
mesh: support for chain topology (backport v4.3)

See merge request espressif/esp-idf!12805
2021-03-22 12:48:41 +00:00
21909d7823 Merge branch 'mesh/ps_duty_signaling_backport_v4.3' into 'release/v4.3'
mesh/ps: network duty signaling (backport v4.3)

See merge request espressif/esp-idf!12804
2021-03-22 12:47:53 +00:00
651a939643 Merge branch 'bugfix/spi_flash_compatible_with_rom_c3_and_s3_v4.3' into 'release/v4.3'
spi_flash: make spiflash compatible with ESP32C3 and ESP32S3 ROM (backport v4.3)

See merge request espressif/esp-idf!12784
2021-03-22 12:47:05 +00:00
3bf9d389ef Merge branch 'bufix/ag_deep_copy_crash_v_4_3' into 'release/v4.3'
components/bt: Fix crash in btc_hf_arg_deep_copy when name or number is NULL

See merge request espressif/esp-idf!12791
2021-03-22 12:46:18 +00:00
6238c49479 freemodbuss: fix event processing after merge 2021-03-19 13:59:54 +01:00
fe1126cccb mesh/ps: network duty signaling 2021-03-19 20:58:00 +08:00
4725249385 esp32c3: correct name for RTC memory region in heap 2021-03-19 17:59:12 +05:30
6cfef8ce93 Merge branch 'bugfix/sign_app_by_rsa_when_require_signed_app_v4.3' into 'release/v4.3'
secure_boot: Secure Boot V2 verify app signature on update (without Secure boot) (v4.3)

See merge request espressif/esp-idf!12766
2021-03-19 12:19:53 +00:00
a643ea9432 spi_flash: make spiflash compatible with ESP32C3 and ESP32S3 ROM 2021-03-19 16:37:34 +08:00
f54dfe2912 provisioning: update README.md 2021-03-19 13:58:08 +08:00
c2ba180de3 provisioning: Update README.md to explain QR code format
Add examples of how to create a QR code that will be recognised by the iOS or Android app

Signed-off-by: yuanjm <yuanjianmin@espressif.com>

Merges https://github.com/espressif/esp-idf/pull/6629
2021-03-19 13:57:20 +08:00
d6f76f8a5f efuse: revert ESP_LOG to ESP_EARLY_LOG in src/esp_efuse_utility.c
Closes https://github.com/espressif/esp-idf/issues/6660
2021-03-19 13:25:32 +08:00
1d778c941c mesh: support for chain topology 2021-03-19 11:25:57 +08:00
87b613fd2f components/bt: Fix crash in btc_hf_arg_deep_copy when name or number is NULL 2021-03-18 20:29:05 +08:00
f5f7d21c83 CI: ignore result from check_doc_links
check_doc_links will always fail due to:
 * No rate limitation for requests
 * Not being able to handle github links with anchors
2021-03-18 13:15:24 +08:00
502a819757 secure boot v2: Fix issue checking multiple signature blocks on OTA update 2021-03-17 17:08:59 +08:00
802a01c0b7 docs: Add docs for Secure Boot V2 "verify on update without secure boot" 2021-03-17 17:08:59 +08:00
a479ee30c9 secure boot: Add boot check for SBV2 "check app signature on update"
As this mode uses the public keys attached to the existing app's signatures to
verify the next app, checking that a signature block is found on boot prevents
the possibility of deploying a non-updatable device from the factory.
2021-03-17 17:08:59 +08:00
46e85ed021 secure_boot: Secure Boot V2 verify app signature on update (without Secure boot)
- ESP32 ECO3, ESP32-S2/C3/S3
2021-03-17 17:08:59 +08:00
0862fe815b secure_boot: Adds empty esp_secure_boot_init_checks
There is no checks
2021-03-17 17:09:00 +08:00
918875424e fix: clear interrupt in touch sensor initialization 2021-03-16 11:37:41 +08:00
5490c0a243 vfs: use sys/dirent.h from newlib
The dirent.h shipped with the risc-v compiler lacks `extern "C"`
declartion and causes linkage declartion conflict when included in C++
files. Use the dirent.h from newlib only to avoid this issue.

(cherry picked from commit b14830c5c0)
2021-03-16 10:33:31 +08:00
a71d9cc466 [cxx]: fixed extern "C" declarations
* Moving #includes above
  #ifdef __cplusplus extern "C" { #endif
  So that we can compile with CPP.

Signed-off-by: Jakob Hasse <jakob.hasse@espressif.com>

Merges https://github.com/espressif/esp-idf/pull/6634
Closes https://github.com/espressif/esp-idf/issues/6633
2021-03-15 17:48:23 +08:00
c75a8b11bb eth_phy: fix wrong register bit order in ksz8041 2021-03-15 13:12:17 +08:00
9c884b3ba9 fix l2cap repeat cid 2021-03-12 15:53:48 +08:00
9a2d251912 Merge branch 'feature/coredump_refactor_riscv_support_v4.3' into 'release/v4.3'
espcoredump: code refactoring and add support for RISC-V implementation (backport v4.3)

See merge request espressif/esp-idf!12680
2021-03-12 07:47:02 +00:00
3b9af23290 Merge branch 'component_bt/optimize_spp_stop_server_v4.3' into 'release/v4.3'
component_bt/Optimize SPP Stop Server API[backport v4.3]

See merge request espressif/esp-idf!12615
2021-03-12 07:45:05 +00:00
ff12b50e45 Merge branch 'feature/wifi_support_sta_sleep_at_disconnected_v4.3' into 'release/v4.3'
esp_wifi: wifi support sta sleep at disconnected (backport v4.3)

See merge request espressif/esp-idf!12720
2021-03-12 07:43:46 +00:00
f6336516d1 Merge branch 'bugfix/fix_ble_connect_evt_report_remote_addr_err_v4.3' into 'release/v4.3'
fix ble connection event report remote address error (backport v4.3)

See merge request espressif/esp-idf!12717
2021-03-12 05:59:25 +00:00
4d80dd1238 Merge branch 'bugfix/c++_usage_esp_core_dump_h_v4.3' into 'release/v4.3'
Fixed c++ include usage for esp_core_dump.h (backport v4.3)

See merge request espressif/esp-idf!12677
2021-03-12 04:01:42 +00:00
zwj
8a2155f95e fix ble connection event report remote address error 2021-03-12 11:44:13 +08:00
367190deaf esp_wifi: support sta to sleep at disconnected status 2021-03-12 00:22:38 +08:00
dbb632fe34 Merge branch 'bugfix/fix_smartconfig_issue_v4.3' into 'release/v4.3'
esp_wifi: Fix the second distribution network failure of smartconfig (backport v4.3)

See merge request espressif/esp-idf!12685
2021-03-11 14:28:52 +00:00
1329747dc1 Merge branch 'bugfix/flash_s3_v4.3' into 'release/v4.3'
spi_flash: remove useless dummy and make rom compatible on esp32s3(backport v4.3)

See merge request espressif/esp-idf!12704
2021-03-11 13:38:52 +00:00
f9e1942252 Merge branch 'bugfix/ota_v4.3' into 'release/v4.3'
ota: fix ota with flash encryption(backport v4.3)

See merge request espressif/esp-idf!12705
2021-03-11 13:21:00 +00:00
82ffb33085 Merge branch 'feature/crypto_reserve_gdma_ch_v4.3' into 'release/v4.3'
aes/sha: use a shared lazy allocated GDMA channel for AES and SHA (v4.3)

See merge request espressif/esp-idf!12676
2021-03-11 10:50:09 +00:00
9fd12182de Merge branch 'docs/esp32c3_fatal_errors_v4.3' into 'release/v4.3'
doc: update "Fatal Errors" chapter for ESP32C3 board (backport v4.3)

See merge request espressif/esp-idf!12678
2021-03-11 10:48:03 +00:00
d42958439d Merge branch 'doc/c3_api_ref_update_v4.3' into 'release/v4.3'
docs: update api-reference chapters for C3 (v4.3)

See merge request espressif/esp-idf!12583
2021-03-11 09:36:44 +00:00
37946ab300 deep sleep: power down wifi and bt during deep sleep 2021-03-11 07:32:30 +00:00
2b7a3f6d85 light sleep: some default parameters optimization 2021-03-11 07:32:30 +00:00
60642e580c esp_wifi: Fix the second distribution network failure of ESPTouch v2 2021-03-11 07:32:30 +00:00
4235e80008 Merge branch 'bugfix/backport_bugfixs_to_release_v4.3' into 'release/v4.3'
Bugfix/backport bugfixs to release v4.3

See merge request espressif/esp-idf!12682
2021-03-11 07:15:00 +00:00
a8e0989648 Merge branch 'feature/re-enable_suspend_test_esp32c3_v4.3' into 'release/v4.3'
freertos: Workaround delay between interrupt request and trigger on RISC-V (backport v4.3)

See merge request espressif/esp-idf!12679
2021-03-11 07:12:56 +00:00
28f50addda ota: fix ota with flash encryption 2021-03-11 14:42:09 +08:00
9393a402eb doc: update "Fatal Errors" chapter for ESP32C3 board 2021-03-11 06:37:30 +00:00
268787c5fb spi_flash: remove useless dummy and make rom compatible on esp32s3 2021-03-11 14:31:27 +08:00
d92ac450a2 temp_sensor: add calibration for esp32c3 2021-03-11 14:25:18 +08:00
233f3f80e5 Merge branch 'feature/skip_validate_v4.3' into 'release/v4.3'
bootloader: Add config options to skip validation of app for minimum boot time (v4.3)

See merge request espressif/esp-idf!12683
2021-03-11 05:47:43 +00:00
d01efe4b8c Fix for C2H flow control param check when only BLE mode is configured. 2021-03-11 12:04:01 +08:00
e48935d187 Merge branch 'bugfix/uart_baud_c3_s3_v4.3' into 'release/v4.3'
uart: fixed incorrect baudrate on C3 and S3 when target is too slow (v4.3)

See merge request espressif/esp-idf!12681
2021-03-10 17:10:13 +00:00
12bbd1f051 Merge branch 'bugfix/fix_some_wifi_bugs_0309_v4.3' into 'release/v4.3'
esp_wifi: Fix some Wi-Fi bugs 0309 (backport v4.3)

See merge request espressif/esp-idf!12670
2021-03-10 11:07:20 +00:00
0305d13467 bootloader: Add config options to skip validation of app for minimum boot time 2021-03-10 19:08:47 +11:00
e6ace495b4 Fix issues during light sleep and DFS 2021-03-10 14:14:49 +08:00
b449909b35 Fix controller task watchdog in Wi-Fi test 2021-03-10 14:14:29 +08:00
0253d825e9 Fix IRAM_ATTR missing 2021-03-10 14:14:04 +08:00
32b0836485 driver: esp32s3 fix UART driver
Fix set UART2 instance to correct base address (esp32s3 has non standard base periph address)
2021-03-10 13:41:10 +08:00
7dca6b7428 uart: fixed incorrect baudrate on C3 and S3 when target is too slow
The integer part of the divider is only 12-bit now. We used prescaler to get low frequency instead.
2021-03-10 13:41:10 +08:00
b180c2a146 Merge branch 'bugfix/touch_element_callback_para_v4.3' into 'release/v4.3'
touch_element: fix event callback parameter type, change it into pointer (backport v4.3)

See merge request espressif/esp-idf!12629
2021-03-10 05:26:50 +00:00
113bf479a4 espcoredump: code refactoring and add support for RISC-V implemetation
This commit includes the refactoring of the core dump feature. Thanks to
this refactoring, it is easier to integrate the support of RISC-V
architecture for this feature.

Fixes ESP-1758
2021-03-10 12:19:00 +08:00
774f010196 freertos: Fix delay between interrupt request and trigger on RISC-V
NOP instructions have been added in order to prevent the code
from executing code it shouldn't execute. This is due to a delay
between the moment an interrupt is requested and the moment it
is fired. It only happens on RISC-V SoC.
2021-03-10 12:14:21 +08:00
22a8fe5b6f Removed esp_core_dump.h from check_public_headers_exceptions.txt (as per @igrr 's request 2021-03-10 12:04:48 +08:00
d36c72fba0 Fixed c++ include usage for esp_core_dump.h 2021-03-10 12:04:42 +08:00
1c8fd4041e aes/sha: use a shared lazy allocated GDMA channel for AES and SHA
Removed the old dynamically allocated GDMA channel approach.
It proved too unreliable as we couldn't not ensure consumers of the mbedtls
would properly free the channels after use.

Replaced by a single shared GDMA channel for AES and SHA, which won't be
released unless user specifically calls API for releasing it.
2021-03-10 09:40:35 +08:00
d4263c2558 Merge branch 'bugfix/btdm_crash_when_esp_restart_v4.3' into 'release/v4.3'
components/bt: Fix crash in Bluetooth when esp_restart

See merge request espressif/esp-idf!12641
2021-03-09 17:30:45 +00:00
ea49545269 esp_wifi: Fix some Wi-Fi bugs 0309
1. Fix the issue that the parameters obtained from RAM cannot be saved to NVS
2. Modify not to store the default value in NVS
3. Fixed issue with hidden AP scans after connecting AP.
4. Fix watchdog issue when receiving action frame.
5. Fixed issue of reason code change from 15 to 204 when provide wrong password
6. Fix set config return value error
7. Fix ampdu age timer memory leak
2021-03-09 20:30:13 +08:00
9ca05c17ae Merge branch 'bugfix/ota_simple_backport_v4.3' into 'release/v4.3'
ota: fix ota with flash encryption(backport v4.3)

See merge request espressif/esp-idf!12639
2021-03-09 09:42:57 +00:00
fd93c475b6 update CN translation based on reviewers' comments 2021-03-09 10:31:33 +11:00
27c72a4105 api-guides: update CN translation for build-system and build-system-legacy,and fix line break in the EN version 2021-03-09 10:30:49 +11:00
5c8b1d6ab8 doc: Update the link to an example that embeds a file
Since we have the CA Certificate Store feature, https_request no longer needs to
embed any certs.
2021-03-09 10:30:49 +11:00
c5f8fbea02 Merge branch 'fix/esp_tls_prevent_freeing_global_CA_store_after_each_request_v4.3' into 'release/v4.3'
fix(esp_tls): prevent freeing global CA store after each request (v4.3)

See merge request espressif/esp-idf!12630
2021-03-08 04:59:19 +00:00
cf7891cb93 Merge branch 'feature/touch_element_api_reference_v4.3' into 'release/v4.3'
touch_element: add touch element lib api-reference doc (backport v4.3)

See merge request espressif/esp-idf!12572
2021-03-08 02:58:43 +00:00
1e77586120 components/bt: Fix crash in Bluetooth when esp_restart 2021-03-05 20:19:18 +08:00
1ea548ecb3 ota: fix ota with flash encryption 2021-03-05 18:39:32 +08:00
962ea61d53 protocomm: Fixed NULL check of allocated memory
Fixes one part of - https://github.com/espressif/esp-idf/issues/6440
2021-03-05 10:04:45 +05:30
d61ee580d5 esp_tls: Fix misplaced paranthesis in esp_tls_mbedtls.c
Fixes one part of -  https://github.com/espressif/esp-idf/issues/6440
2021-03-05 10:04:45 +05:30
947e445e02 Fix esp_tls: Prevent freeing of global ca store after each connection
when dynamic ssl buffers are enabled
2021-03-05 09:53:19 +05:30
1821fd766b touch_element: fix event callback parameter type, change it into pointer 2021-03-05 11:45:47 +08:00
d508182429 Merge branch 'feature/touch_element_example_v4.3' into 'release/v4.3'
touch_element: add touch element lib examples (backport v4.3)

See merge request espressif/esp-idf!12571
2021-03-05 03:29:43 +00:00
58c9a2eaba add API esp_spp_stop_srv_scn to stop a specific server 2021-03-04 15:16:44 +08:00
07b62da0d4 Merge branch 'feature/add_qrcode_in_provisioning_example_v4.3' into 'release/v4.3'
examples: Add QR code support for provisioning examples [backport v4.3]

See merge request espressif/esp-idf!12555
2021-03-03 06:24:56 +00:00
fb82bdb9da docs: update api-reference chapters for C3
Checked and updated the following chapters:
 * api-reference/network
 * api-reference/protocols
 * api-reference/provisioning
 * api-reference/storage
 * api-reference/peripherals/ds
 * api-reference/peripherals/hmac
 * api-reference/peripherals/secure_element
2021-03-02 15:00:56 +08:00
f3be9976b9 tools: Don't count BSS into the total image size 2021-03-01 14:39:32 +01:00
b639514793 touch_element: add touch element api-reference doc 2021-03-01 18:02:53 +08:00
f12b571f82 Merge branch 'bugfix/esp_wifi_deinit_v4.3' into 'release/v4.3'
esp_wifi_deinit: Return ESP_ERR_WIFI_NOT_STOPPED if wifi is not stopped (v4.3)

See merge request espressif/esp-idf!12539
2021-03-01 09:31:13 +00:00
c0f06115d4 touch_element: add touch element lib example 2021-03-01 17:28:04 +08:00
20b25a9667 esp_wifi_deinit: Return ESP_ERR_WIFI_NOT_STOPPED if wifi is not stopped
Add test case to test this workflow
2021-03-01 05:33:26 +00:00
1d9d444c07 Merge branch 'bugfix/deepsleep_disable_brownout_s2_v4.3' into 'release/v4.3'
deep_sleep: on S2 disable the brown out detector before deep sleeping (v4.3)

See merge request espressif/esp-idf!12499
2021-03-01 03:50:20 +00:00
060a829091 examples: Add QR code support for provisioning examples 2021-03-01 10:51:36 +08:00
78314df2a5 Merge branch 'feature/enable_c3_ut_v4.3' into 'release/v4.3'
CI: run C3 unit test on protected branches

See merge request espressif/esp-idf!12416
2021-03-01 02:10:51 +00:00
8ceb462993 Merge branch 'feature/enable_gpio19_esp32c3_v4.3' into 'release/v4.3'
gpio: enable GPIO19 on ESP32C3 boards (backport v4.3)

See merge request espressif/esp-idf!12542
2021-02-27 05:25:42 +00:00
6accffecea Merge branch 'bugfix/fix_spi_slv_hd_dma_reset_issue_4.3' into 'release/v4.3'
spi_slave_hd: fix spi slv hd dma reset issue (4.3)

See merge request espressif/esp-idf!12513
2021-02-27 04:12:42 +00:00
de79e482c9 Merge branch 'feaature/deep_sleep_wakeup_backport' into 'release/v4.3'
esp_system: support gpio wakeup from deep sleep on esp32c3(backport v4.3)

See merge request espressif/esp-idf!12537
2021-02-26 14:49:19 +00:00
6638b81f8e esp_wifi: Fixes issue of crashing when verbose logs are enabled. 2021-02-26 19:00:55 +05:30
d92b647199 Merge branch 'bugfix/fix_some_wifi_bugs_0226_v4.3' into 'release/v4.3'
esp_wifi: fix some wifi bugs (backport v4.3)

See merge request espressif/esp-idf!12538
2021-02-26 12:52:39 +00:00
965daf977a Merge branch 'bugfix/btdm_fix_spp_acceptor_cancle_pair_crash_4.3' into 'release/v4.3'
fix crash caused by spp pairing cancel (4.3)

See merge request espressif/esp-idf!12544
2021-02-26 12:42:21 +00:00
zwj
aa652adc12 fix crash caused by spp pairing cancel 2021-02-26 19:17:51 +08:00
5795075460 gpio: enable GPIO19 on ESP32C3 boards 2021-02-26 17:54:36 +08:00
198d350fe5 esp_system: support gpio wakeup from deep sleep on esp32c3 2021-02-26 17:08:22 +08:00
24f3341a2d Merge branch 'docs/spi_flash_auto_suspend_v4.3' into 'release/v4.3'
spi_flash: update docs after adding CONFIG_SPI_FLASH_AUTO_SUSPEND (v4.3)

See merge request espressif/esp-idf!12512
2021-02-26 08:53:48 +00:00
5a429f644f esp_wifi: update wifi lib 2021-02-26 16:36:16 +08:00
9aae8e0ce3 esp_wifi: synchronize Wi-Fi adapter between different chips
Support preferring to allocate Wi-Fi memory from PSRAM on ESP32-S3

Support Wi-Fi TX cache buffer on ESP32-S3
2021-02-26 16:34:23 +08:00
e5e47ebae6 esp_wifi: store PHY digital registers before disabling PHY and load
them after enabling PHY
2021-02-26 16:34:10 +08:00
436c3c289e esp_wifi: optimization wifi rate
1.support disable 11b rate
2.support config espnow rate
3.fix sta negotiate phymode issue
4.update ftm rate
2021-02-26 16:32:09 +08:00
2aa6aa8b88 change rom function for esp32c3 to fix eb lldesc size issue 2021-02-26 16:31:12 +08:00
3e9cd49d32 spi_slv_hd: add hal_trans_finish comments for clarifying risk 2021-02-26 10:39:12 +08:00
2c1845995b spi_slave_hd: refactor the hal append api to remove the spinlock 2021-02-26 10:39:10 +08:00
0c77299c34 Merge branch 'feature/update_efuse_doc_v4.3' into 'release/v4.3'
doc/efuse: Adds efuse doc for ESP32-C3 (v4.3)

See merge request espressif/esp-idf!12516
2021-02-25 23:22:51 +00:00
9ac3e7c5d1 Merge branch 'feature/doc_update_security_chapters_v4.3' into 'release/v4.3'
doc/secure features: Updates doc esp32c3 (v4.3)

See merge request espressif/esp-idf!12517
2021-02-25 23:14:12 +00:00
c42ce05941 Merge branch 'feature/apply_gdma_new_channel_api_to_adc_4.3' into 'release/v4.3'
adc: apply gdma new channel api to adc (v4.3)

See merge request espressif/esp-idf!12502
2021-02-25 17:37:17 +00:00
ea2eb9d833 doc(esp32c3): Updates secure features doc 2021-02-25 21:08:55 +08:00
dec52a93d4 doc/efuse: Adds efuse doc for ESP32-C3 2021-02-25 21:07:27 +08:00
41bee7831f adc: apply gdma api to adc on esp32c3 2021-02-25 18:53:32 +08:00
bd1b4dbda1 Merge branch 'feature/apply_gdma_new_channel_api_to_spi_4.3' into 'release/v4.3'
spi: apply gdma new channel api to spi (v4.3)

See merge request espressif/esp-idf!12501
2021-02-25 10:36:09 +00:00
1de12526eb spi_flash: update docs after adding CONFIG_SPI_FLASH_AUTO_SUSPEND 2021-02-25 18:08:23 +08:00
f0f2799946 Merge branch 'bugfix/gdma_pair_uninstall_concurrency_issue_v4.3' into 'release/v4.3'
gdma: fix wrong level of {group,pair} reference count (v4.3)

See merge request espressif/esp-idf!12488
2021-02-25 09:11:58 +00:00
5aabdd8abf Merge branch 'bugfix/eclipse_make_decode_v4.3' into 'release/v4.3'
tools: Fix Eclipse build: “UnicodeDecodeError: 'ascii' codec can't decode byte” (v4.3)

See merge request espressif/esp-idf!12357
2021-02-25 07:17:28 +00:00
8a2f91b48a spi: add enum for spi dma channels 2021-02-25 11:03:18 +08:00
ed6fb33726 spi: remove hard-coded DMA chan in soc_caps.h 2021-02-25 11:03:07 +08:00
66d10f0eec spi: refactor spi_common dma allocator 2021-02-25 11:01:33 +08:00
97f248d22c spi: update unit tests to spi gdma allocator 2021-02-25 11:01:27 +08:00
ffc4ff5a8c spi: apply gdma allocator to SPI 2021-02-25 11:01:16 +08:00
326d76ebdf spi: add dma channel auto-alloc feature on esp32 2021-02-25 11:01:06 +08:00
c6ed522d60 deep_sleep: on S2 disable the brown out detector before deep sleeping
On S2 the brown out detector would occasionally trigger erroneously during deep sleep.

Disable it before sleeping to circumvent this issue.

Closes https://github.com/espressif/esp-idf/issues/6179
2021-02-25 10:53:06 +08:00
8e187e7157 Merge branch 'bugfix/c3_unit_test_cleanup_v4.3' into 'release/v4.3'
System: C3 shared stack watchpoint & unit test cleanups (v4.3)

See merge request espressif/esp-idf!12418
2021-02-24 22:51:11 +00:00
19f18aaa11 gdma: fix wrong level of {group,pair} ref count 2021-02-24 17:46:23 +08:00
626a861115 async_mcp: clean eof flag when prepare rx descriptors 2021-02-24 17:46:23 +08:00
a0fdf4b06c Merge branch 'feature/riscv_get_tickrate_v4.3' into 'release/v4.3'
freertos: add API for getting tick rate on C3 (v4.3)

See merge request espressif/esp-idf!12471
2021-02-24 08:29:59 +00:00
3d9523724d freertos: add API for getting tick rate on C3 2021-02-23 12:14:11 +08:00
813b6c4ef6 Merge branch 'bugfix/fix_enable_reset_provision_cause_device_crash_v4.3' into 'release/v4.3'
provisioning: Fix enable CONFIG_EXAMPLE_RESET_PROVISIONED will cause device crash [backport v4.3]

See merge request espressif/esp-idf!12353
2021-02-22 06:13:17 +00:00
1b849d59de Merge branch 'bugfix/freemodbus_fix_parity_propagation_issue_v43' into 'release/v4.3'
freemodbus: fix mb controller parity propagation issues (Backport v4.3)

See merge request espressif/esp-idf!12390
2021-02-22 05:23:33 +00:00
87576aba28 provisioning: Fix enable CONFIG_EXAMPLE_RESET_PROVISIONED will cause device crash 2021-02-22 04:33:59 +00:00
57fb076590 Merge branch 'feature/prefer_python3_in_installer_v4.3' into 'release/v4.3'
tools: Prefer python3 during install and export (v4.3)

See merge request espressif/esp-idf!12376
2021-02-19 15:52:32 +00:00
360e7c4d51 system: enable shared stack watchpoint
Enable shared stack watchpoint for overflow detection

Enable unit tests:
 * "test printf using shared buffer stack" for C3
 * "Test vTaskDelayUntil" for S2
 * "UART can do poll()" for C3
2021-02-19 16:59:29 +08:00
9083ef97e5 spi_flash: disable mmap into instr space unit test for C3
On C3 the cache is programmatically split between Icache and dcache and with the default setup we dont leave a lot pages
available for additional mmaps into instruction space. Disabling this test for now since any hypothetical use case for this
is no longer supported "out of the box"
2021-02-19 16:58:47 +08:00
a7a1e4dfba CI: run C3 unit test on protected branches 2021-02-19 16:47:00 +08:00
8ad92a92b9 Merge branch 'feature/ulp_c3_not_exists_update_doc_v4.3' into 'release/v4.3'
doc/ulp(esp32c3): Excludes ulp and some RTC features from ESP32C3 doc (v4.3)

See merge request espressif/esp-idf!12386
2021-02-17 03:54:01 +00:00
321ee21c4c freemodbus: fix mb controller parity propagation issues
Closes https://github.com/espressif/esp-idf/issues/6377
2021-02-16 10:47:43 +01:00
33820657c5 doc/ulp(esp32c3): Excludes ulp and some RTC features from ESP32C3 doc 2021-02-16 15:37:26 +08:00
33892aadb9 tools: Prefer python3 during install and export
Install and export script should work on systems without "python"
executable.

Closes https://github.com/espressif/esp-idf/pull/6471

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

Related to https://github.com/espressif/esp-idf/issues/6421 and
https://github.com/espressif/arduino-esp32/issues/4717
2021-02-14 18:49:21 +01:00
ad669801ae Fix eclipse build: “UnicodeDecodeError: 'ascii' codec can't decode byte”
Closes https://github.com/espressif/esp-idf/pull/6505
2021-02-10 12:48:44 +01:00
575 changed files with 16396 additions and 7596 deletions

View File

@ -41,16 +41,6 @@
#include "esp_efuse.h"
#include "esp_attr.h"
#ifdef CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/crc.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/crc.h"
#include "esp32s2/rom/secure_boot.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/crc.h"
#include "esp32c3/rom/secure_boot.h"
#endif
#define SUB_TYPE_ID(i) (i & 0x0F)
/* Partial_data is word aligned so no reallocation is necessary for encrypted flash write */

View File

@ -274,6 +274,10 @@ menu "Bootloader config"
config BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
bool "Skip image validation when exiting deep sleep"
# note: dependencies for this config item are different to other "skip image validation"
# options, allowing to turn on "allow insecure options" and have secure boot with
# "skip validation when existing deep sleep". Keeping this to avoid a breaking change,
# but - as noted in help - it invalidates the integrity of Secure Boot checks
depends on (SECURE_BOOT && SECURE_BOOT_INSECURE) || !SECURE_BOOT
default n
help
@ -286,6 +290,48 @@ menu "Bootloader config"
partition as this would skip the validation upon first load of the new
OTA partition.
It is possible to enable this option with Secure Boot if "allow insecure
options" is enabled, however it's strongly recommended to NOT enable it as
it may allow a Secure Boot bypass.
config BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON
bool "Skip image validation from power on reset (READ HELP FIRST)"
# only available if both Secure Boot and Check Signature on Boot are disabled
depends on !SECURE_SIGNED_ON_BOOT
default n
help
Some applications need to boot very quickly from power on. By default, the entire app binary
is read from flash and verified which takes up a significant portion of the boot time.
Enabling this option will skip validation of the app when the SoC boots from power on.
Note that in this case it's not possible for the bootloader to detect if an app image is
corrupted in the flash, therefore it's not possible to safely fall back to a different app
partition. Flash corruption of this kind is unlikely but can happen if there is a serious
firmware bug or physical damage.
Following other reset types, the bootloader will still validate the app image. This increases
the chances that flash corruption resulting in a crash can be detected following soft reset, and
the bootloader will fall back to a valid app image. To increase the chances of successfully recovering
from a flash corruption event, keep the option BOOTLOADER_WDT_ENABLE enabled and consider also enabling
BOOTLOADER_WDT_DISABLE_IN_USER_CODE - then manually disable the RTC Watchdog once the app is running.
In addition, enable both the Task and Interrupt watchdog timers with reset options set.
config BOOTLOADER_SKIP_VALIDATE_ALWAYS
bool "Skip image validation always (READ HELP FIRST)"
# only available if both Secure Boot and Check Signature on Boot are disabled
depends on !SECURE_SIGNED_ON_BOOT
default n
select BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
select BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON
help
Selecting this option prevents the bootloader from ever validating the app image before
booting it. Any flash corruption of the selected app partition will make the entire SoC
unbootable.
Although flash corruption is a very rare case, it is not recommended to select this option.
Consider selecting "Skip image validation from power on reset" instead. However, if boot time
is the only important factor then it can be enabled.
config BOOTLOADER_RESERVE_RTC_SIZE
hex
default 0x10 if BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP || BOOTLOADER_CUSTOM_RESERVE_RTC
@ -378,7 +424,7 @@ menu "Security features"
1. ECDSA based secure boot scheme. (Only choice for Secure Boot V1)
Supported in ESP32 and ESP32-ECO3.
2. The RSA based secure boot scheme. (Only choice for Secure Boot V2)
Supported in ESP32-ECO3. (ESP32 Chip Revision 3 onwards)
Supported in ESP32-ECO3 (ESP32 Chip Revision 3 onwards), ESP32-S2, ESP32-C3, ESP32-S3.
config SECURE_SIGNED_APPS_ECDSA_SCHEME
bool "ECDSA"
@ -390,7 +436,7 @@ menu "Security features"
config SECURE_SIGNED_APPS_RSA_SCHEME
bool "RSA"
depends on SECURE_BOOT_SUPPORTS_RSA && SECURE_BOOT_V2_ENABLED
depends on SECURE_BOOT_SUPPORTS_RSA && (SECURE_SIGNED_APPS_NO_SECURE_BOOT || SECURE_BOOT_V2_ENABLED)
help
Appends the RSA-3072 based Signature block to the application.
Refer to <Secure Boot Version 2 documentation link> before enabling.
@ -399,7 +445,7 @@ menu "Security features"
config SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT
bool "Bootloader verifies app signatures"
default n
depends on SECURE_SIGNED_APPS_NO_SECURE_BOOT
depends on SECURE_SIGNED_APPS_NO_SECURE_BOOT && SECURE_SIGNED_APPS_ECDSA_SCHEME
help
If this option is set, the bootloader will be compiled with code to verify that an app is signed before
booting it.
@ -425,7 +471,7 @@ menu "Security features"
config SECURE_BOOT
bool "Enable hardware Secure Boot in bootloader (READ DOCS FIRST)"
default n
depends on !IDF_TARGET_ESP32C3 # IDF-2647
depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || ESP32C3_REV_MIN_3
help
Build a bootloader which enables Secure Boot on first boot.
@ -442,7 +488,7 @@ menu "Security features"
help
Select the Secure Boot Version. Depends on the Chip Revision.
Secure Boot V2 is the new RSA based secure boot scheme.
Supported in ESP32-ECO3. (ESP32 Chip Revision 3 onwards)
Supported in ESP32-ECO3 (ESP32 Chip Revision 3 onwards), ESP32-S2, ESP32-C3 ECO3.
Secure Boot V1 is the AES based secure boot scheme.
Supported in ESP32 and ESP32-ECO3.
@ -456,8 +502,6 @@ menu "Security features"
config SECURE_BOOT_V2_ENABLED
bool "Enable Secure Boot version 2"
depends on SECURE_BOOT_SUPPORTS_RSA
select SECURE_ENABLE_SECURE_ROM_DL_MODE if !IDF_TARGET_ESP32 && !SECURE_INSECURE_ALLOW_DL_MODE && !SECURE_DISABLE_ROM_DL_MODE # NOERROR
select SECURE_DISABLE_ROM_DL_MODE if ESP32_REV_MIN_3 && !SECURE_INSECURE_ALLOW_DL_MODE
help
Build a bootloader which enables Secure Boot version 2 on first boot.
Refer to Secure Boot V2 section of the ESP-IDF Programmer's Guide for this version before enabling.
@ -626,8 +670,6 @@ menu "Security features"
config SECURE_FLASH_ENCRYPTION_MODE_RELEASE
bool "Release"
select SECURE_ENABLE_SECURE_ROM_DL_MODE if SECURE_TARGET_HAS_SECURE_ROM_DL_MODE && !SECURE_DISABLE_ROM_DL_MODE # NOERROR
endchoice
menu "Potentially insecure options"
@ -692,19 +734,6 @@ menu "Security features"
key digest, causing an immediate denial of service and possibly allowing an additional fault
injection attack to bypass the signature protection.
config SECURE_INSECURE_ALLOW_DL_MODE
bool "Don't automatically restrict UART download mode"
depends on SECURE_BOOT_INSECURE && SECURE_BOOT_V2_ENABLED
default N
help
By default, enabling either flash encryption in release mode or secure boot will automatically
disable UART download mode on ESP32 ECO3, or enable secure download mode on newer chips.
This is recommended to reduce the attack surface of the chip.
To allow the full UART download mode to stay enabled, enable this option and ensure
the options SECURE_DISABLE_ROM_DL_MODE and SECURE_ENABLE_SECURE_ROM_DL_MODE are disabled as applicable.
This is not recommended.
config SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
bool "Leave UART bootloader encryption enabled"
depends on SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
@ -752,47 +781,58 @@ menu "Security features"
endmenu # Potentially Insecure
config SECURE_DISABLE_ROM_DL_MODE
bool "Permanently disable ROM Download Mode"
choice SECURE_UART_ROM_DL_MODE
bool "UART ROM download mode"
default SECURE_ENABLE_SECURE_ROM_DL_MODE if SECURE_TARGET_HAS_SECURE_ROM_DL_MODE && !SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT # NOERROR
default SECURE_INSECURE_ALLOW_DL_MODE
depends on SECURE_BOOT_V2_ENABLED || SECURE_FLASH_ENC_ENABLED
depends on !IDF_TARGET_ESP32 || ESP32_REV_MIN_3
default n
help
If set, during startup the app will burn an eFuse bit to permanently disable the UART ROM
Download Mode. This prevents any future use of esptool.py, espefuse.py and similar tools.
Once disabled, if the SoC is booted with strapping pins set for ROM Download Mode
then an error is printed instead.
config SECURE_DISABLE_ROM_DL_MODE
bool "UART ROM download mode (Permanently disabled (recommended))"
help
If set, during startup the app will burn an eFuse bit to permanently disable the UART ROM
Download Mode. This prevents any future use of esptool.py, espefuse.py and similar tools.
It is recommended to enable this option in any production application where Flash
Encryption and/or Secure Boot is enabled and access to Download Mode is not required.
Once disabled, if the SoC is booted with strapping pins set for ROM Download Mode
then an error is printed instead.
It is also possible to permanently disable Download Mode by calling
esp_efuse_disable_rom_download_mode() at runtime.
It is recommended to enable this option in any production application where Flash
Encryption and/or Secure Boot is enabled and access to Download Mode is not required.
config SECURE_ENABLE_SECURE_ROM_DL_MODE
bool "Permanently switch to ROM UART Secure Download mode"
depends on SECURE_TARGET_HAS_SECURE_ROM_DL_MODE && !SECURE_DISABLE_ROM_DL_MODE
select ESPTOOLPY_NO_STUB
help
If set, during startup the app will burn an eFuse bit to permanently switch the UART ROM
Download Mode into a separate Secure Download mode. This option can only work if
Download Mode is not already disabled by eFuse.
It is also possible to permanently disable Download Mode by calling
esp_efuse_disable_rom_download_mode() at runtime.
Secure Download mode limits the use of Download Mode functions to simple flash read,
write and erase operations, plus a command to return a summary of currently enabled
security features.
config SECURE_ENABLE_SECURE_ROM_DL_MODE
bool "UART ROM download mode (Permanently switch to Secure mode (recommended))"
depends on SECURE_TARGET_HAS_SECURE_ROM_DL_MODE
select ESPTOOLPY_NO_STUB
help
If set, during startup the app will burn an eFuse bit to permanently switch the UART ROM
Download Mode into a separate Secure Download mode. This option can only work if
Download Mode is not already disabled by eFuse.
Secure Download mode is not compatible with the esptool.py flasher stub feature,
espefuse.py, read/writing memory or registers, encrypted download, or any other
features that interact with unsupported Download Mode commands.
Secure Download mode limits the use of Download Mode functions to simple flash read,
write and erase operations, plus a command to return a summary of currently enabled
security features.
Secure Download mode should be enabled in any application where Flash Encryption
and/or Secure Boot is enabled. Disabling this option does not immediately cancel
the benefits of the security features, but it increases the potential "attack
surface" for an attacker to try and bypass them with a successful physical attack.
Secure Download mode is not compatible with the esptool.py flasher stub feature,
espefuse.py, read/writing memory or registers, encrypted download, or any other
features that interact with unsupported Download Mode commands.
It is also possible to enable secure download mode at runtime by calling
esp_efuse_enable_rom_secure_download_mode()
Secure Download mode should be enabled in any application where Flash Encryption
and/or Secure Boot is enabled. Disabling this option does not immediately cancel
the benefits of the security features, but it increases the potential "attack
surface" for an attacker to try and bypass them with a successful physical attack.
It is also possible to enable secure download mode at runtime by calling
esp_efuse_enable_rom_secure_download_mode()
config SECURE_INSECURE_ALLOW_DL_MODE
bool "UART ROM download mode (Enabled (not recommended))"
help
This is a potentially insecure option.
Enabling this option will allow the full UART download mode to stay enabled.
This option SHOULD NOT BE ENABLED for production use cases.
endchoice
endmenu # Security features

View File

@ -28,10 +28,11 @@ set(COMPONENTS
micro-ecc
main
efuse
esp_system)
esp_system
newlib)
set(BOOTLOADER_BUILD 1)
include("${IDF_PATH}/tools/cmake/project.cmake")
set(common_req log esp_rom esp_common esp_hw_support hal)
set(common_req log esp_rom esp_common esp_hw_support hal newlib)
if(LEGACY_INCLUDE_COMMON_HEADERS)
list(APPEND common_req soc hal)
endif()

View File

@ -52,7 +52,7 @@ SECTIONS
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_signatures.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
*libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
@ -167,6 +167,14 @@ SECTIONS
*(.fini.literal)
*(.fini)
*(.gnu.version)
/** CPU will try to prefetch up to 16 bytes of
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
* safe access to up to 16 bytes after the last real instruction, add
* dummy bytes to ensure this
*/
. += 16;
_text_end = ABSOLUTE(.);
_etext = .;
} > iram_seg

View File

@ -40,7 +40,7 @@ SECTIONS
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_signatures.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
*libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
@ -156,6 +156,14 @@ SECTIONS
*(.fini.literal)
*(.fini)
*(.gnu.version)
/** CPU will try to prefetch up to 16 bytes of
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
* safe access to up to 16 bytes after the last real instruction, add
* dummy bytes to ensure this
*/
. += 16;
_text_end = ABSOLUTE(.);
_etext = .;
} > iram_seg

View File

@ -39,7 +39,7 @@ SECTIONS
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_signatures.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
*libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
@ -155,6 +155,14 @@ SECTIONS
*(.fini.literal)
*(.fini)
*(.gnu.version)
/** CPU will try to prefetch up to 16 bytes of
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
* safe access to up to 16 bytes after the last real instruction, add
* dummy bytes to ensure this
*/
. += 16;
_text_end = ABSOLUTE(.);
_etext = .;
} > iram_seg

View File

@ -40,7 +40,7 @@ SECTIONS
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_signatures.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
*libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
@ -156,6 +156,14 @@ SECTIONS
*(.fini.literal)
*(.fini)
*(.gnu.version)
/** CPU will try to prefetch up to 16 bytes of
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
* safe access to up to 16 bytes after the last real instruction, add
* dummy bytes to ensure this
*/
. += 16;
_text_end = ABSOLUTE(.);
_etext = .;
} > iram_seg

View File

@ -9,6 +9,7 @@ set(srcs
"src/bootloader_utility.c"
"src/esp_image_format.c"
"src/flash_encrypt.c"
"src/secure_boot.c"
"src/flash_partitions.c"
"src/flash_qio_mode.c"
"src/bootloader_flash_config_${IDF_TARGET}.c"
@ -34,16 +35,28 @@ else()
"src/idf/bootloader_sha.c")
set(include_dirs "include")
set(priv_include_dirs "include_bootloader")
set(priv_requires spi_flash mbedtls efuse)
set(priv_requires spi_flash mbedtls efuse app_update)
endif()
if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME OR CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME)
if(BOOTLOADER_BUILD)
list(APPEND srcs
"src/${IDF_TARGET}/secure_boot_signatures.c")
else()
list(APPEND srcs
"src/idf/secure_boot_signatures.c")
if(BOOTLOADER_BUILD)
if(CONFIG_SECURE_SIGNED_ON_BOOT)
if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
list(APPEND srcs "src/secure_boot_v1/secure_boot_signatures_bootloader.c")
endif()
if(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME)
list(APPEND srcs "src/secure_boot_v2/secure_boot_signatures_bootloader.c")
endif()
endif()
else()
if(CONFIG_SECURE_SIGNED_ON_UPDATE)
if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
list(APPEND srcs "src/secure_boot_v1/secure_boot_signatures_app.c")
endif()
if(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME)
list(APPEND srcs "src/secure_boot_v2/secure_boot_signatures_app.c")
endif()
endif()
endif()

View File

@ -34,10 +34,13 @@ COMPONENT_OBJEXCLUDE += src/bootloader_flash_config_esp32s2.o \
src/bootloader_random_esp32c3.o
ifndef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
ifndef CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
COMPONENT_OBJEXCLUDE += src/$(IDF_TARGET)/secure_boot_signatures.o \
src/idf/secure_boot_signatures.o
COMPONENT_OBJEXCLUDE += src/secure_boot_v1/secure_boot_signatures_bootloader.o \
src/secure_boot_v1/secure_boot_signatures_app.o
endif
ifndef CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
COMPONENT_OBJEXCLUDE += src/secure_boot_v2/secure_boot_signatures_bootloader.o \
src/secure_boot_v2/secure_boot_signatures_app.o
endif
ifndef CONFIG_SECURE_BOOT

View File

@ -106,6 +106,20 @@ _Static_assert(sizeof(rtc_retain_mem_t) <= ESP_BOOTLOADER_RESERVE_RTC, "Reserved
*/
esp_err_t esp_image_verify(esp_image_load_mode_t mode, const esp_partition_pos_t *part, esp_image_metadata_t *data);
/**
* @brief Get metadata of app
*
* If encryption is enabled, data will be transparently decrypted.
*
* @param part Partition to load the app from.
* @param[out] metadata Pointer to the image metadata structure which is be filled in by this function.
* Fields will all be initialised by this function.
*
* @return
* - ESP_OK if filling of metadata was successful
*/
esp_err_t esp_image_get_metadata(const esp_partition_pos_t *part, esp_image_metadata_t *metadata);
/**
* @brief Verify and load an app image (available only in space of bootloader).
*

View File

@ -19,17 +19,22 @@
#include "esp_image_format.h"
#include "esp_rom_efuse.h"
#include "sdkconfig.h"
#include "esp_rom_crc.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/efuse.h"
#include "esp32/rom/secure_boot.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/efuse.h"
#include "esp32s2/rom/secure_boot.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/efuse.h"
#include "esp32c3/rom/secure_boot.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/efuse.h"
#include "esp32s3/rom/secure_boot.h"
#endif
typedef struct ets_secure_boot_signature ets_secure_boot_signature_t;
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
#if !defined(CONFIG_SECURE_SIGNED_ON_BOOT) || !defined(CONFIG_SECURE_SIGNED_ON_UPDATE) || !defined(CONFIG_SECURE_SIGNED_APPS)
#error "internal sdkconfig error, secure boot should always enable all signature options"
@ -45,6 +50,8 @@ extern "C" {
Can be compiled as part of app or bootloader code.
*/
#define ESP_SECURE_BOOT_DIGEST_LEN 32
/** @brief Is secure boot currently enabled in hardware?
*
* This means that the ROM bootloader code will only boot
@ -181,6 +188,16 @@ typedef struct {
*/
esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest);
#if !CONFIG_IDF_TARGET_ESP32 || CONFIG_ESP32_REV_MIN_3
/**
* @brief Structure to hold public key digests calculated from the signature blocks of a single image.
*
* Each image can have one or more signature blocks (up to SECURE_BOOT_NUM_BLOCKS). Each signature block includes a public key.
*/
typedef struct {
uint8_t key_digests[SECURE_BOOT_NUM_BLOCKS][ESP_SECURE_BOOT_DIGEST_LEN]; /* SHA of the public key components in the signature block */
unsigned num_digests; /* Number of valid digests, starting at index 0 */
} esp_image_sig_public_key_digests_t;
/** @brief Verify the RSA secure boot signature block for Secure Boot V2.
*
@ -194,6 +211,7 @@ esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig
*
*/
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest);
#endif // !CONFIG_IDF_TARGET_ESP32 || CONFIG_ESP32_REV_MIN_3
/** @brief Legacy ECDSA verification function
*
@ -214,6 +232,45 @@ typedef struct {
uint8_t digest[64];
} esp_secure_boot_iv_digest_t;
/** @brief Check the secure boot V2 during startup
*
* @note This function is called automatically during app startup,
* it doesn't need to be called from the app.
*
* Verifies the secure boot config during startup:
*
* - Correct any insecure secure boot settings
*/
void esp_secure_boot_init_checks(void);
#if !BOOTLOADER_BUILD && CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
/** @brief Scan the current running app for signature blocks
*
* @note This function doesn't verify that the signatures are valid or the
* corresponding public keys are trusted, it only reads the number of signature
* blocks present and optionally calculates the digests of the public keys
* provided in the signature blocks.
*
* @param digest_public_keys If true, the key_digests fields in the
* public_key_digests structure will be filled with the digests of the public
* key provided in each signature block. Note that if Secure Boot V2 is enabled,
* each public key will only be trusted if the same digest is also present in
* eFuse (but this is not checked by this function).
*
* @param public_key_digests[out] Structure is initialized with the num_digests
* field set to the number of signatures found. If digest_public_keys is set,
* the public key digests are also calculated and stored here.
*
* @return
* - ESP_OK - At least one signature was found
* - ESP_ERR_NOT_FOUND - No signatures were found, num_digests value will be zero
* - ESP_FAIL - An error occured trying to read the signature blocks from flash
*/
esp_err_t esp_secure_boot_get_signature_blocks_for_running_app(bool digest_public_keys, esp_image_sig_public_key_digests_t *public_key_digests);
#endif // !BOOTLOADER_BUILD && CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
#ifdef __cplusplus
}
#endif

View File

@ -30,6 +30,7 @@
#include "soc/gpio_periph.h"
#include "soc/rtc.h"
#include "soc/efuse_reg.h"
#include "soc/soc_memory_layout.h"
#include "hal/gpio_ll.h"
#include "esp_image_format.h"
#include "bootloader_sha.h"
@ -138,7 +139,18 @@ esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t
#if defined( CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP ) || defined( CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC )
rtc_retain_mem_t *const rtc_retain_mem = (rtc_retain_mem_t *)(SOC_RTC_DRAM_HIGH - sizeof(rtc_retain_mem_t));
#define RTC_RETAIN_MEM_ADDR (SOC_RTC_DATA_HIGH - sizeof(rtc_retain_mem_t))
rtc_retain_mem_t *const rtc_retain_mem = (rtc_retain_mem_t *)RTC_RETAIN_MEM_ADDR;
#if !IS_BOOTLOADER_BUILD
/* The app needs to be told this memory is reserved, important if configured to use RTC memory as heap.
Note that keeping this macro here only works when other symbols in this file are referenced by the app, as
this feature is otherwise 100% part of the bootloader. However this seems to happen in all apps.
*/
SOC_RESERVE_MEMORY_REGION(RTC_RETAIN_MEM_ADDR, RTC_RETAIN_MEM_ADDR + sizeof(rtc_retain_mem_t), rtc_retain_mem);
#endif
static bool check_rtc_retain_mem(void)
{

View File

@ -21,6 +21,7 @@
#include "soc/gpio_sig_map.h"
#include "soc/rtc.h"
#include "hal/clk_gate_ll.h"
#include "hal/gpio_hal.h"
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/usb/cdc_acm.h"
#include "esp32s2/rom/usb/usb_common.h"
@ -69,8 +70,8 @@ void bootloader_console_init(void)
uart_tx_gpio != UART_NUM_0_TXD_DIRECT_GPIO_NUM ||
uart_rx_gpio != UART_NUM_0_RXD_DIRECT_GPIO_NUM) {
// Change default UART pins back to GPIOs
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_U0RXD_U, PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_U0TXD_U, PIN_FUNC_GPIO);
// Route GPIO signals to/from pins
const uint32_t tx_idx = uart_periph_signal[uart_num].tx_sig;
const uint32_t rx_idx = uart_periph_signal[uart_num].rx_sig;

View File

@ -25,6 +25,7 @@
#include "soc/spi_reg.h"
#include "soc/soc_caps.h"
#include "soc/soc_pins.h"
#include "hal/gpio_hal.h"
#include "flash_qio_mode.h"
#include "bootloader_common.h"
#include "bootloader_flash_config.h"
@ -87,7 +88,7 @@ void IRAM_ATTR bootloader_flash_gpio_config(const esp_image_header_t* pfhdr)
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOV302) {
// For ESP32D2WD or ESP32-PICO series,the SPI pins are already configured
// flash clock signal should come from IO MUX.
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
} else {
const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
@ -102,14 +103,14 @@ void IRAM_ATTR bootloader_flash_gpio_config(const esp_image_header_t* pfhdr)
esp_rom_gpio_connect_out_signal(SPI_IOMUX_PIN_NUM_HD, SPIHD_OUT_IDX, 0, 0);
esp_rom_gpio_connect_in_signal(SPI_IOMUX_PIN_NUM_HD, SPIHD_IN_IDX, 0);
//select pin function gpio
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO);
// flash clock signal should come from IO MUX.
// set drive ability for clock
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
uint32_t flash_id = g_rom_flashchip.device_id;

View File

@ -34,6 +34,7 @@
#include "soc/io_mux_reg.h"
#include "soc/rtc.h"
#include "soc/spi_periph.h"
#include "hal/gpio_hal.h"
#include "esp32/rom/cache.h"
#include "esp_rom_gpio.h"
@ -61,7 +62,7 @@ void bootloader_configure_spi_pins(int drv)
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOV302) {
// For ESP32D2WD or ESP32-PICO series,the SPI pins are already configured
// flash clock signal should come from IO MUX.
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
} else {
const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
@ -76,14 +77,14 @@ void bootloader_configure_spi_pins(int drv)
esp_rom_gpio_connect_out_signal(FLASH_SPIHD_IO, SPIHD_OUT_IDX, 0, 0);
esp_rom_gpio_connect_in_signal(FLASH_SPIHD_IO, SPIHD_IN_IDX, 0);
//select pin function gpio
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO);
// flash clock signal should come from IO MUX.
// set drive ability for clock
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
#if CONFIG_SPIRAM_TYPE_ESPPSRAM32 || CONFIG_SPIRAM_TYPE_ESPPSRAM64

View File

@ -19,7 +19,6 @@
#include "esp_log.h"
#include "esp32/rom/cache.h"
#include "esp_rom_crc.h"
#include "soc/efuse_periph.h"
#include "soc/rtc_periph.h"
@ -223,16 +222,12 @@ esp_err_t esp_secure_boot_permanently_enable(void)
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
static const char *TAG = "secure_boot_v2";
#define SIG_BLOCK_MAGIC_BYTE 0xe7
#define CRC_SIGN_BLOCK_LEN 1196
#define SIG_BLOCK_PADDING 4096
#define DIGEST_LEN 32
static esp_err_t validate_signature_block(const ets_secure_boot_signature_t *sig_block, uint8_t *digest)
{
uint32_t crc = esp_rom_crc32_le(0, (uint8_t *)sig_block, CRC_SIGN_BLOCK_LEN);
if (sig_block->block[0].magic_byte == SIG_BLOCK_MAGIC_BYTE && sig_block->block[0].block_crc == crc && !memcmp(digest, sig_block->block[0].image_digest, DIGEST_LEN)) {
if (sig_block->block[0].magic_byte == ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC
&& sig_block->block[0].block_crc == crc
&& !memcmp(digest, sig_block->block[0].image_digest, ESP_SECURE_BOOT_DIGEST_LEN)) {
ESP_LOGI(TAG, "valid signature block found");
return ESP_OK;
}
@ -243,7 +238,7 @@ static esp_err_t secure_boot_v2_digest_generate(uint32_t flash_offset, uint32_t
{
esp_err_t ret = ESP_FAIL;
uint8_t image_digest[DIGEST_LEN] = {0};
uint8_t image_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
size_t sig_block_addr = flash_offset + ALIGN_UP(flash_size, FLASH_SECTOR_SIZE);
ret = bootloader_sha256_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest);
if (ret != ESP_OK) {
@ -266,7 +261,7 @@ static esp_err_t secure_boot_v2_digest_generate(uint32_t flash_offset, uint32_t
}
/* Verifying Signature block */
uint8_t verified_digest[DIGEST_LEN] = {0};
uint8_t verified_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
/* Generating the SHA of the public key components in the signature block */
bootloader_sha256_handle_t sig_block_sha;
@ -318,7 +313,7 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag
return ret;
}
uint8_t boot_pub_key_digest[DIGEST_LEN];
uint8_t boot_pub_key_digest[ESP_SECURE_BOOT_DIGEST_LEN];
uint32_t dis_reg = REG_READ(EFUSE_BLK0_RDATA0_REG);
bool efuse_key_read_protected = dis_reg & EFUSE_RD_DIS_BLK2;
bool efuse_key_write_protected = dis_reg & EFUSE_WR_DIS_BLK2;
@ -350,7 +345,7 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag
}
ESP_LOGI(TAG, "Burning public key hash to efuse.");
ret = esp_efuse_write_block(EFUSE_BLK2, boot_pub_key_digest, 0, (DIGEST_LEN * 8));
ret = esp_efuse_write_block(EFUSE_BLK2, boot_pub_key_digest, 0, (ESP_SECURE_BOOT_DIGEST_LEN * 8));
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Writing public key hash to efuse failed.");
return ret;
@ -366,7 +361,7 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag
efuse_blk2_digest[5] = efuse_blk2_r5;
efuse_blk2_digest[6] = efuse_blk2_r6;
efuse_blk2_digest[7] = efuse_blk2_r7;
memcpy(boot_pub_key_digest, efuse_blk2_digest, DIGEST_LEN);
memcpy(boot_pub_key_digest, efuse_blk2_digest, ESP_SECURE_BOOT_DIGEST_LEN);
ESP_LOGW(TAG, "Using pre-loaded secure boot v2 public key digest in EFUSE block 2");
}
@ -380,7 +375,7 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag
efuse_key_write_protected = true;
}
uint8_t app_pub_key_digest[DIGEST_LEN];
uint8_t app_pub_key_digest[ESP_SECURE_BOOT_DIGEST_LEN];
ret = secure_boot_v2_digest_generate(image_data->start_addr, image_data->image_len - SIG_BLOCK_PADDING, app_pub_key_digest);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Application signature block is invalid.");
@ -388,7 +383,7 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag
}
/* Confirming if the public key in the bootloader's signature block matches with the one in the application's signature block */
if (memcmp(boot_pub_key_digest, app_pub_key_digest, DIGEST_LEN) != 0) {
if (memcmp(boot_pub_key_digest, app_pub_key_digest, ESP_SECURE_BOOT_DIGEST_LEN) != 0) {
ESP_LOGE(TAG, "Application not signed with a valid private key.");
return ESP_FAIL;
}

View File

@ -1,184 +0,0 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "sdkconfig.h"
#include "bootloader_flash_priv.h"
#include "bootloader_sha.h"
#include "bootloader_utility.h"
#include "esp_log.h"
#include "esp_image_format.h"
#include "esp_secure_boot.h"
#include "esp_spi_flash.h"
#include "esp_fault.h"
#include "esp32/rom/sha.h"
#include "uECC_verify_antifault.h"
#include <sys/param.h>
#include <string.h>
static const char *TAG = "secure_boot";
#define DIGEST_LEN 32
#ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
extern const uint8_t signature_verification_key_start[] asm("_binary_signature_verification_key_bin_start");
extern const uint8_t signature_verification_key_end[] asm("_binary_signature_verification_key_bin_end");
#define SIGNATURE_VERIFICATION_KEYLEN 64
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
{
uint8_t digest[DIGEST_LEN];
uint8_t verified_digest[DIGEST_LEN] = { 0 }; /* ignored in this function */
const esp_secure_boot_sig_block_t *sigblock;
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
esp_err_t err = bootloader_sha256_flash_contents(src_addr, length, digest);
if (err != ESP_OK) {
return err;
}
// Map the signature block
sigblock = (const esp_secure_boot_sig_block_t *) bootloader_mmap(src_addr + length, sizeof(esp_secure_boot_sig_block_t));
if(!sigblock) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr + length, sizeof(esp_secure_boot_sig_block_t));
return ESP_FAIL;
}
// Verify the signature
err = esp_secure_boot_verify_ecdsa_signature_block(sigblock, digest, verified_digest);
// Unmap
bootloader_munmap(sigblock);
return err;
}
esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest)
{
uint8_t verified_digest[DIGEST_LEN] = { 0 };
return esp_secure_boot_verify_ecdsa_signature_block(sig_block, image_digest, verified_digest);
}
esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
{
ptrdiff_t keylen;
keylen = signature_verification_key_end - signature_verification_key_start;
if (keylen != SIGNATURE_VERIFICATION_KEYLEN) {
ESP_LOGE(TAG, "Embedded public verification key has wrong length %d", keylen);
return ESP_FAIL;
}
if (sig_block->version != 0) {
ESP_LOGE(TAG, "image has invalid signature version field 0x%08x", sig_block->version);
return ESP_FAIL;
}
ESP_LOGD(TAG, "Verifying secure boot signature");
bool is_valid;
is_valid = uECC_verify_antifault(signature_verification_key_start,
image_digest,
DIGEST_LEN,
sig_block->signature,
uECC_secp256r1(),
verified_digest);
ESP_LOGD(TAG, "Verification result %d", is_valid);
return is_valid ? ESP_OK : ESP_ERR_IMAGE_INVALID;
}
#elif CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
{
uint8_t digest[DIGEST_LEN] = {0};
uint8_t verified_digest[DIGEST_LEN] = {0}; // ignored in this function
const uint8_t *data;
/* Padding to round off the input to the nearest 4k boundary */
int padded_length = ALIGN_UP(length, FLASH_SECTOR_SIZE);
ESP_LOGD(TAG, "verifying src_addr 0x%x length", src_addr, padded_length);
data = bootloader_mmap(src_addr, padded_length + sizeof(ets_secure_boot_signature_t));
if (data == NULL) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, padded_length);
return ESP_FAIL;
}
/* Calculate digest of main image */
esp_err_t err = bootloader_sha256_flash_contents(src_addr, padded_length, digest);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, padded_length);
bootloader_munmap(data);
return err;
}
const ets_secure_boot_signature_t *sig_block = (const ets_secure_boot_signature_t *)(data + padded_length);
err = esp_secure_boot_verify_rsa_signature_block(sig_block, digest, verified_digest);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Secure Boot V2 verification failed.");
}
bootloader_munmap(data);
return err;
}
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
{
secure_boot_v2_status_t r;
uint8_t efuse_trusted_digest[DIGEST_LEN] = {0}, sig_block_trusted_digest[DIGEST_LEN] = {0};
memcpy(efuse_trusted_digest, (uint8_t *)EFUSE_BLK2_RDATA0_REG, DIGEST_LEN); /* EFUSE_BLK2_RDATA0_REG - Stores the Secure Boot Public Key Digest */
if (!ets_use_secure_boot_v2()) {
ESP_LOGI(TAG, "Secure Boot eFuse bit(ABS_DONE_1) not yet programmed.");
/* Generating the SHA of the public key components in the signature block */
bootloader_sha256_handle_t sig_block_sha;
sig_block_sha = bootloader_sha256_start();
bootloader_sha256_data(sig_block_sha, &sig_block->block[0].key, sizeof(sig_block->block[0].key));
bootloader_sha256_finish(sig_block_sha, (unsigned char *)sig_block_trusted_digest);
#if CONFIG_SECURE_BOOT_V2_ENABLED
if (memcmp(efuse_trusted_digest, sig_block_trusted_digest, DIGEST_LEN) != 0) {
/* Most likely explanation for this is that BLK2 is empty, and we're going to burn it
after we verify that the signature is valid. However, if BLK2 is not empty then we need to
fail here.
*/
bool all_zeroes = true;
for (int i = 0; i < DIGEST_LEN; i++) {
all_zeroes = all_zeroes && (efuse_trusted_digest[i] == 0);
}
if (!all_zeroes) {
ESP_LOGE(TAG, "Different public key digest burned to eFuse BLK2");
return ESP_ERR_INVALID_STATE;
}
}
ESP_FAULT_ASSERT(!ets_use_secure_boot_v2());
#endif
memcpy(efuse_trusted_digest, sig_block_trusted_digest, DIGEST_LEN);
}
ESP_LOGI(TAG, "Verifying with RSA-PSS...");
r = ets_secure_boot_verify_signature(sig_block, image_digest, efuse_trusted_digest, verified_digest);
if (r != SBV2_SUCCESS) {
ESP_LOGE(TAG, "Secure Boot V2 verification failed.");
}
return (r == SBV2_SUCCESS) ? ESP_OK : ESP_ERR_IMAGE_INVALID;
}
#endif

View File

@ -262,27 +262,32 @@ static void bootloader_super_wdt_auto_feed(void)
REG_WRITE(RTC_CNTL_SWD_WPROTECT_REG, 0);
}
#if CONFIG_ESP32C3_REV_MIN < 3
static inline void bootloader_hardware_init(void)
{
// TODO ESP32-C3 IDF-2452
REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_IPH, 1);
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_1P1_PVT, 12);
if (bootloader_common_get_chip_revision() < 3) {
REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_IPH, 1);
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_1P1_PVT, 12);
}
}
#endif
/* There happend clock glitch reset for some chip when testing wifi[BIT0] and brownout reset when chip startup[BIT1].
* But super_watch_dog_reset function is ok, so open it[BIT2].
* Whether this api will deleted or not depends on analog design & test result when ECO chip come back.
*/
static inline void bootloader_glitch_reset_disable(void)
{
// TODO ESP32-C3 IDF-2453
REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, BIT2);
uint8_t chip_version = bootloader_common_get_chip_revision();
if (chip_version < 2) {
REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST);
} else {
REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST | RTC_CNTL_FIB_BOR_RST);
}
}
esp_err_t bootloader_init(void)
{
esp_err_t ret = ESP_OK;
#if CONFIG_ESP32C3_REV_MIN < 3
bootloader_hardware_init();
#endif
bootloader_glitch_reset_disable();
bootloader_super_wdt_auto_feed();
// protect memory region

View File

@ -31,17 +31,11 @@
static const char *TAG = "secure_boot_v2";
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
#define SIG_BLOCK_MAGIC_BYTE 0xe7
#define CRC_SIGN_BLOCK_LEN 1196
#define SIG_BLOCK_PADDING 4096
#define DIGEST_LEN 32
/* A signature block is valid when it has correct magic byte, crc and image digest. */
static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *block, int block_num, const uint8_t *image_digest)
{
uint32_t crc = esp_rom_crc32_le(0, (uint8_t *)block, CRC_SIGN_BLOCK_LEN);
if (block->magic_byte != SIG_BLOCK_MAGIC_BYTE) {
if (block->magic_byte != ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC) {
// All signature blocks have been parsed, no new signature block present.
ESP_LOGD(TAG, "Signature block(%d) invalid/absent.", block_num);
return ESP_FAIL;
@ -50,7 +44,7 @@ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *blo
ESP_LOGE(TAG, "Magic byte correct but incorrect crc.");
return ESP_FAIL;
}
if (memcmp(image_digest, block->image_digest, DIGEST_LEN)) {
if (memcmp(image_digest, block->image_digest, ESP_SECURE_BOOT_DIGEST_LEN)) {
ESP_LOGE(TAG, "Magic byte & CRC correct but incorrect image digest.");
return ESP_FAIL;
} else {
@ -61,19 +55,6 @@ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *blo
return ESP_FAIL;
}
/* Structure to hold public key digests calculated from the signature blocks of a single image.
Each image can have one or more signature blocks (up to SECURE_BOOT_NUM_BLOCKS). Each signature block
includes a public key.
Different to the ROM ets_secure_boot_key_digests_t structure which holds pointers to eFuse data with digests,
in this data structure the digest data is included.
*/
typedef struct {
uint8_t key_digests[SECURE_BOOT_NUM_BLOCKS][DIGEST_LEN];
unsigned num_digests; /* Number of valid digests, starting at index 0 */
} image_sig_public_key_digests_t;
/* Generates the public key digests of the valid public keys in an image's
signature block, verifies each signature, and stores the key digests in the
public_key_digests structure.
@ -89,16 +70,16 @@ typedef struct {
@return - ESP_OK if no signatures failed to verify, or if no valid signature blocks are found at all.
- ESP_FAIL if there's a valid signature block that doesn't verify using the included public key (unexpected!)
*/
static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, image_sig_public_key_digests_t *public_key_digests)
static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, esp_image_sig_public_key_digests_t *public_key_digests)
{
esp_err_t ret;
uint8_t image_digest[DIGEST_LEN] = {0};
uint8_t __attribute__((aligned(4))) key_digest[DIGEST_LEN] = {0};
uint8_t image_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
uint8_t __attribute__((aligned(4))) key_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
size_t sig_block_addr = flash_offset + ALIGN_UP(flash_size, FLASH_SECTOR_SIZE);
ESP_LOGD(TAG, "calculating public key digests for sig blocks of image offset 0x%x (sig block offset 0x%x)", flash_offset, sig_block_addr);
bzero(public_key_digests, sizeof(image_sig_public_key_digests_t));
bzero(public_key_digests, sizeof(esp_image_sig_public_key_digests_t));
ret = bootloader_sha256_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest);
if (ret != ESP_OK) {
@ -129,7 +110,7 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin
bootloader_sha256_finish(sig_block_sha, key_digest);
// Check we can verify the image using this signature and this key
uint8_t temp_verified_digest[DIGEST_LEN];
uint8_t temp_verified_digest[ESP_SECURE_BOOT_DIGEST_LEN];
bool verified = ets_rsa_pss_verify(&block->key, block->signature, image_digest, temp_verified_digest);
if (!verified) {
@ -142,7 +123,7 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin
}
ESP_LOGD(TAG, "Signature block (%d) is verified", i);
/* Copy the key digest to the buffer provided by the caller */
memcpy((void *)public_key_digests->key_digests[i], key_digest, DIGEST_LEN);
memcpy((void *)public_key_digests->key_digests[i], key_digest, ESP_SECURE_BOOT_DIGEST_LEN);
public_key_digests->num_digests++;
}
@ -173,8 +154,8 @@ static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t
ESP_LOGI(TAG, "Secure boot digests %s", has_secure_boot_digest ? "already present":"absent, generating..");
if (!has_secure_boot_digest) {
image_sig_public_key_digests_t boot_key_digests = {0};
image_sig_public_key_digests_t app_key_digests = {0};
esp_image_sig_public_key_digests_t boot_key_digests = {0};
esp_image_sig_public_key_digests_t app_key_digests = {0};
/* Generate the bootloader public key digests */
ret = s_calculate_image_public_key_digests(bootloader_data.start_addr, bootloader_data.image_len - SIG_BLOCK_PADDING, &boot_key_digests);
@ -234,7 +215,7 @@ static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t
}
for (int j = 0; j < app_key_digests.num_digests; j++) {
if (!memcmp(boot_key_digests.key_digests[i], app_key_digests.key_digests[j], DIGEST_LEN)) {
if (!memcmp(boot_key_digests.key_digests[i], app_key_digests.key_digests[j], ESP_SECURE_BOOT_DIGEST_LEN)) {
ESP_LOGI(TAG, "Application key(%d) matches with bootloader key(%d).", j, i);
match = true;
}

View File

@ -1,94 +0,0 @@
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "sdkconfig.h"
#include <string.h>
#include "esp_fault.h"
#include "bootloader_flash_priv.h"
#include "bootloader_sha.h"
#include "bootloader_utility.h"
#include "esp_log.h"
#include "esp_image_format.h"
#include "esp_secure_boot.h"
#include "esp32c3/rom/secure_boot.h"
static const char* TAG = "secure_boot";
#define DIGEST_LEN 32
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
{
uint8_t digest[DIGEST_LEN];
uint8_t verified_digest[DIGEST_LEN] = { 0 }; /* Note: this function doesn't do any anti-FI checks on this buffer */
const uint8_t *data;
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
/* Padding to round off the input to the nearest 4k boundary */
int padded_length = ALIGN_UP(length, FLASH_SECTOR_SIZE);
ESP_LOGD(TAG, "verifying src_addr 0x%x length", src_addr, padded_length);
data = bootloader_mmap(src_addr, length + sizeof(struct ets_secure_boot_sig_block));
if (data == NULL) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, length+sizeof(ets_secure_boot_signature_t));
return ESP_FAIL;
}
/* Calculate digest of main image */
esp_err_t err = bootloader_sha256_flash_contents(src_addr, padded_length, digest);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, padded_length);
bootloader_munmap(data);
return err;
}
const ets_secure_boot_signature_t *sig = (const ets_secure_boot_signature_t *)(data + length);
int r = esp_secure_boot_verify_rsa_signature_block(sig, digest, verified_digest);
bootloader_munmap(data);
return (r == ETS_OK) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
{
ets_secure_boot_key_digests_t trusted_keys;
ets_secure_boot_key_digests_t trusted_key_copies[2];
ETS_STATUS r;
ets_secure_boot_status_t sb_result;
memset(&trusted_keys, 0, sizeof(ets_secure_boot_key_digests_t));
memset(trusted_key_copies, 0, 2 * sizeof(ets_secure_boot_key_digests_t));
if (!esp_secure_boot_enabled()) {
return ESP_OK;
}
r = ets_secure_boot_read_key_digests(&trusted_keys);
if (r != ETS_OK) {
ESP_LOGI(TAG, "Could not read secure boot digests!");
return ESP_FAIL;
}
// Create the copies for FI checks (assuming result is ETS_OK, if it's not then it'll fail the fault check anyhow)
ets_secure_boot_read_key_digests(&trusted_key_copies[0]);
ets_secure_boot_read_key_digests(&trusted_key_copies[1]);
ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[0], sizeof(ets_secure_boot_key_digests_t)) == 0);
ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[1], sizeof(ets_secure_boot_key_digests_t)) == 0);
ESP_LOGI(TAG, "Verifying with RSA-PSS boot...");
sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, &trusted_keys, verified_digest);
return (sb_result == SB_SUCCESS) ? ESP_OK : ESP_FAIL;
}

View File

@ -31,17 +31,11 @@
static const char *TAG = "secure_boot_v2";
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
#define SIG_BLOCK_MAGIC_BYTE 0xe7
#define CRC_SIGN_BLOCK_LEN 1196
#define SIG_BLOCK_PADDING 4096
#define DIGEST_LEN 32
/* A signature block is valid when it has correct magic byte, crc and image digest. */
static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *block, int block_num, const uint8_t *image_digest)
{
uint32_t crc = esp_rom_crc32_le(0, (uint8_t *)block, CRC_SIGN_BLOCK_LEN);
if (block->magic_byte != SIG_BLOCK_MAGIC_BYTE) {
if (block->magic_byte != ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC) {
// All signature blocks have been parsed, no new signature block present.
ESP_LOGD(TAG, "Signature block(%d) invalid/absent.", block_num);
return ESP_FAIL;
@ -50,7 +44,7 @@ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *blo
ESP_LOGE(TAG, "Magic byte correct but incorrect crc.");
return ESP_FAIL;
}
if (memcmp(image_digest, block->image_digest, DIGEST_LEN)) {
if (memcmp(image_digest, block->image_digest, ESP_SECURE_BOOT_DIGEST_LEN)) {
ESP_LOGE(TAG, "Magic byte & CRC correct but incorrect image digest.");
return ESP_FAIL;
} else {
@ -61,19 +55,6 @@ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *blo
return ESP_FAIL;
}
/* Structure to hold public key digests calculated from the signature blocks of a single image.
Each image can have one or more signature blocks (up to SECURE_BOOT_NUM_BLOCKS). Each signature block
includes a public key.
Different to the ROM ets_secure_boot_key_digests_t structure which holds pointers to eFuse data with digests,
in this data structure the digest data is included.
*/
typedef struct {
uint8_t key_digests[SECURE_BOOT_NUM_BLOCKS][DIGEST_LEN];
unsigned num_digests; /* Number of valid digests, starting at index 0 */
} image_sig_public_key_digests_t;
/* Generates the public key digests of the valid public keys in an image's
signature block, verifies each signature, and stores the key digests in the
public_key_digests structure.
@ -89,16 +70,16 @@ typedef struct {
@return - ESP_OK if no signatures failed to verify, or if no valid signature blocks are found at all.
- ESP_FAIL if there's a valid signature block that doesn't verify using the included public key (unexpected!)
*/
static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, image_sig_public_key_digests_t *public_key_digests)
static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, esp_image_sig_public_key_digests_t *public_key_digests)
{
esp_err_t ret;
uint8_t image_digest[DIGEST_LEN] = {0};
uint8_t __attribute__((aligned(4))) key_digest[DIGEST_LEN] = {0};
uint8_t image_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
uint8_t __attribute__((aligned(4))) key_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
size_t sig_block_addr = flash_offset + ALIGN_UP(flash_size, FLASH_SECTOR_SIZE);
ESP_LOGD(TAG, "calculating public key digests for sig blocks of image offset 0x%x (sig block offset 0x%x)", flash_offset, sig_block_addr);
bzero(public_key_digests, sizeof(image_sig_public_key_digests_t));
bzero(public_key_digests, sizeof(esp_image_sig_public_key_digests_t));
ret = bootloader_sha256_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest);
if (ret != ESP_OK) {
@ -129,7 +110,7 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin
bootloader_sha256_finish(sig_block_sha, key_digest);
// Check we can verify the image using this signature and this key
uint8_t temp_verified_digest[DIGEST_LEN];
uint8_t temp_verified_digest[ESP_SECURE_BOOT_DIGEST_LEN];
bool verified = ets_rsa_pss_verify(&block->key, block->signature, image_digest, temp_verified_digest);
if (!verified) {
@ -142,7 +123,7 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin
}
ESP_LOGD(TAG, "Signature block (%d) is verified", i);
/* Copy the key digest to the buffer provided by the caller */
memcpy((void *)public_key_digests->key_digests[i], key_digest, DIGEST_LEN);
memcpy((void *)public_key_digests->key_digests[i], key_digest, ESP_SECURE_BOOT_DIGEST_LEN);
public_key_digests->num_digests++;
}
@ -173,8 +154,8 @@ static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t
ESP_LOGI(TAG, "Secure boot digests %s", has_secure_boot_digest ? "already present":"absent, generating..");
if (!has_secure_boot_digest) {
image_sig_public_key_digests_t boot_key_digests = {0};
image_sig_public_key_digests_t app_key_digests = {0};
esp_image_sig_public_key_digests_t boot_key_digests = {0};
esp_image_sig_public_key_digests_t app_key_digests = {0};
/* Generate the bootloader public key digests */
ret = s_calculate_image_public_key_digests(bootloader_data.start_addr, bootloader_data.image_len - SIG_BLOCK_PADDING, &boot_key_digests);
@ -234,7 +215,7 @@ static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t
}
for (int j = 0; j < app_key_digests.num_digests; j++) {
if (!memcmp(boot_key_digests.key_digests[i], app_key_digests.key_digests[j], DIGEST_LEN)) {
if (!memcmp(boot_key_digests.key_digests[i], app_key_digests.key_digests[j], ESP_SECURE_BOOT_DIGEST_LEN)) {
ESP_LOGI(TAG, "Application key(%d) matches with bootloader key(%d).", j, i);
match = true;
}

View File

@ -1,93 +0,0 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "sdkconfig.h"
#include <string.h>
#include "esp_fault.h"
#include "bootloader_flash_priv.h"
#include "bootloader_sha.h"
#include "bootloader_utility.h"
#include "esp_log.h"
#include "esp_image_format.h"
#include "esp_secure_boot.h"
#include "esp32s2/rom/secure_boot.h"
static const char* TAG = "secure_boot";
#define DIGEST_LEN 32
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
{
uint8_t digest[DIGEST_LEN];
uint8_t verified_digest[DIGEST_LEN] = { 0 }; /* Note: this function doesn't do any anti-FI checks on this buffer */
const uint8_t *data;
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
/* Padding to round off the input to the nearest 4k boundary */
int padded_length = ALIGN_UP(length, FLASH_SECTOR_SIZE);
ESP_LOGD(TAG, "verifying src_addr 0x%x length", src_addr, padded_length);
data = bootloader_mmap(src_addr, length + sizeof(struct ets_secure_boot_sig_block));
if (data == NULL) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, length+sizeof(ets_secure_boot_signature_t));
return ESP_FAIL;
}
/* Calculate digest of main image */
esp_err_t err = bootloader_sha256_flash_contents(src_addr, padded_length, digest);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, padded_length);
bootloader_munmap(data);
return err;
}
const ets_secure_boot_signature_t *sig = (const ets_secure_boot_signature_t *)(data + length);
int r = esp_secure_boot_verify_rsa_signature_block(sig, digest, verified_digest);
bootloader_munmap(data);
return (r == ETS_OK) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
{
ets_secure_boot_key_digests_t trusted_keys;
ets_secure_boot_key_digests_t trusted_key_copies[2];
ETS_STATUS r;
ets_secure_boot_status_t sb_result;
memset(&trusted_keys, 0, sizeof(ets_secure_boot_key_digests_t));
memset(trusted_key_copies, 0, 2 * sizeof(ets_secure_boot_key_digests_t));
if (!esp_secure_boot_enabled()) {
return ESP_OK;
}
r = ets_secure_boot_read_key_digests(&trusted_keys);
if (r != ETS_OK) {
ESP_LOGI(TAG, "Could not read secure boot digests!");
return ESP_FAIL;
}
// Create the copies for FI checks (assuming result is ETS_OK, if it's not then it'll fail the fault check anyhow)
ets_secure_boot_read_key_digests(&trusted_key_copies[0]);
ets_secure_boot_read_key_digests(&trusted_key_copies[1]);
ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[0], sizeof(ets_secure_boot_key_digests_t)) == 0);
ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[1], sizeof(ets_secure_boot_key_digests_t)) == 0);
ESP_LOGI(TAG, "Verifying with RSA-PSS boot...");
sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, &trusted_keys, verified_digest);
return (sb_result == SB_SUCCESS) ? ESP_OK : ESP_FAIL;
}

View File

@ -31,17 +31,11 @@
static const char *TAG = "secure_boot_v2";
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
#define SIG_BLOCK_MAGIC_BYTE 0xe7
#define CRC_SIGN_BLOCK_LEN 1196
#define SIG_BLOCK_PADDING 4096
#define DIGEST_LEN 32
/* A signature block is valid when it has correct magic byte, crc and image digest. */
static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *block, int block_num, const uint8_t *image_digest)
{
uint32_t crc = esp_rom_crc32_le(0, (uint8_t *)block, CRC_SIGN_BLOCK_LEN);
if (block->magic_byte != SIG_BLOCK_MAGIC_BYTE) {
if (block->magic_byte != ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC) {
// All signature blocks have been parsed, no new signature block present.
ESP_LOGD(TAG, "Signature block(%d) invalid/absent.", block_num);
return ESP_FAIL;
@ -50,7 +44,7 @@ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *blo
ESP_LOGE(TAG, "Magic byte correct but incorrect crc.");
return ESP_FAIL;
}
if (memcmp(image_digest, block->image_digest, DIGEST_LEN)) {
if (memcmp(image_digest, block->image_digest, ESP_SECURE_BOOT_DIGEST_LEN)) {
ESP_LOGE(TAG, "Magic byte & CRC correct but incorrect image digest.");
return ESP_FAIL;
} else {
@ -61,19 +55,6 @@ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *blo
return ESP_FAIL;
}
/* Structure to hold public key digests calculated from the signature blocks of a single image.
Each image can have one or more signature blocks (up to SECURE_BOOT_NUM_BLOCKS). Each signature block
includes a public key.
Different to the ROM ets_secure_boot_key_digests_t structure which holds pointers to eFuse data with digests,
in this data structure the digest data is included.
*/
typedef struct {
uint8_t key_digests[SECURE_BOOT_NUM_BLOCKS][DIGEST_LEN];
unsigned num_digests; /* Number of valid digests, starting at index 0 */
} image_sig_public_key_digests_t;
/* Generates the public key digests of the valid public keys in an image's
signature block, verifies each signature, and stores the key digests in the
public_key_digests structure.
@ -89,16 +70,16 @@ typedef struct {
@return - ESP_OK if no signatures failed to verify, or if no valid signature blocks are found at all.
- ESP_FAIL if there's a valid signature block that doesn't verify using the included public key (unexpected!)
*/
static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, image_sig_public_key_digests_t *public_key_digests)
static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, esp_image_sig_public_key_digests_t *public_key_digests)
{
esp_err_t ret;
uint8_t image_digest[DIGEST_LEN] = {0};
uint8_t __attribute__((aligned(4))) key_digest[DIGEST_LEN] = {0};
uint8_t image_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
uint8_t __attribute__((aligned(4))) key_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
size_t sig_block_addr = flash_offset + ALIGN_UP(flash_size, FLASH_SECTOR_SIZE);
ESP_LOGD(TAG, "calculating public key digests for sig blocks of image offset 0x%x (sig block offset 0x%x)", flash_offset, sig_block_addr);
bzero(public_key_digests, sizeof(image_sig_public_key_digests_t));
bzero(public_key_digests, sizeof(esp_image_sig_public_key_digests_t));
ret = bootloader_sha256_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest);
if (ret != ESP_OK) {
@ -129,7 +110,7 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin
bootloader_sha256_finish(sig_block_sha, key_digest);
// Check we can verify the image using this signature and this key
uint8_t temp_verified_digest[DIGEST_LEN];
uint8_t temp_verified_digest[ESP_SECURE_BOOT_DIGEST_LEN];
bool verified = ets_rsa_pss_verify(&block->key, block->signature, image_digest, temp_verified_digest);
if (!verified) {
@ -142,7 +123,7 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin
}
ESP_LOGD(TAG, "Signature block (%d) is verified", i);
/* Copy the key digest to the buffer provided by the caller */
memcpy((void *)public_key_digests->key_digests[i], key_digest, DIGEST_LEN);
memcpy((void *)public_key_digests->key_digests[i], key_digest, ESP_SECURE_BOOT_DIGEST_LEN);
public_key_digests->num_digests++;
}
@ -173,8 +154,8 @@ static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t
ESP_LOGI(TAG, "Secure boot digests %s", has_secure_boot_digest ? "already present":"absent, generating..");
if (!has_secure_boot_digest) {
image_sig_public_key_digests_t boot_key_digests = {0};
image_sig_public_key_digests_t app_key_digests = {0};
esp_image_sig_public_key_digests_t boot_key_digests = {0};
esp_image_sig_public_key_digests_t app_key_digests = {0};
/* Generate the bootloader public key digests */
ret = s_calculate_image_public_key_digests(bootloader_data.start_addr, bootloader_data.image_len - SIG_BLOCK_PADDING, &boot_key_digests);
@ -234,7 +215,7 @@ static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t
}
for (int j = 0; j < app_key_digests.num_digests; j++) {
if (!memcmp(boot_key_digests.key_digests[i], app_key_digests.key_digests[j], DIGEST_LEN)) {
if (!memcmp(boot_key_digests.key_digests[i], app_key_digests.key_digests[j], ESP_SECURE_BOOT_DIGEST_LEN)) {
ESP_LOGI(TAG, "Application key(%d) matches with bootloader key(%d).", j, i);
match = true;
}

View File

@ -1,93 +0,0 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string.h>
#include "sdkconfig.h"
#include "esp_fault.h"
#include "bootloader_flash_priv.h"
#include "bootloader_sha.h"
#include "bootloader_utility.h"
#include "esp_log.h"
#include "esp_image_format.h"
#include "esp_secure_boot.h"
#include "esp32s3/rom/secure_boot.h"
static const char* TAG = "secure_boot";
#define DIGEST_LEN 32
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
{
uint8_t digest[DIGEST_LEN];
uint8_t verified_digest[DIGEST_LEN] = { 0 }; /* Note: this function doesn't do any anti-FI checks on this buffer */
const uint8_t *data;
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
/* Padding to round off the input to the nearest 4k boundary */
int padded_length = ALIGN_UP(length, FLASH_SECTOR_SIZE);
ESP_LOGD(TAG, "verifying src_addr 0x%x length", src_addr, padded_length);
data = bootloader_mmap(src_addr, length + sizeof(struct ets_secure_boot_sig_block));
if (data == NULL) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, length+sizeof(ets_secure_boot_signature_t));
return ESP_FAIL;
}
/* Calculate digest of main image */
esp_err_t err = bootloader_sha256_flash_contents(src_addr, padded_length, digest);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, padded_length);
bootloader_munmap(data);
return err;
}
const ets_secure_boot_signature_t *sig = (const ets_secure_boot_signature_t *)(data + length);
int r = esp_secure_boot_verify_rsa_signature_block(sig, digest, verified_digest);
bootloader_munmap(data);
return (r == ETS_OK) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
{
ets_secure_boot_key_digests_t trusted_keys;
ets_secure_boot_key_digests_t trusted_key_copies[2];
ETS_STATUS r;
ets_secure_boot_status_t sb_result;
memset(&trusted_keys, 0, sizeof(ets_secure_boot_key_digests_t));
memset(trusted_key_copies, 0, 2 * sizeof(ets_secure_boot_key_digests_t));
if (!esp_secure_boot_enabled()) {
return ESP_OK;
}
r = ets_secure_boot_read_key_digests(&trusted_keys);
if (r != ETS_OK) {
ESP_LOGI(TAG, "Could not read secure boot digests!");
return ESP_FAIL;
}
// Create the copies for FI checks (assuming result is ETS_OK, if it's not then it'll fail the fault check anyhow)
ets_secure_boot_read_key_digests(&trusted_key_copies[0]);
ets_secure_boot_read_key_digests(&trusted_key_copies[1]);
ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[0], sizeof(ets_secure_boot_key_digests_t)) == 0);
ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[1], sizeof(ets_secure_boot_key_digests_t)) == 0);
ESP_LOGI(TAG, "Verifying with RSA-PSS boot...");
sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, &trusted_keys, verified_digest);
return (sb_result == SB_SUCCESS) ? ESP_OK : ESP_FAIL;
}

View File

@ -327,11 +327,24 @@ err:
esp_err_t bootloader_load_image(const esp_partition_pos_t *part, esp_image_metadata_t *data)
{
#ifdef BOOTLOADER_BUILD
return image_load(ESP_IMAGE_LOAD, part, data);
#else
#if !defined(BOOTLOADER_BUILD)
return ESP_FAIL;
#endif
#else
esp_image_load_mode_t mode = ESP_IMAGE_LOAD;
#if !defined(CONFIG_SECURE_BOOT)
/* Skip validation under particular configurations */
#if CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS
mode = ESP_IMAGE_LOAD_NO_VALIDATE;
#elif CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON
if (rtc_get_reset_reason(0) == POWERON_RESET) {
mode = ESP_IMAGE_LOAD_NO_VALIDATE;
}
#endif // CONFIG_BOOTLOADER_SKIP_...
#endif // CONFIG_SECURE_BOOT
return image_load(mode, part, data);
#endif // BOOTLOADER_BUILD
}
esp_err_t bootloader_load_image_no_verify(const esp_partition_pos_t *part, esp_image_metadata_t *data)
@ -348,6 +361,45 @@ esp_err_t esp_image_verify(esp_image_load_mode_t mode, const esp_partition_pos_t
return image_load(mode, part, data);
}
esp_err_t esp_image_get_metadata(const esp_partition_pos_t *part, esp_image_metadata_t *metadata)
{
if (metadata == NULL || part == NULL || part->size > SIXTEEN_MB) {
return ESP_ERR_INVALID_ARG;
}
memset(metadata, 0, sizeof(esp_image_metadata_t));
metadata->start_addr = part->offset;
esp_err_t err = bootloader_flash_read(metadata->start_addr, &metadata->image, sizeof(esp_image_header_t), true);
if (err != ESP_OK) {
return err;
}
uint32_t next_addr = metadata->start_addr + sizeof(esp_image_header_t);
for (int i = 0; i < metadata->image.segment_count; i++) {
esp_image_segment_header_t *header = &metadata->segments[i];
err = process_segment(i, next_addr, header, true, false, NULL, NULL);
if (err != ESP_OK) {
return err;
}
next_addr += sizeof(esp_image_segment_header_t);
metadata->segment_data[i] = next_addr;
next_addr += header->data_len;
}
metadata->image_len = next_addr - metadata->start_addr;
// checksum
uint32_t unpadded_length = metadata->image_len;
uint32_t length = unpadded_length + 1; // Add a byte for the checksum
length = (length + 15) & ~15; // Pad to next full 16 byte block
if (metadata->image.hash_appended) {
// Account for the hash in the total image length
length += HASH_LEN;
}
metadata->image_len = length;
return ESP_OK;
}
static esp_err_t verify_image_header(uint32_t src_addr, const esp_image_header_t *image, bool silent)
{
esp_err_t err = ESP_OK;
@ -808,18 +860,18 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han
// Use hash to verify signature block
esp_err_t err = ESP_ERR_IMAGE_INVALID;
#if defined(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME) || defined(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME)
const void *sig_block;
#ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
ESP_FAULT_ASSERT(memcmp(image_digest, verified_digest, HASH_LEN) != 0); /* sanity check that these values start differently */
#ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
sig_block = bootloader_mmap(data->start_addr + data->image_len, sizeof(esp_secure_boot_sig_block_t));
err = esp_secure_boot_verify_ecdsa_signature_block(sig_block, image_digest, verified_digest);
#elif CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
ESP_FAULT_ASSERT(memcmp(image_digest, verified_digest, HASH_LEN) != 0); /* sanity check that these values start differently */
#else
sig_block = bootloader_mmap(end, sizeof(ets_secure_boot_signature_t));
err = esp_secure_boot_verify_rsa_signature_block(sig_block, image_digest, verified_digest);
#endif
bootloader_munmap(sig_block);
#endif // CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME or CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
if (err != ESP_OK) {
ESP_LOGE(TAG, "Secure boot signature verification failed");

View File

@ -1,339 +0,0 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "sdkconfig.h"
#include "bootloader_flash_priv.h"
#include "bootloader_sha.h"
#include "bootloader_utility.h"
#include "esp_log.h"
#include "esp_image_format.h"
#include "esp_secure_boot.h"
#include "mbedtls/sha256.h"
#include "mbedtls/x509.h"
#include "mbedtls/md.h"
#include "mbedtls/platform.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include <string.h>
#include <sys/param.h>
#include "esp_secure_boot.h"
#ifdef CONFIG_IDF_TARGET_ESP32S2
#include <esp32s2/rom/secure_boot.h>
#elif CONFIG_IDF_TARGET_ESP32C3
#include <esp32c3/rom/secure_boot.h>
#endif
#define DIGEST_LEN 32
#ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
static const char *TAG = "secure_boot_v1";
extern const uint8_t signature_verification_key_start[] asm("_binary_signature_verification_key_bin_start");
extern const uint8_t signature_verification_key_end[] asm("_binary_signature_verification_key_bin_end");
#define SIGNATURE_VERIFICATION_KEYLEN 64
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
{
uint8_t digest[DIGEST_LEN];
uint8_t verified_digest[DIGEST_LEN];
const esp_secure_boot_sig_block_t *sigblock;
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
esp_err_t err = bootloader_sha256_flash_contents(src_addr, length, digest);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, length);
return err;
}
// Map the signature block and verify the signature
sigblock = (const esp_secure_boot_sig_block_t *)bootloader_mmap(src_addr + length, sizeof(esp_secure_boot_sig_block_t));
if (sigblock == NULL) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr + length, sizeof(esp_secure_boot_sig_block_t));
return ESP_FAIL;
}
err = esp_secure_boot_verify_ecdsa_signature_block(sigblock, digest, verified_digest);
bootloader_munmap(sigblock);
return err;
}
esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
{
#if !(defined(CONFIG_MBEDTLS_ECDSA_C) && defined(CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED))
ESP_LOGE(TAG, "Signature verification requires ECDSA & SECP256R1 curve enabled");
return ESP_ERR_NOT_SUPPORTED;
#else
ptrdiff_t keylen;
/* Note: in IDF app image verification we don't add any fault injection resistance, boot-time checks only */
memset(verified_digest, 0, DIGEST_LEN);
keylen = signature_verification_key_end - signature_verification_key_start;
if (keylen != SIGNATURE_VERIFICATION_KEYLEN) {
ESP_LOGE(TAG, "Embedded public verification key has wrong length %d", keylen);
return ESP_FAIL;
}
if (sig_block->version != 0) {
ESP_LOGE(TAG, "image has invalid signature version field 0x%08x", sig_block->version);
return ESP_FAIL;
}
ESP_LOGD(TAG, "Verifying secure boot signature");
int ret;
mbedtls_mpi r, s;
mbedtls_mpi_init(&r);
mbedtls_mpi_init(&s);
/* Extract r and s components from RAW ECDSA signature of 64 bytes */
#define ECDSA_INTEGER_LEN 32
ret = mbedtls_mpi_read_binary(&r, &sig_block->signature[0], ECDSA_INTEGER_LEN);
if (ret != 0) {
ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(1), err:%d", ret);
return ESP_FAIL;
}
ret = mbedtls_mpi_read_binary(&s, &sig_block->signature[ECDSA_INTEGER_LEN], ECDSA_INTEGER_LEN);
if (ret != 0) {
ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(2), err:%d", ret);
mbedtls_mpi_free(&r);
return ESP_FAIL;
}
/* Initialise ECDSA context */
mbedtls_ecdsa_context ecdsa_context;
mbedtls_ecdsa_init(&ecdsa_context);
mbedtls_ecp_group_load(&ecdsa_context.grp, MBEDTLS_ECP_DP_SECP256R1);
size_t plen = mbedtls_mpi_size(&ecdsa_context.grp.P);
if (keylen != 2 * plen) {
ESP_LOGE(TAG, "Incorrect ECDSA key length %d", keylen);
ret = ESP_FAIL;
goto cleanup;
}
/* Extract X and Y components from ECDSA public key */
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ecdsa_context.Q.X, signature_verification_key_start, plen));
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ecdsa_context.Q.Y, signature_verification_key_start + plen, plen));
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ecdsa_context.Q.Z, 1));
ret = mbedtls_ecdsa_verify(&ecdsa_context.grp, image_digest, DIGEST_LEN, &ecdsa_context.Q, &r, &s);
ESP_LOGD(TAG, "Verification result %d", ret);
cleanup:
mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s);
mbedtls_ecdsa_free(&ecdsa_context);
return ret == 0 ? ESP_OK : ESP_ERR_IMAGE_INVALID;
#endif // CONFIG_MBEDTLS_ECDSA_C && CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED
}
#elif CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
static const char *TAG = "secure_boot_v2";
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
#define RSA_KEY_SIZE 384 /* RSA 3072 Bits */
#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1
inline static bool digest_matches(const void *trusted, const void *computed)
{
if (trusted == NULL) {
return false;
}
// 'trusted' is probably a pointer to read-only efuse registers,
// which only support word reads. memcmp() cannot be guaranteed
// to do word reads, so we make a local copy here (we know that
// memcpy() will do word operations if it can).
uint8_t __attribute__((aligned(4))) trusted_local[ETS_DIGEST_LEN];
uint8_t __attribute__((aligned(4))) computed_local[ETS_DIGEST_LEN];
memcpy(trusted_local, trusted, ETS_DIGEST_LEN);
memcpy(computed_local, computed, ETS_DIGEST_LEN);
return memcmp(trusted_local, computed_local, ETS_DIGEST_LEN) == 0;
}
#endif /* SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1 */
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
{
uint8_t digest[DIGEST_LEN] = {0};
uint8_t verified_digest[DIGEST_LEN] = {0};
/* Rounding off length to the upper 4k boundary */
uint32_t padded_length = ALIGN_UP(length, FLASH_SECTOR_SIZE);
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
esp_err_t err = bootloader_sha256_flash_contents(src_addr, padded_length, digest);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, padded_length);
return err;
}
const ets_secure_boot_signature_t *sig_block = bootloader_mmap(src_addr + padded_length, sizeof(ets_secure_boot_signature_t));
if (sig_block == NULL) {
ESP_LOGE(TAG, "Failed to mmap data at offset 0x%x", src_addr + padded_length);
return ESP_FAIL;
}
err = esp_secure_boot_verify_rsa_signature_block(sig_block, digest, verified_digest);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Secure Boot V2 verification failed.");
}
bootloader_munmap(sig_block);
return err;
}
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
{
uint8_t i = 0;
#if CONFIG_SECURE_BOOT_V2_ENABLED /* Verify key against efuse block */
uint8_t sig_block_key_digest[SECURE_BOOT_NUM_BLOCKS][DIGEST_LEN] = {0};
/* Note: in IDF verification we don't add any fault injection resistance, as we don't expect this to be called
during boot-time verification. */
memset(verified_digest, 0, DIGEST_LEN);
/* Generating the SHA of the public key components in the signature block */
for (i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
bootloader_sha256_handle_t sig_block_sha;
sig_block_sha = bootloader_sha256_start();
bootloader_sha256_data(sig_block_sha, &sig_block->block[i].key, sizeof(sig_block->block[i].key));
bootloader_sha256_finish(sig_block_sha, (unsigned char *)sig_block_key_digest[i]);
}
#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS == 1
uint8_t efuse_trusted_digest[DIGEST_LEN] = {0};
memcpy(efuse_trusted_digest, (uint8_t *) EFUSE_BLK2_RDATA0_REG, sizeof(efuse_trusted_digest));
if (memcmp(efuse_trusted_digest, sig_block_key_digest[0], DIGEST_LEN) != 0) {
const uint8_t zeroes[DIGEST_LEN] = {0};
/* Can't continue if secure boot is enabled, OR if a different digest is already written in efuse BLK2
(If BLK2 is empty and Secure Boot is disabled then we assume that it will be enabled later.)
*/
if (esp_secure_boot_enabled() || memcmp(efuse_trusted_digest, zeroes, DIGEST_LEN) != 0) {
ESP_LOGE(TAG, "Public key digest in eFuse BLK2 and the signature block don't match.");
return ESP_FAIL;
}
}
#elif SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1
bool match = false;
ets_secure_boot_key_digests_t efuse_trusted_digest;
ETS_STATUS r;
r = ets_secure_boot_read_key_digests(&efuse_trusted_digest);
if (r != 0) {
ESP_LOGI(TAG, "Could not read secure boot digests!");
return ESP_FAIL;
}
#endif /* SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS */
#endif /* CONFIG_SECURE_BOOT_V2_ENABLED */
ESP_LOGI(TAG, "Verifying with RSA-PSS...");
int ret = 0;
mbedtls_rsa_context pk;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
unsigned char *sig_be = calloc(1, RSA_KEY_SIZE);
unsigned char *buf = calloc(1, RSA_KEY_SIZE);
if (sig_be == NULL || buf == NULL) {
return ESP_ERR_NO_MEM;
}
mbedtls_entropy_init(&entropy);
mbedtls_ctr_drbg_init(&ctr_drbg);
ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0);
if (ret != 0) {
ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned -0x%04x\n", ret);
goto exit;
}
for (i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1
for (uint8_t j = 0; j < SECURE_BOOT_NUM_BLOCKS; j++) {
if (digest_matches(efuse_trusted_digest.key_digests[j], sig_block_key_digest[i])) {
ESP_LOGI(TAG, "eFuse key matches(%d) matches the application key(%d).", j, i);
match = true;
break;
}
}
if (match == false) {
continue; // Skip the public keys whose digests don't match.
}
# endif // SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1
const mbedtls_mpi N = { .s = 1,
.n = sizeof(sig_block->block[i].key.n)/sizeof(mbedtls_mpi_uint),
.p = (void *)sig_block->block[i].key.n,
};
const mbedtls_mpi e = { .s = 1,
.n = sizeof(sig_block->block[i].key.e)/sizeof(mbedtls_mpi_uint), // 1
.p = (void *)&sig_block->block[i].key.e,
};
mbedtls_rsa_init(&pk, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
ret = mbedtls_rsa_import(&pk, &N, NULL, NULL, NULL, &e);
if (ret != 0) {
ESP_LOGE(TAG, "Failed mbedtls_rsa_import, err: %d", ret);
goto exit;
}
ret = mbedtls_rsa_complete(&pk);
if (ret != 0) {
ESP_LOGE(TAG, "Failed mbedtls_rsa_complete, err: %d", ret);
goto exit;
}
ret = mbedtls_rsa_check_pubkey(&pk);
if (ret != 0) {
ESP_LOGI(TAG, "Key is not an RSA key -%0x", -ret);
goto exit;
}
/* Signature needs to be byte swapped into BE representation */
for (int j = 0; j < RSA_KEY_SIZE; j++) {
sig_be[RSA_KEY_SIZE- j - 1] = sig_block->block[i].signature[j];
}
ret = mbedtls_rsa_public( &pk, sig_be, buf);
if (ret != 0) {
ESP_LOGE(TAG, "mbedtls_rsa_public failed, err: %d", ret);
goto exit;
}
ret = mbedtls_rsa_rsassa_pss_verify( &pk, mbedtls_ctr_drbg_random, &ctr_drbg, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256, DIGEST_LEN,
image_digest, sig_be);
if (ret != 0) {
ESP_LOGE(TAG, "Failed mbedtls_rsa_rsassa_pss_verify, err: %d", ret);
} else {
ESP_LOGI(TAG, "Signature verified successfully!");
}
exit:
mbedtls_rsa_free(&pk);
if (ret == 0) {
break;
}
}
free(sig_be);
free(buf);
#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS == 1
return (ret != 0) ? ESP_ERR_IMAGE_INVALID: ESP_OK;
#elif SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1
return (ret != 0 || match == false) ? ESP_ERR_IMAGE_INVALID: ESP_OK;
#endif /* CONFIG_IDF_TARGET_ESP32 */
}
#endif

View File

@ -0,0 +1,57 @@
// Copyright 2015-2019 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.
#include <strings.h>
#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_efuse.h"
#include "esp_efuse_table.h"
#include "esp_secure_boot.h"
#ifndef BOOTLOADER_BUILD
static __attribute__((unused)) const char *TAG = "secure_boot";
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
static void rsa_check_signature_on_update_check(void)
{
// We rely on the keys used to sign this app to verify the next app on OTA, so make sure there is at
// least one to avoid a stuck firmware
esp_image_sig_public_key_digests_t digests = { 0 };
esp_err_t err = esp_secure_boot_get_signature_blocks_for_running_app(false, &digests);
if (err != ESP_OK || digests.num_digests == 0) {
ESP_LOGE(TAG, "This app is not signed, but check signature on update is enabled in config. It won't be possible to verify any update.");
abort();
}
#if CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT && SECURE_BOOT_NUM_BLOCKS > 1
if (digests.num_digests > 1) {
ESP_LOGW(TAG, "App has %d signatures. Only the first position of signature blocks is used to verify any update", digests.num_digests);
}
#endif
}
#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
void esp_secure_boot_init_checks(void)
{
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
rsa_check_signature_on_update_check();
#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
}
#endif // not BOOTLOADER_BUILD

View File

@ -0,0 +1,136 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "sdkconfig.h"
#include "bootloader_flash_priv.h"
#include "bootloader_sha.h"
#include "bootloader_utility.h"
#include "esp_log.h"
#include "esp_image_format.h"
#include "esp_secure_boot.h"
#include "mbedtls/sha256.h"
#include "mbedtls/x509.h"
#include "mbedtls/md.h"
#include "mbedtls/platform.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include <string.h>
#include <sys/param.h>
#ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
static const char *TAG = "secure_boot_v1";
extern const uint8_t signature_verification_key_start[] asm("_binary_signature_verification_key_bin_start");
extern const uint8_t signature_verification_key_end[] asm("_binary_signature_verification_key_bin_end");
#define SIGNATURE_VERIFICATION_KEYLEN 64
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
{
uint8_t digest[ESP_SECURE_BOOT_DIGEST_LEN];
uint8_t verified_digest[ESP_SECURE_BOOT_DIGEST_LEN];
const esp_secure_boot_sig_block_t *sigblock;
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
esp_err_t err = bootloader_sha256_flash_contents(src_addr, length, digest);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, length);
return err;
}
// Map the signature block and verify the signature
sigblock = (const esp_secure_boot_sig_block_t *)bootloader_mmap(src_addr + length, sizeof(esp_secure_boot_sig_block_t));
if (sigblock == NULL) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr + length, sizeof(esp_secure_boot_sig_block_t));
return ESP_FAIL;
}
err = esp_secure_boot_verify_ecdsa_signature_block(sigblock, digest, verified_digest);
bootloader_munmap(sigblock);
return err;
}
esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
{
#if !(defined(CONFIG_MBEDTLS_ECDSA_C) && defined(CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED))
ESP_LOGE(TAG, "Signature verification requires ECDSA & SECP256R1 curve enabled");
return ESP_ERR_NOT_SUPPORTED;
#else
ptrdiff_t keylen;
/* Note: in IDF app image verification we don't add any fault injection resistance, boot-time checks only */
memset(verified_digest, 0, ESP_SECURE_BOOT_DIGEST_LEN);
keylen = signature_verification_key_end - signature_verification_key_start;
if (keylen != SIGNATURE_VERIFICATION_KEYLEN) {
ESP_LOGE(TAG, "Embedded public verification key has wrong length %d", keylen);
return ESP_FAIL;
}
if (sig_block->version != 0) {
ESP_LOGE(TAG, "image has invalid signature version field 0x%08x", sig_block->version);
return ESP_FAIL;
}
ESP_LOGD(TAG, "Verifying secure boot signature");
int ret;
mbedtls_mpi r, s;
mbedtls_mpi_init(&r);
mbedtls_mpi_init(&s);
/* Extract r and s components from RAW ECDSA signature of 64 bytes */
#define ECDSA_INTEGER_LEN 32
ret = mbedtls_mpi_read_binary(&r, &sig_block->signature[0], ECDSA_INTEGER_LEN);
if (ret != 0) {
ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(1), err:%d", ret);
return ESP_FAIL;
}
ret = mbedtls_mpi_read_binary(&s, &sig_block->signature[ECDSA_INTEGER_LEN], ECDSA_INTEGER_LEN);
if (ret != 0) {
ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(2), err:%d", ret);
mbedtls_mpi_free(&r);
return ESP_FAIL;
}
/* Initialise ECDSA context */
mbedtls_ecdsa_context ecdsa_context;
mbedtls_ecdsa_init(&ecdsa_context);
mbedtls_ecp_group_load(&ecdsa_context.grp, MBEDTLS_ECP_DP_SECP256R1);
size_t plen = mbedtls_mpi_size(&ecdsa_context.grp.P);
if (keylen != 2 * plen) {
ESP_LOGE(TAG, "Incorrect ECDSA key length %d", keylen);
ret = ESP_FAIL;
goto cleanup;
}
/* Extract X and Y components from ECDSA public key */
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ecdsa_context.Q.X, signature_verification_key_start, plen));
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ecdsa_context.Q.Y, signature_verification_key_start + plen, plen));
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ecdsa_context.Q.Z, 1));
ret = mbedtls_ecdsa_verify(&ecdsa_context.grp, image_digest, ESP_SECURE_BOOT_DIGEST_LEN, &ecdsa_context.Q, &r, &s);
ESP_LOGD(TAG, "Verification result %d", ret);
cleanup:
mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s);
mbedtls_ecdsa_free(&ecdsa_context);
return ret == 0 ? ESP_OK : ESP_ERR_IMAGE_INVALID;
#endif // CONFIG_MBEDTLS_ECDSA_C && CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED
}
#endif // CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME

View File

@ -0,0 +1,100 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "sdkconfig.h"
#include "bootloader_flash_priv.h"
#include "bootloader_sha.h"
#include "bootloader_utility.h"
#include "esp_log.h"
#include "esp_image_format.h"
#include "esp_secure_boot.h"
#include "esp_spi_flash.h"
#include "esp_fault.h"
#include "esp32/rom/sha.h"
#include "uECC_verify_antifault.h"
#include <sys/param.h>
#include <string.h>
static const char *TAG = "secure_boot";
#ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
extern const uint8_t signature_verification_key_start[] asm("_binary_signature_verification_key_bin_start");
extern const uint8_t signature_verification_key_end[] asm("_binary_signature_verification_key_bin_end");
#define SIGNATURE_VERIFICATION_KEYLEN 64
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
{
uint8_t digest[ESP_SECURE_BOOT_DIGEST_LEN];
uint8_t verified_digest[ESP_SECURE_BOOT_DIGEST_LEN] = { 0 }; /* ignored in this function */
const esp_secure_boot_sig_block_t *sigblock;
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
esp_err_t err = bootloader_sha256_flash_contents(src_addr, length, digest);
if (err != ESP_OK) {
return err;
}
// Map the signature block
sigblock = (const esp_secure_boot_sig_block_t *) bootloader_mmap(src_addr + length, sizeof(esp_secure_boot_sig_block_t));
if(!sigblock) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr + length, sizeof(esp_secure_boot_sig_block_t));
return ESP_FAIL;
}
// Verify the signature
err = esp_secure_boot_verify_ecdsa_signature_block(sigblock, digest, verified_digest);
// Unmap
bootloader_munmap(sigblock);
return err;
}
esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest)
{
uint8_t verified_digest[ESP_SECURE_BOOT_DIGEST_LEN] = { 0 };
return esp_secure_boot_verify_ecdsa_signature_block(sig_block, image_digest, verified_digest);
}
esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
{
ptrdiff_t keylen;
keylen = signature_verification_key_end - signature_verification_key_start;
if (keylen != SIGNATURE_VERIFICATION_KEYLEN) {
ESP_LOGE(TAG, "Embedded public verification key has wrong length %d", keylen);
return ESP_FAIL;
}
if (sig_block->version != 0) {
ESP_LOGE(TAG, "image has invalid signature version field 0x%08x", sig_block->version);
return ESP_FAIL;
}
ESP_LOGD(TAG, "Verifying secure boot signature");
bool is_valid;
is_valid = uECC_verify_antifault(signature_verification_key_start,
image_digest,
ESP_SECURE_BOOT_DIGEST_LEN,
sig_block->signature,
uECC_secp256r1(),
verified_digest);
ESP_LOGD(TAG, "Verification result %d", is_valid);
return is_valid ? ESP_OK : ESP_ERR_IMAGE_INVALID;
}
#endif // CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME

View File

@ -0,0 +1,294 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "sdkconfig.h"
#include "bootloader_flash_priv.h"
#include "bootloader_sha.h"
#include "bootloader_utility.h"
#include "esp_log.h"
#include "esp_image_format.h"
#include "mbedtls/sha256.h"
#include "mbedtls/x509.h"
#include "mbedtls/md.h"
#include "mbedtls/platform.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include <string.h>
#include <sys/param.h>
#include "esp_secure_boot.h"
#include "esp_ota_ops.h"
// Secure boot V2 for app
_Static_assert(SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS == SECURE_BOOT_NUM_BLOCKS,
"Parts of this code rely on the max number of signatures appended to an image"
"being the same as the max number of trusted keys.");
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
static const char *TAG = "secure_boot_v2";
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
/* A signature block is valid when it has correct magic byte, crc. */
static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *block)
{
if (block->magic_byte != ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC
|| block->block_crc != esp_rom_crc32_le(0, (uint8_t *)block, CRC_SIGN_BLOCK_LEN)) {
return ESP_FAIL;
}
return ESP_OK;
}
esp_err_t esp_secure_boot_get_signature_blocks_for_running_app(bool digest_public_keys, esp_image_sig_public_key_digests_t *public_key_digests)
{
esp_image_metadata_t metadata;
const esp_partition_t* running_app_part = esp_ota_get_running_partition();
if (running_app_part == NULL) {
ESP_LOGE(TAG, "Cannot get running partition");
return ESP_FAIL;
}
const esp_partition_pos_t part_pos = {
.offset = running_app_part->address,
.size = running_app_part->size,
};
esp_err_t err = esp_image_get_metadata(&part_pos, &metadata);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Error reading metadata from running app (err=0x%x)", err);
return ESP_FAIL;
}
memset(public_key_digests, 0, sizeof(esp_image_sig_public_key_digests_t));
// Generating the SHA of the public key components in the signature block
// metadata.image_len doesn't include any padding to start of the signature sector, so pad it here
size_t sig_block_addr = metadata.start_addr + ALIGN_UP(metadata.image_len, FLASH_SECTOR_SIZE);
ESP_LOGD(TAG, "reading signatures for app address 0x%x sig block address 0x%x", part_pos.offset, sig_block_addr);
for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
ets_secure_boot_sig_block_t block;
size_t addr = sig_block_addr + sizeof(ets_secure_boot_sig_block_t) * i;
esp_err_t err = bootloader_flash_read(addr, &block, sizeof(ets_secure_boot_sig_block_t), true);
if (err == ESP_OK) {
if (validate_signature_block(&block) == ESP_OK) {
if (digest_public_keys) {
bootloader_sha256_handle_t sig_block_sha = bootloader_sha256_start();
bootloader_sha256_data(sig_block_sha, &block.key, sizeof(block.key));
bootloader_sha256_finish(sig_block_sha, public_key_digests->key_digests[i]);
}
public_key_digests->num_digests++;
}
} else {
ESP_LOGE(TAG, "Secure boot sign blocks cannot be read from a running app (err=0x%x)", err);
return ESP_FAIL;
}
}
if (public_key_digests->num_digests > 0) {
return ESP_OK;
}
ESP_LOGE(TAG, "No signatures were found for the running app");
return ESP_ERR_NOT_FOUND;
}
static esp_err_t get_secure_boot_key_digests(esp_image_sig_public_key_digests_t *public_key_digests)
{
#ifdef CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
// Gets key digests from running app
ESP_LOGI(TAG, "Take trusted digest key(s) from running app");
return esp_secure_boot_get_signature_blocks_for_running_app(true, public_key_digests);
#elif CONFIG_SECURE_BOOT_V2_ENABLED
ESP_LOGI(TAG, "Take trusted digest key(s) from eFuse block(s)");
#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1
// Read key digests from efuse
ets_secure_boot_key_digests_t efuse_trusted;
if (ets_secure_boot_read_key_digests(&efuse_trusted) == ETS_OK) {
for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
if (efuse_trusted.key_digests[i] != NULL) {
memcpy(public_key_digests->key_digests[i], (uint8_t *)efuse_trusted.key_digests[i], ESP_SECURE_BOOT_DIGEST_LEN);
public_key_digests->num_digests++;
}
}
}
if (public_key_digests->num_digests > 0) {
return ESP_OK;
}
return ESP_ERR_NOT_FOUND;
#else
memcpy(public_key_digests->key_digests[0], (uint8_t *)EFUSE_BLK2_RDATA0_REG, ESP_SECURE_BOOT_DIGEST_LEN);
public_key_digests->num_digests = 1;
return ESP_OK;
#endif // SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS
#endif // CONFIG_SECURE_BOOT_V2_ENABLED
}
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
{
uint8_t digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
uint8_t verified_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
/* Rounding off length to the upper 4k boundary */
uint32_t padded_length = ALIGN_UP(length, FLASH_SECTOR_SIZE);
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
esp_err_t err = bootloader_sha256_flash_contents(src_addr, padded_length, digest);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, padded_length);
return err;
}
const ets_secure_boot_signature_t *sig_block = bootloader_mmap(src_addr + padded_length, sizeof(ets_secure_boot_signature_t));
if (sig_block == NULL) {
ESP_LOGE(TAG, "Failed to mmap data at offset 0x%x", src_addr + padded_length);
return ESP_FAIL;
}
err = esp_secure_boot_verify_rsa_signature_block(sig_block, digest, verified_digest);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Secure Boot V2 verification failed.");
}
bootloader_munmap(sig_block);
return err;
}
// This verify function is called only from app, during ota update.
// This function is compiled in case when CONFIG_SECURE_BOOT_V2_ENABLED==y or CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT==y.
// if CONFIG_SECURE_BOOT_V2_ENABLED==y and key digests from eFuse are missing, then FAIL (eFuse blocks should be set).
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
{
bool any_trusted_key = false;
/* Note: in IDF verification we don't add any fault injection resistance, as we don't expect this to be called
during boot-time verification. */
memset(verified_digest, 0, ESP_SECURE_BOOT_DIGEST_LEN);
esp_image_sig_public_key_digests_t trusted = {0};
if (get_secure_boot_key_digests(&trusted) != ESP_OK) {
ESP_LOGE(TAG, "Could not read secure boot digests!");
return ESP_FAIL;
}
int ret = 0;
mbedtls_rsa_context pk;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
const unsigned rsa_key_size = sizeof(sig_block->block[0].signature);
unsigned char *sig_be = calloc(1, rsa_key_size);
unsigned char *buf = calloc(1, rsa_key_size);
if (sig_be == NULL || buf == NULL) {
return ESP_ERR_NO_MEM;
}
mbedtls_entropy_init(&entropy);
mbedtls_ctr_drbg_init(&ctr_drbg);
ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0);
if (ret != 0) {
ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned -0x%04x\n", ret);
goto exit;
}
#ifdef CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
const unsigned secure_boot_num_blocks = 1;
#else
const unsigned secure_boot_num_blocks = SECURE_BOOT_NUM_BLOCKS;
#endif
for (unsigned app_blk_idx = 0; app_blk_idx < secure_boot_num_blocks; app_blk_idx++) {
uint8_t app_blk_digest[ESP_SECURE_BOOT_DIGEST_LEN] = { 0 };
const ets_secure_boot_sig_block_t *app_blk = &sig_block->block[app_blk_idx];
const ets_secure_boot_sig_block_t *trusted_block = NULL;
if (validate_signature_block(app_blk) != ESP_OK) {
continue; // Skip invalid signature blocks
}
/* Generate the SHA of the public key components in the signature block */
bootloader_sha256_handle_t sig_block_sha = bootloader_sha256_start();
bootloader_sha256_data(sig_block_sha, &app_blk->key, sizeof(app_blk->key));
bootloader_sha256_finish(sig_block_sha, app_blk_digest);
/* Check if the key is one we trust */
for (unsigned trusted_key_idx = 0; trusted_key_idx < secure_boot_num_blocks; trusted_key_idx++) {
if (memcmp(app_blk_digest, trusted.key_digests[trusted_key_idx], ESP_SECURE_BOOT_DIGEST_LEN) == 0) {
ESP_LOGI(TAG, "#%d app key digest == #%d trusted key digest", app_blk_idx, trusted_key_idx);
trusted_block = app_blk;
any_trusted_key = true;
break;
}
ESP_LOGV(TAG, "not trusting app sig %d trust idx %d", app_blk_idx, trusted_key_idx);
}
if (trusted_block == NULL) {
continue; // Skip the signature blocks with no trusted digest
}
ESP_LOGI(TAG, "Verifying with RSA-PSS...");
const mbedtls_mpi N = { .s = 1,
.n = sizeof(trusted_block->key.n)/sizeof(mbedtls_mpi_uint),
.p = (void *)trusted_block->key.n,
};
const mbedtls_mpi e = { .s = 1,
.n = sizeof(trusted_block->key.e)/sizeof(mbedtls_mpi_uint), // 1
.p = (void *)&trusted_block->key.e,
};
mbedtls_rsa_init(&pk, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
ret = mbedtls_rsa_import(&pk, &N, NULL, NULL, NULL, &e);
if (ret != 0) {
ESP_LOGE(TAG, "Failed mbedtls_rsa_import, err: %d", ret);
goto exit;
}
ret = mbedtls_rsa_complete(&pk);
if (ret != 0) {
ESP_LOGE(TAG, "Failed mbedtls_rsa_complete, err: %d", ret);
goto exit;
}
ret = mbedtls_rsa_check_pubkey(&pk);
if (ret != 0) {
ESP_LOGI(TAG, "Key is not an RSA key -%0x", -ret);
goto exit;
}
/* Signature needs to be byte swapped into BE representation */
for (int j = 0; j < rsa_key_size; j++) {
sig_be[rsa_key_size - j - 1] = trusted_block->signature[j];
}
ret = mbedtls_rsa_public( &pk, sig_be, buf);
if (ret != 0) {
ESP_LOGE(TAG, "mbedtls_rsa_public failed, err: %d", ret);
goto exit;
}
ret = mbedtls_rsa_rsassa_pss_verify( &pk, mbedtls_ctr_drbg_random, &ctr_drbg, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256, ESP_SECURE_BOOT_DIGEST_LEN,
image_digest, sig_be);
if (ret != 0) {
ESP_LOGE(TAG, "Failed mbedtls_rsa_rsassa_pss_verify, err: %d", ret);
} else {
ESP_LOGI(TAG, "Signature verified successfully!");
}
exit:
mbedtls_rsa_free(&pk);
if (ret == 0) {
break;
}
}
free(sig_be);
free(buf);
return (ret != 0 || any_trusted_key == false) ? ESP_ERR_IMAGE_INVALID: ESP_OK;
}
#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT

View File

@ -0,0 +1,172 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "sdkconfig.h"
#include <string.h>
#include "esp_fault.h"
#include "bootloader_flash_priv.h"
#include "bootloader_sha.h"
#include "bootloader_utility.h"
#include "esp_log.h"
#include "esp_image_format.h"
#include "esp_secure_boot.h"
// Secure boot V2 for bootloader.
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_BOOT_V2_ENABLED
static const char* TAG = "secure_boot_v2";
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
{
uint8_t digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
uint8_t verified_digest[ESP_SECURE_BOOT_DIGEST_LEN] = { 0 }; /* Note: this function doesn't do any anti-FI checks on this buffer */
/* Rounding off length to the upper 4k boundary */
uint32_t padded_length = ALIGN_UP(length, FLASH_SECTOR_SIZE);
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
/* Calculate digest of main image */
esp_err_t err = bootloader_sha256_flash_contents(src_addr, padded_length, digest);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, padded_length);
return err;
}
const ets_secure_boot_signature_t *sig_block = bootloader_mmap(src_addr + padded_length, sizeof(ets_secure_boot_signature_t));
if (sig_block == NULL) {
ESP_LOGE(TAG, "Failed to mmap data at offset 0x%x", src_addr + padded_length);
return ESP_FAIL;
}
err = esp_secure_boot_verify_rsa_signature_block(sig_block, digest, verified_digest);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Secure Boot V2 verification failed.");
}
bootloader_munmap(sig_block);
return err;
}
/* A signature block is valid when it has correct magic byte, crc. */
static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *block)
{
if (block->magic_byte != ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC
|| block->block_crc != esp_rom_crc32_le(0, (uint8_t *)block, CRC_SIGN_BLOCK_LEN)) {
return ESP_FAIL;
}
return ESP_OK;
}
static esp_err_t get_secure_boot_key_digests(esp_image_sig_public_key_digests_t *public_key_digests)
{
#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1
// Read key digests from efuse
ets_secure_boot_key_digests_t trusted_keys;
ets_secure_boot_key_digests_t trusted_key_copies[2];
ETS_STATUS ets_ret;
memset(&trusted_keys, 0, sizeof(ets_secure_boot_key_digests_t));
memset(trusted_key_copies, 0, 2 * sizeof(ets_secure_boot_key_digests_t));
ets_ret = ets_secure_boot_read_key_digests(&trusted_keys);
// Create the copies for FI checks (assuming result is ETS_OK, if it's not then it'll fail the fault check anyhow)
ets_secure_boot_read_key_digests(&trusted_key_copies[0]);
ets_secure_boot_read_key_digests(&trusted_key_copies[1]);
ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[0], sizeof(ets_secure_boot_key_digests_t)) == 0);
ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[1], sizeof(ets_secure_boot_key_digests_t)) == 0);
if (ets_ret == ETS_OK) {
for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
if (trusted_keys.key_digests[i] != NULL) {
memcpy(public_key_digests->key_digests[i], (uint8_t *)trusted_keys.key_digests[i], ESP_SECURE_BOOT_DIGEST_LEN);
public_key_digests->num_digests++;
}
}
if (public_key_digests->num_digests > 0) {
return ESP_OK;
}
}
return ESP_ERR_NOT_FOUND;
#else
bool all_zeroes = true;
uint32_t *reg = (uint32_t*)&public_key_digests->key_digests[0];
for (int i = 0; i < ESP_SECURE_BOOT_DIGEST_LEN / 4; i++) {
*(reg + i) = REG_READ(EFUSE_BLK2_RDATA0_REG + i * 4);
all_zeroes = all_zeroes && (*(reg + i) == 0);
}
if (all_zeroes) {
return ESP_ERR_NOT_FOUND;
}
public_key_digests->num_digests = 1;
return ESP_OK;
#endif // SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS
}
// if CONFIG_SECURE_BOOT_V2_ENABLED==y and key digests from eFuse are missing, then it is the first boot,
// trusted.key_digests are filled from app sig_block.
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
{
esp_image_sig_public_key_digests_t trusted = {0};
bool efuse_keys_are_not_set = false;
if (get_secure_boot_key_digests(&trusted) != ESP_OK) {
if (esp_secure_boot_enabled()) {
ESP_LOGE(TAG, "Could not read eFuse secure boot digests!");
return ESP_FAIL;
} else {
ESP_LOGI(TAG, "Secure boot V2 is not enabled yet and eFuse digest keys are not set");
efuse_keys_are_not_set = true;
ESP_FAULT_ASSERT(!esp_secure_boot_enabled());
}
}
if (!esp_secure_boot_enabled()) {
// It is the first boot. eFuse secure boot bit is not set yet. eFuse block(s) can be written or not.
// Generating the SHA of the public key components in the signature block
for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
if (validate_signature_block(&sig_block->block[i]) == ESP_OK) {
if (efuse_keys_are_not_set) {
// if efuse key digests are not in eFuse yet due to it is the first boot
// then use digests from app to skip error in ets_secure_boot_verify_signature().
bootloader_sha256_handle_t sig_block_sha = bootloader_sha256_start();
bootloader_sha256_data(sig_block_sha, &sig_block->block[i].key, sizeof(sig_block->block[i].key));
bootloader_sha256_finish(sig_block_sha, trusted.key_digests[i]);
}
}
}
ESP_FAULT_ASSERT(!esp_secure_boot_enabled());
}
ESP_LOGI(TAG, "Verifying with RSA-PSS...");
#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS == 1
int sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, trusted.key_digests[0], verified_digest);
#else
ets_secure_boot_key_digests_t trusted_key_digests;
for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
trusted_key_digests.key_digests[i] = &trusted.key_digests[i];
}
int sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, &trusted_key_digests, verified_digest);
#endif
if (sb_result != SB_SUCCESS) {
ESP_LOGE(TAG, "Secure Boot V2 verification failed.");
return ESP_ERR_IMAGE_INVALID;
} else {
ESP_LOGI(TAG, "Signature verified successfully!");
return ESP_OK;
}
}
#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_BOOT_V2_ENABLED

View File

@ -176,6 +176,14 @@ struct osi_funcs_t {
int (* _coex_register_bt_cb)(coex_func_cb_t cb);
uint32_t (* _coex_bb_reset_lock)(void);
void (* _coex_bb_reset_unlock)(uint32_t restore);
int (* _coex_schm_register_btdm_callback)(void *callback);
void (* _coex_schm_status_bit_clear)(uint32_t type, uint32_t status);
void (* _coex_schm_status_bit_set)(uint32_t type, uint32_t status);
uint32_t (* _coex_schm_interval_get)(void);
uint8_t (* _coex_schm_curr_period_get)(void);
void *(* _coex_schm_curr_phase_get)(void);
int (* _coex_wifi_channel_get)(uint8_t *primary, uint8_t *secondary);
int (* _coex_register_wifi_channel_change_callback)(void *cb);
uint32_t _magic;
};
@ -224,6 +232,14 @@ extern int coex_bt_release(uint32_t event);
extern int coex_register_bt_cb(coex_func_cb_t cb);
extern uint32_t coex_bb_reset_lock(void);
extern void coex_bb_reset_unlock(uint32_t restore);
extern int coex_schm_register_btdm_callback(void *callback);
extern void coex_schm_status_bit_clear(uint32_t type, uint32_t status);
extern void coex_schm_status_bit_set(uint32_t type, uint32_t status);
extern uint32_t coex_schm_interval_get(void);
extern uint8_t coex_schm_curr_period_get(void);
extern void * coex_schm_curr_phase_get(void);
extern int coex_wifi_channel_get(uint8_t *primary, uint8_t *secondary);
extern int coex_register_wifi_channel_change_callback(void *cb);
extern void coex_ble_adv_priority_high_set(bool high);
extern char _bss_start_btdm;
@ -294,7 +310,14 @@ static int coex_bt_release_wrapper(uint32_t event);
static int coex_register_bt_cb_wrapper(coex_func_cb_t cb);
static uint32_t coex_bb_reset_lock_wrapper(void);
static void coex_bb_reset_unlock_wrapper(uint32_t restore);
static int coex_schm_register_btdm_callback_wrapper(void *callback);
static void coex_schm_status_bit_clear_wrapper(uint32_t type, uint32_t status);
static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status);
static uint32_t coex_schm_interval_get_wrapper(void);
static uint8_t coex_schm_curr_period_get_wrapper(void);
static void * coex_schm_curr_phase_get_wrapper(void);
static int coex_wifi_channel_get_wrapper(uint8_t *primary, uint8_t *secondary);
static int coex_register_wifi_channel_change_callback_wrapper(void *cb);
/* Local variable definition
***************************************************************************
*/
@ -348,6 +371,14 @@ static const struct osi_funcs_t osi_funcs_ro = {
._coex_register_bt_cb = coex_register_bt_cb_wrapper,
._coex_bb_reset_lock = coex_bb_reset_lock_wrapper,
._coex_bb_reset_unlock = coex_bb_reset_unlock_wrapper,
._coex_schm_register_btdm_callback = coex_schm_register_btdm_callback_wrapper,
._coex_schm_status_bit_clear = coex_schm_status_bit_clear_wrapper,
._coex_schm_status_bit_set = coex_schm_status_bit_set_wrapper,
._coex_schm_interval_get = coex_schm_interval_get_wrapper,
._coex_schm_curr_period_get = coex_schm_curr_period_get_wrapper,
._coex_schm_curr_phase_get = coex_schm_curr_phase_get_wrapper,
._coex_wifi_channel_get = coex_wifi_channel_get_wrapper,
._coex_register_wifi_channel_change_callback = coex_register_wifi_channel_change_callback_wrapper,
._magic = OSI_MAGIC_VALUE,
};
@ -1001,7 +1032,7 @@ static void coex_bt_wakeup_request_end(void)
return;
}
int IRAM_ATTR coex_bt_request_wrapper(uint32_t event, uint32_t latency, uint32_t duration)
static int IRAM_ATTR coex_bt_request_wrapper(uint32_t event, uint32_t latency, uint32_t duration)
{
#if CONFIG_SW_COEXIST_ENABLE
return coex_bt_request(event, latency, duration);
@ -1010,7 +1041,7 @@ int IRAM_ATTR coex_bt_request_wrapper(uint32_t event, uint32_t latency, uint32_t
#endif
}
int IRAM_ATTR coex_bt_release_wrapper(uint32_t event)
static int IRAM_ATTR coex_bt_release_wrapper(uint32_t event)
{
#if CONFIG_SW_COEXIST_ENABLE
return coex_bt_release(event);
@ -1019,7 +1050,7 @@ int IRAM_ATTR coex_bt_release_wrapper(uint32_t event)
#endif
}
int coex_register_bt_cb_wrapper(coex_func_cb_t cb)
static int coex_register_bt_cb_wrapper(coex_func_cb_t cb)
{
#if CONFIG_SW_COEXIST_ENABLE
return coex_register_bt_cb(cb);
@ -1028,7 +1059,7 @@ int coex_register_bt_cb_wrapper(coex_func_cb_t cb)
#endif
}
uint32_t IRAM_ATTR coex_bb_reset_lock_wrapper(void)
static uint32_t IRAM_ATTR coex_bb_reset_lock_wrapper(void)
{
#if CONFIG_SW_COEXIST_ENABLE
return coex_bb_reset_lock();
@ -1037,13 +1068,81 @@ uint32_t IRAM_ATTR coex_bb_reset_lock_wrapper(void)
#endif
}
void IRAM_ATTR coex_bb_reset_unlock_wrapper(uint32_t restore)
static void IRAM_ATTR coex_bb_reset_unlock_wrapper(uint32_t restore)
{
#if CONFIG_SW_COEXIST_ENABLE
coex_bb_reset_unlock(restore);
#endif
}
static int coex_schm_register_btdm_callback_wrapper(void *callback)
{
#if CONFIG_SW_COEXIST_ENABLE
return coex_schm_register_btdm_callback(callback);
#else
return 0;
#endif
}
static void coex_schm_status_bit_clear_wrapper(uint32_t type, uint32_t status)
{
#if CONFIG_SW_COEXIST_ENABLE
coex_schm_status_bit_clear(type, status);
#endif
}
static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status)
{
#if CONFIG_SW_COEXIST_ENABLE
coex_schm_status_bit_set(type, status);
#endif
}
static uint32_t coex_schm_interval_get_wrapper(void)
{
#if CONFIG_SW_COEXIST_ENABLE
return coex_schm_interval_get();
#else
return 0;
#endif
}
static uint8_t coex_schm_curr_period_get_wrapper(void)
{
#if CONFIG_SW_COEXIST_ENABLE
return coex_schm_curr_period_get();
#else
return 1;
#endif
}
static void * coex_schm_curr_phase_get_wrapper(void)
{
#if CONFIG_SW_COEXIST_ENABLE
return coex_schm_curr_phase_get();
#else
return NULL;
#endif
}
static int coex_wifi_channel_get_wrapper(uint8_t *primary, uint8_t *secondary)
{
#if CONFIG_SW_COEXIST_ENABLE
return coex_wifi_channel_get(primary, secondary);
#else
return -1;
#endif
}
static int coex_register_wifi_channel_change_callback_wrapper(void *cb)
{
#if CONFIG_SW_COEXIST_ENABLE
return coex_register_wifi_channel_change_callback(cb);
#else
return -1;
#endif
}
bool esp_vhci_host_check_send_available(void)
{
return API_vhci_host_check_send_available();
@ -1442,16 +1541,12 @@ esp_err_t esp_bt_controller_deinit(void)
static void bt_shutdown(void)
{
esp_err_t ret = ESP_OK;
ESP_LOGD(BTDM_LOG_TAG, "stop/deinit bt");
ESP_LOGD(BTDM_LOG_TAG, "stop Bluetooth");
ret = esp_bt_controller_disable();
if (ESP_OK != ret) {
ESP_LOGW(BTDM_LOG_TAG, "controller disable ret=%d", ret);
}
ret = esp_bt_controller_deinit();
if (ESP_OK != ret) {
ESP_LOGW(BTDM_LOG_TAG, "controller deinit ret=%d", ret);
}
return;
}

View File

@ -7,7 +7,8 @@ config BT_CTRL_BLE_MAX_ACT
default 10
range 1 10
help
BLE maximum instances of bluetooth controller.
BLE maximum activities of bluetooth controllerboth of connections,
scan , sync and adv(periodic adv, multi-adv).
config BT_CTRL_BLE_MAX_ACT_EFF
int
@ -126,10 +127,20 @@ config BT_CTRL_RX_ANTENNA_INDEX_EFF
choice BT_CTRL_DFT_TX_POWER_LEVEL
prompt "BLE default Tx power level"
default BT_CTRL_DFT_TX_POWER_LEVEL_P9
default BT_CTRL_DFT_TX_POWER_LEVEL_P3
help
Specify default Tx power level
config BT_CTRL_DFT_TX_POWER_LEVEL_N27
bool "-27dBm"
config BT_CTRL_DFT_TX_POWER_LEVEL_N24
bool "-24dBm"
config BT_CTRL_DFT_TX_POWER_LEVEL_N21
bool "-21dBm"
config BT_CTRL_DFT_TX_POWER_LEVEL_N18
bool "-18dBm"
config BT_CTRL_DFT_TX_POWER_LEVEL_N15
bool "-15dBm"
config BT_CTRL_DFT_TX_POWER_LEVEL_N12
bool "-12dBm"
config BT_CTRL_DFT_TX_POWER_LEVEL_N9
@ -146,18 +157,32 @@ choice BT_CTRL_DFT_TX_POWER_LEVEL
bool "+6dBm"
config BT_CTRL_DFT_TX_POWER_LEVEL_P9
bool "+9dBm"
config BT_CTRL_DFT_TX_POWER_LEVEL_P12
bool "+12dBm"
config BT_CTRL_DFT_TX_POWER_LEVEL_P15
bool "+15dBm"
config BT_CTRL_DFT_TX_POWER_LEVEL_P18
bool "+18dBm"
endchoice
config BT_CTRL_DFT_TX_POWER_LEVEL_EFF
int
default 0 if BT_CTRL_DFT_TX_POWER_LEVEL_N12
default 1 if BT_CTRL_DFT_TX_POWER_LEVEL_N9
default 2 if BT_CTRL_DFT_TX_POWER_LEVEL_N6
default 3 if BT_CTRL_DFT_TX_POWER_LEVEL_N3
default 4 if BT_CTRL_DFT_TX_POWER_LEVEL_N0
default 5 if BT_CTRL_DFT_TX_POWER_LEVEL_P3
default 6 if BT_CTRL_DFT_TX_POWER_LEVEL_P6
default 7 if BT_CTRL_DFT_TX_POWER_LEVEL_P9
default 0 if BT_CTRL_DFT_TX_POWER_LEVEL_N27
default 1 if BT_CTRL_DFT_TX_POWER_LEVEL_N24
default 2 if BT_CTRL_DFT_TX_POWER_LEVEL_N21
default 3 if BT_CTRL_DFT_TX_POWER_LEVEL_N18
default 4 if BT_CTRL_DFT_TX_POWER_LEVEL_N15
default 5 if BT_CTRL_DFT_TX_POWER_LEVEL_N12
default 6 if BT_CTRL_DFT_TX_POWER_LEVEL_N9
default 7 if BT_CTRL_DFT_TX_POWER_LEVEL_N6
default 8 if BT_CTRL_DFT_TX_POWER_LEVEL_N3
default 9 if BT_CTRL_DFT_TX_POWER_LEVEL_N0
default 10 if BT_CTRL_DFT_TX_POWER_LEVEL_P3
default 11 if BT_CTRL_DFT_TX_POWER_LEVEL_P6
default 12 if BT_CTRL_DFT_TX_POWER_LEVEL_P9
default 13 if BT_CTRL_DFT_TX_POWER_LEVEL_P12
default 14 if BT_CTRL_DFT_TX_POWER_LEVEL_P15
default 15 if BT_CTRL_DFT_TX_POWER_LEVEL_P18
default 0
config BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP

View File

@ -212,6 +212,7 @@ 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_phase2(void); // shall be called after PHY/RF is enabled
/* Sleep */
extern void btdm_controller_enable_sleep(bool enable);
extern uint8_t btdm_controller_get_sleep_mode(void);
@ -740,13 +741,16 @@ static void IRAM_ATTR btdm_sleep_exit_phase0(void *param)
}
#endif
btdm_wakeup_request();
int event = (int) param;
if (event == BTDM_ASYNC_WAKEUP_SRC_VHCI || event == BTDM_ASYNC_WAKEUP_SRC_DISA) {
btdm_wakeup_request();
}
if (s_lp_cntl.wakeup_timer_required && s_lp_stat.wakeup_timer_started) {
esp_timer_stop(s_btdm_slp_tmr);
s_lp_stat.wakeup_timer_started = 0;
}
int event = (int) param;
if (event == BTDM_ASYNC_WAKEUP_SRC_VHCI || event == BTDM_ASYNC_WAKEUP_SRC_DISA) {
semphr_give_wrapper(s_wakeup_req_sem);
}
@ -1331,14 +1335,51 @@ esp_bt_controller_status_t esp_bt_controller_get_status(void)
/* extra functions */
esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_t power_level)
{
ESP_LOGW(BTDM_LOG_TAG, "%s not implemented, return OK", __func__);
return ESP_OK;
esp_err_t stat = ESP_FAIL;
switch (power_type) {
case ESP_BLE_PWR_TYPE_ADV:
case ESP_BLE_PWR_TYPE_SCAN:
case ESP_BLE_PWR_TYPE_DEFAULT:
if (ble_txpwr_set(power_type, power_level) == 0) {
stat = ESP_OK;
}
break;
default:
stat = ESP_ERR_NOT_SUPPORTED;
break;
}
return stat;
}
esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type)
{
ESP_LOGW(BTDM_LOG_TAG, "%s not implemented, return 0", __func__);
return 0;
esp_power_level_t lvl;
switch (power_type) {
case ESP_BLE_PWR_TYPE_ADV:
case ESP_BLE_PWR_TYPE_SCAN:
lvl = (esp_power_level_t)ble_txpwr_get(power_type);
break;
case ESP_BLE_PWR_TYPE_CONN_HDL0:
case ESP_BLE_PWR_TYPE_CONN_HDL1:
case ESP_BLE_PWR_TYPE_CONN_HDL2:
case ESP_BLE_PWR_TYPE_CONN_HDL3:
case ESP_BLE_PWR_TYPE_CONN_HDL4:
case ESP_BLE_PWR_TYPE_CONN_HDL5:
case ESP_BLE_PWR_TYPE_CONN_HDL6:
case ESP_BLE_PWR_TYPE_CONN_HDL7:
case ESP_BLE_PWR_TYPE_CONN_HDL8:
case ESP_BLE_PWR_TYPE_DEFAULT:
lvl = (esp_power_level_t)ble_txpwr_get(ESP_BLE_PWR_TYPE_DEFAULT);
break;
default:
lvl = ESP_PWR_LVL_INVALID;
break;
}
return lvl;
}
esp_err_t esp_bt_sleep_enable (void)

View File

@ -1004,10 +1004,20 @@ config BT_BLE_ESTAB_LINK_CONN_TOUT
config BT_BLE_RPA_SUPPORTED
bool "Update RPA to Controller"
depends on (BT_BLUEDROID_ENABLED && (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3))
default y
depends on BT_BLUEDROID_ENABLED
default y if (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3)
default n if IDF_TARGET_ESP32
help
This enables controller RPA list function.
For ESP32, ESP32 only support network privacy mode. If this option is enabled, ESP32 will only accept
advertising packets from peer devices that contain private address, HW will not receive the advertising
packets contain identity address after IRK changed. If this option is disabled, address resolution will
be performed in the host, so the functions that require controller to resolve address in the white list
cannot be used. This option is disabled by default on ESP32, please enable or disable this option according
to your own needs.
For ESP32C3 and esp32s3, devices support network privacy mode and device privacy mode, users can switch the
two modes according to their own needs. So this option is enabled by default.
config BT_BLE_50_FEATURES_SUPPORTED
bool "Enable BLE 5.0 features"

View File

@ -133,7 +133,8 @@ esp_err_t esp_spp_start_srv(esp_spp_sec_t sec_mask,
btc_spp_args_t arg;
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
if (strlen(name) > ESP_SPP_SERVER_NAME_MAX) {
if (name == NULL || strlen(name) > ESP_SPP_SERVER_NAME_MAX) {
LOG_ERROR("Invalid server name!\n");
return ESP_ERR_INVALID_ARG;
}
@ -157,13 +158,34 @@ esp_err_t esp_spp_start_srv(esp_spp_sec_t sec_mask,
esp_err_t esp_spp_stop_srv(void)
{
btc_msg_t msg;
btc_spp_args_t arg;
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_SPP;
msg.act = BTC_SPP_ACT_STOP_SRV;
arg.stop_srv.scn = BTC_SPP_INVALID_SCN;
return (btc_transfer_context(&msg, NULL, sizeof(btc_spp_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
return (btc_transfer_context(&msg, &arg, sizeof(btc_spp_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_spp_stop_srv_scn(uint8_t scn)
{
btc_msg_t msg;
btc_spp_args_t arg;
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
if ((scn == 0) || (scn >= PORT_MAX_RFC_PORTS)) {
LOG_ERROR("Invalid SCN!\n");
return ESP_ERR_INVALID_ARG;
}
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_SPP;
msg.act = BTC_SPP_ACT_STOP_SRV;
arg.stop_srv.scn = scn;
return (btc_transfer_context(&msg, &arg, sizeof(btc_spp_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}

View File

@ -301,6 +301,7 @@ typedef void (* esp_blufi_event_cb_t)(esp_blufi_cb_event_t event, esp_blufi_cb_p
* @param len : length of data from phone
* @param output_data : data want to send to phone
* @param output_len : length of data want to send to phone
* @param need_free : output reporting if memory needs to be freed or not *
*/
typedef void (*esp_blufi_negotiate_data_handler_t)(uint8_t *data, int len, uint8_t **output_data, int *output_len, bool *need_free);
@ -311,7 +312,7 @@ typedef void (*esp_blufi_negotiate_data_handler_t)(uint8_t *data, int len, uint8
* @param crypt_len : length of plain text
* @return Nonnegative number is encrypted length, if error, return negative number;
*/
typedef int (* esp_blufi_encrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int cyprt_len);
typedef int (* esp_blufi_encrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int crypt_len);
/**
* @brief BLUFI decrypt the data after negotiate a share key

View File

@ -259,7 +259,7 @@ typedef union {
/**
* @brief GATT Client callback function type
* @param event : Event type
* @param gatts_if : GATT client access interface, normally
* @param gattc_if : GATT client access interface, normally
* different gattc_if correspond to different profile
* @param param : Point to callback parameter, currently is union type
*/
@ -313,7 +313,7 @@ esp_err_t esp_ble_gattc_app_unregister(esp_gatt_if_t gattc_if);
* @param[in] gattc_if: Gatt client access interface.
* @param[in] remote_bda: remote device bluetooth device address.
* @param[in] remote_addr_type: remote device bluetooth device the address type.
* @param[in] is_direct: direct connection or background auto connection
* @param[in] is_direct: direct connection or background auto connection(by now, background auto connection is not supported).
*
* @return
* - ESP_OK: success

View File

@ -188,7 +188,7 @@ typedef void (* esp_hf_incoming_data_cb_t)(const uint8_t *buf, uint32_t len);
*
* @param[in] len : size(in bytes) in buf
*
* @param[out] length of data successfully read
* @return length of data successfully read
*/
typedef uint32_t (* esp_hf_outgoing_data_cb_t) (uint8_t *buf, uint32_t len);

View File

@ -273,7 +273,7 @@ typedef void (* esp_hf_client_incoming_data_cb_t)(const uint8_t *buf, uint32_t l
*
* @param[in] len : size(in bytes) in buf
*
* @param[out] length of data successfully read
* @return length of data successfully read
*
*/
typedef uint32_t (* esp_hf_client_outgoing_data_cb_t)(uint8_t *buf, uint32_t len);

View File

@ -26,11 +26,12 @@ typedef enum {
ESP_SPP_SUCCESS = 0, /*!< Successful operation. */
ESP_SPP_FAILURE, /*!< Generic failure. */
ESP_SPP_BUSY, /*!< Temporarily can not handle this request. */
ESP_SPP_NO_DATA, /*!< no data. */
ESP_SPP_NO_DATA, /*!< No data */
ESP_SPP_NO_RESOURCE, /*!< No more resource */
ESP_SPP_NEED_INIT, /*!< SPP module shall init first */
ESP_SPP_NEED_DEINIT, /*!< SPP module shall deinit first */
ESP_SPP_NO_CONNECTION, /*!< connection may have been closed */
ESP_SPP_NO_CONNECTION, /*!< Connection may have been closed */
ESP_SPP_NO_SERVER, /*!< No SPP server */
} esp_spp_status_t;
/* Security Setting Mask
@ -101,9 +102,10 @@ typedef union {
* @brief SPP_DISCOVERY_COMP_EVT
*/
struct spp_discovery_comp_evt_param {
esp_spp_status_t status; /*!< status */
uint8_t scn_num; /*!< The num of scn_num */
uint8_t scn[ESP_SPP_MAX_SCN]; /*!< channel # */
esp_spp_status_t status; /*!< status */
uint8_t scn_num; /*!< The num of scn_num */
uint8_t scn[ESP_SPP_MAX_SCN]; /*!< channel # */
const char *service_name[ESP_SPP_MAX_SCN]; /*!< service_name */
} disc_comp; /*!< SPP callback param of SPP_DISCOVERY_COMP_EVT */
/**
@ -143,6 +145,7 @@ typedef union {
esp_spp_status_t status; /*!< status */
uint32_t handle; /*!< The connection handle */
uint8_t sec_id; /*!< security ID used by this server */
uint8_t scn; /*!< Server channel number */
bool use_co; /*!< TRUE to use co_rfc_data */
} start; /*!< SPP callback param of ESP_SPP_START_EVT */
@ -151,6 +154,7 @@ typedef union {
*/
struct spp_srv_stop_evt_param {
esp_spp_status_t status; /*!< status */
uint8_t scn; /*!< Server channel number */
} srv_stop; /*!< SPP callback param of ESP_SPP_SRV_STOP_EVT */
/**
@ -304,7 +308,7 @@ esp_err_t esp_spp_disconnect(uint32_t handle);
esp_err_t esp_spp_start_srv(esp_spp_sec_t sec_mask, esp_spp_role_t role, uint8_t local_scn, const char *name);
/**
* @brief This function stops a SPP server.
* @brief This function stops all SPP servers.
* The operation will close all active SPP connection first, then the callback function will be called
* with ESP_SPP_CLOSE_EVT, and the number of ESP_SPP_CLOSE_EVT is equal to the number of connection.
* When the operation is completed, the callback is called with ESP_SPP_SRV_STOP_EVT.
@ -314,8 +318,24 @@ esp_err_t esp_spp_start_srv(esp_spp_sec_t sec_mask, esp_spp_role_t role, uint8_t
* - ESP_OK: success
* - other: failed
*/
esp_err_t esp_spp_stop_srv(void);
/**
* @brief This function stops a specific SPP server.
* The operation will close all active SPP connection first on the specific SPP server, then the callback function will be called
* with ESP_SPP_CLOSE_EVT, and the number of ESP_SPP_CLOSE_EVT is equal to the number of connection.
* When the operation is completed, the callback is called with ESP_SPP_SRV_STOP_EVT.
* This funciton must be called after esp_spp_init() successful and before esp_spp_deinit().
*
* @param[in] scn: Server channel number.
*
* @return
* - ESP_OK: success
* - other: failed
*/
esp_err_t esp_spp_stop_srv_scn(uint8_t scn);
/**
* @brief This function is used to write data, only for ESP_SPP_MODE_CB.
* When this function need to be called repeatedly, it is strongly recommended to call this function again after

View File

@ -1683,8 +1683,7 @@ static void bta_gattc_conn_cback(tGATT_IF gattc_if, BD_ADDR bda, UINT16 conn_id,
tBTA_GATTC_DATA *p_buf;
if (reason != 0) {
APPL_TRACE_WARNING("%s() - cif=%d connected=%d conn_id=%d reason=0x%04x",
__FUNCTION__, gattc_if, connected, conn_id, reason);
APPL_TRACE_WARNING("gattc_conn_cb: if=%d st=%d id=%d rsn=0x%x", gattc_if, connected, conn_id, reason);
}
bt_bdaddr_t bdaddr;
@ -1702,7 +1701,7 @@ static void bta_gattc_conn_cback(tGATT_IF gattc_if, BD_ADDR bda, UINT16 conn_id,
p_buf->int_conn.conn_params.latency = p_lcb->current_used_conn_latency;
p_buf->int_conn.conn_params.timeout = p_lcb->current_used_conn_timeout;
} else {
APPL_TRACE_WARNING("%s not found connection parameters of the device ", __func__);
APPL_TRACE_WARNING("gattc_conn_cb: conn params not found");
}
}
p_buf->int_conn.hdr.layer_specific = conn_id;

View File

@ -172,9 +172,10 @@ typedef struct {
/* data associated with BTA_JV_DISCOVERY_COMP_EVT_ */
typedef struct {
tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
UINT8 scn_num; /* num of channel */
UINT8 scn[BTA_JV_MAX_SCN]; /* channel # */
tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
UINT8 scn_num; /* num of channel */
UINT8 scn[BTA_JV_MAX_SCN]; /* channel # */
const char *service_name[BTA_JV_MAX_SCN]; /* service_name */
} tBTA_JV_DISCOVERY_COMP;
/* data associated with BTA_JV_CREATE_RECORD_EVT */
@ -305,6 +306,7 @@ typedef struct {
tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
UINT32 handle; /* The connection handle */
UINT8 sec_id; /* security ID used by this server */
UINT8 scn; /* Server channe number */
BOOLEAN use_co; /* TRUE to use co_rfc_data */
} tBTA_JV_RFCOMM_START;
@ -376,8 +378,9 @@ typedef struct {
/* data associated with BTA_JV_FREE_SCN_EVT */
typedef struct {
tBTA_JV_STATUS status; /* Status of the operation */
tBTA_JV_SERVER_STATUS server_status;
tBTA_JV_STATUS status; /* Status of the operation */
tBTA_JV_SERVER_STATUS server_status; /* Server status */
UINT8 scn; /* Server channe number */
} tBTA_JV_FREE_SCN;

View File

@ -856,6 +856,7 @@ void bta_jv_free_scn(tBTA_JV_MSG *p_data)
tBTA_JV_FREE_SCN evt_data = {
.status = BTA_JV_SUCCESS,
.server_status = BTA_JV_SERVER_STATUS_MAX,
.scn = scn
};
tBTA_JV_FREE_SCN_USER_DATA *user_data = NULL;
@ -949,6 +950,7 @@ static void bta_jv_start_discovery_cback(UINT16 result, void *user_data)
status = BTA_JV_FAILURE;
if (result == SDP_SUCCESS || result == SDP_DB_FULL) {
tSDP_DISC_REC *p_sdp_rec = NULL;
tSDP_DISC_ATTR *p_attr = NULL;
tSDP_PROTOCOL_ELEM pe;
logu("bta_jv_cb.uuid", bta_jv_cb.uuid.uu.uuid128);
tBT_UUID su = shorten_sdp_uuid(&bta_jv_cb.uuid);
@ -957,7 +959,13 @@ static void bta_jv_start_discovery_cback(UINT16 result, void *user_data)
p_sdp_rec = SDP_FindServiceUUIDInDb(p_bta_jv_cfg->p_sdp_db, &su, p_sdp_rec);
APPL_TRACE_DEBUG("p_sdp_rec:%p", p_sdp_rec);
if (p_sdp_rec && SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_RFCOMM, &pe)){
dcomp.scn[dcomp.scn_num++] = (UINT8) pe.params[0];
dcomp.scn[dcomp.scn_num] = (UINT8) pe.params[0];
if ((p_attr = SDP_FindAttributeInRec(p_sdp_rec, ATTR_ID_SERVICE_NAME)) != NULL) {
dcomp.service_name[dcomp.scn_num] = (char *)p_attr->attr_value.v.array;
} else {
dcomp.service_name[dcomp.scn_num] = NULL;
}
dcomp.scn_num++;
status = BTA_JV_SUCCESS;
}
} while (p_sdp_rec);
@ -2154,6 +2162,7 @@ void bta_jv_rfcomm_start_server(tBTA_JV_MSG *p_data)
evt_data.status = BTA_JV_SUCCESS;
evt_data.handle = p_pcb->handle;
evt_data.sec_id = sec_id;
evt_data.scn = rs->local_scn;
evt_data.use_co = TRUE;
PORT_ClearKeepHandleFlag(handle);

View File

@ -917,6 +917,10 @@ void btc_hf_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
case BTC_HF_COPS_RESPONSE_EVT:
{
if (src->cops_rep.name == NULL) {
break;
}
dst->cops_rep.name = (char *)osi_malloc(strlen(src->cops_rep.name)+1);
if(dst->cops_rep.name) {
memcpy(dst->cops_rep.name, src->cops_rep.name, strlen(src->cops_rep.name)+1);
@ -930,6 +934,10 @@ void btc_hf_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
case BTC_HF_CLCC_RESPONSE_EVT:
{
if (src->clcc_rep.number == NULL) {
break;
}
dst->clcc_rep.number = (char *)osi_malloc(strlen(src->clcc_rep.number)+1);
if(dst->clcc_rep.number) {
memcpy(dst->clcc_rep.number, src->clcc_rep.number, strlen(src->clcc_rep.number)+1);
@ -943,6 +951,10 @@ void btc_hf_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
case BTC_HF_CNUM_RESPONSE_EVT:
{
if (src->cnum_rep.number == NULL) {
break;
}
dst->cnum_rep.number = (char *)osi_malloc(strlen(src->cnum_rep.number)+1);
if(dst->cnum_rep.number) {
memcpy(dst->cnum_rep.number, src->cnum_rep.number, strlen(src->cnum_rep.number)+1);
@ -959,6 +971,10 @@ void btc_hf_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
case BTC_HF_OUT_CALL_EVT:
case BTC_HF_END_CALL_EVT:
{
if (src->phone.number == NULL) {
break;
}
dst->phone.number = (char *)osi_malloc(strlen(src->phone.number)+1);
if(dst->phone.number) {
memcpy(dst->phone.number, src->phone.number, strlen(src->phone.number)+1);

View File

@ -28,6 +28,8 @@
#define ESP_SPP_RINGBUF_SIZE 1000
#define BTC_SPP_INVALID_SCN 0x00
typedef enum {
BTC_SPP_ACT_INIT = 0,
BTC_SPP_ACT_UNINIT,
@ -74,6 +76,10 @@ typedef union {
UINT8 max_session;
char name[ESP_SPP_SERVER_NAME_MAX + 1];
} start_srv;
//BTC_SPP_ACT_STOP_SRV
struct stop_srv_arg {
UINT8 scn;
} stop_srv;
//BTC_SPP_ACT_WRITE
struct write_arg {
UINT32 handle;

View File

@ -265,6 +265,10 @@ static void btc_create_server_fail_cb(void)
{
esp_spp_cb_param_t param;
param.start.status = ESP_SPP_FAILURE;
param.start.handle = 0;
param.start.sec_id = 0;
param.start.scn = BTC_SPP_INVALID_SCN;
param.start.use_co = FALSE;
btc_spp_cb_to_app(ESP_SPP_START_EVT, &param);
}
@ -531,6 +535,7 @@ static void btc_spp_uninit(void)
esp_spp_cb_param_t param;
BTC_TRACE_ERROR("%s unable to malloc user data!", __func__);
param.srv_stop.status = ESP_SPP_NO_RESOURCE;
param.srv_stop.scn = spp_local_param.spp_slots[i]->scn;
btc_spp_cb_to_app(ESP_SPP_SRV_STOP_EVT, &param);
}
BTA_JvFreeChannel(spp_local_param.spp_slots[i]->scn, BTA_JV_CONN_TYPE_RFCOMM,
@ -672,61 +677,117 @@ static void btc_spp_start_srv(btc_spp_args_t *arg)
if (ret != ESP_SPP_SUCCESS) {
esp_spp_cb_param_t param;
param.start.status = ret;
param.start.handle = 0;
param.start.sec_id = 0;
param.start.scn = BTC_SPP_INVALID_SCN;
param.start.use_co = FALSE;
btc_spp_cb_to_app(ESP_SPP_START_EVT, &param);
}
}
static void btc_spp_stop_srv(void)
static void btc_spp_stop_srv(btc_spp_args_t *arg)
{
esp_spp_status_t ret = ESP_SPP_SUCCESS;
bool is_remove_all = false;
uint8_t i, j, srv_cnt = 0;
uint8_t *srv_scn_arr = osi_malloc(MAX_RFC_PORTS);
if (arg->stop_srv.scn == BTC_SPP_INVALID_SCN) {
is_remove_all = true;
}
do {
if (!is_spp_init()) {
BTC_TRACE_ERROR("%s SPP have not been init\n", __func__);
ret = ESP_SPP_NEED_INIT;
break;
}
if (srv_scn_arr == NULL) {
BTC_TRACE_ERROR("%s malloc srv_scn_arr failed\n", __func__);
ret = ESP_SPP_NO_RESOURCE;
break;
}
osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
// first, remove all connection
for (size_t i = 1; i <= MAX_RFC_PORTS; i++) {
if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->connected) {
BTA_JvRfcommClose(spp_local_param.spp_slots[i]->rfc_handle, (tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb,
(void *)spp_local_param.spp_slots[i]->id);
// [1] find all server
for (i = 1; i <= MAX_RFC_PORTS; i++) {
if (spp_local_param.spp_slots[i] != NULL && !spp_local_param.spp_slots[i]->connected &&
spp_local_param.spp_slots[i]->sdp_handle > 0) {
if (is_remove_all) {
srv_scn_arr[srv_cnt++] = spp_local_param.spp_slots[i]->scn;
} else if (spp_local_param.spp_slots[i]->scn == arg->stop_srv.scn) {
srv_scn_arr[srv_cnt++] = spp_local_param.spp_slots[i]->scn;
break;
}
}
}
// second, remove all server
for (size_t i = 1; i <= MAX_RFC_PORTS; i++) {
if (spp_local_param.spp_slots[i] != NULL && !spp_local_param.spp_slots[i]->connected) {
if (spp_local_param.spp_slots[i]->sdp_handle > 0) {
BTA_JvDeleteRecord(spp_local_param.spp_slots[i]->sdp_handle);
}
if (srv_cnt == 0) {
if (is_remove_all) {
BTC_TRACE_ERROR("%s can not find any server!\n", __func__);
} else {
BTC_TRACE_ERROR("%s can not find server:%d!\n", __func__, arg->stop_srv.scn);
}
ret = ESP_SPP_NO_SERVER;
break;
}
if (spp_local_param.spp_slots[i]->rfc_handle > 0) {
BTA_JvRfcommStopServer(spp_local_param.spp_slots[i]->rfc_handle,
(void *)spp_local_param.spp_slots[i]->id);
// [2] remove all local related connection
for (j = 0; j < srv_cnt; j++) {
for (i = 1; i <= MAX_RFC_PORTS; i++) {
if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->connected &&
spp_local_param.spp_slots[i]->sdp_handle > 0 &&
spp_local_param.spp_slots[i]->scn == srv_scn_arr[j]) {
BTA_JvRfcommClose(spp_local_param.spp_slots[i]->rfc_handle,
(tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb,
(void *)spp_local_param.spp_slots[i]->id);
}
}
}
tBTA_JV_FREE_SCN_USER_DATA *user_data = osi_malloc(sizeof(tBTA_JV_FREE_SCN_USER_DATA));
if (user_data) {
user_data->server_status = BTA_JV_SERVER_RUNNING;
user_data->slot_id = spp_local_param.spp_slots[i]->id;
} else {
esp_spp_cb_param_t param;
BTC_TRACE_ERROR("%s unable to malloc user data!", __func__);
param.srv_stop.status = ESP_SPP_NO_RESOURCE;
btc_spp_cb_to_app(ESP_SPP_SRV_STOP_EVT, &param);
// [3] remove all server
for (j = 0; j < srv_cnt; j++) {
for (i = 1; i <= MAX_RFC_PORTS; i++) {
if (spp_local_param.spp_slots[i] != NULL && !spp_local_param.spp_slots[i]->connected &&
spp_local_param.spp_slots[i]->sdp_handle > 0 &&
spp_local_param.spp_slots[i]->scn == srv_scn_arr[j]) {
if (spp_local_param.spp_slots[i]->sdp_handle > 0) {
BTA_JvDeleteRecord(spp_local_param.spp_slots[i]->sdp_handle);
}
if (spp_local_param.spp_slots[i]->rfc_handle > 0) {
BTA_JvRfcommStopServer(spp_local_param.spp_slots[i]->rfc_handle,
(void *)spp_local_param.spp_slots[i]->id);
}
tBTA_JV_FREE_SCN_USER_DATA *user_data = osi_malloc(sizeof(tBTA_JV_FREE_SCN_USER_DATA));
if (user_data) {
user_data->server_status = BTA_JV_SERVER_RUNNING;
user_data->slot_id = spp_local_param.spp_slots[i]->id;
} else {
esp_spp_cb_param_t param;
BTC_TRACE_ERROR("%s unable to malloc user data!", __func__);
param.srv_stop.status = ESP_SPP_NO_RESOURCE;
param.srv_stop.scn = spp_local_param.spp_slots[i]->scn;
btc_spp_cb_to_app(ESP_SPP_SRV_STOP_EVT, &param);
}
BTA_JvFreeChannel(spp_local_param.spp_slots[i]->scn, BTA_JV_CONN_TYPE_RFCOMM,
(tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb, (void *)user_data);
}
BTA_JvFreeChannel(spp_local_param.spp_slots[i]->scn, BTA_JV_CONN_TYPE_RFCOMM,
(tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb, (void *)user_data);
}
}
osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
} while(0);
} while (0);
if (ret != ESP_SPP_SUCCESS) {
esp_spp_cb_param_t param;
param.srv_stop.status = ret;
param.srv_stop.scn = BTC_SPP_INVALID_SCN;
btc_spp_cb_to_app(ESP_SPP_SRV_STOP_EVT, &param);
}
if (srv_scn_arr) {
osi_free(srv_scn_arr);
srv_scn_arr = NULL;
}
}
static void btc_spp_write(btc_spp_args_t *arg)
@ -849,7 +910,7 @@ void btc_spp_call_handler(btc_msg_t *msg)
btc_spp_start_srv(arg);
break;
case BTC_SPP_ACT_STOP_SRV:
btc_spp_stop_srv();
btc_spp_stop_srv(arg);
break;
case BTC_SPP_ACT_WRITE:
btc_spp_write(arg);
@ -876,6 +937,8 @@ void btc_spp_cb_handler(btc_msg_t *msg)
param.disc_comp.status = p_data->disc_comp.status;
param.disc_comp.scn_num = p_data->disc_comp.scn_num;
memcpy(param.disc_comp.scn, p_data->disc_comp.scn, p_data->disc_comp.scn_num);
memcpy(param.disc_comp.service_name, p_data->disc_comp.service_name,
p_data->disc_comp.scn_num * sizeof(const char *));
btc_spp_cb_to_app(ESP_SPP_DISCOVERY_COMP_EVT, &param);
break;
case BTA_JV_RFCOMM_CL_INIT_EVT:
@ -909,6 +972,7 @@ void btc_spp_cb_handler(btc_msg_t *msg)
param.start.status = p_data->rfc_start.status;
param.start.handle = p_data->rfc_start.handle;
param.start.sec_id = p_data->rfc_start.sec_id;
param.start.scn = p_data->rfc_start.scn;
param.start.use_co = p_data->rfc_start.use_co;
btc_spp_cb_to_app(ESP_SPP_START_EVT, &param);
break;
@ -1130,6 +1194,7 @@ void btc_spp_cb_handler(btc_msg_t *msg)
case BTA_JV_FREE_SCN_EVT:
if (p_data->free_scn.server_status == BTA_JV_SERVER_RUNNING) {
param.srv_stop.status = p_data->free_scn.status;
param.srv_stop.scn = p_data->free_scn.scn;
btc_spp_cb_to_app(ESP_SPP_SRV_STOP_EVT, &param);
}
break;

View File

@ -341,8 +341,7 @@ tBTM_STATUS BTM_BleSetExtendedAdvParams(UINT8 instance, tBTM_BLE_GAP_EXT_ADV_PAR
params->peer_addr, params->filter_policy, params->tx_power,
params->primary_phy, params->max_skip,
params->secondary_phy, params->sid, params->scan_req_notif)) != HCI_SUCCESS) {
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
__func__, btm_ble_hci_status_to_str(err), err);
BTM_TRACE_ERROR("LE EA SetParams: cmd err=0x%x", err);
status = BTM_ILLEGAL_VALUE;
goto end;
}
@ -390,14 +389,12 @@ tBTM_STATUS BTM_BleConfigExtendedAdvDataRaw(BOOLEAN is_scan_rsp, UINT8 instance,
}
if (!is_scan_rsp) {
if ((err = btsnd_hcic_ble_set_ext_adv_data(instance, operation, 0, send_data_len, &data[data_offset])) != HCI_SUCCESS) {
BTM_TRACE_ERROR("%s, line %d, fail to send the hci command, the error code = %s",
__func__, __LINE__, btm_ble_hci_status_to_str(err));
BTM_TRACE_ERROR("LE EA SetAdvData: cmd err=0x%x", err);
status = BTM_ILLEGAL_VALUE;
}
} else {
if ((err = btsnd_hcic_ble_set_ext_adv_scan_rsp_data(instance, operation, 0, send_data_len, &data[data_offset])) != HCI_SUCCESS) {
BTM_TRACE_ERROR("%s, line %d, fail to send the hci command, the error code = %s(0x%x)",
__func__, __LINE__, btm_ble_hci_status_to_str(err), err);
BTM_TRACE_ERROR("LE EA SetScanRspData: cmd err=0x%x", err);
status = BTM_ILLEGAL_VALUE;
}
}
@ -452,8 +449,7 @@ tBTM_STATUS BTM_BleStartExtAdv(BOOLEAN enable, UINT8 num, tBTM_BLE_EXT_ADV *ext_
if ((err = btsnd_hcic_ble_ext_adv_enable(enable, num, instance,
duration, max_events)) != HCI_SUCCESS) {
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
__func__, btm_ble_hci_status_to_str(err), err);
BTM_TRACE_ERROR("LE EA En=%d: cmd err=0x%x", enable, err);
status = BTM_ILLEGAL_VALUE;
}
@ -464,9 +460,8 @@ tBTM_STATUS BTM_BleStartExtAdv(BOOLEAN enable, UINT8 num, tBTM_BLE_EXT_ADV *ext_
// enable = false, num == 0 or ext_adv = NULL
if ((err = btsnd_hcic_ble_ext_adv_enable(enable, num, NULL, NULL, NULL)) != HCI_SUCCESS) {
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
__func__, btm_ble_hci_status_to_str(err), err);
status = BTM_ILLEGAL_VALUE;
BTM_TRACE_ERROR("LE EA En=%d: cmd err=0x%x", enable, err);
status = BTM_ILLEGAL_VALUE;
}
goto end;
}
@ -504,8 +499,7 @@ tBTM_STATUS BTM_BleExtAdvSetRemove(UINT8 instance)
}
if ((err = btsnd_hcic_ble_remove_adv_set(instance)) != HCI_SUCCESS) {
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
__func__, btm_ble_hci_status_to_str(err), err);
BTM_TRACE_ERROR("LE EAS Rm: cmd err=0x%x", err);
status = BTM_ILLEGAL_VALUE;
}
@ -527,8 +521,7 @@ tBTM_STATUS BTM_BleExtAdvSetClear(void)
tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0};
if ((err = btsnd_hcic_ble_clear_adv_set()) != HCI_SUCCESS) {
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
__func__, btm_ble_hci_status_to_str(err), err);
BTM_TRACE_ERROR("LE EAS Clr: cmd err=0x%x", err);
status = BTM_ILLEGAL_VALUE;
}
@ -559,15 +552,14 @@ tBTM_STATUS BTM_BlePeriodicAdvSetParams(UINT8 instance, tBTM_BLE_Periodic_Adv_Pa
extend_adv_cb.inst[instance].connetable ||
extend_adv_cb.inst[instance].legacy_pdu) {
BTM_TRACE_ERROR("%s, instance = %d, Before set the periodic adv parameters, please configure the the \
extend adv to nonscannable and nonconnectable fisrt, and it shouldn't include the legacy bit.", __func__, instance);
extend adv to nonscannable and nonconnectable first, and it shouldn't include the legacy bit.", __func__, instance);
status = BTM_ILLEGAL_VALUE;
goto end;
}
if ((err= btsnd_hcic_ble_set_periodic_adv_params(instance, params->interval_min,
params->interval_max, params->properties)) != HCI_SUCCESS) {
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
__func__, btm_ble_hci_status_to_str(err), err);
BTM_TRACE_ERROR("LE PA SetParams: cmd err=0x%x", err);
status = BTM_ILLEGAL_VALUE;
}
@ -619,8 +611,7 @@ tBTM_STATUS BTM_BlePeriodicAdvCfgDataRaw(UINT8 instance, UINT16 len, UINT8 *data
}
if ((err = btsnd_hcic_ble_set_periodic_adv_data(instance, operation, send_data_len, &data[data_offset])) != HCI_SUCCESS) {
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
__func__, btm_ble_hci_status_to_str(err), err);
BTM_TRACE_ERROR("LE PA SetData: cmd err=0x%x", err);
status = BTM_ILLEGAL_VALUE;
}
rem_len -= send_data_len;
@ -643,14 +634,13 @@ tBTM_STATUS BTM_BlePeriodicAdvEnable(UINT8 instance, BOOLEAN enable)
tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0};
if (instance >= MAX_BLE_ADV_INSTANCE) {
BTM_TRACE_ERROR("%s, invalid insatnce %d", __func__, instance);
BTM_TRACE_ERROR("%s, invalid instance %d", __func__, instance);
status = BTM_ILLEGAL_VALUE;
goto end;
}
if ((err = btsnd_hcic_ble_periodic_adv_enable(enable, instance)) != HCI_SUCCESS) {
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
__func__, btm_ble_hci_status_to_str(err), err);
BTM_TRACE_ERROR("LE PA En=%d: cmd err=0x%x", enable, err);
status = BTM_ILLEGAL_VALUE;
}
@ -688,7 +678,7 @@ tBTM_STATUS BTM_BlePeriodicAdvCreateSync(tBTM_BLE_Periodic_Sync_Params *params)
if (!btsnd_hcic_ble_periodic_adv_create_sync(params->filter_policy, params->sid, params->addr_type,
params->addr, params->sync_timeout, 0)) {
BTM_TRACE_ERROR("%s, send cmd failed", __func__);
BTM_TRACE_ERROR("LE PA CreateSync cmd failed");
status = BTM_ILLEGAL_VALUE;
}
@ -749,8 +739,7 @@ tBTM_STATUS BTM_BlePeriodicAdvSyncCancel(void)
tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0};
if ((err = btsnd_hcic_ble_periodic_adv_create_sync_cancel()) != HCI_SUCCESS) {
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
__func__, btm_ble_hci_status_to_str(err), err);
BTM_TRACE_ERROR("LE PA SyncCancel, cmd err=0x%x", err);
status = BTM_ILLEGAL_VALUE;
}
@ -770,8 +759,7 @@ tBTM_STATUS BTM_BlePeriodicAdvSyncTerm(UINT16 sync_handle)
tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0};
if (( err = btsnd_hcic_ble_periodic_adv_term_sync(sync_handle)) != HCI_SUCCESS) {
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
__func__, btm_ble_hci_status_to_str(err), err);
BTM_TRACE_ERROR("LE PA SyncTerm: cmd err=0x%x", err);
status = BTM_ILLEGAL_VALUE;
}
@ -797,8 +785,7 @@ tBTM_STATUS BTM_BlePeriodicAdvAddDevToList(tBLE_ADDR_TYPE addr_type, BD_ADDR add
}
if ((err = btsnd_hcic_ble_add_dev_to_periodic_adv_list(addr_type, addr, sid)) != HCI_SUCCESS) {
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
__func__, btm_ble_hci_status_to_str(err), err);
BTM_TRACE_ERROR("LE PA AddDevToList: cmd err=0x%x", err);
status = BTM_ILLEGAL_VALUE;
}
@ -824,8 +811,7 @@ tBTM_STATUS BTM_BlePeriodicAdvRemoveDevFromList(tBLE_ADDR_TYPE addr_type, BD_ADD
}
if ((err = btsnd_hcic_ble_rm_dev_from_periodic_adv_list(addr_type, addr, sid)) != HCI_SUCCESS) {
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
__func__, btm_ble_hci_status_to_str(err), err);
BTM_TRACE_ERROR("LE PA RmDevFromList: cmd err=0x%x", err);
status = BTM_ILLEGAL_VALUE;
}
@ -845,8 +831,7 @@ tBTM_STATUS BTM_BlePeriodicAdvClearDev(void)
tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0};
if ((err = btsnd_hcic_ble_clear_periodic_adv_list()) != HCI_SUCCESS) {
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
__func__, btm_ble_hci_status_to_str(err), err);
BTM_TRACE_ERROR("LE PA ClrDev: cmd err=0x%x", err);
status = BTM_ILLEGAL_VALUE;
}
@ -894,8 +879,7 @@ tBTM_STATUS BTM_BleSetExtendedScanParams(tBTM_BLE_EXT_SCAN_PARAMS *params)
if ((err = btsnd_hcic_ble_set_ext_scan_params(params->own_addr_type, params->filter_policy, phy_mask, phy_count,
hci_params)) != HCI_SUCCESS) {
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
__func__, btm_ble_hci_status_to_str(err), err);
BTM_TRACE_ERROR("LE ES SetParams: cmd err=0x%x", err);
status = BTM_ILLEGAL_VALUE;
}
@ -923,8 +907,7 @@ tBTM_STATUS BTM_BleExtendedScan(BOOLEAN enable, UINT16 duration, UINT16 period)
}
if ((err = btsnd_hcic_ble_ext_scan_enable(enable, extend_adv_cb.scan_duplicate, duration, period)) != HCI_SUCCESS) {
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
__func__, btm_ble_hci_status_to_str(err), err);
BTM_TRACE_ERROR("LE ES En=%d: cmd err=0x%x", enable, err);
status = BTM_ILLEGAL_VALUE;
}

View File

@ -414,12 +414,13 @@ void btm_ble_resolve_random_addr(BD_ADDR random_bda, tBTM_BLE_RESOLVE_CBACK *p_c
/* start to resolve random address */
/* check for next security record */
for (p_node = list_begin(btm_cb.p_sec_dev_rec_list); p_node; p_node = list_next(p_node)) {
p_dev_rec = list_node(p_node);
p_dev_rec = list_node(p_node);
p_mgnt_cb->p_dev_rec = p_dev_rec;
if (btm_ble_match_random_bda(p_dev_rec)) {
break;
}
}
break;
}
p_mgnt_cb->p_dev_rec = NULL;
}
btm_ble_resolve_address_cmpl();
} else {
(*p_cback)(NULL, p);

View File

@ -4589,26 +4589,6 @@ void btm_sec_disconnected (UINT16 handle, UINT8 reason)
#endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
BTM_TRACE_EVENT("%s before update sec_flags=0x%x\n", __func__, p_dev_rec->sec_flags);
/* If we are in the process of bonding we need to tell client that auth failed */
if ( (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
&& (memcmp (btm_cb.pairing_bda, p_dev_rec->bd_addr, BD_ADDR_LEN) == 0)) {
btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
p_dev_rec->sec_flags &= ~BTM_SEC_LINK_KEY_KNOWN;
if (btm_cb.api.p_auth_complete_callback) {
/* If the disconnection reason is REPEATED_ATTEMPTS,
send this error message to complete callback function
to display the error message of Repeated attempts.
All others, send HCI_ERR_AUTH_FAILURE. */
if (reason == HCI_ERR_REPEATED_ATTEMPTS) {
result = HCI_ERR_REPEATED_ATTEMPTS;
} else if (old_pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD) {
result = HCI_ERR_HOST_REJECT_SECURITY;
}
(*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class,
p_dev_rec->sec_bd_name, result);
}
}
#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, p_dev_rec->bd_addr, HCI_SUCCESS);
/* see sec_flags processing in btm_acl_removed */
@ -4645,6 +4625,26 @@ void btm_sec_disconnected (UINT16 handle, UINT8 reason)
}
BTM_TRACE_EVENT("%s after update sec_flags=0x%x\n", __func__, p_dev_rec->sec_flags);
/* If we are in the process of bonding we need to tell client that auth failed */
if ( (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
&& (memcmp (btm_cb.pairing_bda, p_dev_rec->bd_addr, BD_ADDR_LEN) == 0)) {
btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
p_dev_rec->sec_flags &= ~BTM_SEC_LINK_KEY_KNOWN;
if (btm_cb.api.p_auth_complete_callback) {
/* If the disconnection reason is REPEATED_ATTEMPTS,
send this error message to complete callback function
to display the error message of Repeated attempts.
All others, send HCI_ERR_AUTH_FAILURE. */
if (reason == HCI_ERR_REPEATED_ATTEMPTS) {
result = HCI_ERR_REPEATED_ATTEMPTS;
} else if (old_pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD) {
result = HCI_ERR_HOST_REJECT_SECURITY;
}
(*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class,
p_dev_rec->sec_bd_name, result);
}
}
}
/*******************************************************************************

View File

@ -707,6 +707,10 @@ static void btu_hcif_disconnection_comp_evt (UINT8 *p)
handle = HCID_GET_HANDLE (handle);
if (reason != HCI_ERR_PEER_USER && reason != HCI_ERR_CONN_CAUSE_LOCAL_HOST) {
HCI_TRACE_WARNING("DiscCmpl evt: hdl=%d, rsn=0x%x", handle, reason);
}
#if BTM_SCO_INCLUDED == TRUE
/* If L2CAP doesn't know about it, send it to SCO */
if (!l2c_link_hci_disc_comp (handle, reason)) {
@ -1126,7 +1130,7 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l
uint8_t status;
STREAM_TO_UINT8 (status, p);
if(status != HCI_SUCCESS) {
HCI_TRACE_ERROR("%s opcode 0x%x status 0x%x", __func__, opcode, status);
HCI_TRACE_ERROR("CC evt: op=0x%x, status=0x%x", opcode, status);
}
break;
}
@ -1259,7 +1263,7 @@ static void btu_hcif_hdl_command_status (UINT16 opcode, UINT8 status, UINT8 *p_c
{
uint8_t btm_status = BTM_SUCCESS;
if(status != HCI_SUCCESS) {
HCI_TRACE_ERROR("%s, Create sync error, the error code = 0x%x", __func__, status);
HCI_TRACE_ERROR("CS evt: LE PA CreateSync status=0x%x", status);
btm_status = BTM_ILLEGAL_VALUE;
}
btm_create_sync_callback(btm_status);
@ -1269,7 +1273,7 @@ static void btu_hcif_hdl_command_status (UINT16 opcode, UINT8 status, UINT8 *p_c
{
uint8_t btm_status = BTM_SUCCESS;
if(status != HCI_SUCCESS) {
HCI_TRACE_ERROR("%s, Set phy error, the error code = 0x%x", __func__, status);
HCI_TRACE_ERROR("CS evt: LE SetPhy status=0x%x", status);
btm_status = BTM_ILLEGAL_VALUE;
}
btm_set_phy_callback(btm_status);

View File

@ -1833,7 +1833,7 @@ UINT16 L2CA_SendFixedChnlData (UINT16 fixed_cid, BD_ADDR rem_bda, BT_HDR *p_buf)
}
// If already congested, do not accept any more packets
if (p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL]->cong_sent) {
if (p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL]->cong_sent && fixed_cid != L2CAP_SMP_CID) {
L2CAP_TRACE_DEBUG ("L2CAP - CID: 0x%04x cannot send, already congested\
xmit_hold_q.count: %u buff_quota: %u", fixed_cid,
fixed_queue_length(p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL]->xmit_hold_q),

View File

@ -591,7 +591,7 @@ void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status, UINT16 conn_in
/* See if we have a link control block for the remote device */
p_lcb = l2cu_find_lcb_by_handle(handle);
if (!p_lcb) {
L2CAP_TRACE_WARNING("l2cble_process_conn_update_evt: Invalid handle: %d", handle);
L2CAP_TRACE_WARNING("le con upd: inv hdl=%d", handle);
return;
}
if (status == HCI_SUCCESS){
@ -599,7 +599,7 @@ void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status, UINT16 conn_in
p_lcb->current_used_conn_latency = conn_latency;
p_lcb->current_used_conn_timeout = conn_timeout;
}else{
L2CAP_TRACE_WARNING("l2cble_process_conn_update_evt: Error status: %d", status);
L2CAP_TRACE_WARNING("le con upd: err_stat=0x%x", status);
}
p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING;
@ -617,7 +617,7 @@ void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status, UINT16 conn_in
btu_stop_timer (&p_lcb->timer_entry);
L2CAP_TRACE_DEBUG("l2cble_process_conn_update_evt: conn_update_mask=%d", p_lcb->conn_update_mask);
L2CAP_TRACE_DEBUG("le con upd: conn_update_mask=%d", p_lcb->conn_update_mask);
}
/*******************************************************************************

View File

@ -1456,9 +1456,11 @@ void l2cu_change_pri_ccb (tL2C_CCB *p_ccb, tL2CAP_CHNL_PRIORITY priority)
** Returns pointer to CCB, or NULL if none
**
*******************************************************************************/
bool l2cu_find_ccb_in_list(void *p_ccb_node, void *p_local_cid);
tL2C_CCB *l2cu_allocate_ccb (tL2C_LCB *p_lcb, UINT16 cid)
{
tL2C_CCB *p_ccb = NULL;
uint16_t tmp_cid = L2CAP_BASE_APPL_CID;
L2CAP_TRACE_DEBUG ("l2cu_allocate_ccb: cid 0x%04x", cid);
p_ccb = l2cu_find_free_ccb ();
@ -1481,7 +1483,13 @@ tL2C_CCB *l2cu_allocate_ccb (tL2C_LCB *p_lcb, UINT16 cid)
p_ccb->in_use = TRUE;
/* Get a CID for the connection */
p_ccb->local_cid = L2CAP_BASE_APPL_CID + (list_length(l2cb.p_ccb_pool) - 1);
for (tmp_cid = L2CAP_BASE_APPL_CID; tmp_cid < MAX_L2CAP_CHANNELS + L2CAP_BASE_APPL_CID; tmp_cid++) {
if (list_foreach(l2cb.p_ccb_pool, l2cu_find_ccb_in_list, &tmp_cid) == NULL) {
break;
}
}
assert(tmp_cid != MAX_L2CAP_CHANNELS + L2CAP_BASE_APPL_CID);
p_ccb->local_cid = tmp_cid;
p_ccb->p_lcb = p_lcb;
p_ccb->p_rcb = NULL;
p_ccb->should_free_rcb = false;

View File

@ -488,6 +488,7 @@ esp_err_t esp_bt_sleep_disable(void);
* Note that scan duplicate list will be automatically cleared when the maximum amount of device in the filter is reached
* the amount of device in the filter can be configured in menuconfig.
*
* @note This function name is incorrectly spelled, it will be fixed in release 5.x version.
*
* @return
* - ESP_OK : success

View File

@ -26,7 +26,7 @@ extern "C" {
#endif
#define ESP_BT_CTRL_CONFIG_MAGIC_VAL 0x5A5AA5A5
#define ESP_BT_CTRL_CONFIG_VERSION 0x02101290
#define ESP_BT_CTRL_CONFIG_VERSION 0x02103080
#define ESP_BT_HCI_TL_MAGIC_VALUE 0xfadebead
#define ESP_BT_HCI_TL_VERSION 0x00010000
@ -133,6 +133,8 @@ enum {
#define CFG_NASK CFG_MASK_BIT_SCAN_DUPLICATE_OPTION
#define BLE_HW_TARGET_CODE_ESP32C3_CHIP_ECO0 (0x01010000)
#define BT_CONTROLLER_INIT_CONFIG_DEFAULT() { \
.magic = ESP_BT_CTRL_CONFIG_MAGIC_VAL, \
.version = ESP_BT_CTRL_CONFIG_VERSION, \
@ -158,6 +160,7 @@ enum {
.normal_adv_size = NORMAL_SCAN_DUPLICATE_CACHE_SIZE, \
.mesh_adv_size = MESH_DUPLICATE_SCAN_CACHE_SIZE, \
.coex_phy_coded_tx_rx_time_limit = CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EFF, \
.hw_target_code = BLE_HW_TARGET_CODE_ESP32C3_CHIP_ECO0, \
};
#else
@ -221,6 +224,7 @@ typedef struct {
uint16_t normal_adv_size; /*!< Normal adv size for scan duplicate */
uint16_t mesh_adv_size; /*!< Mesh adv size for scan duplicate */
uint8_t coex_phy_coded_tx_rx_time_limit; /*!< limit on max tx/rx time in case of connection using CODED-PHY with Wi-Fi coexistence */
uint32_t hw_target_code; /*!< hardware target */
} esp_bt_controller_config_t;
/**
@ -263,22 +267,23 @@ typedef enum {
* @brief Bluetooth TX power level(index), it's just a index corresponding to power(dbm).
*/
typedef enum {
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_PWR_LVL_N27 = 0, /*!< Corresponding to -27dbm */
ESP_PWR_LVL_N24 = 1, /*!< Corresponding to -24dbm */
ESP_PWR_LVL_N21 = 2, /*!< Corresponding to -21dbm */
ESP_PWR_LVL_N18 = 3, /*!< Corresponding to -18dbm */
ESP_PWR_LVL_N15 = 4, /*!< Corresponding to -15dbm */
ESP_PWR_LVL_N12 = 5, /*!< Corresponding to -12dbm */
ESP_PWR_LVL_N9 = 6, /*!< Corresponding to -9dbm */
ESP_PWR_LVL_N6 = 7, /*!< Corresponding to -6dbm */
ESP_PWR_LVL_N3 = 8, /*!< Corresponding to -3dbm */
ESP_PWR_LVL_N0 = 9, /*!< Corresponding to 0dbm */
ESP_PWR_LVL_P3 = 10, /*!< Corresponding to +3dbm */
ESP_PWR_LVL_P6 = 11, /*!< Corresponding to +6dbm */
ESP_PWR_LVL_P9 = 12, /*!< Corresponding to +9dbm */
ESP_PWR_LVL_P12 = 13, /*!< Corresponding to +12dbm */
ESP_PWR_LVL_P15 = 14, /*!< Corresponding to +15dbm */
ESP_PWR_LVL_P18 = 15, /*!< Corresponding to +18dbm */
ESP_PWR_LVL_INVALID = 0xFF, /*!< Indicates an invalid value */
} esp_power_level_t;
/**

View File

@ -160,17 +160,12 @@ static void adc_power_on_internal(void)
void adc_power_acquire(void)
{
bool powered_on = false;
ADC_POWER_ENTER();
s_adc_power_on_cnt++;
if (s_adc_power_on_cnt == 1) {
adc_power_on_internal();
powered_on = true;
}
ADC_POWER_EXIT();
if (powered_on) {
ESP_LOGV(ADC_TAG, "%s: ADC powered on", __func__);
}
}
void adc_power_on(void)
@ -182,12 +177,15 @@ void adc_power_on(void)
static void adc_power_off_internal(void)
{
#if CONFIG_IDF_TARGET_ESP32
adc_hal_set_power_manage(ADC_POWER_SW_OFF);
#else
adc_hal_set_power_manage(ADC_POWER_BY_FSM);
#endif
}
void adc_power_release(void)
{
bool powered_off = false;
ADC_POWER_ENTER();
s_adc_power_on_cnt--;
/* Sanity check */
@ -197,12 +195,8 @@ void adc_power_release(void)
abort();
} else if (s_adc_power_on_cnt == 0) {
adc_power_off_internal();
powered_off = true;
}
ADC_POWER_EXIT();
if (powered_off) {
ESP_LOGV(ADC_TAG, "%s: ADC powered off", __func__);
}
}
void adc_power_off(void)
@ -212,6 +206,33 @@ void adc_power_off(void)
ADC_POWER_EXIT();
}
esp_err_t adc1_pad_get_io_num(adc1_channel_t channel, gpio_num_t *gpio_num)
{
ADC_CHANNEL_CHECK(ADC_NUM_1, channel);
int io = ADC_GET_IO_NUM(ADC_NUM_1, channel);
if (io < 0) {
return ESP_ERR_INVALID_ARG;
} else {
*gpio_num = (gpio_num_t)io;
}
return ESP_OK;
}
esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num)
{
ADC_CHANNEL_CHECK(ADC_NUM_2, channel);
int io = ADC_GET_IO_NUM(ADC_NUM_2, channel);
if (io < 0) {
return ESP_ERR_INVALID_ARG;
} else {
*gpio_num = (gpio_num_t)io;
}
return ESP_OK;
}
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
esp_err_t adc_set_clk_div(uint8_t clk_div)
@ -323,20 +344,6 @@ esp_err_t adc_rtc_reset(void)
/*-------------------------------------------------------------------------------------
* ADC1
*------------------------------------------------------------------------------------*/
esp_err_t adc1_pad_get_io_num(adc1_channel_t channel, gpio_num_t *gpio_num)
{
ADC_CHANNEL_CHECK(ADC_NUM_1, channel);
int io = ADC_GET_IO_NUM(ADC_NUM_1, channel);
if (io < 0) {
return ESP_ERR_INVALID_ARG;
} else {
*gpio_num = (gpio_num_t)io;
}
return ESP_OK;
}
esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten)
{
ADC_CHANNEL_CHECK(ADC_NUM_1, channel);
@ -466,20 +473,6 @@ void adc1_ulp_enable(void)
/*---------------------------------------------------------------
ADC2
---------------------------------------------------------------*/
esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num)
{
ADC_CHANNEL_CHECK(ADC_NUM_2, channel);
int io = ADC_GET_IO_NUM(ADC_NUM_2, channel);
if (io < 0) {
return ESP_ERR_INVALID_ARG;
} else {
*gpio_num = (gpio_num_t)io;
}
return ESP_OK;
}
/** For ESP32S2 the ADC2 The right to use ADC2 is controlled by the arbiter, and there is no need to set a lock.*/
esp_err_t adc2_wifi_acquire(void)
{
@ -562,6 +555,7 @@ static inline void adc2_dac_disable( adc2_channel_t channel)
*/
esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *raw_out)
{
esp_err_t ret = ESP_OK;
int adc_value = 0;
ADC_CHECK(raw_out != NULL, "ADC out value err", ESP_ERR_INVALID_ARG);
@ -601,7 +595,8 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
#endif //CONFIG_PM_ENABLE
#endif //CONFIG_IDF_TARGET_ESP32
if (adc_hal_convert(ADC_NUM_2, channel, &adc_value)) {
ret = adc_hal_convert(ADC_NUM_2, channel, &adc_value);
if (ret != ESP_OK) {
adc_value = -1;
}
@ -618,13 +613,8 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
adc_power_release();
SARADC2_RELEASE();
if (adc_value < 0) {
ESP_LOGD( ADC_TAG, "ADC2 ARB: Return data is invalid." );
return ESP_ERR_INVALID_STATE;
}
*raw_out = adc_value;
return ESP_OK;
return ret;
}
esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)

View File

@ -25,6 +25,7 @@
#include "soc/io_mux_reg.h"
#include "hal/cpu_hal.h"
#include "hal/cpu_ll.h"
#include "hal/gpio_hal.h"
#include "driver/periph_ctrl.h"
#include "esp_rom_gpio.h"
#include "freertos/FreeRTOS.h"
@ -267,13 +268,13 @@ esp_err_t dedic_gpio_new_bundle(const dedic_gpio_bundle_config_t *config, dedic_
// route dedicated GPIO channel signals to GPIO matrix
if (config->flags.in_en) {
for (size_t i = 0; i < config->array_size; i++) {
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->gpio_array[i]], PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[config->gpio_array[i]], PIN_FUNC_GPIO);
esp_rom_gpio_connect_in_signal(config->gpio_array[i], dedic_gpio_periph_signals.cores[core_id].in_sig_per_channel[in_offset + i], config->flags.in_invert);
}
}
if (config->flags.out_en) {
for (size_t i = 0; i < config->array_size; i++) {
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->gpio_array[i]], PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[config->gpio_array[i]], PIN_FUNC_GPIO);
esp_rom_gpio_connect_out_signal(config->gpio_array[i], dedic_gpio_periph_signals.cores[core_id].out_sig_per_channel[out_offset + i], config->flags.out_invert, false);
}
}

View File

@ -135,6 +135,7 @@ esp_err_t adc_digi_init(void)
esp_err_t adc_digi_deinit(void)
{
adc_power_release();
ADC_ENTER_CRITICAL();
adc_hal_digi_deinit();
ADC_EXIT_CRITICAL();
@ -143,6 +144,8 @@ esp_err_t adc_digi_deinit(void)
esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
{
/* If enable digital controller, adc xpd should always on. */
adc_power_acquire();
ADC_ENTER_CRITICAL();
adc_hal_digi_controller_config(config);
ADC_EXIT_CRITICAL();

View File

@ -19,6 +19,7 @@
#include "sdkconfig.h"
#include "esp_intr_alloc.h"
#include "esp_log.h"
#include "esp_pm.h"
#include "sys/lock.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
@ -32,6 +33,7 @@
#include "hal/adc_hal.h"
#include "hal/dma_types.h"
#include "esp32c3/esp_efuse_rtc_calib.h"
#include "esp_private/gdma.h"
#define ADC_CHECK_RET(fun_ret) ({ \
if (fun_ret != ESP_OK) { \
@ -57,37 +59,34 @@ extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate posi
#define ADC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock)
#define ADC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
/*---------------------------------------------------------------
Digital Controller Context
---------------------------------------------------------------*/
/**
* 1. adc_digi_mutex: this mutex lock is used for ADC digital controller. On ESP32-C3, the ADC single read APIs (unit1 & unit2)
* and ADC DMA continuous read APIs share the ``apb_saradc_struct.h`` regs.
*
* 2. sar_adc_mutex: this mutex lock is used for SARADC2 module. On ESP32C-C3, the ADC single read APIs (unit2), ADC DMA
* continuous read APIs and WIFI share the SARADC2 analog IP.
*
* Sequence:
* Acquire: 1. sar_adc_mutex; 2. adc_digi_mutex;
* Release: 1. adc_digi_mutex; 2. sar_adc_mutex;
* 1. sar_adc1_lock: this mutex lock is to protect the SARADC1 module.
* 2. sar_adc2_lock: this mutex lock is to protect the SARADC2 module. On C3, it is controlled by the digital controller
* and PWDET controller.
* 3. adc_reg_lock: this spin lock is to protect the shared registers used by ADC1 / ADC2 single read mode.
*/
static _lock_t adc_digi_mutex;
#define ADC_DIGI_LOCK_ACQUIRE() _lock_acquire(&adc_digi_mutex)
#define ADC_DIGI_LOCK_RELEASE() _lock_release(&adc_digi_mutex)
static _lock_t sar_adc2_mutex;
#define SAC_ADC2_LOCK_ACQUIRE() _lock_acquire(&sar_adc2_mutex)
#define SAC_ADC2_LOCK_RELEASE() _lock_release(&sar_adc2_mutex)
static _lock_t sar_adc1_lock;
#define SAR_ADC1_LOCK_ACQUIRE() _lock_acquire(&sar_adc1_lock)
#define SAR_ADC1_LOCK_RELEASE() _lock_release(&sar_adc1_lock)
static _lock_t sar_adc2_lock;
#define SAR_ADC2_LOCK_ACQUIRE() _lock_acquire(&sar_adc2_lock)
#define SAR_ADC2_LOCK_RELEASE() _lock_release(&sar_adc2_lock)
portMUX_TYPE adc_reg_lock = portMUX_INITIALIZER_UNLOCKED;
#define ADC_REG_LOCK_ENTER() portENTER_CRITICAL(&adc_reg_lock)
#define ADC_REG_LOCK_EXIT() portEXIT_CRITICAL(&adc_reg_lock)
#define INTERNAL_BUF_NUM 5
#define IN_SUC_EOF_BIT GDMA_LL_EVENT_RX_SUC_EOF
/*---------------------------------------------------------------
Digital Controller Context
---------------------------------------------------------------*/
typedef struct adc_digi_context_t {
intr_handle_t dma_intr_hdl; //MD interrupt handle
uint32_t bytes_between_intr; //bytes between in suc eof intr
uint8_t *rx_dma_buf; //dma buffer
adc_dma_hal_context_t hal_dma; //dma context (hal)
adc_dma_hal_config_t hal_dma_config; //dma config (hal)
adc_hal_context_t hal; //hal context
gdma_channel_handle_t rx_dma_channel; //dma rx channel handle
RingbufHandle_t ringbuf_hdl; //RX ringbuffer handler
intptr_t rx_eof_desc_addr; //eof descriptor address of RX channel
bool ringbuf_overflow_flag; //1: ringbuffer overflow
bool driver_start_flag; //1: driver is started; 0: driver is stoped
bool use_adc1; //1: ADC unit1 will be used; 0: ADC unit1 won't be used.
@ -95,6 +94,7 @@ typedef struct adc_digi_context_t {
adc_atten_t adc1_atten; //Attenuation for ADC1. On this chip each ADC can only support one attenuation.
adc_atten_t adc2_atten; //Attenuation for ADC2. On this chip each ADC can only support one attenuation.
adc_digi_config_t digi_controller_config; //Digital Controller Configuration
esp_pm_lock_handle_t pm_lock; //For power management
} adc_digi_context_t;
static adc_digi_context_t *s_adc_digi_ctx = NULL;
@ -104,7 +104,7 @@ static uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t cha
/*---------------------------------------------------------------
ADC Continuous Read Mode (via DMA)
---------------------------------------------------------------*/
static void adc_dma_intr(void* arg);
static IRAM_ATTR bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data);
static int8_t adc_digi_get_io_num(uint8_t adc_unit, uint8_t adc_channel)
{
@ -149,11 +149,6 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
goto cleanup;
}
ret = esp_intr_alloc(SOC_GDMA_ADC_INTR_SOURCE, 0, adc_dma_intr, (void *)s_adc_digi_ctx, &s_adc_digi_ctx->dma_intr_hdl);
if (ret != ESP_OK) {
goto cleanup;
}
//ringbuffer
s_adc_digi_ctx->ringbuf_hdl = xRingbufferCreate(init_config->max_store_buf_size, RINGBUF_TYPE_BYTEBUF);
if (!s_adc_digi_ctx->ringbuf_hdl) {
@ -161,22 +156,19 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
goto cleanup;
}
//malloc internal buffer
s_adc_digi_ctx->bytes_between_intr = init_config->conv_num_each_intr;
s_adc_digi_ctx->rx_dma_buf = heap_caps_calloc(1, s_adc_digi_ctx->bytes_between_intr * INTERNAL_BUF_NUM, MALLOC_CAP_INTERNAL);
//malloc internal buffer used by DMA
s_adc_digi_ctx->rx_dma_buf = heap_caps_calloc(1, init_config->conv_num_each_intr * INTERNAL_BUF_NUM, MALLOC_CAP_INTERNAL);
if (!s_adc_digi_ctx->rx_dma_buf) {
ret = ESP_ERR_NO_MEM;
goto cleanup;
}
//malloc dma descriptor
s_adc_digi_ctx->hal_dma_config.rx_desc = heap_caps_calloc(1, (sizeof(dma_descriptor_t)) * INTERNAL_BUF_NUM, MALLOC_CAP_DMA);
if (!s_adc_digi_ctx->hal_dma_config.rx_desc) {
s_adc_digi_ctx->hal.rx_desc = heap_caps_calloc(1, (sizeof(dma_descriptor_t)) * INTERNAL_BUF_NUM, MALLOC_CAP_DMA);
if (!s_adc_digi_ctx->hal.rx_desc) {
ret = ESP_ERR_NO_MEM;
goto cleanup;
}
s_adc_digi_ctx->hal_dma_config.desc_max_num = INTERNAL_BUF_NUM;
s_adc_digi_ctx->hal_dma_config.dma_chan = init_config->dma_chan;
//malloc pattern table
s_adc_digi_ctx->digi_controller_config.adc_pattern = calloc(1, SOC_ADC_PATT_LEN_MAX * sizeof(adc_digi_pattern_table_t));
@ -185,6 +177,14 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
goto cleanup;
}
#if CONFIG_PM_ENABLE
ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "adc_dma", &s_adc_digi_ctx->pm_lock);
if (ret != ESP_OK) {
goto cleanup;
}
#endif //CONFIG_PM_ENABLE
//init gpio pins
if (init_config->adc1_chan_mask) {
ret = adc_digi_gpio_init(ADC_NUM_1, init_config->adc1_chan_mask);
if (ret != ESP_OK) {
@ -198,8 +198,39 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
}
}
//alloc rx gdma channel
gdma_channel_alloc_config_t rx_alloc_config = {
.direction = GDMA_CHANNEL_DIRECTION_RX,
};
ret = gdma_new_channel(&rx_alloc_config, &s_adc_digi_ctx->rx_dma_channel);
if (ret != ESP_OK) {
goto cleanup;
}
gdma_connect(s_adc_digi_ctx->rx_dma_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_ADC, 0));
gdma_strategy_config_t strategy_config = {
.auto_update_desc = true,
.owner_check = true
};
gdma_apply_strategy(s_adc_digi_ctx->rx_dma_channel, &strategy_config);
gdma_rx_event_callbacks_t cbs = {
.on_recv_eof = adc_dma_in_suc_eof_callback
};
gdma_register_rx_event_callbacks(s_adc_digi_ctx->rx_dma_channel, &cbs, s_adc_digi_ctx);
int dma_chan;
gdma_get_channel_id(s_adc_digi_ctx->rx_dma_channel, &dma_chan);
adc_hal_config_t config = {
.desc_max_num = INTERNAL_BUF_NUM,
.dma_chan = dma_chan,
.eof_num = init_config->conv_num_each_intr / ADC_HAL_DATA_LEN_PER_CONV
};
adc_hal_context_config(&s_adc_digi_ctx->hal, &config);
//enable SARADC module clock
periph_module_enable(PERIPH_SARADC_MODULE);
periph_module_enable(PERIPH_GDMA_MODULE);
adc_hal_calibration_init(ADC_NUM_1);
adc_hal_calibration_init(ADC_NUM_2);
@ -212,46 +243,42 @@ cleanup:
}
static IRAM_ATTR void adc_dma_intr(void *arg)
static IRAM_ATTR bool adc_dma_intr(adc_digi_context_t *adc_digi_ctx);
static IRAM_ATTR bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data)
{
assert(event_data);
adc_digi_context_t *adc_digi_ctx = (adc_digi_context_t *)user_data;
adc_digi_ctx->rx_eof_desc_addr = event_data->rx_eof_desc_addr;
return adc_dma_intr(adc_digi_ctx);
}
static IRAM_ATTR bool adc_dma_intr(adc_digi_context_t *adc_digi_ctx)
{
portBASE_TYPE taskAwoken = 0;
BaseType_t ret;
adc_hal_dma_desc_status_t status = false;
dma_descriptor_t *current_desc = NULL;
//clear the in suc eof interrupt
adc_hal_digi_clr_intr(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config, IN_SUC_EOF_BIT);
while (s_adc_digi_ctx->hal_dma_config.cur_desc_ptr->dw0.owner == 0) {
dma_descriptor_t *current_desc = s_adc_digi_ctx->hal_dma_config.cur_desc_ptr;
ret = xRingbufferSendFromISR(s_adc_digi_ctx->ringbuf_hdl, current_desc->buffer, current_desc->dw0.length, &taskAwoken);
if (ret == pdFALSE) {
//ringbuffer overflow
s_adc_digi_ctx->ringbuf_overflow_flag = 1;
}
s_adc_digi_ctx->hal_dma_config.desc_cnt += 1;
//cycle the dma descriptor and buffers
s_adc_digi_ctx->hal_dma_config.cur_desc_ptr = s_adc_digi_ctx->hal_dma_config.cur_desc_ptr->next;
if (!s_adc_digi_ctx->hal_dma_config.cur_desc_ptr) {
while (1) {
status = adc_hal_get_reading_result(&adc_digi_ctx->hal, adc_digi_ctx->rx_eof_desc_addr, &current_desc);
if (status != ADC_HAL_DMA_DESC_VALID) {
break;
}
ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, current_desc->buffer, current_desc->dw0.length, &taskAwoken);
if (ret == pdFALSE) {
//ringbuffer overflow
adc_digi_ctx->ringbuf_overflow_flag = 1;
}
}
if (!s_adc_digi_ctx->hal_dma_config.cur_desc_ptr) {
assert(s_adc_digi_ctx->hal_dma_config.desc_cnt == s_adc_digi_ctx->hal_dma_config.desc_max_num);
//reset the current descriptor status
s_adc_digi_ctx->hal_dma_config.cur_desc_ptr = s_adc_digi_ctx->hal_dma_config.rx_desc;
s_adc_digi_ctx->hal_dma_config.desc_cnt = 0;
if (status == ADC_HAL_DMA_DESC_NULL) {
//start next turns of dma operation
adc_hal_digi_dma_multi_descriptor(&s_adc_digi_ctx->hal_dma_config, s_adc_digi_ctx->rx_dma_buf, s_adc_digi_ctx->bytes_between_intr, s_adc_digi_ctx->hal_dma_config.desc_max_num);
adc_hal_digi_rxdma_start(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config);
adc_hal_digi_rxdma_start(&adc_digi_ctx->hal, adc_digi_ctx->rx_dma_buf);
}
if(taskAwoken == pdTRUE) {
portYIELD_FROM_ISR();
}
return (taskAwoken == pdTRUE);
}
esp_err_t adc_digi_start(void)
@ -260,15 +287,21 @@ esp_err_t adc_digi_start(void)
ESP_LOGE(ADC_TAG, "The driver is already started");
return ESP_ERR_INVALID_STATE;
}
adc_power_acquire();
//reset flags
s_adc_digi_ctx->ringbuf_overflow_flag = 0;
s_adc_digi_ctx->driver_start_flag = 1;
//When using SARADC2 module, this task needs to be protected from WIFI
if (s_adc_digi_ctx->use_adc2) {
SAC_ADC2_LOCK_ACQUIRE();
if (s_adc_digi_ctx->use_adc1) {
SAR_ADC1_LOCK_ACQUIRE();
}
ADC_DIGI_LOCK_ACQUIRE();
if (s_adc_digi_ctx->use_adc2) {
SAR_ADC2_LOCK_ACQUIRE();
}
#if CONFIG_PM_ENABLE
// Lock APB frequency while ADC driver is in use
esp_pm_lock_acquire(s_adc_digi_ctx->pm_lock);
#endif
adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
if (s_adc_digi_ctx->use_adc1) {
@ -281,26 +314,16 @@ esp_err_t adc_digi_start(void)
}
adc_hal_init();
adc_hal_arbiter_config(&config);
adc_hal_digi_init(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config);
adc_hal_digi_init(&s_adc_digi_ctx->hal);
adc_hal_digi_controller_config(&s_adc_digi_ctx->digi_controller_config);
//create dma descriptors
adc_hal_digi_dma_multi_descriptor(&s_adc_digi_ctx->hal_dma_config, s_adc_digi_ctx->rx_dma_buf, s_adc_digi_ctx->bytes_between_intr, s_adc_digi_ctx->hal_dma_config.desc_max_num);
adc_hal_digi_set_eof_num(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config, (s_adc_digi_ctx->bytes_between_intr)/4);
//set the current descriptor pointer
s_adc_digi_ctx->hal_dma_config.cur_desc_ptr = s_adc_digi_ctx->hal_dma_config.rx_desc;
s_adc_digi_ctx->hal_dma_config.desc_cnt = 0;
//enable in suc eof intr
adc_hal_digi_ena_intr(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config, IN_SUC_EOF_BIT);
//start ADC
adc_hal_digi_start(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config);
//reset ADC and DMA
adc_hal_fifo_reset(&s_adc_digi_ctx->hal);
//start DMA
adc_hal_digi_rxdma_start(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config);
adc_hal_digi_rxdma_start(&s_adc_digi_ctx->hal, s_adc_digi_ctx->rx_dma_buf);
//start ADC
adc_hal_digi_start(&s_adc_digi_ctx->hal);
return ESP_OK;
}
@ -314,20 +337,27 @@ esp_err_t adc_digi_stop(void)
s_adc_digi_ctx->driver_start_flag = 0;
//disable the in suc eof intrrupt
adc_hal_digi_dis_intr(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config, IN_SUC_EOF_BIT);
adc_hal_digi_dis_intr(&s_adc_digi_ctx->hal, IN_SUC_EOF_BIT);
//clear the in suc eof interrupt
adc_hal_digi_clr_intr(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config, IN_SUC_EOF_BIT);
//stop DMA
adc_hal_digi_rxdma_stop(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config);
adc_hal_digi_clr_intr(&s_adc_digi_ctx->hal, IN_SUC_EOF_BIT);
//stop ADC
adc_hal_digi_stop(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config);
adc_hal_digi_stop(&s_adc_digi_ctx->hal);
//stop DMA
adc_hal_digi_rxdma_stop(&s_adc_digi_ctx->hal);
adc_hal_digi_deinit();
ADC_DIGI_LOCK_RELEASE();
//When using SARADC2 module, this task needs to be protected from WIFI
if (s_adc_digi_ctx->use_adc2) {
SAC_ADC2_LOCK_RELEASE();
#if CONFIG_PM_ENABLE
if (s_adc_digi_ctx->pm_lock) {
esp_pm_lock_release(s_adc_digi_ctx->pm_lock);
}
#endif //CONFIG_PM_ENABLE
if (s_adc_digi_ctx->use_adc1) {
SAR_ADC1_LOCK_RELEASE();
}
if (s_adc_digi_ctx->use_adc2) {
SAR_ADC2_LOCK_RELEASE();
}
adc_power_release();
return ESP_OK;
}
@ -375,23 +405,27 @@ esp_err_t adc_digi_deinitialize(void)
return ESP_ERR_INVALID_STATE;
}
if (s_adc_digi_ctx->dma_intr_hdl) {
esp_intr_free(s_adc_digi_ctx->dma_intr_hdl);
}
if(s_adc_digi_ctx->ringbuf_hdl) {
if (s_adc_digi_ctx->ringbuf_hdl) {
vRingbufferDelete(s_adc_digi_ctx->ringbuf_hdl);
s_adc_digi_ctx->ringbuf_hdl = NULL;
}
#if CONFIG_PM_ENABLE
if (s_adc_digi_ctx->pm_lock) {
esp_pm_lock_delete(s_adc_digi_ctx->pm_lock);
}
#endif //CONFIG_PM_ENABLE
free(s_adc_digi_ctx->rx_dma_buf);
free(s_adc_digi_ctx->hal_dma_config.rx_desc);
free(s_adc_digi_ctx->hal.rx_desc);
free(s_adc_digi_ctx->digi_controller_config.adc_pattern);
gdma_disconnect(s_adc_digi_ctx->rx_dma_channel);
gdma_del_channel(s_adc_digi_ctx->rx_dma_channel);
free(s_adc_digi_ctx);
s_adc_digi_ctx = NULL;
periph_module_disable(PERIPH_SARADC_MODULE);
periph_module_disable(PERIPH_GDMA_MODULE);
return ESP_OK;
}
@ -402,6 +436,38 @@ esp_err_t adc_digi_deinitialize(void)
static adc_atten_t s_atten1_single[ADC1_CHANNEL_MAX]; //Array saving attenuate of each channel of ADC1, used by single read API
static adc_atten_t s_atten2_single[ADC2_CHANNEL_MAX]; //Array saving attenuate of each channel of ADC2, used by single read API
esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio)
{
esp_err_t ret;
uint32_t channel = ADC2_CHANNEL_MAX;
if (adc_unit == ADC_UNIT_2) {
for (int i = 0; i < ADC2_CHANNEL_MAX; i++) {
if (gpio == ADC_GET_IO_NUM(ADC_NUM_2, i)) {
channel = i;
break;
}
}
if (channel == ADC2_CHANNEL_MAX) {
return ESP_ERR_INVALID_ARG;
}
}
adc_power_acquire();
if (adc_unit & ADC_UNIT_1) {
ADC_ENTER_CRITICAL();
adc_hal_vref_output(ADC_NUM_1, channel, true);
ADC_EXIT_CRITICAL()
} else if (adc_unit & ADC_UNIT_2) {
ADC_ENTER_CRITICAL();
adc_hal_vref_output(ADC_NUM_2, channel, true);
ADC_EXIT_CRITICAL()
}
ret = adc_digi_gpio_init(ADC_NUM_2, BIT(channel));
return ret;
}
esp_err_t adc1_config_width(adc_bits_width_t width_bit)
{
//On ESP32C3, the data width is always 12-bits.
@ -429,41 +495,26 @@ esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten)
int adc1_get_raw(adc1_channel_t channel)
{
int raw_out = 0;
adc_digi_config_t dig_cfg = {
.conv_limit_en = 0,
.conv_limit_num = 250,
.sample_freq_hz = SOC_ADC_SAMPLE_FREQ_THRES_HIGH,
};
ADC_DIGI_LOCK_ACQUIRE();
periph_module_enable(PERIPH_SARADC_MODULE);
adc_power_acquire();
SAR_ADC1_LOCK_ACQUIRE();
adc_atten_t atten = s_atten1_single[channel];
uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_1, channel, atten);
adc_hal_set_calibration_param(ADC_NUM_1, cal_val);
adc_hal_digi_controller_config(&dig_cfg);
ADC_REG_LOCK_ENTER();
adc_hal_set_atten(ADC_NUM_2, channel, atten);
adc_hal_convert(ADC_NUM_1, channel, &raw_out);
ADC_REG_LOCK_EXIT();
adc_hal_intr_clear(ADC_EVENT_ADC1_DONE);
SAR_ADC1_LOCK_RELEASE();
adc_hal_adc1_onetime_sample_enable(true);
adc_hal_onetime_channel(ADC_NUM_1, channel);
adc_hal_set_onetime_atten(atten);
//Trigger single read.
adc_hal_onetime_start(&dig_cfg);
while (!adc_hal_intr_get_raw(ADC_EVENT_ADC1_DONE));
adc_hal_single_read(ADC_NUM_1, &raw_out);
adc_hal_intr_clear(ADC_EVENT_ADC1_DONE);
adc_hal_adc1_onetime_sample_enable(false);
adc_hal_digi_deinit();
adc_power_release();
periph_module_disable(PERIPH_SARADC_MODULE);
ADC_DIGI_LOCK_RELEASE();
return raw_out;
}
@ -489,42 +540,26 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
}
esp_err_t ret = ESP_OK;
adc_digi_config_t dig_cfg = {
.conv_limit_en = 0,
.conv_limit_num = 250,
.sample_freq_hz = SOC_ADC_SAMPLE_FREQ_THRES_HIGH,
};
SAC_ADC2_LOCK_ACQUIRE();
ADC_DIGI_LOCK_ACQUIRE();
periph_module_enable(PERIPH_SARADC_MODULE);
adc_power_acquire();
SAR_ADC2_LOCK_ACQUIRE();
adc_atten_t atten = s_atten2_single[channel];
uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_2, channel, atten);
adc_hal_set_calibration_param(ADC_NUM_2, cal_val);
adc_hal_digi_controller_config(&dig_cfg);
ADC_REG_LOCK_ENTER();
adc_hal_set_atten(ADC_NUM_2, channel, atten);
ret = adc_hal_convert(ADC_NUM_2, channel, raw_out);
ADC_REG_LOCK_EXIT();
adc_hal_intr_clear(ADC_EVENT_ADC2_DONE);
SAR_ADC2_LOCK_RELEASE();
adc_hal_adc2_onetime_sample_enable(true);
adc_hal_onetime_channel(ADC_NUM_2, channel);
adc_hal_set_onetime_atten(atten);
//Trigger single read.
adc_hal_onetime_start(&dig_cfg);
while (!adc_hal_intr_get_raw(ADC_EVENT_ADC2_DONE));
ret = adc_hal_single_read(ADC_NUM_2, raw_out);
adc_hal_intr_clear(ADC_EVENT_ADC2_DONE);
adc_hal_adc2_onetime_sample_enable(false);
adc_hal_digi_deinit();
adc_power_release();
periph_module_disable(PERIPH_SARADC_MODULE);
ADC_DIGI_LOCK_RELEASE();
SAC_ADC2_LOCK_RELEASE();
return ret;
}
@ -551,7 +586,7 @@ esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
s_adc_digi_ctx->use_adc1 = 0;
s_adc_digi_ctx->use_adc2 = 0;
for (int i = 0; i < config->adc_pattern_len; i++) {
const adc_digi_pattern_table_t* pat = &config->adc_pattern[i];
const adc_digi_pattern_table_t *pat = &config->adc_pattern[i];
if (pat->unit == ADC_NUM_1) {
s_adc_digi_ctx->use_adc1 = 1;
@ -575,86 +610,6 @@ esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
return ESP_OK;
}
esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config)
{
if (adc_unit & ADC_UNIT_1) {
return ESP_ERR_NOT_SUPPORTED;
}
ADC_ENTER_CRITICAL();
adc_hal_arbiter_config(config);
ADC_EXIT_CRITICAL();
return ESP_OK;
}
/**
* @brief Set ADC module controller.
* There are five SAR ADC controllers:
* Two digital controller: Continuous conversion mode (DMA). High performance with multiple channel scan modes;
* Two RTC controller: Single conversion modes (Polling). For low power purpose working during deep sleep;
* the other is dedicated for Power detect (PWDET / PKDET), Only support ADC2.
*
* @note Only ADC2 support arbiter to switch controllers automatically. Access to the ADC is based on the priority of the controller.
* @note For ADC1, Controller access is mutually exclusive.
*
* @param adc_unit ADC unit.
* @param ctrl ADC controller, Refer to `adc_controller_t`.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_set_controller(adc_unit_t adc_unit, adc_controller_t ctrl)
{
adc_arbiter_t config = {0};
adc_arbiter_t cfg = ADC_ARBITER_CONFIG_DEFAULT();
if (adc_unit & ADC_UNIT_1) {
adc_hal_set_controller(ADC_NUM_1, ctrl);
}
if (adc_unit & ADC_UNIT_2) {
adc_hal_set_controller(ADC_NUM_2, ctrl);
switch (ctrl) {
case ADC2_CTRL_FORCE_PWDET:
config.pwdet_pri = 2;
config.mode = ADC_ARB_MODE_SHIELD;
adc_hal_arbiter_config(&config);
adc_hal_set_controller(ADC_NUM_2, ADC2_CTRL_PWDET);
break;
case ADC2_CTRL_FORCE_RTC:
config.rtc_pri = 2;
config.mode = ADC_ARB_MODE_SHIELD;
adc_hal_arbiter_config(&config);
adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_RTC);
break;
case ADC2_CTRL_FORCE_DIG:
config.dig_pri = 2;
config.mode = ADC_ARB_MODE_SHIELD;
adc_hal_arbiter_config(&config);
adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_DIG);
break;
default:
adc_hal_arbiter_config(&cfg);
break;
}
}
return ESP_OK;
}
/**
* @brief Reset FSM of adc digital controller.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_reset(void)
{
ADC_ENTER_CRITICAL();
adc_hal_digi_reset();
adc_hal_digi_clear_pattern_table(ADC_NUM_1);
adc_hal_digi_clear_pattern_table(ADC_NUM_2);
ADC_EXIT_CRITICAL();
return ESP_OK;
}
/*************************************/
/* Digital controller filter setting */
/*************************************/
@ -712,90 +667,6 @@ esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable)
return ESP_OK;
}
/**************************************/
/* Digital controller intr setting */
/**************************************/
esp_err_t adc_digi_intr_enable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask)
{
ADC_ENTER_CRITICAL();
if (adc_unit & ADC_UNIT_1) {
adc_hal_digi_intr_enable(ADC_NUM_1, intr_mask);
}
if (adc_unit & ADC_UNIT_2) {
adc_hal_digi_intr_enable(ADC_NUM_2, intr_mask);
}
ADC_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t adc_digi_intr_disable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask)
{
ADC_ENTER_CRITICAL();
if (adc_unit & ADC_UNIT_1) {
adc_hal_digi_intr_disable(ADC_NUM_1, intr_mask);
}
if (adc_unit & ADC_UNIT_2) {
adc_hal_digi_intr_disable(ADC_NUM_2, intr_mask);
}
ADC_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t adc_digi_intr_clear(adc_unit_t adc_unit, adc_digi_intr_t intr_mask)
{
ADC_ENTER_CRITICAL();
if (adc_unit & ADC_UNIT_1) {
adc_hal_digi_intr_clear(ADC_NUM_1, intr_mask);
}
if (adc_unit & ADC_UNIT_2) {
adc_hal_digi_intr_clear(ADC_NUM_2, intr_mask);
}
ADC_EXIT_CRITICAL();
return ESP_OK;
}
uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit)
{
uint32_t ret = 0;
ADC_ENTER_CRITICAL();
if (adc_unit & ADC_UNIT_1) {
ret = adc_hal_digi_get_intr_status(ADC_NUM_1);
}
if (adc_unit & ADC_UNIT_2) {
ret = adc_hal_digi_get_intr_status(ADC_NUM_2);
}
ADC_EXIT_CRITICAL();
return ret;
}
static bool s_isr_registered = 0;
static intr_handle_t s_adc_isr_handle = NULL;
esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags)
{
ADC_CHECK((fn != NULL), "Parameter error", ESP_ERR_INVALID_ARG);
ADC_CHECK(s_isr_registered == 0, "ADC ISR have installed, can not install again", ESP_FAIL);
esp_err_t ret = esp_intr_alloc(ETS_APB_ADC_INTR_SOURCE, intr_alloc_flags, fn, arg, &s_adc_isr_handle);
if (ret == ESP_OK) {
s_isr_registered = 1;
}
return ret;
}
esp_err_t adc_digi_isr_deregister(void)
{
esp_err_t ret = ESP_FAIL;
if (s_isr_registered) {
ret = esp_intr_free(s_adc_isr_handle);
if (ret == ESP_OK) {
s_isr_registered = 0;
}
}
return ret;
}
/*---------------------------------------------------------------
RTC controller setting
---------------------------------------------------------------*/

View File

@ -22,25 +22,6 @@ extern "C" {
/*---------------------------------------------------------------
Common setting
---------------------------------------------------------------*/
/**
* @brief Config ADC module arbiter.
* The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority,
* the low priority controller will read the invalid ADC2 data, and the validity of the data can be judged by the flag bit in the data.
*
* @note Only ADC2 support arbiter.
* @note Default priority: Wi-Fi > RTC > Digital;
* @note In normal use, there is no need to call this interface to config arbiter.
*
* @param adc_unit ADC unit.
* @param config Refer to `adc_arbiter_t`.
*
* @return
* - ESP_OK Success
* - ESP_ERR_NOT_SUPPORTED ADC unit not support arbiter.
*/
esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config);
/*************************************/
/* Digital controller filter setting */
/*************************************/
@ -114,78 +95,6 @@ esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monit
*/
esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable);
/**************************************/
/* Digital controller intr setting */
/**************************************/
/**
* @brief Enable interrupt of adc digital controller by bitmask.
*
* @param adc_unit ADC unit.
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_intr_enable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask);
/**
* @brief Disable interrupt of adc digital controller by bitmask.
*
* @param adc_unit ADC unit.
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_intr_disable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask);
/**
* @brief Clear interrupt of adc digital controller by bitmask.
*
* @param adc_unit ADC unit.
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_intr_clear(adc_unit_t adc_unit, adc_digi_intr_t intr_mask);
/**
* @brief Get interrupt status mask of adc digital controller.
*
* @param adc_unit ADC unit.
* @return
* - intr Interrupt bitmask, See ``adc_digi_intr_t``.
*/
uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit);
/**
* @brief Register ADC interrupt handler, the handler is an ISR.
* The handler will be attached to the same CPU core that this function is running on.
*
* @param fn Interrupt handler function.
* @param arg Parameter for handler function
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
*
* @return
* - ESP_OK Success
* - ESP_ERR_NOT_FOUND Can not find the interrupt that matches the flags.
* - ESP_ERR_INVALID_ARG Function pointer error.
*/
esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags);
/**
* @brief Deregister ADC interrupt handler, the handler is an ISR.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG hander error.
* - ESP_FAIL ISR not be registered.
*/
esp_err_t adc_digi_isr_deregister(void);
#ifdef __cplusplus
}
#endif

View File

@ -15,6 +15,7 @@
#include <esp_types.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "esp_log.h"
@ -26,6 +27,7 @@
#include "driver/temp_sensor.h"
#include "regi2c_ctrl.h"
#include "esp32c3/rom/ets_sys.h"
#include "esp32c3/esp_efuse_rtc_calib.h"
static const char *TAG = "tsens";
@ -58,6 +60,8 @@ static const tsens_dac_offset_t dac_offset[TSENS_DAC_MAX] = {
{TSENS_DAC_L4, 2, 10, -40, 20, 3},
};
static float s_deltaT = NAN; // unused number
esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens)
{
REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_TSENS_CLK_EN);
@ -112,6 +116,28 @@ esp_err_t temp_sensor_read_raw(uint32_t *tsens_out)
return ESP_OK;
}
static void read_delta_t_from_efuse(void)
{
uint32_t version = esp_efuse_rtc_calib_get_ver();
if (version == 1) {
// fetch calibration value for temp sensor from eFuse
s_deltaT = esp_efuse_rtc_calib_get_cal_temp(version);
} else {
// no value to fetch, use 0.
s_deltaT = 0;
}
ESP_LOGD(TAG, "s_deltaT = %f", s_deltaT);
}
static float parse_temp_sensor_raw_value(uint32_t tsens_raw, const int dac_offset)
{
if (isnan(s_deltaT)) { //suggests that the value is not initialized
read_delta_t_from_efuse();
}
float result = (TSENS_ADC_FACTOR * (float)tsens_raw - TSENS_DAC_FACTOR * dac_offset - TSENS_SYS_OFFSET) - s_deltaT / 10.0;
return result;
}
esp_err_t temp_sensor_read_celsius(float *celsius)
{
TSENS_CHECK(celsius != NULL, ESP_ERR_INVALID_ARG);
@ -123,7 +149,7 @@ esp_err_t temp_sensor_read_celsius(float *celsius)
printf("tsens_out %d\r\n", tsens_out);
TSENS_CHECK(ret == ESP_OK, ret);
const tsens_dac_offset_t *dac = &dac_offset[tsens.dac_offset];
*celsius = (TSENS_ADC_FACTOR * (float)tsens_out - TSENS_DAC_FACTOR * dac->offset - TSENS_SYS_OFFSET);
*celsius = parse_temp_sensor_raw_value(tsens_out, dac->offset);
if (*celsius < dac->range_min || *celsius > dac->range_max) {
ESP_LOGW(TAG, "Exceeding the temperature range!");
ret = ESP_ERR_INVALID_STATE;

View File

@ -89,6 +89,7 @@ esp_err_t adc_digi_deinit(void)
s_adc_digi_arbiter_lock = NULL;
}
#endif
adc_power_release();
ADC_ENTER_CRITICAL();
adc_hal_digi_deinit();
ADC_EXIT_CRITICAL();
@ -124,6 +125,8 @@ esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
}
}
/* If enable digtal controller, adc xpd should always on. */
adc_power_acquire();
ADC_ENTER_CRITICAL();
adc_hal_digi_controller_config(config);
ADC_EXIT_CRITICAL();

View File

@ -13,12 +13,12 @@
#pragma once
#include "driver/touch_sensor_common.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "driver/touch_sensor_common.h"
/**
* @brief Set touch sensor FSM start
* @note Start FSM after the touch sensor FSM mode is set.
@ -579,6 +579,22 @@ esp_err_t touch_pad_sleep_channel_reset_benchmark(void);
*/
esp_err_t touch_pad_sleep_channel_read_proximity_cnt(touch_pad_t pad_num, uint32_t *proximity_cnt);
/**
* @brief Change the operating frequency of touch pad in deep sleep state. Reducing the operating frequency can effectively reduce power consumption.
* If this function is not called, the working frequency of touch in the deep sleep state is the same as that in the wake-up state.
*
* @param sleep_cycle The touch sensor will sleep after each measurement.
* sleep_cycle decide the interval between each measurement.
* t_sleep = sleep_cycle / (RTC_SLOW_CLK frequency).
* The approximate frequency value of RTC_SLOW_CLK can be obtained using rtc_clk_slow_freq_get_hz function.
* @param meas_times The times of charge and discharge in each measure process of touch channels.
* The timer frequency is 8Mhz. Range: 0 ~ 0xffff.
* Recommended typical value: Modify this value to make the measurement time around 1ms.
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_sleep_channel_set_work_time(uint16_t sleep_cycle, uint16_t meas_times);
#ifdef __cplusplus
}
#endif

View File

@ -14,6 +14,7 @@
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include "esp_types.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
@ -61,7 +62,7 @@ static const tsens_dac_offset_t dac_offset[TSENS_DAC_MAX] = {
static SemaphoreHandle_t rtc_tsens_mux = NULL;
static float deltaT = 1000; // greater than range
static float s_deltaT = NAN; // Unused number
esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens)
{
@ -142,20 +143,20 @@ static void read_delta_t_from_efuse(void)
uint32_t version = esp_efuse_rtc_table_read_calib_version();
if (version == 1 || version == 2) {
// fetch calibration value for temp sensor from eFuse
deltaT = esp_efuse_rtc_table_get_parsed_efuse_value(RTCCALIB_IDX_TMPSENSOR, false) / 10.0;
s_deltaT = esp_efuse_rtc_table_get_parsed_efuse_value(RTCCALIB_IDX_TMPSENSOR, false) / 10.0;
} else {
// no value to fetch, use 0.
deltaT = 0;
s_deltaT = 0;
}
ESP_LOGD(TAG, "deltaT = %f\n", deltaT);
ESP_LOGD(TAG, "s_deltaT = %f\n", s_deltaT);
}
static float parse_temp_sensor_raw_value(uint32_t tsens_raw, const tsens_dac_offset_t *dac)
static float parse_temp_sensor_raw_value(uint32_t tsens_raw, const int dac_offset)
{
if (deltaT > 512) { //suggests that the value is not initialized
if (isnan(s_deltaT)) { //suggests that the value is not initialized
read_delta_t_from_efuse();
}
float result = (TSENS_ADC_FACTOR * (float)tsens_raw - TSENS_DAC_FACTOR * dac->offset - TSENS_SYS_OFFSET) - deltaT;
float result = (TSENS_ADC_FACTOR * (float)tsens_raw - TSENS_DAC_FACTOR * dac_offset - TSENS_SYS_OFFSET) - s_deltaT;
return result;
}
@ -169,7 +170,7 @@ esp_err_t temp_sensor_read_celsius(float *celsius)
ret = temp_sensor_read_raw(&tsens_out);
TSENS_CHECK(ret == ESP_OK, ret);
const tsens_dac_offset_t *dac = &dac_offset[tsens.dac_offset];
*celsius = parse_temp_sensor_raw_value(tsens_out, dac);
*celsius = parse_temp_sensor_raw_value(tsens_out, dac->offset);
if (*celsius < dac->range_min || *celsius > dac->range_max) {
ESP_LOGW(TAG, "Exceeding the temperature range!");
ret = ESP_ERR_INVALID_STATE;

View File

@ -629,3 +629,9 @@ esp_err_t touch_pad_sleep_channel_read_proximity_cnt(touch_pad_t pad_num, uint32
touch_hal_sleep_read_proximity_cnt(approach_cnt);
return ESP_OK;
}
esp_err_t touch_pad_sleep_channel_set_work_time(uint16_t sleep_cycle, uint16_t meas_times)
{
touch_hal_sleep_channel_set_work_time(sleep_cycle, meas_times);
return ESP_OK;
}

View File

@ -577,6 +577,22 @@ esp_err_t touch_pad_sleep_channel_reset_benchmark(void);
*/
esp_err_t touch_pad_sleep_channel_read_proximity_cnt(touch_pad_t pad_num, uint32_t *proximity_cnt);
/**
* @brief Change the operating frequency of touch pad in deep sleep state. Reducing the operating frequency can effectively reduce power consumption.
* If this function is not called, the working frequency of touch in the deep sleep state is the same as that in the wake-up state.
*
* @param sleep_cycle The touch sensor will sleep after each measurement.
* sleep_cycle decide the interval between each measurement.
* t_sleep = sleep_cycle / (RTC_SLOW_CLK frequency).
* The approximate frequency value of RTC_SLOW_CLK can be obtained using rtc_clk_slow_freq_get_hz function.
* @param meas_times The times of charge and discharge in each measure process of touch channels.
* The timer frequency is 8Mhz. Range: 0 ~ 0xffff.
* Recommended typical value: Modify this value to make the measurement time around 1ms.
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_sleep_channel_set_work_time(uint16_t sleep_cycle, uint16_t meas_times);
#ifdef __cplusplus
}
#endif

View File

@ -50,17 +50,30 @@ typedef struct gdma_channel_t gdma_channel_t;
typedef struct gdma_tx_channel_t gdma_tx_channel_t;
typedef struct gdma_rx_channel_t gdma_rx_channel_t;
/**
* GDMA driver consists of there object class, namely: Group, Pair and Channel.
* Channel is allocated when user calls `gdma_new_channel`, its lifecycle is maintained by user.
* Pair and Group are all lazy allocated, their life cycles are maintained by this driver.
* We use reference count to track their life cycles, i.e. the driver will free their memory only when their reference count reached to 0.
*
* We don't use an all-in-one spin lock in this driver, instead, we created different spin locks at different level.
* For platform, it has a spinlock, which is used to protect the group handle slots and reference count of each group.
* For group, it has a spinlock, which is used to protect group level stuffs, e.g. hal object, pair handle slots and reference count of each pair.
* For pair, it has a sinlock, which is used to protect pair level stuffs, e.g. interrupt handle, channel handle slots, occupy code.
*/
struct gdma_platform_t {
portMUX_TYPE spinlock; // platform level spinlock
gdma_group_t *groups[SOC_GDMA_GROUPS]; // array of GDMA group instances
int group_ref_counts[SOC_GDMA_GROUPS]; // reference count used to protect group install/uninstall
};
struct gdma_group_t {
int group_id; // Group ID, index from 0
gdma_hal_context_t hal; // HAL instance is at group level
portMUX_TYPE spinlock; // group level spinlock
int ref_count; // reference count
gdma_pair_t *pairs[SOC_GDMA_PAIRS_PER_GROUP]; // handles of GDMA pairs
gdma_pair_t *pairs[SOC_GDMA_PAIRS_PER_GROUP]; // handles of GDMA pairs
int pair_ref_counts[SOC_GDMA_PAIRS_PER_GROUP]; // reference count used to protect pair install/uninstall
};
struct gdma_pair_t {
@ -71,7 +84,6 @@ struct gdma_pair_t {
int occupy_code; // each bit indicates which channel has been occupied (an occupied channel will be skipped during channel search)
intr_handle_t intr; // Interrupt is at pair level
portMUX_TYPE spinlock; // pair level spinlock
int ref_count; // reference count
};
struct gdma_channel_t {
@ -138,9 +150,9 @@ esp_err_t gdma_new_channel(const gdma_channel_alloc_config_t *config, gdma_chann
DMA_CHECK(config->sibling_chan->direction != config->direction,
"sibling channel should have a different direction", err, ESP_ERR_INVALID_ARG);
group = pair->group;
portENTER_CRITICAL(&pair->spinlock);
pair->ref_count++; // channel obtains a reference to pair
portEXIT_CRITICAL(&pair->spinlock);
portENTER_CRITICAL(&group->spinlock);
group->pair_ref_counts[pair->pair_id]++; // channel obtains a reference to pair
portEXIT_CRITICAL(&group->spinlock);
goto search_done; // skip the search path below if user has specify a sibling channel
}
@ -152,10 +164,14 @@ esp_err_t gdma_new_channel(const gdma_channel_alloc_config_t *config, gdma_chann
portENTER_CRITICAL(&pair->spinlock);
if (!(search_code & pair->occupy_code)) { // pair has suitable position for acquired channel(s)
pair->occupy_code |= search_code;
pair->ref_count++; // channel obtains a reference to pair
search_code = 0; // exit search loop
}
portEXIT_CRITICAL(&pair->spinlock);
if (!search_code) {
portENTER_CRITICAL(&group->spinlock);
group->pair_ref_counts[j]++; // channel obtains a reference to pair
portEXIT_CRITICAL(&group->spinlock);
}
}
gdma_release_pair_handle(pair);
} // loop used to search pair
@ -404,26 +420,21 @@ err:
return ret_code;
}
static inline bool gdma_is_group_busy(gdma_group_t *group)
{
return group->ref_count;
}
static void gdma_uninstall_group(gdma_group_t *group)
{
int group_id = group->group_id;
bool do_deinitialize = false;
if (s_platform.groups[group_id] && !gdma_is_group_busy(group)) {
portENTER_CRITICAL(&s_platform.spinlock);
if (s_platform.groups[group_id] && !gdma_is_group_busy(group)) {
do_deinitialize = true;
s_platform.groups[group_id] = NULL; // deregister from platfrom
gdma_ll_enable_clock(group->hal.dev, false);
periph_module_disable(gdma_periph_signals.groups[group_id].module);
}
portEXIT_CRITICAL(&s_platform.spinlock);
portENTER_CRITICAL(&s_platform.spinlock);
s_platform.group_ref_counts[group_id]--;
if (s_platform.group_ref_counts[group_id] == 0) {
assert(s_platform.groups[group_id]);
do_deinitialize = true;
s_platform.groups[group_id] = NULL; // deregister from platfrom
gdma_ll_enable_clock(group->hal.dev, false);
periph_module_disable(gdma_periph_signals.groups[group_id].module);
}
portEXIT_CRITICAL(&s_platform.spinlock);
if (do_deinitialize) {
free(group);
@ -453,7 +464,7 @@ static gdma_group_t *gdma_acquire_group_handle(int group_id)
group = s_platform.groups[group_id];
}
// someone acquired the group handle means we have a new object that refer to this group
group->ref_count++;
s_platform.group_ref_counts[group_id]++;
portEXIT_CRITICAL(&s_platform.spinlock);
if (new_group) {
@ -468,39 +479,31 @@ out:
static void gdma_release_group_handle(gdma_group_t *group)
{
if (group) {
portENTER_CRITICAL(&group->spinlock);
group->ref_count--;
portEXIT_CRITICAL(&group->spinlock);
gdma_uninstall_group(group);
}
}
static inline bool gdma_is_pair_busy(gdma_pair_t *pair)
{
return pair->ref_count;
}
static void gdma_uninstall_pair(gdma_pair_t *pair)
{
gdma_group_t *group = pair->group;
int pair_id = pair->pair_id;
bool do_deinitialize = false;
if (group->pairs[pair_id] && !gdma_is_pair_busy(pair)) {
portENTER_CRITICAL(&group->spinlock);
if (group->pairs[pair_id] && !gdma_is_pair_busy(pair)) {
do_deinitialize = true;
group->pairs[pair_id] = NULL; // deregister from pair
group->ref_count--; // decrease reference count, because this pair won't refer to the group
if (pair->intr) {
// disable interrupt handler (but not freed, esp_intr_free is a blocking API, we can't use it in a critical section)
esp_intr_disable(pair->intr);
gdma_ll_enable_interrupt(group->hal.dev, pair->pair_id, UINT32_MAX, false); // disable all interupt events
gdma_ll_clear_interrupt_status(group->hal.dev, pair->pair_id, UINT32_MAX); // clear all pending events
}
portENTER_CRITICAL(&group->spinlock);
group->pair_ref_counts[pair_id]--;
if (group->pair_ref_counts[pair_id] == 0) {
assert(group->pairs[pair_id]);
do_deinitialize = true;
group->pairs[pair_id] = NULL; // deregister from pair
if (pair->intr) {
// disable interrupt handler (but not freed, esp_intr_free is a blocking API, we can't use it in a critical section)
esp_intr_disable(pair->intr);
gdma_ll_enable_interrupt(group->hal.dev, pair->pair_id, UINT32_MAX, false); // disable all interupt events
gdma_ll_clear_interrupt_status(group->hal.dev, pair->pair_id, UINT32_MAX); // clear all pending events
}
portEXIT_CRITICAL(&group->spinlock);
}
portEXIT_CRITICAL(&group->spinlock);
if (do_deinitialize) {
if (pair->intr) {
esp_intr_free(pair->intr); // free interrupt resource
@ -508,6 +511,7 @@ static void gdma_uninstall_pair(gdma_pair_t *pair)
}
free(pair);
ESP_LOGD(TAG, "del pair (%d,%d)", group->group_id, pair_id);
gdma_uninstall_group(group);
}
}
@ -525,7 +529,6 @@ static gdma_pair_t *gdma_acquire_pair_handle(gdma_group_t *group, int pair_id)
new_pair = true;
pair = pre_alloc_pair;
group->pairs[pair_id] = pair; // register to group
group->ref_count++; // pair obtains a reference to group
pair->group = group;
pair->pair_id = pair_id;
pair->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
@ -533,10 +536,13 @@ static gdma_pair_t *gdma_acquire_pair_handle(gdma_group_t *group, int pair_id)
pair = group->pairs[pair_id];
}
// someone acquired the pair handle means we have a new object that refer to this pair
pair->ref_count++;
group->pair_ref_counts[pair_id]++;
portEXIT_CRITICAL(&group->spinlock);
if (new_pair) {
portENTER_CRITICAL(&s_platform.spinlock);
s_platform.group_ref_counts[group->group_id]++; // pair obtains a reference to group
portEXIT_CRITICAL(&s_platform.spinlock);
ESP_LOGD(TAG, "new pair (%d,%d) at %p", group->group_id, pair->pair_id, pair);
} else {
free(pre_alloc_pair);
@ -548,9 +554,6 @@ out:
static void gdma_release_pair_handle(gdma_pair_t *pair)
{
if (pair) {
portENTER_CRITICAL(&pair->spinlock);
pair->ref_count--;
portEXIT_CRITICAL(&pair->spinlock);
gdma_uninstall_pair(pair);
}
}
@ -558,16 +561,15 @@ static void gdma_release_pair_handle(gdma_pair_t *pair)
static esp_err_t gdma_del_tx_channel(gdma_channel_t *dma_channel)
{
gdma_pair_t *pair = dma_channel->pair;
gdma_group_t *group = pair->group;
gdma_tx_channel_t *tx_chan = __containerof(dma_channel, gdma_tx_channel_t, base);
portENTER_CRITICAL(&pair->spinlock);
pair->tx_chan = NULL;
pair->ref_count--; // decrease reference count, because this channel won't refer to the pair
pair->occupy_code &= ~SEARCH_REQUEST_TX_CHANNEL;
portEXIT_CRITICAL(&pair->spinlock);
ESP_LOGD(TAG, "del tx channel (%d,%d)", pair->group->group_id, pair->pair_id);
ESP_LOGD(TAG, "del tx channel (%d,%d)", group->group_id, pair->pair_id);
free(tx_chan);
gdma_uninstall_pair(pair);
return ESP_OK;
}
@ -575,16 +577,15 @@ static esp_err_t gdma_del_tx_channel(gdma_channel_t *dma_channel)
static esp_err_t gdma_del_rx_channel(gdma_channel_t *dma_channel)
{
gdma_pair_t *pair = dma_channel->pair;
gdma_group_t *group = pair->group;
gdma_rx_channel_t *rx_chan = __containerof(dma_channel, gdma_rx_channel_t, base);
portENTER_CRITICAL(&pair->spinlock);
pair->rx_chan = NULL;
pair->ref_count--; // decrease reference count, because this channel won't refer to the pair
pair->occupy_code &= ~SEARCH_REQUEST_RX_CHANNEL;
portEXIT_CRITICAL(&pair->spinlock);
ESP_LOGD(TAG, "del rx channel (%d,%d)", pair->group->group_id, pair->pair_id);
ESP_LOGD(TAG, "del rx channel (%d,%d)", group->group_id, pair->pair_id);
free(rx_chan);
gdma_uninstall_pair(pair);
return ESP_OK;
}

View File

@ -391,7 +391,8 @@ esp_err_t gpio_config(const gpio_config_t *pGPIOConfig)
gpio_intr_disable(io_num);
}
PIN_FUNC_SELECT(io_reg, PIN_FUNC_GPIO); /*function number 2 is GPIO_FUNC for each pin */
/* By default, all the pins have to be configured as GPIO pins. */
gpio_hal_iomux_func_sel(io_reg, PIN_FUNC_GPIO);
}
io_num++;
@ -554,11 +555,16 @@ esp_err_t gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type)
esp_err_t ret = ESP_OK;
if ((intr_type == GPIO_INTR_LOW_LEVEL) || (intr_type == GPIO_INTR_HIGH_LEVEL)) {
#if SOC_RTCIO_WAKE_SUPPORTED
if (rtc_gpio_is_valid_gpio(gpio_num)) {
ret = rtc_gpio_wakeup_enable(gpio_num, intr_type);
}
#endif
portENTER_CRITICAL(&gpio_context.gpio_spinlock);
gpio_hal_wakeup_enable(gpio_context.gpio_hal, gpio_num, intr_type);
#if SOC_GPIO_SUPPORT_SLP_SWITCH && CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND
gpio_hal_sleep_sel_dis(gpio_context.gpio_hal, gpio_num);
#endif
portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
} else {
ESP_LOGE(GPIO_TAG, "GPIO wakeup only supports level mode, but edge mode set. gpio_num:%u", gpio_num);
@ -572,12 +578,16 @@ esp_err_t gpio_wakeup_disable(gpio_num_t gpio_num)
{
GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
esp_err_t ret = ESP_OK;
#if SOC_RTCIO_WAKE_SUPPORTED
if (rtc_gpio_is_valid_gpio(gpio_num)) {
ret = rtc_gpio_wakeup_disable(gpio_num);
}
#endif
portENTER_CRITICAL(&gpio_context.gpio_spinlock);
gpio_hal_wakeup_disable(gpio_context.gpio_hal, gpio_num);
#if SOC_GPIO_SUPPORT_SLP_SWITCH && CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND
gpio_hal_sleep_sel_en(gpio_context.gpio_hal, gpio_num);
#endif
portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
return ret;
}
@ -630,7 +640,9 @@ esp_err_t gpio_hold_en(gpio_num_t gpio_num)
int ret = ESP_OK;
if (rtc_gpio_is_valid_gpio(gpio_num)) {
#if SOC_RTCIO_HOLD_SUPPORTED
ret = rtc_gpio_hold_en(gpio_num);
#endif
} else if (GPIO_HOLD_MASK[gpio_num]) {
portENTER_CRITICAL(&gpio_context.gpio_spinlock);
gpio_hal_hold_en(gpio_context.gpio_hal, gpio_num);
@ -648,7 +660,9 @@ esp_err_t gpio_hold_dis(gpio_num_t gpio_num)
int ret = ESP_OK;
if (rtc_gpio_is_valid_gpio(gpio_num)) {
#if SOC_RTCIO_HOLD_SUPPORTED
ret = rtc_gpio_hold_dis(gpio_num);
#endif
}else if (GPIO_HOLD_MASK[gpio_num]) {
portENTER_CRITICAL(&gpio_context.gpio_spinlock);
gpio_hal_hold_dis(gpio_context.gpio_hal, gpio_num);
@ -678,7 +692,9 @@ void gpio_deep_sleep_hold_dis(void)
esp_err_t gpio_force_hold_all()
{
#if SOC_RTCIO_HOLD_SUPPORTED
rtc_gpio_force_hold_all();
#endif
portENTER_CRITICAL(&gpio_context.gpio_spinlock);
gpio_hal_force_hold_all(gpio_context.gpio_hal);
portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
@ -687,9 +703,11 @@ esp_err_t gpio_force_hold_all()
esp_err_t gpio_force_unhold_all()
{
#if SOC_RTCIO_HOLD_SUPPORTED
rtc_gpio_force_hold_dis_all();
#endif
portENTER_CRITICAL(&gpio_context.gpio_spinlock);
gpio_hal_force_unhold_all(gpio_context.gpio_hal);
gpio_hal_force_unhold_all();
portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
return ESP_OK;
}
@ -876,5 +894,41 @@ esp_err_t gpio_sleep_pupd_config_unapply(gpio_num_t gpio_num)
gpio_hal_sleep_pupd_config_unapply(gpio_context.gpio_hal, gpio_num);
return ESP_OK;
}
#endif // CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
#endif // SOC_GPIO_SUPPORT_SLP_SWITCH
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
esp_err_t gpio_deep_sleep_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type)
{
if (!gpio_hal_is_valid_deepsleep_wakeup_gpio(gpio_num)) {
ESP_LOGE(GPIO_TAG, "GPIO %d does not support deep sleep wakeup", gpio_num);
return ESP_ERR_INVALID_ARG;
}
if ((intr_type != GPIO_INTR_LOW_LEVEL) && (intr_type != GPIO_INTR_HIGH_LEVEL)) {
ESP_LOGE(GPIO_TAG, "GPIO wakeup only supports level mode, but edge mode set. gpio_num:%u", gpio_num);
return ESP_ERR_INVALID_ARG;
}
portENTER_CRITICAL(&gpio_context.gpio_spinlock);
gpio_hal_deepsleep_wakeup_enable(gpio_context.gpio_hal, gpio_num, intr_type);
#if SOC_GPIO_SUPPORT_SLP_SWITCH && CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND
gpio_hal_sleep_sel_dis(gpio_context.gpio_hal, gpio_num);
#endif
portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
return ESP_OK;
}
esp_err_t gpio_deep_sleep_wakeup_disable(gpio_num_t gpio_num)
{
if (!gpio_hal_is_valid_deepsleep_wakeup_gpio(gpio_num)) {
ESP_LOGE(GPIO_TAG, "GPIO %d does not support deep sleep wakeup", gpio_num);
return ESP_ERR_INVALID_ARG;
}
portENTER_CRITICAL(&gpio_context.gpio_spinlock);
gpio_hal_deepsleep_wakeup_disable(gpio_context.gpio_hal, gpio_num);
#if SOC_GPIO_SUPPORT_SLP_SWITCH && CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND
gpio_hal_sleep_sel_en(gpio_context.gpio_hal, gpio_num);
#endif
portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
return ESP_OK;
}
#endif // SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP

View File

@ -25,6 +25,7 @@
#include "esp_pm.h"
#include "soc/soc_memory_layout.h"
#include "hal/i2c_hal.h"
#include "hal/gpio_hal.h"
#include "soc/i2c_periph.h"
#include "driver/i2c.h"
#include "driver/periph_ctrl.h"
@ -831,7 +832,7 @@ esp_err_t i2c_set_pin(i2c_port_t i2c_num, int sda_io_num, int scl_io_num, bool s
scl_in_sig = i2c_periph_signal[i2c_num].scl_in_sig;
if (sda_io_num >= 0) {
gpio_set_level(sda_io_num, I2C_IO_INIT_LEVEL);
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[sda_io_num], PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[sda_io_num], PIN_FUNC_GPIO);
gpio_set_direction(sda_io_num, GPIO_MODE_INPUT_OUTPUT_OD);
if (sda_pullup_en == GPIO_PULLUP_ENABLE) {
@ -844,7 +845,7 @@ esp_err_t i2c_set_pin(i2c_port_t i2c_num, int sda_io_num, int scl_io_num, bool s
}
if (scl_io_num >= 0) {
gpio_set_level(scl_io_num, I2C_IO_INIT_LEVEL);
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[scl_io_num], PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[scl_io_num], PIN_FUNC_GPIO);
gpio_set_direction(scl_io_num, GPIO_MODE_INPUT_OUTPUT_OD);
esp_rom_gpio_connect_out_signal(scl_io_num, scl_out_sig, 0, 0);
esp_rom_gpio_connect_in_signal(scl_io_num, scl_in_sig, 0);

View File

@ -24,6 +24,7 @@
#include "soc/lldesc.h"
#include "driver/gpio.h"
#include "driver/i2s.h"
#include "hal/gpio_hal.h"
#if SOC_I2S_SUPPORTS_ADC_DAC
#include "driver/dac.h"
#include "hal/i2s_hal.h"
@ -118,7 +119,7 @@ static inline void gpio_matrix_out_check(int gpio, uint32_t signal_idx, bool out
{
//if pin = -1, do not need to configure
if (gpio != -1) {
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO);
gpio_set_direction(gpio, GPIO_MODE_OUTPUT);
esp_rom_gpio_connect_out_signal(gpio, signal_idx, out_inv, oen_inv);
}
@ -127,7 +128,7 @@ static inline void gpio_matrix_out_check(int gpio, uint32_t signal_idx, bool out
static inline void gpio_matrix_in_check(int gpio, uint32_t signal_idx, bool inv)
{
if (gpio != -1) {
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO);
//Set direction, for some GPIOs, the input function are not enabled as default.
gpio_set_direction(gpio, GPIO_MODE_INPUT);
esp_rom_gpio_connect_in_signal(gpio, signal_idx, inv);

View File

@ -60,7 +60,7 @@ typedef enum {
ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO1 */
ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO2 */
ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO3 */
ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO34 */
ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO4 */
ADC1_CHANNEL_MAX,
} adc1_channel_t;
#endif // CONFIG_IDF_TARGET_*
@ -137,9 +137,8 @@ typedef enum {
typedef struct adc_digi_init_config_s {
uint32_t max_store_buf_size; ///< Max length of the converted data that driver can store before they are processed. When this length is reached, driver will dump out all the old data and start to store them again.
uint32_t conv_num_each_intr; ///< Bytes of data that can be converted in 1 interrupt.
uint32_t dma_chan; ///< DMA channel.
uint16_t adc1_chan_mask; ///< Channel list of ADC1 to be initialized.
uint16_t adc2_chan_mask; ///< Channel list of ADC2 to be initialized.
uint32_t adc1_chan_mask; ///< Channel list of ADC1 to be initialized.
uint32_t adc2_chan_mask; ///< Channel list of ADC2 to be initialized.
} adc_digi_init_config_t;
#endif
@ -176,6 +175,7 @@ void adc_power_acquire(void);
*/
void adc_power_release(void);
#if !CONFIG_IDF_TARGET_ESP32C3
/**
* @brief Initialize ADC pad
* @param adc_unit ADC unit index
@ -185,11 +185,11 @@ void adc_power_release(void);
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t adc_gpio_init(adc_unit_t adc_unit, adc_channel_t channel);
#endif //#if !CONFIG_IDF_TARGET_ESP32C3
/*---------------------------------------------------------------
RTC controller setting
ADC Single Read Setting
---------------------------------------------------------------*/
/**
* @brief Get the GPIO number of a specific ADC1 channel.
*
@ -284,6 +284,7 @@ esp_err_t adc1_config_width(adc_bits_width_t width_bit);
*/
int adc1_get_raw(adc1_channel_t channel);
#if !CONFIG_IDF_TARGET_ESP32C3
/**
* @brief Set ADC data invert
* @param adc_unit ADC unit index
@ -324,6 +325,7 @@ esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t width_bit);
* to be called to configure ADC1 channels, before ADC1 is used by the ULP.
*/
void adc1_ulp_enable(void);
#endif //#if !CONFIG_IDF_TARGET_ESP32C3
/**
* @brief Get the GPIO number of a specific ADC2 channel.
@ -450,6 +452,7 @@ esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio);
* - ESP_ERR_INVALID_ARG: Unsupported GPIO
*/
esp_err_t adc2_vref_to_gpio(gpio_num_t gpio) __attribute__((deprecated));
/*---------------------------------------------------------------
Digital controller setting
---------------------------------------------------------------*/
@ -490,7 +493,7 @@ esp_err_t adc_digi_controller_config(const adc_digi_config_t *config);
/**
* @brief Initialize the Digital ADC.
*
* @param init_config Pointer to Digital ADC initilisation config. Refer to ``adc_digi_init_config_t``.
* @param init_config Pointer to Digital ADC initilization config. Refer to ``adc_digi_init_config_t``.
*
* @return
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.

View File

@ -516,6 +516,38 @@ esp_err_t gpio_sleep_pupd_config_unapply(gpio_num_t gpio_num);
#endif
#endif
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
#define GPIO_IS_DEEP_SLEEP_WAKEUP_VALID_GPIO(gpio_num) ((gpio_num & ~SOC_GPIO_DEEP_SLEEP_WAKEUP_VALID_GPIO_MASK) == 0)
/**
* @brief Enable GPIO deep-sleep wake-up function.
*
* @param gpio_num GPIO number.
*
* @param intr_type GPIO wake-up type. Only GPIO_INTR_LOW_LEVEL or GPIO_INTR_HIGH_LEVEL can be used.
*
* @note Called by the SDK. User shouldn't call this directly in the APP.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t gpio_deep_sleep_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type);
/**
* @brief Disable GPIO deep-sleep wake-up function.
*
* @param gpio_num GPIO number
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t gpio_deep_sleep_wakeup_disable(gpio_num_t gpio_num);
#endif
#ifdef __cplusplus
}
#endif

View File

@ -28,6 +28,12 @@ extern "C" {
/// Handle representing an SD SPI device
typedef int sdspi_dev_handle_t;
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
#define SDSPI_DEFAULT_HOST HSPI_HOST
#else
#define SDSPI_DEFAULT_HOST SPI2_HOST
#endif
/**
* @brief Default sdmmc_host_t structure initializer for SD over SPI driver
*
@ -37,7 +43,7 @@ typedef int sdspi_dev_handle_t;
*/
#define SDSPI_HOST_DEFAULT() {\
.flags = SDMMC_HOST_FLAG_SPI | SDMMC_HOST_FLAG_DEINIT_ARG, \
.slot = HSPI_HOST, \
.slot = SDSPI_DEFAULT_HOST, \
.max_freq_khz = SDMMC_FREQ_DEFAULT, \
.io_voltage = 3.3f, \
.init = &sdspi_host_init, \
@ -71,7 +77,7 @@ typedef struct {
* Macro defining default configuration of SD SPI device.
*/
#define SDSPI_DEVICE_CONFIG_DEFAULT() {\
.host_id = HSPI_HOST, \
.host_id = SDSPI_DEFAULT_HOST, \
.gpio_cs = GPIO_NUM_13, \
.gpio_cd = SDSPI_SLOT_NO_CD, \
.gpio_wp = SDSPI_SLOT_NO_WP, \
@ -228,7 +234,7 @@ typedef struct {
*
* @note The SDIO over sdspi needs an extra interrupt line. Call ``gpio_install_isr_service()`` before this function.
*
* @param slot SPI controller to use (HSPI_HOST or VSPI_HOST)
* @param slot SPI controller to use (SPI2_HOST or SPI3_HOST)
* @param slot_config pointer to slot configuration structure
* @deprecated Use `sdspi_host_init_device` instead.

View File

@ -72,6 +72,24 @@ extern "C"
#define SPICOMMON_BUSFLAG_NATIVE_PINS SPICOMMON_BUSFLAG_IOMUX_PINS
/**
* @brief SPI DMA channels
*/
typedef enum {
SPI_DMA_DISABLED = 0, ///< Do not enable DMA for SPI
#if CONFIG_IDF_TARGET_ESP32
SPI_DMA_CH1 = 1, ///< Enable DMA, select DMA Channel 1
SPI_DMA_CH2 = 2, ///< Enable DMA, select DMA Channel 2
#endif
SPI_DMA_CH_AUTO = 3, ///< Enable DMA, channel is automatically selected by driver
} spi_common_dma_t;
#if __cplusplus
/* Needed for C++ backwards compatibility with earlier ESP-IDF where this argument is a bare 'int'. Can be removed in ESP-IDF 5 */
typedef int spi_dma_chan_t;
#else
typedef spi_common_dma_t spi_dma_chan_t;
#endif
/**
* @brief This is a configuration structure for a SPI bus.
@ -101,15 +119,14 @@ typedef struct {
/**
* @brief Initialize a SPI bus
*
* @warning For now, only supports HSPI and VSPI.
* @warning SPI0/1 is not supported
*
* @param host_id SPI peripheral that controls this bus
* @param bus_config Pointer to a spi_bus_config_t struct specifying how the host should be initialized
* @param dma_chan Either channel 1 or 2, or 0 in the case when no DMA is required. Selecting a DMA channel
* for a SPI bus allows transfers on the bus to have sizes only limited by the amount of
* internal memory. Selecting no DMA channel (by passing the value 0) limits the amount of
* bytes transfered to a maximum of 64. Set to 0 if only the SPI flash uses
* this bus.
* @param host_id SPI peripheral that controls this bus
* @param bus_config Pointer to a spi_bus_config_t struct specifying how the host should be initialized
* @param dma_chan - Selecting a DMA channel for an SPI bus allows transactions on the bus with size only limited by the amount of internal memory.
* - Selecting SPI_DMA_DISABLED limits the size of transactions.
* - Set to SPI_DMA_DISABLED if only the SPI flash uses this bus.
* - Set to SPI_DMA_CH_AUTO to let the driver to allocate the DMA channel.
*
* @warning If a DMA channel is selected, any transmit and receive buffer used should be allocated in
* DMA-capable memory.
@ -121,10 +138,11 @@ typedef struct {
* @return
* - ESP_ERR_INVALID_ARG if configuration is invalid
* - ESP_ERR_INVALID_STATE if host already is in use
* - ESP_ERR_NOT_FOUND if there is no available DMA channel
* - ESP_ERR_NO_MEM if out of memory
* - ESP_OK on success
*/
esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *bus_config, int dma_chan);
esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *bus_config, spi_dma_chan_t dma_chan);
/**
* @brief Free a SPI bus

View File

@ -65,7 +65,9 @@ typedef struct {
spi_bus_config_t bus_cfg; ///< Config used to initialize the bus
uint32_t flags; ///< Flags (attributes) of the bus
int max_transfer_sz; ///< Maximum length of bytes available to send
int dma_chan; ///< DMA channel used
bool dma_enabled; ///< To enable DMA or not
int tx_dma_chan; ///< TX DMA channel, on ESP32 and ESP32S2, tx_dma_chan and rx_dma_chan are same
int rx_dma_chan; ///< RX DMA channel, on ESP32 and ESP32S2, tx_dma_chan and rx_dma_chan are same
int dma_desc_num; ///< DMA descriptor number of dmadesc_tx or dmadesc_rx.
lldesc_t *dmadesc_tx; ///< DMA descriptor array for TX
lldesc_t *dmadesc_rx; ///< DMA descriptor array for RX
@ -116,47 +118,29 @@ bool spicommon_periph_in_use(spi_host_device_t host);
bool spicommon_periph_free(spi_host_device_t host);
/**
* @brief Try to claim a SPI DMA channel
* @brief Alloc DMA for SPI Slave
*
* Call this if your driver wants to use SPI with a DMA channnel.
* @param host_id SPI host ID
* @param dma_chan DMA channel to be used
* @param[out] out_actual_tx_dma_chan Actual TX DMA channel (if you choose to assign a specific DMA channel, this will be the channel you assigned before)
* @param[out] out_actual_rx_dma_chan Actual RX DMA channel (if you choose to assign a specific DMA channel, this will be the channel you assigned before)
*
* @param dma_chan channel to claim
*
* @note This public API is deprecated.
*
* @return True if success; false otherwise.
* @return
* - ESP_OK: On success
* - ESP_ERR_NO_MEM: No enough memory
* - ESP_ERR_NOT_FOUND: There is no available DMA channel
*/
bool spicommon_dma_chan_claim(int dma_chan);
esp_err_t spicommon_slave_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan);
/**
* @brief Check whether the spi DMA channel is in use.
* @brief Free DMA for SPI Slave
*
* @param dma_chan DMA channel to check.
* @param host_id SPI host ID
*
* @note This public API is deprecated.
*
* @return True if in use, otherwise false.
* @return
* - ESP_OK: On success
*/
bool spicommon_dma_chan_in_use(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
*
* @note This public API is deprecated.
*
* @return True if success; false otherwise.
*/
bool spicommon_dma_chan_free(int dma_chan);
/**
* @brief Connect SPI and DMA peripherals
*
* @param host SPI peripheral
* @param dma_chan DMA channel
*/
void spicommon_connect_spi_and_dma(spi_host_device_t host, int dma_chan);
esp_err_t spicommon_slave_free_dma(spi_host_device_t host_id);
/**
* @brief Connect a SPI peripheral to GPIO pins
@ -170,7 +154,6 @@ void spicommon_connect_spi_and_dma(spi_host_device_t host, int dma_chan);
*
* @param host SPI peripheral to be routed
* @param bus_config Pointer to a spi_bus_config struct detailing the GPIO pins
* @param dma_chan DMA-channel (1 or 2) to use, or 0 for no DMA.
* @param flags Combination of SPICOMMON_BUSFLAG_* flags, set to ensure the pins set are capable with some functions:
* - ``SPICOMMON_BUSFLAG_MASTER``: Initialize I/O in master mode
* - ``SPICOMMON_BUSFLAG_SLAVE``: Initialize I/O in slave mode
@ -192,7 +175,7 @@ void spicommon_connect_spi_and_dma(spi_host_device_t host, int dma_chan);
* - ESP_ERR_INVALID_ARG if parameter is invalid
* - ESP_OK on success
*/
esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_config_t *bus_config, int dma_chan, uint32_t flags, uint32_t *flags_o);
esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_config_t *bus_config, uint32_t flags, uint32_t *flags_o);
/**
* @brief Free the IO used by a SPI peripheral

View File

@ -88,14 +88,15 @@ struct spi_slave_transaction_t {
/**
* @brief Initialize a SPI bus as a slave interface
*
* @warning For now, only supports HSPI and VSPI.
* @warning SPI0/1 is not supported
*
* @param host SPI peripheral to use as a SPI slave interface
* @param bus_config Pointer to a spi_bus_config_t struct specifying how the host should be initialized
* @param slave_config Pointer to a spi_slave_interface_config_t struct specifying the details for the slave interface
* @param dma_chan Either 1 or 2. A SPI bus used by this driver must have a DMA channel associated with
* it. The SPI hardware has two DMA channels to share. This parameter indicates which
* one to use.
* @param host SPI peripheral to use as a SPI slave interface
* @param bus_config Pointer to a spi_bus_config_t struct specifying how the host should be initialized
* @param slave_config Pointer to a spi_slave_interface_config_t struct specifying the details for the slave interface
* @param dma_chan - Selecting a DMA channel for an SPI bus allows transactions on the bus with size only limited by the amount of internal memory.
* - Selecting SPI_DMA_DISABLED limits the size of transactions.
* - Set to SPI_DMA_DISABLED if only the SPI flash uses this bus.
* - Set to SPI_DMA_CH_AUTO to let the driver to allocate the DMA channel.
*
* @warning If a DMA channel is selected, any transmit and receive buffer used should be allocated in
* DMA-capable memory.
@ -107,10 +108,11 @@ struct spi_slave_transaction_t {
* @return
* - ESP_ERR_INVALID_ARG if configuration is invalid
* - ESP_ERR_INVALID_STATE if host already is in use
* - ESP_ERR_NOT_FOUND if there is no available DMA channel
* - ESP_ERR_NO_MEM if out of memory
* - ESP_OK on success
*/
esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *bus_config, const spi_slave_interface_config_t *slave_config, int dma_chan);
esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *bus_config, const spi_slave_interface_config_t *slave_config, spi_dma_chan_t dma_chan);
/**
* @brief Free a SPI bus claimed as a SPI slave interface

View File

@ -86,7 +86,7 @@ typedef struct {
uint32_t address_bits; ///< address field bits, multiples of 8 and at least 8.
uint32_t dummy_bits; ///< dummy field bits, multiples of 8 and at least 8.
uint32_t queue_size; ///< Transaction queue size. This sets how many transactions can be 'in the air' (queued using spi_slave_hd_queue_trans but not yet finished using spi_slave_hd_get_trans_result) at the same time
uint32_t dma_chan; ///< DMA channel used
spi_dma_chan_t dma_chan; ///< DMA channel to used.
spi_slave_hd_callback_config_t cb_config; ///< Callback configuration
} spi_slave_hd_slot_config_t;
@ -97,10 +97,11 @@ typedef struct {
* @param bus_config Bus configuration for the bus used
* @param config Configuration for the SPI Slave HD driver
* @return
* - ESP_OK: on success
* - ESP_ERR_INVALID_ARG: invalid argument given
* - ESP_OK: on success
* - ESP_ERR_INVALID_ARG: invalid argument given
* - ESP_ERR_INVALID_STATE: function called in invalid state, may be some resources are already in use
* - ESP_ERR_NO_MEM: memory allocation failed
* - ESP_ERR_NOT_FOUND if there is no available DMA channel
* - ESP_ERR_NO_MEM: memory allocation failed
* - or other return value from `esp_intr_alloc`
*/
esp_err_t spi_slave_hd_init(spi_host_device_t host_id, const spi_bus_config_t *bus_config,

View File

@ -21,6 +21,7 @@
#include "soc/rtc.h"
#include "soc/soc_caps.h"
#include "hal/ledc_hal.h"
#include "hal/gpio_hal.h"
#include "driver/ledc.h"
#include "esp_rom_gpio.h"
#include "esp_rom_sys.h"
@ -355,7 +356,7 @@ esp_err_t ledc_set_pin(int gpio_num, ledc_mode_t speed_mode, ledc_channel_t ledc
LEDC_ARG_CHECK(ledc_channel < LEDC_CHANNEL_MAX, "ledc_channel");
LEDC_ARG_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "gpio_num");
LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode");
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO);
gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT);
esp_rom_gpio_connect_out_signal(gpio_num, ledc_periph_signal[speed_mode].sig_out0_idx + ledc_channel, 0, 0);
return ESP_OK;
@ -402,7 +403,7 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t* ledc_conf)
ledc_channel, gpio_num, duty, timer_select
);
/*set LEDC signal in gpio matrix*/
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO);
gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT);
esp_rom_gpio_connect_out_signal(gpio_num, ledc_periph_signal[speed_mode].sig_out0_idx + ledc_channel, 0, 0);

View File

@ -24,6 +24,7 @@
#include "driver/periph_ctrl.h"
#include "sdkconfig.h"
#include "hal/mcpwm_hal.h"
#include "hal/gpio_hal.h"
#include "esp_rom_gpio.h"
typedef struct {
@ -109,7 +110,7 @@ esp_err_t mcpwm_gpio_init(mcpwm_unit_t mcpwm_num, mcpwm_io_signals_t io_signal,
MCPWM_CHECK((GPIO_IS_VALID_GPIO(gpio_num)), MCPWM_GPIO_ERROR, ESP_ERR_INVALID_ARG);
periph_module_enable(PERIPH_PWM0_MODULE + mcpwm_num);
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO);
bool mcpwm_gpio_sig = (io_signal <= MCPWM2B);
if (mcpwm_num == MCPWM_UNIT_0) {
if (mcpwm_gpio_sig) {

View File

@ -19,6 +19,7 @@
#include "driver/periph_ctrl.h"
#include "driver/pcnt.h"
#include "hal/pcnt_hal.h"
#include "hal/gpio_hal.h"
#include "esp_rom_gpio.h"
#define PCNT_CHANNEL_ERR_STR "PCNT CHANNEL ERROR"
@ -85,14 +86,14 @@ static inline esp_err_t _pcnt_set_pin(pcnt_port_t pcnt_port, pcnt_unit_t unit, p
PCNT_CHECK(GPIO_IS_VALID_GPIO(ctrl_io) || ctrl_io < 0, PCNT_GPIO_ERR_STR, ESP_ERR_INVALID_ARG);
if (pulse_io >= 0) {
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[pulse_io], PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[pulse_io], PIN_FUNC_GPIO);
gpio_set_direction(pulse_io, GPIO_MODE_INPUT);
gpio_set_pull_mode(pulse_io, GPIO_PULLUP_ONLY);
esp_rom_gpio_connect_in_signal(pulse_io, pcnt_periph_signals.units[unit].channels[channel].pulse_sig, 0);
}
if (ctrl_io >= 0) {
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[ctrl_io], PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[ctrl_io], PIN_FUNC_GPIO);
gpio_set_direction(ctrl_io, GPIO_MODE_INPUT);
gpio_set_pull_mode(ctrl_io, GPIO_PULLUP_ONLY);
esp_rom_gpio_connect_in_signal(ctrl_io, pcnt_periph_signals.units[unit].channels[channel].control_sig, 0);

View File

@ -30,6 +30,7 @@
#include "soc/rtc.h"
#include "hal/rmt_hal.h"
#include "hal/rmt_ll.h"
#include "hal/gpio_hal.h"
#include "esp_rom_gpio.h"
#define RMT_CHANNEL_ERROR_STR "RMT CHANNEL ERR"
@ -534,7 +535,7 @@ esp_err_t rmt_set_pin(rmt_channel_t channel, rmt_mode_t mode, gpio_num_t gpio_nu
(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num) && (mode == RMT_MODE_TX))),
RMT_GPIO_ERROR_STR, ESP_ERR_INVALID_ARG);
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO);
if (mode == RMT_MODE_TX) {
RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT);

View File

@ -21,7 +21,7 @@
#include "driver/rtc_io.h"
#include "hal/rtc_io_hal.h"
static const char *RTCIO_TAG = "RTCIO";
static const char __attribute__((__unused__)) *RTCIO_TAG = "RTCIO";
#define RTCIO_CHECK(a, str, ret_val) ({ \
if (!(a)) { \
@ -164,29 +164,19 @@ esp_err_t rtc_gpio_pulldown_dis(gpio_num_t gpio_num)
esp_err_t rtc_gpio_hold_en(gpio_num_t gpio_num)
{
#ifdef CONFIG_IDF_TARGET_ESP32C3 // should use HAL here, TODO ESP32-C3 IDF-2511
RTCIO_CHECK(gpio_num <= GPIO_NUM_5, "RTCIO number error", ESP_ERR_INVALID_ARG);
REG_SET_BIT(RTC_CNTL_PAD_HOLD_REG, BIT(gpio_num));
#else
RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG);
RTCIO_ENTER_CRITICAL();
rtcio_hal_hold_enable(rtc_io_number_get(gpio_num));
RTCIO_EXIT_CRITICAL();
#endif
return ESP_OK;
}
esp_err_t rtc_gpio_hold_dis(gpio_num_t gpio_num)
{
#ifdef CONFIG_IDF_TARGET_ESP32C3 // should use HAL here, TODO ESP32-C3 IDF-2511
RTCIO_CHECK(gpio_num <= GPIO_NUM_5, "RTCIO number error", ESP_ERR_INVALID_ARG);
REG_CLR_BIT(RTC_CNTL_PAD_HOLD_REG, BIT(gpio_num));
#else
RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG);
RTCIO_ENTER_CRITICAL();
rtcio_hal_hold_disable(rtc_io_number_get(gpio_num));
RTCIO_EXIT_CRITICAL();
#endif
return ESP_OK;
}
@ -224,16 +214,6 @@ esp_err_t rtc_gpio_force_hold_dis_all(void)
esp_err_t rtc_gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type)
{
#ifdef CONFIG_IDF_TARGET_ESP32C3 // should use HAL here, TODO ESP32-C3 IDF-2511
RTCIO_CHECK(gpio_num <= GPIO_NUM_5, "RTCIO number error", ESP_ERR_INVALID_ARG);
REG_SET_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_PIN0_WAKEUP_ENABLE_M >> gpio_num);
uint32_t reg = REG_READ(RTC_CNTL_GPIO_WAKEUP_REG);
reg &= (~(RTC_CNTL_GPIO_PIN0_INT_TYPE_V << (RTC_CNTL_GPIO_PIN0_INT_TYPE_S - gpio_num * 3)));
reg |= (intr_type << (RTC_CNTL_GPIO_PIN0_INT_TYPE_S - gpio_num * 3));
REG_WRITE(RTC_CNTL_GPIO_WAKEUP_REG, reg);
ESP_LOGD(RTCIO_TAG, "gpio wake up 0x%08x", REG_READ(RTC_CNTL_GPIO_WAKEUP_REG));
#else
RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG);
if (intr_type == GPIO_INTR_POSEDGE || intr_type == GPIO_INTR_NEGEDGE || intr_type == GPIO_INTR_ANYEDGE) {
return ESP_ERR_INVALID_ARG; // Dont support this mode.
@ -241,21 +221,15 @@ esp_err_t rtc_gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type)
RTCIO_ENTER_CRITICAL();
rtcio_hal_wakeup_enable(rtc_io_number_get(gpio_num), intr_type);
RTCIO_EXIT_CRITICAL();
#endif // CONFIG_IDF_TARGET_ESP32C3
return ESP_OK;
}
esp_err_t rtc_gpio_wakeup_disable(gpio_num_t gpio_num)
{
#ifdef CONFIG_IDF_TARGET_ESP32C3 // should use HAL here, TODO ESP32-C3 IDF-2511
RTCIO_CHECK(gpio_num <= GPIO_NUM_5, "RTCIO number error", ESP_ERR_INVALID_ARG);
REG_CLR_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_PIN0_WAKEUP_ENABLE_M >> gpio_num);
#else
RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG);
RTCIO_ENTER_CRITICAL();
rtcio_hal_wakeup_disable(rtc_io_number_get(gpio_num));
RTCIO_EXIT_CRITICAL();
#endif
return ESP_OK;
}

View File

@ -98,6 +98,7 @@ The driver of FIFOs works as below:
#include "driver/periph_ctrl.h"
#include "driver/gpio.h"
#include "hal/sdio_slave_hal.h"
#include "hal/gpio_hal.h"
#define SDIO_SLAVE_CHECK(res, str, ret_val) do { if(!(res)){\
@ -280,7 +281,7 @@ static void configure_pin(int pin, uint32_t func, bool pullup)
assert(reg != UINT32_MAX);
PIN_INPUT_ENABLE(reg);
PIN_FUNC_SELECT(reg, sdmmc_func);
gpio_hal_iomux_func_sel(reg, sdmmc_func);
PIN_SET_DRV(reg, drive_strength);
gpio_pulldown_dis(pin);
if (pullup) {
@ -322,7 +323,7 @@ static void recover_pin(int pin, int sdio_func)
int func = REG_GET_FIELD(reg, MCU_SEL);
if (func == sdio_func) {
gpio_set_direction(pin, GPIO_MODE_INPUT);
PIN_FUNC_SELECT(reg, PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(reg, PIN_FUNC_GPIO);
}
}

View File

@ -29,6 +29,7 @@
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "soc/sdmmc_periph.h"
#include "hal/gpio_hal.h"
#define SDMMC_EVENT_QUEUE_LENGTH 32
@ -303,7 +304,7 @@ static void configure_pin(int pin)
uint32_t reg = GPIO_PIN_MUX_REG[pin];
assert(reg != UINT32_MAX);
PIN_INPUT_ENABLE(reg);
PIN_FUNC_SELECT(reg, sdmmc_func);
gpio_hal_iomux_func_sel(reg, sdmmc_func);
PIN_SET_DRV(reg, drive_strength);
}

View File

@ -17,6 +17,7 @@
#include "driver/sigmadelta.h"
#include "esp_heap_caps.h"
#include "hal/sigmadelta_hal.h"
#include "hal/gpio_hal.h"
#include "esp_rom_gpio.h"
static const char *TAG = "sigma-delta";
@ -57,7 +58,7 @@ static inline esp_err_t _sigmadelta_set_pin(sigmadelta_port_t sigmadelta_port, s
{
SIGMADELTA_OBJ_CHECK(sigmadelta_port);
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO);
gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT);
esp_rom_gpio_connect_out_signal(gpio_num, sigma_delta_periph_signals.channels[channel].sd_sig, 0, 0);
return ESP_OK;

View File

@ -30,22 +30,13 @@
#include "driver/spi_common_internal.h"
#include "stdatomic.h"
#include "hal/spi_hal.h"
#include "hal/gpio_hal.h"
#include "esp_rom_gpio.h"
#if CONFIG_IDF_TARGET_ESP32
#include "soc/dport_reg.h"
#endif
//This GDMA related part will be introduced by GDMA dedicated APIs in the future. Here we temporarily use macros.
#if SOC_GDMA_SUPPORTED
#include "hal/gdma_ll.h"
#include "soc/gdma_channel.h"
#include "soc/spi_caps.h"
#define spi_dma_set_rx_channel_priority(gdma_chan, priority) gdma_ll_rx_set_priority(&GDMA, gdma_chan, priority);
#define spi_dma_set_tx_channel_priority(gdma_chan, priority) gdma_ll_tx_set_priority(&GDMA, gdma_chan, priority);
#define spi_dma_connect_rx_channel_to_periph(gdma_chan, periph_id) gdma_ll_rx_connect_to_periph(&GDMA, gdma_chan, periph_id);
#define spi_dma_connect_tx_channel_to_periph(gdma_chan, periph_id) gdma_ll_tx_connect_to_periph(&GDMA, gdma_chan, periph_id);
#include "esp_private/gdma.h"
#endif
static const char *SPI_TAG = "spi";
@ -63,44 +54,61 @@ static const char *SPI_TAG = "spi";
SPI_CHECK(GPIO_IS_VALID_GPIO(pin_num), pin_name" not valid", ESP_ERR_INVALID_ARG); \
}
typedef struct spi_device_t spi_device_t;
#define SPI_MAIN_BUS_DEFAULT() { \
.host_id = 0, \
.bus_attr = { \
.tx_dma_chan = 0, \
.rx_dma_chan = 0, \
.max_transfer_sz = SOC_SPI_MAXIMUM_BUFFER_SIZE, \
.dma_desc_num= 0, \
}, \
}
#define FUNC_GPIO PIN_FUNC_GPIO
#define DMA_CHANNEL_ENABLED(dma_chan) (BIT(dma_chan-1))
typedef struct {
int host_id;
spi_destroy_func_t destroy_func;
void* destroy_arg;
spi_bus_attr_t bus_attr;
#if SOC_GDMA_SUPPORTED
gdma_channel_handle_t tx_channel;
gdma_channel_handle_t rx_channel;
#endif
} spicommon_bus_context_t;
#define MAIN_BUS_DEFAULT() { \
.host_id = 0, \
.bus_attr = { \
.dma_chan = 0, \
.max_transfer_sz = SOC_SPI_MAXIMUM_BUFFER_SIZE, \
.dma_desc_num= 0, \
}, \
}
//Periph 1 is 'claimed' by SPI flash code.
static atomic_bool spi_periph_claimed[SOC_SPI_PERIPH_NUM] = { ATOMIC_VAR_INIT(true), ATOMIC_VAR_INIT(false), ATOMIC_VAR_INIT(false),
#if SOC_SPI_PERIPH_NUM >= 4
ATOMIC_VAR_INIT(false),
static atomic_bool spi_periph_claimed[SOC_SPI_PERIPH_NUM] = { ATOMIC_VAR_INIT(true), ATOMIC_VAR_INIT(false),
#if (SOC_SPI_PERIPH_NUM >= 3)
ATOMIC_VAR_INIT(false),
#endif
#if (SOC_SPI_PERIPH_NUM >= 4)
ATOMIC_VAR_INIT(false),
#endif
};
static const char* spi_claiming_func[3] = {NULL, NULL, NULL};
static uint8_t spi_dma_chan_enabled = 0;
static portMUX_TYPE spi_dma_spinlock = portMUX_INITIALIZER_UNLOCKED;
static spicommon_bus_context_t s_mainbus = MAIN_BUS_DEFAULT();
static const char* spi_claiming_func[3] = {NULL, NULL, NULL};
static spicommon_bus_context_t s_mainbus = SPI_MAIN_BUS_DEFAULT();
static spicommon_bus_context_t* bus_ctx[SOC_SPI_PERIPH_NUM] = {&s_mainbus};
#if !SOC_GDMA_SUPPORTED
//Each bit stands for 1 dma channel, BIT(0) should be used for SPI1
static uint8_t spi_dma_chan_enabled = 0;
static portMUX_TYPE spi_dma_spinlock = portMUX_INITIALIZER_UNLOCKED;
#endif //#if !SOC_GDMA_SUPPORTED
static inline bool is_valid_host(spi_host_device_t host)
{
#if (SOC_SPI_PERIPH_NUM == 2)
return host >= SPI1_HOST && host <= SPI2_HOST;
#elif (SOC_SPI_PERIPH_NUM == 3)
return host >= SPI1_HOST && host <= SPI3_HOST;
#endif
}
//----------------------------------------------------------alloc spi periph-------------------------------------------------------//
//Returns true if this peripheral is successfully claimed, false if otherwise.
bool spicommon_periph_claim(spi_host_device_t host, const char* source)
{
@ -139,90 +147,217 @@ int spicommon_irqdma_source_for_host(spi_host_device_t host)
return spi_periph_signal[host].irq_dma;
}
//----------------------------------------------------------alloc dma periph-------------------------------------------------------//
#if !SOC_GDMA_SUPPORTED
static inline periph_module_t get_dma_periph(int dma_chan)
{
assert(dma_chan >= 1 && dma_chan <= SOC_SPI_DMA_CHAN_NUM);
#if CONFIG_IDF_TARGET_ESP32S2
if (dma_chan == 1) {
return PERIPH_SPI2_DMA_MODULE;
} else if (dma_chan==2) {
} else if (dma_chan == 2) {
return PERIPH_SPI3_DMA_MODULE;
} else {
abort();
return -1;
}
#elif CONFIG_IDF_TARGET_ESP32
return PERIPH_SPI_DMA_MODULE;
#elif SOC_GDMA_SUPPORTED
return PERIPH_GDMA_MODULE;
#else
return 0;
#endif
}
bool spicommon_dma_chan_claim(int dma_chan)
static bool spicommon_dma_chan_claim(int dma_chan, uint32_t *out_actual_dma_chan)
{
bool ret = false;
assert(dma_chan >= 1 && dma_chan <= SOC_SPI_DMA_CHAN_NUM);
portENTER_CRITICAL(&spi_dma_spinlock);
if ( !(spi_dma_chan_enabled & DMA_CHANNEL_ENABLED(dma_chan)) ) {
// get the channel only when it's not claimed yet.
spi_dma_chan_enabled |= DMA_CHANNEL_ENABLED(dma_chan);
bool is_used = (BIT(dma_chan) & spi_dma_chan_enabled);
if (!is_used) {
spi_dma_chan_enabled |= BIT(dma_chan);
periph_module_enable(get_dma_periph(dma_chan));
*out_actual_dma_chan = dma_chan;
ret = true;
}
periph_module_enable(get_dma_periph(dma_chan));
portEXIT_CRITICAL(&spi_dma_spinlock);
return ret;
}
bool spicommon_dma_chan_in_use(int dma_chan)
{
assert(dma_chan ==1 || dma_chan == 2);
return spi_dma_chan_enabled & DMA_CHANNEL_ENABLED(dma_chan);
}
bool spicommon_dma_chan_free(int dma_chan)
{
assert( dma_chan == 1 || dma_chan == 2 );
assert( spi_dma_chan_enabled & DMA_CHANNEL_ENABLED(dma_chan) );
portENTER_CRITICAL(&spi_dma_spinlock);
spi_dma_chan_enabled &= ~DMA_CHANNEL_ENABLED(dma_chan);
periph_module_disable(get_dma_periph(dma_chan));
portEXIT_CRITICAL(&spi_dma_spinlock);
return true;
}
void spicommon_connect_spi_and_dma(spi_host_device_t host, int dma_chan)
static void spicommon_connect_spi_and_dma(spi_host_device_t host, int dma_chan)
{
#if CONFIG_IDF_TARGET_ESP32
DPORT_SET_PERI_REG_BITS(DPORT_SPI_DMA_CHAN_SEL_REG, 3, dma_chan, (host * 2));
#elif CONFIG_IDF_TARGET_ESP32S2
//On ESP32S2, each SPI controller has its own DMA channel. So there is no need to connect them.
#elif SOC_GDMA_SUPPORTED
int gdma_chan, periph_id;
if (dma_chan == 1) {
gdma_chan = SOC_GDMA_SPI2_DMA_CHANNEL;
periph_id = SOC_GDMA_TRIG_PERIPH_SPI2;
#ifdef SOC_GDMA_TRIG_PERIPH_SPI3
} else if (dma_chan == 2) {
gdma_chan = SOC_GDMA_SPI3_DMA_CHANNEL;
periph_id = SOC_GDMA_TRIG_PERIPH_SPI3;
#endif
} else {
abort();
}
spi_dma_connect_rx_channel_to_periph(gdma_chan, periph_id);
spi_dma_connect_tx_channel_to_periph(gdma_chan, periph_id);
spi_dma_set_rx_channel_priority(gdma_chan, 1);
spi_dma_set_tx_channel_priority(gdma_chan, 1);
#endif //#elif SOC_GDMA_SUPPORTED
}
static esp_err_t spicommon_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan)
{
assert(is_valid_host(host_id));
#if CONFIG_IDF_TARGET_ESP32
assert(dma_chan > SPI_DMA_DISABLED && dma_chan <= SPI_DMA_CH_AUTO);
#elif CONFIG_IDF_TARGET_ESP32S2
assert(dma_chan == (int)host_id || dma_chan == SPI_DMA_CH_AUTO);
#endif
esp_err_t ret = ESP_OK;
bool success = false;
uint32_t actual_dma_chan = 0;
if (dma_chan == SPI_DMA_CH_AUTO) {
#if CONFIG_IDF_TARGET_ESP32
for (int i = 1; i < SOC_SPI_DMA_CHAN_NUM+1; i++) {
success = spicommon_dma_chan_claim(i, &actual_dma_chan);
if (success) {
break;
}
}
#elif CONFIG_IDF_TARGET_ESP32S2
//On ESP32S2, each SPI controller has its own DMA channel
success = spicommon_dma_chan_claim(host_id, &actual_dma_chan);
#endif //#if CONFIG_IDF_TARGET_XXX
} else {
success = spicommon_dma_chan_claim((int)dma_chan, &actual_dma_chan);
}
//On ESP32 and ESP32S2, actual_tx_dma_chan and actual_rx_dma_chan are always same
*out_actual_tx_dma_chan = actual_dma_chan;
*out_actual_rx_dma_chan = actual_dma_chan;
if (!success) {
SPI_CHECK(false, "no available dma channel", ESP_ERR_NOT_FOUND);
}
spicommon_connect_spi_and_dma(host_id, *out_actual_tx_dma_chan);
return ret;
}
#else //SOC_GDMA_SUPPORTED
static esp_err_t spicommon_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan)
{
assert(is_valid_host(host_id));
assert(dma_chan == SPI_DMA_CH_AUTO);
esp_err_t ret = ESP_OK;
spicommon_bus_context_t *ctx = bus_ctx[host_id];
if (dma_chan == SPI_DMA_CH_AUTO) {
gdma_channel_alloc_config_t tx_alloc_config = {
.flags.reserve_sibling = 1,
.direction = GDMA_CHANNEL_DIRECTION_TX,
};
ret = gdma_new_channel(&tx_alloc_config, &ctx->tx_channel);
if (ret != ESP_OK) {
return ret;
}
gdma_channel_alloc_config_t rx_alloc_config = {
.direction = GDMA_CHANNEL_DIRECTION_RX,
.sibling_chan = ctx->tx_channel,
};
ret = gdma_new_channel(&rx_alloc_config, &ctx->rx_channel);
if (ret != ESP_OK) {
return ret;
}
if (host_id == SPI2_HOST) {
gdma_connect(ctx->rx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SPI, 2));
gdma_connect(ctx->tx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SPI, 2));
}
#if (SOC_SPI_PERIPH_NUM >= 3)
else if (host_id == SPI3_HOST) {
gdma_connect(ctx->rx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SPI, 3));
gdma_connect(ctx->tx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SPI, 3));
}
#endif
gdma_get_channel_id(ctx->tx_channel, (int *)out_actual_tx_dma_chan);
gdma_get_channel_id(ctx->rx_channel, (int *)out_actual_rx_dma_chan);
}
return ret;
}
#endif //#if !SOC_GDMA_SUPPORTED
esp_err_t spicommon_slave_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan)
{
assert(is_valid_host(host_id));
#if CONFIG_IDF_TARGET_ESP32
assert(dma_chan > SPI_DMA_DISABLED && dma_chan <= SPI_DMA_CH_AUTO);
#elif CONFIG_IDF_TARGET_ESP32S2
assert(dma_chan == (int)host_id || dma_chan == SPI_DMA_CH_AUTO);
#endif
esp_err_t ret = ESP_OK;
uint32_t actual_tx_dma_chan = 0;
uint32_t actual_rx_dma_chan = 0;
spicommon_bus_context_t *ctx = (spicommon_bus_context_t *)calloc(1, sizeof(spicommon_bus_context_t));
if (!ctx) {
ret = ESP_ERR_NO_MEM;
goto cleanup;
}
bus_ctx[host_id] = ctx;
ctx->host_id = host_id;
ret = spicommon_dma_chan_alloc(host_id, dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan);
if (ret != ESP_OK) {
goto cleanup;
}
ctx->bus_attr.tx_dma_chan = actual_tx_dma_chan;
ctx->bus_attr.rx_dma_chan = actual_rx_dma_chan;
*out_actual_tx_dma_chan = actual_tx_dma_chan;
*out_actual_rx_dma_chan = actual_rx_dma_chan;
return ret;
cleanup:
free(ctx);
ctx = NULL;
return ret;
}
//----------------------------------------------------------free dma periph-------------------------------------------------------//
static esp_err_t spicommon_dma_chan_free(spi_host_device_t host_id)
{
assert(is_valid_host(host_id));
spicommon_bus_context_t *ctx = bus_ctx[host_id];
#if !SOC_GDMA_SUPPORTED
//On ESP32S2, each SPI controller has its own DMA channel
int dma_chan = ctx->bus_attr.tx_dma_chan;
assert(spi_dma_chan_enabled & BIT(dma_chan));
portENTER_CRITICAL(&spi_dma_spinlock);
spi_dma_chan_enabled &= ~BIT(dma_chan);
periph_module_disable(get_dma_periph(dma_chan));
portEXIT_CRITICAL(&spi_dma_spinlock);
#else //SOC_GDMA_SUPPORTED
if (ctx->rx_channel) {
gdma_disconnect(ctx->rx_channel);
gdma_del_channel(ctx->rx_channel);
}
if (ctx->tx_channel) {
gdma_disconnect(ctx->tx_channel);
gdma_del_channel(ctx->tx_channel);
}
#endif
return ESP_OK;
}
esp_err_t spicommon_slave_free_dma(spi_host_device_t host_id)
{
assert(is_valid_host(host_id));
esp_err_t ret = spicommon_dma_chan_free(host_id);
free(bus_ctx[host_id]);
bus_ctx[host_id] = NULL;
return ret;
}
//----------------------------------------------------------IO general-------------------------------------------------------//
static bool bus_uses_iomux_pins(spi_host_device_t host, const spi_bus_config_t* bus_config)
{
if (bus_config->sclk_io_num>=0 &&
@ -254,7 +389,7 @@ Do the common stuff to hook up a SPI host to a bus defined by a bunch of GPIO pi
bus config struct and it'll set up the GPIO matrix and enable the device. If a pin is set to non-negative value,
it should be able to be initialized.
*/
esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_config_t *bus_config, int dma_chan, uint32_t flags, uint32_t* flags_o)
esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_config_t *bus_config, uint32_t flags, uint32_t* flags_o)
{
uint32_t temp_flag = 0;
@ -364,7 +499,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
#if CONFIG_IDF_TARGET_ESP32S2
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[bus_config->mosi_io_num]);
#endif
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->mosi_io_num], FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->mosi_io_num], FUNC_GPIO);
}
if (bus_config->miso_io_num >= 0) {
if (miso_need_output || (temp_flag&SPICOMMON_BUSFLAG_DUAL)) {
@ -377,7 +512,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
#if CONFIG_IDF_TARGET_ESP32S2
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[bus_config->miso_io_num]);
#endif
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->miso_io_num], FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->miso_io_num], FUNC_GPIO);
}
if (bus_config->quadwp_io_num >= 0) {
gpio_set_direction(bus_config->quadwp_io_num, GPIO_MODE_INPUT_OUTPUT);
@ -386,7 +521,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
#if CONFIG_IDF_TARGET_ESP32S2
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[bus_config->quadwp_io_num]);
#endif
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadwp_io_num], FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->quadwp_io_num], FUNC_GPIO);
}
if (bus_config->quadhd_io_num >= 0) {
gpio_set_direction(bus_config->quadhd_io_num, GPIO_MODE_INPUT_OUTPUT);
@ -395,7 +530,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
#if CONFIG_IDF_TARGET_ESP32S2
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[bus_config->quadhd_io_num]);
#endif
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadhd_io_num], FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->quadhd_io_num], FUNC_GPIO);
}
if (bus_config->sclk_io_num >= 0) {
if (sclk_need_output) {
@ -408,7 +543,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
#if CONFIG_IDF_TARGET_ESP32S2
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[bus_config->sclk_io_num]);
#endif
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->sclk_io_num], FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->sclk_io_num], FUNC_GPIO);
}
}
@ -448,7 +583,7 @@ void spicommon_cs_initialize(spi_host_device_t host, int cs_io_num, int cs_num,
}
if (cs_num == 0) esp_rom_gpio_connect_in_signal(cs_io_num, spi_periph_signal[host].spics_in, false);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[cs_io_num]);
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[cs_io_num], FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[cs_io_num], FUNC_GPIO);
}
}
@ -480,22 +615,23 @@ spi_bus_lock_handle_t spi_bus_lock_get_by_id(spi_host_device_t host_id)
return bus_ctx[host_id]->bus_attr.lock;
}
static inline bool is_valid_host(spi_host_device_t host)
{
return host >= SPI1_HOST && host <= SPI3_HOST;
}
esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *bus_config, int dma_chan)
//----------------------------------------------------------master bus init-------------------------------------------------------//
esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *bus_config, spi_dma_chan_t dma_chan)
{
esp_err_t err = ESP_OK;
spicommon_bus_context_t *ctx = NULL;
spi_bus_attr_t *bus_attr = NULL;
uint32_t actual_tx_dma_chan = 0;
uint32_t actual_rx_dma_chan = 0;
SPI_CHECK(is_valid_host(host_id), "invalid host_id", ESP_ERR_INVALID_ARG);
SPI_CHECK(bus_ctx[host_id] == NULL, "SPI bus already initialized.", ESP_ERR_INVALID_STATE);
#ifdef CONFIG_IDF_TARGET_ESP32
SPI_CHECK( dma_chan >= 0 && dma_chan <= 2, "invalid dma channel", ESP_ERR_INVALID_ARG );
SPI_CHECK(dma_chan >= SPI_DMA_DISABLED && dma_chan <= SPI_DMA_CH_AUTO, "invalid dma channel", ESP_ERR_INVALID_ARG );
#elif CONFIG_IDF_TARGET_ESP32S2
SPI_CHECK( dma_chan == 0 || dma_chan == host_id, "invalid dma channel", ESP_ERR_INVALID_ARG );
SPI_CHECK( dma_chan == SPI_DMA_DISABLED || dma_chan == (int)host_id || dma_chan == SPI_DMA_CH_AUTO, "invalid dma channel", ESP_ERR_INVALID_ARG );
#elif SOC_GDMA_SUPPORTED
SPI_CHECK( dma_chan == SPI_DMA_DISABLED || dma_chan == SPI_DMA_CH_AUTO, "invalid dma channel, chip only support spi dma channel auto-alloc", ESP_ERR_INVALID_ARG );
#endif
SPI_CHECK((bus_config->intr_flags & (ESP_INTR_FLAG_HIGH|ESP_INTR_FLAG_EDGE|ESP_INTR_FLAG_INTRDISABLED))==0, "intr flag not allowed", ESP_ERR_INVALID_ARG);
#ifndef CONFIG_SPI_MASTER_ISR_IN_IRAM
@ -505,36 +641,27 @@ esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *
bool spi_chan_claimed = spicommon_periph_claim(host_id, "spi master");
SPI_CHECK(spi_chan_claimed, "host_id already in use", ESP_ERR_INVALID_STATE);
if (dma_chan != 0) {
bool dma_chan_claimed = spicommon_dma_chan_claim(dma_chan);
if (!dma_chan_claimed) {
spicommon_periph_free(host_id);
SPI_CHECK(false, "dma channel already in use", ESP_ERR_INVALID_STATE);
}
spicommon_connect_spi_and_dma(host_id, dma_chan);
}
//clean and initialize the context
ctx = (spicommon_bus_context_t*)malloc(sizeof(spicommon_bus_context_t));
ctx = (spicommon_bus_context_t *)calloc(1, sizeof(spicommon_bus_context_t));
if (!ctx) {
err = ESP_ERR_NO_MEM;
goto cleanup;
}
*ctx = (spicommon_bus_context_t) {
.host_id = host_id,
.bus_attr = {
.bus_cfg = *bus_config,
.dma_chan = dma_chan,
},
};
bus_ctx[host_id] = ctx;
ctx->host_id = host_id;
bus_attr = &ctx->bus_attr;
if (dma_chan == 0) {
bus_attr->max_transfer_sz = SOC_SPI_MAXIMUM_BUFFER_SIZE;
bus_attr->dma_desc_num = 0;
} else {
//See how many dma descriptors we need and allocate them
bus_attr->bus_cfg = *bus_config;
if (dma_chan != SPI_DMA_DISABLED) {
bus_attr->dma_enabled = 1;
err = spicommon_dma_chan_alloc(host_id, dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan);
if (err != ESP_OK) {
goto cleanup;
}
bus_attr->tx_dma_chan = actual_tx_dma_chan;
bus_attr->rx_dma_chan = actual_rx_dma_chan;
int dma_desc_ct = lldesc_get_required_num(bus_config->max_transfer_sz);
if (dma_desc_ct == 0) dma_desc_ct = 1; //default to 4k when max is not given
@ -546,6 +673,10 @@ esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *
goto cleanup;
}
bus_attr->dma_desc_num = dma_desc_ct;
} else {
bus_attr->dma_enabled = 0;
bus_attr->max_transfer_sz = SOC_SPI_MAXIMUM_BUFFER_SIZE;
bus_attr->dma_desc_num = 0;
}
spi_bus_lock_config_t lock_config = {
@ -565,12 +696,11 @@ esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *
}
#endif //CONFIG_PM_ENABLE
err = spicommon_bus_initialize_io(host_id, bus_config, dma_chan, SPICOMMON_BUSFLAG_MASTER | bus_config->flags, &bus_attr->flags);
err = spicommon_bus_initialize_io(host_id, bus_config, SPICOMMON_BUSFLAG_MASTER | bus_config->flags, &bus_attr->flags);
if (err != ESP_OK) {
goto cleanup;
}
bus_ctx[host_id] = ctx;
return ESP_OK;
cleanup:
@ -583,12 +713,15 @@ cleanup:
}
free(bus_attr->dmadesc_tx);
free(bus_attr->dmadesc_rx);
}
free(ctx);
if (dma_chan) {
spicommon_dma_chan_free(dma_chan);
bus_attr->dmadesc_tx = NULL;
bus_attr->dmadesc_rx = NULL;
if (bus_attr->dma_enabled) {
spicommon_dma_chan_free(host_id);
}
}
spicommon_periph_free(host_id);
free(bus_ctx[host_id]);
bus_ctx[host_id] = NULL;
return err;
}
@ -615,15 +748,14 @@ esp_err_t spi_bus_free(spi_host_device_t host_id)
esp_pm_lock_delete(bus_attr->pm_lock);
#endif
spi_bus_deinit_lock(bus_attr->lock);
free(bus_attr->dmadesc_rx);
free(bus_attr->dmadesc_tx);
if (bus_attr->dma_chan > 0) {
spicommon_dma_chan_free (bus_attr->dma_chan);
bus_attr->dmadesc_tx = NULL;
bus_attr->dmadesc_rx = NULL;
if (bus_attr->dma_enabled > 0) {
spicommon_dma_chan_free(host_id);
}
spicommon_periph_free(host_id);
free(ctx);
bus_ctx[host_id] = NULL;
return err;

View File

@ -188,10 +188,12 @@ static esp_err_t spi_master_deinit_driver(void* arg);
static inline bool is_valid_host(spi_host_device_t host)
{
//SPI1 can be used as GPSPI only on ESP32
#if CONFIG_IDF_TARGET_ESP32
return host >= SPI1_HOST && host <= SPI3_HOST;
#else
// SPI_HOST (SPI1_HOST) is not supported by the SPI Master driver on ESP32-S2 and later
#elif (SOC_SPI_PERIPH_NUM == 2)
return host == SPI2_HOST;
#elif (SOC_SPI_PERIPH_NUM == 3)
return host >= SPI2_HOST && host <= SPI3_HOST;
#endif
}
@ -231,17 +233,18 @@ static esp_err_t spi_master_init_driver(spi_host_device_t host_id)
}
//assign the SPI, RX DMA and TX DMA peripheral registers beginning address
spi_hal_dma_config_t hal_dma_config = {
spi_hal_config_t hal_config = {
//On ESP32-S2 and earlier chips, DMA registers are part of SPI registers. Pass the registers of SPI peripheral to control it.
.dma_in = SPI_LL_GET_HW(host_id),
.dma_out = SPI_LL_GET_HW(host_id),
.dma_enabled = bus_attr->dma_enabled,
.dmadesc_tx = bus_attr->dmadesc_tx,
.dmadesc_rx = bus_attr->dmadesc_rx,
.dmadesc_n = bus_attr->dma_desc_num
.tx_dma_chan = bus_attr->tx_dma_chan,
.rx_dma_chan = bus_attr->rx_dma_chan,
.dmadesc_n = bus_attr->dma_desc_num,
};
spi_hal_init(&host->hal, host_id, &hal_dma_config);
host->hal.dma_enabled = (bus_attr->dma_chan != 0);
spi_hal_init(&host->hal, host_id, &hal_config);
if (host_id != SPI1_HOST) {
//SPI1 attributes are already initialized at start up.
@ -606,8 +609,9 @@ static void SPI_MASTER_ISR_ATTR spi_intr(void *arg)
//Okay, transaction is done.
const int cs = host->cur_cs;
//Tell common code DMA workaround that our DMA channel is idle. If needed, the code will do a DMA reset.
if (bus_attr->dma_chan) {
spicommon_dmaworkaround_idle(bus_attr->dma_chan);
if (bus_attr->dma_enabled) {
//This workaround is only for esp32, where tx_dma_chan and rx_dma_chan are always same
spicommon_dmaworkaround_idle(bus_attr->tx_dma_chan);
}
//cur_cs is changed to DEV_NUM_MAX here
@ -658,9 +662,10 @@ static void SPI_MASTER_ISR_ATTR spi_intr(void *arg)
if (trans_found) {
spi_trans_priv_t *const cur_trans_buf = &host->cur_trans_buf;
if (bus_attr->dma_chan != 0 && (cur_trans_buf->buffer_to_rcv || cur_trans_buf->buffer_to_send)) {
if (bus_attr->dma_enabled && (cur_trans_buf->buffer_to_rcv || cur_trans_buf->buffer_to_send)) {
//mark channel as active, so that the DMA will not be reset by the slave
spicommon_dmaworkaround_transfer_active(bus_attr->dma_chan);
//This workaround is only for esp32, where tx_dma_chan and rx_dma_chan are always same
spicommon_dmaworkaround_transfer_active(bus_attr->tx_dma_chan);
}
spi_new_trans(device_to_send, cur_trans_buf);
}
@ -693,7 +698,7 @@ static SPI_MASTER_ISR_ATTR esp_err_t check_trans_valid(spi_device_handle_t handl
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)) && !is_half_duplex), "incompatible iface params", ESP_ERR_INVALID_ARG);
#ifdef CONFIG_IDF_TARGET_ESP32
SPI_CHECK(!is_half_duplex || bus_attr->dma_chan == 0 || !rx_enabled || !tx_enabled, "SPI half duplex mode does not support using DMA with both MOSI and MISO phases.", ESP_ERR_INVALID_ARG );
SPI_CHECK(!is_half_duplex || !bus_attr->dma_enabled || !rx_enabled || !tx_enabled, "SPI half duplex mode does not support using DMA with both MOSI and MISO phases.", ESP_ERR_INVALID_ARG );
#elif CONFIG_IDF_TARGET_ESP32S3
SPI_CHECK(!is_half_duplex || !tx_enabled || !rx_enabled, "SPI half duplex mode is not supported when both MOSI and MISO phases are enabled.", ESP_ERR_INVALID_ARG);
#endif
@ -788,7 +793,7 @@ esp_err_t SPI_MASTER_ATTR spi_device_queue_trans(spi_device_handle_t handle, spi
SPI_CHECK(!spi_bus_device_is_polling(handle), "Cannot queue new transaction while previous polling transaction is not terminated.", ESP_ERR_INVALID_STATE );
spi_trans_priv_t trans_buf;
ret = setup_priv_desc(trans_desc, &trans_buf, (host->bus_attr->dma_chan!=0));
ret = setup_priv_desc(trans_desc, &trans_buf, (host->bus_attr->dma_enabled));
if (ret != ESP_OK) return ret;
#ifdef CONFIG_PM_ENABLE
@ -877,8 +882,9 @@ esp_err_t SPI_MASTER_ISR_ATTR spi_device_acquire_bus(spi_device_t *device, TickT
//configure the device ahead so that we don't need to do it again in the following transactions
spi_setup_device(host->device[device->id]);
//the DMA is also occupied by the device, all the slave devices that using DMA should wait until bus released.
if (host->bus_attr->dma_chan != 0) {
spicommon_dmaworkaround_transfer_active(host->bus_attr->dma_chan);
if (host->bus_attr->dma_enabled) {
//This workaround is only for esp32, where tx_dma_chan and rx_dma_chan are always same
spicommon_dmaworkaround_transfer_active(host->bus_attr->tx_dma_chan);
}
return ESP_OK;
}
@ -893,8 +899,9 @@ void SPI_MASTER_ISR_ATTR spi_device_release_bus(spi_device_t *dev)
assert(0);
}
if (host->bus_attr->dma_chan != 0) {
spicommon_dmaworkaround_idle(host->bus_attr->dma_chan);
if (host->bus_attr->dma_enabled) {
//This workaround is only for esp32, where tx_dma_chan and rx_dma_chan are always same
spicommon_dmaworkaround_idle(host->bus_attr->tx_dma_chan);
}
//Tell common code DMA workaround that our DMA channel is idle. If needed, the code will do a DMA reset.
@ -928,7 +935,7 @@ esp_err_t SPI_MASTER_ISR_ATTR spi_device_polling_start(spi_device_handle_t handl
}
if (ret != ESP_OK) return ret;
ret = setup_priv_desc(trans_desc, &host->cur_trans_buf, (host->bus_attr->dma_chan!=0));
ret = setup_priv_desc(trans_desc, &host->cur_trans_buf, (host->bus_attr->dma_enabled));
if (ret!=ESP_OK) return ret;
//Polling, no interrupt is used.

View File

@ -67,7 +67,9 @@ typedef struct {
int max_transfer_sz;
QueueHandle_t trans_queue;
QueueHandle_t ret_queue;
int dma_chan;
bool dma_enabled;
uint32_t tx_dma_chan;
uint32_t rx_dma_chan;
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_handle_t pm_lock;
#endif
@ -79,10 +81,12 @@ static void IRAM_ATTR spi_intr(void *arg);
static inline bool is_valid_host(spi_host_device_t host)
{
//SPI1 can be used as GPSPI only on ESP32
#if CONFIG_IDF_TARGET_ESP32
return host >= SPI1_HOST && host <= SPI3_HOST;
#else
// SPI_HOST (SPI1_HOST) is not supported by the SPI Slave driver on ESP32-S2 & later
#elif (SOC_SPI_PERIPH_NUM == 2)
return host == SPI2_HOST;
#elif (SOC_SPI_PERIPH_NUM == 3)
return host >= SPI2_HOST && host <= SPI3_HOST;
#endif
}
@ -108,17 +112,20 @@ static inline void restore_cs(spi_slave_t *host)
}
}
esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *bus_config, const spi_slave_interface_config_t *slave_config, int dma_chan)
esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *bus_config, const spi_slave_interface_config_t *slave_config, spi_dma_chan_t dma_chan)
{
bool spi_chan_claimed, dma_chan_claimed;
bool spi_chan_claimed;
uint32_t actual_tx_dma_chan = 0;
uint32_t actual_rx_dma_chan = 0;
esp_err_t ret = ESP_OK;
esp_err_t err;
//We only support HSPI/VSPI, period.
SPI_CHECK(is_valid_host(host), "invalid host", ESP_ERR_INVALID_ARG);
#if defined(CONFIG_IDF_TARGET_ESP32)
SPI_CHECK( dma_chan >= 0 && dma_chan <= 2, "invalid dma channel", ESP_ERR_INVALID_ARG );
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
SPI_CHECK( dma_chan == 0 || dma_chan == host, "invalid dma channel", ESP_ERR_INVALID_ARG );
#ifdef CONFIG_IDF_TARGET_ESP32
SPI_CHECK(dma_chan >= SPI_DMA_DISABLED && dma_chan <= SPI_DMA_CH_AUTO, "invalid dma channel", ESP_ERR_INVALID_ARG );
#elif CONFIG_IDF_TARGET_ESP32S2
SPI_CHECK( dma_chan == SPI_DMA_DISABLED || dma_chan == (int)host || dma_chan == SPI_DMA_CH_AUTO, "invalid dma channel", ESP_ERR_INVALID_ARG );
#elif SOC_GDMA_SUPPORTED
SPI_CHECK( dma_chan == SPI_DMA_DISABLED || dma_chan == SPI_DMA_CH_AUTO, "invalid dma channel, chip only support spi dma channel auto-alloc", ESP_ERR_INVALID_ARG );
#endif
SPI_CHECK((bus_config->intr_flags & (ESP_INTR_FLAG_HIGH|ESP_INTR_FLAG_EDGE|ESP_INTR_FLAG_INTRDISABLED))==0, "intr flag not allowed", ESP_ERR_INVALID_ARG);
#ifndef CONFIG_SPI_SLAVE_ISR_IN_IRAM
@ -129,17 +136,6 @@ 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 slave");
SPI_CHECK(spi_chan_claimed, "host already in use", ESP_ERR_INVALID_STATE);
bool use_dma = dma_chan != 0;
if (use_dma) {
dma_chan_claimed=spicommon_dma_chan_claim(dma_chan);
if ( !dma_chan_claimed ) {
spicommon_periph_free( host );
SPI_CHECK(dma_chan_claimed, "dma channel already in use", ESP_ERR_INVALID_STATE);
}
spicommon_connect_spi_and_dma(host, dma_chan);
}
spihost[host] = malloc(sizeof(spi_slave_t));
if (spihost[host] == NULL) {
ret = ESP_ERR_NO_MEM;
@ -149,7 +145,16 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
memcpy(&spihost[host]->cfg, slave_config, sizeof(spi_slave_interface_config_t));
spihost[host]->id = host;
err = spicommon_bus_initialize_io(host, bus_config, dma_chan, SPICOMMON_BUSFLAG_SLAVE|bus_config->flags, &spihost[host]->flags);
bool use_dma = (dma_chan != SPI_DMA_DISABLED);
spihost[host]->dma_enabled = use_dma;
if (use_dma) {
ret = spicommon_slave_dma_chan_alloc(host, dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan);
if (ret != ESP_OK) {
goto cleanup;
}
}
err = spicommon_bus_initialize_io(host, bus_config, SPICOMMON_BUSFLAG_SLAVE|bus_config->flags, &spihost[host]->flags);
if (err!=ESP_OK) {
ret = err;
goto cleanup;
@ -162,7 +167,8 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
if (use_dma) freeze_cs(spihost[host]);
int dma_desc_ct = 0;
spihost[host]->dma_chan = dma_chan;
spihost[host]->tx_dma_chan = actual_tx_dma_chan;
spihost[host]->rx_dma_chan = actual_rx_dma_chan;
if (use_dma) {
//See how many dma descriptors we need and allocate them
dma_desc_ct = (bus_config->max_transfer_sz + SPI_MAX_DMA_LEN - 1) / SPI_MAX_DMA_LEN;
@ -220,6 +226,8 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
hal->tx_lsbfirst = (slave_config->flags & SPI_SLAVE_TXBIT_LSBFIRST) ? 1 : 0;
hal->mode = slave_config->mode;
hal->use_dma = use_dma;
hal->tx_dma_chan = actual_tx_dma_chan;
hal->rx_dma_chan = actual_rx_dma_chan;
spi_slave_hal_setup_device(hal);
@ -239,10 +247,14 @@ cleanup:
#endif
}
spi_slave_hal_deinit(&spihost[host]->hal);
if (spihost[host]->dma_enabled) {
spicommon_slave_free_dma(host);
}
free(spihost[host]);
spihost[host] = NULL;
spicommon_periph_free(host);
if (dma_chan != 0) spicommon_dma_chan_free(dma_chan);
return ret;
}
@ -252,8 +264,8 @@ esp_err_t spi_slave_free(spi_host_device_t host)
SPI_CHECK(spihost[host], "host not slave", ESP_ERR_INVALID_ARG);
if (spihost[host]->trans_queue) vQueueDelete(spihost[host]->trans_queue);
if (spihost[host]->ret_queue) vQueueDelete(spihost[host]->ret_queue);
if ( spihost[host]->dma_chan > 0 ) {
spicommon_dma_chan_free ( spihost[host]->dma_chan );
if (spihost[host]->dma_enabled) {
spicommon_slave_free_dma(host);
}
free(spihost[host]->hal.dmadesc_tx);
free(spihost[host]->hal.dmadesc_rx);
@ -274,9 +286,9 @@ esp_err_t SPI_SLAVE_ATTR spi_slave_queue_trans(spi_host_device_t host, const spi
BaseType_t r;
SPI_CHECK(is_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_enabled == 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 ||
SPI_CHECK(spihost[host]->dma_enabled == 0 || trans_desc->rx_buffer==NULL ||
(esp_ptr_dma_capable(trans_desc->rx_buffer) && esp_ptr_word_aligned(trans_desc->rx_buffer) &&
(trans_desc->length%4==0)),
"rxdata not in DMA-capable memory or not WORD aligned", ESP_ERR_INVALID_ARG);
@ -332,7 +344,7 @@ static void SPI_SLAVE_ISR_ATTR spi_intr(void *arg)
assert(spi_slave_hal_usr_is_done(hal));
bool use_dma = host->dma_chan != 0;
bool use_dma = host->dma_enabled;
if (host->cur_trans) {
// When DMA is enabled, the slave rx dma suffers from unexpected transactions. Forbid reading until transaction ready.
if (use_dma) freeze_cs(host);
@ -341,7 +353,8 @@ static void SPI_SLAVE_ISR_ATTR spi_intr(void *arg)
host->cur_trans->trans_len = spi_slave_hal_get_rcv_bitlen(hal);
if (spi_slave_hal_dma_need_reset(hal)) {
spicommon_dmaworkaround_req_reset(host->dma_chan, spi_slave_restart_after_dmareset, host);
//On ESP32 and ESP32S2, actual_tx_dma_chan and actual_rx_dma_chan are always same
spicommon_dmaworkaround_req_reset(host->tx_dma_chan, spi_slave_restart_after_dmareset, host);
}
if (host->cfg.post_trans_cb) host->cfg.post_trans_cb(host->cur_trans);
//Okay, transaction is done.
@ -350,7 +363,8 @@ static void SPI_SLAVE_ISR_ATTR spi_intr(void *arg)
host->cur_trans = NULL;
}
if (use_dma) {
spicommon_dmaworkaround_idle(host->dma_chan);
//On ESP32 and ESP32S2, actual_tx_dma_chan and actual_rx_dma_chan are always same
spicommon_dmaworkaround_idle(host->tx_dma_chan);
if (spicommon_dmaworkaround_reset_in_progress()) {
//We need to wait for the reset to complete. Disable int (will be re-enabled on reset callback) and exit isr.
esp_intr_disable(host->intr);
@ -375,7 +389,8 @@ static void SPI_SLAVE_ISR_ATTR spi_intr(void *arg)
hal->tx_buffer = trans->tx_buffer;
if (use_dma) {
spicommon_dmaworkaround_transfer_active(host->dma_chan);
//On ESP32 and ESP32S2, actual_tx_dma_chan and actual_rx_dma_chan are always same
spicommon_dmaworkaround_transfer_active(host->tx_dma_chan);
}
spi_slave_hal_prepare_data(hal);

View File

@ -23,12 +23,15 @@
#include "hal/spi_slave_hd_hal.h"
//SPI1 can never be used as the slave
#define VALID_HOST(x) (x>SPI_HOST && x<=HSPI_HOST)
#if (SOC_SPI_PERIPH_NUM == 2)
#define VALID_HOST(x) ((x) == SPI2_HOST)
#elif (SOC_SPI_PERIPH_NUM == 3)
#define VALID_HOST(x) ((x) >= SPI2_HOST && (x) <= SPI3_HOST)
#endif
#define SPIHD_CHECK(cond,warn,ret) do{if(!(cond)){ESP_LOGE(TAG, warn); return ret;}} while(0)
typedef struct {
int dma_chan;
bool dma_enabled;
int max_transfer_sz;
uint32_t flags;
portMUX_TYPE int_spinlock;
@ -64,12 +67,18 @@ static void spi_slave_hd_intr_append(void *arg);
esp_err_t spi_slave_hd_init(spi_host_device_t host_id, const spi_bus_config_t *bus_config,
const spi_slave_hd_slot_config_t *config)
{
bool spi_chan_claimed, dma_chan_claimed;
bool spi_chan_claimed;
bool append_mode = (config->flags & SPI_SLAVE_HD_APPEND_MODE);
uint32_t actual_tx_dma_chan = 0;
uint32_t actual_rx_dma_chan = 0;
esp_err_t ret = ESP_OK;
SPIHD_CHECK(VALID_HOST(host_id), "invalid host", ESP_ERR_INVALID_ARG);
SPIHD_CHECK(config->dma_chan == 0 || config->dma_chan == host_id, "invalid dma channel", ESP_ERR_INVALID_ARG);
#if CONFIG_IDF_TARGET_ESP32S2
SPIHD_CHECK(config->dma_chan == SPI_DMA_DISABLED || config->dma_chan == (int)host_id || config->dma_chan == SPI_DMA_CH_AUTO, "invalid dma channel", ESP_ERR_INVALID_ARG);
#elif SOC_GDMA_SUPPORTED
SPIHD_CHECK(config->dma_chan == SPI_DMA_DISABLED || config->dma_chan == SPI_DMA_CH_AUTO, "invalid dma channel, chip only support spi dma channel auto-alloc", ESP_ERR_INVALID_ARG);
#endif
#if !CONFIG_IDF_TARGET_ESP32S2
//Append mode is only supported on ESP32S2 now
SPIHD_CHECK(append_mode == 0, "Append mode is only supported on ESP32S2 now", ESP_ERR_INVALID_ARG);
@ -78,29 +87,23 @@ esp_err_t spi_slave_hd_init(spi_host_device_t host_id, const spi_bus_config_t *b
spi_chan_claimed = spicommon_periph_claim(host_id, "slave_hd");
SPIHD_CHECK(spi_chan_claimed, "host already in use", ESP_ERR_INVALID_STATE);
if ( config->dma_chan != 0 ) {
dma_chan_claimed = spicommon_dma_chan_claim(config->dma_chan);
if (!dma_chan_claimed) {
spicommon_periph_free(host_id);
SPIHD_CHECK(dma_chan_claimed, "dma channel already in use", ESP_ERR_INVALID_STATE);
}
spicommon_connect_spi_and_dma(host_id, config->dma_chan);
}
spi_slave_hd_slot_t* host = malloc(sizeof(spi_slave_hd_slot_t));
spi_slave_hd_slot_t* host = calloc(1, sizeof(spi_slave_hd_slot_t));
if (host == NULL) {
ret = ESP_ERR_NO_MEM;
goto cleanup;
}
spihost[host_id] = host;
memset(host, 0, sizeof(spi_slave_hd_slot_t));
host->dma_chan = config->dma_chan;
host->int_spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
host->dma_enabled = (config->dma_chan != SPI_DMA_DISABLED);
ret = spicommon_bus_initialize_io(host_id, bus_config, config->dma_chan,
SPICOMMON_BUSFLAG_SLAVE | bus_config->flags, &host->flags);
if (host->dma_enabled) {
ret = spicommon_slave_dma_chan_alloc(host_id, config->dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan);
if (ret != ESP_OK) {
goto cleanup;
}
}
ret = spicommon_bus_initialize_io(host_id, bus_config, SPICOMMON_BUSFLAG_SLAVE | bus_config->flags, &host->flags);
if (ret != ESP_OK) {
goto cleanup;
}
@ -113,14 +116,16 @@ esp_err_t spi_slave_hd_init(spi_host_device_t host_id, const spi_bus_config_t *b
.host_id = host_id,
.dma_in = SPI_LL_GET_HW(host_id),
.dma_out = SPI_LL_GET_HW(host_id),
.dma_chan = config->dma_chan,
.dma_enabled = host->dma_enabled,
.tx_dma_chan = actual_tx_dma_chan,
.rx_dma_chan = actual_rx_dma_chan,
.append_mode = append_mode,
.mode = config->mode,
.tx_lsbfirst = (config->flags & SPI_SLAVE_HD_RXBIT_LSBFIRST),
.rx_lsbfirst = (config->flags & SPI_SLAVE_HD_TXBIT_LSBFIRST),
};
if (config->dma_chan != 0) {
if (host->dma_enabled) {
//Malloc for all the DMA descriptors
uint32_t total_desc_size = spi_slave_hd_hal_get_total_desc_size(&host->hal, bus_config->max_transfer_sz);
host->hal.dmadesc_tx = heap_caps_malloc(total_desc_size, MALLOC_CAP_DMA);
@ -243,8 +248,8 @@ esp_err_t spi_slave_hd_deinit(spi_host_device_t host_id)
}
spicommon_periph_free(host_id);
if (host->dma_chan) {
spicommon_dma_chan_free(host->dma_chan);
if (host->dma_enabled) {
spicommon_slave_free_dma(host_id);
}
free(host);
spihost[host_id] = NULL;
@ -392,9 +397,7 @@ static IRAM_ATTR void spi_slave_hd_intr_append(void *arg)
spi_slave_hd_data_t *trans_desc;
while (1) {
bool trans_finish = false;
portENTER_CRITICAL_ISR(&host->int_spinlock);
trans_finish = spi_slave_hd_hal_get_tx_finished_trans(hal, (void **)&trans_desc);
portEXIT_CRITICAL_ISR(&host->int_spinlock);
if (!trans_finish) {
break;
}
@ -425,9 +428,7 @@ static IRAM_ATTR void spi_slave_hd_intr_append(void *arg)
size_t trans_len;
while (1) {
bool trans_finish = false;
portENTER_CRITICAL_ISR(&host->int_spinlock);
trans_finish = spi_slave_hd_hal_get_rx_finished_trans(hal, (void **)&trans_desc, &trans_len);
portEXIT_CRITICAL_ISR(&host->int_spinlock);
if (!trans_finish) {
break;
}
@ -546,17 +547,13 @@ esp_err_t spi_slave_hd_append_trans(spi_host_device_t host_id, spi_slave_chan_t
if (ret == pdFALSE) {
return ESP_ERR_TIMEOUT;
}
portENTER_CRITICAL(&host->int_spinlock);
err = spi_slave_hd_hal_txdma_append(hal, trans->data, trans->len, trans);
portEXIT_CRITICAL(&host->int_spinlock);
} else {
BaseType_t ret = xSemaphoreTake(host->rx_cnting_sem, timeout);
if (ret == pdFALSE) {
return ESP_ERR_TIMEOUT;
}
portENTER_CRITICAL(&host->int_spinlock);
err = spi_slave_hd_hal_rxdma_append(hal, trans->data, trans->len, trans);
portEXIT_CRITICAL(&host->int_spinlock);
}
if (err != ESP_OK) {
ESP_LOGE(TAG, "Wait until the DMA finishes its transaction");

View File

@ -16,32 +16,29 @@
// All the tests using the header should use this definition as much as possible,
// so that the working host can be changed easily in the future.
#if CONFIG_IDF_TARGET_ESP32
#define TEST_SPI_HOST HSPI_HOST
#define TEST_SLAVE_HOST VSPI_HOST
#define TEST_SPI_HOST SPI2_HOST
#define TEST_SLAVE_HOST SPI3_HOST
#define PIN_NUM_MISO HSPI_IOMUX_PIN_NUM_MISO
#define PIN_NUM_MOSI HSPI_IOMUX_PIN_NUM_MOSI
#define PIN_NUM_CLK HSPI_IOMUX_PIN_NUM_CLK
#define PIN_NUM_CS HSPI_IOMUX_PIN_NUM_CS
#define PIN_NUM_WP HSPI_IOMUX_PIN_NUM_WP
#define PIN_NUM_HD HSPI_IOMUX_PIN_NUM_HD
#define PIN_NUM_MISO SPI2_IOMUX_PIN_NUM_MISO
#define PIN_NUM_MOSI SPI2_IOMUX_PIN_NUM_MOSI
#define PIN_NUM_CLK SPI2_IOMUX_PIN_NUM_CLK
#define PIN_NUM_CS SPI2_IOMUX_PIN_NUM_CS
#define PIN_NUM_WP SPI2_IOMUX_PIN_NUM_WP
#define PIN_NUM_HD SPI2_IOMUX_PIN_NUM_HD
#define SLAVE_PIN_NUM_MISO VSPI_IOMUX_PIN_NUM_MISO
#define SLAVE_PIN_NUM_MOSI VSPI_IOMUX_PIN_NUM_MOSI
#define SLAVE_PIN_NUM_CLK VSPI_IOMUX_PIN_NUM_CLK
#define SLAVE_PIN_NUM_CS VSPI_IOMUX_PIN_NUM_CS
#define SLAVE_PIN_NUM_WP VSPI_IOMUX_PIN_NUM_WP
#define SLAVE_PIN_NUM_HD VSPI_IOMUX_PIN_NUM_HD
#define MASTER_IOMUX_PIN_MISO SPI2_IOMUX_PIN_NUM_MISO
#define MASTER_IOMUX_PIN_MOSI SPI2_IOMUX_PIN_NUM_MOSI
#define MASTER_IOMUX_PIN_SCLK SPI2_IOMUX_PIN_NUM_CLK
#define MASTER_IOMUX_PIN_CS SPI2_IOMUX_PIN_NUM_CS
#define MASTER_IOMUX_PIN_WP SPI2_IOMUX_PIN_NUM_WP
#define MASTER_IOMUX_PIN_HD SPI2_IOMUX_PIN_NUM_HD
#define SLAVE_IOMUX_PIN_MISO VSPI_IOMUX_PIN_NUM_MISO
#define SLAVE_IOMUX_PIN_MOSI VSPI_IOMUX_PIN_NUM_MOSI
#define SLAVE_IOMUX_PIN_SCLK VSPI_IOMUX_PIN_NUM_CLK
#define SLAVE_IOMUX_PIN_CS VSPI_IOMUX_PIN_NUM_CS
#define MASTER_IOMUX_PIN_MISO HSPI_IOMUX_PIN_NUM_MISO
#define MASTER_IOMUX_PIN_MOSI HSPI_IOMUX_PIN_NUM_MOSI
#define MASTER_IOMUX_PIN_SCLK HSPI_IOMUX_PIN_NUM_CLK
#define MASTER_IOMUX_PIN_CS HSPI_IOMUX_PIN_NUM_CS
#define SLAVE_IOMUX_PIN_MISO SPI3_IOMUX_PIN_NUM_MISO
#define SLAVE_IOMUX_PIN_MOSI SPI3_IOMUX_PIN_NUM_MOSI
#define SLAVE_IOMUX_PIN_SCLK SPI3_IOMUX_PIN_NUM_CLK
#define SLAVE_IOMUX_PIN_CS SPI3_IOMUX_PIN_NUM_CS
#define SLAVE_IOMUX_PIN_WP SPI3_IOMUX_PIN_NUM_WP
#define SLAVE_IOMUX_PIN_HD SPI3_IOMUX_PIN_NUM_HD
#define UNCONNECTED_PIN 27
#define INPUT_ONLY_PIN 34
@ -50,34 +47,29 @@
#define WIRE_DELAY 12.5
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#define TEST_SPI_HOST SPI2_HOST
#define TEST_SLAVE_HOST SPI3_HOST
#define TEST_SPI_HOST FSPI_HOST
#define TEST_SLAVE_HOST HSPI_HOST
#define PIN_NUM_MISO SPI2_IOMUX_PIN_NUM_MISO
#define PIN_NUM_MOSI SPI2_IOMUX_PIN_NUM_MOSI
#define PIN_NUM_CLK SPI2_IOMUX_PIN_NUM_CLK
#define PIN_NUM_CS SPI2_IOMUX_PIN_NUM_CS
#define PIN_NUM_WP SPI2_IOMUX_PIN_NUM_WP
#define PIN_NUM_HD SPI2_IOMUX_PIN_NUM_HD
#define PIN_NUM_MISO FSPI_IOMUX_PIN_NUM_MISO
#define PIN_NUM_MOSI FSPI_IOMUX_PIN_NUM_MOSI
#define PIN_NUM_CLK FSPI_IOMUX_PIN_NUM_CLK
#define PIN_NUM_CS FSPI_IOMUX_PIN_NUM_CS
#define PIN_NUM_WP FSPI_IOMUX_PIN_NUM_WP
#define PIN_NUM_HD FSPI_IOMUX_PIN_NUM_HD
#define SLAVE_PIN_NUM_MISO HSPI_IOMUX_PIN_NUM_MISO
#define SLAVE_PIN_NUM_MOSI HSPI_IOMUX_PIN_NUM_MOSI
#define SLAVE_PIN_NUM_CLK HSPI_IOMUX_PIN_NUM_CLK
#define SLAVE_PIN_NUM_CS HSPI_IOMUX_PIN_NUM_CS
#define SLAVE_PIN_NUM_WP -1
#define SLAVE_PIN_NUM_HD -1
#define MASTER_IOMUX_PIN_MISO SPI2_IOMUX_PIN_NUM_MISO
#define MASTER_IOMUX_PIN_MOSI SPI2_IOMUX_PIN_NUM_MOSI
#define MASTER_IOMUX_PIN_SCLK SPI2_IOMUX_PIN_NUM_CLK
#define MASTER_IOMUX_PIN_CS SPI2_IOMUX_PIN_NUM_CS
#define MASTER_IOMUX_PIN_WP SPI2_IOMUX_PIN_NUM_WP
#define MASTER_IOMUX_PIN_HD SPI2_IOMUX_PIN_NUM_HD
#define SLAVE_IOMUX_PIN_MISO -1
#define SLAVE_IOMUX_PIN_MOSI -1
#define SLAVE_IOMUX_PIN_SCLK -1
#define SLAVE_IOMUX_PIN_CS -1
#define MASTER_IOMUX_PIN_MISO FSPI_IOMUX_PIN_NUM_MISO
#define MASTER_IOMUX_PIN_MOSI FSPI_IOMUX_PIN_NUM_MOSI
#define MASTER_IOMUX_PIN_SCLK FSPI_IOMUX_PIN_NUM_CLK
#define MASTER_IOMUX_PIN_CS FSPI_IOMUX_PIN_NUM_CS
#define SLAVE_IOMUX_PIN_NUM_WP -1
#define SLAVE_IOMUX_PIN_NUM_HD -1
#define UNCONNECTED_PIN 41
#define INPUT_ONLY_PIN 46
@ -86,40 +78,30 @@
#define WIRE_DELAY 12.5
#elif CONFIG_IDF_TARGET_ESP32C3
#define TEST_SPI_HOST FSPI_HOST
#define TEST_SLAVE_HOST FSPI_HOST
#define PIN_NUM_MISO FSPI_IOMUX_PIN_NUM_MISO
#define PIN_NUM_MOSI FSPI_IOMUX_PIN_NUM_MOSI
#define PIN_NUM_CLK FSPI_IOMUX_PIN_NUM_CLK
#define PIN_NUM_CS FSPI_IOMUX_PIN_NUM_CS
#define PIN_NUM_WP FSPI_IOMUX_PIN_NUM_WP
#define PIN_NUM_HD FSPI_IOMUX_PIN_NUM_HD
#define SLAVE_PIN_NUM_MISO -1
#define SLAVE_PIN_NUM_MOSI -1
#define SLAVE_PIN_NUM_CLK -1
#define SLAVE_PIN_NUM_CS -1
#define SLAVE_PIN_NUM_WP -1
#define SLAVE_PIN_NUM_HD -1
//NOTE: On esp32c3, there is only 1 GPSPI controller, so master-slave test on single board should be disabled
#define SLAVE_IOMUX_PIN_MISO FSPI_IOMUX_PIN_NUM_MISO
#define SLAVE_IOMUX_PIN_MOSI FSPI_IOMUX_PIN_NUM_MOSI
#define SLAVE_IOMUX_PIN_SCLK FSPI_IOMUX_PIN_NUM_CLK
#define SLAVE_IOMUX_PIN_CS FSPI_IOMUX_PIN_NUM_CS
#define TEST_SPI_HOST SPI2_HOST
#define TEST_SLAVE_HOST SPI2_HOST
#define MASTER_IOMUX_PIN_MISO FSPI_IOMUX_PIN_NUM_MISO
#define MASTER_IOMUX_PIN_MOSI FSPI_IOMUX_PIN_NUM_MOSI
#define MASTER_IOMUX_PIN_SCLK FSPI_IOMUX_PIN_NUM_CLK
#define MASTER_IOMUX_PIN_CS FSPI_IOMUX_PIN_NUM_CS
#define PIN_NUM_MISO SPI2_IOMUX_PIN_NUM_MISO
#define PIN_NUM_MOSI SPI2_IOMUX_PIN_NUM_MOSI
#define PIN_NUM_CLK SPI2_IOMUX_PIN_NUM_CLK
#define PIN_NUM_CS SPI2_IOMUX_PIN_NUM_CS
#define PIN_NUM_WP SPI2_IOMUX_PIN_NUM_WP
#define PIN_NUM_HD SPI2_IOMUX_PIN_NUM_HD
#define SLAVE_IOMUX_PIN_MISO SPI2_IOMUX_PIN_NUM_MISO
#define SLAVE_IOMUX_PIN_MOSI SPI2_IOMUX_PIN_NUM_MOSI
#define SLAVE_IOMUX_PIN_SCLK SPI2_IOMUX_PIN_NUM_CLK
#define SLAVE_IOMUX_PIN_CS SPI2_IOMUX_PIN_NUM_CS
#define MASTER_IOMUX_PIN_MISO SPI2_IOMUX_PIN_NUM_MISO
#define MASTER_IOMUX_PIN_MOSI SPI2_IOMUX_PIN_NUM_MOSI
#define MASTER_IOMUX_PIN_SCLK SPI2_IOMUX_PIN_NUM_CLK
#define MASTER_IOMUX_PIN_CS SPI2_IOMUX_PIN_NUM_CS
#define GPIO_DELAY 0
#define ESP_SPI_SLAVE_TV 0
#define WIRE_DELAY 12.5
#endif
#define GET_DMA_CHAN(HOST) (HOST)

View File

@ -122,7 +122,6 @@ static void continuous_adc_init(uint16_t adc1_chan_mask, uint16_t adc2_chan_mask
adc_digi_init_config_t adc_dma_config = {
.max_store_buf_size = TEST_COUNT*2,
.conv_num_each_intr = 128,
.dma_chan = SOC_GDMA_ADC_DMA_CHANNEL,
.adc1_chan_mask = adc1_chan_mask,
.adc2_chan_mask = adc2_chan_mask,
};

View File

@ -2,6 +2,7 @@
#include "driver/spi_slave.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include "hal/gpio_hal.h"
int test_freq_default[]=TEST_FREQ_DEFAULT();
@ -202,13 +203,13 @@ void master_free_device_bus(spi_device_handle_t spi)
void spitest_gpio_output_sel(uint32_t gpio_num, int func, uint32_t signal_idx)
{
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], func);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_num], func);
GPIO.func_out_sel_cfg[gpio_num].func_sel = signal_idx;
}
void spitest_gpio_input_sel(uint32_t gpio_num, int func, uint32_t signal_idx)
{
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], func);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_num], func);
GPIO.func_in_sel_cfg[signal_idx].func_sel = gpio_num;
}

View File

@ -17,6 +17,7 @@
#include "soc/uart_struct.h"
#include "driver/periph_ctrl.h"
#include "esp_rom_gpio.h"
#include "hal/gpio_hal.h"
#define DATA_LENGTH 512 /*!<Data buffer length for test buffer*/
@ -651,7 +652,7 @@ TEST_CASE("I2C general API test", "[i2c]")
//Init uart baud rate detection
static void uart_aut_baud_det_init(int rxd_io_num)
{
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[rxd_io_num], PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[rxd_io_num], PIN_FUNC_GPIO);
gpio_set_direction(rxd_io_num, GPIO_MODE_INPUT_OUTPUT);
esp_rom_gpio_connect_out_signal(rxd_io_num, I2CEXT1_SCL_OUT_IDX, 0, 0);
esp_rom_gpio_connect_in_signal(rxd_io_num, U1RXD_IN_IDX, 0);

View File

@ -11,6 +11,7 @@
#include "freertos/task.h"
#include "driver/i2s.h"
#include "driver/gpio.h"
#include "hal/gpio_hal.h"
#include "unity.h"
#include "math.h"
#include "esp_rom_gpio.h"
@ -44,9 +45,9 @@
static void i2s_test_io_config(int mode)
{
// Connect internal signals using IO matrix.
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[MASTER_BCK_IO], PIN_FUNC_GPIO);
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[MASTER_WS_IO], PIN_FUNC_GPIO);
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[DATA_OUT_IO], PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[MASTER_BCK_IO], PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[MASTER_WS_IO], PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[DATA_OUT_IO], PIN_FUNC_GPIO);
gpio_set_direction(MASTER_BCK_IO, GPIO_MODE_INPUT_OUTPUT);
gpio_set_direction(MASTER_WS_IO, GPIO_MODE_INPUT_OUTPUT);

View File

@ -3,6 +3,7 @@
#include <string.h>
#include "sdkconfig.h"
#include "hal/cpu_hal.h"
#include "hal/gpio_hal.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
@ -63,7 +64,7 @@ static void rmt_setup_testbench(int tx_channel, int rx_channel, uint32_t flags)
}
// Routing internal signals by IO Matrix (bind rmt tx and rx signal on the same GPIO)
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[RMT_DATA_IO], PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[RMT_DATA_IO], PIN_FUNC_GPIO);
TEST_ESP_OK(gpio_set_direction(RMT_DATA_IO, GPIO_MODE_INPUT_OUTPUT));
esp_rom_gpio_connect_out_signal(RMT_DATA_IO, RMT_SIG_OUT0_IDX + tx_channel, 0, 0);
esp_rom_gpio_connect_in_signal(RMT_DATA_IO, RMT_SIG_IN0_IDX + rx_channel, 0);

View File

@ -39,7 +39,7 @@
//TEST_CNT > 512
#define TEST_CNT 10000
#define TEST_SDSPI_HOST HSPI_HOST
#define TEST_SDSPI_HOST SPI2_HOST
#define TEST_SDSPI_DMACHAN 1
#define TEST_RESET_DATA_LEN 10

View File

@ -74,7 +74,7 @@ TEST_CASE("SPI Master clockdiv calculation routines", "[spi]")
.quadhd_io_num=-1
};
esp_err_t ret;
ret=spi_bus_initialize(TEST_SPI_HOST, &buscfg, 1);
ret = spi_bus_initialize(TEST_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO);
TEST_ASSERT(ret==ESP_OK);
check_spi_pre_n_for(26000000, 1, 3);
@ -110,13 +110,10 @@ static spi_device_handle_t setup_spi_bus_loopback(int clkspeed, bool dma) {
.spics_io_num=PIN_NUM_CS,
.queue_size=3,
};
esp_err_t ret;
spi_device_handle_t handle;
ret=spi_bus_initialize(TEST_SPI_HOST, &buscfg, dma?1:0);
TEST_ASSERT(ret==ESP_OK);
ret=spi_bus_add_device(TEST_SPI_HOST, &devcfg, &handle);
TEST_ASSERT(ret==ESP_OK);
TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &buscfg, dma ? SPI_DMA_CH_AUTO : 0));
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &handle));
//connect MOSI to two devices breaks the output, fix it.
spitest_gpio_output_sel(PIN_NUM_MOSI, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spid_out);
printf("Bus/dev inited.\n");
@ -276,8 +273,10 @@ static esp_err_t test_master_pins(int mosi, int miso, int sclk, int cs)
spi_device_interface_config_t master_cfg = SPI_DEVICE_TEST_DEFAULT_CONFIG();
master_cfg.spics_io_num = cs;
ret = spi_bus_initialize(TEST_SPI_HOST, &cfg, 1);
if (ret != ESP_OK) return ret;
ret = spi_bus_initialize(TEST_SPI_HOST, &cfg, SPI_DMA_CH_AUTO);
if (ret != ESP_OK) {
return ret;
}
spi_device_handle_t spi;
ret = spi_bus_add_device(TEST_SPI_HOST, &master_cfg, &spi);
@ -301,8 +300,10 @@ static esp_err_t test_slave_pins(int mosi, int miso, int sclk, int cs)
spi_slave_interface_config_t slave_cfg = SPI_SLAVE_TEST_DEFAULT_CONFIG();
slave_cfg.spics_io_num = cs;
ret = spi_slave_initialize(TEST_SLAVE_HOST, &cfg, &slave_cfg, TEST_DMA_CHAN_SLAVE);
if (ret != ESP_OK) return ret;
ret = spi_slave_initialize(TEST_SLAVE_HOST, &cfg, &slave_cfg, SPI_DMA_CH_AUTO);
if (ret != ESP_OK) {
return ret;
}
spi_slave_free(TEST_SLAVE_HOST);
return ESP_OK;
@ -315,7 +316,6 @@ TEST_CASE("spi placed on input-only pins", "[spi]")
TEST_ESP_OK(test_master_pins(PIN_NUM_MOSI, INPUT_ONLY_PIN, PIN_NUM_CLK, PIN_NUM_CS));
TEST_ASSERT(test_master_pins(PIN_NUM_MOSI, PIN_NUM_MISO, INPUT_ONLY_PIN, PIN_NUM_CS) != ESP_OK);
TEST_ASSERT(test_master_pins(PIN_NUM_MOSI, PIN_NUM_MISO, PIN_NUM_CLK, INPUT_ONLY_PIN) != ESP_OK);
TEST_ESP_OK(test_slave_pins(PIN_NUM_MOSI, PIN_NUM_MISO, PIN_NUM_CLK, PIN_NUM_CS));
TEST_ESP_OK(test_slave_pins(INPUT_ONLY_PIN, PIN_NUM_MISO, PIN_NUM_CLK, PIN_NUM_CS));
TEST_ASSERT(test_slave_pins(PIN_NUM_MOSI, INPUT_ONLY_PIN, PIN_NUM_CLK, PIN_NUM_CS) != ESP_OK);
@ -336,18 +336,18 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]")
flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_IOMUX_PINS | SPICOMMON_BUSFLAG_QUAD;
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[TEST_SPI_HOST].spid_iomux_pin, .miso_io_num = spi_periph_signal[TEST_SPI_HOST].spiq_iomux_pin, .sclk_io_num = spi_periph_signal[TEST_SPI_HOST].spiclk_iomux_pin, .quadhd_io_num = spi_periph_signal[TEST_SPI_HOST].spihd_iomux_pin, .quadwp_io_num = spi_periph_signal[TEST_SPI_HOST].spiwp_iomux_pin,
.max_transfer_sz = 8, .flags = flags_expected};
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
ESP_LOGI(TAG, "test 4 iomux output pins...");
flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_IOMUX_PINS | SPICOMMON_BUSFLAG_DUAL;
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[TEST_SPI_HOST].spid_iomux_pin, .miso_io_num = spi_periph_signal[TEST_SPI_HOST].spiq_iomux_pin, .sclk_io_num = spi_periph_signal[TEST_SPI_HOST].spiclk_iomux_pin, .quadhd_io_num = -1, .quadwp_io_num = -1,
.max_transfer_sz = 8, .flags = flags_expected};
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
ESP_LOGI(TAG, "test 6 output pins...");
@ -355,9 +355,9 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]")
//swap MOSI and MISO
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[TEST_SPI_HOST].spiq_iomux_pin, .miso_io_num = spi_periph_signal[TEST_SPI_HOST].spid_iomux_pin, .sclk_io_num = spi_periph_signal[TEST_SPI_HOST].spiclk_iomux_pin, .quadhd_io_num = spi_periph_signal[TEST_SPI_HOST].spihd_iomux_pin, .quadwp_io_num = spi_periph_signal[TEST_SPI_HOST].spiwp_iomux_pin,
.max_transfer_sz = 8, .flags = flags_expected};
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
ESP_LOGI(TAG, "test 4 output pins...");
@ -365,9 +365,9 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]")
//swap MOSI and MISO
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[TEST_SPI_HOST].spiq_iomux_pin, .miso_io_num = spi_periph_signal[TEST_SPI_HOST].spid_iomux_pin, .sclk_io_num = spi_periph_signal[TEST_SPI_HOST].spiclk_iomux_pin, .quadhd_io_num = -1, .quadwp_io_num = -1,
.max_transfer_sz = 8, .flags = flags_expected};
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
#if !DISABLED_FOR_TARGETS(ESP32C3) //There is no input-only pin on esp32c3, so this test could be ignored.
@ -375,14 +375,14 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]")
flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_WPHD | SPICOMMON_BUSFLAG_GPIO_PINS;
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[TEST_SPI_HOST].spid_iomux_pin, .miso_io_num = INPUT_ONLY_PIN, .sclk_io_num = spi_periph_signal[TEST_SPI_HOST].spiclk_iomux_pin, .quadhd_io_num = spi_periph_signal[TEST_SPI_HOST].spihd_iomux_pin, .quadwp_io_num = spi_periph_signal[TEST_SPI_HOST].spiwp_iomux_pin,
.max_transfer_sz = 8, .flags = flags_expected};
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
ESP_LOGI(TAG, "test slave 5 output pins and MISO on input-only pin...");
flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_WPHD | SPICOMMON_BUSFLAG_GPIO_PINS;
cfg = (spi_bus_config_t){.mosi_io_num = INPUT_ONLY_PIN, .miso_io_num = spi_periph_signal[TEST_SPI_HOST].spiq_iomux_pin, .sclk_io_num = spi_periph_signal[TEST_SPI_HOST].spiclk_iomux_pin, .quadhd_io_num = spi_periph_signal[TEST_SPI_HOST].spihd_iomux_pin, .quadwp_io_num = spi_periph_signal[TEST_SPI_HOST].spiwp_iomux_pin,
.max_transfer_sz = 8, .flags = flags_expected};
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
ESP_LOGI(TAG, "test master 3 output pins and MOSI on input-only pin...");
@ -390,14 +390,14 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]")
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[TEST_SPI_HOST].spid_iomux_pin, .miso_io_num = INPUT_ONLY_PIN, .sclk_io_num = spi_periph_signal[TEST_SPI_HOST].spiclk_iomux_pin, .quadhd_io_num = -1, .quadwp_io_num = -1,
.max_transfer_sz = 8, .flags = flags_expected};
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
ESP_LOGI(TAG, "test slave 3 output pins and MISO on input-only pin...");
flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_GPIO_PINS;
cfg = (spi_bus_config_t){.mosi_io_num = INPUT_ONLY_PIN, .miso_io_num = spi_periph_signal[TEST_SPI_HOST].spiq_iomux_pin, .sclk_io_num = spi_periph_signal[TEST_SPI_HOST].spiclk_iomux_pin, .quadhd_io_num = -1, .quadwp_io_num = -1,
.max_transfer_sz = 8, .flags = flags_expected};
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
#endif
@ -406,75 +406,75 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]")
//swap MOSI and MISO
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[TEST_SPI_HOST].spiq_iomux_pin, .miso_io_num = spi_periph_signal[TEST_SPI_HOST].spid_iomux_pin, .sclk_io_num = spi_periph_signal[TEST_SPI_HOST].spiclk_iomux_pin, .quadhd_io_num = spi_periph_signal[TEST_SPI_HOST].spihd_iomux_pin, .quadwp_io_num = spi_periph_signal[TEST_SPI_HOST].spiwp_iomux_pin,
.max_transfer_sz = 8, .flags = flags_expected};
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
ESP_LOGI(TAG, "check native flag for 4 output pins...");
flags_expected = SPICOMMON_BUSFLAG_IOMUX_PINS;
//swap MOSI and MISO
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[TEST_SPI_HOST].spiq_iomux_pin, .miso_io_num = spi_periph_signal[TEST_SPI_HOST].spid_iomux_pin, .sclk_io_num = spi_periph_signal[TEST_SPI_HOST].spiclk_iomux_pin, .quadhd_io_num = -1, .quadwp_io_num = -1,
.max_transfer_sz = 8, .flags = flags_expected};
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
#if !DISABLED_FOR_TARGETS(ESP32C3) //There is no input-only pin on esp32c3, so this test could be ignored.
ESP_LOGI(TAG, "check dual flag for master 5 output pins and MISO/MOSI on input-only pin...");
flags_expected = SPICOMMON_BUSFLAG_DUAL | SPICOMMON_BUSFLAG_GPIO_PINS;
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[TEST_SPI_HOST].spid_iomux_pin, .miso_io_num = INPUT_ONLY_PIN, .sclk_io_num = spi_periph_signal[TEST_SPI_HOST].spiclk_iomux_pin, .quadhd_io_num = spi_periph_signal[TEST_SPI_HOST].spihd_iomux_pin, .quadwp_io_num = spi_periph_signal[TEST_SPI_HOST].spiwp_iomux_pin,
.max_transfer_sz = 8, .flags = flags_expected};
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
cfg = (spi_bus_config_t){.mosi_io_num = INPUT_ONLY_PIN, .miso_io_num = spi_periph_signal[TEST_SPI_HOST].spiq_iomux_pin, .sclk_io_num = spi_periph_signal[TEST_SPI_HOST].spiclk_iomux_pin, .quadhd_io_num = spi_periph_signal[TEST_SPI_HOST].spihd_iomux_pin, .quadwp_io_num = spi_periph_signal[TEST_SPI_HOST].spiwp_iomux_pin,
.max_transfer_sz = 8, .flags = flags_expected};
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
ESP_LOGI(TAG, "check dual flag for master 3 output pins and MISO/MOSI on input-only pin...");
flags_expected = SPICOMMON_BUSFLAG_DUAL | SPICOMMON_BUSFLAG_GPIO_PINS;
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[TEST_SPI_HOST].spid_iomux_pin, .miso_io_num = INPUT_ONLY_PIN, .sclk_io_num = spi_periph_signal[TEST_SPI_HOST].spiclk_iomux_pin, .quadhd_io_num = -1, .quadwp_io_num = -1,
.max_transfer_sz = 8, .flags = flags_expected};
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
cfg = (spi_bus_config_t){.mosi_io_num = INPUT_ONLY_PIN, .miso_io_num = spi_periph_signal[TEST_SPI_HOST].spiq_iomux_pin, .sclk_io_num = spi_periph_signal[TEST_SPI_HOST].spiclk_iomux_pin, .quadhd_io_num = -1, .quadwp_io_num = -1,
.max_transfer_sz = 8, .flags = flags_expected};
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
#endif
ESP_LOGI(TAG, "check sclk flag...");
flags_expected = SPICOMMON_BUSFLAG_SCLK;
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[TEST_SPI_HOST].spid_iomux_pin, .miso_io_num = spi_periph_signal[TEST_SPI_HOST].spiq_iomux_pin, .sclk_io_num = -1, .quadhd_io_num = spi_periph_signal[TEST_SPI_HOST].spihd_iomux_pin, .quadwp_io_num = spi_periph_signal[TEST_SPI_HOST].spiwp_iomux_pin,
.max_transfer_sz = 8, .flags = flags_expected};
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
ESP_LOGI(TAG, "check mosi flag...");
flags_expected = SPICOMMON_BUSFLAG_MOSI;
cfg = (spi_bus_config_t){.mosi_io_num = -1, .miso_io_num = spi_periph_signal[TEST_SPI_HOST].spiq_iomux_pin, .sclk_io_num = spi_periph_signal[TEST_SPI_HOST].spiclk_iomux_pin, .quadhd_io_num = spi_periph_signal[TEST_SPI_HOST].spihd_iomux_pin, .quadwp_io_num = spi_periph_signal[TEST_SPI_HOST].spiwp_iomux_pin,
.max_transfer_sz = 8, .flags = flags_expected};
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
ESP_LOGI(TAG, "check miso flag...");
flags_expected = SPICOMMON_BUSFLAG_MISO;
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[TEST_SPI_HOST].spid_iomux_pin, .miso_io_num = -1, .sclk_io_num = spi_periph_signal[TEST_SPI_HOST].spiclk_iomux_pin, .quadhd_io_num = spi_periph_signal[TEST_SPI_HOST].spihd_iomux_pin, .quadwp_io_num = spi_periph_signal[TEST_SPI_HOST].spiwp_iomux_pin,
.max_transfer_sz = 8, .flags = flags_expected};
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
ESP_LOGI(TAG, "check quad flag...");
flags_expected = SPICOMMON_BUSFLAG_QUAD;
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[TEST_SPI_HOST].spid_iomux_pin, .miso_io_num = spi_periph_signal[TEST_SPI_HOST].spiq_iomux_pin, .sclk_io_num = spi_periph_signal[TEST_SPI_HOST].spiclk_iomux_pin, .quadhd_io_num = -1, .quadwp_io_num = spi_periph_signal[TEST_SPI_HOST].spiwp_iomux_pin,
.max_transfer_sz = 8, .flags = flags_expected};
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[TEST_SPI_HOST].spid_iomux_pin, .miso_io_num = spi_periph_signal[TEST_SPI_HOST].spiq_iomux_pin, .sclk_io_num = spi_periph_signal[TEST_SPI_HOST].spiclk_iomux_pin, .quadhd_io_num = spi_periph_signal[TEST_SPI_HOST].spihd_iomux_pin, .quadwp_io_num = -1,
.max_transfer_sz = 8, .flags = flags_expected};
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
}
TEST_CASE("SPI Master no response when switch from host1 (HSPI) to host2 (VSPI)", "[spi]")
TEST_CASE("SPI Master no response when switch from host1 (SPI2) to host2 (SPI3)", "[spi]")
{
//spi config
spi_bus_config_t bus_config;
@ -507,30 +507,29 @@ TEST_CASE("SPI Master no response when switch from host1 (HSPI) to host2 (VSPI)"
//initialize for first host
host = TEST_SPI_HOST;
TEST_ASSERT(spi_bus_initialize(host, &bus_config, GET_DMA_CHAN(host)) == ESP_OK);
TEST_ASSERT(spi_bus_add_device(host, &device_config, &spi) == ESP_OK);
TEST_ESP_OK(spi_bus_initialize(host, &bus_config, SPI_DMA_CH_AUTO));
TEST_ESP_OK(spi_bus_add_device(host, &device_config, &spi));
printf("before first xmit\n");
TEST_ASSERT(spi_device_transmit(spi, &transaction) == ESP_OK);
TEST_ESP_OK(spi_device_transmit(spi, &transaction));
printf("after first xmit\n");
TEST_ASSERT(spi_bus_remove_device(spi) == ESP_OK);
TEST_ASSERT(spi_bus_free(host) == ESP_OK);
TEST_ESP_OK(spi_bus_remove_device(spi));
TEST_ESP_OK(spi_bus_free(host));
//for second host and failed before
host = TEST_SLAVE_HOST;
TEST_ASSERT(spi_bus_initialize(host, &bus_config, GET_DMA_CHAN(host)) == ESP_OK);
TEST_ASSERT(spi_bus_add_device(host, &device_config, &spi) == ESP_OK);
TEST_ESP_OK(spi_bus_initialize(host, &bus_config, SPI_DMA_CH_AUTO));
TEST_ESP_OK(spi_bus_add_device(host, &device_config, &spi));
printf("before second xmit\n");
// the original version (bit mis-written) stucks here.
TEST_ASSERT(spi_device_transmit(spi, &transaction) == ESP_OK);
TEST_ESP_OK(spi_device_transmit(spi, &transaction));
// test case success when see this.
printf("after second xmit\n");
TEST_ASSERT(spi_bus_remove_device(spi) == ESP_OK);
TEST_ASSERT(spi_bus_free(host) == ESP_OK);
TEST_ESP_OK(spi_bus_remove_device(spi));
TEST_ESP_OK(spi_bus_free(host));
}
DRAM_ATTR static uint32_t data_dram[80]={0};
@ -588,11 +587,9 @@ TEST_CASE("SPI Master DMA test, TX and RX in different regions", "[spi]")
spi_device_interface_config_t devcfg=SPI_DEVICE_TEST_DEFAULT_CONFIG();
//Initialize the SPI bus
ret=spi_bus_initialize(TEST_SPI_HOST, &buscfg, 1);
TEST_ASSERT(ret==ESP_OK);
TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
//Attach the LCD to the SPI bus
ret=spi_bus_add_device(TEST_SPI_HOST, &devcfg, &spi);
TEST_ASSERT(ret==ESP_OK);
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &spi));
//connect MOSI to two devices breaks the output, fix it.
spitest_gpio_output_sel(buscfg.mosi_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spid_out);
@ -658,7 +655,6 @@ TEST_CASE("SPI Master DMA test: length, start, not aligned", "[spi]")
uint8_t tx_buf[320]={0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0xaa, 0xcc, 0xff, 0xee, 0x55, 0x77, 0x88, 0x43};
uint8_t rx_buf[320];
esp_err_t ret;
spi_device_handle_t spi;
spi_bus_config_t buscfg={
.miso_io_num=PIN_NUM_MOSI,
@ -675,11 +671,9 @@ TEST_CASE("SPI Master DMA test: length, start, not aligned", "[spi]")
.pre_cb=NULL,
};
//Initialize the SPI bus
ret=spi_bus_initialize(TEST_SPI_HOST, &buscfg, 1);
TEST_ASSERT(ret==ESP_OK);
TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
//Attach the LCD to the SPI bus
ret=spi_bus_add_device(TEST_SPI_HOST, &devcfg, &spi);
TEST_ASSERT(ret==ESP_OK);
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &spi));
//connect MOSI to two devices breaks the output, fix it.
spitest_gpio_output_sel(buscfg.mosi_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spid_out);
@ -746,7 +740,7 @@ void test_cmd_addr(spi_slave_task_context_t *slave_context, bool lsb_first)
//initial master, mode 0, 1MHz
spi_bus_config_t buscfg=SPI_BUS_TEST_DEFAULT_CONFIG();
buscfg.quadhd_io_num = UNCONNECTED_PIN;
TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &buscfg, 1));
TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
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;
@ -984,6 +978,8 @@ TEST_CASE("SPI master hd dma TX without RX test", "[spi]")
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &dev_cfg, &spi));
spi_slave_interface_config_t slave_cfg = SPI_SLAVE_TEST_DEFAULT_CONFIG();
printf("TEST_SLAVE_HOST is %d\n", TEST_SLAVE_HOST);
TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &bus_cfg, &slave_cfg, TEST_SLAVE_HOST));
same_pin_func_sel(bus_cfg, dev_cfg, 0);
@ -1076,16 +1072,13 @@ TEST_CASE("SPI master hd dma TX without RX test", "[spi]")
static void speed_setup(spi_device_handle_t* spi, bool use_dma)
{
esp_err_t ret;
spi_bus_config_t buscfg=SPI_BUS_TEST_DEFAULT_CONFIG();
spi_device_interface_config_t devcfg=SPI_DEVICE_TEST_DEFAULT_CONFIG();
devcfg.queue_size=8; //We want to be able to queue 7 transactions at a time
//Initialize the SPI bus and the device to test
ret=spi_bus_initialize(TEST_SPI_HOST, &buscfg, (use_dma? GET_DMA_CHAN(TEST_SPI_HOST): 0));
TEST_ASSERT(ret==ESP_OK);
ret=spi_bus_add_device(TEST_SPI_HOST, &devcfg, spi);
TEST_ASSERT(ret==ESP_OK);
TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &buscfg, (use_dma ? SPI_DMA_CH_AUTO : 0)));
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, spi));
}
static void sorted_array_insert(uint32_t* array, int* size, uint32_t item)

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