/* ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, 2011,2012 Giovanni Di Sirio. This file is part of ChibiOS/RT. ChibiOS/RT is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. ChibiOS/RT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* This structure is used to hold the values representing a calendar time. It contains the following members, with the meanings as shown. int tm_sec seconds after minute [0-61] (61 allows for 2 leap-seconds) int tm_min minutes after hour [0-59] int tm_hour hours after midnight [0-23] int tm_mday day of the month [1-31] int tm_mon month of year [0-11] int tm_year current year-1900 int tm_wday days since Sunday [0-6] int tm_yday days since January 1st [0-365] int tm_isdst daylight savings indicator (1 = yes, 0 = no, -1 = unknown) */ #define WAKEUP_TEST FALSE #include #include #include #include "ch.h" #include "hal.h" #include "shell.h" #include "chprintf.h" #include "chrtclib.h" #if WAKEUP_TEST static RTCWakeup wakeupspec; #endif static RTCAlarm alarmspec; static time_t unix_time; /* libc stub */ int _getpid(void) {return 1;} /* libc stub */ void _exit(int i) {(void)i;} /* libc stub */ #include #undef errno extern int errno; int _kill(int pid, int sig) { (void)pid; (void)sig; errno = EINVAL; return -1; } /* sleep indicator thread */ static WORKING_AREA(blinkWA, 128); static msg_t blink_thd(void *arg){ (void)arg; while (TRUE) { chThdSleepMilliseconds(100); palTogglePad(GPIOB, GPIOB_LED_R); } return 0; } static void func_sleep(void){ chSysLock(); SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; PWR->CR |= (PWR_CR_PDDS | PWR_CR_LPDS | PWR_CR_CSBF | PWR_CR_CWUF); RTC->ISR &= ~(RTC_ISR_ALRBF | RTC_ISR_ALRAF | RTC_ISR_WUTF | RTC_ISR_TAMP1F | RTC_ISR_TSOVF | RTC_ISR_TSF); __WFI(); } static void cmd_sleep(BaseSequentialStream *chp, int argc, char *argv[]){ (void)argv; if (argc > 0) { chprintf(chp, "Usage: sleep\r\n"); return; } chprintf(chp, "Going to sleep.\r\n"); chThdSleepMilliseconds(200); /* going to anabiosis */ func_sleep(); } /* * */ static void cmd_alarm(BaseSequentialStream *chp, int argc, char *argv[]){ int i = 0; (void)argv; if (argc < 1) { goto ERROR; } if ((argc == 1) && (strcmp(argv[0], "get") == 0)){ rtcGetAlarm(&RTCD1, 0, &alarmspec); chprintf(chp, "%D%s",alarmspec," - alarm in STM internal format\r\n"); return; } if ((argc == 2) && (strcmp(argv[0], "set") == 0)){ i = atol(argv[1]); alarmspec.tv_datetime = ((i / 10) & 7 << 4) | (i % 10) | RTC_ALRMAR_MSK4 | RTC_ALRMAR_MSK3 | RTC_ALRMAR_MSK2; rtcSetAlarm(&RTCD1, 0, &alarmspec); return; } else{ goto ERROR; } ERROR: chprintf(chp, "Usage: alarm get\r\n"); chprintf(chp, " alarm set N\r\n"); chprintf(chp, "where N is alarm time in seconds\r\n"); } /* * */ static void cmd_date(BaseSequentialStream *chp, int argc, char *argv[]){ (void)argv; struct tm timp; if (argc == 0) { goto ERROR; } if ((argc == 1) && (strcmp(argv[0], "get") == 0)){ unix_time = rtcGetTimeUnixSec(&RTCD1); if (unix_time == -1){ chprintf(chp, "incorrect time in RTC cell\r\n"); } else{ chprintf(chp, "%D%s",unix_time," - unix time\r\n"); rtcGetTimeTm(&RTCD1, &timp); chprintf(chp, "%s%s",asctime(&timp)," - formatted time string\r\n"); } return; } if ((argc == 2) && (strcmp(argv[0], "set") == 0)){ unix_time = atol(argv[1]); if (unix_time > 0){ rtcSetTimeUnixSec(&RTCD1, unix_time); return; } else{ goto ERROR; } } else{ goto ERROR; } ERROR: chprintf(chp, "Usage: date get\r\n"); chprintf(chp, " date set N\r\n"); chprintf(chp, "where N is time in seconds sins Unix epoch\r\n"); chprintf(chp, "you can get current N value from unix console by the command\r\n"); chprintf(chp, "%s", "date +\%s\r\n"); return; } static SerialConfig ser_cfg = { 115200, 0, 0, 0, }; static const ShellCommand commands[] = { {"alarm", cmd_alarm}, {"date", cmd_date}, {"sleep", cmd_sleep}, {NULL, NULL} }; static const ShellConfig shell_cfg1 = { (BaseSequentialStream *)&SD2, commands }; /** * Main function. */ int main(void){ halInit(); chSysInit(); chThdCreateStatic(blinkWA, sizeof(blinkWA), NORMALPRIO, blink_thd, NULL); #if !WAKEUP_TEST /* switch off wakeup */ rtcSetPeriodicWakeup_v2(&RTCD1, NULL); /* Shell initialization.*/ sdStart(&SD2, &ser_cfg); shellInit(); static WORKING_AREA(waShell, 1024); shellCreateStatic(&shell_cfg1, waShell, sizeof(waShell), NORMALPRIO); /* wait until user do not want to test wakeup */ while (TRUE){ chThdSleepMilliseconds(200); } #else /* set wakeup */ wakeupspec.wakeup = ((uint32_t)4) << 16; /* select 1 Hz clock source */ wakeupspec.wakeup |= 9; /* set counter value to 9. Period will be 9+1 seconds. */ rtcSetPeriodicWakeup_v2(&RTCD1, &wakeupspec); chThdSleepSeconds(3); func_sleep(); #endif /* !WAKEUP_TEST */ return 0; }