Kenji Arai / nRF51_WakeUp

Dependents:   BLE_LoopbackUART_low_pwr_w_RTC1 BLE_Uart_Server

Files at this revision

API Documentation at this revision

Comitter:
kenjiArai
Date:
Sat Apr 02 06:19:14 2016 +0000
Child:
1:cc54cd1df555
Commit message:
Wake-up function using RTC1. This revision, current consumption is around 80uA at deep sleep mode and this is not enough!! I cannot reduce it until today. This is a temporary revision which I need your help.

Changed in this revision

nRF51_WakeUp.cpp Show annotated file Show diff for this revision Revisions of this file
nRF51_WakeUp.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nRF51_WakeUp.cpp	Sat Apr 02 06:19:14 2016 +0000
@@ -0,0 +1,87 @@
+/*
+ * mbed library program
+ *  Wake-Up function only at Sleep mode
+ *
+ * Copyright (c) 2016 Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  http://mbed.org/users/kenjiArai/
+ *      Created:    March     24th, 2016
+ *      Revised:    April      2nd, 2016
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
+ * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "nRF51_WakeUp.h"
+
+#define MAX_RTC_TASKS_DELAY     47  // Maximum delay until an RTC task is executed
+
+nRF51_WakeUp::nRF51_WakeUp(PinName p_trigger, PinName p_interrupt):
+                           _pin0(p_trigger), _pin1(p_interrupt), _pin2(p_interrupt)
+{
+    _pin0 = 0;                  // Trigger output
+    _pin2.mode(PullDown);       // Interrupt
+    p_name_trgr = p_trigger;    // keep pin name(number)
+}
+
+void nRF51_WakeUp::set_and_wait(uint32_t t_sec){
+    //----- Set interrupt condition and calling routine ---
+    _pin1.rise(this, &nRF51_WakeUp::action4restart);
+    //----- Set wakeup timer using RTC1 -------------------
+    NVIC_ClearPendingIRQ(RTC1_IRQn);
+    NVIC_DisableIRQ(RTC1_IRQn);
+    NRF_RTC1->TASKS_STOP  = 1;
+    nrf_delay_us(MAX_RTC_TASKS_DELAY);
+    NRF_RTC1->TASKS_CLEAR = 1;
+    nrf_delay_us(MAX_RTC_TASKS_DELAY);
+    NRF_RTC1->INTENCLR = RTC_INTENSET_COMPARE0_Msk;
+    NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk;
+    NRF_RTC1->INTENCLR = RTC_INTENSET_OVRFLW_Msk;
+    NRF_RTC1->EVTENCLR = RTC_EVTEN_OVRFLW_Msk;
+    NRF_RTC1->EVENTS_COMPARE[0] = 0;
+    NRF_RTC1->EVTENCLR = 0x000f0003; // all clear
+    NRF_RTC1->EVTENSET = RTC_EVTEN_COMPARE0_Msk;
+    do {
+        NRF_RTC1->PRESCALER = 4095;
+    } while (NRF_RTC1->PRESCALER != 4095);
+    // Set wake-up time
+    NRF_RTC1->CC[0] = t_sec * 8;   // 125mS clock -> seconds (1Sec/125mS = 8)
+    //----- Connection RTC1 trigger to Interrupt pin ------
+    // GPIOE
+    NRF_GPIOTE->CONFIG[0] =
+          (GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos)
+        | (p_name_trgr << GPIOTE_CONFIG_PSEL_Pos)
+        | (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos);
+    // Set PPI
+    NRF_PPI->CH[0].EEP = (uint32_t)&NRF_RTC1->EVENTS_COMPARE[0];
+    NRF_PPI->CH[0].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];
+    // Enable only PPI channels 0
+    NRF_PPI->CHEN = PPI_CHEN_CH0_Enabled << PPI_CHEN_CH0_Pos;
+    //----- Start RTC1 for next wake-up -------------------
+    NRF_RTC1->TASKS_START = 1;
+    nrf_delay_us(MAX_RTC_TASKS_DELAY);
+    //----- Goto Deep Sleep mode --------------------------
+    NRF_RADIO->POWER = 0;
+    NRF_UART0->POWER = 0;
+    NRF_RADIO->POWER = 0;
+    NRF_SPI0->POWER  = 0;
+    NRF_SPI1->POWER  = 0;
+    NRF_TWI0->POWER  = 0;
+    NRF_TWI1->POWER  = 0;
+    NRF_POWER->RAMON =
+          POWER_RAMON_ONRAM0_RAM0On   << POWER_RAMON_ONRAM0_Pos
+        | POWER_RAMON_ONRAM1_RAM1On   << POWER_RAMON_ONRAM1_Pos
+        | POWER_RAMON_OFFRAM0_RAM0Off << POWER_RAMON_OFFRAM0_Pos
+        | POWER_RAMON_OFFRAM1_RAM1Off << POWER_RAMON_OFFRAM1_Pos;
+    while(true){
+        deepsleep();
+    }
+}
+
+void nRF51_WakeUp::action4restart(void){
+    NVIC_SystemReset();
+    deepsleep();        // Not come here (Just in case)
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nRF51_WakeUp.h	Sat Apr 02 06:19:14 2016 +0000
@@ -0,0 +1,82 @@
+/*
+ * mbed library program
+ *  Wake-Up function only at Sleep mode
+ *      Limitation:
+ *       1) only for nRF51822
+ *       2) RTC1 is used in mbed
+ *
+ * Copyright (c) 2016 Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  http://mbed.org/users/kenjiArai/
+ *      Created:    March     24th, 2016
+ *      Revised:    April      2nd, 2016
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
+ * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef NRF51_WAKEUP
+#define NRF51_WAKEUP
+
+#include "mbed.h"
+#include "nrf_soc.h"
+#include "nrf_delay.h"
+
+#ifndef TARGET_NRF51822
+#error "This function is only for nRF51822."
+#endif
+
+/** Set deepsleep duration time and wakeup as same as RESET state
+ *
+ * @code
+ * #include "mbed.h"
+ * #include "nRF51_WakeUp.h"
+ *
+ * DigitalOut   myled(LED1);
+ * DigitalIn    sw(P0_1);
+ * // RTC1 is 24bit counter, you cannot wait over 582 hours (125ms * 2^24 = 0.125 * 2097152 sec)
+ * nRF51_WakeUp wakeup(LED2, P0_0); // Trigger & Interrupt (MUST tied up together!!)
+ *
+ * int main() {
+ *   while(true){
+ *      myled = 1;
+ *      wait(1.0);
+ *      myled = 0;
+ *      wait(1.0);
+ *      if (sw == 0){
+ *          wakeup.set_and_wait(120);   // 2 minutes
+ *          deepsleep();                // just in case
+ *      }
+ *   }
+ * }
+ * @endcode
+ */
+
+class nRF51_WakeUp
+{
+public:
+    /** Configure control pin
+      * @param output(trigger) pin & Interrupt input pin
+      * @Hardware: Trigger pin and Interrupt pin are must connected!!
+      */
+    nRF51_WakeUp(PinName p_trigger, PinName p_interrupt);
+
+    /** Set wake-up time then goto Deep Sleep mode
+      * @param wake-up time (in minutes)
+      * @none
+      */
+    void set_and_wait(uint32_t t_sec);
+
+private:
+    void        action4restart(void);
+
+    DigitalOut  _pin0;
+    InterruptIn _pin1;
+    DigitalIn   _pin2;
+    PinName     p_name_trgr;
+};
+
+#endif      // NRF51_WAKEUP