|
|
@@ -23,8 +23,11 @@
|
|
|
#include "bspconfig.h"
|
|
|
#include "my_rtc.h"
|
|
|
#include "rt.h"
|
|
|
-// sunxi 20220408 #include "mcf5441x_gpio.h"
|
|
|
-//#include "linux/math64.h"
|
|
|
+#include "bsp_ccu.h"
|
|
|
+#include "bsp_ustimer.h"
|
|
|
+#include "rt_printf.h"
|
|
|
+#include "rt_types.h"
|
|
|
+#include <sys/mman.h>
|
|
|
|
|
|
|
|
|
/*------------------------------- 宏定义 --------------------------------------
|
|
|
@@ -65,7 +68,9 @@ unsigned int g_irig_code_index;
|
|
|
unsigned char g_irig_code[100];
|
|
|
|
|
|
|
|
|
-
|
|
|
+int g_gps_fd = -1;
|
|
|
+unsigned g_gps_mapped_size;
|
|
|
+void *g_gps_map_base, *g_gps_virt_addr;
|
|
|
|
|
|
/*------------------------------ 函数声明 -------------------------------------
|
|
|
*/
|
|
|
@@ -80,8 +85,8 @@ void gps_isr(void);
|
|
|
/******************************************************************************
|
|
|
函数名称: gps_init
|
|
|
函数版本: 01.01
|
|
|
-创建作者: sunxi
|
|
|
-创建日期: 2008-08-06
|
|
|
+创建作者: ocean
|
|
|
+创建日期: 2025-11-21
|
|
|
函数说明: gps初始化。
|
|
|
参数说明: 无
|
|
|
返回值: 成功返回0.
|
|
|
@@ -89,47 +94,110 @@ void gps_isr(void);
|
|
|
*/
|
|
|
int gps_init(void)
|
|
|
{
|
|
|
- //设置GPIO
|
|
|
- //GPIO_GPS_INT_INIT(); //对时输入
|
|
|
- //GPIO_GPS_INIT(); //对时输出
|
|
|
-
|
|
|
- //以下设置输入捕获定时器
|
|
|
- //设置DTIM扩展模式寄存器。
|
|
|
- MCF_REG08(MCF_DTIM_DTXMR(CFG_DTIM_GPS_CAP)) = 0;
|
|
|
-
|
|
|
- //设置DTIM模式寄存器。定时器时钟源为1M,所以定时器分辨率为1us。
|
|
|
- //32位计数值的计数周期为4294.967296s(大于1.1小时),
|
|
|
- MCF_REG16(MCF_DTIM_DTMR(CFG_DTIM_GPS_CAP)) = (unsigned short)(0
|
|
|
- | MCF_DTIM_DTMR_RST //允许定时器
|
|
|
- | MCF_DTIM_DTMR_CLK_DIV1 //输入clock除1
|
|
|
- // | MCF_DTIM_DTMR_FRR //自由运行模式(free run)
|
|
|
- | MCF_DTIM_DTMR_ORRI //当参考计数值到达后,产生DMA或中断
|
|
|
- // | MCF_DTIM_DTMR_OM //输出模式为低脉冲模式
|
|
|
- // | MCF_DTIM_DTMR_CE_ANY //上升沿和下降沿都捕获
|
|
|
- | MCF_DTIM_DTMR_PS(DTIM_CLOCK_PER_US - 1));//将定时器clock周期设为1us。
|
|
|
-
|
|
|
- //不清零,因为内核中使用了该定时器
|
|
|
-
|
|
|
- //清除计数值
|
|
|
- //MCF_REG32(MCF_DTIM_DTCN(CFG_DTIM_GPS_CAP)) = 0;
|
|
|
-
|
|
|
- //清除中断
|
|
|
- MCF_REG08(MCF_DTIM_DTER(CFG_DTIM_GPS_CAP)) = MCF_DTIM_DTER_CAP | MCF_DTIM_DTER_REF;
|
|
|
-
|
|
|
- //申请实时中断
|
|
|
- rt_request_irq(CFG_DTIM_VECTOR_BEGIN + CFG_DTIM_GPS_CAP,CFG_INT_LEVEL_CLOCK,gps_isr,"gps_isr_cap");
|
|
|
-
|
|
|
- //设置参考值
|
|
|
- g_1s_refence = MCF_REG32(MCF_DTIM_DTCN(CFG_DTIM_GPS_CAP)) + 1000000;
|
|
|
- MCF_REG32(MCF_DTIM_DTRR(CFG_DTIM_GPS_CAP)) = g_1s_refence;
|
|
|
-
|
|
|
+ struct timespec ts;
|
|
|
+ struct rtc_time_t ct;
|
|
|
+ void *temp_ccu_base, *temp_virt_l_base, *temp_virt_h_base, *temp_virt_ctl_base, *temp_virt_irq_base;
|
|
|
+ unsigned long read_result;
|
|
|
+ off_t target;
|
|
|
+ unsigned page_size, offset_in_page;
|
|
|
+ unsigned width = 8 * sizeof(int);
|
|
|
+ target = TIMER_BASE;
|
|
|
+ // 获取页面大小
|
|
|
+ g_gps_mapped_size = page_size = sysconf(_SC_PAGESIZE);
|
|
|
+ offset_in_page = (unsigned)target & (page_size - 1);
|
|
|
+ if (offset_in_page + width > page_size) {
|
|
|
+ /* This access spans pages.
|
|
|
+ * Must map two pages to make it possible: */
|
|
|
+ g_gps_mapped_size *= 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ g_gps_fd = open("/dev/mem", O_RDWR | O_SYNC);
|
|
|
+ if (g_gps_fd < 0)
|
|
|
+ {
|
|
|
+ printf("open(/dev/mem) failed.\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ fflush(stdout);
|
|
|
+
|
|
|
+ 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));
|
|
|
+ if (g_gps_map_base == (void *)-1)
|
|
|
+ {
|
|
|
+ printf ("NULL pointer!\n");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ printf ("BSP gps map Successfull!\n");
|
|
|
+ }
|
|
|
+ fflush(stdout);
|
|
|
+
|
|
|
+ g_gps_virt_addr = (char*)g_gps_map_base + offset_in_page;
|
|
|
+ // printf("g_ustimer_virt_addr: %p %p %x\n", g_ustimer_virt_addr, g_ustimer_map_base, offset_in_page);
|
|
|
+
|
|
|
+ // Init timer ccu clock
|
|
|
+ /* set TMR3 clock source to HOSC, 8 pre-division */
|
|
|
+ temp_ccu_base = g_ccu_map_base + 0x080C;
|
|
|
+ read_result = *(volatile u_int32_t*)(temp_ccu_base);
|
|
|
+ read_result &= ~(0x01 << 24);
|
|
|
+ read_result |= (1 << 31) | 3;
|
|
|
+ *(volatile u_int32_t*)(temp_ccu_base) = read_result;
|
|
|
+
|
|
|
+ // Enable timer3
|
|
|
+ /* set timer intervalue */
|
|
|
+ temp_virt_l_base = (char*)g_gps_map_base + 0x84;
|
|
|
+ temp_virt_h_base = (char*)g_gps_map_base + 0x8C;
|
|
|
+ *(volatile u_int32_t*)(temp_virt_l_base) = 3000000;
|
|
|
+ *(volatile u_int32_t*)(temp_virt_h_base) = 0x0;
|
|
|
+
|
|
|
+ /* set mode to auto reload */
|
|
|
+ temp_virt_ctl_base = (char*)g_gps_map_base + 0x80;
|
|
|
+ read_result = *(volatile u_int32_t*)(temp_virt_ctl_base);
|
|
|
+ read_result &= TIMER_CTL_PERIODIC;
|
|
|
+ *(volatile u_int32_t*)(temp_virt_ctl_base) = (read_result | TIMER_CTL_AUTORELOAD | TIMER_CTL_ENABLE);
|
|
|
+
|
|
|
+ /* Enable timer interrupt */
|
|
|
+ temp_virt_irq_base = (char*)g_gps_map_base + 0x00;
|
|
|
+ read_result = *(volatile u_int32_t*)(temp_virt_irq_base);
|
|
|
+ *(volatile u_int32_t*)(temp_virt_irq_base) = (read_result | TIMER_IRQ_EN(3));
|
|
|
+
|
|
|
+ /* Get linux system current time */
|
|
|
+ clock_gettime(CLOCK_REALTIME, &ts);
|
|
|
+ timespec_to_rtc(ts, &ct, 1);
|
|
|
+ if(ct.hour>=24||ct.min>=60||ct.month>12||ct.day>31||ct.day==0||ct.month==0) // 读取系统时钟错误
|
|
|
+ {
|
|
|
+ /* Reset linux system time */
|
|
|
+ ct.year = 8;
|
|
|
+ ct.month = 8;
|
|
|
+ ct.day = 8;
|
|
|
+ ct.hour = 8;
|
|
|
+ ct.min = 8;
|
|
|
+ rtc_to_timespec(&ct, &ts);
|
|
|
+ rt_printf("gps read system date data error!!!");
|
|
|
+ }
|
|
|
+
|
|
|
+ g_sys_time.tv_sec = ts.tv_sec;
|
|
|
+ g_sys_time.tv_nsec = ts.tv_nsec;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int gps_exit(void)
|
|
|
{
|
|
|
-// MCF_REG16(MCF_DTIM_DTMR(CFG_DTIM_GPS_CAP)) = 0; //和内核ustimer共用定时器,不能关闭
|
|
|
- rt_free_irq(CFG_DTIM_VECTOR_BEGIN + CFG_DTIM_GPS_CAP);
|
|
|
+ unsigned long read_result;
|
|
|
+ void *temp_virt_ctl_base;
|
|
|
+ if (g_gps_fd >= 0)
|
|
|
+ {
|
|
|
+ close(g_gps_fd);
|
|
|
+ g_gps_fd = -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ temp_virt_ctl_base = (char*)g_gps_map_base + 0x80;
|
|
|
+ read_result = *(volatile u_int32_t*)(temp_virt_ctl_base);
|
|
|
+ read_result &= ~(TIMER_CTL_ENABLE);
|
|
|
+ *(volatile u_int32_t*)(temp_virt_ctl_base) = (read_result);
|
|
|
+
|
|
|
+ if (munmap(g_gps_map_base, g_gps_mapped_size) == -1) {
|
|
|
+ printf("munmap failed!");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
@@ -137,76 +205,63 @@ int gps_exit(void)
|
|
|
|
|
|
int gps_get_time(struct timespec *p_ts)
|
|
|
{
|
|
|
- //register long tv_sec,tv_nsec;
|
|
|
- //uint32_t flags;
|
|
|
- //unsigned int dtcn,dtrr,ref;
|
|
|
+ unsigned long flags;
|
|
|
+ register long tv_sec,tv_nsec;
|
|
|
+ unsigned long read_result;
|
|
|
+ void *temp_virt_cvl_base, *temp_virt_irq_base;
|
|
|
|
|
|
//检查参数
|
|
|
if(p_ts == 0)
|
|
|
return -1;
|
|
|
-
|
|
|
-#if 0
|
|
|
|
|
|
//关中断
|
|
|
rt_irq_save(flags);
|
|
|
|
|
|
- dtrr=g_1s_refence;
|
|
|
- dtcn=MCF_REG32(MCF_DTIM_DTCN(CFG_DTIM_GPS_CAP));
|
|
|
- //得到当前时间
|
|
|
tv_sec = g_sys_time.tv_sec;
|
|
|
+
|
|
|
+ temp_virt_cvl_base = (char*)g_gps_map_base + 0x88;
|
|
|
+ temp_virt_irq_base = (char*)g_gps_map_base + 0x04;
|
|
|
+ // read_result = *(volatile u_int32_t*)(temp_virt_cvl_base);
|
|
|
+ tv_nsec = 3000000 - (*(volatile u_int32_t*)(temp_virt_cvl_base));
|
|
|
+
|
|
|
+ if (((*(volatile u_int32_t*)(temp_virt_irq_base)) & (1 << 3)) != 0)
|
|
|
+ {
|
|
|
+ tv_sec += 1;
|
|
|
+ tv_nsec = 3000000 - (*(volatile u_int32_t*)(temp_virt_cvl_base));
|
|
|
+ }
|
|
|
|
|
|
//恢复中断级别
|
|
|
rt_irq_restore(flags);
|
|
|
|
|
|
- ref = dtrr - 1000000;
|
|
|
- tv_nsec = (dtcn - ref)*1000;
|
|
|
-
|
|
|
- while(tv_nsec > 1000000000)
|
|
|
- {
|
|
|
- tv_sec++;
|
|
|
- tv_nsec -= 1000000000;
|
|
|
- }
|
|
|
-
|
|
|
p_ts->tv_sec = tv_sec;
|
|
|
- p_ts->tv_nsec = tv_nsec;
|
|
|
-#else
|
|
|
- struct timeval tv;
|
|
|
-
|
|
|
- gettimeofday(&tv,NULL);
|
|
|
- p_ts->tv_sec = tv.tv_sec + 8*60*60;
|
|
|
- p_ts->tv_nsec = tv.tv_usec * 1000;
|
|
|
+ p_ts->tv_nsec = (tv_nsec / 3) * 1000;
|
|
|
|
|
|
-#endif
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int gps_set_time(struct timespec *p_ts)
|
|
|
{
|
|
|
-// register long tv_sec,tv_nsec;
|
|
|
- //uint32_t flags;
|
|
|
-
|
|
|
- //检查参数
|
|
|
- if(p_ts == 0)
|
|
|
+ unsigned int flags;
|
|
|
+ unsigned long tmp;
|
|
|
+ void *temp_virt_cvl_base, *temp_virt_irq_base;
|
|
|
+
|
|
|
+ if (!p_ts) {
|
|
|
return -1;
|
|
|
-
|
|
|
- //关中断
|
|
|
- rt_irq_save(flags);
|
|
|
- g_sys_time = *p_ts;
|
|
|
+ }
|
|
|
+
|
|
|
+ rt_irq_save(flags);
|
|
|
+ g_sys_time.tv_nsec = p_ts->tv_nsec;
|
|
|
+ g_sys_time.tv_sec = p_ts->tv_sec;
|
|
|
|
|
|
- //(**1**)
|
|
|
- g_1s_refence = MCF_REG32(MCF_DTIM_DTCN(CFG_DTIM_GPS_CAP)) + (1000000000 - p_ts->tv_nsec)/1000;
|
|
|
- //为了防止边界中断问题,这里让MCF_DTIM_DTCN和MCF_DTIM_DTRR的差值人为加多100us,
|
|
|
- //加多100us后,会导致定时中断推迟100us的产生,但不影响时间的正确获取.
|
|
|
- //(**2**)
|
|
|
- MCF_REG32(MCF_DTIM_DTRR(CFG_DTIM_GPS_CAP)) = g_1s_refence+100;
|
|
|
-
|
|
|
- //如果参考中断标志产生,清除中断
|
|
|
- if (MCF_REG08(MCF_DTIM_DTER(CFG_DTIM_GPS_CAP))& MCF_DTIM_DTER_REF)
|
|
|
- {
|
|
|
- MCF_REG08(MCF_DTIM_DTER(CFG_DTIM_GPS_CAP)) = MCF_DTIM_DTER_REF;
|
|
|
- }
|
|
|
- //恢复中断级别
|
|
|
- rt_irq_restore(flags);
|
|
|
+ tmp = 3000000 - ((g_sys_time.tv_nsec / 1000) * 3);
|
|
|
+ if (tmp > 3000000)
|
|
|
+ tmp = 3000000;
|
|
|
+
|
|
|
+ temp_virt_cvl_base = (char*)g_gps_map_base + 0x88;
|
|
|
+ *(volatile u_int32_t*)(temp_virt_cvl_base) = tmp;
|
|
|
+ // ((TIMER_TypeDef *) g_timer_base)->TMR3_CVH_REG = 0x0;
|
|
|
+
|
|
|
+ rt_irq_restore(flags);
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
@@ -266,6 +321,24 @@ int gps_reset(void)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/******************************************************************************
|
|
|
+函数名称: gps_pulse_isr
|
|
|
+函数版本: 01.01
|
|
|
+创建作者: ocean
|
|
|
+创建日期: 2023-11-24
|
|
|
+函数说明: gps脉冲中断
|
|
|
+参数说明: 无
|
|
|
+返回值: 成功返回0.
|
|
|
+修改记录:
|
|
|
+*/
|
|
|
+void gps_pulse_isr(void *data)
|
|
|
+{
|
|
|
+ unsigned int flags;
|
|
|
+
|
|
|
+ rt_irq_save(flags);
|
|
|
+ g_sys_time.tv_sec++;
|
|
|
+ rt_irq_restore(flags);
|
|
|
+}
|
|
|
|
|
|
/******************************************************************************
|
|
|
函数名称: gps_isr
|
|
|
@@ -280,28 +353,17 @@ int gps_reset(void)
|
|
|
|
|
|
void gps_isr(void)
|
|
|
{
|
|
|
-// rt_printf("gps_isr\n\r");
|
|
|
-
|
|
|
- //毫秒中断
|
|
|
- if(MCF_REG08(MCF_DTIM_DTER(CFG_DTIM_GPS_CAP)) & MCF_DTIM_DTER_REF)
|
|
|
- {
|
|
|
- MCF_REG08(MCF_DTIM_DTER(CFG_DTIM_GPS_CAP)) = MCF_DTIM_DTER_REF;
|
|
|
-
|
|
|
- _gps_1s_isr();
|
|
|
- }
|
|
|
-
|
|
|
- //捕获中断
|
|
|
- if(MCF_REG08(MCF_DTIM_DTER(CFG_DTIM_GPS_CAP)) & MCF_DTIM_DTER_CAP)
|
|
|
- {
|
|
|
- MCF_REG08(MCF_DTIM_DTER(CFG_DTIM_GPS_CAP)) = MCF_DTIM_DTER_CAP;
|
|
|
- timespec_to_rtc(g_sys_time, &tmp_sys_time, 1);
|
|
|
- _gps_capture_isr();
|
|
|
- rtc_to_timespec(&tmp_sys_time, &g_sys_time);
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
+ void *temp_virt_cvl_base, *temp_virt_irq_base;
|
|
|
+ // clear irq flags
|
|
|
+ if (g_gps_map_base) {
|
|
|
+ temp_virt_irq_base = (char*)g_gps_map_base + 0x04;
|
|
|
+ if (((*(volatile u_int32_t*)(temp_virt_irq_base)) & (1 << 3)) != 0)
|
|
|
+ {
|
|
|
+ gps_pulse_isr(NULL);
|
|
|
+ *(volatile u_int32_t*)(temp_virt_irq_base) = (1 << 3);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
-
|
|
|
}
|
|
|
|
|
|
/*------------------------------ 内部函数 -------------------------------------
|