NuMaker tickless example

Committer:
ccli8
Date:
Mon Oct 02 11:24:10 2017 +0800
Revision:
10:d2e2c79389e1
Parent:
5:fdfb7a10cc59
Child:
11:0c4b39c54af2
Support NANO130

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ccli8 1:eb1da9d36e12 1 #include "mbed.h"
ccli8 1:eb1da9d36e12 2 #include "wakeup.h"
ccli8 1:eb1da9d36e12 3 #include "rtc_api.h"
ccli8 1:eb1da9d36e12 4 #include "mbed_mktime.h"
ccli8 1:eb1da9d36e12 5
ccli8 1:eb1da9d36e12 6 #define YEAR0 1900
ccli8 1:eb1da9d36e12 7
ccli8 4:da41f0e17d5a 8 static Semaphore sem_rtc(0, 1);
ccli8 4:da41f0e17d5a 9
ccli8 4:da41f0e17d5a 10 static void rtc_loop(void);
ccli8 4:da41f0e17d5a 11 static void schedule_rtc_alarm(uint32_t secs);
ccli8 1:eb1da9d36e12 12
ccli8 10:d2e2c79389e1 13 #if defined(TARGET_NUMAKER_PFM_NANO130)
ccli8 10:d2e2c79389e1 14 /* This target doesn't support relocating vector table and requires overriding
ccli8 10:d2e2c79389e1 15 * vector handler at link-time. */
ccli8 10:d2e2c79389e1 16 extern "C" void RTC_IRQHandler(void)
ccli8 10:d2e2c79389e1 17 #else
ccli8 1:eb1da9d36e12 18 void RTC_IRQHandler(void)
ccli8 10:d2e2c79389e1 19 #endif
ccli8 1:eb1da9d36e12 20 {
ccli8 1:eb1da9d36e12 21 /* Check if RTC alarm interrupt has occurred */
ccli8 10:d2e2c79389e1 22 #if defined(TARGET_NUMAKER_PFM_NANO130)
ccli8 10:d2e2c79389e1 23 if (RTC->RIIR & RTC_RIIR_AIF_Msk) {
ccli8 10:d2e2c79389e1 24 /* Clear RTC alarm interrupt flag */
ccli8 10:d2e2c79389e1 25 RTC->RIIR = RTC_RIIR_AIF_Msk;
ccli8 10:d2e2c79389e1 26
ccli8 10:d2e2c79389e1 27 wakeup_eventflags.set(EventFlag_Wakeup_RTC_Alarm);
ccli8 10:d2e2c79389e1 28 }
ccli8 10:d2e2c79389e1 29 #elif defined(TARGET_NUMAKER_PFM_NUC472)
ccli8 1:eb1da9d36e12 30 if (RTC->INTSTS & RTC_INTSTS_ALMIF_Msk) {
ccli8 1:eb1da9d36e12 31 /* Clear RTC alarm interrupt flag */
ccli8 1:eb1da9d36e12 32 RTC->INTSTS = RTC_INTSTS_ALMIF_Msk;
ccli8 1:eb1da9d36e12 33
ccli8 1:eb1da9d36e12 34 wakeup_eventflags.set(EventFlag_Wakeup_RTC_Alarm);
ccli8 1:eb1da9d36e12 35 }
ccli8 1:eb1da9d36e12 36 #else
ccli8 1:eb1da9d36e12 37 if (RTC_GET_ALARM_INT_FLAG()) {
ccli8 1:eb1da9d36e12 38 /* Clear RTC alarm interrupt flag */
ccli8 1:eb1da9d36e12 39 RTC_CLEAR_ALARM_INT_FLAG();
ccli8 1:eb1da9d36e12 40
ccli8 1:eb1da9d36e12 41 wakeup_eventflags.set(EventFlag_Wakeup_RTC_Alarm);
ccli8 1:eb1da9d36e12 42 }
ccli8 1:eb1da9d36e12 43 #endif
ccli8 4:da41f0e17d5a 44
ccli8 4:da41f0e17d5a 45 /* Wake up RTC loop to schedule another RTC alarm */
ccli8 4:da41f0e17d5a 46 sem_rtc.release();
ccli8 1:eb1da9d36e12 47 }
ccli8 1:eb1da9d36e12 48
ccli8 1:eb1da9d36e12 49 void config_rtc_wakeup(void)
ccli8 1:eb1da9d36e12 50 {
ccli8 5:fdfb7a10cc59 51 static Thread thread_rtc(osPriorityNormal, 2048);
ccli8 4:da41f0e17d5a 52
ccli8 4:da41f0e17d5a 53 Callback<void()> callback(&rtc_loop);
ccli8 4:da41f0e17d5a 54 thread_rtc.start(callback);
ccli8 1:eb1da9d36e12 55 }
ccli8 1:eb1da9d36e12 56
ccli8 4:da41f0e17d5a 57 void rtc_loop(void)
ccli8 1:eb1da9d36e12 58 {
ccli8 4:da41f0e17d5a 59 /* Schedule RTC alarm in 3 secs */
ccli8 4:da41f0e17d5a 60 schedule_rtc_alarm(3);
ccli8 1:eb1da9d36e12 61
ccli8 4:da41f0e17d5a 62 while (true) {
ccli8 4:da41f0e17d5a 63 int32_t sem_tokens = sem_rtc.wait(osWaitForever);
ccli8 4:da41f0e17d5a 64 if (sem_tokens < 1) {
ccli8 4:da41f0e17d5a 65 printf("RTC Alarm fails with Semaphore.wait(): %d\n", sem_tokens);
ccli8 4:da41f0e17d5a 66 }
ccli8 4:da41f0e17d5a 67 else {
ccli8 4:da41f0e17d5a 68 /* Re-schedule RTC alarm in 3 secs */
ccli8 4:da41f0e17d5a 69 schedule_rtc_alarm(3);
ccli8 4:da41f0e17d5a 70 }
ccli8 4:da41f0e17d5a 71 }
ccli8 4:da41f0e17d5a 72 }
ccli8 4:da41f0e17d5a 73
ccli8 4:da41f0e17d5a 74 void schedule_rtc_alarm(uint32_t secs)
ccli8 4:da41f0e17d5a 75 {
ccli8 1:eb1da9d36e12 76 /* time() will call set_time(0) internally to set timestamp if rtc is not yet enabled, where the 0 timestamp
ccli8 1:eb1da9d36e12 77 * corresponds to 00:00 hours, Jan 1, 1970 UTC. But Nuvoton mcu's rtc supports calendar since 2000 and 1970
ccli8 1:eb1da9d36e12 78 * is not supported. For this test, a timestamp after 2000 is explicitly set. */
ccli8 1:eb1da9d36e12 79 {
ccli8 1:eb1da9d36e12 80 static bool time_inited = false;
ccli8 1:eb1da9d36e12 81
ccli8 1:eb1da9d36e12 82 if (! time_inited) {
ccli8 1:eb1da9d36e12 83 time_inited = true;
ccli8 1:eb1da9d36e12 84
ccli8 1:eb1da9d36e12 85 #define CUSTOM_TIME 1256729737
ccli8 1:eb1da9d36e12 86 set_time(CUSTOM_TIME); // Set RTC time to Wed, 28 Oct 2009 11:35:37
ccli8 1:eb1da9d36e12 87 }
ccli8 1:eb1da9d36e12 88 }
ccli8 1:eb1da9d36e12 89
ccli8 10:d2e2c79389e1 90 #if defined(TARGET_NUMAKER_PFM_NANO130)
ccli8 10:d2e2c79389e1 91 RTC_DisableInt(RTC_RIER_AIER_Msk);
ccli8 10:d2e2c79389e1 92 #else
ccli8 1:eb1da9d36e12 93 RTC_DisableInt(RTC_INTEN_ALMIEN_Msk);
ccli8 10:d2e2c79389e1 94 #endif
ccli8 1:eb1da9d36e12 95
ccli8 1:eb1da9d36e12 96 time_t t = time(NULL);
ccli8 1:eb1da9d36e12 97 t += secs; // Schedule RTC alarm after secs
ccli8 1:eb1da9d36e12 98
ccli8 1:eb1da9d36e12 99 // Convert timestamp to struct tm
ccli8 1:eb1da9d36e12 100 struct tm timeinfo;
ccli8 1:eb1da9d36e12 101 if (_rtc_localtime(t, &timeinfo) == false) {
ccli8 1:eb1da9d36e12 102 printf("config_rtc_alarm() fails\n");
ccli8 1:eb1da9d36e12 103 return;
ccli8 1:eb1da9d36e12 104 }
ccli8 1:eb1da9d36e12 105
ccli8 1:eb1da9d36e12 106 S_RTC_TIME_DATA_T rtc_datetime;
ccli8 1:eb1da9d36e12 107
ccli8 1:eb1da9d36e12 108 // Convert struct tm to S_RTC_TIME_DATA_T
ccli8 1:eb1da9d36e12 109 rtc_datetime.u32Year = timeinfo.tm_year + YEAR0;
ccli8 1:eb1da9d36e12 110 rtc_datetime.u32Month = timeinfo.tm_mon + 1;
ccli8 1:eb1da9d36e12 111 rtc_datetime.u32Day = timeinfo.tm_mday;
ccli8 1:eb1da9d36e12 112 rtc_datetime.u32DayOfWeek = timeinfo.tm_wday;
ccli8 1:eb1da9d36e12 113 rtc_datetime.u32Hour = timeinfo.tm_hour;
ccli8 1:eb1da9d36e12 114 rtc_datetime.u32Minute = timeinfo.tm_min;
ccli8 1:eb1da9d36e12 115 rtc_datetime.u32Second = timeinfo.tm_sec;
ccli8 1:eb1da9d36e12 116 rtc_datetime.u32TimeScale = RTC_CLOCK_24;
ccli8 1:eb1da9d36e12 117
ccli8 1:eb1da9d36e12 118 RTC_SetAlarmDateAndTime(&rtc_datetime);
ccli8 1:eb1da9d36e12 119
ccli8 1:eb1da9d36e12 120 /* NOTE: The Mbed RTC HAL implementation of Nuvoton's targets doesn't use interrupt, so we can override vector
ccli8 1:eb1da9d36e12 121 handler (via NVIC_SetVector). */
ccli8 1:eb1da9d36e12 122 /* NOTE: The name of symbol PWRWU_IRQHandler is mangled in C++ and cannot override that in startup file in C.
ccli8 1:eb1da9d36e12 123 * So the NVIC_SetVector call cannot be left out. */
ccli8 1:eb1da9d36e12 124 NVIC_SetVector(RTC_IRQn, (uint32_t) RTC_IRQHandler);
ccli8 1:eb1da9d36e12 125 NVIC_EnableIRQ(RTC_IRQn);
ccli8 1:eb1da9d36e12 126 /* Enable RTC alarm interrupt and wake-up function will be enabled also */
ccli8 10:d2e2c79389e1 127 #if defined(TARGET_NUMAKER_PFM_NANO130)
ccli8 10:d2e2c79389e1 128 RTC_EnableInt(RTC_RIER_AIER_Msk);
ccli8 10:d2e2c79389e1 129 #else
ccli8 1:eb1da9d36e12 130 RTC_EnableInt(RTC_INTEN_ALMIEN_Msk);
ccli8 10:d2e2c79389e1 131 #endif
ccli8 1:eb1da9d36e12 132 }