RTC 时间设置

              MMI

                |

                |

    alarm.c----alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)--case ANDROID_ALARM_SET_RTC:

                |

                |

          interface.c----rtc_set_time(alarm_rtc_dev, &rtc_new_rtc_time);

                |

                |

                V

          rtc-m41t94.c---- m41t94_set_time(struct device *dev, struct rtc_time *tm)

 


static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)

{

;

;

 case ANDROID_ALARM_SET_RTC:
  if (copy_from_user(&new_rtc_time, (void __user *)arg,
      sizeof(new_rtc_time))) {
   rv = -EFAULT;
   goto err1;
  }
  rtc_time_to_tm(new_rtc_time.tv_sec, &rtc_new_rtc_time);

  ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_IO,
   "set rtc %ld %ld - rtc %02d:%02d:%02d %02d/%02d/%04d/n",
   new_rtc_time.tv_sec, new_rtc_time.tv_nsec,
   rtc_new_rtc_time.tm_hour, rtc_new_rtc_time.tm_min,
   rtc_new_rtc_time.tm_sec, rtc_new_rtc_time.tm_mon + 1,
   rtc_new_rtc_time.tm_mday,
   rtc_new_rtc_time.tm_year + 1900);

  mutex_lock(&alarm_setrtc_mutex);
  spin_lock_irqsave(&alarm_slock, flags);
  for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++)
   hrtimer_try_to_cancel(&alarm_timer[i]);
  getnstimeofday(&tmp_time);
  elapsed_rtc_delta = timespec_sub(elapsed_rtc_delta,
     timespec_sub(tmp_time, new_rtc_time));
  spin_unlock_irqrestore(&alarm_slock, flags);
  rv = do_settimeofday(&new_rtc_time);
  spin_lock_irqsave(&alarm_slock, flags);
  for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++)
   alarm_start_hrtimer(i);
  spin_unlock_irqrestore(&alarm_slock, flags);
  if (rv < 0) {
   ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_ERRORS,
           "Failed to set time/n");
   mutex_unlock(&alarm_setrtc_mutex);
   goto err1;
  }
  rv = rtc_set_time(alarm_rtc_dev, &rtc_new_rtc_time);
  spin_lock_irqsave(&alarm_slock, flags);
  alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
  wake_up(&alarm_wait_queue);
  spin_unlock_irqrestore(&alarm_slock, flags);
  mutex_unlock(&alarm_setrtc_mutex);
  if (rv < 0) {
   ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_ERRORS,
       "Failed to set RTC, time will be lost on reboot/n");
   goto err1;
  }
  break;

 

}

android RTC 时间设置,

1,用户设置时间,MMI通过ioctrl命令调用,

2,内核执行alarm_ioctl的

 case ANDROID_ALARM_SET_RTC:

3,

将用户空间的时间参数通过copy_from_user取出。为绝对的秒保持在new_rtc_time.tv_sec

4,通过rtc_time_to_tm(new_rtc_time.tv_sec, &rtc_new_rtc_time);将绝对的秒转换为年月日时分秒格式放到rtc_new_rtc_time

struct rtc_time {
 int tm_sec;
 int tm_min;
 int tm_hour;
 int tm_mday;
 int tm_mon;
 int tm_year;
 int tm_wday;
 int tm_yday;
 int tm_isdst;
};
5,  因为要对RTC操作,要用mutex_lock(&alarm_setrtc_mutex);加锁

要清除alarm,要用 spin_lock_irqsave(&alarm_slock, flags);加锁

getnstimeofday(&tmp_time);获得ns级的时间

然后可调用do_settimeofday同步系统时钟:

通过函数

  rv = rtc_set_time(alarm_rtc_dev, &rtc_new_rtc_time);

调用interface.c 的

err = mutex_lock_interruptible(&rtc->ops_lock);

  err = rtc->ops->set_time(rtc->dev.parent, tm);
        mutex_unlock(&rtc->ops_lock);

调用硬件RTC的驱动

static const struct rtc_class_ops m41t94_rtc_ops = {
 .read_time = m41t94_read_time,
 .set_time = m41t94_set_time,
};

的m41t94_set_time设置到硬件RTC芯片

 

 spin_lock_irqsave(&alarm_slock, flags);
  alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
  wake_up(&alarm_wait_queue);
  spin_unlock_irqrestore(&alarm_slock, flags);  释放原来申请的锁
  mutex_unlock(&alarm_setrtc_mutex);   释放原来申请的锁

 

因为时间改了。唤醒alarm队列,释放原来申请的锁alarm_slock和alarm_setrtc_mutex

 

 


 

 

 

### 使用STM32 HAL库配置和设置RTC实时钟时间 为了使用STM32 HAL库来配置并设置RTC实时时钟,需遵循一系列特定的操作流程。这包括初始化硬件资源、启用RTC功能以及设定初始时间和日期。 #### 1. 配置外部低速晶振(LSE) 由于LSE用于提供精确的时间基准,在启动之前需要确保其正常工作: ```c // 复位备份区域以清除任何先前状态 BKP_DeInit(); // 启用外部低速晶振(LSE) RCC_LSEConfig(RCC_LSE_ON); uint8_t temp = 0; while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET && temp < 250) { temp++; delay_ms(10); } if (temp >= 250) return 1; // 如果超过尝试次数则返回错误代码表示失败[^1] // 设置RTC时钟源为LSE RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); // 使能RTC时钟 RCC_RTCCLKCmd(ENABLE); ``` 这段代码首先复位备份域(BKP),接着开启LSE,并通过轮询方式确认LSE已准备好。如果未能成功,则退出函数并报告错误。最后选择LSE作为RTC的时钟源并激活RTC模块。 #### 2. 初始化RTC预分频寄存器 为了让RTC能够按照预期频率运行,还需要适当调整预分频系数: ```c // 设定RTC预分频值为32767,即每秒触发一次更新事件 RTC_SetPrescaler(32767); ``` 此操作使得RTC能够在一秒内完成一次完整的计数周期,从而实现精准的时间测量。 #### 3. 设置当前时间和日期 一旦完成了上述准备工作之后就可以正式写入所需的时间戳了: ```c RTC_TimeTypeDef sTime = {0}; sTime.Hours = 14; /* 小时 */ sTime.Minutes = 30; /* 分钟 */ sTime.Seconds = 0; /* 秒 */ /* 调用HAL库API设置时间 */ HAL_StatusTypeDef status_time = HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN); RTC_DateTypeDef sDate = {0}; sDate.WeekDay = RTC_WEEKDAY_MONDAY; sDate.Month = RTC_MONTH_JANUARY; sDate.Date = 1; sDate.Year = 0; /* 调用HAL库API设置日期 */ HAL_StatusTypeDef status_date = HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN); if ((status_time != HAL_OK) || (status_date != HAL_OK)) { Error_Handler(); } void Error_Handler(void){ while(1){} } ``` 这里定义了一个`RTC_TimeTypeDef`结构体变量`sTime`用来存储具体时刻的信息;同样地也创建了另一个名为`sDate`的对象保存对应的日历数据。随后调用了两个不同的HAL API分别负责处理各自的任务—一个是针对时间部分(`HAL_RTC_SetTime`)而另一个则是关于日期方面(`HAL_RTC_SetDate`)的工作。注意这里的格式参数被指定成了二进制形式(`RTC_FORMAT_BIN`)以便于更直观地理解数值含义。 #### 4. 获取最新时间和日期 当需要读取最新的时间或日期信息时,应该先获取时间再获取日期以保证数据的一致性和准确性: ```c RTC_TimeTypeDef currentTime; HAL_RTC_GetTime(&hrtc, &currentTime, RTC_FORMAT_BIN); RTC_DateTypeDef currentDate; HAL_RTC_GetDate(&hrtc, &currentDate, RTC_FORMAT_BIN); ``` 这种顺序可以防止因两者之间存在延迟而导致显示不同步的情况发生[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值