static int rtc_post_skip (ulong * diff) { struct rtc_time tm1; struct rtc_time tm2; ulong start1; ulong start2; rtc_get (&tm1); start1 = get_timer (0); while (1) { rtc_get (&tm2); start2 = get_timer (0); if (tm1.tm_sec != tm2.tm_sec) break; if (start2 - start1 > 1500) break; } if (tm1.tm_sec != tm2.tm_sec) { *diff = start2 - start1; return 0; } else { return -1; } }
int do_date (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { struct rtc_time tm; int rcode = 0; int old_bus; /* switch to correct I2C bus */ old_bus = I2C_GET_BUS(); I2C_SET_BUS(CONFIG_SYS_RTC_BUS_NUM); switch (argc) { case 2: /* set date & time */ if (strcmp(argv[1],"reset") == 0) { puts ("Reset RTC...\n"); rtc_reset (); } else { /* initialize tm with current time */ rcode = rtc_get (&tm); if(!rcode) { /* insert new date & time */ if (mk_date (argv[1], &tm) != 0) { puts ("## Bad date format\n"); break; } /* and write to RTC */ rcode = rtc_set (&tm); if(rcode) puts("## Set date failled\n"); } else { puts("## Get date failled\n"); } } /* FALL TROUGH */ case 1: /* get date & time */ rcode = rtc_get (&tm); if (rcode) { puts("## Get date failled\n"); break; } printf ("Date: %4d-%02d-%02d (%sday) Time: %2d:%02d:%02d\n", tm.tm_year, tm.tm_mon, tm.tm_mday, (tm.tm_wday<0 || tm.tm_wday>6) ? "unknown " : RELOC(weekdays[tm.tm_wday]), tm.tm_hour, tm.tm_min, tm.tm_sec); break; default: cmd_usage(cmdtp); rcode = 1; } /* switch back to original I2C bus */ I2C_SET_BUS(old_bus); return rcode; }
uint_fast8_t platform_rtc_secs(void) { irqflags_t irqflags = di(); uint_fast8_t secs = rtc_get(0); irqrestore(irqflags); return secs; }
// clock commands static void cmd_clock(void) { u08 cmd, value; u08 exit = 0; rtc_time t; while((cmd = get_char()) != 0) { switch(cmd) { case '?': // get time (raw) { rtc_get(t); for(int i=0;i<7;i++) { uart_send_hex_byte_space(t[i]); } uart_send_crlf(); set_result(0); } break; case 't': // get time { u08 *str = (u08 *)rtc_get_time_str(); uart_send_string(str); uart_send_crlf(); } break; case 'y': // set year value = parse_hex_byte(0); rtc_set_entry(RTC_INDEX_YEAR, value); break; case 'o': // set year value = parse_hex_byte(1); rtc_set_entry(RTC_INDEX_MONTH, value); break; case 'd': // set day value = parse_hex_byte(1); rtc_set_entry(RTC_INDEX_DAY, value); break; case 'h': // set hour value = parse_hex_byte(0); rtc_set_entry(RTC_INDEX_HOUR, value); break; case 'i': // set minute value = parse_hex_byte(1); rtc_set_entry(RTC_INDEX_MINUTE, value); break; case 's': // set seconds value = parse_hex_byte(1); rtc_set_entry(RTC_INDEX_SECOND, value); break; default: set_result(ERROR_SYNTAX); case '.': exit = 1; break; } if(exit) break; } }
//实时时钟配置 //初始化RTC时钟,同时检测时钟是否工作正常 //BKP->DR1用于保存是否第一次配置的设置 //返回0:正常 //其他:错误代码 u8 rtc_init(void) { //检查是不是第一次配置时钟 u8 temp=0; if (BKP->DR1 != 0X5050)//第一次配置 { RCC->APB1ENR |= 1<<28; //使能电源时钟 RCC->APB1ENR |= 1<<27; //使能备份时钟 PWR->CR |= 1<<8; //取消备份区写保护 RCC->BDCR |= 1<<16; //备份区域软复位 RCC->BDCR &= ~(1<<16); //备份区域软复位结束 RCC->BDCR |= 1<<0; //开启外部低速振荡器 while ((!(RCC->BDCR&0X02)) && temp < 250)//等待外部时钟就绪 { temp++; delay_ms(10); }; if(temp>=250) return 1;//初始化时钟失败,晶振有问题 RCC->BDCR |= 1<<8; //LSI作为RTC时钟 RCC->BDCR |= 1<<15; //RTC时钟使能 while (!(RTC->CRL & (1<<5))) ; //等待RTC寄存器操作完成 while (!(RTC->CRL & (1<<3))) ; //等待RTC寄存器同步 RTC->CRH |= 0X01; //允许秒中断 while (!(RTC->CRL & (1<<5))) ; //等待RTC寄存器操作完成 RTC->CRL |= 1<<4; //允许配置 RTC->PRLH = 0X0000; RTC->PRLL = 32767; //时钟周期设置(有待观察,看是否跑慢了?)理论值:32767 //auto_time_set(); //rtc_set(2009,12,2,10,0,55); //设置时间 RTC->CRL &= ~(1<<4); //配置更新 while(!(RTC->CRL&(1<<5))) ; //等待RTC寄存器操作完成 BKP->DR1 = 0X5050; //BKP_Write(1,0X5050);; //在寄存器1标记已经开启了 //printf("FIRST TIME\n"); }else//系统继续计时 { while (!(RTC->CRL & (1 << 3))) ; //等待RTC寄存器同步 RTC->CRH |= 0X01; //允许秒中断 while (!(RTC->CRL & (1 << 5))) ; //等待RTC寄存器操作完成 //printf("OK\n"); } nvic_init(0,0,RTC_IRQChannel,2); //RTC,G2,P2,S2.优先级最低 rtc_get();//更新时间 return 0; //ok }
static inline time_t svc_get_sys_time() { #if (SYS_TIMER_SOFT_RTC == 0) return rtc_get(SYS_TIMER_RTC); #else TIME uptime; svc_get_uptime(&uptime); return uptime.sec + _sys_diff; #endif //SYS_TIMER_SOFT_RTC == 0 }
__time32_t (__time32)(__time32_t *t) { unsigned now = -1; #ifdef CONFIG_DRIVER_RTC now = rtc_get(); #endif if (t) { *t = (__time32_t) now; } return (__time32_t) now; }
int platform_rtc_read(void) { uint16_t len = sizeof(struct cmos_rtc); irqflags_t irqflags; struct cmos_rtc cmos; uint8_t *p; uint_fast8_t r, y; if (udata.u_count < len) len = udata.u_count; irqflags = di(); p = cmos.data.bytes; y = rtc_get(11); if (y >= 0x70) *p++ = 0x19; else *p++ = 0x20; *p++ = y; *p++ = rtc_get(9) & 0x1F; *p++ = rtc_get(7) & 0x3F; *p++ = rtc_get(4) & 0x3F; *p++ = rtc_get(2) & 0x7F; *p++ = rtc_get(0) & 0x7F; irqrestore(irqflags); cmos.type = CMOS_RTC_BCD; if (uput(&cmos, udata.u_base, len) == -1) return -1; return len; }
// Validate that the RTC is set to a valid time, and to a relatively // sane one. Report the validated or reset time back via rtc. void sanitize_rtc(void* ctx, fuchsia_hardware_rtc_Time* rtc, zx_status_t (*rtc_get)(void*, fuchsia_hardware_rtc_Time*), zx_status_t (*rtc_set)(void*, const fuchsia_hardware_rtc_Time*)) { // January 1, 2016 00:00:00 static const fuchsia_hardware_rtc_Time default_rtc = { .day = 1, .month = 1, .year = default_year, }; rtc_get(ctx, rtc); if (rtc_is_invalid(rtc) || rtc->year < default_year) { rtc_set(ctx, &default_rtc); *rtc = default_rtc; } }
//RTC中断服务函数 //const u8* Week[2][7]= //{ //{"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"}, //{"日","一","二","三","四","五","六"} //}; //RTC时钟中断 //每秒触发一次 void RTC_IRQHandler(void) { if(RTC->CRL & 0x0001)//秒钟中断 { rtc_get(); //更新时间 //printf("CRL:%d\n",RTC->CRL); } if(RTC->CRL & 0x0002)//闹钟中断 { //printf("Alarm!\n"); RTC->CRL &= ~(0x0002);//清闹钟中断 //闹钟处理 } RTC->CRL&=0X0FFA; //清除溢出,秒钟中断标志 while(!(RTC->CRL&(1<<5)));//等待RTC寄存器操作完成 }
int32_t kernel_main(multiboot_t *mboot_ptr) { textmode_init(); printf(" _____ _ _ ____ _____ \n / ____(_) | | / __ \\ / ____|\n | (___ _ _ __ ___ _ __ | | ___| | | | (___ \n \\___ \\| | '_ ` _ \\| '_ \\| |/ _ \\ | | |\\___ \\ \n ____) | | | | | | | |_) | | __/ |__| |____) |\n |_____/|_|_| |_| |_| .__/|_|\\___|\\____/|_____/ \n | | \n |_| \n"); textmode_set_colors(COLOR_RED, COLOR_BLACK); textmode_move_cursor(19, 6); printf("Version %i.%i.%i", VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD); textmode_move_cursor(19, 7); printf("Built %s", VERSION_DATE); textmode_set_colors(COLOR_GREEN, COLOR_BLACK); textmode_move_cursor(41, 6); printf("Written by Joe Biellik"); textmode_set_colors(COLOR_LTGRAY, COLOR_BLACK); textmode_move_cursor(0, 9); fpu_init(); gdt_init(); idt_init(); __asm __volatile__("sti"); // Start interrupts pit_init(); serial_init(); // Test serial int8_t buffer[50]; sprintf(buffer, "SimpleOS %i.%i.%i (%s)\n", VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_DATE); serial_write(SERIAL_PORT_A, buffer); // Test RTC datetime_t *dt = 0; rtc_get(dt); printf("Started at %02i-%02i-%02i %02i:%02i:%02i\n\n", dt->year, dt->month, dt->day, dt->hour, dt->min, dt->sec); // Test CPU cpu_detect(); printf("\n"); // Test PCI pci_scan(); for (;;); return 0x12345678; }
static inline uint32_t get_distance(uint32_t wakeup) { uint32_t distance = UINT32_MAX; /* A wakeup time of dg_configWAKEUP_XTAL16_TIME means infinite sleep * or disabled */ if (wakeup != dg_configWAKEUP_XTAL16_TIME) { distance = wakeup - rtc_get(); if (distance > (UINT32_MAX / 2)) { /* If it's too large, we've probably missed * the deadline. No sleep_duration for the MAC */ distance = 0; } } return distance; }
void time_init(void) { #ifdef CONFIG_BFIN_HAVE_RTC time_t secs_since_1970 = 0; /* Initialize the RTC sub-system */ rtc_init(); /* Retrieve calendar time (secs since Jan 1970) */ rtc_get(&secs_since_1970); #else time_t secs_since_1970 = (365 * 35 + 9) * 24 * 3600; /* 1 Jan 2005 */ #endif /* Initialize xtime. From now on, xtime is updated with timer interrupts */ xtime.tv_sec = secs_since_1970; xtime.tv_nsec = 0; wall_to_monotonic.tv_sec = -xtime.tv_sec; time_sched_init(timer_interrupt); }
static void prvTimeManageTask( void *pvParameters ) { configASSERT( ( ( unsigned long ) pvParameters ) == TIME_MANAGE_PARAMETER ); minute_count = 0; report_timeout = 60; // Produce a time report once every 60 minutes. /* @non-terminating@ */ for( ;; ) { if (rtc_triggered_a2()) { rtc_get(&time); minute_count++; if(minute_count == report_timeout) report_time(); update_absolute_time(); broadcast_minute(); rtc_reset_a2(); } exec_commands(); } }
int rtc_post_test (int flags) { ulong diff; unsigned int i; struct rtc_time svtm; static unsigned int daysnl[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; static unsigned int daysl[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; unsigned int ynl = 1999; unsigned int yl = 2000; unsigned int skipped = 0; int reliable; /* Time reliability */ reliable = rtc_get (&svtm); /* Time uniformity */ if (rtc_post_skip (&diff) != 0) { post_log ("Timeout while waiting for a new second !\n"); return -1; } for (i = 0; i < 5; i++) { if (rtc_post_skip (&diff) != 0) { post_log ("Timeout while waiting for a new second !\n"); return -1; } if (diff < 950 || diff > 1050) { post_log ("Invalid second duration !\n"); return -1; } } /* Passing month boundaries */ if (rtc_post_skip (&diff) != 0) { post_log ("Timeout while waiting for a new second !\n"); return -1; } rtc_get (&svtm); for (i = 0; i < 12; i++) { time_t t; struct rtc_time tm; tm.tm_year = ynl; tm.tm_mon = i + 1; tm.tm_mday = daysnl[i]; tm.tm_hour = 23; tm.tm_min = 59; tm.tm_sec = 59; t = rtc_mktime(&tm); rtc_to_tm(t, &tm); rtc_set (&tm); skipped++; if (rtc_post_skip (&diff) != 0) { rtc_post_restore (&svtm, skipped); post_log ("Timeout while waiting for a new second !\n"); return -1; } rtc_get (&tm); if (tm.tm_mon == i + 1) { rtc_post_restore (&svtm, skipped); post_log ("Month %d boundary is not passed !\n", i + 1); return -1; } } for (i = 0; i < 12; i++) { time_t t; struct rtc_time tm; tm.tm_year = yl; tm.tm_mon = i + 1; tm.tm_mday = daysl[i]; tm.tm_hour = 23; tm.tm_min = 59; tm.tm_sec = 59; t = rtc_mktime(&tm); rtc_to_tm(t, &tm); rtc_set (&tm); skipped++; if (rtc_post_skip (&diff) != 0) { rtc_post_restore (&svtm, skipped); post_log ("Timeout while waiting for a new second !\n"); return -1; } rtc_get (&tm); if (tm.tm_mon == i + 1) { rtc_post_restore (&svtm, skipped); post_log ("Month %d boundary is not passed !\n", i + 1); return -1; } } rtc_post_restore (&svtm, skipped); /* If come here, then RTC operates correcty, check the correctness * of the time it reports. */ if (reliable < 0) { post_log ("RTC Time is not reliable! Power fault? \n"); return -1; } return 0; }
static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { struct rtc_time tm; int rcode = 0; int old_bus __maybe_unused; /* switch to correct I2C bus */ #ifdef CONFIG_DM_RTC struct udevice *dev; rcode = uclass_get_device(UCLASS_RTC, 0, &dev); if (rcode) { printf("Cannot find RTC: err=%d\n", rcode); return CMD_RET_FAILURE; } #elif defined(CONFIG_SYS_I2C) old_bus = i2c_get_bus_num(); i2c_set_bus_num(CONFIG_SYS_RTC_BUS_NUM); #else old_bus = I2C_GET_BUS(); I2C_SET_BUS(CONFIG_SYS_RTC_BUS_NUM); #endif switch (argc) { case 2: /* set date & time */ if (strcmp(argv[1],"reset") == 0) { puts ("Reset RTC...\n"); #ifdef CONFIG_DM_RTC rcode = dm_rtc_reset(dev); if (!rcode) rcode = dm_rtc_set(dev, &default_tm); #else rtc_reset(); rcode = rtc_set(&default_tm); #endif if (rcode) puts("## Failed to set date after RTC reset\n"); } else { /* initialize tm with current time */ #ifdef CONFIG_DM_RTC rcode = dm_rtc_get(dev, &tm); #else rcode = rtc_get(&tm); #endif if (!rcode) { /* insert new date & time */ if (mk_date(argv[1], &tm) != 0) { puts ("## Bad date format\n"); break; } /* and write to RTC */ #ifdef CONFIG_DM_RTC rcode = dm_rtc_set(dev, &tm); #else rcode = rtc_set(&tm); #endif if (rcode) { printf("## Set date failed: err=%d\n", rcode); } } else { puts("## Get date failed\n"); } } /* FALL TROUGH */ case 1: /* get date & time */ #ifdef CONFIG_DM_RTC rcode = dm_rtc_get(dev, &tm); #else rcode = rtc_get(&tm); #endif if (rcode) { puts("## Get date failed\n"); break; } printf ("Date: %4d-%02d-%02d (%sday) Time: %2d:%02d:%02d\n", tm.tm_year, tm.tm_mon, tm.tm_mday, (tm.tm_wday<0 || tm.tm_wday>6) ? "unknown " : RELOC(weekdays[tm.tm_wday]), tm.tm_hour, tm.tm_min, tm.tm_sec); break; default: rcode = CMD_RET_USAGE; } /* switch back to original I2C bus */ #ifdef CONFIG_SYS_I2C i2c_set_bus_num(old_bus); #elif !defined(CONFIG_DM_RTC) I2C_SET_BUS(old_bus); #endif return rcode ? CMD_RET_FAILURE : 0; }
static void getRtcTime() { rtc_get(&timeData); }