这部分问题多多。
1.如何关机保持时间
1. 保证提供给RTC的3V电池有电;比较好就是挂个充电电池。也可以采用别的方案,我们公司就没有使用充电电池。不过个人认为还是使用充电电池好。
2. 更改2410的BSP,具体为:
在文件Platform/SMDK2410/kernel/hal/oemioctl.c中将
- case IOCTL_HAL_INIT_RTC:
- // The kernel has detected a cold-boot.
- if(nInBufSize >= sizeof(SYSTEMTIME))
- return OEMSetRealTime((LPSYSTEMTIME)lpInBuf);
- else
- return FALSE;
- break;
改为:
- case IOCTL_HAL_INIT_RTC:
- // The kernel has detected a cold-boot.
- if(nInBufSize >= sizeof(SYSTEMTIME))
- return TRUE; //改这里
- else
- return FALSE;
- break;
这个是我遇到的第一个问题。
2.如何保证开机时间不会跑飞,避免USB同步无法使用。
由于没有采用充电电池,在中间调试阶段又出现新问题了。我们的方案断电比较久的话就无法保持时间,实际上在开发阶段是不会带电池的,所以第二天工作都要重新校准系统的时间,不然USB无法同步上。为了解决这个问题,研究了内核这部分代码。发现有一些BUG。做了修正。
修改timer.c中的OEMSetRealTime(LPSYSTEMTIME lpst) 函数
- if ( firsttime == 0 )
- {
- OEMGetRealTime(lpst);
- if (lpst->wYear >2100 || lpst->wYear <2000)
- {
- lpst->wYear = 2008;
- lpst->wMonth = 9;
- lpst->wDay = 1;
- }
- firsttime = 1;
- }
主要是在第一次上电获取一下时间,并判断时间是否跑飞了。是的话给他初始化一个值。只要时间正常那么都能同步上PC。在S3C2410中rBCDYEAR虽然是uint型,但是根据CPU资料说明,他只能表示00-99这个范围的值。那么系统的时间也就只能是2000年至2099年了。改了这个,那么自然也就要把oemioctl.c中修改的代码还原,不然开机就不执行了。
3.修改年份超过2009年后时间获取的一个BUG。
研究过程中发现rBCDYEAR只最后一个字节有效,并且高4位表示年的十位数,低4位表示年的各位数。而在OEMGetRealTime函数中有这么一段代码
- if ( lpst->wSecond == 0 )
- {
- lpst->wSecond = FROM_BCD(s2410RTC->rBCDSEC & 0x7f);
- lpst->wMinute = FROM_BCD(s2410RTC->rBCDMIN & 0x7f);
- lpst->wHour = FROM_BCD(s2410RTC->rBCDHOUR& 0x3f);
- lpst->wDayOfWeek = (s2410RTC->rBCDDATE - 1);
- lpst->wDay = FROM_BCD(s2410RTC->rBCDDAY & 0x3f);
- lpst->wMonth = FROM_BCD(s2410RTC->rBCDMON & 0x1f);
- lpst->wYear = (2000 + s2410RTC->rBCDYEAR);
- }
其中lpst->wYear = (2000 + s2410RTC->rBCDYEAR); 让我是在很纳闷,怎么这里就不一样了。我还记得我开始在wince平台上编程时使用GetLocalTime函数的BUG(http://blog.csdn.net/constantine/archive/2007/09/21/1794368.aspx),这个BUG就是在wSecond为0时发生的,我想问题应该出在这里了。修改一下
- if ( lpst->wSecond == 0 )
- {
- .........
- lpst->wYear = 2000 + FROM_BCD(s2410RTC->rBCDYEAR); //修改这里
- }
果然问题没有了。
关于RTC设计的问题网上并不少,但是看过之后都是一个毛病。也不知道是谁错起头的,接着大家就跟着一起犯错。或者说还有我没看清除的情况,见鬼了。
当然,现在还不到2010年,估计没多少人注意到这个问题。