This is an automated email from the ASF dual-hosted git repository. andk pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 01d13a12c7da2167da7bf1bf6c17842242cefeb2 Author: Andrzej Kaczmarek <[email protected]> AuthorDate: Thu Nov 26 22:14:49 2020 +0100 hw/mcu/dialog: Ack PDC after writing SYS_SLEEP Writing SYS_SLEEP=1 (can be done when releasing PD_SYS) should disable PD_SYS if there is no PDC irq pending, i.e. no PDC entries are pending. This means it's possible that PD_SYS release will effectively power off M33 core immediately. After wakeup M33 will be restored to state that was saved before previous "complete" deep sleep and this does not seem to be an issue, likely because it always go to sleep from the same code so it also continues to execute the same code after wakeup. However, disabling PD_SYS by SYS_SLEEP=1 can sometimes corrupt cache, i.e. TAG RAM will be updated but corresponding cache lines won't (see DA1469x errata 5.24). This means effectively NOP instructions will be fetched from cache instead of actual code. In our case this corrupts da1469x_pd_release_internal() and it may be stuck in an infinite loop as a result. To make sure writing SYS_SLEEP=1 does not disable M33, prior to write we need to trigger PDC irq and then ack everything it after write to make sleep possible. --- hw/mcu/dialog/da1469x/src/da1469x_priv.h | 1 + hw/mcu/dialog/da1469x/src/da1469x_sleep.c | 10 ++++++++-- hw/mcu/dialog/da1469x/src/system_da1469x.c | 8 ++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/hw/mcu/dialog/da1469x/src/da1469x_priv.h b/hw/mcu/dialog/da1469x/src/da1469x_priv.h index 6434850..98f6208 100755 --- a/hw/mcu/dialog/da1469x/src/da1469x_priv.h +++ b/hw/mcu/dialog/da1469x/src/da1469x_priv.h @@ -27,6 +27,7 @@ extern "C" { #endif +extern uint8_t g_mcu_pdc_sw_trigger_idx; extern uint8_t g_mcu_pdc_combo_idx; extern bool g_mcu_lpclk_available; diff --git a/hw/mcu/dialog/da1469x/src/da1469x_sleep.c b/hw/mcu/dialog/da1469x/src/da1469x_sleep.c index 45597f9..7465827 100644 --- a/hw/mcu/dialog/da1469x/src/da1469x_sleep.c +++ b/hw/mcu/dialog/da1469x/src/da1469x_sleep.c @@ -31,6 +31,7 @@ extern int da1469x_m33_sleep(void) __attribute__((naked)); +uint8_t g_mcu_pdc_sw_trigger_idx; uint8_t g_mcu_pdc_combo_idx; static bool g_mcu_wait_for_jtag; @@ -62,8 +63,6 @@ da1469x_sleep(os_time_t ticks) int slept; bool can_sleep = true; - da1469x_pdc_ack_all_m33(); - if (da1469x_sleep_is_blocked() || ticks < 3) { __DSB(); __WFI(); @@ -82,12 +81,19 @@ da1469x_sleep(os_time_t ticks) /* Must enter mcu gpio sleep before releasing MCU_PD_DOMAIN_SYS */ mcu_gpio_enter_sleep(); + /* + * Set SW trigger entry pending in PDC to make sure SYS_SLEEP=1 won't + * disable us. + */ + da1469x_pdc_set(g_mcu_pdc_sw_trigger_idx); + /* PD_SYS will not be disabled here until we enter deep sleep, so don't wait */ if (!da1469x_pd_release_nowait(MCU_PD_DOMAIN_SYS)) { __DSB(); __WFI(); slept = 0; } else { + da1469x_pdc_ack_all_m33(); slept = da1469x_m33_sleep(); } diff --git a/hw/mcu/dialog/da1469x/src/system_da1469x.c b/hw/mcu/dialog/da1469x/src/system_da1469x.c index 9d1e8f6..509c008 100644 --- a/hw/mcu/dialog/da1469x/src/system_da1469x.c +++ b/hw/mcu/dialog/da1469x/src/system_da1469x.c @@ -125,6 +125,14 @@ SystemInit(void) da1469x_pdc_ack(idx); g_mcu_pdc_combo_idx = idx; + /* Add entry for SW trigger */ + idx = da1469x_pdc_add(MCU_PDC_TRIGGER_SW_TRIGGER, MCU_PDC_MASTER_M33, + MCU_PDC_EN_XTAL); + assert(idx >= 0); + da1469x_pdc_set(idx); + da1469x_pdc_ack(idx); + g_mcu_pdc_sw_trigger_idx = idx; + /* Enable cache retainability */ CRG_TOP->PMU_CTRL_REG |= CRG_TOP_PMU_CTRL_REG_RETAIN_CACHE_Msk; #endif
