From 878b222741dd2b628240d1b19401c04ae507860f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8B=A4=E4=B8=BA=E6=9C=AC?= <1207280597@qq.com> Date: Tue, 18 Jul 2017 11:33:27 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=86=E2=80=9C=E9=BE=99=E8=8A=AF1c=E5=BA=93?= =?UTF-8?q?=E2=80=9D=E4=B8=AD=E7=A1=AC=E4=BB=B6=E5=AE=9A=E6=97=B6=E5=99=A8?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E6=8E=A5=E5=8F=A3=E7=A7=BB=E6=A4=8D=E5=88=B0?= =?UTF-8?q?RT-Thread?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/ls1cdev/libraries/ls1c_timer.c | 200 +++++++++++++++++++++++++++++ bsp/ls1cdev/libraries/ls1c_timer.h | 69 ++++++++++ 2 files changed, 269 insertions(+) create mode 100644 bsp/ls1cdev/libraries/ls1c_timer.c create mode 100644 bsp/ls1cdev/libraries/ls1c_timer.h diff --git a/bsp/ls1cdev/libraries/ls1c_timer.c b/bsp/ls1cdev/libraries/ls1c_timer.c new file mode 100644 index 0000000000..8c3b164121 --- /dev/null +++ b/bsp/ls1cdev/libraries/ls1c_timer.c @@ -0,0 +1,200 @@ +// 硬件定时器源码 + + +#include "ls1c_public.h" +#include "ls1c_pin.h" +#include "ls1c_clock.h" +#include "ls1c_regs.h" +#include "ls1c_pwm.h" +#include "ls1c_timer.h" + + +// 定时器中计数器(CNTR、HRC和LRC)的最大值 +#define TIMER_COUNTER_MAX (0xffffff) + + + +/* + * 获取指定定时器的寄存器基地址 + * @timer 硬件定时器 + * @ret 基地址 + */ +unsigned int timer_get_reg_base(ls1c_timer_t timer) +{ + unsigned int reg_base = 0; + + switch (timer) + { + case TIMER_PWM0: + reg_base = LS1C_REG_BASE_PWM0; + break; + + case TIMER_PWM1: + reg_base = LS1C_REG_BASE_PWM1; + break; + + case TIMER_PWM2: + reg_base = LS1C_REG_BASE_PWM2; + break; + + case TIMER_PWM3: + reg_base = LS1C_REG_BASE_PWM3; + break; + } + + return reg_base; +} + + +/* + * 初始化定时器,并开始定时 + * @timer_info 定时器和定时时间信息 + */ +void timer_init(timer_info_t *timer_info) +{ + unsigned int timer_reg_base = 0; // 寄存器基地址 + unsigned long timer_clk = 0; // 硬件定时器的时钟 + unsigned long tmp; + unsigned int ctrl = 0; // 控制寄存器中的控制信息 + + // 判断入参 + if (NULL == timer_info) + { + return ; + } + + /* + * 把定时时间换算为计数器的值 + * 计数器值 = 定时器的时钟 * 定时时间(单位ns) / 1000000000 + * 龙芯1c的定时器时钟为APB时钟,达到126Mhz, + * 为避免计算过程发生溢出,这里采用手动优化上面的计算式,也可以采用浮点运算 + */ + timer_clk = clk_get_apb_rate(); + tmp = (timer_clk / 1000000) * (timer_info->time_ns / 1000); // 将1000000000拆分为1000000和1000 + tmp = MIN(tmp, TIMER_COUNTER_MAX); + + // 控制寄存器信息 + ctrl = (1 << LS1C_PWM_INT_LRC_EN) + | (0 << LS1C_PWM_INT_HRC_EN) + | (0 << LS1C_PWM_CNTR_RST) + | (0 << LS1C_PWM_INT_SR) + | (1 << LS1C_PWM_INTEN) + | (1 << LS1C_PWM_SINGLE) + | (1 << LS1C_PWM_OE) + | (1 << LS1C_PWM_CNT_EN); + + // 设置各个寄存器 + timer_reg_base = timer_get_reg_base(timer_info->timer); // 获取寄存器基地址 + reg_write_32(0, (volatile unsigned int *)(timer_reg_base + LS1C_PWM_HRC)); + reg_write_32(tmp--, (volatile unsigned int *)(timer_reg_base + LS1C_PWM_LRC)); + reg_write_32(0, (volatile unsigned int *)(timer_reg_base + LS1C_PWM_CNTR)); + reg_write_32(ctrl, (volatile unsigned int *)(timer_reg_base + LS1C_PWM_CTRL)); + + return ; +} + + +/* + * 判断指定定时器是否超时(实现定时) + * @timer_info 定时器 + * @ret TRUE or FALSE + */ +BOOL timer_is_time_out(timer_info_t *timer_info) +{ + unsigned int timer_reg_base = 0; // 寄存器基地址 + unsigned int ctrl; // 控制寄存器的值 + + // 判断入参 + if (NULL == timer_info) + { + return FALSE; + } + + // 读取控制寄存器 + timer_reg_base = timer_get_reg_base(timer_info->timer); + ctrl = reg_read_32((volatile unsigned int *)(timer_reg_base + LS1C_PWM_CTRL)); + + // 判断中断状态位 + if (ctrl & (1 << LS1C_PWM_INT_SR)) + { + return TRUE; + } + else + { + return FALSE; + } +} + + + +/* + * 停止定时器 + * @timer_info 定时器 + */ +void timer_stop(timer_info_t *timer_info) +{ + unsigned int timer_reg_base = 0; + + // 判断入参 + if (NULL == timer_info) + { + return ; + } + + timer_reg_base = timer_get_reg_base(timer_info->timer); + reg_write_32(0, (volatile unsigned int *)(timer_reg_base + LS1C_PWM_CTRL)); + + return ; +} + + + +/* + * 获取定时器从初始化到现在的时间(实现计时功能),单位ns + * @timer_info 硬件定时器 + * @ret 时间,单位ns + */ +unsigned long timer_get_time_ns(timer_info_t *timer_info) +{ + unsigned int timer_reg_base = 0; + unsigned int cntr = 0; // 寄存器CNTR的值 + unsigned long time_ns = 0; // 时间,单位ns + unsigned long timer_clk = 0; // 定时器时钟 + + // 读取寄存器CNTR的值 + timer_reg_base = timer_get_reg_base(timer_info->timer); + cntr = reg_read_32((volatile unsigned int *)(timer_reg_base + LS1C_PWM_CNTR)); + + /* + * 将CNTR值换算为时间,单位us + * 时间 = (计数器值CNTR * 1000000000) / 定时器时钟频率 + * 为避免产生溢出,手动优化上式为 时间 = (计数器值CNTR * 1000) / (定时器时钟频率 / 1000000) + */ + timer_clk = clk_get_apb_rate(); + time_ns = (cntr * 1000 ) / (timer_clk /1000000); +// myprintf("[%s] time_us=%lu, cntr=%d, timer_clk=%d\n", __FUNCTION__, time_ns, cntr, timer_clk); + + return time_ns; +} + + + +/* + * 打印timer相关寄存器的值 + * @timer_info 硬件定时器 + */ +void timer_print_regs(timer_info_t *timer_info) +{ + unsigned int timer_reg_base = 0; + + timer_reg_base = timer_get_reg_base(timer_info->timer); + myprintf("CNTR=0x%x, HRC=0x%x, LRC=0x%x, CTRL=0x%x\n", + reg_read_32((volatile unsigned int *)(timer_reg_base + LS1C_PWM_CNTR)), + reg_read_32((volatile unsigned int *)(timer_reg_base + LS1C_PWM_HRC)), + reg_read_32((volatile unsigned int *)(timer_reg_base + LS1C_PWM_LRC)), + reg_read_32((volatile unsigned int *)(timer_reg_base + LS1C_PWM_CTRL))); + + return ; +} + + diff --git a/bsp/ls1cdev/libraries/ls1c_timer.h b/bsp/ls1cdev/libraries/ls1c_timer.h new file mode 100644 index 0000000000..df38c705f5 --- /dev/null +++ b/bsp/ls1cdev/libraries/ls1c_timer.h @@ -0,0 +1,69 @@ +// 硬件定时器头文件 + + +#ifndef __OPENLOONGSON_TIMER_H +#define __OPENLOONGSON_TIMER_H + + +#include "ls1c_public.h" + + +// 硬件定时器 +typedef enum +{ + TIMER_PWM0, // PWM0用作硬件定时器 + TIMER_PWM1, // PWM1用作硬件定时器 + TIMER_PWM2, // PWM2用作硬件定时器 + TIMER_PWM3 // PWM3用作硬件定时器 +}ls1c_timer_t; + + +// 硬件定时器信息 +typedef struct +{ + ls1c_timer_t timer; // 硬件定时器 + unsigned long time_ns; // 定时时间 +}timer_info_t; + + + +/* + * 初始化定时器,并开始定时 + * @timer_info 定时器和定时时间信息 + */ +void timer_init(timer_info_t *timer_info); + + +/* + * 判断指定定时器是否超时 + * @timer_info 定时器 + * @ret TRUE or FALSE + */ +BOOL timer_is_time_out(timer_info_t *timer_info); + + +/* + * 停止定时器 + * @timer_info 定时器 + */ +void timer_stop(timer_info_t *timer_info); + + + +/* + * 获取定时器从初始化到现在的时间(实现计时功能),单位ns + * @timer_info 硬件定时器 + * @ret 时间,单位ns + */ +unsigned long timer_get_time_ns(timer_info_t *timer_info); + + +/* + * 打印timer相关寄存器的值 + * @timer_info 硬件定时器 + */ +void timer_print_regs(timer_info_t *timer_info); + + +#endif +