GD32F407V RTC实时时间有时不走动

[复制链接]
1319|2
 楼主| jacksonjim 发表于 2022-5-18 09:47 | 显示全部楼层 |阅读模式
本帖最后由 jacksonjim 于 2022-5-18 13:40 编辑

目前有个项目上使用RTC,一开始验证RTC时间是正常,使用外部LXATL晶振,后面整合到系统后,在做IAP升级操作时,没有进行全部擦除,只升级应用部分程序,目前出现问题是RTC 在内部有电池供电情况下,断了其它电源输入后时间会出现停止不走动或会遇到出现类似重置RTC 备份域的归零时间了,硬件上排查没有发现问题点,目前想知道有哪些初始化的关键点,是否引起这些问题!RTC初始化参考了GD官方的demo和其它几个示例进行修改,
另外 目前GD32好像没有找到关于时间同步校正设置时间的函数,因为在日常使用中必须通过上位机来修改时间,如果每次都要走RTC重置来达到好像也不太合理,因为在正常量产时不可能每次下载软件能达到同步的,这也是不太合理的,STM32是有HAL库函数可以直接修改时间的,所以不明白GD32的为什么没有想到这点的,是因为GD32的RTC本身就是一个**肋的功能还是其它原因呢不是很明白?目前个人研究尝试用实现函数rtc_time_update来达到修改同步时间,但是好像是不太行,目前不知道具体原因是什么?


麻烦各位大神帮看下分析分析原因。谢谢


RTC 主要代码逻辑部分

  1. rtc_timestamp_struct rtc_timestamp;
  2. rtc_tamper_struct rtc_tamper;
  3. rtc_parameter_struct rtc_initpara;
  4. __IO uint32_t prescaler_a = 0, prescaler_s = 0;

  5. void rtc_pre_config(void);

  6. void RTC_init(void)
  7. {
  8. #if 0
  9.     nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);

  10.     rcu_periph_clock_enable(RCU_GPIOC);
  11.     rcu_periph_clock_enable(RCU_SYSCFG);
  12.     gpio_mode_set(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_13);
  13. #endif
  14.     // enable access to RTC registers in backup domain
  15.     rcu_periph_clock_enable(RCU_PMU);
  16.     pmu_backup_write_enable();

  17.     rtc_pre_config();

  18.     // rtc_tamper_disable(RTC_TAMPER0);

  19.     /* check if RTC has aready been configured */
  20.     if (BKP_VALUE != RTC_BKP0)
  21.     {
  22.         rtc_time_set(0x22, RTC_MAY, 0x17, 0x00, 0x00, 0x00);
  23.     }
  24.     else
  25.     {
  26.         /* detect the reset source */
  27.         if (RESET != rcu_flag_get(RCU_FLAG_PORRST))
  28.         {
  29.             // printf("power on reset occurred....\n\r");
  30.         }
  31.         else if (RESET != rcu_flag_get(RCU_FLAG_EPRST))
  32.         {
  33.             // printf("external reset occurred....\n\r");
  34.         }
  35.         // printf("no need to configure RTC....\n\r");

  36.         // rtc_show_time();
  37.     }

  38.     rcu_all_reset_flag_clear();
  39. #if 0
  40.     exti_flag_clear(EXTI_21);
  41.     exti_init(EXTI_21, EXTI_INTERRUPT, EXTI_TRIG_RISING);
  42.     nvic_irq_enable(TAMPER_STAMP_IRQn, 0, 0);


  43.     /* RTC tamper configuration */
  44.     rtc_tamper.tamper_filter = RTC_FLT_EDGE;
  45.     rtc_tamper.tamper_source = RTC_TAMPER0;
  46.     rtc_tamper.tamper_trigger = RTC_TAMPER_TRIGGER_EDGE_FALLING;
  47.     rtc_tamper.tamper_with_timestamp = ENABLE;
  48.     rtc_tamper_enable(&rtc_tamper);

  49.     rtc_interrupt_enable(RTC_INT_TAMP);
  50.     rtc_flag_clear(RTC_FLAG_TS | RTC_FLAG_TSOVR | RTC_FLAG_TP0);
  51.     /* rtc_timestamp_enable(RTC_TIMESTAMP_FALLING_EDGE);
  52.     rtc_interrupt_enable(RTC_INT_TIMESTAMP);
  53.     rtc_flag_clear(RTC_FLAG_TS | RTC_FLAG_TSOVR); */
  54. #endif
  55. }

  56. void rtc_pre_config(void)
  57. {
  58. #if defined(RTC_CLOCK_SOURCE_IRC32K)
  59.     rcu_osci_on(RCU_IRC32K);
  60.     rcu_osci_stab_wait(RCU_IRC32K);
  61.     rcu_rtc_clock_config(RCU_RTCSRC_IRC32K);

  62.     prescaler_a = 0x63;  // 0x63  ck_apre频率 = RTC_CLOCK / (prescaler_a+1) = 32000 / (99+1)=320HZ
  63.     prescaler_s = 0x118; // 0x13F ck_spre频率 = ck_apre / (prescaler_s+1) = 320 / (319+1)=1HZ
  64. #elif defined(RTC_CLOCK_SOURCE_LXTAL)
  65.     rcu_osci_on(RCU_LXTAL);
  66.     rcu_osci_stab_wait(RCU_LXTAL);
  67.     rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);

  68.     prescaler_a = 0x7F; // ck_apre频率 = RTC_CLOCK/(prescaler_a+1) = 32768/(127+1)=256HZ
  69.     prescaler_s = 0xFF; // ck_spre频率 = ck_apre/(prescaler_s+1) = 256/(255+1)=1HZ
  70. #else
  71. #error RTC clock source should be defined.
  72. #endif /* RTC_CLOCK_SOURCE_IRC32K */

  73.     // rtc_smooth_calibration_config(RTC_CALIBRATION_WINDOW_32S, RTC_CALIBRATION_PLUS_SET, 0x1F);
  74.     // rtc_coarse_calibration_config(CALIB_INCREASE, 0x1F);

  75.     // rtc_coarse_calibration_config(CALIB_DECREASE, 0x1D); //对晶振进行粗校准
  76.     rcu_periph_clock_enable(RCU_RTC);
  77.     rtc_register_sync_wait();
  78. }

  79. ErrStatus rtc_time_set(uint16_t year, uint8_t month, uint8_t day, uint8_t hh, uint8_t mm, uint8_t ss)
  80. {
  81.     rtc_initpara.factor_asyn = prescaler_a;
  82.     rtc_initpara.factor_syn = prescaler_s;
  83.     rtc_initpara.year = year & 0x00FF;
  84.     rtc_initpara.day_of_week = RTC_SATURDAY;
  85.     rtc_initpara.month = month;
  86.     rtc_initpara.date = day;
  87.     rtc_initpara.display_format = RTC_24HOUR;
  88.     rtc_initpara.am_pm = RTC_AM;

  89.     // current time input
  90.     // =======Configure RTC Time========
  91.     rtc_initpara.hour = hh;
  92.     rtc_initpara.minute = mm;
  93.     rtc_initpara.second = ss;

  94.     /* RTC current time configuration */
  95.     if (ERROR == rtc_init(&rtc_initpara))
  96.     {
  97.         return ERROR;
  98.     }
  99.     else
  100.     {
  101.         RTC_BKP0 = BKP_VALUE;
  102.         return SUCCESS;
  103.     }
  104. }

  105. ErrStatus rtc_time_update(uint16_t year, uint8_t month, uint8_t day, uint8_t hh, uint8_t mm, uint8_t ss)
  106. {
  107.     uint32_t reg_time = 0U, reg_date = 0U;
  108.     ErrStatus error_status = ERROR;
  109.     reg_date = (DATE_YR(year) |
  110.                 DATE_DOW(RTC_SATURDAY) |
  111.                 DATE_MON(month) |
  112.                 DATE_DAY(day));

  113.     reg_time = (RTC_AM |
  114.                 TIME_HR(hh) |
  115.                 TIME_MN(mm) |
  116.                 TIME_SC(ss));

  117.     /* 1st: disable the write protection */
  118.     RTC_WPK = RTC_UNLOCK_KEY1;
  119.     RTC_WPK = RTC_UNLOCK_KEY2;
  120.     error_status = rtc_init_mode_enter();
  121.     if (ERROR != error_status)
  122.     {
  123.         RTC_TIME = (uint32_t)reg_time;
  124.         RTC_DATE = (uint32_t)reg_date;
  125.         rtc_init_mode_exit();
  126.         error_status = rtc_register_sync_wait();
  127.     }
  128.     RTC_WPK = RTC_LOCK_KEY;
  129.     return error_status;
  130. }

  131. void rtc_alart_set(uint8_t hh, uint8_t mm, uint8_t ss)
  132. {
  133.     rtc_alarm_struct rtc_alarm;
  134.     rtc_alarm_disable(RTC_ALARM0);
  135.     rtc_alarm.alarm_mask = RTC_ALARM_DATE_MASK | RTC_ALARM_HOUR_MASK | RTC_ALARM_MINUTE_MASK;
  136.     rtc_alarm.weekday_or_date = RTC_ALARM_DATE_SELECTED;
  137.     rtc_alarm.alarm_day = 0x31;
  138.     rtc_alarm.am_pm = RTC_AM;

  139.     rtc_alarm.alarm_hour = hh;

  140.     rtc_alarm.alarm_minute = mm;

  141.     rtc_alarm.alarm_second = ss;

  142.     rtc_alarm_config(RTC_ALARM0, &rtc_alarm);

  143.     rtc_alarm_enable(RTC_ALARM0);
  144. }

  145. /**
  146. * [url=home.php?mod=space&uid=247401]@brief[/url] timestamp time
  147. *
  148. */
  149. void rtc_show_timestamp(void)
  150. {
  151.     char buf[128] = {0};
  152.     uint32_t ts_subsecond = 0;
  153.     uint8_t ts_subsecond_ss, ts_subsecond_ts, ts_subsecond_hs;

  154.     rtc_timestamp_get(&rtc_timestamp);
  155.     /* get the subsecond value of timestamp time, and convert it into fractional format */
  156.     ts_subsecond = rtc_timestamp_subsecond_get();
  157.     ts_subsecond_ss = (1000 - (ts_subsecond * 1000 + 1000) / 400) / 100;
  158.     ts_subsecond_ts = (1000 - (ts_subsecond * 1000 + 1000) / 400) % 100 / 10;
  159.     ts_subsecond_hs = (1000 - (ts_subsecond * 1000 + 1000) / 400) % 10;

  160.     sprintf(buf, "timestamp: %0.2x:%0.2x:%0.2x.%d%d%d \n\r",
  161.             rtc_timestamp.timestamp_hour, rtc_timestamp.timestamp_minute, rtc_timestamp.timestamp_second,
  162.             ts_subsecond_ss, ts_subsecond_ts, ts_subsecond_hs);
  163.     RS485_sendData(UART4, (uint8_t *)buf, strlen(buf));
  164. }

  165. /**
  166. * [url=home.php?mod=space&uid=247401]@brief[/url] current time
  167. *
  168. */
  169. void rtc_show_time(void)
  170. {
  171.     uint32_t time_subsecond = 0;
  172.     char buf[128] = {0};
  173.     uint8_t subsecond_ss = 0, subsecond_ts = 0, subsecond_hs = 0;

  174.     rtc_current_time_get(&rtc_initpara);

  175.     /* get the subsecond value of current time, and convert it into fractional format */
  176.     time_subsecond = rtc_subsecond_get();
  177.     subsecond_ss = (1000 - (time_subsecond * 1000 + 1000) / 400) / 100;
  178.     subsecond_ts = (1000 - (time_subsecond * 1000 + 1000) / 400) % 100 / 10;
  179.     subsecond_hs = (1000 - (time_subsecond * 1000 + 1000) / 400) % 10;

  180.     sprintf(buf, "CurTime: %0.2x:%0.2x:%0.2x.%d%d%d \n\r",
  181.             rtc_initpara.hour, rtc_initpara.minute, rtc_initpara.second,
  182.             subsecond_ss, subsecond_ts, subsecond_hs);
  183.     RS485_sendData(UART4, (uint8_t *)buf, strlen(buf));
  184.     Uart5_Send_Data((uint8_t *)buf, strlen(buf));
  185. }

  186. void RTC_WKUP_IRQHandler(void)
  187. {
  188.     if (RESET != rtc_flag_get(RTC_FLAG_WT))
  189.     {
  190.         exti_flag_clear(EXTI_22);
  191.         // gd_eval_led_toggle(LED1);
  192.         // rtc_show_time();
  193.         rtc_flag_clear(RTC_FLAG_WT);
  194.     }
  195. }

  196. /*!
  197.     \brief      this function handles RTC interrupt request
  198.     \param[in]  none
  199.     \param[out] none
  200.     \retval     none
  201. */
  202. void RTC_Alarm_IRQHandler(void)
  203. {
  204.     if (RESET != rtc_flag_get(RTC_FLAG_ALRM0))
  205.     {
  206.         rtc_flag_clear(RTC_FLAG_ALRM0);
  207.         exti_flag_clear(EXTI_17);
  208.         // gd_eval_led_toggle(LED2);
  209.     }
  210. }

  211. /*!
  212.     \brief      this function handles RTC interrupt request
  213.     \param[in]  none
  214.     \param[out] none
  215.     \retval     none
  216. */
  217. void TAMPER_STAMP_IRQHandler(void)
  218. {
  219.     if (RESET != rtc_flag_get(RTC_FLAG_TP0))
  220.     // if (RESET != rtc_flag_get(RTC_FLAG_TS))
  221.     {
  222.         exti_flag_clear(EXTI_21);
  223.         // gd_eval_led_toggle(LED1);

  224.         /* if tamper0 event occurs, check if the BKP0 register has been reset or not */
  225.         /*  if(BKP_VALUE != RTC_BKP0)
  226.              gd_eval_led_toggle(LED2);
  227.          else
  228.              gd_eval_led_toggle(LED3); */

  229.         rtc_show_timestamp();
  230.         rtc_flag_clear(RTC_FLAG_TS | RTC_FLAG_TSOVR | RTC_FLAG_TP0);

  231.         // rtc_flag_clear(RTC_FLAG_TS | RTC_FLAG_TSOVR);
  232.     }
  233. }



caizhiwei 发表于 2023-3-20 13:38 | 显示全部楼层
留个记号
caizhiwei 发表于 2023-3-24 10:03 | 显示全部楼层
走不动倒是没遇到过,遇到了奇葩读日期出问题,哎。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

4

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部