| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- /******************************************************************************
- 版权所有: @copyright (C) 2024-2034 HaiYang Technology Corp. All rights reserved.
- 文件名称: ustimer.c
- 文件版本: 01.01
- 创建作者: zhaoyang
- 创建日期: 2025-07-28
- 功能说明: us定时器模块驱动程序。目前使用了TIM2定时器,作为延时函数的参考定时器用。
- TIM2的时钟周期为1/3us。延时函数的最大时间长度为1431.6557653秒。
- 其它说明:
- 修改记录:
- */
- #include "bsp_ustimer.h"
- #include <stdlib.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <stdio.h>
- #include <sys/mman.h>
- #include "bsp_ccu.h"
- #include "rt_types.h"
- #define MAP_SIZE 4096UL
- #define MAP_MASK (MAP_SIZE - 1)
- #define BSP_USTIMER_DELAY_MAX_US (10UL*60*BSP_USTIMER_SEC) //10分钟
- int g_ustimer_fd = -1;
- unsigned g_ustimer_mapped_size;
- void *g_ustimer_map_base, *g_ustimer_virt_addr;
- /******************************************************************************
- 函数名称: bsp_ustimer_init
- 函数版本: 01.01
- 创建作者: zhaoyang
- 创建日期: 2025-07-28
- 函数说明: 使用timer2做为延时函数参考定时器并注册
- 参数说明: 无
- 返回值: 无
- 修改记录:
- */
- int bsp_ustimer_init(void)
- {
- void *temp_ccu_base, *temp_virt_l_base, *temp_virt_h_base, *temp_virt_ctl_base;
- unsigned long read_result;
- off_t target;
- unsigned page_size, offset_in_page;
- unsigned width = 8 * sizeof(int);
- target = TIMER_BASE;
- // 获取页面大小
- g_ustimer_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_ustimer_mapped_size *= 2;
- }
-
- g_ustimer_fd = open("/dev/mem", O_RDWR | O_SYNC);
- if (g_ustimer_fd < 0)
- {
- printf("open(/dev/mem) failed.\n");
- return -1;
- }
- fflush(stdout);
- g_ustimer_map_base = mmap (NULL, g_ustimer_mapped_size, PROT_READ | PROT_WRITE, MAP_SHARED, g_ustimer_fd, target & ~(off_t)(page_size - 1));
- if (g_ustimer_map_base == (void *)-1)
- {
- printf ("NULL pointer!\n");
- }
- else
- {
- printf ("BSP ustimer map Successfull!\n");
- }
- fflush(stdout);
- g_ustimer_virt_addr = (char*)g_ustimer_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 TMR2 clock source to HOSC, 8 pre-division */
- temp_ccu_base = g_ccu_map_base + 0x0808;
- read_result = *(volatile u_int32_t*)(temp_ccu_base);
- read_result &= ~((0x01 << 24) | 7);
- read_result |= (1 << 31) | 3;
- *(volatile u_int32_t*)(temp_ccu_base) = read_result;
- // Enable timer2
- /* set timer intervalue */
- temp_virt_l_base = (char*)g_ustimer_map_base + 0x64;
- temp_virt_h_base = (char*)g_ustimer_map_base + 0x6C;
- *(volatile u_int32_t*)(temp_virt_l_base) = 0xFFFFFFFF;
- *(volatile u_int32_t*)(temp_virt_h_base) = 0xFFFFFF;
- /* set mode to auto reload */
- temp_virt_ctl_base = (char*)g_ustimer_map_base + 0x60;
- 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);
- // read_result = *(volatile u_int32_t*)g_ustimer_virt_addr;
- // printf("ustimer_init res: 0x%08lx\n", read_result);
- return 0;
- }
- /******************************************************************************
- 函数名称: bsp_ustimer_exit
- 函数版本: 01.01
- 创建作者: zhaoyang
- 创建日期: 2025-07-28
- 函数说明: 用户定时器注销
- 参数说明: 无
- 返回值: 无
- 修改记录:
- */
- int bsp_ustimer_exit(void)
- {
- if (g_ustimer_fd >= 0)
- {
- close(g_ustimer_fd);
- g_ustimer_fd = -1;
- }
- if (munmap(g_ustimer_map_base, g_ustimer_mapped_size) == -1) {
- printf("munmap failed!");
- return -1;
- }
-
- return 0;
- }
- /******************************************************************************
- 函数名称: bsp_ustimer_get_origin
- 函数版本: 01.01
- 创建作者: zhaoyang
- 创建日期: 2025-07-28
- 函数说明: 得到当前时刻定时器的值,用作ustimer_get_duration、
- ustimer_delay_origin函数的origin参数。
- 参数说明: 无
- 返回值: 当前时刻定时器的值。
- 修改记录:
- */
- unsigned long bsp_ustimer_get_origin(void)
- {
- void *temp_virt_l_base, *temp_virt_h_base;
- u_int64_t val_low, val_high;
- if (!g_ustimer_map_base) {
- return 0;
- }
- temp_virt_l_base = (char*)g_ustimer_map_base + 0x68;
- temp_virt_h_base = (char*)g_ustimer_map_base + 0x70;
- val_low = (~*(volatile u_int32_t*)temp_virt_l_base) & TIMER_VL_MASK;
- val_high = (~*(volatile u_int32_t*)temp_virt_h_base) & TIMER_VH_MASK;
- return ((val_high << TIMER_VH_OFFSET) | val_low)/3;
- }
- /******************************************************************************
- 函数名称: bsp_ustimer_get_duration
- 函数版本: 01.01
- 创建作者: zhaoyang
- 创建日期: 2025-07-28
- 函数说明: 得到当前时刻相对于指定时间原点的时间间隔,以us为单位。
- 参数说明: origin: 时间原点,以us为单位。
- 返回值: 当前时刻相对于原点的的时间间隔。
- 修改记录:
- */
- unsigned long bsp_ustimer_get_duration(unsigned long origin)
- {
- if(!g_ustimer_map_base)
- return 0;
- // 返回差值(根据C语言算法,会自动处理回绕问题)
- return bsp_ustimer_get_origin() - origin;
- }
- /******************************************************************************
- 函数名称: bsp_ustimer_delay_origin
- 函数版本: 01.01
- 创建作者: zhaoyang
- 创建日期: 2025-07-28
- 函数说明: 以us为单位的延时函数。最大延时值为1小时(3600000000us)和
- ustimer_delay函数不同的是bsp_ustimer_delay_origin函数的延时计算的时间
- 原点为origin,而不是函数被调用的时刻。当这个函数退出时,会确保延时
- 大于等于设定值。如果需要高精度的延时,调用这个函数时应先屏蔽中断。
- 参数说明:
- origin: 延时计算的时间原点,以us为单位,通常通过ustimer_get_origin函数获得。
- us: 延时us数。
- 返回值:
- 0: 成功
- 其它: 失败
- 修改记录:
- */
- unsigned long bsp_ustimer_delay_origin(unsigned long origin,unsigned long us)
- {
- if(!g_ustimer_map_base)
- return 0;
- //检查参数
- if(us > BSP_USTIMER_DELAY_MAX_US)
- return -1;
- // 循环等待
- while (us > (bsp_ustimer_get_origin() - origin))
- ;
- return 0;
- }
- /******************************************************************************
- 函数名称: ustimer_delay
- 函数版本: 01.01
- 创建作者: zhaoyang
- 创建日期: 2025-07-28
- 函数说明: 以us为单位的延时函数。最大延时值为1小时(3600000000us)。
- 当这个函数退出时,会确保延时大于等于设定值。如果需要高精度的延时,
- 调用这个函数时应先屏蔽中断。
- 参数说明:
- us: 延时us数。
- 返回值:
- 0: 成功
- 其它: 失败
- 修改记录:
- */
- unsigned long bsp_ustimer_delay(unsigned long us)
- {
- u64 origin;
- if(!g_ustimer_map_base)
- return 0;
- //检查参数
- if(us > BSP_USTIMER_DELAY_MAX_US)
- return -1;
- origin = bsp_ustimer_get_origin();
- bsp_ustimer_delay_origin(origin, us);
- return 0;
- }
|