gps.c 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079
  1. /******************************************************************************
  2. 版权所有:
  3. 文件名称: rt_gps.c
  4. 文件版本: 01.01
  5. 创建作者: sunxi
  6. 创建日期: 2008-06-04
  7. 功能说明: GPS时钟模块驱动程序。
  8. 其它说明: 1. GPS卫星同步时钟只保证整秒时PR上升沿的精度(一般1us之内),
  9. 其它bit的上升沿精度并不保证。
  10. 2. GPS接收模块只给出秒脉冲和串口数据。
  11. 3. 使用B码对时的时候,B码给的数据中可能包含闰秒(负闰秒:58->0;
  12. 正闰秒:60->0),所以秒的有效数据范围为0~60。但是系统中其它
  13. 计时模块没有闰秒的概念,单独在B码模块使用闰秒有可能造成整个计时
  14. 系统的混乱,所以最终决定将秒的有效数据范围还是限制在0~59,这样
  15. 当正闰秒出现时,系统时间将是:58->59->0->0-1。初步估计,这种影响
  16. 在可接受的范围之内。
  17. 4. 目前在冷火Linux平台上对时误差<8US.(2010-11-23)
  18. 修改记录:
  19. */
  20. /*------------------------------- 头文件 --------------------------------------
  21. */
  22. #include "bspconfig.h"
  23. #include "my_rtc.h"
  24. #include "rt.h"
  25. #include "bsp_ccu.h"
  26. #include "bsp_ustimer.h"
  27. #include "rt_printf.h"
  28. #include "rt_types.h"
  29. #include <sys/mman.h>
  30. #include "gps.h"
  31. #include <sys/prctl.h>
  32. #include <sys/syscall.h>
  33. #include <pthread.h>
  34. #include <sched.h>
  35. /*------------------------------- 宏定义 --------------------------------------
  36. */
  37. #if CFG_BSP_DEBUG
  38. #define _DEBUG_GPS
  39. #endif
  40. #define DTIM_CLOCK_PER_US (CFG_CPU_CLK / 2 / 1000000)
  41. #define GPS_SIGAL_DIFF 1 // GPS信号宽度误差
  42. #define GPS_IRIG_CODE_0 0
  43. #define GPS_IRIG_CODE_1 1
  44. #define GPS_IRIG_CODE_P 2
  45. /*------------------------------ 全局变量 -------------------------------------
  46. */
  47. extern int g_clock_mode;
  48. struct timespec g_sys_time;
  49. static struct rtc_time_t tmp_sys_time;
  50. // 毫秒中断的参考值
  51. unsigned int g_1s_refence;
  52. // 输入信号是否合法,合法为1,不合法为0
  53. int g_signal_valid;
  54. // GPS对时使用的保活计数值
  55. unsigned int g_keep_alive_gps;
  56. // 处理B码的全局变量
  57. unsigned int g_irig_old_value;
  58. unsigned int g_irig_old_interval;
  59. unsigned int g_irig_code_index;
  60. unsigned char g_irig_code[100];
  61. int g_gps_fd = -1;
  62. unsigned g_gps_mapped_size;
  63. void *g_gps_map_base, *g_gps_virt_addr;
  64. static void *gpio_base = NULL;
  65. /*------------------------------ 函数声明 -------------------------------------
  66. */
  67. int _gps_irig_decode(unsigned char *code, struct rtc_time_t *p_tm);
  68. void _ms_update_time(void);
  69. void _gps_capture_isr(void);
  70. void _gps_1s_isr(void);
  71. void gps_isr(void);
  72. /*------------------------------ 外部函数 -------------------------------------
  73. */
  74. /******************************************************************************
  75. 函数名称: gps_init
  76. 函数版本: 01.01
  77. 创建作者: ocean
  78. 创建日期: 2025-11-21
  79. 函数说明: gps初始化。
  80. 参数说明: 无
  81. 返回值: 成功返回0.
  82. 修改记录:
  83. */
  84. int gps_init(void)
  85. {
  86. struct timespec ts;
  87. struct rtc_time_t ct;
  88. void *temp_ccu_base, *temp_virt_l_base, *temp_virt_h_base, *temp_virt_ctl_base, *temp_virt_irq_base;
  89. unsigned long read_result;
  90. off_t target;
  91. unsigned page_size, offset_in_page;
  92. unsigned width = 8 * sizeof(int);
  93. target = TIMER_BASE;
  94. // 获取页面大小
  95. g_gps_mapped_size = page_size = sysconf(_SC_PAGESIZE);
  96. offset_in_page = (unsigned)target & (page_size - 1);
  97. if (offset_in_page + width > page_size)
  98. {
  99. /* This access spans pages.
  100. * Must map two pages to make it possible: */
  101. g_gps_mapped_size *= 2;
  102. }
  103. g_gps_fd = open("/dev/mem", O_RDWR | O_SYNC);
  104. if (g_gps_fd < 0)
  105. {
  106. printf("open(/dev/mem) failed.\n");
  107. return -1;
  108. }
  109. fflush(stdout);
  110. g_gps_map_base = mmap(NULL, g_gps_mapped_size, PROT_READ | PROT_WRITE, MAP_SHARED, g_gps_fd, target & ~(off_t)(page_size - 1));
  111. if (g_gps_map_base == (void *)-1)
  112. {
  113. printf("NULL pointer!\n");
  114. }
  115. else
  116. {
  117. printf("BSP gps map Successfull!\n");
  118. }
  119. fflush(stdout);
  120. /* Get linux system current time */
  121. // 此处精度还可以再提高,但是ioctl接口读取rtc时间后会有问题,暂时先这样了
  122. clock_gettime(CLOCK_REALTIME, &ts);
  123. timespec_to_rtc(ts, &ct, 1);
  124. if (ct.hour >= 24 || ct.min >= 60 || ct.month > 12 || ct.day > 31 || ct.day == 0 || ct.month == 0) // 读取系统时钟错误
  125. {
  126. /* Reset linux system time */
  127. ct.year = 8;
  128. ct.month = 8;
  129. ct.day = 8;
  130. ct.hour = 8;
  131. ct.min = 8;
  132. rtc_to_timespec(&ct, &ts);
  133. rt_printf("gps read system date data error!!!");
  134. }
  135. g_sys_time.tv_sec = ts.tv_sec;
  136. g_sys_time.tv_nsec = ts.tv_nsec;
  137. g_gps_virt_addr = (char *)g_gps_map_base + offset_in_page;
  138. // printf("g_gps_virt_addr: %p %p %x\n", g_gps_virt_addr, g_gps_map_base, offset_in_page);
  139. // Init timer ccu clock
  140. /* set TMR3 clock source to HOSC, 8 pre-division */
  141. temp_ccu_base = g_ccu_map_base + 0x080C;
  142. read_result = *(volatile u_int32_t *)(temp_ccu_base);
  143. read_result &= ~(0x01 << 24);
  144. read_result |= (1 << 31) | 3;
  145. *(volatile u_int32_t *)(temp_ccu_base) = read_result;
  146. // Enable timer3
  147. /* set timer intervalue */
  148. temp_virt_l_base = (char *)g_gps_map_base + 0x84;
  149. temp_virt_h_base = (char *)g_gps_map_base + 0x8C;
  150. *(volatile u_int32_t *)(temp_virt_l_base) = (ts.tv_nsec == 0) ? 3000000 : ts.tv_nsec / 1000 * 3;
  151. *(volatile u_int32_t *)(temp_virt_h_base) = 0x0;
  152. /* set mode to auto reload */
  153. temp_virt_ctl_base = (char *)g_gps_map_base + 0x80;
  154. read_result = *(volatile u_int32_t *)(temp_virt_ctl_base);
  155. read_result &= TIMER_CTL_PERIODIC;
  156. *(volatile u_int32_t *)(temp_virt_ctl_base) = (read_result | TIMER_CTL_AUTORELOAD | TIMER_CTL_ENABLE);
  157. /* Enable timer interrupt */
  158. temp_virt_irq_base = (char *)g_gps_map_base + 0x00;
  159. read_result = *(volatile u_int32_t *)(temp_virt_irq_base);
  160. *(volatile u_int32_t *)(temp_virt_irq_base) = (read_result | TIMER_IRQ_EN(3));
  161. usleep(1);
  162. read_result = *(volatile u_int32_t *)temp_virt_ctl_base;
  163. read_result &= ~TIMER_CTL_ENABLE;
  164. *(volatile u_int32_t *)temp_virt_ctl_base = read_result;
  165. *(volatile u_int32_t *)(temp_virt_l_base) = 3000000;
  166. read_result |= (TIMER_CTL_ENABLE);
  167. *(volatile u_int32_t *)temp_virt_ctl_base = read_result;
  168. init_timer_1ms_thread();
  169. return 0;
  170. }
  171. int timer_1ms(void *arg)
  172. {
  173. cpu_set_t set;
  174. CPU_ZERO(&set);
  175. CPU_SET(3, &set);
  176. pid_t tid = syscall(SYS_gettid);
  177. sched_setaffinity(tid, sizeof(cpu_set_t), &set);
  178. printf("Thread created successfully: %s, PID: %d LWP: %d\r\n",
  179. "timer_1ms", (int)syscall(SYS_gettid), (int)syscall(SYS_gettid));
  180. prctl(PR_SET_NAME, "gps_check_isr_thread");
  181. while (1)
  182. {
  183. gps_isr();
  184. usleep(500); // 扫描间隔改为500us EWen
  185. }
  186. return 0;
  187. }
  188. void init_timer_1ms_thread(void)
  189. {
  190. // 设置实时性
  191. pthread_attr_t attr;
  192. struct sched_param param;
  193. pthread_t thread;
  194. if (pthread_attr_init(&attr) != 0)
  195. {
  196. perror("pthread_attr_init failed");
  197. return;
  198. }
  199. if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) != 0)
  200. {
  201. perror("pthread_attr_setschedpolicy failed");
  202. goto cleanup;
  203. }
  204. param.sched_priority = 99;
  205. if (pthread_attr_setschedparam(&attr, &param) != 0)
  206. {
  207. perror("pthread_attr_setschedparam failed");
  208. goto cleanup;
  209. }
  210. if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) != 0)
  211. {
  212. perror("pthread_attr_setinheritsched failed");
  213. goto cleanup;
  214. }
  215. if (pthread_create(&thread, &attr, timer_1ms, NULL) != 0)
  216. {
  217. perror("pthread_create failed");
  218. goto cleanup;
  219. }
  220. // 分离线程
  221. pthread_detach(thread);
  222. printf("PPS线程已启动并在后台运行\n");
  223. cleanup:
  224. pthread_attr_destroy(&attr);
  225. }
  226. int gps_exit(void)
  227. {
  228. unsigned long read_result;
  229. void *temp_virt_ctl_base;
  230. if (g_gps_fd >= 0)
  231. {
  232. close(g_gps_fd);
  233. g_gps_fd = -1;
  234. }
  235. temp_virt_ctl_base = (char *)g_gps_map_base + 0x80;
  236. read_result = *(volatile u_int32_t *)(temp_virt_ctl_base);
  237. read_result &= ~(TIMER_CTL_ENABLE);
  238. *(volatile u_int32_t *)(temp_virt_ctl_base) = (read_result);
  239. if (munmap(g_gps_map_base, g_gps_mapped_size) == -1)
  240. {
  241. printf("munmap failed!");
  242. return -1;
  243. }
  244. return 0;
  245. }
  246. int gps_get_time(struct timespec *p_ts)
  247. {
  248. unsigned long flags;
  249. register long tv_sec, tv_nsec;
  250. unsigned long read_result;
  251. void *temp_virt_cvl_base, *temp_virt_irq_base;
  252. // 检查参数
  253. if (p_ts == 0)
  254. return -1;
  255. // 关中断
  256. rt_irq_save(flags);
  257. tv_sec = g_sys_time.tv_sec;
  258. temp_virt_cvl_base = (char *)g_gps_map_base + 0x88;
  259. temp_virt_irq_base = (char *)g_gps_map_base + 0x04;
  260. // read_result = *(volatile u_int32_t*)(temp_virt_cvl_base);
  261. tv_nsec = 3000000 - (*(volatile u_int32_t *)(temp_virt_cvl_base));
  262. if (((*(volatile u_int32_t *)(temp_virt_irq_base)) & (1 << 3)) != 0)
  263. {
  264. tv_sec += 1;
  265. tv_nsec = 3000000 - (*(volatile u_int32_t *)(temp_virt_cvl_base));
  266. }
  267. // 恢复中断级别
  268. rt_irq_restore(flags);
  269. p_ts->tv_sec = tv_sec;
  270. p_ts->tv_nsec = (tv_nsec / 3) * 1000;
  271. return 0;
  272. }
  273. int gps_set_time(struct timespec *p_ts)
  274. {
  275. int ret = 0;
  276. bool write_rtc = false;
  277. struct timespec r_ts;
  278. struct rtc_time_t rtc_set, rtc_read;
  279. unsigned int flags;
  280. unsigned int tmp;
  281. unsigned int read_result;
  282. void *temp_virt_ivl_base, *temp_virt_ctrl_base;
  283. if (!p_ts)
  284. {
  285. return -1;
  286. }
  287. // 转换为rtc格式
  288. if (timespec_to_rtc(*p_ts, &rtc_set, 1) != 0)
  289. {
  290. return -11;
  291. }
  292. if (rtc_set.ms > 59999)
  293. {
  294. return -2;
  295. }
  296. if (rtc_set.min > 59)
  297. {
  298. return -3;
  299. }
  300. if (rtc_set.hour >= 24)
  301. {
  302. return -4;
  303. }
  304. if (rtc_set.day > 31)
  305. {
  306. return -5;
  307. }
  308. if (rtc_set.month > 12)
  309. {
  310. return -6;
  311. }
  312. rt_irq_save(flags);
  313. g_sys_time.tv_nsec = p_ts->tv_nsec;
  314. g_sys_time.tv_sec = p_ts->tv_sec;
  315. clk_time_get(&r_ts);
  316. timespec_to_rtc(r_ts, &rtc_read, 1);
  317. tmp = 3000000 - ((g_sys_time.tv_nsec / 1000) * 3);
  318. if (tmp > 3000000)
  319. tmp = 3000000;
  320. temp_virt_ctrl_base = (char *)g_gps_map_base + 0x80;
  321. temp_virt_ivl_base = (char *)g_gps_map_base + 0x84;
  322. read_result = *(volatile u_int32_t *)temp_virt_ctrl_base;
  323. read_result &= ~TIMER_CTL_ENABLE;
  324. *(volatile u_int32_t *)temp_virt_ctrl_base = read_result;
  325. // 暂停定时器后根据对时ms修改间隔寄存器的值然后开启定时器的同时reload计数寄存器从设置的ms开始跑
  326. *(volatile u_int32_t *)(temp_virt_ivl_base) = tmp;
  327. read_result |= (TIMER_CTL_ENABLE | TIMER_CTL_AUTORELOAD);
  328. *(volatile u_int32_t *)temp_virt_ctrl_base = read_result;
  329. if (tmp != 3000000)
  330. {
  331. usleep(1);
  332. // 暂停定时器将间隔寄存器恢复3000000,即1s的定时器中断
  333. read_result = *(volatile u_int32_t *)temp_virt_ctrl_base;
  334. read_result &= ~TIMER_CTL_ENABLE;
  335. *(volatile u_int32_t *)temp_virt_ctrl_base = read_result;
  336. *(volatile u_int32_t *)(temp_virt_ivl_base) = 3000000;
  337. read_result |= (TIMER_CTL_ENABLE);
  338. *(volatile u_int32_t *)temp_virt_ctrl_base = read_result;
  339. // ((TIMER_TypeDef *) g_timer_base)->TMR3_CVH_REG = 0x0;
  340. }
  341. rt_irq_restore(flags);
  342. // 更新RTC时间
  343. write_rtc = false;
  344. // 秒脉冲修正不需要频繁写入rtc
  345. if (rtc_set.ms != rtc_read.ms)
  346. {
  347. if (rtc_set.ms >= rtc_read.ms)
  348. {
  349. if (rtc_set.ms - rtc_read.ms >= 10)
  350. {
  351. write_rtc = true;
  352. }
  353. }
  354. else
  355. {
  356. if (rtc_read.ms - rtc_set.ms >= 10)
  357. {
  358. write_rtc = true;
  359. }
  360. }
  361. }
  362. if (write_rtc)
  363. {
  364. ret = rtc_time_write(&rtc_set);
  365. if (ret == 0)
  366. {
  367. rt_err_clr(ERR_CODE_RTC, 0);
  368. }
  369. else
  370. {
  371. rt_printf("rtc_time_write:ret=%d.\r\n", ret);
  372. }
  373. }
  374. }
  375. /******************************************************************************
  376. 函数名称: gps_disable
  377. 函数版本: 01.01
  378. 创建作者:
  379. 创建日期: 2014-12-02
  380. 函数说明: 禁止GPS输入功能。
  381. 参数说明: 无
  382. 返回值: 无.
  383. 修改记录:
  384. */
  385. void gps_disable(void)
  386. {
  387. MCF_REG16(MCF_DTIM_DTMR(CFG_DTIM_GPS_CAP)) &= ~MCF_DTIM_DTMR_CE_ANY;
  388. }
  389. /******************************************************************************
  390. 函数名称: gps_enable
  391. 函数版本: 01.01
  392. 创建作者:
  393. 创建日期: 2014-12-02
  394. 函数说明: 使能GPS输入功能。
  395. 参数说明: 无
  396. 返回值: 无.
  397. 修改记录:
  398. */
  399. void gps_enable(void)
  400. {
  401. MCF_REG16(MCF_DTIM_DTMR(CFG_DTIM_GPS_CAP)) |= MCF_DTIM_DTMR_CE_ANY;
  402. }
  403. /******************************************************************************
  404. 函数名称: gps_reset
  405. 函数版本: 01.01
  406. 创建作者: sunxi
  407. 创建日期: 2008-08-06
  408. 函数说明: gps对时模块复位。
  409. 参数说明: 无
  410. 返回值: 成功返回0.
  411. 修改记录:
  412. */
  413. int gps_reset(void)
  414. {
  415. // 全局变量清零
  416. g_signal_valid = 0;
  417. g_keep_alive_gps = 0;
  418. g_irig_old_value = 0;
  419. g_irig_old_interval = 0;
  420. g_irig_code_index = 0;
  421. return 0;
  422. }
  423. /******************************************************************************
  424. 函数名称: gps_pulse_isr
  425. 函数版本: 01.01
  426. 创建作者: ocean
  427. 创建日期: 2023-11-24
  428. 函数说明: gps脉冲中断
  429. 参数说明: 无
  430. 返回值: 成功返回0.
  431. 修改记录:
  432. */
  433. void gps_pulse_isr(void *data)
  434. {
  435. unsigned int flags;
  436. rt_irq_save(flags);
  437. g_sys_time.tv_sec++;
  438. rt_irq_restore(flags);
  439. }
  440. /******************************************************************************
  441. 函数名称: gps_isr
  442. 函数版本: 01.01
  443. 创建作者: sunxi
  444. 创建日期: 2008-08-06
  445. 函数说明: gps中断处理函数。
  446. 参数说明: 无
  447. 返回值: 成功返回0.
  448. 修改记录:
  449. */
  450. void gps_isr(void)
  451. {
  452. void *temp_virt_cvl_base, *temp_virt_irq_base;
  453. // clear irq flags
  454. if (g_gps_map_base)
  455. {
  456. temp_virt_irq_base = (char *)g_gps_map_base + 0x04;
  457. if (((*(volatile u_int32_t *)(temp_virt_irq_base)) & (1 << 3)) != 0)
  458. {
  459. gps_pulse_isr(NULL);
  460. *(volatile u_int32_t *)(temp_virt_irq_base) = (1 << 3);
  461. }
  462. }
  463. }
  464. /*------------------------------ 内部函数 -------------------------------------
  465. */
  466. // 闰年判断
  467. int _is_leap_year(int year)
  468. {
  469. if ((((year & 0x3) == 0) && (year % 100 != 0)) || (year % 400 == 0))
  470. return 1;
  471. else
  472. return 0;
  473. }
  474. // 日期转换,给出一年中的第几天(从1开始,不是从0开始),算出是这一年的几月几日
  475. int _days_translate(struct rtc_time_t *pt, int year, int day)
  476. {
  477. static int month_last_day[2][13] =
  478. {
  479. {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, // 平年
  480. {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}, // 闰年
  481. };
  482. int i;
  483. int *last_day;
  484. if (pt == 0 || day == 0 || day > 366)
  485. return -1;
  486. last_day = month_last_day[_is_leap_year(year)];
  487. for (i = 0; i < 13; i++)
  488. {
  489. if (day <= last_day[i])
  490. {
  491. break;
  492. }
  493. }
  494. pt->month = (unsigned char)i;
  495. pt->day = (unsigned char)(day - last_day[i - 1]);
  496. return 0;
  497. }
  498. int _gps_irig_decode(unsigned char *code, struct rtc_time_t *p_tm)
  499. {
  500. #if 0
  501. int tmp;
  502. //检查P码位置
  503. if( code[0]!=GPS_IRIG_CODE_P
  504. ||code[9]!=GPS_IRIG_CODE_P
  505. ||code[19]!=GPS_IRIG_CODE_P
  506. ||code[29]!=GPS_IRIG_CODE_P
  507. ||code[39]!=GPS_IRIG_CODE_P
  508. ||code[49]!=GPS_IRIG_CODE_P
  509. ||code[59]!=GPS_IRIG_CODE_P
  510. ||code[69]!=GPS_IRIG_CODE_P
  511. ||code[79]!=GPS_IRIG_CODE_P
  512. ||code[89]!=GPS_IRIG_CODE_P)
  513. return -1;
  514. //秒
  515. tmp = ((code[8]<<2)+(code[7]<<1)+code[6])*10
  516. +(code[4]<<3)+(code[3]<<2)+(code[2]<<1)+(code[1]);
  517. if(tmp>=60)
  518. return -2;
  519. p_tm->ms = (unsigned short)(tmp*1000 + p_tm->ms%1000);
  520. //分
  521. tmp = ((code[17]<<2)+(code[16]<<1)+code[15])*10
  522. +(code[13]<<3)+(code[12]<<2)+(code[11]<<1)+(code[10]<<0);
  523. if(tmp>=60)
  524. return -3;
  525. p_tm->min=(unsigned char)tmp;
  526. //时
  527. tmp = ((code[26]<<1)+code[25])*10
  528. +(code[23]<<3)+(code[22]<<GPS_IRIG_CODE_P)+(code[21]<<1)+(code[20]<<0);
  529. if(tmp>=24)
  530. return -4;
  531. p_tm->hour=(unsigned char)tmp;
  532. if(g_clock_mode == CLOCK_MODE_GPS_B_YEAR_NONE)
  533. {
  534. //不带年的B码对时
  535. //日
  536. tmp = ((code[41]<<1)+code[40])*100
  537. +((code[38]<<3)+(code[37]<<2)+(code[36]<<1)+code[35])*10
  538. + (code[33]<<3)+(code[32]<<2)+(code[31]<<1)+code[30];
  539. if(tmp>366 || tmp == 0)
  540. return -5;
  541. p_tm->year = tmp_sys_time.year;
  542. _days_translate(p_tm,p_tm->year + 2000,tmp);
  543. }
  544. else if(g_clock_mode == CLOCK_MODE_GPS_B_YEAR)
  545. {
  546. //带年的B码对时
  547. //日
  548. tmp=((code[38]<<3)+(code[37]<<2)+(code[36]<<1)+code[35])*10+
  549. (code[33]<<3)+(code[32]<<2)+(code[31]<<1)+code[30];
  550. if(tmp>31||tmp==0)
  551. return -6;
  552. p_tm->day = (unsigned char)tmp;
  553. //月
  554. tmp=(code[43]<<3)+(code[42]<<2)+(code[41]<<1)+code[40];
  555. if(tmp > 12)
  556. return -7;
  557. p_tm->month = (unsigned char)tmp;
  558. //年
  559. tmp=((code[58]<<3)+(code[57]<<2)+(code[56]<<1)+code[55])*10+
  560. (code[53]<<3)+(code[52]<<2)+(code[51]<<1)+code[50];
  561. p_tm->year = (unsigned short)tmp;
  562. }
  563. else if(g_clock_mode == CLOCK_MODE_GPS_B_2009)
  564. {
  565. //年
  566. tmp=((code[58]<<3)+(code[57]<<2)+(code[56]<<1)+code[55])*10+
  567. (code[53]<<3)+(code[52]<<2)+(code[51]<<1)+code[50];
  568. p_tm->year = (unsigned short)tmp;
  569. //日
  570. tmp = ((code[41]<<1)+code[40])*100
  571. +((code[38]<<3)+(code[37]<<2)+(code[36]<<1)+code[35])*10
  572. + (code[33]<<3)+(code[32]<<2)+(code[31]<<1)+code[30];
  573. if(tmp>366 || tmp == 0)
  574. return -8;
  575. _days_translate(p_tm,p_tm->year + 2000,tmp);
  576. }
  577. #endif
  578. return 0;
  579. }
  580. void _ms_update_time(void)
  581. {
  582. struct rtc_time_t *pt = &tmp_sys_time;
  583. int day_flag = 0;
  584. if (pt->ms < 60000)
  585. return;
  586. pt->ms = 0;
  587. pt->min++;
  588. if (pt->min >= 60)
  589. {
  590. pt->min = 0;
  591. pt->hour++;
  592. if (pt->hour >= 24)
  593. {
  594. pt->hour = 0;
  595. pt->day++;
  596. if (pt->month == 2)
  597. {
  598. // 2月
  599. if (pt->day > 28)
  600. {
  601. if (_is_leap_year(pt->year + 2000))
  602. {
  603. // 闰年 2月29天?
  604. if (pt->day > 29)
  605. {
  606. day_flag = 1;
  607. }
  608. }
  609. else
  610. {
  611. // 其他28天
  612. day_flag = 1;
  613. }
  614. }
  615. }
  616. else
  617. {
  618. // 非2月
  619. if (pt->day > 30)
  620. {
  621. if (pt->month == 4 || pt->month == 6 || pt->month == 9 || pt->month == 11)
  622. {
  623. day_flag = 1;
  624. }
  625. }
  626. if (pt->day > 31)
  627. {
  628. day_flag = 1;
  629. }
  630. }
  631. if (day_flag)
  632. {
  633. pt->day = 1;
  634. pt->month++;
  635. if (pt->month > 12)
  636. {
  637. pt->month = 1;
  638. pt->year++;
  639. }
  640. }
  641. }
  642. }
  643. }
  644. void _gps_1s_isr(void)
  645. {
  646. // unsigned int now;
  647. // uint32_t flags;
  648. #if 0
  649. if(tmp_sys_time.ms%2 == 0)
  650. {
  651. // DIO_KOUT6_OFF();
  652. }
  653. else
  654. {
  655. // DIO_KOUT6_ON();
  656. }
  657. //计数
  658. tmp_sys_time.ms ++;
  659. //输出对时脉冲(10ms,下降沿)
  660. if((tmp_sys_time.ms%1000) >= 10 )
  661. {
  662. //GPIO_GPS_HIGH();
  663. }
  664. else if(tmp_sys_time.ms%1000 != 0)
  665. {
  666. //GPIO_GPS_LOW();
  667. }
  668. else
  669. {
  670. //tmp_sys_time.ms%1000 == 0的情况
  671. if(g_clock_mode == CLOCK_MODE_EXT || g_clock_mode == CLOCK_MODE_GPS_MINUTE)
  672. {
  673. //当对时模式为外部对时或分对时的时候,在这儿输出下降沿。
  674. //GPIO_GPS_LOW();
  675. }
  676. else if(g_signal_valid == 0)
  677. {
  678. //输入信号不合法,在此输出下降沿
  679. //GPIO_GPS_LOW();
  680. }
  681. }
  682. #endif
  683. rt_irq_save(flags);
  684. g_sys_time.tv_sec++;
  685. g_1s_refence += 1000000;
  686. MCF_REG32(MCF_DTIM_DTRR(CFG_DTIM_GPS_CAP)) = g_1s_refence;
  687. rt_irq_restore(flags);
  688. // 更新系统时间
  689. //_ms_update_time();
  690. // GPS保活处理
  691. if (g_keep_alive_gps)
  692. {
  693. // 减1s
  694. g_keep_alive_gps -= 1000;
  695. }
  696. return;
  697. }
  698. void _gps_capture_isr(void)
  699. {
  700. #if 0
  701. unsigned int interval,capture_value,n;
  702. //如果不是GPS对时模式,不进行任何处理
  703. // if(g_clock_mode == CLOCK_MODE_EXT)
  704. return;
  705. //得到计数值,并计算和上一次计数器之差,也就是两次中断之间的计数值.
  706. capture_value = MCF_REG32(MCF_DTIM_DTCR(CFG_DTIM_GPS_CAP));
  707. interval = (capture_value - g_irig_old_value + 500L)/1000;
  708. //消除干扰信号
  709. if(interval < 2)
  710. {
  711. rt_printf("gps:interval = %d\r\n",interval);
  712. //干扰信号,直接返回
  713. return;
  714. }
  715. #if 0
  716. if(GPIO_GPS_INT_STATUS())
  717. rt_printf("H:");
  718. else
  719. rt_printf("L:");
  720. rt_printf("%d,%d\r\n",capture_value - g_irig_old_value,capture_value);
  721. goto __ret;
  722. #endif
  723. if(g_clock_mode == CLOCK_MODE_GPS_SECOND)
  724. {
  725. //输入信号不为低电平时不进行逻辑判断。
  726. //注意:目前输入信号经过了两个反相器。
  727. if(GPIO_GPS_INT_STATUS() == 0)
  728. {
  729. goto __ret;
  730. }
  731. //检查输入信号正负脉冲之和是否为1000ms.
  732. n = interval + g_irig_old_interval;
  733. //if( n < 999 || n > 1001)
  734. if( abs(n - 1000) > GPS_SIGAL_DIFF)
  735. { //输入信号不正常,重新搜索秒开始位置
  736. rt_printf("gps:%d,%d\r\n",interval,g_irig_old_interval);
  737. g_signal_valid = 0;
  738. goto __ret;
  739. }
  740. //分板对时下降沿
  741. //GPIO_GPS_LOW();
  742. //修正时间
  743. tmp_sys_time.ms = (unsigned short)((tmp_sys_time.ms+500)/1000*1000);
  744. _ms_update_time();
  745. //修正边沿
  746. MCF_REG08(MCF_DTIM_DTER(CFG_DTIM_GPS_CAP)) = MCF_DTIM_DTER_REF;
  747. g_1s_refence = capture_value + 1000000;
  748. MCF_REG32(MCF_DTIM_DTRR(CFG_DTIM_GPS_CAP)) = g_1s_refence;
  749. //GPS保活
  750. g_keep_alive_gps = CLOCK_ALIVE_GPS;
  751. g_signal_valid = 1;
  752. goto __ret;
  753. }
  754. if(g_clock_mode == CLOCK_MODE_GPS_MINUTE)
  755. {
  756. //输入信号不为低电平时不进行逻辑判断。
  757. //注意:目前输入信号经过了两个反相器。
  758. if(GPIO_GPS_INT_STATUS() == 0)
  759. {
  760. goto __ret;
  761. }
  762. //检查输入信号正负脉冲之和是否为1分钟。
  763. //由于我们使用的晶体是50ppm的,在一分钟之内可能有3ms的误差,
  764. //所以我们以5ms作为指标判断。
  765. n = interval + g_irig_old_interval;
  766. if( n < (60*1000 - 5) || n > (60*1000 + 5))
  767. { //输入信号不正常,重新搜索分开始位置
  768. rt_printf("gps:%d,%d\r\n",interval,g_irig_old_interval);
  769. g_signal_valid = 0;
  770. goto __ret;;
  771. }
  772. //分板对时下降沿
  773. //GPIO_GPS_LOW();
  774. //修正时间
  775. if(tmp_sys_time.ms > 30000)
  776. {
  777. tmp_sys_time.ms = 60000;
  778. _ms_update_time();
  779. }
  780. else
  781. {
  782. tmp_sys_time.ms = 0;
  783. }
  784. //修正边沿
  785. MCF_REG08(MCF_DTIM_DTER(CFG_DTIM_GPS_CAP)) = MCF_DTIM_DTER_REF;
  786. g_1s_refence = capture_value + 1000000;
  787. MCF_REG32(MCF_DTIM_DTRR(CFG_DTIM_GPS_CAP)) = g_1s_refence;
  788. //GPS保活
  789. g_keep_alive_gps = CLOCK_ALIVE_GPS + 60000;
  790. g_signal_valid = 1;
  791. goto __ret;
  792. }
  793. //!!!以下为B码对时
  794. //检查输入信号
  795. if(abs(interval - 2)> GPS_SIGAL_DIFF && abs(interval - 5) > GPS_SIGAL_DIFF && abs(interval - 8) > GPS_SIGAL_DIFF)
  796. {
  797. rt_printf("gps:%d\r\n",interval);
  798. //输入信号不正常,重新搜索秒开始位置
  799. g_signal_valid = 0;
  800. g_irig_code_index = 0;
  801. goto __ret;
  802. }
  803. //输入信号不为低电平时不进行逻辑判断。
  804. //注意:目前输入信号经过了两个反相器。
  805. if(GPIO_GPS_INT_STATUS() == 0)
  806. {
  807. goto __ret;
  808. }
  809. //检查输入信号正负脉冲之和是否为10ms。
  810. if(abs(interval + g_irig_old_interval - 10) > GPS_SIGAL_DIFF)
  811. { //输入信号不正常,重新搜索秒开始位置
  812. rt_printf("gps:%d,%d\r\n",interval,g_irig_old_interval);
  813. g_signal_valid = 0;
  814. g_irig_code_index = 0;
  815. goto __ret;;
  816. }
  817. //如果g_irig_code_index<2,需要搜索秒开始位置
  818. if(g_irig_code_index <2)
  819. {
  820. //如果不是P码,放弃处理,重新搜索。
  821. if(abs(g_irig_old_interval - 8) > GPS_SIGAL_DIFF)
  822. {
  823. g_signal_valid = 0;
  824. g_irig_code_index = 0;
  825. goto __ret;
  826. }
  827. //保存P码
  828. g_irig_code[g_irig_code_index++] = GPS_IRIG_CODE_P;
  829. if(g_irig_code_index == 1 && g_signal_valid == 1)
  830. {
  831. //分板对时下降沿
  832. //GPIO_GPS_LOW();
  833. //修正时间
  834. tmp_sys_time.ms = (unsigned short)((tmp_sys_time.ms+500)/1000*1000);
  835. _ms_update_time();
  836. //修正边沿
  837. MCF_REG32(MCF_DTIM_DTER(CFG_DTIM_GPS_CAP)) = MCF_DTIM_DTER_REF;
  838. g_1s_refence = capture_value + 1000000;
  839. MCF_REG32(MCF_DTIM_DTRR(CFG_DTIM_GPS_CAP)) = g_1s_refence;
  840. }
  841. goto __ret;
  842. }
  843. //保存编码
  844. switch(g_irig_old_interval)
  845. {
  846. case 1:
  847. case 2:
  848. case 3:
  849. g_irig_code[g_irig_code_index++] = GPS_IRIG_CODE_0;
  850. break;
  851. case 4:
  852. case 5:
  853. case 6:
  854. g_irig_code[g_irig_code_index++] = GPS_IRIG_CODE_1;
  855. break;
  856. case 7:
  857. case 8:
  858. case 9:
  859. g_irig_code[g_irig_code_index++] = GPS_IRIG_CODE_P;
  860. break;
  861. default:
  862. rt_printf("gps:g_irig_old_interval=%d!\r\n",g_irig_old_interval);
  863. g_signal_valid = 0;
  864. g_irig_code_index = 0;
  865. goto __ret;
  866. break;
  867. }
  868. //如果接收完时间信息,就开始处理
  869. if(g_irig_code_index >= 100)
  870. {
  871. if(_gps_irig_decode(&g_irig_code[1],&tmp_sys_time) == 0)
  872. {
  873. g_signal_valid = 1;
  874. g_keep_alive_gps = CLOCK_ALIVE_GPS;
  875. }
  876. else
  877. g_signal_valid = 0;
  878. g_irig_code_index = 0;
  879. }
  880. __ret:
  881. g_irig_old_value = capture_value;
  882. g_irig_old_interval = interval;
  883. #endif
  884. }
  885. /*------------------------------ 测试函数 -------------------------------------
  886. */
  887. #ifdef _DEBUG_GPS
  888. #include "ustimer.h"
  889. int gps_test(void)
  890. {
  891. unsigned int us0, t;
  892. rt_printf("gps_test start...\r\n");
  893. // rt_irq_level(0);
  894. t = 0;
  895. us0 = ustimer_get_origin();
  896. // sunxi 20220424 while(1) ;
  897. while (t < 10)
  898. {
  899. // rt_printf("pit(t=%03dsec):g_gps_ms:%06d,diff(g_gps_ms-t*1000):%d!\r\n",t,g_gps_ms,g_gps_ms -t*1000);
  900. rt_printf("g_sys_time: %04d-%02d-%02d time: %02d:%02d:%05d!\r\n",
  901. tmp_sys_time.year + 2000,
  902. tmp_sys_time.month,
  903. tmp_sys_time.day,
  904. tmp_sys_time.hour,
  905. tmp_sys_time.min,
  906. tmp_sys_time.ms);
  907. ustimer_delay_origin(us0, ++t * USTIMER_SEC);
  908. }
  909. rt_printf("gps_test end...\r\n");
  910. return 0;
  911. }
  912. #endif