在RTT提供RTC alarm.c文件是缺少两个命令字的实现的。分别为
RT_DEVICE_CTRL_RTC_SET_ALARM,RT_DEVICE_CTRL_RTC_GET_ALARM。
分析alarm文件实现方法,可见由一个事件集IPC同步控制alarm的主线程。
/** \brief rtc alarm service thread entry
*
*/
static void rt_alarmsvc_thread_init(void *param)
{
rt_uint32_t recv;
_container.current = RT_NULL;
while (1)
{
if (rt_event_recv(&_container.event, 0xFFFF,
RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
RT_WAITING_FOREVER, &recv) == RT_EOK)
{
alarm_update(recv);
}
}
}
然后就找到发送事件同步函数代码
void rt_alarm_update(rt_device_t dev, rt_uint32_t event)
{
rt_event_send(&_container.event, 1);
}
4. 这样,只要在驱动drv_rtc.c添加相应的配置代码,实验alarm功能即可完成alarm.c的功能。配合stm32cubemx,生成相关代码。并在MDK上调试通过,采用中断方式响应。通过后,再移植到STUDIO上即可。
5.drv_rtc.c添加设置与查询函数
static rt_err_t rt_rtc_control(rt_device_t dev, int cmd, void args)
{
rt_err_t result = RT_EOK;
RT_ASSERT(dev != RT_NULL);
switch (cmd)
{
case RT_DEVICE_CTRL_RTC_GET_TIME: (rt_uint32_t )args = get_rtc_timestamp();
LOG_D(“RTC: get rtc_time %x\n”, (rt_uint32_t *)args);
break;
case RT_DEVICE_CTRL_RTC_SET_TIME:
if (set_rtc_time_stamp(*(rt_uint32_t *)args))
{
result = -RT_ERROR;
}
LOG_D("RTC: set rtc_time %x\n", *(rt_uint32_t *)args);
break;
case RT_DEVICE_CTRL_RTC_SET_ALARM:
if (set_rtc_alarm_stamp(*(struct rt_rtc_wkalarm *)args))
{
result = -RT_ERROR;
}
LOG_D("RTC: set rtc_alarm tme : hour: %d , min: %d , sec: %d \n", *(struct rt_rtc_wkalarm *)args->tm_hour,*(struct rt_rtc_wkalarm *)args->tm_min,*(struct rt_rtc_wkalarm *)args->tm_sec);
break;
case RT_DEVICE_CTRL_RTC_GET_ALARM:
*(struct rt_rtc_wkalarm *)args = get_rtc_alarm_stamp();
LOG_D("RTC: get rtc_alarm time : hour: %d , min: %d , sec: %d \n", *(struct rt_rtc_wkalarm *)args->tm_hour,*(struct rt_rtc_wkalarm *)args->tm_min,*(struct rt_rtc_wkalarm *)args->tm_sec);
break;
}
return result;
}
6. 对应的子函数的实现
static rt_err_t set_rtc_alarm_stamp(struct rt_rtc_wkalarm wkalarm)
{
RTC_AlarmTypeDef sAlarm = {0};
if(wkalarm.enable == RT_FALSE)
{
if (HAL_RTC_DeactivateAlarm(&RTC_Handler,RTC_ALARM_A) != HAL_OK)
{
return -RT_ERROR;
}
LOG_D("stop rtc alarm.");
}else {
sAlarm.AlarmTime.Hours = wkalarm.tm_hour;
sAlarm.AlarmTime.Minutes = wkalarm.tm_min;
sAlarm.AlarmTime.Seconds = wkalarm.tm_sec;
sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY;
sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
sAlarm.AlarmDateWeekDay = 1;
sAlarm.Alarm = RTC_ALARM_A;
if (HAL_RTC_SetAlarm_IT(&RTC_Handler, &sAlarm, RTC_FORMAT_BIN) != HAL_OK)
{
return -RT_ERROR;
}
LOG_D("set rtc alarm.");
}
return RT_EOK;
}
/ USER CODE END RTC_Alarm_IRQn 0 /
HAL_RTC_AlarmIRQHandler(&RTC_Handler);
/ USER CODE BEGIN RTC_Alarm_IRQn 1 /
/ USER CODE END RTC_Alarm_IRQn 1 /
}
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
rt_alarm_update(0,0);
}
struct rt_rtc_wkalarm get_rtc_alarm_stamp(void)
{
RTC_AlarmTypeDef sAlarm = {0};
struct rt_rtc_wkalarm wkalarm;
if (HAL_RTC_GetAlarm(&RTC_Handler, &sAlarm,RTC_ALARM_A, RTC_FORMAT_BIN) != HAL_OK)
{
LOG_D(“get rtc alarm fail!.”);
}
wkalarm.tm_sec = sAlarm.AlarmTime.Seconds;
wkalarm.tm_min = sAlarm.AlarmTime.Minutes;
wkalarm.tm_hour = sAlarm.AlarmTime.Hours;
LOG_D("get rtc alarm.");
return wkalarm;
}
7. 我是采用中断方式响应事件,上面代码添加中断处理函数。在回调里实现发送事件。
/ USER CODE END RTC_Alarm_IRQn 0 /
HAL_RTC_AlarmIRQHandler(&RTC_Handler);
/ USER CODE BEGIN RTC_Alarm_IRQn 1 /
/ USER CODE END RTC_Alarm_IRQn 1 /
}
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
rt_alarm_update(0,0);
}
8. 由于采用了中断,所以初始化要增加中继使能
HAL_NVIC_SetPriority(RTC_Alarm_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
原作者:mii
|