mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Revision:
184:08ed48f1de7f
Parent:
182:a56a73fd2a6f
Child:
186:707f6e361f3e
--- a/targets/TARGET_NUVOTON/TARGET_M480/lp_ticker.c	Tue Mar 20 17:01:51 2018 +0000
+++ b/targets/TARGET_NUVOTON/TARGET_M480/lp_ticker.c	Thu Apr 19 17:12:19 2018 +0100
@@ -47,6 +47,9 @@
 #define TMR_CMP_MIN         2
 #define TMR_CMP_MAX         0xFFFFFFu
 
+/* NOTE: When system clock is higher than timer clock, we need to add 3 engine clock
+ *       (recommended by designer) delay to wait for above timer control to take effect. */
+
 void lp_ticker_init(void)
 {
     if (ticker_inited) {
@@ -63,8 +66,10 @@
     // Enable IP clock
     CLK_EnableModuleClock(TIMER_MODINIT.clkidx);
 
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+
     // Configure clock
-    uint32_t clk_timer = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    uint32_t clk_timer = TIMER_GetModuleClock(timer_base);
     uint32_t prescale_timer = clk_timer / NU_TMRCLK_PER_SEC - 1;
     MBED_ASSERT((prescale_timer != (uint32_t) -1) && prescale_timer <= 127);
     MBED_ASSERT((clk_timer % NU_TMRCLK_PER_SEC) == 0);
@@ -72,19 +77,28 @@
     MBED_ASSERT(cmp_timer >= TMR_CMP_MIN && cmp_timer <= TMR_CMP_MAX);
     // Continuous mode
     // NOTE: TIMER_CTL_CNTDATEN_Msk exists in NUC472, but not in M451/M480. In M451/M480, TIMER_CNT is updated continuously by default.
-    ((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname))->CTL = TIMER_CONTINUOUS_MODE | prescale_timer/* | TIMER_CTL_CNTDATEN_Msk*/;
-    ((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname))->CMP = cmp_timer;
+    timer_base->CTL = TIMER_CONTINUOUS_MODE | prescale_timer/* | TIMER_CTL_CNTDATEN_Msk*/;
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
+    timer_base->CMP = cmp_timer;
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
 
     // Set vector
     NVIC_SetVector(TIMER_MODINIT.irq_n, (uint32_t) TIMER_MODINIT.var);
 
     NVIC_EnableIRQ(TIMER_MODINIT.irq_n);
 
-    TIMER_EnableInt((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
-    TIMER_EnableWakeup((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
-    /* NOTE: When engine is clocked by low power clock source (LXT/LIRC), we need to wait for 3 engine clocks. */
+    TIMER_EnableInt(timer_base);
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
+    TIMER_EnableWakeup(timer_base);
     wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
-    TIMER_Start((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+
+    TIMER_Start(timer_base);
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
+    /* Wait for timer to start counting and raise active flag */
+    while(! (timer_base->CTL & TIMER_CTL_ACTSTS_Msk));
 }
 
 timestamp_t lp_ticker_read()
@@ -93,7 +107,7 @@
         lp_ticker_init();
     }
 
-    TIMER_T * timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
 
     return  (TIMER_GetCounter(timer_base) / NU_TMRCLK_PER_TICK);
 }
@@ -108,27 +122,27 @@
      * This behavior is not what we want. To fix it, we could configure new CMP value
      * without stopping counting first.
      */
-    TIMER_T * timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
+    TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname);
 
     /* NOTE: Because H/W timer requests min compare value, our implementation would have alarm delay of 
      *       (TMR_CMP_MIN - interval_clk) clocks when interval_clk is between [1, TMR_CMP_MIN). */
     uint32_t cmp_timer = timestamp * NU_TMRCLK_PER_TICK;
     cmp_timer = NU_CLAMP(cmp_timer, TMR_CMP_MIN, TMR_CMP_MAX);
+
     timer_base->CMP = cmp_timer;
-
-    /* NOTE: When engine is clocked by low power clock source (LXT/LIRC), we need to wait for 3 engine clocks. */
     wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
-    TIMER_Start(timer_base);
 }
 
 void lp_ticker_disable_interrupt(void)
 {
     TIMER_DisableInt((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
 }
 
 void lp_ticker_clear_interrupt(void)
 {
     TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
 }
 
 void lp_ticker_fire_interrupt(void)
@@ -150,8 +164,11 @@
 static void tmr1_vec(void)
 {
     TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
     TIMER_ClearWakeupFlag((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
-    
+    wait_us((NU_US_PER_SEC / NU_TMRCLK_PER_SEC) * 3);
+
     // NOTE: lp_ticker_set_interrupt() may get called in lp_ticker_irq_handler();
     lp_ticker_irq_handler();
 }