Merge branch 'fix/fix_regdma_wait_node_issue_v5.3' into 'release/v5.3'

fix(esp_driver_gptimer): do gptimer retention by timer unit rather than timer group (v5.3)

See merge request espressif/esp-idf!35358
This commit is contained in:
Jiang Jiang Jian
2024-12-09 15:27:24 +08:00
26 changed files with 395 additions and 258 deletions
@@ -269,6 +269,13 @@ void *regdma_link_new_branch_wait_default(void *backup, uint32_t value, uint32_t
*/
void *regdma_link_init(const regdma_link_config_t *config, bool branch, uint32_t module, int nentry, ...);
/**
* @brief Get REGDMA linked list node mode through configuration parameters
* @param config REGDMA linked node configuration parameters
* @return REGDMA linked list node mode
*/
regdma_link_mode_t regdma_link_get_config_mode(const regdma_link_config_t *config);
/**
* @brief Recurse the REGDMA linked list and call the hook subroutine for each node
* @param link The REGDMA linkded list head pointer
+12 -6
View File
@@ -774,10 +774,10 @@ static void print_info_branch_continuous_wrapper(FILE *out, void *link)
regdma_link_head_t head = REGDMA_LINK_HEAD(link);
regdma_link_branch_continuous_t *cons = __containerof(link, regdma_link_branch_continuous_t, head);
assert((cons->stat.module & (cons->stat.module - 1)) == 0);
fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:%p, backup start:%p, restore start:%p, buff_ptr:%p\n" LOG_RESET_COLOR,
fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:{%p, %p, %p, %p}, backup start:%p, restore start:%p, buff_ptr:%p\n" LOG_RESET_COLOR,
__builtin_ffs(cons->stat.module) - 1, cons->stat.id, link,
s_link_mode_str[cons->head.mode], cons->head.length, s_boolean_str[cons->head.branch], s_boolean_str[cons->head.skip_r], s_boolean_str[cons->head.skip_b], s_boolean_str[cons->head.eof],
cons->body.next,
cons->body.next[0], cons->body.next[1], cons->body.next[2], cons->body.next[3],
cons->body.backup, cons->body.restore,
cons->body.mem);
print_info_link_data(out, (const uint32_t *)cons->body.mem, head.length);
@@ -788,10 +788,10 @@ static void print_info_branch_addr_map_wrapper(FILE *out, void *link)
regdma_link_head_t head = REGDMA_LINK_HEAD(link);
regdma_link_branch_addr_map_t *map = __containerof(link, regdma_link_branch_addr_map_t, head);
assert((map->stat.module & (map->stat.module - 1)) == 0);
fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:%p, backup start:%p, restore start:%p, buff_ptr:%p, map:{%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32"}\n" LOG_RESET_COLOR,
fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:{%p, %p, %p, %p}, backup start:%p, restore start:%p, buff_ptr:%p, map:{%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32"}\n" LOG_RESET_COLOR,
__builtin_ffs(map->stat.module) - 1, map->stat.id, link,
s_link_mode_str[map->head.mode], map->head.length, s_boolean_str[map->head.branch], s_boolean_str[map->head.skip_r], s_boolean_str[map->head.skip_b], s_boolean_str[map->head.eof],
map->body.next,
map->body.next[0], map->body.next[1], map->body.next[2], map->body.next[3],
map->body.backup, map->body.restore,
map->body.mem, map->body.map[0], map->body.map[1], map->body.map[2], map->body.map[3]);
print_info_link_data(out, (const uint32_t *)map->body.mem, head.length);
@@ -800,10 +800,10 @@ static void print_info_branch_addr_map_wrapper(FILE *out, void *link)
static void print_info_branch_write_wait_wrapper(FILE *out, void *link)
{
regdma_link_branch_write_wait_t *ww = __containerof(link, regdma_link_branch_write_wait_t, head);
fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:%p, backup start:%p, value:%"PRIx32", mask:%"PRIx32"\n" LOG_RESET_COLOR,
fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:{%p, %p, %p, %p}, backup start:%p, value:%"PRIx32", mask:%"PRIx32"\n" LOG_RESET_COLOR,
__builtin_ffs(ww->stat.module) - 1, ww->stat.id, link,
s_link_mode_str[ww->head.mode], ww->head.length, s_boolean_str[ww->head.branch], s_boolean_str[ww->head.skip_r], s_boolean_str[ww->head.skip_b], s_boolean_str[ww->head.eof],
ww->body.next,
ww->body.next[0], ww->body.next[1], ww->body.next[2], ww->body.next[3],
ww->body.backup, ww->body.value, ww->body.mask);
}
@@ -842,3 +842,9 @@ void regdma_link_dump(FILE *out, void *link, int entry)
fprintf(out, "This REGDMA linked list is empty!\n");
}
}
regdma_link_mode_t regdma_link_get_config_mode(const regdma_link_config_t *config)
{
assert(config != NULL);
return (regdma_link_mode_t)config->head.mode;
}
+37 -8
View File
@@ -21,6 +21,10 @@
#include "sdkconfig.h"
#include "esp_pmu.h"
#if SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE
#include "soc/pmu_reg.h" // for PMU_DATE_REG, it can provide full 32 bit read and write access
#endif
static __attribute__((unused)) const char *TAG = "sleep";
struct sleep_retention_module_object {
@@ -472,8 +476,9 @@ static void sleep_retention_entries_destroy(sleep_retention_module_t module)
static esp_err_t sleep_retention_entries_create_impl(const sleep_retention_entries_config_t retent[], int num, regdma_link_priority_t priority, sleep_retention_module_t module)
{
esp_err_t err = ESP_OK;
_lock_acquire_recursive(&s_retention.lock);
for (int i = num - 1; i >= 0; i--) {
for (int i = num - 1; (i >= 0) && (err == ESP_OK); i--) {
#if SOC_PM_RETENTION_HAS_CLOCK_BUG
if ((retent[i].owner > BIT(EXTRA_LINK_NUM)) && (retent[i].config.id != 0xffff)) {
_lock_release_recursive(&s_retention.lock);
@@ -481,16 +486,40 @@ static esp_err_t sleep_retention_entries_create_impl(const sleep_retention_entri
return ESP_ERR_NOT_SUPPORTED;
}
#endif
void *link = sleep_retention_entries_try_create(&retent[i].config, retent[i].owner, priority, module);
if (link == NULL) {
_lock_release_recursive(&s_retention.lock);
sleep_retention_entries_do_destroy(module);
return ESP_ERR_NO_MEM;
#if SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE
/* There is a bug in REGDMA wait mode, when two wait nodes need to wait for the
* same value (_val & _mask), the second wait node will immediately return to
* wait done, The reason is that the wait mode comparison output logic immediate
* compares the value of the previous wait register cached inside the
* digital logic before reading out he register contents specified by _backup.
*/
#define config_is_wait_mode(_config) (regdma_link_get_config_mode(_config) == REGDMA_LINK_MODE_WAIT)
if ((retent[i].config.id != 0xffff) && config_is_wait_mode(&(retent[i].config)) && (retent[i].config.id != 0xfffe)) {
uint32_t value = retent[i].config.write_wait.value;
uint32_t mask = retent[i].config.write_wait.mask;
bool skip_b = retent[i].config.head.skip_b;
bool skip_r = retent[i].config.head.skip_r;
sleep_retention_entries_config_t wait_bug_workaround[] = {
[0] = { .config = REGDMA_LINK_WRITE_INIT(0xfffe, PMU_DATE_REG, ~value, mask, skip_b, skip_r), .owner = retent[i].owner },
[1] = { .config = REGDMA_LINK_WAIT_INIT (0xfffe, PMU_DATE_REG, ~value, mask, skip_b, skip_r), .owner = retent[i].owner }
};
err = sleep_retention_entries_create_impl(wait_bug_workaround, ARRAY_SIZE(wait_bug_workaround), priority, module);
}
#endif
if (err == ESP_OK) {
void *link = sleep_retention_entries_try_create(&retent[i].config, retent[i].owner, priority, module);
if (link == NULL) {
_lock_release_recursive(&s_retention.lock);
sleep_retention_entries_do_destroy(module);
return ESP_ERR_NO_MEM;
}
sleep_retention_entries_update(retent[i].owner, link, priority);
} else {
break;
}
sleep_retention_entries_update(retent[i].owner, link, priority);
}
_lock_release_recursive(&s_retention.lock);
return ESP_OK;
return err;
}
static esp_err_t sleep_retention_entries_create_bonding(regdma_link_priority_t priority, sleep_retention_module_t module)