From a78bdc94591baba438ca40e563286aa8d060e8ba Mon Sep 17 00:00:00 2001 From: Peter Wittich Date: Fri, 26 Nov 2021 23:04:50 -0500 Subject: [PATCH] Enable RTC in Hibernation module and add a basic CLI for setting it (#118) * Start of use of Hibernation module in Calendar mode for wall clock time * CLI interface to time control * RTC for REV2 only --- makedefs | 6 +- projects/cm_mcu/CommandLineTask.c | 8 +++ projects/cm_mcu/LocalTasks.c | 53 +++++++++++++++-- projects/cm_mcu/Tasks.h | 3 + projects/cm_mcu/cm_mcu.c | 6 ++ projects/cm_mcu/commands/BoardCommands.c | 74 +++++++++++++++++++++++- projects/cm_mcu/commands/BoardCommands.h | 1 + 7 files changed, 143 insertions(+), 8 deletions(-) diff --git a/makedefs b/makedefs index cd09d187..3704de82 100644 --- a/makedefs +++ b/makedefs @@ -109,8 +109,8 @@ CFLAGS=-mthumb \ -Wall \ -pedantic \ -DPART_${PART} \ - -Wdouble-promotion \ - -fstack-usage \ + -Wdouble-promotion \ + -fstack-usage \ -c # @@ -131,7 +131,7 @@ LD=${PREFIX}-ld # # The flags passed to the linker. # -LDFLAGS=--gc-sections +LDFLAGS=--gc-sections #-specs=nano.specs -specs=nosys.specs # # Get the location of libgcc.a from the GCC front-end. diff --git a/projects/cm_mcu/CommandLineTask.c b/projects/cm_mcu/CommandLineTask.c index bfcac190..5f2cd59c 100644 --- a/projects/cm_mcu/CommandLineTask.c +++ b/projects/cm_mcu/CommandLineTask.c @@ -676,6 +676,14 @@ static struct command_t commands[] = { TaskStatsCommand, "Displays a table showing the state of each FreeRTOS task\r\n", 0 }, +#ifdef REV2 + { + "time", + time_ctl, + "(set HH:MM:SS MM/DD/YYYY| #include #include // memset +#include // struct tm + +// ROM header must come before MAP header +#include "driverlib/rom.h" +#include "driverlib/rom_map.h" +#include "inc/hw_types.h" +#include "inc/hw_hibernate.h" +#include "driverlib/hibernate.h" #include "Tasks.h" #include "MonitorTask.h" @@ -218,25 +226,25 @@ void LGA80D_init(void) &page); if (r) { log_debug(LOG_SERVICE, "dev = %d, page = %d, r= %d\r\n", dev, page, r); - log_error(LOG_SERVICE, "error(0)\r\n"); + log_error(LOG_SERVICE, "LGA80D(0)\r\n"); } // actual command -- frequency switch r = apollo_pmbus_rw(&g_sMaster1, &eStatus1, false, pm_addrs_dcdc + dev, &extra_cmds[2], (uint8_t *)&freqlin11); if (r) { - log_error(LOG_SERVICE, "error(1)\r\n"); + log_error(LOG_SERVICE, "LGA80D(1)\r\n"); } // actual command -- vout_droop switch r = apollo_pmbus_rw(&g_sMaster1, &eStatus1, false, pm_addrs_dcdc + dev, &extra_cmds[5], (uint8_t *)&drooplin11); if (r) { - log_error(LOG_SERVICE, "error(2)\r\n"); + log_error(LOG_SERVICE, "LGA80D(2)\r\n"); } // actual command -- multiphase_ramp_gain switch uint8_t val = 0x7U; // by suggestion of Artesian r = apollo_pmbus_rw(&g_sMaster1, &eStatus1, false, pm_addrs_dcdc + dev, &extra_cmds[6], &val); if (r) { - log_error(LOG_SERVICE, "error(3)\r\n"); + log_error(LOG_SERVICE, "LGA80D(3)\r\n"); } } } @@ -348,3 +356,40 @@ void initFPGAMon() #endif // REV1 } } + +#ifdef REV2 +// initialize the real-time clock, which lives in the Hibernate Module in the TM4C1294NCPDT +extern uint32_t g_ui32SysClock; + +void InitRTC() +{ + // Enable the RTC module + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE); + // wait for it to be ready + while (! ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_HIBERNATE) ) + { + + } + // Enable the clocking. AFAIK the argument is not used + ROM_HibernateEnableExpClk(g_ui32SysClock); + // Set to use external crystal with 12 pF drive + ROM_HibernateClockConfig(HIBERNATE_OSC_LOWDRIVE ); + // enable the RTC + ROM_HibernateRTCEnable(); + // set the RTC to calendar mode + ROM_HibernateCounterMode(HIBERNATE_COUNTER_24HR); + // set to a default value + struct tm now = { + .tm_sec = 0, + .tm_min = 0, + .tm_hour = 0, + .tm_mday = 23, + .tm_mon = 10, // month goes from 0-11 + .tm_year = 121, // year is since 1900 + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0, + }; + ROM_HibernateCalendarSet(&now); +} +#endif // REV2 diff --git a/projects/cm_mcu/Tasks.h b/projects/cm_mcu/Tasks.h index cf018b3a..7f5b188f 100644 --- a/projects/cm_mcu/Tasks.h +++ b/projects/cm_mcu/Tasks.h @@ -228,6 +228,9 @@ uint16_t getZYNQMonTestData(); const uint32_t *getSystemStack(); int SystemStackWaterHighWaterMark(); +// hibernate/RTC +void InitRTC(); + struct dev_i2c_addr_t; // forward reference void snapdump(struct dev_i2c_addr_t *add, uint8_t page, uint8_t snapshot[32], bool reset); diff --git a/projects/cm_mcu/cm_mcu.c b/projects/cm_mcu/cm_mcu.c index 24055648..8bd71428 100644 --- a/projects/cm_mcu/cm_mcu.c +++ b/projects/cm_mcu/cm_mcu.c @@ -199,6 +199,11 @@ void SystemInitInterrupts() setupActiveLowPins(); +#ifdef REV2 + // RTC in the Hibernation module + InitRTC(); +#endif // REV2 + // SYSTICK timer -- this is already enabled in the portable layer return; } @@ -240,6 +245,7 @@ int main(void) initFPGAMon(); + // all facilities start at INFO for (enum log_facility_t i = 0; i < NUM_LOG_FACILITIES; ++i) { log_set_level(LOG_INFO, i); diff --git a/projects/cm_mcu/commands/BoardCommands.c b/projects/cm_mcu/commands/BoardCommands.c index e384b015..f9921284 100644 --- a/projects/cm_mcu/commands/BoardCommands.c +++ b/projects/cm_mcu/commands/BoardCommands.c @@ -4,9 +4,10 @@ * Created on: Jan 18, 2021 * Author: fatimayousuf */ - +#include #include "BoardCommands.h" #include "common/pinsel.h" +#include "driverlib/hibernate.h" // This command takes no arguments BaseType_t restart_mcu(int argc, char **argv, char* m) @@ -127,4 +128,75 @@ BaseType_t jtag_sm_ctl(int argc, char **argv, char *m) } return pdFALSE; } +#include "inc/hw_hibernate.h" +BaseType_t time_ctl(int argc, char **argv, char *m) +{ + int copied = 0; + if (argc == 4) { + if (strncmp(argv[1], "set", 3) == 0) { + // we don't have access to sscanf, let alone strptime, since it requires _sbrk ... + // convert HH:MM:SS into three strings + char *p = argv[2]; + char *pp[3]; + pp[0] = p; + int i = 1; + while ( *p != '\0') { + if ( *p == ':' ) { + pp[i++] = p+1; + *p = '\0'; + } + ++p; + } + BaseType_t hour, min, sec; + hour = atoi(pp[0]); + min = atoi(pp[1]); + sec = atoi(pp[2]); + // now convert MM/DD/YY into three strings + p = argv[3]; + pp[0] = p; + i = 1; + while ( *p != '\0') { + if ( *p == '/' ) { + pp[i++] = p+1; + *p = '\0'; + } + ++p; + } + + BaseType_t month, year, day; + + month = atoi(pp[0]); + day = atoi(pp[1]); + year = atoi(pp[2]); + struct tm t; + t.tm_hour = hour; + t.tm_min = min; + t.tm_sec = sec; + t.tm_year = year>=100?year-1900:year+1900; // years since 1900 + t.tm_mday = day; + t.tm_mon = month-1; // month goes from 0-11 + + copied += snprintf(m + copied, SCRATCH_SIZE - copied, "New time: %02d:%02d:%02d %02d/%02d/%d\r\n", + t.tm_hour, t.tm_min, t.tm_sec, t.tm_mon+1, t.tm_mday, t.tm_year+1900); + ROM_HibernateCalendarSet(&t); + } + else { + copied += snprintf(m + copied, SCRATCH_SIZE - copied, "Usage: %s set HH:MM:SS MM:DD:YYYY\r\n", argv[0]); + } + } + else { // all other cases + uint32_t ui32Date = HWREG(HIB_CAL1); + if ( ! (ui32Date & HIB_CAL1_VALID )) { + copied += snprintf(m+copied, SCRATCH_SIZE-copied, "%s: RTC state invalid\r\n", argv[0]); + } + else { + struct tm now; + ROM_HibernateCalendarGet(&now); + copied += snprintf(m + copied, SCRATCH_SIZE - copied, "Time now: %02d:%02d:%02d %02d/%02d/%d\r\n", + now.tm_hour, now.tm_min, now.tm_sec, now.tm_mon+1, now.tm_mday, now.tm_year+1900); + } + } + return pdFALSE; +} + #endif diff --git a/projects/cm_mcu/commands/BoardCommands.h b/projects/cm_mcu/commands/BoardCommands.h index ffc90e64..38653003 100644 --- a/projects/cm_mcu/commands/BoardCommands.h +++ b/projects/cm_mcu/commands/BoardCommands.h @@ -15,5 +15,6 @@ BaseType_t set_board_id(int argc, char **argv, char* m); BaseType_t set_board_id_password(int argc, char **argv, char* m); BaseType_t board_id_info(int argc, char **argv, char* m); BaseType_t jtag_sm_ctl(int argc, char **argv, char *m); +BaseType_t time_ctl(int argc, char **argv, char *m); #endif