mirror of
https://github.com/espressif/esp-idf
synced 2025-03-09 09:09:10 -04:00
Compare commits
105 Commits
ba15ac8634
...
2acbecbb40
Author | SHA1 | Date | |
---|---|---|---|
|
2acbecbb40 | ||
|
8140b10a16 | ||
|
534ca101e4 | ||
|
fa85714845 | ||
|
181e51a596 | ||
|
6c1c6a3e37 | ||
|
4f716817e0 | ||
|
6acb4620b4 | ||
|
e78d06beb2 | ||
|
d680db8ed3 | ||
|
8165bbca55 | ||
|
8051d60d0b | ||
|
0b6fc0b7e8 | ||
|
befd021767 | ||
|
3139ef5ab6 | ||
|
c11d71f06f | ||
|
25a7cdcbd3 | ||
|
8cb6baac6c | ||
|
44c701abb6 | ||
|
fd9bfb42a1 | ||
|
feaf29a340 | ||
|
54b25318cd | ||
|
798b52af1d | ||
|
c0e96ceb34 | ||
|
6e48d5bd6b | ||
|
a3ff680dff | ||
|
dfe5f7432f | ||
|
717627ad1a | ||
|
b5936c8323 | ||
|
81047b02d0 | ||
|
e4995581dc | ||
|
9a59b6379c | ||
|
498c159b55 | ||
|
e5bd4427e3 | ||
|
49a5cd23a4 | ||
|
7c52647243 | ||
|
fd5a63f31e | ||
|
2dec9fadf9 | ||
|
625bd4f767 | ||
|
521c0ef956 | ||
|
28f8ac5f12 | ||
|
76e606ab32 | ||
|
1eab7a033b | ||
|
75d98216a2 | ||
|
eef5add97e | ||
|
43d2a6eeed | ||
|
2318522f04 | ||
|
d474c76556 | ||
|
5a0b570702 | ||
|
2e8abdb814 | ||
|
14977d7561 | ||
|
8732cc6c6b | ||
|
60ad592a23 | ||
|
61bd1eb225 | ||
|
9e0c9be1d4 | ||
|
9645d8d015 | ||
|
f7d023383b | ||
|
5b52358092 | ||
|
52a8f6cdd5 | ||
|
98c1974fb5 | ||
|
dacd74cd0f | ||
|
81e1277559 | ||
|
39528b1783 | ||
|
fa0dc23a71 | ||
|
d5699b08cc | ||
|
d4fd54f8ce | ||
|
e00f6cbde9 | ||
|
5875b03266 | ||
|
0b556de95c | ||
|
b4b57a25b8 | ||
|
e1353a1a0e | ||
|
ce9e615679 | ||
|
1ea757c0f1 | ||
|
8ab23d4395 | ||
|
1cddcd010c | ||
|
1b75fb5622 | ||
|
340a4a95ee | ||
|
82927f768b | ||
|
594f604e7d | ||
|
75916a8758 | ||
|
404ee09181 | ||
|
d480469aa3 | ||
|
faa44d5843 | ||
|
6c01cdc38f | ||
|
07410a1381 | ||
|
33fe673e85 | ||
|
72cbfbf26a | ||
|
6e182d7ed3 | ||
|
023bbe5cb1 | ||
|
e226a65a1f | ||
|
91fa868bd6 | ||
|
29accf2533 | ||
|
50b5ff058c | ||
|
157c27e8cf | ||
|
f49d6bf061 | ||
|
d6cdb3e0ae | ||
|
ea06ee1ad6 | ||
|
5a26d7008d | ||
|
2a359c3ee4 | ||
|
e3954297bb | ||
|
de1a4f0c0d | ||
|
eb01aaacc7 | ||
|
8b2331a810 | ||
|
7443d7d274 | ||
|
d4d308d580 |
3
.gitignore
vendored
3
.gitignore
vendored
@ -88,3 +88,6 @@ build
|
||||
|
||||
# lock files for examples and components
|
||||
dependencies.lock
|
||||
|
||||
# managed_components for examples
|
||||
managed_components
|
||||
|
@ -108,6 +108,7 @@ before_script:
|
||||
before_script:
|
||||
- source tools/ci/utils.sh
|
||||
- apply_bot_filter
|
||||
- export IDF_TOOLS_PATH="${HOME}/.espressif_runner_${CI_RUNNER_ID}_${CI_CONCURRENT_ID}"
|
||||
- $IDF_PATH/tools/idf_tools.py install-python-env
|
||||
# On macOS, these tools need to be installed
|
||||
- $IDF_PATH/tools/idf_tools.py --non-interactive install cmake ninja
|
||||
|
@ -365,6 +365,15 @@ menu "Bootloader config"
|
||||
in this area of memory, you can increase it. It must be a multiple of 4 bytes.
|
||||
This area (rtc_retain_mem_t) is reserved and has access from the bootloader and an application.
|
||||
|
||||
config BOOTLOADER_FLASH_XMC_SUPPORT
|
||||
bool "Enable the support for flash chips of XMC (READ HELP FIRST)"
|
||||
default y
|
||||
help
|
||||
Perform the startup flow recommended by XMC. Please consult XMC for the details of this flow.
|
||||
XMC chips will be forbidden to be used, when this option is disabled.
|
||||
|
||||
DON'T DISABLE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.
|
||||
|
||||
endmenu # Bootloader
|
||||
|
||||
|
||||
|
@ -18,6 +18,19 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Read flash ID by sending RDID command (0x9F)
|
||||
* @return flash raw ID
|
||||
* mfg_id = (ID >> 16) & 0xFF;
|
||||
flash_id = ID & 0xffff;
|
||||
*/
|
||||
uint32_t bootloader_read_flash_id(void);
|
||||
|
||||
#if SOC_CACHE_SUPPORT_WRAP
|
||||
/**
|
||||
* @brief Set the burst mode setting command for specified wrap mode.
|
||||
@ -27,3 +40,22 @@
|
||||
*/
|
||||
esp_err_t bootloader_flash_wrap_set(spi_flash_wrap_mode_t mode);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Unlock Flash write protect.
|
||||
* Please do not call this function in SDK.
|
||||
*
|
||||
* @note This can be overridden because it's attribute weak.
|
||||
*/
|
||||
esp_err_t bootloader_flash_unlock(void);
|
||||
|
||||
/**
|
||||
* @brief Startup flow recommended by XMC. Call at startup before any erase/write operation.
|
||||
*
|
||||
* @return ESP_OK When startup successfully, otherwise ESP_FAIL (indiciating you should reboot before erase/write).
|
||||
*/
|
||||
esp_err_t bootloader_flash_xmc_startup(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -37,6 +37,7 @@
|
||||
#define CMD_RDSR 0x05
|
||||
#define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */
|
||||
#define CMD_OTPEN 0x3A /* Enable OTP mode, not all SPI flash uses this command */
|
||||
#define CMD_RDSFDP 0x5A /* Read the SFDP of the flash */
|
||||
#define CMD_WRAP 0x77 /* Set burst with wrap command */
|
||||
#define CMD_RESUME 0x7A /* Resume command to clear flash suspend bit */
|
||||
|
||||
@ -164,6 +165,15 @@ static inline uint32_t bootloader_cache_pages_to_map(uint32_t size, uint32_t vad
|
||||
*/
|
||||
uint32_t bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len);
|
||||
|
||||
/**
|
||||
* @brief Read the SFDP of the flash
|
||||
*
|
||||
* @param sfdp_addr Address of the parameter to read
|
||||
* @param miso_byte_num Bytes to read
|
||||
* @return The read SFDP, little endian, 4 bytes at most
|
||||
*/
|
||||
uint32_t bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num);
|
||||
|
||||
/**
|
||||
* @brief Enable the flash write protect (WEL bit).
|
||||
*/
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "esp32s2/rom/usb/usb_common.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#include "esp32c3/rom/ets_sys.h"
|
||||
#include "esp32c3/rom/uart.h"
|
||||
#endif
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "esp_rom_uart.h"
|
||||
@ -111,3 +112,11 @@ void bootloader_console_init(void)
|
||||
esp_rom_install_channel_putc(1, bootloader_console_write_char_usb);
|
||||
}
|
||||
#endif //CONFIG_ESP_CONSOLE_USB_CDC
|
||||
|
||||
#ifdef CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
|
||||
void bootloader_console_init(void)
|
||||
{
|
||||
UartDevice *uart = GetUartDevice();
|
||||
uart->buff_uart_no = ESP_ROM_USB_SERIAL_DEVICE_NUM;
|
||||
}
|
||||
#endif //CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
|
||||
|
@ -31,7 +31,9 @@
|
||||
# define SPIFLASH SPIMEM1
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/spi_flash.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/rom/spi_flash.h"
|
||||
@ -39,6 +41,17 @@
|
||||
#include "esp32c3/rom/spi_flash.h"
|
||||
#endif
|
||||
|
||||
#define BYTESHIFT(VAR, IDX) (((VAR) >> ((IDX) * 8)) & 0xFF)
|
||||
#define ISSI_ID 0x9D
|
||||
#define GD_Q_ID_HIGH 0xC8
|
||||
#define GD_Q_ID_MID 0x40
|
||||
#define GD_Q_ID_LOW 0x16
|
||||
|
||||
#define ESP_BOOTLOADER_SPIFLASH_BP_MASK_ISSI (BIT7 | BIT5 | BIT4 | BIT3 | BIT2)
|
||||
#define ESP_BOOTLOADER_SPIFLASH_QE_16B BIT9 // QE position when you write 16 bits at one time.
|
||||
#define ESP_BOOTLOADER_SPIFLASH_QE_8B BIT1 // QE position when you write 8 bits(for SR2) at one time.
|
||||
#define ESP_BOOTLOADER_SPIFLASH_WRITE_8B (8)
|
||||
#define ESP_BOOTLOADER_SPIFLASH_WRITE_16B (16)
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
/* Normal app version maps to esp_spi_flash.h operations...
|
||||
@ -109,7 +122,7 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
|
||||
return spi_flash_erase_range(start_addr, size);
|
||||
}
|
||||
|
||||
#else
|
||||
#else //BOOTLOADER_BUILD
|
||||
/* Bootloader version, uses ROM functions only */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
@ -398,7 +411,7 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
err = spi_to_esp_err(esp_rom_spiflash_unlock());
|
||||
err = bootloader_flash_unlock();
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
@ -440,31 +453,131 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
|
||||
return spi_to_esp_err(rc);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // BOOTLOADER_BUILD
|
||||
|
||||
FORCE_INLINE_ATTR bool is_issi_chip(const esp_rom_spiflash_chip_t* chip)
|
||||
{
|
||||
return BYTESHIFT(chip->device_id, 2) == ISSI_ID;
|
||||
}
|
||||
|
||||
// For GD25Q32, GD25Q64, GD25Q127C, GD25Q128, which use single command to read/write different SR.
|
||||
FORCE_INLINE_ATTR bool is_gd_q_chip(const esp_rom_spiflash_chip_t* chip)
|
||||
{
|
||||
return BYTESHIFT(chip->device_id, 2) == GD_Q_ID_HIGH && BYTESHIFT(chip->device_id, 1) == GD_Q_ID_MID && BYTESHIFT(chip->device_id, 0) >= GD_Q_ID_LOW;
|
||||
}
|
||||
|
||||
esp_err_t IRAM_ATTR __attribute__((weak)) bootloader_flash_unlock(void)
|
||||
{
|
||||
uint16_t status = 0; // status for SR1 or SR1+SR2 if writing SR with 01H + 2Bytes.
|
||||
uint16_t new_status = 0;
|
||||
uint8_t status_sr2 = 0; // status_sr2 for SR2.
|
||||
uint8_t new_status_sr2 = 0;
|
||||
uint8_t write_sr_bit = 0;
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
if (is_issi_chip(&g_rom_flashchip)) {
|
||||
write_sr_bit = ESP_BOOTLOADER_SPIFLASH_WRITE_8B;
|
||||
// ISSI chips have different QE position
|
||||
|
||||
status = bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8);
|
||||
|
||||
/* Clear all bits in the mask.
|
||||
(This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.)
|
||||
*/
|
||||
new_status = status & (~ESP_BOOTLOADER_SPIFLASH_BP_MASK_ISSI);
|
||||
// Skip if nothing needs to be cleared. Otherwise will waste time waiting for the flash to clear nothing.
|
||||
} else if (is_gd_q_chip(&g_rom_flashchip)) {
|
||||
/* The GD chips behaviour is to clear all bits in SR1 and clear bits in SR2 except QE bit.
|
||||
Use 01H to write SR1 and 31H to write SR2.
|
||||
*/
|
||||
write_sr_bit = ESP_BOOTLOADER_SPIFLASH_WRITE_8B;
|
||||
|
||||
status = bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8);
|
||||
new_status = 0;
|
||||
|
||||
status_sr2 = bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8);
|
||||
new_status_sr2 = status_sr2 & ESP_BOOTLOADER_SPIFLASH_QE_8B;
|
||||
} else {
|
||||
/* For common behaviour, like XMC chips, Use 01H+2Bytes to write both SR1 and SR2*/
|
||||
write_sr_bit = ESP_BOOTLOADER_SPIFLASH_WRITE_16B;
|
||||
status = bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8) | (bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8) << 8);
|
||||
|
||||
/* Clear all bits except QE, if it is set.
|
||||
(This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.)
|
||||
*/
|
||||
new_status = status & ESP_BOOTLOADER_SPIFLASH_QE_16B;
|
||||
}
|
||||
|
||||
if (status != new_status) {
|
||||
/* if the status in SR not equal to the ideal status, the status need to be updated */
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
bootloader_execute_flash_command(CMD_WREN, 0, 0, 0);
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
bootloader_execute_flash_command(CMD_WRSR, new_status, write_sr_bit, 0);
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
}
|
||||
|
||||
if (status_sr2 != new_status_sr2) {
|
||||
/* If the status in SR2 not equal to the ideal status, the status need to be updated.
|
||||
It doesn't need to be updated if status in SR2 is 0.
|
||||
Note: if we need to update both SR1 and SR2, the `CMD_WREN` needs to be sent again.
|
||||
*/
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
bootloader_execute_flash_command(CMD_WREN, 0, 0, 0);
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
bootloader_execute_flash_command(CMD_WRSR2, new_status_sr2, write_sr_bit, 0);
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
}
|
||||
|
||||
bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0);
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* dummy_len_plus values defined in ROM for SPI flash configuration */
|
||||
#ifndef g_rom_spiflash_dummy_len_plus // ESP32-C3 uses a macro to access ROM data here
|
||||
extern uint8_t g_rom_spiflash_dummy_len_plus[];
|
||||
#endif
|
||||
uint32_t bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len)
|
||||
IRAM_ATTR static uint32_t bootloader_flash_execute_command_common(
|
||||
uint8_t command,
|
||||
uint32_t addr_len, uint32_t address,
|
||||
uint8_t dummy_len,
|
||||
uint8_t mosi_len, uint32_t mosi_data,
|
||||
uint8_t miso_len)
|
||||
{
|
||||
assert(mosi_len <= 32);
|
||||
assert(miso_len <= 32);
|
||||
uint32_t old_ctrl_reg = SPIFLASH.ctrl.val;
|
||||
uint32_t old_user_reg = SPIFLASH.user.val;
|
||||
uint32_t old_user1_reg = SPIFLASH.user1.val;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.ctrl.val = SPI_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
|
||||
#else
|
||||
SPIFLASH.ctrl.val = SPI_MEM_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
|
||||
#endif
|
||||
SPIFLASH.user.usr_dummy = 0;
|
||||
SPIFLASH.user.usr_addr = 0;
|
||||
//command phase
|
||||
SPIFLASH.user.usr_command = 1;
|
||||
SPIFLASH.user2.usr_command_bitlen = 7;
|
||||
|
||||
SPIFLASH.user2.usr_command_value = command;
|
||||
SPIFLASH.user.usr_miso = miso_len > 0;
|
||||
//addr phase
|
||||
SPIFLASH.user.usr_addr = addr_len > 0;
|
||||
SPIFLASH.user1.usr_addr_bitlen = addr_len - 1;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0;
|
||||
SPIFLASH.addr = (addr_len > 0)? (address << (32-addr_len)) : 0;
|
||||
#else
|
||||
SPIFLASH.miso_dlen.usr_miso_bit_len = miso_len ? (miso_len - 1) : 0;
|
||||
SPIFLASH.addr = address;
|
||||
#endif
|
||||
//dummy phase
|
||||
if (miso_len > 0) {
|
||||
uint32_t total_dummy = dummy_len + g_rom_spiflash_dummy_len_plus[1];
|
||||
SPIFLASH.user.usr_dummy = total_dummy > 0;
|
||||
SPIFLASH.user1.usr_dummy_cyclelen = total_dummy - 1;
|
||||
} else {
|
||||
SPIFLASH.user.usr_dummy = 0;
|
||||
SPIFLASH.user1.usr_dummy_cyclelen = 0;
|
||||
}
|
||||
//output data
|
||||
SPIFLASH.user.usr_mosi = mosi_len > 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0;
|
||||
@ -472,24 +585,52 @@ uint32_t bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, u
|
||||
SPIFLASH.mosi_dlen.usr_mosi_bit_len = mosi_len ? (mosi_len - 1) : 0;
|
||||
#endif
|
||||
SPIFLASH.data_buf[0] = mosi_data;
|
||||
|
||||
if (g_rom_spiflash_dummy_len_plus[1]) {
|
||||
/* When flash pins are mapped via GPIO matrix, need a dummy cycle before reading via MISO */
|
||||
if (miso_len > 0) {
|
||||
SPIFLASH.user.usr_dummy = 1;
|
||||
SPIFLASH.user1.usr_dummy_cyclelen = g_rom_spiflash_dummy_len_plus[1] - 1;
|
||||
} else {
|
||||
SPIFLASH.user.usr_dummy = 0;
|
||||
SPIFLASH.user1.usr_dummy_cyclelen = 0;
|
||||
}
|
||||
}
|
||||
//input data
|
||||
SPIFLASH.user.usr_miso = miso_len > 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0;
|
||||
#else
|
||||
SPIFLASH.miso_dlen.usr_miso_bit_len = miso_len ? (miso_len - 1) : 0;
|
||||
#endif
|
||||
|
||||
SPIFLASH.cmd.usr = 1;
|
||||
while (SPIFLASH.cmd.usr != 0) {
|
||||
}
|
||||
|
||||
SPIFLASH.ctrl.val = old_ctrl_reg;
|
||||
return SPIFLASH.data_buf[0];
|
||||
SPIFLASH.user.val = old_user_reg;
|
||||
SPIFLASH.user1.val = old_user1_reg;
|
||||
|
||||
uint32_t ret = SPIFLASH.data_buf[0];
|
||||
if (miso_len < 32) {
|
||||
//set unused bits to 0
|
||||
ret &= ~(UINT32_MAX << miso_len);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t IRAM_ATTR bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len)
|
||||
{
|
||||
const uint8_t addr_len = 0;
|
||||
const uint8_t address = 0;
|
||||
const uint8_t dummy_len = 0;
|
||||
|
||||
return bootloader_flash_execute_command_common(command, addr_len, address,
|
||||
dummy_len, mosi_len, mosi_data, miso_len);
|
||||
}
|
||||
|
||||
// cmd(0x5A) + 24bit address + 8 cycles dummy
|
||||
uint32_t IRAM_ATTR bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num)
|
||||
{
|
||||
assert(miso_byte_num <= 4);
|
||||
const uint8_t command = CMD_RDSFDP;
|
||||
const uint8_t addr_len = 24;
|
||||
const uint8_t dummy_len = 8;
|
||||
const uint8_t mosi_len = 0;
|
||||
const uint32_t mosi_data = 0;
|
||||
const uint8_t miso_len = miso_byte_num * 8;
|
||||
|
||||
return bootloader_flash_execute_command_common(command, addr_len, sfdp_addr,
|
||||
dummy_len, mosi_len, mosi_data, miso_len);
|
||||
}
|
||||
|
||||
void bootloader_enable_wp(void)
|
||||
@ -497,6 +638,13 @@ void bootloader_enable_wp(void)
|
||||
bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */
|
||||
}
|
||||
|
||||
uint32_t IRAM_ATTR bootloader_read_flash_id(void)
|
||||
{
|
||||
uint32_t id = bootloader_execute_flash_command(CMD_RDID, 0, 0, 24);
|
||||
id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00);
|
||||
return id;
|
||||
}
|
||||
|
||||
#if SOC_CACHE_SUPPORT_WRAP
|
||||
esp_err_t bootloader_flash_wrap_set(spi_flash_wrap_mode_t mode)
|
||||
{
|
||||
@ -528,3 +676,104 @@ esp_err_t bootloader_flash_wrap_set(spi_flash_wrap_mode_t mode)
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif //SOC_CACHE_SUPPORT_WRAP
|
||||
|
||||
/*******************************************************************************
|
||||
* XMC startup flow
|
||||
******************************************************************************/
|
||||
|
||||
#define XMC_SUPPORT CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT
|
||||
#define XMC_VENDOR_ID 0x20
|
||||
|
||||
#if BOOTLOADER_BUILD
|
||||
#define BOOTLOADER_FLASH_LOG(level, ...) ESP_LOG##level(TAG, ##__VA_ARGS__)
|
||||
#else
|
||||
static DRAM_ATTR char bootloader_flash_tag[] = "bootloader_flash";
|
||||
#define BOOTLOADER_FLASH_LOG(level, ...) ESP_DRAM_LOG##level(bootloader_flash_tag, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if XMC_SUPPORT
|
||||
//strictly check the model
|
||||
static IRAM_ATTR bool is_xmc_chip_strict(uint32_t rdid)
|
||||
{
|
||||
uint32_t vendor_id = BYTESHIFT(rdid, 2);
|
||||
uint32_t mfid = BYTESHIFT(rdid, 1);
|
||||
uint32_t cpid = BYTESHIFT(rdid, 0);
|
||||
|
||||
if (vendor_id != XMC_VENDOR_ID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool matched = false;
|
||||
if (mfid == 0x40) {
|
||||
if (cpid >= 0x13 && cpid <= 0x20) {
|
||||
matched = true;
|
||||
}
|
||||
} else if (mfid == 0x41) {
|
||||
if (cpid >= 0x17 && cpid <= 0x20) {
|
||||
matched = true;
|
||||
}
|
||||
} else if (mfid == 0x50) {
|
||||
if (cpid >= 0x15 && cpid <= 0x16) {
|
||||
matched = true;
|
||||
}
|
||||
}
|
||||
return matched;
|
||||
}
|
||||
|
||||
esp_err_t IRAM_ATTR bootloader_flash_xmc_startup(void)
|
||||
{
|
||||
// If the RDID value is a valid XMC one, may skip the flow
|
||||
const bool fast_check = true;
|
||||
if (fast_check && is_xmc_chip_strict(g_rom_flashchip.device_id)) {
|
||||
BOOTLOADER_FLASH_LOG(D, "XMC chip detected by RDID (%08X), skip.", g_rom_flashchip.device_id);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Check the Manufacturer ID in SFDP registers (JEDEC standard). If not XMC chip, no need to run the flow
|
||||
const int sfdp_mfid_addr = 0x10;
|
||||
uint8_t mf_id = (bootloader_flash_read_sfdp(sfdp_mfid_addr, 1) & 0xff);
|
||||
if (mf_id != XMC_VENDOR_ID) {
|
||||
BOOTLOADER_FLASH_LOG(D, "non-XMC chip detected by SFDP Read (%02X), skip.", mf_id);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
BOOTLOADER_FLASH_LOG(I, "XM25QHxxC startup flow");
|
||||
// Enter DPD
|
||||
bootloader_execute_flash_command(0xB9, 0, 0, 0);
|
||||
// Enter UDPD
|
||||
bootloader_execute_flash_command(0x79, 0, 0, 0);
|
||||
// Exit UDPD
|
||||
bootloader_execute_flash_command(0xFF, 0, 0, 0);
|
||||
// Delay tXUDPD
|
||||
esp_rom_delay_us(2000);
|
||||
// Release Power-down
|
||||
bootloader_execute_flash_command(0xAB, 0, 0, 0);
|
||||
esp_rom_delay_us(20);
|
||||
// Read flash ID and check again
|
||||
g_rom_flashchip.device_id = bootloader_read_flash_id();
|
||||
if (!is_xmc_chip_strict(g_rom_flashchip.device_id)) {
|
||||
BOOTLOADER_FLASH_LOG(E, "XMC flash startup fail");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#else
|
||||
//only compare the vendor id
|
||||
static IRAM_ATTR bool is_xmc_chip(uint32_t rdid)
|
||||
{
|
||||
uint32_t vendor_id = (rdid >> 16) & 0xFF;
|
||||
return (vendor_id == XMC_VENDOR_ID);
|
||||
}
|
||||
|
||||
esp_err_t IRAM_ATTR bootloader_flash_xmc_startup(void)
|
||||
{
|
||||
if (is_xmc_chip(g_rom_flashchip.device_id)) {
|
||||
BOOTLOADER_FLASH_LOG(E, "XMC chip detected (%08X) while support disabled.", g_rom_flashchip.device_id);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#endif //XMC_SUPPORT
|
||||
|
@ -260,7 +260,7 @@ static esp_err_t bootloader_init_spi_flash(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_rom_spiflash_unlock();
|
||||
bootloader_flash_unlock();
|
||||
|
||||
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
||||
bootloader_enable_qio_mode();
|
||||
@ -388,6 +388,11 @@ esp_err_t bootloader_init(void)
|
||||
bootloader_print_banner();
|
||||
// update flash ID
|
||||
bootloader_flash_update_id();
|
||||
// Check and run XMC startup flow
|
||||
if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!");
|
||||
goto err;
|
||||
}
|
||||
// read bootloader header
|
||||
if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
|
||||
goto err;
|
||||
|
@ -212,7 +212,7 @@ static esp_err_t bootloader_init_spi_flash(void)
|
||||
#endif
|
||||
|
||||
bootloader_spi_flash_resume();
|
||||
esp_rom_spiflash_unlock();
|
||||
bootloader_flash_unlock();
|
||||
|
||||
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
||||
bootloader_enable_qio_mode();
|
||||
@ -329,6 +329,11 @@ esp_err_t bootloader_init(void)
|
||||
bootloader_print_banner();
|
||||
// update flash ID
|
||||
bootloader_flash_update_id();
|
||||
// Check and run XMC startup flow
|
||||
if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!");
|
||||
goto err;
|
||||
}
|
||||
// read bootloader header
|
||||
if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
|
||||
goto err;
|
||||
|
@ -206,7 +206,7 @@ static esp_err_t bootloader_init_spi_flash(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_rom_spiflash_unlock();
|
||||
bootloader_flash_unlock();
|
||||
|
||||
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
||||
bootloader_enable_qio_mode();
|
||||
@ -310,6 +310,11 @@ esp_err_t bootloader_init(void)
|
||||
bootloader_print_banner();
|
||||
// update flash ID
|
||||
bootloader_flash_update_id();
|
||||
// Check and run XMC startup flow
|
||||
if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!");
|
||||
goto err;
|
||||
}
|
||||
// read bootloader header
|
||||
if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
|
||||
goto err;
|
||||
|
@ -206,7 +206,7 @@ static esp_err_t bootloader_init_spi_flash(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_rom_spiflash_unlock();
|
||||
bootloader_flash_unlock();
|
||||
|
||||
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
||||
bootloader_enable_qio_mode();
|
||||
@ -318,6 +318,11 @@ esp_err_t bootloader_init(void)
|
||||
bootloader_print_banner();
|
||||
// update flash ID
|
||||
bootloader_flash_update_id();
|
||||
// Check and run XMC startup flow
|
||||
if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!");
|
||||
goto err;
|
||||
}
|
||||
// read bootloader header
|
||||
if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
|
||||
goto err;
|
||||
|
@ -111,14 +111,6 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
|
||||
The command passed here is always the on-the-wire command given to the SPI flash unit.
|
||||
*/
|
||||
|
||||
/* dummy_len_plus values defined in ROM for SPI flash configuration */
|
||||
uint32_t bootloader_read_flash_id(void)
|
||||
{
|
||||
uint32_t id = bootloader_execute_flash_command(CMD_RDID, 0, 0, 24);
|
||||
id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00);
|
||||
return id;
|
||||
}
|
||||
|
||||
void bootloader_enable_qio_mode(void)
|
||||
{
|
||||
uint32_t raw_flash_id;
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit cfbb0571fb424ca4a68a0c172cbff1fdc79fd91b
|
||||
Subproject commit 1c6d248b6296473a353047700922534b09d9203f
|
@ -1691,55 +1691,65 @@ int bt_mesh_provisioner_set_heartbeat_filter_info(uint8_t op, uint16_t src, uint
|
||||
}
|
||||
}
|
||||
|
||||
static bool filter_with_rejectlist(struct heartbeat_filter *filter,
|
||||
uint16_t hb_src, uint16_t hb_dst)
|
||||
static bool filter_with_rejectlist(uint16_t hb_src, uint16_t hb_dst)
|
||||
{
|
||||
switch (filter->type) {
|
||||
case HEARTBEAT_FILTER_WITH_SRC:
|
||||
if (hb_src == filter->src) {
|
||||
return true;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hb_rx.filter); i++) {
|
||||
struct heartbeat_filter *filter = &hb_rx.filter[i];
|
||||
|
||||
switch (filter->type) {
|
||||
case HEARTBEAT_FILTER_WITH_SRC:
|
||||
if (hb_src == filter->src) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case HEARTBEAT_FILTER_WITH_DST:
|
||||
if (hb_dst == filter->dst) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case HEARTBEAT_FILTER_WITH_BOTH:
|
||||
if (hb_src == filter->src && hb_dst == filter->dst) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BT_DBG("Unknown filter addr type 0x%02x", filter->type);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case HEARTBEAT_FILTER_WITH_DST:
|
||||
if (hb_dst == filter->dst) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case HEARTBEAT_FILTER_WITH_BOTH:
|
||||
if (hb_src == filter->src && hb_dst == filter->dst) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BT_WARN("Unknown filter addr type 0x%02x", filter->type);
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool filter_with_acceptlist(struct heartbeat_filter *filter,
|
||||
uint16_t hb_src, uint16_t hb_dst)
|
||||
static bool filter_with_acceptlist(uint16_t hb_src, uint16_t hb_dst)
|
||||
{
|
||||
switch (filter->type) {
|
||||
case HEARTBEAT_FILTER_WITH_SRC:
|
||||
if (hb_src == filter->src) {
|
||||
return false;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hb_rx.filter); i++) {
|
||||
struct heartbeat_filter *filter = &hb_rx.filter[i];
|
||||
|
||||
switch (filter->type) {
|
||||
case HEARTBEAT_FILTER_WITH_SRC:
|
||||
if (hb_src == filter->src) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case HEARTBEAT_FILTER_WITH_DST:
|
||||
if (hb_dst == filter->dst) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case HEARTBEAT_FILTER_WITH_BOTH:
|
||||
if (hb_src == filter->src && hb_dst == filter->dst) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BT_DBG("Unknown filter addr type 0x%02x", filter->type);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case HEARTBEAT_FILTER_WITH_DST:
|
||||
if (hb_dst == filter->dst) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case HEARTBEAT_FILTER_WITH_BOTH:
|
||||
if (hb_src == filter->src && hb_dst == filter->dst) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BT_WARN("Unknown filter addr type 0x%02x", filter->type);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1749,26 +1759,20 @@ void bt_mesh_provisioner_heartbeat(uint16_t hb_src, uint16_t hb_dst,
|
||||
uint8_t init_ttl, uint8_t rx_ttl,
|
||||
uint8_t hops, uint16_t feat, int8_t rssi)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (hb_rx.cb == NULL) {
|
||||
BT_DBG("Receiving heartbeat is not enabled");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hb_rx.filter); i++) {
|
||||
struct heartbeat_filter *filter = &hb_rx.filter[i];
|
||||
|
||||
if (hb_rx.type == HEARTBEAT_FILTER_REJECTLIST) {
|
||||
if (filter_with_rejectlist(filter, hb_src, hb_dst)) {
|
||||
BT_DBG("Filtered by rejectlist, src 0x%04x, dst 0x%04x", hb_src, hb_dst);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (filter_with_acceptlist(filter, hb_src, hb_dst)) {
|
||||
BT_DBG("Filtered by acceptlist, src 0x%04x, dst 0x%04x", hb_src, hb_dst);
|
||||
return;
|
||||
}
|
||||
if (hb_rx.type == HEARTBEAT_FILTER_REJECTLIST) {
|
||||
if (filter_with_rejectlist(hb_src, hb_dst)) {
|
||||
BT_INFO("Filtered by rejectlist, src 0x%04x, dst 0x%04x", hb_src, hb_dst);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (filter_with_acceptlist(hb_src, hb_dst)) {
|
||||
BT_INFO("Filtered by acceptlist, src 0x%04x, dst 0x%04x", hb_src, hb_dst);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1026,6 +1026,16 @@ config BT_BLE_ESTAB_LINK_CONN_TOUT
|
||||
Bluetooth Connection establishment maximum time, if connection time exceeds this value, the connection
|
||||
establishment fails, ESP_GATTC_OPEN_EVT or ESP_GATTS_OPEN_EVT is triggered.
|
||||
|
||||
config BT_MAX_DEVICE_NAME_LEN
|
||||
int "length of bluetooth device name"
|
||||
depends on BT_BLUEDROID_ENABLED
|
||||
range 32 248
|
||||
default 32
|
||||
help
|
||||
Bluetooth Device name length shall be no larger than 248 octets, If the broadcast data cannot contain
|
||||
the complete device name, then only the shortname will be displayed, the rest parts that can't fit in
|
||||
will be truncated.
|
||||
|
||||
config BT_BLE_RPA_SUPPORTED
|
||||
bool "Update RPA to Controller"
|
||||
depends on BT_BLUEDROID_ENABLED
|
||||
|
@ -39,13 +39,18 @@ esp_err_t esp_bt_dev_set_device_name(const char *name)
|
||||
if (!name){
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (strlen(name) > ESP_DEV_DEVICE_NAME_MAX) {
|
||||
if (strlen(name) > BTC_MAX_LOC_BD_NAME_LEN) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_DEV;
|
||||
msg.act = BTC_DEV_ACT_SET_DEVICE_NAME;
|
||||
arg.set_dev_name.device_name = (char *)malloc((BTC_MAX_LOC_BD_NAME_LEN + 1) * sizeof(char));
|
||||
if (!arg.set_dev_name.device_name) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
strcpy(arg.set_dev_name.device_name, name);
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_dev_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
|
@ -5364,6 +5364,16 @@ void bta_dm_ble_set_data_length(tBTA_DM_MSG *p_data)
|
||||
APPL_TRACE_ERROR("%s error: Invalid connection remote_bda.", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
p_acl_cb->p_set_pkt_data_cback = p_data->ble_set_data_length.p_set_pkt_data_cback;
|
||||
// if the value of the data length is same, triger callback directly
|
||||
if(p_data->ble_set_data_length.tx_data_length == p_acl_cb->data_length_params.tx_len) {
|
||||
if(p_data->ble_set_data_length.p_set_pkt_data_cback) {
|
||||
(*p_data->ble_set_data_length.p_set_pkt_data_cback)(status, &p_acl_cb->data_length_params);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(p_acl_cb->data_len_updating) {
|
||||
// aleady have one cmd
|
||||
if(p_acl_cb->data_len_waiting) {
|
||||
@ -5376,14 +5386,6 @@ void bta_dm_ble_set_data_length(tBTA_DM_MSG *p_data)
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
p_acl_cb->p_set_pkt_data_cback = p_data->ble_set_data_length.p_set_pkt_data_cback;
|
||||
// if the value of the data length is same, triger callback directly
|
||||
if(p_data->ble_set_data_length.tx_data_length == p_acl_cb->data_length_params.tx_len) {
|
||||
if(p_data->ble_set_data_length.p_set_pkt_data_cback) {
|
||||
(*p_data->ble_set_data_length.p_set_pkt_data_cback)(status, &p_acl_cb->data_length_params);
|
||||
}
|
||||
return;
|
||||
}
|
||||
status = BTM_SetBleDataLength(p_data->ble_set_data_length.remote_bda,
|
||||
p_data->ble_set_data_length.tx_data_length);
|
||||
}
|
||||
|
@ -13,11 +13,30 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include <string.h>
|
||||
#include "osi/allocator.h"
|
||||
#include "bta/bta_api.h"
|
||||
#include "btc/btc_task.h"
|
||||
#include "btc/btc_manage.h"
|
||||
#include "btc/btc_dev.h"
|
||||
|
||||
void btc_dev_arg_deep_free(btc_msg_t *msg)
|
||||
{
|
||||
BTC_TRACE_DEBUG("%s \n", __func__);
|
||||
|
||||
switch (msg->act) {
|
||||
case BTC_DEV_ACT_SET_DEVICE_NAME:{
|
||||
char *device_name = ((btc_dev_args_t *)msg->arg)->set_dev_name.device_name;
|
||||
if (device_name) {
|
||||
osi_free(device_name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BTC_TRACE_DEBUG("Unhandled deep free %d\n", msg->act);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void btc_dev_call_handler(btc_msg_t *msg)
|
||||
{
|
||||
btc_dev_args_t *arg = (btc_dev_args_t *)msg->arg;
|
||||
@ -31,4 +50,6 @@ void btc_dev_call_handler(btc_msg_t *msg)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
btc_dev_arg_deep_free(msg);
|
||||
}
|
||||
|
@ -27,8 +27,7 @@ typedef enum {
|
||||
typedef union {
|
||||
// BTC_BT_GAP_ACT_SET_DEV_NAME
|
||||
struct set_bt_dev_name_args {
|
||||
#define ESP_DEV_DEVICE_NAME_MAX (32)
|
||||
char device_name[ESP_DEV_DEVICE_NAME_MAX + 1];
|
||||
char *device_name;
|
||||
} set_dev_name;
|
||||
} btc_dev_args_t;
|
||||
|
||||
|
@ -149,6 +149,14 @@
|
||||
#endif
|
||||
|
||||
#if CONFIG_BT_CTRL_ESP32
|
||||
|
||||
//Device Nane Maximum Length
|
||||
#ifdef CONFIG_BT_MAX_DEVICE_NAME_LEN
|
||||
#define UC_MAX_LOC_BD_NAME_LEN CONFIG_BT_MAX_DEVICE_NAME_LEN
|
||||
#else
|
||||
#define UC_MAX_LOC_BD_NAME_LEN 64
|
||||
#endif
|
||||
|
||||
//BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP
|
||||
#ifdef CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP
|
||||
#define UC_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP
|
||||
|
@ -827,8 +827,12 @@
|
||||
|
||||
/* Maximum local device name length stored btm database.
|
||||
'0' disables storage of the local name in BTM */
|
||||
#ifndef BTM_MAX_LOC_BD_NAME_LEN
|
||||
#if UC_MAX_LOC_BD_NAME_LEN
|
||||
#define BTM_MAX_LOC_BD_NAME_LEN UC_MAX_LOC_BD_NAME_LEN
|
||||
#define BTC_MAX_LOC_BD_NAME_LEN BTM_MAX_LOC_BD_NAME_LEN
|
||||
#else
|
||||
#define BTM_MAX_LOC_BD_NAME_LEN 64
|
||||
#define BTC_MAX_LOC_BD_NAME_LEN BTM_MAX_LOC_BD_NAME_LEN
|
||||
#endif
|
||||
|
||||
/* Fixed Default String. When this is defined as null string, the device's
|
||||
|
@ -954,8 +954,10 @@ void btm_read_remote_version_complete (UINT8 *p)
|
||||
if (HCI_LE_DATA_LEN_EXT_SUPPORTED(p_acl_cb->peer_le_features)) {
|
||||
uint16_t data_length = controller_get_interface()->get_ble_default_data_packet_length();
|
||||
uint16_t data_txtime = controller_get_interface()->get_ble_default_data_packet_txtime();
|
||||
p_acl_cb->data_len_updating = true;
|
||||
btsnd_hcic_ble_set_data_length(p_acl_cb->hci_handle, data_length, data_txtime);
|
||||
if (data_length != p_acl_cb->data_length_params.tx_len) {
|
||||
p_acl_cb->data_len_updating = true;
|
||||
btsnd_hcic_ble_set_data_length(p_acl_cb->hci_handle, data_length, data_txtime);
|
||||
}
|
||||
}
|
||||
l2cble_notify_le_connection (p_acl_cb->remote_addr);
|
||||
} else {
|
||||
|
@ -523,10 +523,6 @@ tBTM_STATUS BTM_BleStartExtAdv(BOOLEAN enable, UINT8 num, tBTM_BLE_EXT_ADV *ext_
|
||||
end:
|
||||
|
||||
if (!enable && status == BTM_SUCCESS) {
|
||||
// Reset the configure parameters when stop extend adv.
|
||||
for (int i = 0; i < MAX_BLE_ADV_INSTANCE; i++) {
|
||||
extend_adv_cb.inst[i].configured = false;
|
||||
}
|
||||
// disable all ext adv
|
||||
if(num == 0) {
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit aef55bbf636ed580d4d6408a5c2e75d1f70a875e
|
||||
Subproject commit 6a06e0459e43771066160f5cfade55bb749fbacd
|
@ -327,6 +327,14 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
p_i2s_obj[i2s_num]->sample_rate = rate;
|
||||
|
||||
/**
|
||||
* Due to hardware issue, bck division on ESP32/ESP32-S2 should be greater than 8 in slave mode
|
||||
* So the factor need to be an appropriate value
|
||||
*/
|
||||
if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_SLAVE) && !p_i2s_obj[i2s_num]->use_apll) {
|
||||
factor = 64 * bits;
|
||||
}
|
||||
double clkmdiv = (double)I2S_BASE_CLK / (rate * factor);
|
||||
|
||||
if (clkmdiv > 256) {
|
||||
|
@ -505,13 +505,13 @@ static inline SPI_MASTER_ISR_ATTR bool spi_bus_device_is_polling(spi_device_t *d
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
// The interrupt may get invoked by the bus lock.
|
||||
static void spi_bus_intr_enable(void *host)
|
||||
static void SPI_MASTER_ISR_ATTR spi_bus_intr_enable(void *host)
|
||||
{
|
||||
esp_intr_enable(((spi_host_t*)host)->intr);
|
||||
}
|
||||
|
||||
// The interrupt is always disabled by the ISR itself, not exposed
|
||||
static void spi_bus_intr_disable(void *host)
|
||||
static void SPI_MASTER_ISR_ATTR spi_bus_intr_disable(void *host)
|
||||
{
|
||||
esp_intr_disable(((spi_host_t*)host)->intr);
|
||||
}
|
||||
@ -921,13 +921,14 @@ esp_err_t SPI_MASTER_ISR_ATTR spi_device_polling_start(spi_device_handle_t handl
|
||||
{
|
||||
esp_err_t ret;
|
||||
SPI_CHECK(ticks_to_wait == portMAX_DELAY, "currently timeout is not available for polling transactions", ESP_ERR_INVALID_ARG);
|
||||
|
||||
spi_host_t *host = handle->host;
|
||||
ret = check_trans_valid(handle, trans_desc);
|
||||
if (ret!=ESP_OK) return ret;
|
||||
|
||||
SPI_CHECK(!spi_bus_device_is_polling(handle), "Cannot send polling transaction while the previous polling transaction is not terminated.", ESP_ERR_INVALID_STATE );
|
||||
|
||||
/* If device_acquiring_lock is set to handle, it means that the user has already
|
||||
* acquired the bus thanks to the function `spi_device_acquire_bus()`.
|
||||
* In that case, we don't need to take the lock again. */
|
||||
spi_host_t *host = handle->host;
|
||||
if (host->device_acquiring_lock != handle) {
|
||||
ret = spi_bus_lock_acquire_start(handle->dev_lock, ticks_to_wait);
|
||||
} else {
|
||||
|
@ -216,8 +216,12 @@ static void IRAM_ATTR timer_isr_default(void *arg)
|
||||
is_awoken = timer_obj->timer_isr_fun.fn(timer_obj->timer_isr_fun.args);
|
||||
//Clear intrrupt status
|
||||
timer_hal_clear_intr_status(&(timer_obj->hal));
|
||||
//After the alarm has been triggered, we need enable it again, so it is triggered the next time.
|
||||
timer_hal_set_alarm_enable(&(timer_obj->hal), TIMER_ALARM_EN);
|
||||
//If the timer is set to auto reload, we need enable it again, so it is triggered the next time.
|
||||
if (timer_hal_get_auto_reload(&timer_obj->hal)) {
|
||||
timer_hal_set_alarm_enable(&(timer_obj->hal), TIMER_ALARM_EN);
|
||||
} else {
|
||||
timer_hal_set_alarm_enable(&(timer_obj->hal), TIMER_ALARM_DIS);
|
||||
}
|
||||
}
|
||||
}
|
||||
TIMER_EXIT_CRITICAL(&timer_spinlock[timer_obj->timer_isr_fun.isr_timer_group]);
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include <assert.h>
|
||||
#include "esp_efuse_table.h"
|
||||
|
||||
// md5_digest_table 7e5a29e190c8e3a63e1a85a40b50c355
|
||||
// md5_digest_table fe80e03d1417e5757ef89923f8d01d33
|
||||
// This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY.
|
||||
// If you want to change some fields, you need to change esp_efuse_table.csv file
|
||||
// then run `efuse_common_table` or `efuse_custom_table` command it will generate this file.
|
||||
@ -155,10 +155,6 @@ static const esp_efuse_desc_t RD_DIS_SYS_DATA_PART2[] = {
|
||||
{EFUSE_BLK0, 38, 1}, // Read protection for EFUSE_BLK10. SYS_DATA_PART2,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t DIS_RTC_RAM_BOOT[] = {
|
||||
{EFUSE_BLK0, 39, 1}, // Disable boot from RTC RAM,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t DIS_ICACHE[] = {
|
||||
{EFUSE_BLK0, 40, 1}, // Disable Icache,
|
||||
};
|
||||
@ -677,11 +673,6 @@ const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_SYS_DATA_PART2[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_DIS_RTC_RAM_BOOT[] = {
|
||||
&DIS_RTC_RAM_BOOT[0], // Disable boot from RTC RAM
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_DIS_ICACHE[] = {
|
||||
&DIS_ICACHE[0], // Disable Icache
|
||||
NULL
|
||||
|
@ -50,7 +50,6 @@
|
||||
RD_DIS_KEY4, EFUSE_BLK0, 36, 1, Read protection for EFUSE_BLK8. KEY4
|
||||
RD_DIS_KEY5, EFUSE_BLK0, 37, 1, Read protection for EFUSE_BLK9. KEY5
|
||||
RD_DIS_SYS_DATA_PART2, EFUSE_BLK0, 38, 1, Read protection for EFUSE_BLK10. SYS_DATA_PART2
|
||||
DIS_RTC_RAM_BOOT, EFUSE_BLK0, 39, 1, Disable boot from RTC RAM
|
||||
DIS_ICACHE, EFUSE_BLK0, 40, 1, Disable Icache
|
||||
DIS_USB_JTAG, EFUSE_BLK0, 41, 1, Disable USB JTAG
|
||||
DIS_DOWNLOAD_ICACHE, EFUSE_BLK0, 42, 1, Disable Icache in download mode
|
||||
|
Can't render this file because it contains an unexpected character in line 7 and column 87.
|
@ -17,7 +17,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// md5_digest_table 7e5a29e190c8e3a63e1a85a40b50c355
|
||||
// md5_digest_table fe80e03d1417e5757ef89923f8d01d33
|
||||
// This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY.
|
||||
// If you want to change some fields, you need to change esp_efuse_table.csv file
|
||||
// then run `efuse_common_table` or `efuse_custom_table` command it will generate this file.
|
||||
@ -57,7 +57,6 @@ extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY3[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY4[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY5[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_SYS_DATA_PART2[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_RTC_RAM_BOOT[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_ICACHE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_USB_JTAG[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_DOWNLOAD_ICACHE[];
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2017-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.
|
||||
@ -17,7 +17,7 @@
|
||||
#include <assert.h>
|
||||
#include "esp_efuse_table.h"
|
||||
|
||||
// md5_digest_table 6a29c09c943d9cb07bd874af57b5870e
|
||||
// md5_digest_table 32d4e5502110edd26bdad463b5ac1d2d
|
||||
// This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY.
|
||||
// If you want to change some fields, you need to change esp_efuse_table.csv file
|
||||
// then run `efuse_common_table` or `efuse_custom_table` command it will generate this file.
|
||||
@ -27,10 +27,6 @@ static const esp_efuse_desc_t WR_DIS_RD_DIS[] = {
|
||||
{EFUSE_BLK0, 0, 1}, // Write protection for RD_DIS_KEY0 RD_DIS_KEY1 RD_DIS_KEY2 RD_DIS_KEY3 RD_DIS_KEY4 RD_DIS_KEY5 RD_DIS_SYS_DATA_PART2,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t WR_DIS_DIS_RTC_RAM_BOOT[] = {
|
||||
{EFUSE_BLK0, 1, 1}, // Write protection for DIS_RTC_RAM_BOOT,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t WR_DIS_GROUP_1[] = {
|
||||
{EFUSE_BLK0, 2, 1}, // Write protection for DIS_ICACHE DIS_DCACHE DIS_DOWNLOAD_ICACHE DIS_DOWNLOAD_DCACHE DIS_FORCE_DOWNLOAD DIS_USB DIS_CAN SOFT_DIS_JTAG HARD_DIS_JTAG DIS_DOWNLOAD_MANUAL_ENCRYPT,
|
||||
};
|
||||
@ -163,10 +159,6 @@ static const esp_efuse_desc_t RD_DIS_SYS_DATA_PART2[] = {
|
||||
{EFUSE_BLK0, 38, 1}, // Read protection for EFUSE_BLK10. SYS_DATA_PART2,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t DIS_RTC_RAM_BOOT[] = {
|
||||
{EFUSE_BLK0, 39, 1}, // Disable boot from RTC RAM,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t DIS_ICACHE[] = {
|
||||
{EFUSE_BLK0, 40, 1}, // Disable Icache,
|
||||
};
|
||||
@ -461,11 +453,6 @@ const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_RD_DIS[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_DIS_RTC_RAM_BOOT[] = {
|
||||
&WR_DIS_DIS_RTC_RAM_BOOT[0], // Write protection for DIS_RTC_RAM_BOOT
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_GROUP_1[] = {
|
||||
&WR_DIS_GROUP_1[0], // Write protection for DIS_ICACHE DIS_DCACHE DIS_DOWNLOAD_ICACHE DIS_DOWNLOAD_DCACHE DIS_FORCE_DOWNLOAD DIS_USB DIS_CAN SOFT_DIS_JTAG HARD_DIS_JTAG DIS_DOWNLOAD_MANUAL_ENCRYPT
|
||||
NULL
|
||||
@ -631,11 +618,6 @@ const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_SYS_DATA_PART2[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_DIS_RTC_RAM_BOOT[] = {
|
||||
&DIS_RTC_RAM_BOOT[0], // Disable boot from RTC RAM
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_DIS_ICACHE[] = {
|
||||
&DIS_ICACHE[0], // Disable Icache
|
||||
NULL
|
||||
|
@ -14,7 +14,6 @@
|
||||
# EFUSE_RD_WR_DIS_REG #
|
||||
# EFUSE_WR_DIS [WR_DIS 0 32] #
|
||||
WR_DIS_RD_DIS, EFUSE_BLK0, 0, 1, Write protection for RD_DIS_KEY0 RD_DIS_KEY1 RD_DIS_KEY2 RD_DIS_KEY3 RD_DIS_KEY4 RD_DIS_KEY5 RD_DIS_SYS_DATA_PART2
|
||||
WR_DIS_DIS_RTC_RAM_BOOT, EFUSE_BLK0, 1, 1, Write protection for DIS_RTC_RAM_BOOT
|
||||
WR_DIS_GROUP_1, EFUSE_BLK0, 2, 1, Write protection for DIS_ICACHE DIS_DCACHE DIS_DOWNLOAD_ICACHE DIS_DOWNLOAD_DCACHE DIS_FORCE_DOWNLOAD DIS_USB DIS_CAN SOFT_DIS_JTAG HARD_DIS_JTAG DIS_DOWNLOAD_MANUAL_ENCRYPT
|
||||
WR_DIS_GROUP_2, EFUSE_BLK0, 3, 1, Write protection for VDD_SPI_XPD VDD_SPI_TIEH VDD_SPI_FORCE VDD_SPI_INIT VDD_SPI_DCAP WDT_DELAY_SEL
|
||||
WR_DIS_SPI_BOOT_CRYPT_CNT, EFUSE_BLK0, 4, 1, Write protection for SPI_BOOT_CRYPT_CNT
|
||||
@ -51,7 +50,6 @@
|
||||
RD_DIS_KEY4, EFUSE_BLK0, 36, 1, Read protection for EFUSE_BLK8. KEY4
|
||||
RD_DIS_KEY5, EFUSE_BLK0, 37, 1, Read protection for EFUSE_BLK9. KEY5
|
||||
RD_DIS_SYS_DATA_PART2, EFUSE_BLK0, 38, 1, Read protection for EFUSE_BLK10. SYS_DATA_PART2
|
||||
DIS_RTC_RAM_BOOT, EFUSE_BLK0, 39, 1, Disable boot from RTC RAM
|
||||
DIS_ICACHE, EFUSE_BLK0, 40, 1, Disable Icache
|
||||
DIS_DCACHE, EFUSE_BLK0, 41, 1, Disable Dcace
|
||||
DIS_DOWNLOAD_ICACHE, EFUSE_BLK0, 42, 1, Disable Icache in download mode include boot_mode 0 1 2 3 6 7
|
||||
|
Can't render this file because it contains an unexpected character in line 8 and column 53.
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2017-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.
|
||||
@ -17,7 +17,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// md5_digest_table 6a29c09c943d9cb07bd874af57b5870e
|
||||
// md5_digest_table 32d4e5502110edd26bdad463b5ac1d2d
|
||||
// This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY.
|
||||
// If you want to change some fields, you need to change esp_efuse_table.csv file
|
||||
// then run `efuse_common_table` or `efuse_custom_table` command it will generate this file.
|
||||
@ -25,7 +25,6 @@ extern "C" {
|
||||
|
||||
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_RD_DIS[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_DIS_RTC_RAM_BOOT[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_GROUP_1[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_GROUP_2[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT[];
|
||||
@ -59,7 +58,6 @@ extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY3[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY4[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY5[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_SYS_DATA_PART2[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_RTC_RAM_BOOT[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_ICACHE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_DCACHE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_DOWNLOAD_ICACHE[];
|
||||
|
@ -24,4 +24,5 @@ PROVIDE ( SYSCON = 0x60026000 );
|
||||
PROVIDE ( TWAI = 0x6002B000 );
|
||||
PROVIDE ( GPSPI4 = 0x60037000 );
|
||||
PROVIDE ( APB_SARADC = 0x60040000 );
|
||||
PROVIDE ( USB_SERIAL_JTAG = 0x60043000 );
|
||||
PROVIDE ( GDMA = 0x6003F000 );
|
||||
|
@ -106,7 +106,7 @@ void IRAM_ATTR esp_restart_noos(void)
|
||||
|
||||
// Reset timer/spi/uart
|
||||
SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG,
|
||||
SYSTEM_TIMERS_RST | SYSTEM_SPI01_RST | SYSTEM_UART_RST);
|
||||
SYSTEM_TIMERS_RST | SYSTEM_SPI01_RST | SYSTEM_UART_RST | SYSTEM_SYSTIMER_RST);
|
||||
REG_WRITE(SYSTEM_PERIP_RST_EN0_REG, 0);
|
||||
// Reset dma
|
||||
SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST);
|
||||
|
@ -73,9 +73,12 @@ menu "Common ESP-related"
|
||||
- If "None" is selected, there will be no console output on any UART, except
|
||||
for initial output from ROM bootloader. This ROM output can be suppressed by
|
||||
GPIO strapping or EFUSE, refer to chip datasheet for details.
|
||||
- On chips with USB peripheral, "USB CDC" option redirects output to the
|
||||
- On chips with USB OTG peripheral, "USB CDC" option redirects output to the
|
||||
CDC port. This option uses the CDC driver in the chip ROM.
|
||||
This option is incompatible with TinyUSB stack.
|
||||
- On chips with an USB serial/JTAG debug controller, selecting the option
|
||||
for that redirects output to the CDC/ACM (serial port emulation) component
|
||||
of that device.
|
||||
config ESP_CONSOLE_UART_DEFAULT
|
||||
bool "Default: UART0"
|
||||
config ESP_CONSOLE_USB_CDC
|
||||
@ -83,6 +86,9 @@ menu "Common ESP-related"
|
||||
# The naming is confusing: USB_ENABLED means that TinyUSB driver is enabled, not USB in general.
|
||||
# && !USB_ENABLED is because the ROM CDC driver is currently incompatible with TinyUSB.
|
||||
depends on IDF_TARGET_ESP32S2 && !USB_ENABLED
|
||||
config ESP_CONSOLE_USB_SERIAL_JTAG
|
||||
bool "USB Serial/JTAG Controller"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config ESP_CONSOLE_UART_CUSTOM
|
||||
bool "Custom UART"
|
||||
config ESP_CONSOLE_NONE
|
||||
|
@ -61,11 +61,11 @@ void esp_reset_reason_set_hint(esp_reset_reason_t hint);
|
||||
*/
|
||||
esp_reset_reason_t esp_reset_reason_get_hint(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the time in microseconds since startup
|
||||
*
|
||||
* @returns time since startup in microseconds
|
||||
* @returns time since g_startup_time; definition should be fixed by system time provider
|
||||
* no matter the underlying timer used.
|
||||
*/
|
||||
int64_t esp_system_get_time(void);
|
||||
|
||||
|
@ -1,26 +1,22 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEZTCCA02gAwIBAgIQQAF1BIMUpMghjISpDBbN3zANBgkqhkiG9w0BAQsFADA/
|
||||
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
|
||||
DkRTVCBSb290IENBIFgzMB4XDTIwMTAwNzE5MjE0MFoXDTIxMDkyOTE5MjE0MFow
|
||||
MjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxCzAJBgNVBAMT
|
||||
AlIzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuwIVKMz2oJTTDxLs
|
||||
jVWSw/iC8ZmmekKIp10mqrUrucVMsa+Oa/l1yKPXD0eUFFU1V4yeqKI5GfWCPEKp
|
||||
Tm71O8Mu243AsFzzWTjn7c9p8FoLG77AlCQlh/o3cbMT5xys4Zvv2+Q7RVJFlqnB
|
||||
U840yFLuta7tj95gcOKlVKu2bQ6XpUA0ayvTvGbrZjR8+muLj1cpmfgwF126cm/7
|
||||
gcWt0oZYPRfH5wm78Sv3htzB2nFd1EbjzK0lwYi8YGd1ZrPxGPeiXOZT/zqItkel
|
||||
/xMY6pgJdz+dU/nPAeX1pnAXFK9jpP+Zs5Od3FOnBv5IhR2haa4ldbsTzFID9e1R
|
||||
oYvbFQIDAQABo4IBaDCCAWQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8E
|
||||
BAMCAYYwSwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5p
|
||||
ZGVudHJ1c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTE
|
||||
p7Gkeyxx+tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEE
|
||||
AYLfEwEBATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2Vu
|
||||
Y3J5cHQub3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0
|
||||
LmNvbS9EU1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYf
|
||||
r52LFMLGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjANBgkqhkiG9w0B
|
||||
AQsFAAOCAQEA2UzgyfWEiDcx27sT4rP8i2tiEmxYt0l+PAK3qB8oYevO4C5z70kH
|
||||
ejWEHx2taPDY/laBL21/WKZuNTYQHHPD5b1tXgHXbnL7KqC401dk5VvCadTQsvd8
|
||||
S8MXjohyc9z9/G2948kLjmE6Flh9dDYrVYA9x2O+hEPGOaEOa1eePynBgPayvUfL
|
||||
qjBstzLhWVQLGAkXXmNs+5ZnPBxzDJOLxhF2JIbeQAcH5H0tZrUlo5ZYyOqA7s9p
|
||||
O5b85o3AM/OJ+CktFBQtfvBhcJVd9wvlwPsk+uyOy2HI7mNxKKgsBTt375teA2Tw
|
||||
UdHkhVNcsAKX1H7GNNLOEADksd86wuoXvg==
|
||||
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
|
||||
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
|
||||
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
|
||||
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
|
||||
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
|
||||
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
|
||||
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
|
||||
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
|
||||
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
|
||||
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
|
||||
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
|
||||
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
|
||||
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
|
||||
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
|
||||
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
|
||||
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
|
||||
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
|
||||
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
|
||||
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
|
||||
-----END CERTIFICATE-----
|
||||
|
@ -39,6 +39,11 @@ void esp_gdbstub_putchar(int c)
|
||||
REG_WRITE(UART_FIFO_REG(UART_NUM), c);
|
||||
}
|
||||
|
||||
void esp_gdbstub_flush()
|
||||
{
|
||||
//not needed for uart
|
||||
}
|
||||
|
||||
int esp_gdbstub_readmem(intptr_t addr)
|
||||
{
|
||||
if (addr < 0x20000000 || addr >= 0x80000000) {
|
||||
|
@ -1,20 +1,15 @@
|
||||
// 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.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
#include "soc/uart_periph.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/usb_serial_jtag_struct.h"
|
||||
#include "hal/usb_serial_jtag_ll.h"
|
||||
#include "esp_gdbstub_common.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
@ -60,6 +55,33 @@ void esp_gdbstub_target_init()
|
||||
{
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
|
||||
|
||||
int esp_gdbstub_getchar()
|
||||
{
|
||||
uint8_t c;
|
||||
//retry the read until we succeed
|
||||
while (usb_serial_jtag_ll_read_rxfifo(&c, 1)==0) ;
|
||||
return c;
|
||||
}
|
||||
|
||||
void esp_gdbstub_putchar(int c)
|
||||
{
|
||||
uint8_t cc=c;
|
||||
//retry the write until we succeed
|
||||
while (usb_serial_jtag_ll_write_txfifo(&cc, 1)<1) ;
|
||||
}
|
||||
|
||||
void esp_gdbstub_flush()
|
||||
{
|
||||
usb_serial_jtag_ll_txfifo_flush();
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
//assume UART gdbstub channel
|
||||
|
||||
int esp_gdbstub_getchar()
|
||||
{
|
||||
while (REG_GET_FIELD(UART_STATUS_REG(UART_NUM), UART_RXFIFO_CNT) == 0) {
|
||||
@ -76,6 +98,13 @@ void esp_gdbstub_putchar(int c)
|
||||
REG_WRITE(UART_FIFO_AHB_REG(UART_NUM), c);
|
||||
}
|
||||
|
||||
void esp_gdbstub_flush()
|
||||
{
|
||||
//not needed for uart
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int esp_gdbstub_readmem(intptr_t addr)
|
||||
{
|
||||
if (!check_inside_valid_region(addr)) {
|
||||
@ -86,3 +115,26 @@ int esp_gdbstub_readmem(intptr_t addr)
|
||||
uint32_t shift = (addr & 3) * 8;
|
||||
return (val_aligned >> shift) & 0xff;
|
||||
}
|
||||
|
||||
int esp_gdbstub_writemem(unsigned int addr, unsigned char data)
|
||||
{
|
||||
if (!check_inside_valid_region(addr)) {
|
||||
/* see esp_cpu_configure_region_protection */
|
||||
return -1;
|
||||
}
|
||||
|
||||
int *i = (int *)(addr & (~3));
|
||||
if ((addr & 3) == 0) {
|
||||
*i = (*i & 0xffffff00) | (data << 0);
|
||||
}
|
||||
if ((addr & 3) == 1) {
|
||||
*i = (*i & 0xffff00ff) | (data << 8);
|
||||
}
|
||||
if ((addr & 3) == 2) {
|
||||
*i = (*i & 0xff00ffff) | (data << 16);
|
||||
}
|
||||
if ((addr & 3) == 3) {
|
||||
*i = (*i & 0x00ffffff) | (data << 24);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -39,6 +39,11 @@ void esp_gdbstub_putchar(int c)
|
||||
REG_WRITE(UART_FIFO_AHB_REG(UART_NUM), c);
|
||||
}
|
||||
|
||||
void esp_gdbstub_flush()
|
||||
{
|
||||
//not needed for uart
|
||||
}
|
||||
|
||||
int esp_gdbstub_readmem(intptr_t addr)
|
||||
{
|
||||
if (addr < 0x20000000 || addr >= 0x80000000) {
|
||||
|
@ -39,6 +39,11 @@ void esp_gdbstub_putchar(int c)
|
||||
REG_WRITE(UART_FIFO_AHB_REG(UART_NUM), c);
|
||||
}
|
||||
|
||||
void esp_gdbstub_flush()
|
||||
{
|
||||
//not needed for uart
|
||||
}
|
||||
|
||||
int esp_gdbstub_readmem(intptr_t addr)
|
||||
{
|
||||
if (addr < 0x20000000 || addr >= 0x80000000) {
|
||||
|
@ -119,6 +119,11 @@ void esp_gdbstub_putchar(int c);
|
||||
*/
|
||||
int esp_gdbstub_readmem(intptr_t addr);
|
||||
|
||||
/**
|
||||
* Make sure all bytes sent using putchar() end up at the host.
|
||||
* (Usually stubbed for UART, but can be useful for other channels)
|
||||
*/
|
||||
void esp_gdbstub_flush(void);
|
||||
|
||||
/**** GDB packet related functions ****/
|
||||
|
||||
|
@ -64,6 +64,7 @@ void esp_gdbstub_send_end(void)
|
||||
{
|
||||
esp_gdbstub_putchar('#');
|
||||
esp_gdbstub_send_hex(s_chsum, 8);
|
||||
esp_gdbstub_flush();
|
||||
}
|
||||
|
||||
// Send a packet with a string as content
|
||||
|
@ -61,16 +61,16 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
if (cal_clk == RTC_CAL_8MD256) {
|
||||
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN);
|
||||
}
|
||||
/* Prepare calibration */
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cal_clk);
|
||||
/* There may be another calibration process already running during we call this function,
|
||||
* so we should wait the last process is done.
|
||||
*/
|
||||
if (!GET_PERI_REG_MASK(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT)) {
|
||||
if (GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING)) {
|
||||
while (!GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY));
|
||||
}
|
||||
if (GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING)) {
|
||||
while (!GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY)
|
||||
&& !GET_PERI_REG_MASK(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT));
|
||||
}
|
||||
|
||||
/* Prepare calibration */
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cal_clk);
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles);
|
||||
/* Figure out how long to wait for calibration to finish */
|
||||
|
@ -66,6 +66,8 @@ void rtc_init(rtc_config_t cfg)
|
||||
/* Reset RTC bias to default value (needed if waking up from deep sleep) */
|
||||
REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_WAK, RTC_CNTL_DBIAS_1V10);
|
||||
REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_SLP, RTC_CNTL_DBIAS_1V10);
|
||||
/* Recover default wait cycle for touch or COCPU after wakeup from deep sleep. */
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER2_REG, RTC_CNTL_ULPCP_TOUCH_START_WAIT, RTC_CNTL_ULPCP_TOUCH_START_WAIT_DEFAULT);
|
||||
|
||||
if (cfg.clkctl_init) {
|
||||
//clear CMMU clock force on
|
||||
|
@ -138,6 +138,8 @@ void rtc_sleep_init(rtc_sleep_config_t cfg)
|
||||
|
||||
REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_DEEP_SLP_REJECT_EN, cfg.deep_slp_reject);
|
||||
REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_LIGHT_SLP_REJECT_EN, cfg.light_slp_reject);
|
||||
/* Set wait cycle for touch or COCPU after deep sleep and light sleep. */
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER2_REG, RTC_CNTL_ULPCP_TOUCH_START_WAIT, RTC_CNTL_ULPCP_TOUCH_START_WAIT_IN_SLEEP);
|
||||
|
||||
REG_SET_FIELD(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_XTL_FORCE_PU, cfg.xtal_fpu);
|
||||
}
|
||||
@ -157,8 +159,6 @@ void rtc_sleep_set_wakeup_time(uint64_t t)
|
||||
/* Read back 'reject' status when waking from light or deep sleep */
|
||||
static uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu);
|
||||
|
||||
static const unsigned DEEP_SLEEP_TOUCH_WAIT_CYCLE = 0xFF;
|
||||
|
||||
uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu)
|
||||
{
|
||||
REG_SET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA, wakeup_opt);
|
||||
@ -170,9 +170,6 @@ uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp
|
||||
SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG,
|
||||
RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR);
|
||||
|
||||
/* Set wait cycle for touch or COCPU after deep sleep. */
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER2_REG, RTC_CNTL_ULPCP_TOUCH_START_WAIT, DEEP_SLEEP_TOUCH_WAIT_CYCLE);
|
||||
|
||||
/* Start entry into sleep mode */
|
||||
SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SLEEP_EN);
|
||||
|
||||
@ -233,23 +230,17 @@ uint32_t rtc_deep_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt)
|
||||
"s32i a2, %4, 0\n"
|
||||
"memw\n"
|
||||
|
||||
/* Set wait cycle for touch or COCPU after deep sleep (can be moved to C code part?) */
|
||||
"l32i a2, %5, 0\n"
|
||||
"and a2, a2, %6\n"
|
||||
"or a2, a2, %7\n"
|
||||
"s32i a2, %5, 0\n"
|
||||
|
||||
/* Set register bit to go into deep sleep */
|
||||
"l32i a2, %8, 0\n"
|
||||
"or a2, a2, %9\n"
|
||||
"s32i a2, %8, 0\n"
|
||||
"l32i a2, %5, 0\n"
|
||||
"or a2, a2, %6\n"
|
||||
"s32i a2, %5, 0\n"
|
||||
"memw\n"
|
||||
|
||||
/* Wait for sleep reject interrupt (never finishes if successful) */
|
||||
".Lwaitsleep:"
|
||||
"memw\n"
|
||||
"l32i a2, %10, 0\n"
|
||||
"and a2, a2, %11\n"
|
||||
"l32i a2, %7, 0\n"
|
||||
"and a2, a2, %8\n"
|
||||
"beqz a2, .Lwaitsleep\n"
|
||||
|
||||
:
|
||||
@ -260,13 +251,10 @@ uint32_t rtc_deep_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt)
|
||||
"r" (DPORT_RTC_MEM_CRC_START), // %2
|
||||
"r" (DPORT_RTC_FASTMEM_CRC_REG), // %3
|
||||
"r" (RTC_MEMORY_CRC_REG), // %4
|
||||
"r" (RTC_CNTL_TIMER2_REG), // %5
|
||||
"r" (~RTC_CNTL_ULPCP_TOUCH_START_WAIT_M), // %6
|
||||
"r" (DEEP_SLEEP_TOUCH_WAIT_CYCLE << RTC_CNTL_ULPCP_TOUCH_START_WAIT_S), // %7
|
||||
"r" (RTC_CNTL_STATE0_REG), // %8
|
||||
"r" (RTC_CNTL_SLEEP_EN), // %9
|
||||
"r" (RTC_CNTL_INT_RAW_REG), // %10
|
||||
"r" (RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW) // %11
|
||||
"r" (RTC_CNTL_STATE0_REG), // %5
|
||||
"r" (RTC_CNTL_SLEEP_EN), // %6
|
||||
"r" (RTC_CNTL_INT_RAW_REG), // %7
|
||||
"r" (RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW) // %8
|
||||
: "a2" // working register
|
||||
);
|
||||
|
||||
@ -285,5 +273,9 @@ static uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu)
|
||||
rtc_sleep_pd_config_t pd_cfg = RTC_SLEEP_PD_CONFIG_ALL(0);
|
||||
rtc_sleep_pd(pd_cfg);
|
||||
}
|
||||
|
||||
/* Recover default wait cycle for touch or COCPU after wakeup. */
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER2_REG, RTC_CNTL_ULPCP_TOUCH_START_WAIT, RTC_CNTL_ULPCP_TOUCH_START_WAIT_DEFAULT);
|
||||
|
||||
return reject;
|
||||
}
|
||||
|
@ -38,16 +38,16 @@
|
||||
*/
|
||||
static uint32_t rtc_clk_cal_internal_oneoff(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
{
|
||||
/* Prepare calibration */
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cal_clk);
|
||||
/* There may be another calibration process already running during we call this function,
|
||||
* so we should wait the last process is done.
|
||||
*/
|
||||
if (!GET_PERI_REG_MASK(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT)) {
|
||||
if (GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING)) {
|
||||
while (!GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY));
|
||||
}
|
||||
if (GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING)) {
|
||||
while (!GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY)
|
||||
&& !GET_PERI_REG_MASK(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT));
|
||||
}
|
||||
|
||||
/* Prepare calibration */
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cal_clk);
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles);
|
||||
/* Figure out how long to wait for calibration to finish */
|
||||
|
@ -60,16 +60,16 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
if (cal_clk == RTC_CAL_8MD256) {
|
||||
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN);
|
||||
}
|
||||
/* Prepare calibration */
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cal_clk);
|
||||
/* There may be another calibration process already running during we call this function,
|
||||
* so we should wait the last process is done.
|
||||
*/
|
||||
if (!GET_PERI_REG_MASK(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT)) {
|
||||
if (GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING)) {
|
||||
while (!GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY));
|
||||
}
|
||||
if (GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING)) {
|
||||
while (!GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY)
|
||||
&& !GET_PERI_REG_MASK(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT));
|
||||
}
|
||||
|
||||
/* Prepare calibration */
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cal_clk);
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles);
|
||||
/* Figure out how long to wait for calibration to finish */
|
||||
|
@ -327,7 +327,7 @@ TEST_CASE("Test rtc clk calibration compensation", "[rtc_clk]")
|
||||
// so that t2 > t1 remains true
|
||||
int64_t t2 = esp_rtc_get_time_us();
|
||||
|
||||
TEST_ASSERT(t2 > t1);
|
||||
TEST_ASSERT_GREATER_THAN(t1, t2);
|
||||
|
||||
// Restore calibration value
|
||||
esp_clk_slowclk_cal_set(esp_clk_slowclk_cal_get() * 2);
|
||||
@ -337,7 +337,7 @@ TEST_CASE("Test rtc clk calibration compensation", "[rtc_clk]")
|
||||
|
||||
t2 = esp_rtc_get_time_us();
|
||||
|
||||
TEST_ASSERT(t2 > t1);
|
||||
TEST_ASSERT_GREATER_THAN(t1, t2);
|
||||
}
|
||||
|
||||
static void trigger_deepsleep(void)
|
||||
@ -364,7 +364,7 @@ static void check_time_deepsleep_1(void)
|
||||
RESET_REASON reason = rtc_get_reset_reason(0);
|
||||
TEST_ASSERT(reason == DEEPSLEEP_RESET);
|
||||
int64_t end = esp_rtc_get_time_us();
|
||||
TEST_ASSERT(end > start);
|
||||
TEST_ASSERT_GREATER_THAN(start, end);
|
||||
|
||||
esp_clk_slowclk_cal_set(esp_clk_slowclk_cal_get() * 2);
|
||||
|
||||
@ -384,7 +384,7 @@ static void check_time_deepsleep_2(void)
|
||||
RESET_REASON reason = rtc_get_reset_reason(0);
|
||||
TEST_ASSERT(reason == DEEPSLEEP_RESET);
|
||||
int64_t end = esp_rtc_get_time_us();
|
||||
TEST_ASSERT(end > start);
|
||||
TEST_ASSERT_GREATER_THAN(start, end);
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_STAGES("Test rtc clk calibration compensation across deep sleep", "[rtc_clk][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET]", trigger_deepsleep, check_time_deepsleep_1, check_time_deepsleep_2);
|
||||
|
@ -19,3 +19,4 @@
|
||||
#define ESP_ROM_HAS_JPEG_DECODE (1) // ROM has JPEG decode library
|
||||
#define ESP_ROM_UART_CLK_IS_XTAL (1) // UART clock source is selected to XTAL in ROM
|
||||
#define ESP_ROM_HAS_RETARGETABLE_LOCKING (1) // ROM was built with retargetable locking
|
||||
#define ESP_ROM_USB_SERIAL_DEVICE_NUM (3) // UART uses USB_SERIAL_JTAG port in ROM.
|
||||
|
@ -260,7 +260,7 @@ esp_rom_spiflash_result_t esp_rom_spiflash_read_status(esp_rom_spiflash_chip_t *
|
||||
esp_rom_spiflash_result_t esp_rom_spiflash_read_statushigh(esp_rom_spiflash_chip_t *spi, uint32_t *status);
|
||||
|
||||
/**
|
||||
* @brief Write status to Falsh status register.
|
||||
* @brief Write status to Flash status register.
|
||||
* Please do not call this function in SDK.
|
||||
*
|
||||
* @param esp_rom_spiflash_chip_t *spi : The information for Flash, which is exported from ld file.
|
||||
|
@ -93,8 +93,8 @@ typedef enum {
|
||||
RTCWDT_CPU_RESET = 13, /**<13, RTC Watch dog Reset CPU*/
|
||||
RTCWDT_BROWN_OUT_RESET = 15, /**<15, Reset when the vdd voltage is not stable*/
|
||||
RTCWDT_RTC_RESET = 16, /**<16, RTC Watch dog reset digital core and rtc module*/
|
||||
TG1WDT_CPU_RESET = 17, /**<11, Time Group1 reset CPU*/
|
||||
SUPER_WDT_RESET = 18, /**<11, super watchdog reset digital core and rtc module*/
|
||||
TG1WDT_CPU_RESET = 17, /**<17, Time Group1 reset CPU*/
|
||||
SUPER_WDT_RESET = 18, /**<18, super watchdog reset digital core and rtc module*/
|
||||
} RESET_REASON;
|
||||
|
||||
typedef enum {
|
||||
|
@ -40,7 +40,6 @@ typedef struct {
|
||||
#define ESP_ROM_SPIFLASH_BP2 BIT4
|
||||
#define ESP_ROM_SPIFLASH_WR_PROTECT (ESP_ROM_SPIFLASH_BP0|ESP_ROM_SPIFLASH_BP1|ESP_ROM_SPIFLASH_BP2)
|
||||
#define ESP_ROM_SPIFLASH_QE BIT9
|
||||
#define ESP_ROM_SPIFLASH_BP_MASK_ISSI (BIT7 | BIT5 | BIT4 | BIT3 | BIT2)
|
||||
|
||||
#define FLASH_OP_MODE_RDCMD_DOUT 0x3B
|
||||
#define ESP_ROM_FLASH_SECTOR_SIZE 0x1000
|
||||
|
@ -119,7 +119,6 @@ extern "C" {
|
||||
#define ESP_ROM_SPIFLASH_BP2 BIT4
|
||||
#define ESP_ROM_SPIFLASH_WR_PROTECT (ESP_ROM_SPIFLASH_BP0|ESP_ROM_SPIFLASH_BP1|ESP_ROM_SPIFLASH_BP2)
|
||||
#define ESP_ROM_SPIFLASH_QE BIT9
|
||||
#define ESP_ROM_SPIFLASH_BP_MASK_ISSI (BIT7 | BIT5 | BIT4 | BIT3 | BIT2)
|
||||
|
||||
#define FLASH_ID_GD25LQ32C 0xC86016
|
||||
|
||||
|
@ -111,7 +111,6 @@ extern "C" {
|
||||
#define ESP_ROM_SPIFLASH_BP2 BIT4
|
||||
#define ESP_ROM_SPIFLASH_WR_PROTECT (ESP_ROM_SPIFLASH_BP0|ESP_ROM_SPIFLASH_BP1|ESP_ROM_SPIFLASH_BP2)
|
||||
#define ESP_ROM_SPIFLASH_QE BIT9
|
||||
#define ESP_ROM_SPIFLASH_BP_MASK_ISSI (BIT7 | BIT5 | BIT4 | BIT3 | BIT2)
|
||||
|
||||
#define FLASH_ID_GD25LQ32C 0xC86016
|
||||
|
||||
|
@ -62,10 +62,7 @@ esp_err_t essl_wait_for_ready(essl_handle_t handle, uint32_t wait_ms)
|
||||
|
||||
esp_err_t essl_send_packet(essl_handle_t handle, const void *start, size_t length, uint32_t wait_ms)
|
||||
{
|
||||
if (handle == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (start == NULL || length == 0) {
|
||||
if (handle == NULL || start == NULL || length == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (handle->send_packet == NULL) {
|
||||
@ -87,9 +84,9 @@ esp_err_t essl_send_packet(essl_handle_t handle, const void *start, size_t lengt
|
||||
} else if (err != ESP_ERR_NOT_FOUND) {
|
||||
return err;
|
||||
} // else ESP_ERR_NOT_FOUND
|
||||
//the slave has no enough memory, retry
|
||||
//the slave is not ready, retry
|
||||
} while (remain_wait_ms > 0);
|
||||
return ESP_OK;
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t essl_get_packet(essl_handle_t handle, void *out_data, size_t size, size_t *out_length, uint32_t wait_ms)
|
||||
|
@ -17,8 +17,46 @@
|
||||
#include "esp_log.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "essl_spi/esp32s2_defs.h"
|
||||
#include "essl_internal.h"
|
||||
#include "essl_spi.h"
|
||||
#include "essl_spi/esp32s2_defs.h"
|
||||
|
||||
#define ESSL_SPI_CHECK(cond, warn, ret) do{if(!(cond)){ESP_LOGE(TAG, warn); return ret;}} while(0)
|
||||
|
||||
/**
|
||||
* Initialise device function list of SPI by this macro.
|
||||
*/
|
||||
#define ESSL_SPI_DEFAULT_DEV_FUNC() (essl_dev_t) {\
|
||||
.get_tx_buffer_num = essl_spi_get_tx_buffer_num,\
|
||||
.update_tx_buffer_num = essl_spi_update_tx_buffer_num,\
|
||||
.get_rx_data_size = essl_spi_get_rx_data_size,\
|
||||
.update_rx_data_size = essl_spi_update_rx_data_size,\
|
||||
.send_packet = essl_spi_send_packet,\
|
||||
.get_packet = essl_spi_get_packet,\
|
||||
.write_reg = essl_spi_write_reg,\
|
||||
.read_reg = essl_spi_read_reg,\
|
||||
}
|
||||
|
||||
static const char TAG[] = "essl_spi";
|
||||
|
||||
typedef struct {
|
||||
spi_device_handle_t spi; // Pointer to SPI device handle.
|
||||
/* Master TX, Slave RX */
|
||||
struct {
|
||||
size_t sent_buf_num; // Number of TX buffers that has been sent out by the master.
|
||||
size_t slave_rx_buf_num; // Number of RX buffers laoded by the slave.
|
||||
uint16_t tx_buffer_size; /* Buffer size for Master TX / Slave RX direction.
|
||||
* Data with length within this size will still be regarded as one buffer.
|
||||
* E.g. 10 bytes data costs 2 buffers if the size is 8 bytes per buffer. */
|
||||
uint8_t tx_sync_reg; // The pre-negotiated register ID for Master-TX-SLAVE-RX synchronization. 1 word (4 Bytes) will be reserved for the synchronization.
|
||||
} master_out;
|
||||
/* Master RX, Slave TX */
|
||||
struct {
|
||||
size_t received_bytes; // Number of the RX bytes that has been received by the Master.
|
||||
size_t slave_tx_bytes; // Number of the TX bytes that has been loaded by the Slave
|
||||
uint8_t rx_sync_reg; // The pre-negotiated register ID for Master-RX-SLAVE-TX synchronization. 1 word (4 Bytes) will be reserved for the synchronization.
|
||||
} master_in;
|
||||
} essl_spi_context_t;
|
||||
|
||||
|
||||
static uint16_t get_hd_command(uint16_t cmd_i, uint32_t flags)
|
||||
@ -153,12 +191,12 @@ esp_err_t essl_spi_rddma(spi_device_handle_t spi, uint8_t *out_data, int len, in
|
||||
seg_len = (seg_len > 0)? seg_len : len;
|
||||
|
||||
uint8_t* read_ptr = out_data;
|
||||
esp_err_t err = ESP_OK;
|
||||
esp_err_t ret = ESP_OK;
|
||||
while (len > 0) {
|
||||
int send_len = MIN(seg_len, len);
|
||||
|
||||
err = essl_spi_rddma_seg(spi, read_ptr, send_len, flags);
|
||||
if (err != ESP_OK) return err;
|
||||
ret = essl_spi_rddma_seg(spi, read_ptr, send_len, flags);
|
||||
if (ret != ESP_OK) return ret;
|
||||
|
||||
len -= send_len;
|
||||
read_ptr += send_len;
|
||||
@ -217,3 +255,235 @@ esp_err_t essl_spi_int(spi_device_handle_t spi, int int_n, uint32_t flags)
|
||||
};
|
||||
return spi_device_transmit(spi, &end_t);
|
||||
}
|
||||
|
||||
//------------------------------------ APPEND MODE ----------------------------------//
|
||||
static uint32_t essl_spi_get_rx_data_size(void *arg);
|
||||
static esp_err_t essl_spi_update_rx_data_size(void *arg, uint32_t wait_ms);
|
||||
static uint32_t essl_spi_get_tx_buffer_num(void *arg);
|
||||
static esp_err_t essl_spi_update_tx_buffer_num(void *arg, uint32_t wait_ms);
|
||||
|
||||
esp_err_t essl_spi_init_dev(essl_handle_t *out_handle, const essl_spi_config_t *init_config)
|
||||
{
|
||||
ESSL_SPI_CHECK(init_config->spi, "Check SPI initialization first", ESP_ERR_INVALID_STATE);
|
||||
ESSL_SPI_CHECK(init_config->tx_sync_reg <= (SOC_SPI_MAXIMUM_BUFFER_SIZE - 1) * 4, "tx_sync_reg ID larger than interal register length", ESP_ERR_INVALID_ARG);
|
||||
ESSL_SPI_CHECK(init_config->rx_sync_reg <= (SOC_SPI_MAXIMUM_BUFFER_SIZE - 1) * 4, "rx_sync_reg ID larger than interal register length", ESP_ERR_INVALID_ARG);
|
||||
ESSL_SPI_CHECK(init_config->tx_sync_reg != init_config->rx_sync_reg, "Should use different word of registers for synchronization", ESP_ERR_INVALID_ARG);
|
||||
|
||||
essl_spi_context_t *context = calloc(1, sizeof(essl_spi_context_t));
|
||||
essl_dev_t *dev = calloc(1, sizeof(essl_dev_t));
|
||||
if (!context || !dev) {
|
||||
free(context);
|
||||
free(dev);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
*context = (essl_spi_context_t) {
|
||||
.spi = *init_config->spi,
|
||||
.master_out.tx_buffer_size = init_config->tx_buf_size,
|
||||
.master_out.tx_sync_reg = init_config->tx_sync_reg,
|
||||
.master_in.rx_sync_reg = init_config->rx_sync_reg
|
||||
};
|
||||
|
||||
*dev = ESSL_SPI_DEFAULT_DEV_FUNC();
|
||||
dev->args = context;
|
||||
|
||||
*out_handle = dev;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t essl_spi_deinit_dev(essl_handle_t handle)
|
||||
{
|
||||
ESSL_SPI_CHECK(handle, "ESSL SPI is not in use", ESP_ERR_INVALID_STATE);
|
||||
free(handle->args);
|
||||
free(handle);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void essl_spi_reset_cnt(void *arg)
|
||||
{
|
||||
essl_spi_context_t *ctx = arg;
|
||||
if (ctx) {
|
||||
ctx->master_out.sent_buf_num = 0;
|
||||
ctx->master_in.received_bytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------ RX ----------------------------------//
|
||||
esp_err_t essl_spi_read_reg(void *arg, uint8_t addr, uint8_t *out_value, uint32_t wait_ms)
|
||||
{
|
||||
essl_spi_context_t *ctx = arg;
|
||||
ESSL_SPI_CHECK(arg, "Check ESSL SPI initialization first", ESP_ERR_INVALID_STATE);
|
||||
uint8_t reserved_1_head = ctx->master_out.tx_sync_reg < ctx->master_in.rx_sync_reg ? ctx->master_out.tx_sync_reg : ctx->master_in.rx_sync_reg;
|
||||
uint8_t reserved_1_tail = reserved_1_head + 3;
|
||||
uint8_t reserved_2_head = ctx->master_out.tx_sync_reg < ctx->master_in.rx_sync_reg ? ctx->master_in.rx_sync_reg : ctx->master_out.tx_sync_reg;
|
||||
uint8_t reserved_2_tail = reserved_2_head + 3;
|
||||
ESSL_SPI_CHECK(addr < reserved_1_head || (addr > reserved_1_tail && addr < reserved_2_head) || addr > reserved_2_tail, "Invalid address", ESP_ERR_INVALID_ARG);
|
||||
|
||||
return essl_spi_rdbuf(ctx->spi, out_value, addr, sizeof(uint8_t), 0);
|
||||
}
|
||||
|
||||
static uint32_t essl_spi_get_rx_data_size(void *arg)
|
||||
{
|
||||
essl_spi_context_t *ctx = arg;
|
||||
ESP_LOGV(TAG, "slave tx buffer: %d bytes, master has read: %d bytes", ctx->master_in.slave_tx_bytes, ctx->master_in.received_bytes);
|
||||
return ctx->master_in.slave_tx_bytes - ctx->master_in.received_bytes;
|
||||
}
|
||||
|
||||
static esp_err_t essl_spi_update_rx_data_size(void *arg, uint32_t wait_ms)
|
||||
{
|
||||
essl_spi_context_t *ctx = arg;
|
||||
uint32_t updated_size;
|
||||
uint32_t previous_size;
|
||||
esp_err_t ret;
|
||||
|
||||
ret = essl_spi_rdbuf_polling(ctx->spi, (uint8_t *)&previous_size, ctx->master_in.rx_sync_reg, sizeof(uint32_t), 0);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read until the last 2 reading result are same. Reason:
|
||||
* SPI transaction is carried on per 1 Byte. So when Master is reading the shared register, if the
|
||||
* register value is changed by Slave at this time, Master may get wrong data.
|
||||
*/
|
||||
while (1) {
|
||||
ret = essl_spi_rdbuf_polling(ctx->spi, (uint8_t *)&updated_size, ctx->master_in.rx_sync_reg, sizeof(uint32_t), 0);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
if (updated_size == previous_size) {
|
||||
ctx->master_in.slave_tx_bytes = updated_size;
|
||||
ESP_LOGV(TAG, "updated: slave prepared tx buffer is: %d bytes", updated_size);
|
||||
return ret;
|
||||
}
|
||||
previous_size = updated_size;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t essl_spi_get_packet(void *arg, void *out_data, size_t size, uint32_t wait_ms)
|
||||
{
|
||||
ESSL_SPI_CHECK(arg, "Check ESSL SPI initialization first", ESP_ERR_INVALID_STATE);
|
||||
if (!esp_ptr_dma_capable(out_data) || ((intptr_t)out_data % 4) != 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
essl_spi_context_t *ctx = arg;
|
||||
esp_err_t ret;
|
||||
|
||||
if (essl_spi_get_rx_data_size(arg) < size) {
|
||||
/**
|
||||
* For realistic situation, usually there will be a large overhead (Slave will load large amount of data),
|
||||
* so here we only update the Slave's TX size when the last-updated size is smaller than what Master requires.
|
||||
*/
|
||||
ret = essl_spi_update_rx_data_size(arg, wait_ms);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
//Slave still did not load enough size of buffer
|
||||
if (essl_spi_get_rx_data_size(arg) < size) {
|
||||
ESP_LOGV(TAG, "slave buffer: %d is not enough, %d is required", ctx->master_in.slave_tx_bytes, ctx->master_in.received_bytes + size);
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "get_packet: size to read is: %d", size);
|
||||
ret = essl_spi_rddma_seg(ctx->spi, out_data, size, 0);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
ctx->master_in.received_bytes += size;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
//------------------------------------ TX ----------------------------------//
|
||||
esp_err_t essl_spi_write_reg(void *arg, uint8_t addr, uint8_t value, uint8_t *out_value, uint32_t wait_ms)
|
||||
{
|
||||
essl_spi_context_t *ctx = arg;
|
||||
ESSL_SPI_CHECK(arg, "Check ESSL SPI initialization first", ESP_ERR_INVALID_STATE);
|
||||
uint8_t reserved_1_head = ctx->master_out.tx_sync_reg < ctx->master_in.rx_sync_reg ? ctx->master_out.tx_sync_reg : ctx->master_in.rx_sync_reg;
|
||||
uint8_t reserved_1_tail = reserved_1_head + 3;
|
||||
uint8_t reserved_2_head = ctx->master_out.tx_sync_reg < ctx->master_in.rx_sync_reg ? ctx->master_in.rx_sync_reg : ctx->master_out.tx_sync_reg;
|
||||
uint8_t reserved_2_tail = reserved_2_head + 3;
|
||||
ESSL_SPI_CHECK(addr < reserved_1_head || (addr > reserved_1_tail && addr < reserved_2_head) || addr > reserved_2_tail, "Invalid address", ESP_ERR_INVALID_ARG);
|
||||
ESSL_SPI_CHECK(out_value == NULL, "This feature is not supported", ESP_ERR_NOT_SUPPORTED);
|
||||
|
||||
return essl_spi_wrbuf(ctx->spi, &value, addr, sizeof(uint8_t), 0);
|
||||
}
|
||||
|
||||
static uint32_t essl_spi_get_tx_buffer_num(void *arg)
|
||||
{
|
||||
essl_spi_context_t *ctx = arg;
|
||||
ESP_LOGV(TAG, "slave rx buffer: %d, master has sent: %d", ctx->master_out.slave_rx_buf_num, ctx->master_out.sent_buf_num);
|
||||
return ctx->master_out.slave_rx_buf_num - ctx->master_out.sent_buf_num;
|
||||
}
|
||||
|
||||
static esp_err_t essl_spi_update_tx_buffer_num(void *arg, uint32_t wait_ms)
|
||||
{
|
||||
essl_spi_context_t *ctx = arg;
|
||||
uint32_t updated_num;
|
||||
uint32_t previous_size;
|
||||
esp_err_t ret;
|
||||
|
||||
ret = essl_spi_rdbuf_polling(ctx->spi, (uint8_t *)&previous_size, ctx->master_out.tx_sync_reg, sizeof(uint32_t), 0);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read until the last 2 reading result are same. Reason:
|
||||
* SPI transaction is carried on per 1 Byte. So when Master is reading the shared register, if the
|
||||
* register value is changed by Slave at this time, Master may get wrong data.
|
||||
*/
|
||||
while (1) {
|
||||
ret = essl_spi_rdbuf_polling(ctx->spi, (uint8_t *)&updated_num, ctx->master_out.tx_sync_reg, sizeof(uint32_t), 0);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
if (updated_num == previous_size) {
|
||||
ctx->master_out.slave_rx_buf_num = updated_num;
|
||||
ESP_LOGV(TAG, "updated: slave prepared rx buffer: %d", updated_num);
|
||||
return ret;
|
||||
}
|
||||
previous_size = updated_num;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t essl_spi_send_packet(void *arg, const void *data, size_t size, uint32_t wait_ms)
|
||||
{
|
||||
ESSL_SPI_CHECK(arg, "Check ESSL SPI initialization first", ESP_ERR_INVALID_STATE);
|
||||
if (!esp_ptr_dma_capable(data)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
essl_spi_context_t *ctx = arg;
|
||||
esp_err_t ret;
|
||||
uint32_t buf_num_to_use = (size + ctx->master_out.tx_buffer_size - 1) / ctx->master_out.tx_buffer_size;
|
||||
|
||||
if (essl_spi_get_tx_buffer_num(arg) < buf_num_to_use) {
|
||||
/**
|
||||
* For realistic situation, usually there will be a large overhead (Slave will load enough number of RX buffers),
|
||||
* so here we only update the Slave's RX buffer number when the last-updated number is smaller than what Master requires.
|
||||
*/
|
||||
ret = essl_spi_update_tx_buffer_num(arg, wait_ms);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
//Slave still did not load a sufficient amount of buffers
|
||||
if (essl_spi_get_tx_buffer_num(arg) < buf_num_to_use) {
|
||||
ESP_LOGV(TAG, "slave buffer: %d is not enough, %d is required", ctx->master_out.slave_rx_buf_num, ctx->master_out.sent_buf_num + buf_num_to_use);
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "send_packet: size to write is: %d", size);
|
||||
ret = essl_spi_wrdma_seg(ctx->spi, data, size, 0);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
ctx->master_out.sent_buf_num += buf_num_to_use;
|
||||
|
||||
return essl_spi_wrdma_done(ctx->spi, 0);
|
||||
}
|
||||
|
@ -31,53 +31,64 @@ typedef struct essl_dev_t* essl_handle_t;
|
||||
*
|
||||
* @param handle Handle of a ``essl`` device.
|
||||
* @param wait_ms Millisecond to wait before timeout, will not wait at all if set to 0-9.
|
||||
* @return ESP_OK if success, or other value returned from lower layer `init`.
|
||||
* @return
|
||||
* - ESP_OK: If success
|
||||
* - ESP_ERR_NOT_SUPPORTED: Current device does not support this function.
|
||||
* - Other value returned from lower layer `init`.
|
||||
*/
|
||||
esp_err_t essl_init(essl_handle_t handle, uint32_t wait_ms);
|
||||
|
||||
/** Wait for interrupt of a ESP32 slave device.
|
||||
/** Wait for interrupt of an ESSL slave device.
|
||||
*
|
||||
* @param handle Handle of a ``essl`` device.
|
||||
* @param wait_ms Millisecond to wait before timeout, will not wait at all if set to 0-9.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if success
|
||||
* - ESP_OK: If success
|
||||
* - ESP_ERR_NOT_SUPPORTED: Current device does not support this function.
|
||||
* - One of the error codes from SDMMC host controller
|
||||
*/
|
||||
esp_err_t essl_wait_for_ready(essl_handle_t handle, uint32_t wait_ms);
|
||||
|
||||
/** Get buffer num for the host to send data to the slave. The buffers are size of ``buffer_size``.
|
||||
*
|
||||
* @param handle Handle of a ``essl`` device.
|
||||
* @param out_tx_num Output of buffer num that host can send data to ESP32 slave.
|
||||
* @param handle Handle of an ESSL device.
|
||||
* @param out_tx_num Output of buffer num that host can send data to ESSL slave.
|
||||
* @param wait_ms Millisecond to wait before timeout, will not wait at all if set to 0-9.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - One of the error codes from SDMMC host controller
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_NOT_SUPPORTED: This API is not supported in this mode
|
||||
* - One of the error codes from SDMMC/SPI host controller
|
||||
*/
|
||||
esp_err_t essl_get_tx_buffer_num(essl_handle_t handle, uint32_t *out_tx_num, uint32_t wait_ms);
|
||||
|
||||
/** Get amount of data the ESP32 slave preparing to send to host.
|
||||
/** Get the size, in bytes, of the data that the ESSL slave is ready to send
|
||||
*
|
||||
* @param handle Handle of a ``essl`` device.
|
||||
* @param out_rx_size Output of data size to read from slave.
|
||||
* @param handle Handle of an ESSL device.
|
||||
* @param out_rx_size Output of data size to read from slave, in bytes
|
||||
* @param wait_ms Millisecond to wait before timeout, will not wait at all if set to 0-9.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - One of the error codes from SDMMC host controller
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_NOT_SUPPORTED: This API is not supported in this mode
|
||||
* - One of the error codes from SDMMC/SPI host controller
|
||||
*/
|
||||
esp_err_t essl_get_rx_data_size(essl_handle_t handle, uint32_t *out_rx_size, uint32_t wait_ms);
|
||||
|
||||
|
||||
/** Reset the counters of this component. Usually you don't need to do this unless you know the slave is reset.
|
||||
*
|
||||
* @param handle Handle of a ``essl`` device.
|
||||
* @param handle Handle of an ESSL device.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_NOT_SUPPORTED: This API is not supported in this mode
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument, handle is not init.
|
||||
*/
|
||||
esp_err_t essl_reset_cnt(essl_handle_t handle);
|
||||
|
||||
/** Send a packet to the ESP32 slave. The slave receive the packet into buffers whose size is ``buffer_size`` (configured during initialization).
|
||||
/** Send a packet to the ESSL Slave. The Slave receives the packet into buffers whose size is ``buffer_size`` (configured during initialization).
|
||||
*
|
||||
* @param handle Handle of a ``essl`` device.
|
||||
* @param start Start address of the packet to send
|
||||
@ -86,12 +97,15 @@ esp_err_t essl_reset_cnt(essl_handle_t handle);
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_TIMEOUT No buffer to use, or error ftrom SDMMC host controller
|
||||
* - One of the error codes from SDMMC host controller
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument, handle is not init or other argument is not valid.
|
||||
* - ESP_ERR_TIMEOUT: No buffer to use, or error ftrom SDMMC host controller.
|
||||
* - ESP_ERR_NOT_FOUND: Slave is not ready for receiving.
|
||||
* - ESP_ERR_NOT_SUPPORTED: This API is not supported in this mode
|
||||
* - One of the error codes from SDMMC/SPI host controller.
|
||||
*/
|
||||
esp_err_t essl_send_packet(essl_handle_t handle, const void *start, size_t length, uint32_t wait_ms);
|
||||
|
||||
/** Get a packet from ESP32 slave.
|
||||
/** Get a packet from ESSL slave.
|
||||
*
|
||||
* @param handle Handle of a ``essl`` device.
|
||||
* @param[out] out_data Data output address
|
||||
@ -100,16 +114,19 @@ esp_err_t essl_send_packet(essl_handle_t handle, const void *start, size_t lengt
|
||||
* @param wait_ms Millisecond to wait before timeout, will not wait at all if set to 0-9.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success, all the data are read from the slave.
|
||||
* - ESP_ERR_NOT_FINISHED Read success, while there're data remaining.
|
||||
* - One of the error codes from SDMMC host controller
|
||||
* - ESP_OK Success: All the data has been read from the slave.
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument, The handle is not initialized or the other arguments are invalid.
|
||||
* - ESP_ERR_NOT_FINISHED: Read was successful, but there is still data remaining.
|
||||
* - ESP_ERR_NOT_FOUND: Slave is not ready to send data.
|
||||
* - ESP_ERR_NOT_SUPPORTED: This API is not supported in this mode
|
||||
* - One of the error codes from SDMMC/SPI host controller.
|
||||
*/
|
||||
esp_err_t essl_get_packet(essl_handle_t handle, void *out_data, size_t size, size_t *out_length, uint32_t wait_ms);
|
||||
|
||||
/** Write general purpose R/W registers (8-bit) of ESP32 slave.
|
||||
/** Write general purpose R/W registers (8-bit) of ESSL slave.
|
||||
*
|
||||
* @param handle Handle of a ``essl`` device.
|
||||
* @param addr Address of register to write. Valid address: 0-59.
|
||||
* @param handle Handle of an ESSL device.
|
||||
* @param addr Address of register to write. For SDIO, valid address: 0-59. For SPI, see ``essl_spi.h``
|
||||
* @param value Value to write to the register.
|
||||
* @param value_o Output of the returned written value.
|
||||
* @param wait_ms Millisecond to wait before timeout, will not wait at all if set to 0-9.
|
||||
@ -118,22 +135,20 @@ esp_err_t essl_get_packet(essl_handle_t handle, void *out_data, size_t size, siz
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Address not valid.
|
||||
* - One of the error codes from SDMMC host controller
|
||||
* - One of the error codes from SDMMC/SPI host controller
|
||||
*/
|
||||
esp_err_t essl_write_reg(essl_handle_t handle, uint8_t addr, uint8_t value, uint8_t *value_o, uint32_t wait_ms);
|
||||
|
||||
/** Read general purpose R/W registers (8-bit) of ESP32 slave.
|
||||
/** Read general purpose R/W registers (8-bit) of ESSL slave.
|
||||
*
|
||||
* @param handle Handle of a ``essl`` device.
|
||||
* @param add Address of register to read. Valid address: 0-27, 32-63 (28-31 reserved, return interrupt bits on read).
|
||||
* @param add Address of register to read. For SDIO, Valid address: 0-27, 32-63 (28-31 reserved, return interrupt bits on read). For SPI, see ``essl_spi.h``
|
||||
* @param value_o Output value read from the register.
|
||||
* @param wait_ms Millisecond to wait before timeout, will not wait at all if set to 0-9.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Address not valid.
|
||||
* - One of the error codes from SDMMC host controller
|
||||
* - One of the error codes from SDMMC/SPI host controller
|
||||
*/
|
||||
esp_err_t essl_read_reg(essl_handle_t handle, uint8_t add, uint8_t *value_o, uint32_t wait_ms);
|
||||
|
||||
@ -143,25 +158,26 @@ esp_err_t essl_read_reg(essl_handle_t handle, uint8_t add, uint8_t *value_o, uin
|
||||
* @param wait_ms Millisecond to wait before timeout, will not wait at all if set to 0-9.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_NOT_SUPPORTED Currently our driver doesnot support SDIO with SPI interface.
|
||||
* - ESP_OK If interrupt triggered.
|
||||
* - ESP_ERR_TIMEOUT No interrupts before timeout.
|
||||
* - ESP_OK: If interrupt is triggered.
|
||||
* - ESP_ERR_NOT_SUPPORTED: Current device does not support this function.
|
||||
* - ESP_ERR_TIMEOUT: No interrupts before timeout.
|
||||
*/
|
||||
esp_err_t essl_wait_int(essl_handle_t handle, uint32_t wait_ms);
|
||||
|
||||
/** Clear interrupt bits of ESP32 slave. All the bits set in the mask will be cleared, while other bits will stay the same.
|
||||
/** Clear interrupt bits of ESSL slave. All the bits set in the mask will be cleared, while other bits will stay the same.
|
||||
*
|
||||
* @param handle Handle of a ``essl`` device.
|
||||
* @param intr_mask Mask of interrupt bits to clear.
|
||||
* @param wait_ms Millisecond to wait before timeout, will not wait at all if set to 0-9.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - One of the error codes from SDMMC host controller
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_NOT_SUPPORTED: Current device does not support this function.
|
||||
* - One of the error codes from SDMMC host controller
|
||||
*/
|
||||
esp_err_t essl_clear_intr(essl_handle_t handle, uint32_t intr_mask, uint32_t wait_ms);
|
||||
|
||||
/** Get interrupt bits of ESP32 slave.
|
||||
/** Get interrupt bits of ESSL slave.
|
||||
*
|
||||
* @param handle Handle of a ``essl`` device.
|
||||
* @param intr_raw Output of the raw interrupt bits. Set to NULL if only masked bits are read.
|
||||
@ -169,25 +185,27 @@ esp_err_t essl_clear_intr(essl_handle_t handle, uint32_t intr_mask, uint32_t wai
|
||||
* @param wait_ms Millisecond to wait before timeout, will not wait at all if set to 0-9.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_INVALID_ARG if both ``intr_raw`` and ``intr_st`` are NULL.
|
||||
* - One of the error codes from SDMMC host controller
|
||||
* - ESP_OK: Success
|
||||
* - ESP_INVALID_ARG: If both ``intr_raw`` and ``intr_st`` are NULL.
|
||||
* - ESP_ERR_NOT_SUPPORTED: Current device does not support this function.
|
||||
* - One of the error codes from SDMMC host controller
|
||||
*/
|
||||
esp_err_t essl_get_intr(essl_handle_t handle, uint32_t *intr_raw, uint32_t *intr_st, uint32_t wait_ms);
|
||||
|
||||
/** Set interrupt enable bits of ESP32 slave. The slave only sends interrupt on the line when there is a bit both the raw status and the enable are set.
|
||||
/** Set interrupt enable bits of ESSL slave. The slave only sends interrupt on the line when there is a bit both the raw status and the enable are set.
|
||||
*
|
||||
* @param handle Handle of a ``essl`` device.
|
||||
* @param ena_mask Mask of the interrupt bits to enable.
|
||||
* @param wait_ms Millisecond to wait before timeout, will not wait at all if set to 0-9.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - One of the error codes from SDMMC host controller
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_NOT_SUPPORTED: Current device does not support this function.
|
||||
* - One of the error codes from SDMMC host controller
|
||||
*/
|
||||
esp_err_t essl_set_intr_ena(essl_handle_t handle, uint32_t ena_mask, uint32_t wait_ms);
|
||||
|
||||
/** Get interrupt enable bits of ESP32 slave.
|
||||
/** Get interrupt enable bits of ESSL slave.
|
||||
*
|
||||
* @param handle Handle of a ``essl`` device.
|
||||
* @param ena_mask_o Output of interrupt bit enable mask.
|
||||
@ -206,7 +224,8 @@ esp_err_t essl_get_intr_ena(essl_handle_t handle, uint32_t *ena_mask_o, uint32_t
|
||||
* @param wait_ms Millisecond to wait before timeout, will not wait at all if set to 0-9.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - One of the error codes from SDMMC host controller
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_NOT_SUPPORTED: Current device does not support this function.
|
||||
* - One of the error codes from SDMMC host controller
|
||||
*/
|
||||
esp_err_t essl_send_slave_intr(essl_handle_t handle, uint32_t intr_mask, uint32_t wait_ms);
|
||||
|
@ -23,22 +23,141 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/// Configuration of ESSL SPI device
|
||||
typedef struct {
|
||||
spi_device_handle_t *spi; ///< Pointer to SPI device handle.
|
||||
uint32_t tx_buf_size; ///< The pre-negotiated Master TX buffer size used by both the host and the slave.
|
||||
uint8_t tx_sync_reg; ///< The pre-negotiated register ID for Master-TX-SLAVE-RX synchronization. 1 word (4 Bytes) will be reserved for the synchronization.
|
||||
uint8_t rx_sync_reg; ///< The pre-negotiated register ID for Master-RX-Slave-TX synchronization. 1 word (4 Bytes) will be reserved for the synchronization.
|
||||
} essl_spi_config_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// APIs for DMA Append Mode
|
||||
// This mode has a better performance for continuous Half Duplex SPI transactions.
|
||||
//
|
||||
// * You can use the ``essl_spi_init_dev`` and ``essl_spi_deinit_dev`` together with APIs in ``essl.h`` to communicate
|
||||
// with ESP SPI Slaves in Half Duplex DMA Append Mode. See example for SPI SLAVE HALFDUPLEX APPEND MODE.
|
||||
// * You can also use the following APIs to create your own logic.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* @brief Initialize the ESSL SPI device function list and get its handle
|
||||
*
|
||||
* @param[out] out_handle Output of the handle
|
||||
* @param init_config Configuration for the ESSL SPI device
|
||||
* @return
|
||||
* - ESP_OK: On success
|
||||
* - ESP_ERR_NO_MEM: Memory exhausted
|
||||
* - ESP_ERR_INVALID_STATE: SPI driver is not initialized
|
||||
* - ESP_ERR_INVALID_ARG: Wrong register ID
|
||||
*/
|
||||
esp_err_t essl_spi_init_dev(essl_handle_t *out_handle, const essl_spi_config_t *init_config);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the ESSL SPI device and free the memory used by the device
|
||||
*
|
||||
* @param handle Handle of the ESSL SPI device
|
||||
* @return
|
||||
* - ESP_OK: On success
|
||||
* - ESP_ERR_INVALID_STATE: ESSL SPI is not in use
|
||||
*/
|
||||
esp_err_t essl_spi_deinit_dev(essl_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Read from the shared registers
|
||||
*
|
||||
* @note The registers for Master/Slave synchronization are reserved. Do not use them. (see `rx_sync_reg` in `essl_spi_config_t`)
|
||||
*
|
||||
* @param arg Context of the component. (Member ``arg`` from ``essl_handle_t``)
|
||||
* @param addr Address of the shared registers. (Valid: 0 ~ SOC_SPI_MAXIMUM_BUFFER_SIZE, registers for M/S sync are reserved, see note1).
|
||||
* @param[out] out_value Read buffer for the shared registers.
|
||||
* @param wait_ms Time to wait before timeout (reserved for future use, user should set this to 0).
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - ESP_ERR_INVALID_STATE: ESSL SPI has not been initialized.
|
||||
* - ESP_ERR_INVALID_ARG: The address argument is not valid. See note 1.
|
||||
* - or other return value from :cpp:func:`spi_device_transmit`.
|
||||
*/
|
||||
esp_err_t essl_spi_read_reg(void *arg, uint8_t addr, uint8_t *out_value, uint32_t wait_ms);
|
||||
|
||||
/**
|
||||
* @brief Get a packet from Slave
|
||||
*
|
||||
* @param arg Context of the component. (Member ``arg`` from ``essl_handle_t``)
|
||||
* @param[out] out_data Output data address
|
||||
* @param size The size of the output data.
|
||||
* @param wait_ms Time to wait before timeout (reserved for future use, user should set this to 0).
|
||||
* @return
|
||||
* - ESP_OK: On Success
|
||||
* - ESP_ERR_INVALID_STATE: ESSL SPI has not been initialized.
|
||||
* - ESP_ERR_INVALID_ARG: The output data address is neither DMA capable nor 4 byte-aligned
|
||||
* - ESP_ERR_INVALID_SIZE: Master requires ``size`` bytes of data but Slave did not load enough bytes.
|
||||
*/
|
||||
esp_err_t essl_spi_get_packet(void *arg, void *out_data, size_t size, uint32_t wait_ms);
|
||||
|
||||
/**
|
||||
* @brief Write to the shared registers
|
||||
*
|
||||
* @note The registers for Master/Slave synchronization are reserved. Do not use them. (see `tx_sync_reg` in `essl_spi_config_t`)
|
||||
* @note Feature of checking the actual written value (``out_value``) is not supported.
|
||||
*
|
||||
* @param arg Context of the component. (Member ``arg`` from ``essl_handle_t``)
|
||||
* @param addr Address of the shared registers. (Valid: 0 ~ SOC_SPI_MAXIMUM_BUFFER_SIZE, registers for M/S sync are reserved, see note1)
|
||||
* @param value Buffer for data to send, should be align to 4.
|
||||
* @param[out] out_value Not supported, should be set to NULL.
|
||||
* @param wait_ms Time to wait before timeout (reserved for future use, user should set this to 0).
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - ESP_ERR_INVALID_STATE: ESSL SPI has not been initialized.
|
||||
* - ESP_ERR_INVALID_ARG: The address argument is not valid. See note 1.
|
||||
* - ESP_ERR_NOT_SUPPORTED: Should set ``out_value`` to NULL. See note 2.
|
||||
* - or other return value from :cpp:func:`spi_device_transmit`.
|
||||
*
|
||||
*/
|
||||
esp_err_t essl_spi_write_reg(void *arg, uint8_t addr, uint8_t value, uint8_t *out_value, uint32_t wait_ms);
|
||||
|
||||
/**
|
||||
* @brief Send a packet to Slave
|
||||
*
|
||||
* @param arg Context of the component. (Member ``arg`` from ``essl_handle_t``)
|
||||
* @param data Address of the data to send
|
||||
* @param size Size of the data to send.
|
||||
* @param wait_ms Time to wait before timeout (reserved for future use, user should set this to 0).
|
||||
* @return
|
||||
* - ESP_OK: On success
|
||||
* - ESP_ERR_INVALID_STATE: ESSL SPI has not been initialized.
|
||||
* - ESP_ERR_INVALID_ARG: The data address is not DMA capable
|
||||
* - ESP_ERR_INVALID_SIZE: Master will send ``size`` bytes of data but Slave did not load enough RX buffer
|
||||
*/
|
||||
esp_err_t essl_spi_send_packet(void *arg, const void *data, size_t size, uint32_t wait_ms);
|
||||
|
||||
/**
|
||||
* @brief Reset the counter in Master context
|
||||
*
|
||||
* @note Shall only be called if the slave has reset its counter. Else, Slave and Master would be desynchronized
|
||||
*
|
||||
* @param arg Context of the component. (Member ``arg`` from ``essl_handle_t``)
|
||||
*/
|
||||
void essl_spi_reset_cnt(void *arg);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Basic commands to communicate with the SPI Slave HD on ESP32-S2
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Read the shared buffer from the slave in ISR way
|
||||
*
|
||||
* @note The slave's HW doesn't guarantee the data in one SPI transaction is consistent. It sends data in unit of byte.
|
||||
* In other words, if the slave SW attempts to update the shared register when a rdbuf SPI transaction is in-flight,
|
||||
* the data got by the master will be the combination of bytes of different writes of slave SW.
|
||||
*
|
||||
* @note ``out_data`` should be prepared in words and in the DRAM. The buffer may be written in words
|
||||
* by the DMA. When a byte is written, the remaining bytes in the same word will also be
|
||||
* overwritten, even the ``len`` is shorter than a word.
|
||||
*
|
||||
* @param spi SPI device handle representing the slave
|
||||
* @param out_data Buffer for read data, strongly suggested to be in the DRAM and align to 4
|
||||
* @param addr Address of the slave shared buffer
|
||||
* @param len Length to read
|
||||
* @param flags `SPI_TRANS_*` flags to control the transaction mode of the transaction to send.
|
||||
* @param spi SPI device handle representing the slave
|
||||
* @param[out] out_data Buffer for read data, strongly suggested to be in the DRAM and aligned to 4
|
||||
* @param addr Address of the slave shared buffer
|
||||
* @param len Length to read
|
||||
* @param flags `SPI_TRANS_*` flags to control the transaction mode of the transaction to send.
|
||||
* @return
|
||||
* - ESP_OK: on success
|
||||
* - or other return value from :cpp:func:`spi_device_transmit`.
|
||||
@ -52,11 +171,11 @@ esp_err_t essl_spi_rdbuf(spi_device_handle_t spi, uint8_t *out_data, int addr, i
|
||||
* by the DMA. When a byte is written, the remaining bytes in the same word will also be
|
||||
* overwritten, even the ``len`` is shorter than a word.
|
||||
*
|
||||
* @param spi SPI device handle representing the slave
|
||||
* @param out_data Buffer for read data, strongly suggested to be in the DRAM and align to 4
|
||||
* @param addr Address of the slave shared buffer
|
||||
* @param len Length to read
|
||||
* @param flags `SPI_TRANS_*` flags to control the transaction mode of the transaction to send.
|
||||
* @param spi SPI device handle representing the slave
|
||||
* @param[out] out_data Buffer for read data, strongly suggested to be in the DRAM and aligned to 4
|
||||
* @param addr Address of the slave shared buffer
|
||||
* @param len Length to read
|
||||
* @param flags `SPI_TRANS_*` flags to control the transaction mode of the transaction to send.
|
||||
* @return
|
||||
* - ESP_OK: on success
|
||||
* - or other return value from :cpp:func:`spi_device_transmit`.
|
||||
@ -71,7 +190,7 @@ esp_err_t essl_spi_rdbuf_polling(spi_device_handle_t spi, uint8_t *out_data, int
|
||||
* overwritten, even the ``len`` is shorter than a word.
|
||||
*
|
||||
* @param spi SPI device handle representing the slave
|
||||
* @param data Buffer for data to send, strongly suggested to be in the DRAM and align to 4
|
||||
* @param data Buffer for data to send, strongly suggested to be in the DRAM
|
||||
* @param addr Address of the slave shared buffer,
|
||||
* @param len Length to write
|
||||
* @param flags `SPI_TRANS_*` flags to control the transaction mode of the transaction to send.
|
||||
@ -89,7 +208,7 @@ esp_err_t essl_spi_wrbuf(spi_device_handle_t spi, const uint8_t *data, int addr,
|
||||
* overwritten, even the ``len`` is shorter than a word.
|
||||
*
|
||||
* @param spi SPI device handle representing the slave
|
||||
* @param data Buffer for data to send, strongly suggested to be in the DRAM and align to 4
|
||||
* @param data Buffer for data to send, strongly suggested to be in the DRAM
|
||||
* @param addr Address of the slave shared buffer,
|
||||
* @param len Length to write
|
||||
* @param flags `SPI_TRANS_*` flags to control the transaction mode of the transaction to send.
|
||||
@ -105,10 +224,10 @@ esp_err_t essl_spi_wrbuf_polling(spi_device_handle_t spi, const uint8_t *data, i
|
||||
* @note This function combines several :cpp:func:`essl_spi_rddma_seg` and one
|
||||
* :cpp:func:`essl_spi_rddma_done` at the end. Used when the slave is working in segment mode.
|
||||
*
|
||||
* @param spi SPI device handle representing the slave
|
||||
* @param out_data Buffer to hold the received data, strongly suggested to be in the DRAM and align to 4
|
||||
* @param len Total length of data to receive.
|
||||
* @param seg_len Length of each segment, which is not larger than the maximum transaction length
|
||||
* @param spi SPI device handle representing the slave
|
||||
* @param[out] out_data Buffer to hold the received data, strongly suggested to be in the DRAM and aligned to 4
|
||||
* @param len Total length of data to receive.
|
||||
* @param seg_len Length of each segment, which is not larger than the maximum transaction length
|
||||
* allowed for the spi device. Suggested to be multiples of 4. When set < 0, means send
|
||||
* all data in one segment (the ``rddma_done`` will still be sent.)
|
||||
* @param flags `SPI_TRANS_*` flags to control the transaction mode of the transaction to send.
|
||||
@ -123,10 +242,10 @@ esp_err_t essl_spi_rddma(spi_device_handle_t spi, uint8_t *out_data, int len, in
|
||||
*
|
||||
* @note To read long buffer, call :cpp:func:`essl_spi_rddma` instead.
|
||||
*
|
||||
* @param spi SPI device handle representing the slave
|
||||
* @param out_data Buffer to hold the received data, strongly suggested to be in the DRAM and align to 4
|
||||
* @param seg_len Length of this segment
|
||||
* @param flags `SPI_TRANS_*` flags to control the transaction mode of the transaction to send.
|
||||
* @param spi SPI device handle representing the slave
|
||||
* @param[out] out_data Buffer to hold the received data. strongly suggested to be in the DRAM and aligned to 4
|
||||
* @param seg_len Length of this segment
|
||||
* @param flags `SPI_TRANS_*` flags to control the transaction mode of the transaction to send.
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - or other return value from :cpp:func:`spi_device_transmit`.
|
||||
@ -155,7 +274,7 @@ esp_err_t essl_spi_rddma_done(spi_device_handle_t spi, uint32_t flags);
|
||||
* :cpp:func:`essl_spi_wrdma_done` at the end. Used when the slave is working in segment mode.
|
||||
*
|
||||
* @param spi SPI device handle representing the slave
|
||||
* @param data Buffer for data to send, strongly suggested to be in the DRAM and align to 4
|
||||
* @param data Buffer for data to send, strongly suggested to be in the DRAM
|
||||
* @param len Total length of data to send.
|
||||
* @param seg_len Length of each segment, which is not larger than the maximum transaction length
|
||||
* allowed for the spi device. Suggested to be multiples of 4. When set < 0, means send
|
||||
@ -173,7 +292,7 @@ esp_err_t essl_spi_wrdma(spi_device_handle_t spi, const uint8_t *data, int len,
|
||||
* @note To send long buffer, call :cpp:func:`essl_spi_wrdma` instead.
|
||||
*
|
||||
* @param spi SPI device handle representing the slave
|
||||
* @param data Buffer for data to send, strongly suggested to be in the DRAM and align to 4
|
||||
* @param data Buffer for data to send, strongly suggested to be in the DRAM
|
||||
* @param seg_len Length of this segment
|
||||
* @param flags `SPI_TRANS_*` flags to control the transaction mode of the transaction to send.
|
||||
* @return
|
||||
|
29
components/esp_system/README.md
Normal file
29
components/esp_system/README.md
Normal file
@ -0,0 +1,29 @@
|
||||
## System Notes
|
||||
|
||||
### Timekeeping
|
||||
|
||||
The following are the timekeeping mechanisms available and their differences:
|
||||
|
||||
1. System time (`esp_system_get_time`)
|
||||
|
||||
Time with the origin at `g_startup_time`. The implementation is not handled by `esp_system`,
|
||||
but it does provide a default implementation using RTC timer. Currently, `esp_timer`
|
||||
provides system time, since the hardware timers are under the control of that
|
||||
component. However, no matter the underlying timer, the system time provider
|
||||
should maintain the definition of having the origin point at `g_startup_time`.
|
||||
|
||||
2. `esp_timer` time (`esp_timer_get_time`)
|
||||
|
||||
This is the time read from an underlying hardware timer, controlled through config. Origin
|
||||
is at the point where the underlying timer starts counting.
|
||||
|
||||
3. `newlib` time (`gettimeofday`)
|
||||
|
||||
Timekeeping function in standard library. Can be set (`settimeofday`) or moved forward/backward (`adjtime`);
|
||||
with the possibility of the changes being made persistent through config.
|
||||
Currently implemented in terms of system time, as the point of origin is fixed.
|
||||
If persistence is enabled, RTC time is also used in conjuction with system time.
|
||||
|
||||
4. RTC time (`esp_rtc_get_time_us`)
|
||||
|
||||
Time read from RTC timer.
|
@ -383,6 +383,8 @@ esp_err_t esp_light_sleep_start(void);
|
||||
*
|
||||
* This function does not return.
|
||||
*
|
||||
* @note The device will wake up immediately if the deep-sleep time is set to 0
|
||||
*
|
||||
* @param time_in_us deep-sleep time, unit: microsecond
|
||||
*/
|
||||
void esp_deep_sleep(uint64_t time_in_us) __attribute__((noreturn));
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include "esp_private/panic_internal.h"
|
||||
#include "port/panic_funcs.h"
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
@ -60,6 +61,10 @@
|
||||
#include "esp_gdbstub.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
|
||||
#include "hal/usb_serial_jtag_ll.h"
|
||||
#endif
|
||||
|
||||
bool g_panic_abort = false;
|
||||
static char *s_panic_abort_details = NULL;
|
||||
|
||||
@ -68,13 +73,13 @@ static wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
|
||||
#if !CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
|
||||
|
||||
#if CONFIG_ESP_CONSOLE_UART
|
||||
static uart_hal_context_t s_panic_uart = { .dev = CONFIG_ESP_CONSOLE_UART_NUM == 0 ? &UART0 : &UART1 };
|
||||
static uart_hal_context_t s_panic_uart = { .dev = CONFIG_ESP_CONSOLE_UART_NUM == 0 ? &UART0 :&UART1 };
|
||||
|
||||
void panic_print_char(const char c)
|
||||
{
|
||||
uint32_t sz = 0;
|
||||
while(!uart_hal_get_txfifo_len(&s_panic_uart));
|
||||
uart_hal_write_txfifo(&s_panic_uart, (uint8_t*) &c, 1, &sz);
|
||||
while (!uart_hal_get_txfifo_len(&s_panic_uart));
|
||||
uart_hal_write_txfifo(&s_panic_uart, (uint8_t *) &c, 1, &sz);
|
||||
}
|
||||
#endif // CONFIG_ESP_CONSOLE_UART
|
||||
|
||||
@ -87,6 +92,27 @@ void panic_print_char(const char c)
|
||||
}
|
||||
#endif // CONFIG_ESP_CONSOLE_USB_CDC
|
||||
|
||||
#if CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
|
||||
//Timeout; if there's no host listening, the txfifo won't ever
|
||||
//be writable after the first packet.
|
||||
|
||||
#define USBSERIAL_TIMEOUT_MAX_US 50000
|
||||
static int s_usbserial_timeout = 0;
|
||||
|
||||
void panic_print_char(const char c)
|
||||
{
|
||||
while (!usb_serial_jtag_ll_txfifo_writable() && s_usbserial_timeout < (USBSERIAL_TIMEOUT_MAX_US / 100)) {
|
||||
esp_rom_delay_us(100);
|
||||
s_usbserial_timeout++;
|
||||
}
|
||||
if (usb_serial_jtag_ll_txfifo_writable()) {
|
||||
usb_serial_jtag_ll_write_txfifo((const uint8_t *)&c, 1);
|
||||
s_usbserial_timeout = 0;
|
||||
}
|
||||
}
|
||||
#endif //CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
|
||||
|
||||
|
||||
#if CONFIG_ESP_CONSOLE_NONE
|
||||
void panic_print_char(const char c)
|
||||
{
|
||||
@ -96,7 +122,7 @@ void panic_print_char(const char c)
|
||||
|
||||
void panic_print_str(const char *str)
|
||||
{
|
||||
for(int i = 0; str[i] != 0; i++) {
|
||||
for (int i = 0; str[i] != 0; i++) {
|
||||
panic_print_char(str[i]);
|
||||
}
|
||||
}
|
||||
@ -152,7 +178,7 @@ void esp_panic_handler_reconfigure_wdts(void)
|
||||
//Reconfigure TWDT (Timer Group 0)
|
||||
wdt_hal_init(&wdt0_context, WDT_MWDT0, MWDT0_TICK_PRESCALER, false); //Prescaler: wdt counts in ticks of TG0_WDT_TICK_US
|
||||
wdt_hal_write_protect_disable(&wdt0_context);
|
||||
wdt_hal_config_stage(&wdt0_context, 0, 1000*1000/MWDT0_TICKS_PER_US, WDT_STAGE_ACTION_RESET_SYSTEM); //1 second before reset
|
||||
wdt_hal_config_stage(&wdt0_context, 0, 1000 * 1000 / MWDT0_TICKS_PER_US, WDT_STAGE_ACTION_RESET_SYSTEM); //1 second before reset
|
||||
wdt_hal_enable(&wdt0_context);
|
||||
wdt_hal_write_protect_enable(&wdt0_context);
|
||||
|
||||
@ -204,29 +230,29 @@ void esp_panic_handler(panic_info_t *info)
|
||||
info->exception = PANIC_EXCEPTION_ABORT;
|
||||
}
|
||||
|
||||
/*
|
||||
* For any supported chip, the panic handler prints the contents of panic_info_t in the following format:
|
||||
*
|
||||
*
|
||||
* Guru Meditation Error: Core <core> (<exception>). <description>
|
||||
* <details>
|
||||
*
|
||||
* <state>
|
||||
*
|
||||
* <elf_info>
|
||||
*
|
||||
*
|
||||
* ----------------------------------------------------------------------------------------
|
||||
* core - core where exception was triggered
|
||||
* exception - what kind of exception occured
|
||||
* description - a short description regarding the exception that occured
|
||||
* details - more details about the exception
|
||||
* state - processor state like register contents, and backtrace
|
||||
* elf_info - details about the image currently running
|
||||
*
|
||||
* NULL fields in panic_info_t are not printed.
|
||||
*
|
||||
* */
|
||||
/*
|
||||
* For any supported chip, the panic handler prints the contents of panic_info_t in the following format:
|
||||
*
|
||||
*
|
||||
* Guru Meditation Error: Core <core> (<exception>). <description>
|
||||
* <details>
|
||||
*
|
||||
* <state>
|
||||
*
|
||||
* <elf_info>
|
||||
*
|
||||
*
|
||||
* ----------------------------------------------------------------------------------------
|
||||
* core - core where exception was triggered
|
||||
* exception - what kind of exception occured
|
||||
* description - a short description regarding the exception that occured
|
||||
* details - more details about the exception
|
||||
* state - processor state like register contents, and backtrace
|
||||
* elf_info - details about the image currently running
|
||||
*
|
||||
* NULL fields in panic_info_t are not printed.
|
||||
*
|
||||
* */
|
||||
if (info->reason) {
|
||||
panic_print_str("Guru Meditation Error: Core ");
|
||||
panic_print_dec(info->core);
|
||||
@ -309,7 +335,7 @@ void esp_panic_handler(panic_info_t *info)
|
||||
wdt_hal_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
panic_print_str("Entering gdb stub now.\r\n");
|
||||
esp_gdbstub_panic_handler((esp_gdbstub_frame_t*)info->frame);
|
||||
esp_gdbstub_panic_handler((esp_gdbstub_frame_t *)info->frame);
|
||||
#else
|
||||
#if CONFIG_ESP_COREDUMP_ENABLE
|
||||
static bool s_dumping_core;
|
||||
@ -335,8 +361,7 @@ void esp_panic_handler(panic_info_t *info)
|
||||
#if CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT || CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
|
||||
|
||||
if (esp_reset_reason_get_hint() == ESP_RST_UNKNOWN) {
|
||||
switch (info->exception)
|
||||
{
|
||||
switch (info->exception) {
|
||||
case PANIC_EXCEPTION_IWDT:
|
||||
esp_reset_reason_set_hint(ESP_RST_INT_WDT);
|
||||
break;
|
||||
@ -365,7 +390,7 @@ void esp_panic_handler(panic_info_t *info)
|
||||
void IRAM_ATTR __attribute__((noreturn)) panic_abort(const char *details)
|
||||
{
|
||||
g_panic_abort = true;
|
||||
s_panic_abort_details = (char*) details;
|
||||
s_panic_abort_details = (char *) details;
|
||||
|
||||
#if CONFIG_APPTRACE_ENABLE
|
||||
#if CONFIG_SYSVIEW_ENABLE
|
||||
@ -377,7 +402,7 @@ void IRAM_ATTR __attribute__((noreturn)) panic_abort(const char *details)
|
||||
#endif
|
||||
|
||||
*((int *) 0) = 0; // NOLINT(clang-analyzer-core.NullDereference) should be an invalid operation on targets
|
||||
while(1);
|
||||
while (1);
|
||||
}
|
||||
|
||||
/* Weak versions of reset reason hint functions.
|
||||
|
@ -67,6 +67,7 @@
|
||||
#endif
|
||||
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "esp_private/crosscore_int.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
|
||||
@ -130,6 +131,15 @@ static volatile bool s_resume_cores;
|
||||
// If CONFIG_SPIRAM_IGNORE_NOTFOUND is set and external RAM is not found or errors out on testing, this is set to false.
|
||||
bool g_spiram_ok = true;
|
||||
|
||||
static void core_intr_matrix_clear(void)
|
||||
{
|
||||
uint32_t core_id = cpu_hal_get_core_id();
|
||||
|
||||
for (int i = 0; i < ETS_MAX_INTR_SOURCE; i++) {
|
||||
intr_matrix_set(core_id, i, ETS_INVALID_INUM);
|
||||
}
|
||||
}
|
||||
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
void startup_resume_other_cores(void)
|
||||
{
|
||||
@ -163,6 +173,9 @@ void IRAM_ATTR call_start_cpu1(void)
|
||||
s_cpu_up[1] = true;
|
||||
ESP_EARLY_LOGI(TAG, "App cpu up.");
|
||||
|
||||
// Clear interrupt matrix for APP CPU core
|
||||
core_intr_matrix_clear();
|
||||
|
||||
//Take care putting stuff here: if asked, FreeRTOS will happily tell you the scheduler
|
||||
//has started, but it isn't active *on this CPU* yet.
|
||||
esp_cache_err_int_init();
|
||||
@ -233,16 +246,6 @@ static void start_other_core(void)
|
||||
}
|
||||
#endif // !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
|
||||
static void intr_matrix_clear(void)
|
||||
{
|
||||
for (int i = 0; i < ETS_MAX_INTR_SOURCE; i++) {
|
||||
intr_matrix_set(0, i, ETS_INVALID_INUM);
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
intr_matrix_set(1, i, ETS_INVALID_INUM);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We arrive here after the bootloader finished loading the program from flash. The hardware is mostly uninitialized,
|
||||
* and the app CPU is in reset. We do have a stack, so we can do the initialization in C.
|
||||
@ -446,7 +449,8 @@ void IRAM_ATTR call_start_cpu0(void)
|
||||
// and default RTC-backed system time provider.
|
||||
g_startup_time = esp_rtc_get_time_us();
|
||||
|
||||
intr_matrix_clear();
|
||||
// Clear interrupt matrix for PRO CPU core
|
||||
core_intr_matrix_clear();
|
||||
|
||||
#ifdef CONFIG_ESP_CONSOLE_UART
|
||||
uint32_t clock_hz = rtc_clk_apb_freq_get();
|
||||
@ -489,7 +493,7 @@ void IRAM_ATTR call_start_cpu0(void)
|
||||
|
||||
extern void esp_rom_spiflash_attach(uint32_t, bool);
|
||||
esp_rom_spiflash_attach(esp_rom_efuse_get_flash_gpio_info(), false);
|
||||
esp_rom_spiflash_unlock();
|
||||
bootloader_flash_unlock();
|
||||
#else
|
||||
// This assumes that DROM is the first segment in the application binary, i.e. that we can read
|
||||
// the binary header through cache by accessing SOC_DROM_LOW address.
|
||||
|
@ -225,9 +225,9 @@ __attribute__((weak)) void esp_perip_clk_init(void)
|
||||
/* For reason that only reset CPU, do not disable the clocks
|
||||
* that have been enabled before reset.
|
||||
*/
|
||||
if ((rst_reas[0] >= TGWDT_CPU_RESET && rst_reas[0] <= RTCWDT_CPU_RESET)
|
||||
if ((rst_reas[0] == TGWDT_CPU_RESET || rst_reas[0] == SW_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET)
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
|| (rst_reas[1] >= TGWDT_CPU_RESET && rst_reas[1] <= RTCWDT_CPU_RESET)
|
||||
|| (rst_reas[1] == TGWDT_CPU_RESET || rst_reas[1] == SW_CPU_RESET || rst_reas[1] == RTCWDT_CPU_RESET)
|
||||
#endif
|
||||
) {
|
||||
common_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN_REG);
|
||||
|
@ -223,12 +223,11 @@ __attribute__((weak)) void esp_perip_clk_init(void)
|
||||
/* For reason that only reset CPU, do not disable the clocks
|
||||
* that have been enabled before reset.
|
||||
*/
|
||||
/* For reason that only reset CPU, do not disable the clocks
|
||||
* that have been enabled before reset.
|
||||
*/
|
||||
if ((rst_reas[0] >= TG0WDT_CPU_RESET && rst_reas[0] <= TG0WDT_CPU_RESET && rst_reas[0] != RTCWDT_BROWN_OUT_RESET)
|
||||
if ((rst_reas[0] == TG0WDT_CPU_RESET || rst_reas[0] == RTC_SW_CPU_RESET ||
|
||||
rst_reas[0] == RTCWDT_CPU_RESET || rst_reas[0] == TG1WDT_CPU_RESET)
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
|| (rst_reas[1] >= TG0WDT_CPU_RESET && rst_reas[1] <= RTCWDT_CPU_RESET)
|
||||
|| (rst_reas[1] == TG0WDT_CPU_RESET || rst_reas[1] == RTC_SW_CPU_RESET ||
|
||||
rst_reas[1] == RTCWDT_CPU_RESET || rst_reas[1] == TG1WDT_CPU_RESET)
|
||||
#endif
|
||||
) {
|
||||
common_perip_clk = ~READ_PERI_REG(SYSTEM_PERIP_CLK_EN0_REG);
|
||||
|
@ -219,9 +219,10 @@ __attribute__((weak)) void esp_perip_clk_init(void)
|
||||
/* For reason that only reset CPU, do not disable the clocks
|
||||
* that have been enabled before reset.
|
||||
*/
|
||||
if (rst_reas[0] >= TG0WDT_CPU_RESET &&
|
||||
rst_reas[0] <= TG0WDT_CPU_RESET &&
|
||||
rst_reas[0] != RTCWDT_BROWN_OUT_RESET) {
|
||||
if (rst_reas[0] == TG0WDT_CPU_RESET ||
|
||||
rst_reas[0] == RTC_SW_CPU_RESET ||
|
||||
rst_reas[0] == RTCWDT_CPU_RESET ||
|
||||
rst_reas[0] == TG1WDT_CPU_RESET) {
|
||||
common_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN_REG);
|
||||
hwcrypto_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN1_REG);
|
||||
wifi_bt_sdio_clk = ~DPORT_READ_PERI_REG(DPORT_WIFI_CLK_EN_REG);
|
||||
@ -314,7 +315,6 @@ __attribute__((weak)) void esp_perip_clk_init(void)
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_BT_LPCK_DIV_FRAC_REG, DPORT_LPCLK_SEL_8M);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_BT_LPCK_DIV_FRAC_REG, DPORT_LPCLK_SEL_RTC_SLOW);
|
||||
|
||||
periph_ll_reset(PERIPH_SYSTIMER_MODULE);
|
||||
|
||||
/* Enable RNG clock. */
|
||||
periph_module_enable(PERIPH_RNG_MODULE);
|
||||
|
@ -221,9 +221,11 @@ __attribute__((weak)) void esp_perip_clk_init(void)
|
||||
/* For reason that only reset CPU, do not disable the clocks
|
||||
* that have been enabled before reset.
|
||||
*/
|
||||
if ((rst_reas[0] >= TG0WDT_CPU_RESET && rst_reas[0] <= TG0WDT_CPU_RESET && rst_reas[0] != RTCWDT_BROWN_OUT_RESET)
|
||||
if ((rst_reas[0] == TG0WDT_CPU_RESET || rst_reas[0] == RTC_SW_CPU_RESET ||
|
||||
rst_reas[0] == RTCWDT_CPU_RESET || rst_reas[0] == TG1WDT_CPU_RESET)
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
|| (rst_reas[1] >= TG0WDT_CPU_RESET && rst_reas[1] <= RTCWDT_CPU_RESET)
|
||||
|| (rst_reas[1] == TG0WDT_CPU_RESET || rst_reas[1] == RTC_SW_CPU_RESET ||
|
||||
rst_reas[1] == RTCWDT_CPU_RESET || rst_reas[1] == TG1WDT_CPU_RESET)
|
||||
#endif
|
||||
) {
|
||||
common_perip_clk = ~READ_PERI_REG(SYSTEM_PERIP_CLK_EN0_REG);
|
||||
|
@ -550,8 +550,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
|
||||
}
|
||||
|
||||
// Configure timer wakeup
|
||||
if ((s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) &&
|
||||
s_config.sleep_duration > 0) {
|
||||
if (s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) {
|
||||
timer_wakeup_prepare();
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,7 @@
|
||||
#include "esp_pthread.h"
|
||||
#include "esp_private/usb_console.h"
|
||||
#include "esp_vfs_cdcacm.h"
|
||||
#include "esp_vfs_usb_serial_jtag.h"
|
||||
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
@ -277,6 +278,10 @@ static void do_core_init(void)
|
||||
ESP_ERROR_CHECK(esp_vfs_dev_cdcacm_register());
|
||||
const char *default_stdio_dev = "/dev/cdcacm";
|
||||
#endif // CONFIG_ESP_CONSOLE_USB_CDC
|
||||
#ifdef CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
|
||||
ESP_ERROR_CHECK(esp_vfs_dev_usb_serial_jtag_register());
|
||||
const char *default_stdio_dev = "/dev/usbserjtag";
|
||||
#endif // CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
|
||||
#endif // CONFIG_VFS_SUPPORT_IO
|
||||
|
||||
#if defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_NONE)
|
||||
|
@ -16,8 +16,8 @@
|
||||
#include "esp32c3/memprot.h"
|
||||
#endif
|
||||
|
||||
#define SHUTDOWN_HANDLERS_NO 5
|
||||
|
||||
#define SHUTDOWN_HANDLERS_NO 4
|
||||
static shutdown_handler_t shutdown_handlers[SHUTDOWN_HANDLERS_NO];
|
||||
|
||||
esp_err_t esp_register_shutdown_handler(shutdown_handler_t handler)
|
||||
|
36
components/esp_system/test/test_system_time.c
Normal file
36
components/esp_system/test/test_system_time.c
Normal file
@ -0,0 +1,36 @@
|
||||
#include <stdio.h>
|
||||
#include "unity.h"
|
||||
|
||||
#include "esp_private/system_internal.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/clk.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/clk.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/clk.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#include "esp32c3/clk.h"
|
||||
#endif
|
||||
|
||||
TEST_CASE("Test effect of rtc clk calibration compensation on system time", "[esp_system]")
|
||||
{
|
||||
uint32_t prev_cal = esp_clk_slowclk_cal_get();
|
||||
int64_t t1 = esp_system_get_time();
|
||||
|
||||
// Modify calibration value
|
||||
esp_clk_slowclk_cal_set(prev_cal/2);
|
||||
|
||||
// Internally, the origin point of rtc clk has been adjusted
|
||||
// so that t2 > t1 remains true
|
||||
int64_t t2 = esp_system_get_time();
|
||||
|
||||
TEST_ASSERT_GREATER_THAN(t1, t2);
|
||||
|
||||
// Restore calibration value
|
||||
esp_clk_slowclk_cal_set(prev_cal);
|
||||
|
||||
t2 = esp_system_get_time();
|
||||
|
||||
TEST_ASSERT_GREATER_THAN(t1, t2);
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
|
||||
set(srcs "src/esp_timer.c"
|
||||
"src/ets_timer_legacy.c")
|
||||
"src/ets_timer_legacy.c"
|
||||
"src/system_time.c")
|
||||
|
||||
if(CONFIG_ESP_TIMER_IMPL_FRC2)
|
||||
list(APPEND srcs "src/esp_timer_impl_frc_legacy.c")
|
||||
|
@ -186,8 +186,7 @@ esp_err_t esp_timer_delete(esp_timer_handle_t timer);
|
||||
|
||||
/**
|
||||
* @brief Get time in microseconds since boot
|
||||
* @return number of microseconds since esp_timer_init was called (this normally
|
||||
* happens early during application startup).
|
||||
* @return number of microseconds since underlying timer has been started
|
||||
*/
|
||||
int64_t esp_timer_get_time(void);
|
||||
|
||||
|
@ -117,3 +117,10 @@ uint64_t esp_timer_impl_get_counter_reg(void);
|
||||
* @return the value of the alarm register
|
||||
*/
|
||||
uint64_t esp_timer_impl_get_alarm_reg(void);
|
||||
|
||||
#if CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER
|
||||
/**
|
||||
* @brief Initialize esp_timer as system time provider.
|
||||
*/
|
||||
void esp_timer_impl_init_system_time(void);
|
||||
#endif
|
||||
|
@ -384,9 +384,7 @@ esp_err_t esp_timer_init(void)
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER
|
||||
// [refactor-todo] this logic, "esp_rtc_get_time_us() - g_startup_time", is also
|
||||
// the weak definition of esp_system_get_time; find a way to remove this duplication.
|
||||
esp_timer_private_advance(esp_rtc_get_time_us() - g_startup_time);
|
||||
esp_timer_impl_init_system_time();
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
@ -517,20 +515,6 @@ int64_t IRAM_ATTR esp_timer_get_next_alarm(void)
|
||||
return next_alarm;
|
||||
}
|
||||
|
||||
// Provides strong definition for system time functions relied upon
|
||||
// by core components.
|
||||
#if CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER
|
||||
int64_t IRAM_ATTR esp_system_get_time(void)
|
||||
{
|
||||
return esp_timer_get_time();
|
||||
}
|
||||
|
||||
uint32_t IRAM_ATTR esp_system_get_time_resolution(void)
|
||||
{
|
||||
return 1000;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool esp_timer_is_active(esp_timer_handle_t timer)
|
||||
{
|
||||
return timer_armed(timer);
|
||||
|
64
components/esp_timer/src/system_time.c
Normal file
64
components/esp_timer/src/system_time.c
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
// Provides strong definition for system time functions relied upon
|
||||
// by core components.
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER
|
||||
#include "esp_timer.h"
|
||||
#include "esp_timer_impl.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_newlib.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "esp_private/startup_internal.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#include "esp32c3/rtc.h"
|
||||
#endif
|
||||
|
||||
__attribute__((unused)) static const char* TAG = "system_time";
|
||||
|
||||
// Correction for underlying timer to keep definition
|
||||
// of system time consistent.
|
||||
static int64_t s_correction_us = 0;
|
||||
|
||||
void esp_timer_impl_init_system_time(void)
|
||||
{
|
||||
s_correction_us = esp_rtc_get_time_us() - g_startup_time - esp_timer_impl_get_time();
|
||||
#if defined(CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER) && defined(CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER)
|
||||
esp_err_t err = esp_register_shutdown_handler(esp_sync_counters_rtc_and_frc);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Register shutdown handler failed, err = 0x%x", err);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int64_t IRAM_ATTR esp_system_get_time(void)
|
||||
{
|
||||
return esp_timer_get_time() + s_correction_us;
|
||||
}
|
||||
|
||||
uint32_t IRAM_ATTR esp_system_get_time_resolution(void)
|
||||
{
|
||||
return 1000;
|
||||
}
|
||||
#endif
|
@ -15,7 +15,16 @@ else()
|
||||
set(extra_priv_requires)
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "src/coexist.c"
|
||||
idf_build_get_property(build_dir BUILD_DIR)
|
||||
|
||||
if(CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN)
|
||||
if(NOT EXISTS "${build_dir}/phy_multiple_init_data.bin")
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${idf_target}/phy_multiple_init_data.bin DESTINATION "${build_dir}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_ESP32_MULTIPLE_PHY_DATA_BIN_EMBEDDED)
|
||||
idf_component_register(SRCS "src/coexist.c"
|
||||
"src/lib_printf.c"
|
||||
"src/mesh_event.c"
|
||||
"src/phy_init.c"
|
||||
@ -25,13 +34,31 @@ idf_component_register(SRCS "src/coexist.c"
|
||||
"src/wifi_default.c"
|
||||
"src/wifi_netif.c"
|
||||
"${idf_target}/esp_adapter.c"
|
||||
INCLUDE_DIRS "include" "${idf_target}/include"
|
||||
PRIV_REQUIRES wpa_supplicant nvs_flash esp_netif driver ${extra_priv_requires}
|
||||
REQUIRES esp_event
|
||||
PRIV_REQUIRES esp_timer esp_pm wpa_supplicant nvs_flash esp_netif ${extra_priv_requires}
|
||||
LDFRAGMENTS "${ldfragments}")
|
||||
|
||||
idf_build_get_property(build_dir BUILD_DIR)
|
||||
INCLUDE_DIRS "include" "${idf_target}/include"
|
||||
PRIV_REQUIRES wpa_supplicant nvs_flash esp_netif driver ${extra_priv_requires}
|
||||
REQUIRES esp_event
|
||||
PRIV_REQUIRES esp_timer esp_pm wpa_supplicant nvs_flash esp_netif ${extra_priv_requires}
|
||||
LDFRAGMENTS "${ldfragments}"
|
||||
EMBED_FILES "${build_dir}/phy_multiple_init_data.bin"
|
||||
)
|
||||
else()
|
||||
idf_component_register(SRCS "src/coexist.c"
|
||||
"src/lib_printf.c"
|
||||
"src/mesh_event.c"
|
||||
"src/phy_init.c"
|
||||
"src/smartconfig.c"
|
||||
"src/smartconfig_ack.c"
|
||||
"src/wifi_init.c"
|
||||
"src/wifi_default.c"
|
||||
"src/wifi_netif.c"
|
||||
"${idf_target}/esp_adapter.c"
|
||||
INCLUDE_DIRS "include" "${idf_target}/include"
|
||||
PRIV_REQUIRES wpa_supplicant nvs_flash esp_netif driver ${extra_priv_requires}
|
||||
REQUIRES esp_event
|
||||
PRIV_REQUIRES esp_timer esp_pm wpa_supplicant nvs_flash esp_netif ${extra_priv_requires}
|
||||
LDFRAGMENTS "${ldfragments}"
|
||||
)
|
||||
endif()
|
||||
|
||||
set(target_name "${idf_target}")
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC "-L ${CMAKE_CURRENT_SOURCE_DIR}/lib/${target_name}")
|
||||
@ -58,7 +85,10 @@ if(CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION)
|
||||
partition_table_get_partition_info(phy_partition_offset "--partition-type data --partition-subtype phy" "offset")
|
||||
|
||||
if(CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN)
|
||||
set(phy_init_data_bin "${CMAKE_CURRENT_SOURCE_DIR}/phy_multiple_init_data.bin")
|
||||
set(phy_init_data_bin "${build_dir}/phy_multiple_init_data.bin")
|
||||
if(CONFIG_ESP32_MULTIPLE_PHY_DATA_BIN_EMBEDDED)
|
||||
set(COMPONENT_EMBED_FILES "${build_dir}/phy_multiple_init_data.bin")
|
||||
endif()
|
||||
else()
|
||||
set(phy_init_data_bin "${build_dir}/phy_init_data.bin")
|
||||
|
||||
|
@ -373,6 +373,14 @@ menu "PHY"
|
||||
3. Country configured by API esp_wifi_set_country()
|
||||
and the parameter policy is WIFI_COUNTRY_POLICY_AUTO.
|
||||
|
||||
config ESP32_MULTIPLE_PHY_DATA_BIN_EMBEDDED
|
||||
bool "Support embedded multiple phy init data bin to app bin"
|
||||
depends on ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
|
||||
default n
|
||||
help
|
||||
If enabled, multiple phy init data bin will embedded into app bin
|
||||
If not enabled, multiple phy init data bin will still leave alone, and need to be flashed by users.
|
||||
|
||||
config ESP32_PHY_INIT_DATA_ERROR
|
||||
bool "Terminate operation when PHY init data error"
|
||||
depends on ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
|
||||
|
@ -3,7 +3,7 @@ ifdef CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION
|
||||
ESP_WIFI_COMPONENT_PATH := $(COMPONENT_PATH)
|
||||
|
||||
ifdef CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
|
||||
PHY_INIT_DATA_BIN = $(ESP_WIFI_COMPONENT_PATH)/phy_multiple_init_data.bin
|
||||
PHY_INIT_DATA_BIN = $(ESP_WIFI_COMPONENT_PATH)/$(IDF_TARGET)/phy_multiple_init_data.bin
|
||||
else
|
||||
PHY_INIT_DATA_OBJ = $(BUILD_DIR_BASE)/phy_init_data.o
|
||||
PHY_INIT_DATA_BIN = $(BUILD_DIR_BASE)/phy_init_data.bin
|
||||
|
BIN
components/esp_wifi/esp32c3/phy_multiple_init_data.bin
Normal file
BIN
components/esp_wifi/esp32c3/phy_multiple_init_data.bin
Normal file
Binary file not shown.
BIN
components/esp_wifi/esp32s2/phy_multiple_init_data.bin
Normal file
BIN
components/esp_wifi/esp32s2/phy_multiple_init_data.bin
Normal file
Binary file not shown.
BIN
components/esp_wifi/esp32s3/phy_multiple_init_data.bin
Normal file
BIN
components/esp_wifi/esp32s3/phy_multiple_init_data.bin
Normal file
Binary file not shown.
@ -1 +1 @@
|
||||
Subproject commit e6945e61f7c63545a77b0575c3770a85b4de948e
|
||||
Subproject commit 3cc2b74980f1768ef68dd85e5d9f6ecf94a594ba
|
@ -84,6 +84,10 @@ uint32_t* s_mac_bb_pd_mem = NULL;
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
|
||||
#if CONFIG_ESP32_MULTIPLE_PHY_DATA_BIN_EMBEDDED
|
||||
extern uint8_t multi_phy_init_data_bin_start[] asm("_binary_phy_multiple_init_data_bin_start");
|
||||
extern uint8_t multi_phy_init_data_bin_end[] asm("_binary_phy_multiple_init_data_bin_end");
|
||||
#endif
|
||||
/* The following static variables are only used by Wi-Fi tasks, so they can be handled without lock */
|
||||
static phy_init_data_type_t s_phy_init_data_type = 0;
|
||||
|
||||
@ -327,7 +331,20 @@ IRAM_ATTR void esp_mac_bb_power_down(void)
|
||||
|
||||
const esp_phy_init_data_t* esp_phy_get_init_data(void)
|
||||
{
|
||||
const esp_partition_t* partition = esp_partition_find_first(
|
||||
esp_err_t err = ESP_OK;
|
||||
const esp_partition_t* partition = NULL;
|
||||
#if CONFIG_ESP32_MULTIPLE_PHY_DATA_BIN_EMBEDDED
|
||||
size_t init_data_store_length = sizeof(phy_init_magic_pre) +
|
||||
sizeof(esp_phy_init_data_t) + sizeof(phy_init_magic_post);
|
||||
uint8_t* init_data_store = (uint8_t*) malloc(init_data_store_length);
|
||||
if (init_data_store == NULL) {
|
||||
ESP_LOGE(TAG, "failed to allocate memory for updated country code PHY init data");
|
||||
return NULL;
|
||||
}
|
||||
memcpy(init_data_store, multi_phy_init_data_bin_start, init_data_store_length);
|
||||
ESP_LOGI(TAG, "loading embedded multiple PHY init data");
|
||||
#else
|
||||
partition = esp_partition_find_first(
|
||||
ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_PHY, NULL);
|
||||
if (partition == NULL) {
|
||||
ESP_LOGE(TAG, "PHY data partition not found");
|
||||
@ -341,15 +358,18 @@ const esp_phy_init_data_t* esp_phy_get_init_data(void)
|
||||
ESP_LOGE(TAG, "failed to allocate memory for PHY init data");
|
||||
return NULL;
|
||||
}
|
||||
esp_err_t err = esp_partition_read(partition, 0, init_data_store, init_data_store_length);
|
||||
err = esp_partition_read(partition, 0, init_data_store, init_data_store_length);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "failed to read PHY data partition (0x%x)", err);
|
||||
free(init_data_store);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
if (memcmp(init_data_store, PHY_INIT_MAGIC, sizeof(phy_init_magic_pre)) != 0 ||
|
||||
memcmp(init_data_store + init_data_store_length - sizeof(phy_init_magic_post),
|
||||
PHY_INIT_MAGIC, sizeof(phy_init_magic_post)) != 0) {
|
||||
ESP_LOGE(TAG, "failed to validate PHY data partition");
|
||||
free(init_data_store);
|
||||
return NULL;
|
||||
}
|
||||
#if CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
|
||||
@ -697,14 +717,17 @@ static esp_err_t phy_get_multiple_init_data(const esp_partition_t* partition,
|
||||
ESP_LOGE(TAG, "failed to allocate memory for PHY init data control info");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t err = esp_partition_read(partition, init_data_store_length, init_data_control_info, sizeof(phy_control_info_data_t));
|
||||
esp_err_t err = ESP_OK;
|
||||
#if CONFIG_ESP32_MULTIPLE_PHY_DATA_BIN_EMBEDDED
|
||||
memcpy(init_data_control_info, multi_phy_init_data_bin_start + init_data_store_length, sizeof(phy_control_info_data_t));
|
||||
#else
|
||||
err = esp_partition_read(partition, init_data_store_length, init_data_control_info, sizeof(phy_control_info_data_t));
|
||||
if (err != ESP_OK) {
|
||||
free(init_data_control_info);
|
||||
ESP_LOGE(TAG, "failed to read PHY control info data partition (0x%x)", err);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
#endif
|
||||
if ((init_data_control_info->check_algorithm) == PHY_CRC_ALGORITHM) {
|
||||
err = phy_crc_check_init_data(init_data_control_info->multiple_bin_checksum, init_data_control_info->control_info_checksum,
|
||||
sizeof(phy_control_info_data_t) - sizeof(init_data_control_info->control_info_checksum));
|
||||
@ -726,6 +749,9 @@ static esp_err_t phy_get_multiple_init_data(const esp_partition_t* partition,
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
#if CONFIG_ESP32_MULTIPLE_PHY_DATA_BIN_EMBEDDED
|
||||
memcpy(init_data_multiple, multi_phy_init_data_bin_start + init_data_store_length + sizeof(phy_control_info_data_t), sizeof(esp_phy_init_data_t) * init_data_control_info->number);
|
||||
#else
|
||||
err = esp_partition_read(partition, init_data_store_length + sizeof(phy_control_info_data_t),
|
||||
init_data_multiple, sizeof(esp_phy_init_data_t) * init_data_control_info->number);
|
||||
if (err != ESP_OK) {
|
||||
@ -734,7 +760,7 @@ static esp_err_t phy_get_multiple_init_data(const esp_partition_t* partition,
|
||||
ESP_LOGE(TAG, "failed to read PHY init data multiple bin partition (0x%x)", err);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
#endif
|
||||
if ((init_data_control_info->check_algorithm) == PHY_CRC_ALGORITHM) {
|
||||
err = phy_crc_check_init_data(init_data_multiple, init_data_control_info->multiple_bin_checksum,
|
||||
sizeof(esp_phy_init_data_t) * init_data_control_info->number);
|
||||
@ -766,6 +792,19 @@ static esp_err_t phy_get_multiple_init_data(const esp_partition_t* partition,
|
||||
|
||||
esp_err_t esp_phy_update_init_data(phy_init_data_type_t init_data_type)
|
||||
{
|
||||
#if CONFIG_ESP32_MULTIPLE_PHY_DATA_BIN_EMBEDDED
|
||||
esp_err_t err = ESP_OK;
|
||||
const esp_partition_t* partition = NULL;
|
||||
size_t init_data_store_length = sizeof(phy_init_magic_pre) +
|
||||
sizeof(esp_phy_init_data_t) + sizeof(phy_init_magic_post);
|
||||
uint8_t* init_data_store = (uint8_t*) malloc(init_data_store_length);
|
||||
if (init_data_store == NULL) {
|
||||
ESP_LOGE(TAG, "failed to allocate memory for updated country code PHY init data");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
memcpy(init_data_store, multi_phy_init_data_bin_start, init_data_store_length);
|
||||
ESP_LOGI(TAG, "load embedded multi phy init data");
|
||||
#else
|
||||
const esp_partition_t* partition = esp_partition_find_first(
|
||||
ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_PHY, NULL);
|
||||
if (partition == NULL) {
|
||||
@ -786,6 +825,7 @@ esp_err_t esp_phy_update_init_data(phy_init_data_type_t init_data_type)
|
||||
ESP_LOGE(TAG, "failed to read updated country code PHY data partition (0x%x)", err);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
if (memcmp(init_data_store, PHY_INIT_MAGIC, sizeof(phy_init_magic_pre)) != 0 ||
|
||||
memcmp(init_data_store + init_data_store_length - sizeof(phy_init_magic_post),
|
||||
PHY_INIT_MAGIC, sizeof(phy_init_magic_post)) != 0) {
|
||||
@ -831,6 +871,12 @@ esp_err_t esp_phy_update_country_info(const char *country)
|
||||
{
|
||||
#if CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
|
||||
uint8_t phy_init_data_type_map = 0;
|
||||
|
||||
if (!s_multiple_phy_init_data_bin) {
|
||||
ESP_LOGD(TAG, "Does not support multiple PHY init data bins");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
//if country equal s_phy_current_country, return;
|
||||
if (!memcmp(country, s_phy_current_country, sizeof(s_phy_current_country))) {
|
||||
return ESP_OK;
|
||||
@ -838,11 +884,6 @@ esp_err_t esp_phy_update_country_info(const char *country)
|
||||
|
||||
memcpy(s_phy_current_country, country, sizeof(s_phy_current_country));
|
||||
|
||||
if (!s_multiple_phy_init_data_bin) {
|
||||
ESP_LOGD(TAG, "Does not support multiple PHY init data bins");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
phy_init_data_type_map = phy_find_bin_type_according_country(country);
|
||||
if (phy_init_data_type_map == s_phy_init_data_type) {
|
||||
return ESP_OK;
|
||||
|
@ -20,12 +20,12 @@ eps4 0x60820
|
||||
eps5 0x0
|
||||
eps6 0x0
|
||||
eps7 0x0
|
||||
pc 0x400d0e45 0x400d0e45 <recur_func+29>
|
||||
lbeg 0x400014fd 1073747197
|
||||
lend 0x4000150d 1073747213
|
||||
lcount 0xffffffff 4294967295
|
||||
sar 0x0 0
|
||||
ps 0x60820 395296
|
||||
pc 0x400d0e45 0x400d0e45 <recur_func+29>
|
||||
lbeg 0x400014fd 1073747197
|
||||
lend 0x4000150d 1073747213
|
||||
lcount 0xffffffff 4294967295
|
||||
sar 0x0 0
|
||||
ps 0x60820 395296
|
||||
threadptr <unavailable>
|
||||
br <unavailable>
|
||||
scompare1 <unavailable>
|
||||
@ -41,22 +41,22 @@ f64r_hi <unavailable>
|
||||
f64s <unavailable>
|
||||
fcr <unavailable>
|
||||
fsr <unavailable>
|
||||
a0 0x800d0e20 -2146628064
|
||||
a1 0x3ffbaad0 1073457872
|
||||
a2 0x2 2
|
||||
a3 0x3ffbab1c 1073457948
|
||||
a4 0x3ffbab10 1073457936
|
||||
a5 0x3ffae970 1073408368
|
||||
a6 0x0 0
|
||||
a7 0x0 0
|
||||
a8 0x5 5
|
||||
a9 0xffffffad -83
|
||||
a10 0x20 32
|
||||
a11 0x3ffb62e0 1073439456
|
||||
a12 0x1 1
|
||||
a13 0x80 128
|
||||
a14 0x1 1
|
||||
a15 0x0 0
|
||||
a0 0x800d0e20 -2146628064
|
||||
a1 0x3ffbaad0 1073457872
|
||||
a2 0x2 2
|
||||
a3 0x3ffbab1c 1073457948
|
||||
a4 0x3ffbab10 1073457936
|
||||
a5 0x3ffae970 1073408368
|
||||
a6 0x0 0
|
||||
a7 0x0 0
|
||||
a8 0x5 5
|
||||
a9 0xffffffad -83
|
||||
a10 0x20 32
|
||||
a11 0x3ffb62e0 1073439456
|
||||
a12 0x1 1
|
||||
a13 0x80 128
|
||||
a14 0x1 1
|
||||
a15 0x0 0
|
||||
|
||||
==================== CURRENT THREAD STACK =====================
|
||||
#0 0x400d0e45 in recur_func () at /home/alexey/projects/esp/esp-idf/components/espcoredump/test/test_core_dump.c:61
|
||||
@ -66,7 +66,7 @@ a15 0x0 0
|
||||
#4 0x40088160 in xthal_restore_extra_nw () at /Users/igrokhotkov/e/esp32/hal/hal/state_asm.S:97
|
||||
|
||||
======================== THREADS INFO =========================
|
||||
Id Target Id Frame
|
||||
Id Target Id Frame
|
||||
* 1 process 1073439328 0x400d0e45 in recur_func () at /home/alexey/projects/esp/esp-idf/components/espcoredump/test/test_core_dump.c:61
|
||||
2 process 1073455736 0x400092dc in ?? ()
|
||||
3 process 1073444404 0x400e85b2 in intrusive_list<nvs::HashList::HashListBlock>::intrusive_list (this=0x0) at /home/alexey/projects/esp/esp-idf/components/nvs_flash/src/intrusive_list.h:33
|
||||
|
@ -113,6 +113,29 @@ menu "Modbus configuration"
|
||||
Modbus port data processing task priority.
|
||||
The priority of Modbus controller task is equal to (CONFIG_FMB_PORT_TASK_PRIO - 1).
|
||||
|
||||
choice FMB_PORT_TASK_AFFINITY
|
||||
prompt "Modbus task affinity"
|
||||
default FMB_PORT_TASK_AFFINITY_CPU0
|
||||
depends on !FREERTOS_UNICORE
|
||||
help
|
||||
Allows setting the core affinity of the Modbus controller task, i.e. whether the task is pinned to
|
||||
particular CPU, or allowed to run on any CPU.
|
||||
|
||||
config FMB_PORT_TASK_AFFINITY_NO_AFFINITY
|
||||
bool "No affinity"
|
||||
config FMB_PORT_TASK_AFFINITY_CPU0
|
||||
bool "CPU0"
|
||||
config FMB_PORT_TASK_AFFINITY_CPU1
|
||||
bool "CPU1"
|
||||
|
||||
endchoice
|
||||
|
||||
config FMB_PORT_TASK_AFFINITY
|
||||
hex
|
||||
default FREERTOS_NO_AFFINITY if FMB_PORT_TASK_AFFINITY_NO_AFFINITY || FREERTOS_UNICORE
|
||||
default 0x0 if FMB_PORT_TASK_AFFINITY_CPU0
|
||||
default 0x1 if FMB_PORT_TASK_AFFINITY_CPU1
|
||||
|
||||
config FMB_CONTROLLER_SLAVE_ID_SUPPORT
|
||||
bool "Modbus controller slave ID support"
|
||||
default y
|
||||
@ -164,25 +187,40 @@ menu "Modbus configuration"
|
||||
Modbus stack event processing time.
|
||||
|
||||
config FMB_TIMER_PORT_ENABLED
|
||||
bool "Modbus slave stack use timer for 3.5T symbol time measurement"
|
||||
default y
|
||||
bool "Modbus stack use timer for 3.5T symbol time measurement"
|
||||
default n
|
||||
help
|
||||
If this option is set the Modbus stack uses timer for T3.5 time measurement.
|
||||
Else the internal UART TOUT timeout is used for 3.5T symbol time measurement.
|
||||
|
||||
config FMB_TIMER_GROUP
|
||||
int "Modbus Timer group number"
|
||||
int "Slave Timer group number"
|
||||
range 0 1
|
||||
default 0
|
||||
help
|
||||
Modbus Timer group number that is used for timeout measurement.
|
||||
Modbus slave Timer group number that is used for timeout measurement.
|
||||
|
||||
config FMB_TIMER_INDEX
|
||||
int "Modbus Timer index in the group"
|
||||
int "Slave Timer index in the group"
|
||||
range 0 1
|
||||
default 0
|
||||
help
|
||||
Modbus Timer Index in the group that is used for timeout measurement.
|
||||
Modbus slave Timer Index in the group that is used for timeout measurement.
|
||||
|
||||
config FMB_MASTER_TIMER_GROUP
|
||||
int "Master Timer group number"
|
||||
range 0 1
|
||||
default FMB_TIMER_GROUP
|
||||
help
|
||||
Modbus master Timer group number that is used for timeout measurement.
|
||||
|
||||
config FMB_MASTER_TIMER_INDEX
|
||||
int "Master Timer index"
|
||||
range 0 1
|
||||
default FMB_TIMER_INDEX
|
||||
help
|
||||
Modbus master Timer Index in the group that is used for timeout measurement.
|
||||
Note: Modbus master and slave should have different timer index to be able to work simultaneously.
|
||||
|
||||
config FMB_TIMER_ISR_IN_IRAM
|
||||
bool "Place timer interrupt handler into IRAM"
|
||||
|
@ -54,7 +54,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef MB_PORT_HAS_CLOSE
|
||||
#define MB_PORT_HAS_CLOSE 0
|
||||
#define MB_PORT_HAS_CLOSE 1
|
||||
#endif
|
||||
|
||||
/* ----------------------- Static variables ---------------------------------*/
|
||||
|
@ -91,8 +91,6 @@ eMBMasterTCPStart( void )
|
||||
void
|
||||
eMBMasterTCPStop( void )
|
||||
{
|
||||
/* Make sure that no more clients are connected. */
|
||||
vMBMasterTCPPortDisable( );
|
||||
}
|
||||
|
||||
eMBErrorCode
|
||||
|
@ -50,6 +50,9 @@
|
||||
#define MB_TCP_STACK_SIZE (CONFIG_FMB_PORT_TASK_STACK_SIZE)
|
||||
#define MB_TCP_TASK_PRIO (CONFIG_FMB_PORT_TASK_PRIO)
|
||||
|
||||
// The task affinity for Modbus stack tasks
|
||||
#define MB_PORT_TASK_AFFINITY (CONFIG_FMB_PORT_TASK_AFFINITY)
|
||||
|
||||
#define MB_TCP_READ_TIMEOUT_MS (100) // read timeout in mS
|
||||
#define MB_TCP_READ_TIMEOUT (pdMS_TO_TICKS(MB_TCP_READ_TIMEOUT_MS))
|
||||
#define MB_TCP_SEND_TIMEOUT_MS (500) // send event timeout in mS
|
||||
@ -58,6 +61,8 @@
|
||||
|
||||
#define MB_TCP_FRAME_LOG_BUFSIZE (256)
|
||||
|
||||
#define MB_PORT_HAS_CLOSE (1) // Define to explicitly close port on destroy
|
||||
|
||||
// Define number of timer reloads per 1 mS
|
||||
#define MB_TIMER_TICS_PER_MS (20UL)
|
||||
|
||||
|
@ -249,8 +249,10 @@ BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate,
|
||||
uart_set_always_rx_timeout(ucUartNumber, true);
|
||||
|
||||
// Create a task to handle UART events
|
||||
BaseType_t xStatus = xTaskCreate(vUartTask, "uart_queue_task", MB_SERIAL_TASK_STACK_SIZE,
|
||||
NULL, MB_SERIAL_TASK_PRIO, &xMbTaskHandle);
|
||||
BaseType_t xStatus = xTaskCreatePinnedToCore(vUartTask, "uart_queue_task",
|
||||
MB_SERIAL_TASK_STACK_SIZE,
|
||||
NULL, MB_SERIAL_TASK_PRIO,
|
||||
&xMbTaskHandle, MB_PORT_TASK_AFFINITY);
|
||||
if (xStatus != pdPASS) {
|
||||
vTaskDelete(xMbTaskHandle);
|
||||
// Force exit from function with failure
|
||||
|
@ -243,8 +243,10 @@ BOOL xMBMasterPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
|
||||
uart_set_always_rx_timeout(ucUartNumber, true);
|
||||
|
||||
// Create a task to handle UART events
|
||||
BaseType_t xStatus = xTaskCreate(vUartTask, "uart_queue_task", MB_SERIAL_TASK_STACK_SIZE,
|
||||
NULL, MB_SERIAL_TASK_PRIO, &xMbTaskHandle);
|
||||
BaseType_t xStatus = xTaskCreatePinnedToCore(vUartTask, "uart_queue_task",
|
||||
MB_SERIAL_TASK_STACK_SIZE,
|
||||
NULL, MB_SERIAL_TASK_PRIO,
|
||||
&xMbTaskHandle, MB_PORT_TASK_AFFINITY);
|
||||
if (xStatus != pdPASS) {
|
||||
vTaskDelete(xMbTaskHandle);
|
||||
// Force exit from function with failure
|
||||
|
@ -147,8 +147,7 @@ vMBPortTimersDisable(void)
|
||||
void vMBPortTimerClose(void)
|
||||
{
|
||||
#ifdef CONFIG_FMB_TIMER_PORT_ENABLED
|
||||
ESP_ERROR_CHECK(timer_pause(usTimerGroupIndex, usTimerIndex));
|
||||
ESP_ERROR_CHECK(timer_disable_intr(usTimerGroupIndex, usTimerIndex));
|
||||
ESP_ERROR_CHECK(timer_deinit(usTimerGroupIndex, usTimerIndex));
|
||||
ESP_ERROR_CHECK(esp_intr_free(xTimerIntHandle));
|
||||
#endif
|
||||
}
|
||||
|
@ -50,16 +50,13 @@
|
||||
#define MB_TIMER_DIVIDER ((TIMER_BASE_CLK / 1000000UL) * MB_TICK_TIME_US - 1) // divider for 50uS
|
||||
#define MB_TIMER_WITH_RELOAD (1)
|
||||
|
||||
// Timer group and timer number to measure time (configurable in KConfig)
|
||||
#define MB_TIMER_INDEX (CONFIG_FMB_TIMER_INDEX)
|
||||
#define MB_TIMER_GROUP (CONFIG_FMB_TIMER_GROUP)
|
||||
|
||||
/* ----------------------- Variables ----------------------------------------*/
|
||||
static USHORT usT35TimeOut50us;
|
||||
|
||||
static const USHORT usTimerIndex = MB_TIMER_INDEX; // Initialize Modbus Timer index used by stack,
|
||||
static const USHORT usTimerGroupIndex = MB_TIMER_GROUP; // Timer group index used by stack
|
||||
static timer_isr_handle_t xTimerIntHandle; // Timer interrupt handle
|
||||
// Initialize Modbus Timer group and index used by stack
|
||||
static const USHORT usTimerIndex = CONFIG_FMB_MASTER_TIMER_INDEX;
|
||||
static const USHORT usTimerGroupIndex = CONFIG_FMB_MASTER_TIMER_GROUP;
|
||||
static timer_isr_handle_t xTimerIntHandle; // Timer interrupt handle
|
||||
|
||||
/* ----------------------- static functions ---------------------------------*/
|
||||
static void IRAM_ATTR vTimerGroupIsr(void *param)
|
||||
@ -193,7 +190,6 @@ vMBMasterPortTimersDisable()
|
||||
|
||||
void vMBMasterPortTimerClose(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(timer_pause(usTimerGroupIndex, usTimerIndex));
|
||||
ESP_ERROR_CHECK(timer_disable_intr(usTimerGroupIndex, usTimerIndex));
|
||||
ESP_ERROR_CHECK(timer_deinit(usTimerGroupIndex, usTimerIndex));
|
||||
ESP_ERROR_CHECK(esp_intr_free(xTimerIntHandle));
|
||||
}
|
||||
|
@ -671,12 +671,13 @@ esp_err_t mbc_serial_master_create(void** handler)
|
||||
MB_MASTER_CHECK((mbm_opts->mbm_event_group != NULL),
|
||||
ESP_ERR_NO_MEM, "mb event group error.");
|
||||
// Create modbus controller task
|
||||
status = xTaskCreate((void*)&modbus_master_task,
|
||||
status = xTaskCreatePinnedToCore((void*)&modbus_master_task,
|
||||
"modbus_matask",
|
||||
MB_CONTROLLER_STACK_SIZE,
|
||||
NULL, // No parameters
|
||||
MB_CONTROLLER_PRIORITY,
|
||||
&mbm_opts->mbm_task_handle);
|
||||
&mbm_opts->mbm_task_handle,
|
||||
MB_PORT_TASK_AFFINITY);
|
||||
if (status != pdPASS) {
|
||||
vTaskDelete(mbm_opts->mbm_task_handle);
|
||||
MB_MASTER_CHECK((status == pdPASS), ESP_ERR_NO_MEM,
|
||||
|
@ -173,7 +173,7 @@ static esp_err_t mbc_serial_slave_destroy(void)
|
||||
mb_error = eMBClose();
|
||||
MB_SLAVE_CHECK((mb_error == MB_ENOERR), ESP_ERR_INVALID_STATE,
|
||||
"mb stack close failure returned (0x%x).", (uint32_t)mb_error);
|
||||
|
||||
mbs_interface_ptr = NULL;
|
||||
vMBPortSetMode((UCHAR)MB_PORT_INACTIVE);
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -212,12 +212,13 @@ esp_err_t mbc_serial_slave_create(void** handler)
|
||||
MB_SLAVE_CHECK((mbs_opts->mbs_notification_queue_handle != NULL),
|
||||
ESP_ERR_NO_MEM, "mb notify queue creation error.");
|
||||
// Create Modbus controller task
|
||||
status = xTaskCreate((void*)&modbus_slave_task,
|
||||
status = xTaskCreatePinnedToCore((void*)&modbus_slave_task,
|
||||
"modbus_slave_task",
|
||||
MB_CONTROLLER_STACK_SIZE,
|
||||
NULL,
|
||||
MB_CONTROLLER_PRIORITY,
|
||||
&mbs_opts->mbs_task_handle);
|
||||
&mbs_opts->mbs_task_handle,
|
||||
MB_PORT_TASK_AFFINITY);
|
||||
if (status != pdPASS) {
|
||||
vTaskDelete(mbs_opts->mbs_task_handle);
|
||||
MB_SLAVE_CHECK((status == pdPASS), ESP_ERR_NO_MEM,
|
||||
|
@ -37,6 +37,7 @@
|
||||
|
||||
// The response time is average processing time + data transmission
|
||||
#define MB_RESPONSE_TIMEOUT pdMS_TO_TICKS(CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND)
|
||||
#define MB_TCP_CONNECTION_TOUT pdMS_TO_TICKS(CONFIG_FMB_TCP_CONNECTION_TOUT_SEC * 1000)
|
||||
|
||||
static mb_master_interface_t* mbm_interface_ptr = NULL;
|
||||
|
||||
@ -116,15 +117,23 @@ static esp_err_t mbc_tcp_master_start(void)
|
||||
result = (BOOL)xMBTCPPortMasterAddSlaveIp(*comm_ip_table);
|
||||
MB_MASTER_CHECK(result, ESP_ERR_INVALID_STATE, "mb stack add slave IP failed: %s.", *comm_ip_table);
|
||||
}
|
||||
// Add end of list condition
|
||||
(void)xMBTCPPortMasterAddSlaveIp(NULL);
|
||||
// Init polling event handlers and wait before start polling
|
||||
xMBTCPPortMasterWaitEvent(mbm_opts->mbm_event_group, (EventBits_t)MB_EVENT_STACK_STARTED, 1);
|
||||
|
||||
status = eMBMasterEnable();
|
||||
MB_MASTER_CHECK((status == MB_ENOERR), ESP_ERR_INVALID_STATE,
|
||||
"mb stack set slave ID failure, eMBMasterEnable() returned (0x%x).", (uint32_t)status);
|
||||
|
||||
bool start = (bool)xMBTCPPortMasterWaitEvent(mbm_opts->mbm_event_group, (EventBits_t)MB_EVENT_STACK_STARTED);
|
||||
MB_MASTER_CHECK((start), ESP_ERR_INVALID_STATE, "mb stack start failed.");
|
||||
// Send end of list condition to start connection phase
|
||||
(void)xMBTCPPortMasterAddSlaveIp(NULL);
|
||||
|
||||
// Wait for connection done event
|
||||
bool start = (bool)xMBTCPPortMasterWaitEvent(mbm_opts->mbm_event_group,
|
||||
(EventBits_t)MB_EVENT_STACK_STARTED, MB_TCP_CONNECTION_TOUT);
|
||||
MB_MASTER_CHECK((start), ESP_ERR_INVALID_STATE,
|
||||
"mb stack could not connect to slaves for %d seconds.",
|
||||
CONFIG_FMB_TCP_CONNECTION_TOUT_SEC);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -136,17 +145,19 @@ static esp_err_t mbc_tcp_master_destroy(void)
|
||||
MB_MASTER_CHECK((mbm_opts != NULL), ESP_ERR_INVALID_ARG, "mb incorrect options pointer.");
|
||||
eMBErrorCode mb_error = MB_ENOERR;
|
||||
|
||||
// Stop polling by clearing correspondent bit in the event group
|
||||
xEventGroupClearBits(mbm_opts->mbm_event_group,
|
||||
(EventBits_t)MB_EVENT_STACK_STARTED);
|
||||
// Disable and then destroy the Modbus stack
|
||||
mb_error = eMBMasterDisable();
|
||||
MB_MASTER_CHECK((mb_error == MB_ENOERR), ESP_ERR_INVALID_STATE, "mb stack disable failure.");
|
||||
(void)vTaskDelete(mbm_opts->mbm_task_handle);
|
||||
(void)vEventGroupDelete(mbm_opts->mbm_event_group);
|
||||
mb_error = eMBMasterClose();
|
||||
MB_MASTER_CHECK((mb_error == MB_ENOERR), ESP_ERR_INVALID_STATE,
|
||||
"mb stack close failure returned (0x%x).", (uint32_t)mb_error);
|
||||
// Stop polling by clearing correspondent bit in the event group
|
||||
xEventGroupClearBits(mbm_opts->mbm_event_group,
|
||||
(EventBits_t)MB_EVENT_STACK_STARTED);
|
||||
(void)vTaskDelete(mbm_opts->mbm_task_handle);
|
||||
mbm_opts->mbm_task_handle = NULL;
|
||||
(void)vEventGroupDelete(mbm_opts->mbm_event_group);
|
||||
mbm_opts->mbm_event_group = NULL;
|
||||
free(mbm_interface_ptr); // free the memory allocated for options
|
||||
vMBPortSetMode((UCHAR)MB_PORT_INACTIVE);
|
||||
mbm_interface_ptr = NULL;
|
||||
|
@ -64,7 +64,7 @@
|
||||
|
||||
#define MB_EVENT_REQ_ERR_MASK ( EV_MASTER_PROCESS_SUCCESS )
|
||||
|
||||
#define MB_EVENT_WAIT_TOUT_MS ( 2000 )
|
||||
#define MB_EVENT_WAIT_TOUT_MS ( 3000 )
|
||||
|
||||
#define MB_TCP_READ_TICK_MS ( 1 )
|
||||
#define MB_TCP_READ_BUF_RETRY_CNT ( 4 )
|
||||
@ -76,6 +76,7 @@ void vMBPortEventClose( void );
|
||||
/* ----------------------- Static variables ---------------------------------*/
|
||||
static MbPortConfig_t xMbPortConfig;
|
||||
static EventGroupHandle_t xMasterEventHandle = NULL;
|
||||
static SemaphoreHandle_t xShutdownSemaphore = NULL;
|
||||
static EventBits_t xMasterEvent = 0;
|
||||
|
||||
/* ----------------------- Static functions ---------------------------------*/
|
||||
@ -84,7 +85,7 @@ static void vMBTCPPortMasterTask(void *pvParameters);
|
||||
/* ----------------------- Begin implementation -----------------------------*/
|
||||
|
||||
// Waits for stack start event to start Modbus event processing
|
||||
BOOL xMBTCPPortMasterWaitEvent(EventGroupHandle_t xEventHandle, EventBits_t xEvent)
|
||||
BOOL xMBTCPPortMasterWaitEvent(EventGroupHandle_t xEventHandle, EventBits_t xEvent, USHORT usTimeout)
|
||||
{
|
||||
xMasterEventHandle = xEventHandle;
|
||||
xMasterEvent = xEvent;
|
||||
@ -92,7 +93,7 @@ BOOL xMBTCPPortMasterWaitEvent(EventGroupHandle_t xEventHandle, EventBits_t xEve
|
||||
(BaseType_t)(xEvent),
|
||||
pdFALSE, // do not clear start bit
|
||||
pdFALSE,
|
||||
portMAX_DELAY);
|
||||
usTimeout);
|
||||
return (BOOL)(status & xEvent);
|
||||
}
|
||||
|
||||
@ -122,12 +123,13 @@ xMBMasterTCPPortInit( USHORT usTCPPort )
|
||||
}
|
||||
|
||||
// Create task for packet processing
|
||||
BaseType_t xErr = xTaskCreate(vMBTCPPortMasterTask,
|
||||
BaseType_t xErr = xTaskCreatePinnedToCore(vMBTCPPortMasterTask,
|
||||
"tcp_master_task",
|
||||
MB_TCP_STACK_SIZE,
|
||||
NULL,
|
||||
MB_TCP_TASK_PRIO,
|
||||
&xMbPortConfig.xMbTcpTaskHandle);
|
||||
&xMbPortConfig.xMbTcpTaskHandle,
|
||||
MB_PORT_TASK_AFFINITY);
|
||||
if (xErr != pdTRUE)
|
||||
{
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "TCP master task creation failure.");
|
||||
@ -156,6 +158,8 @@ static void vMBTCPPortMasterStartPoll(void)
|
||||
if (!(xFlags & xMasterEvent)) {
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to start TCP stack.");
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to start polling. Incorrect event handle...");
|
||||
}
|
||||
}
|
||||
|
||||
@ -169,6 +173,8 @@ static void vMBTCPPortMasterStopPoll(void)
|
||||
if (!(xFlags & xMasterEvent)) {
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to stop polling.");
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to stop polling. Incorrect event handle...");
|
||||
}
|
||||
}
|
||||
|
||||
@ -185,6 +191,14 @@ static void vMBTCPPortMasterMStoTimeVal(USHORT usTimeoutMs, struct timeval *tv)
|
||||
tv->tv_usec = (usTimeoutMs - (tv->tv_sec * 1000)) * 1000;
|
||||
}
|
||||
|
||||
static void xMBTCPPortMasterCheckShutdown(void) {
|
||||
// First check if the task is not flagged for shutdown
|
||||
if (xShutdownSemaphore) {
|
||||
xSemaphoreGive(xShutdownSemaphore);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL xMBTCPPortMasterCloseConnection(MbSlaveInfo_t* pxInfo)
|
||||
{
|
||||
if (!pxInfo) {
|
||||
@ -256,6 +270,7 @@ static int xMBTCPPortMasterGetBuf(MbSlaveInfo_t* pxInfo, UCHAR* pucDstBuf, USHOR
|
||||
|
||||
// Receive data from connected client
|
||||
while (usBytesLeft > 0) {
|
||||
xMBTCPPortMasterCheckShutdown();
|
||||
// none blocking read from socket with timeout
|
||||
xLength = recv(pxInfo->xSockId, pucBuf, usBytesLeft, MSG_DONTWAIT);
|
||||
if (xLength < 0) {
|
||||
@ -341,6 +356,9 @@ static int vMBTCPPortMasterReadPacket(MbSlaveInfo_t* pxInfo)
|
||||
|
||||
static err_t xMBTCPPortMasterSetNonBlocking(MbSlaveInfo_t* pxInfo)
|
||||
{
|
||||
if (!pxInfo) {
|
||||
return ERR_CONN;
|
||||
}
|
||||
// Set non blocking attribute for socket
|
||||
ULONG ulFlags = fcntl(pxInfo->xSockId, F_GETFL);
|
||||
if (fcntl(pxInfo->xSockId, F_SETFL, ulFlags | O_NONBLOCK) == -1) {
|
||||
@ -465,6 +483,10 @@ BOOL xMBTCPPortMasterAddSlaveIp(const CHAR* pcIpStr)
|
||||
// Unblocking connect function
|
||||
static err_t xMBTCPPortMasterConnect(MbSlaveInfo_t* pxInfo)
|
||||
{
|
||||
if (!pxInfo) {
|
||||
return ERR_CONN;
|
||||
}
|
||||
|
||||
err_t xErr = ERR_OK;
|
||||
CHAR cStr[128];
|
||||
CHAR* pcStr = NULL;
|
||||
@ -623,7 +645,8 @@ static void vMBTCPPortMasterTask(void *pvParameters)
|
||||
|
||||
// Register each slave in the connection info structure
|
||||
while (1) {
|
||||
BaseType_t xStatus = xQueueReceive(xMbPortConfig.xConnectQueue, (void*)&pcAddrStr, portMAX_DELAY);
|
||||
BaseType_t xStatus = xQueueReceive(xMbPortConfig.xConnectQueue, (void*)&pcAddrStr, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS));
|
||||
xMBTCPPortMasterCheckShutdown();
|
||||
if (xStatus != pdTRUE) {
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to register slave IP.");
|
||||
} else {
|
||||
@ -724,10 +747,14 @@ static void vMBTCPPortMasterTask(void *pvParameters)
|
||||
pxInfo->pcIpAddr, xErr);
|
||||
break;
|
||||
}
|
||||
pxInfo->xError = xErr;
|
||||
if (pxInfo) {
|
||||
pxInfo->xError = xErr;
|
||||
}
|
||||
xMBTCPPortMasterCheckShutdown();
|
||||
}
|
||||
}
|
||||
ESP_LOGI(MB_TCP_MASTER_PORT_TAG, "Connected %d slaves, start polling...", usSlaveConnCnt);
|
||||
|
||||
vMBTCPPortMasterStartPoll(); // Send event to start stack
|
||||
|
||||
// Slave receive data loop
|
||||
@ -745,6 +772,7 @@ static void vMBTCPPortMasterTask(void *pvParameters)
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Incorrect connection options for slave index: %d.",
|
||||
xMbPortConfig.ucCurSlaveIndex);
|
||||
vMBTCPPortMasterStopPoll();
|
||||
xMBTCPPortMasterCheckShutdown();
|
||||
break; // incorrect slave descriptor, reconnect.
|
||||
}
|
||||
xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo);
|
||||
@ -760,6 +788,7 @@ static void vMBTCPPortMasterTask(void *pvParameters)
|
||||
xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo);
|
||||
// Wait completion of last transaction
|
||||
xMBMasterPortFsmWaitConfirmation(MB_EVENT_REQ_DONE_MASK, pdMS_TO_TICKS(xTime + 1));
|
||||
xMBTCPPortMasterCheckShutdown();
|
||||
continue;
|
||||
} else if (xRes < 0) {
|
||||
// Select error (slave connection or r/w failure).
|
||||
@ -770,6 +799,7 @@ static void vMBTCPPortMasterTask(void *pvParameters)
|
||||
xMBMasterPortFsmWaitConfirmation(MB_EVENT_REQ_DONE_MASK, pdMS_TO_TICKS(xTime));
|
||||
// Stop polling process
|
||||
vMBTCPPortMasterStopPoll();
|
||||
xMBTCPPortMasterCheckShutdown();
|
||||
// Check disconnected slaves, do not need a result just to print information.
|
||||
xMBTCPPortMasterCheckConnState(&xConnSet);
|
||||
break;
|
||||
@ -802,6 +832,7 @@ static void vMBTCPPortMasterTask(void *pvParameters)
|
||||
pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr, xErr);
|
||||
// Stop polling process
|
||||
vMBTCPPortMasterStopPoll();
|
||||
xMBTCPPortMasterCheckShutdown();
|
||||
// Check disconnected slaves, do not need a result just to print information.
|
||||
xMBTCPPortMasterCheckConnState(&xConnSet);
|
||||
break;
|
||||
@ -818,6 +849,7 @@ static void vMBTCPPortMasterTask(void *pvParameters)
|
||||
pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr, xTime);
|
||||
}
|
||||
}
|
||||
xMBTCPPortMasterCheckShutdown();
|
||||
} // while(usMbSlaveInfoCount)
|
||||
} // while (1)
|
||||
vTaskDelete(NULL);
|
||||
@ -826,18 +858,6 @@ static void vMBTCPPortMasterTask(void *pvParameters)
|
||||
extern void vMBMasterPortEventClose(void);
|
||||
extern void vMBMasterPortTimerClose(void);
|
||||
|
||||
void
|
||||
vMBMasterTCPPortClose(void)
|
||||
{
|
||||
(void)vTaskDelete(xMbPortConfig.xMbTcpTaskHandle);
|
||||
(void)vMBMasterTCPPortDisable();
|
||||
free(xMbPortConfig.pxMbSlaveInfo);
|
||||
vQueueDelete(xMbPortConfig.xConnectQueue);
|
||||
vMBMasterPortTimerClose();
|
||||
// Release resources for the event queue.
|
||||
vMBMasterPortEventClose();
|
||||
}
|
||||
|
||||
void
|
||||
vMBMasterTCPPortDisable(void)
|
||||
{
|
||||
@ -854,6 +874,29 @@ vMBMasterTCPPortDisable(void)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
vMBMasterTCPPortClose(void)
|
||||
{
|
||||
// Try to exit the task gracefully, so select could release its internal callbacks
|
||||
// that were allocated on the stack of the task we're going to delete
|
||||
xShutdownSemaphore = xSemaphoreCreateBinary();
|
||||
// if no semaphore (alloc issues) or couldn't acquire it, just delete the task
|
||||
if (xShutdownSemaphore == NULL || xSemaphoreTake(xShutdownSemaphore, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS)) != pdTRUE) {
|
||||
ESP_LOGW(MB_TCP_MASTER_PORT_TAG, "Modbus port task couldn't exit gracefully within timeout -> abruptly deleting the task.");
|
||||
vTaskDelete(xMbPortConfig.xMbTcpTaskHandle);
|
||||
}
|
||||
if (xShutdownSemaphore) {
|
||||
vSemaphoreDelete(xShutdownSemaphore);
|
||||
xShutdownSemaphore = NULL;
|
||||
}
|
||||
vMBMasterTCPPortDisable();
|
||||
free(xMbPortConfig.pxMbSlaveInfo);
|
||||
vQueueDelete(xMbPortConfig.xConnectQueue);
|
||||
vMBMasterPortTimerClose();
|
||||
// Release resources for the event queue.
|
||||
vMBMasterPortEventClose();
|
||||
}
|
||||
|
||||
BOOL
|
||||
xMBMasterTCPPortGetRequest( UCHAR ** ppucMBTCPFrame, USHORT * usTCPLength )
|
||||
{
|
||||
|
@ -104,10 +104,11 @@ BOOL xMBTCPPortMasterAddSlaveIp(const CHAR* pcIpStr);
|
||||
*
|
||||
* @param xEventHandle Master event handle
|
||||
* @param xEvent event mask to start Modbus stack FSM
|
||||
* @param usTimeout - timeout in ticks to wait for stack to start
|
||||
*
|
||||
* @return TRUE if stack started, else FALSE
|
||||
*/
|
||||
BOOL xMBTCPPortMasterWaitEvent(EventGroupHandle_t xEventHandle, EventBits_t xEvent);
|
||||
BOOL xMBTCPPortMasterWaitEvent(EventGroupHandle_t xEventHandle, EventBits_t xEvent, USHORT usTimeout);
|
||||
|
||||
/**
|
||||
* Set network options for Master port
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user