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

Reply via email to