305 lines
7.6 KiB
C
305 lines
7.6 KiB
C
#include "includes.h"
|
||
#include "os/os_api.h"
|
||
#include "asm/clock.h"
|
||
#include "asm/irq.h"
|
||
//#include "jiffies.h"
|
||
#include "system/timer.h"
|
||
#include "system/init.h"
|
||
#include "gpio.h"
|
||
//#include "asm/power_interface.h"
|
||
#include "generic/atomic.h"
|
||
#include "asm/cpu.h"
|
||
#include "demo_config.h"
|
||
|
||
|
||
#ifdef USE_TIMER_TEST2_DEMO
|
||
|
||
//用户只能选择:JL_TIMER2、JL_TIMER3、JL_TIMER4、JL_TIMER5
|
||
//PWM使用定时器2或者3映射PWM时候,不能用于定时
|
||
static JL_TIMER_TypeDef *TMR = JL_TIMER4;//选择定时器4
|
||
static u8 timer_irq = IRQ_TIMER4_IDX;//选择定时器4
|
||
//#define JL_TIMER_B JL_TIMER5
|
||
|
||
//u32 timer_b_cnt;
|
||
|
||
static const u8 timer_index[16] = {0, 4, 1, 5, 2, 6, 3, 7, 8, 12, 9, 13, 10, 14, 11, 15};
|
||
static const u32 timer_table[16] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768};
|
||
static u32 timer_clk = 0;
|
||
void timer4_stop(void);
|
||
void timer4_run(u32 precesion);
|
||
// timer_b_test(void);
|
||
void test(void);
|
||
|
||
|
||
#define AWINLINE __attribute__((always_inline))
|
||
|
||
//#define TSEC SEC_USED(.volatile_ram_code) //当中断1ms一下,建议使用函数放在内部ram
|
||
#define TSEC
|
||
#define TIMER_CON JL_TIMER4->CON //定时器4的控制寄存器
|
||
#define TIMER_CNT JL_TIMER4->CNT //定时器4的计数寄存器
|
||
#define TIMER_PRD JL_TIMER4->PRD //定时器4的周期寄存器
|
||
//#define TIMER_VETOR IRQ_TIMER4_IDX
|
||
|
||
struct timer_hdl {
|
||
u32 ticks;
|
||
int index;
|
||
int prd;
|
||
u32 fine_cnt;
|
||
u8 run;
|
||
u32 precesion;
|
||
void *power_ctrl;
|
||
struct list_head head;
|
||
};
|
||
|
||
static struct timer_hdl hdl;
|
||
|
||
#define __this (&hdl)
|
||
|
||
static const u32 timer_div[] = {
|
||
/*0000*/ 1,
|
||
/*0001*/ 4,
|
||
/*0010*/ 16,
|
||
/*0011*/ 64,
|
||
/*0100*/ 2,
|
||
/*0101*/ 8,
|
||
/*0110*/ 32,
|
||
/*0111*/ 128,
|
||
/*1000*/ 256,
|
||
/*1001*/ 4 * 256,
|
||
/*1010*/ 16 * 256,
|
||
/*1011*/ 64 * 256,
|
||
/*1100*/ 2 * 256,
|
||
/*1101*/ 8 * 256,
|
||
/*1110*/ 32 * 256,
|
||
/*1111*/ 128 * 256,
|
||
};
|
||
|
||
#define APP_TIMER_CLK clk_get("osc") //获得时钟源
|
||
#define MAX_TIME_CNT 0x7fff //最大计数值
|
||
#define MIN_TIME_CNT 0x100 //最小计数值
|
||
|
||
static AWINLINE TSEC void timer_cfg(u32 freq, u32 us) //定时中断配置
|
||
{
|
||
u32 clock = timer_clk;
|
||
u8 psc = 0;
|
||
u8 tmp = 0;
|
||
u32 prd = 0;
|
||
u32 ts = us / (1000 * 1000);//计算秒
|
||
u32 tu = us % (1000 * 1000);//计算秒剩余us
|
||
u8 i;
|
||
float tp = 0;
|
||
|
||
if (freq >= clock) {
|
||
freq = clock;
|
||
} else if (freq <= 1) {
|
||
freq = 1;
|
||
if (ts) {
|
||
tp = (float)tu / (1000 * 1000);
|
||
}
|
||
}
|
||
/*求prd值*/
|
||
prd = clock / freq;
|
||
if (prd > 65535) {
|
||
for (psc = 0; psc < 16; psc++) {
|
||
prd = (u32)(clock / (timer_table[psc]) / freq);
|
||
if (prd <= 65535) {
|
||
break;
|
||
} else if (psc == 15) {
|
||
prd = 65535;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
prd = ts ? (prd * ts + tp * prd) : prd;
|
||
psc = timer_index[psc];
|
||
TMR->CON = 0;
|
||
TMR->CNT = 0;
|
||
TMR->CON |= BIT(14);
|
||
TMR->PRD = prd;
|
||
TMR->CON |= psc << 4; //lsb_clk分频
|
||
TMR->CON |= BIT(0);
|
||
}
|
||
static void TSEC timer_set(u32 us)//设置时间,该函数可以在中断调用重新设置定时器值
|
||
{
|
||
u32 freq = 1000000 / us;
|
||
timer_cfg(freq, us);
|
||
}
|
||
static void TSEC timer_freq_set(u32 freq)//设置频率,该函数可以在中断调用重新设置定时器值
|
||
{
|
||
timer_cfg(freq, 0);
|
||
}
|
||
static ___interrupt TSEC void timer_isr(void)//中断
|
||
{
|
||
if (TMR->CON & BIT(15)) {
|
||
TMR->CON |= BIT(14);
|
||
putchar('@');
|
||
//todo,中断函数执行程序...
|
||
}
|
||
}
|
||
|
||
//example test
|
||
static int c_main(void)
|
||
{
|
||
timer_clk = clk_get("timer");//先获取定时器的时钟源
|
||
request_irq(timer_irq, 3, timer_isr, 0);//注册中断函数定和中断优先级
|
||
#if 1
|
||
timer_set(50 * 1000); //初始化50ms进一次中断
|
||
os_time_dly(500);
|
||
timer4_stop(); //定时器停止
|
||
os_time_dly(500);
|
||
timer4_run(2); //定时器开始
|
||
os_time_dly(500);
|
||
test(); //输入捕获功能测试
|
||
#else
|
||
//timer_freq_set(10000);//设置10K频率进中断
|
||
#endif
|
||
return 0;
|
||
}
|
||
|
||
static void timer4_suspend(void) //定时器暂停
|
||
{
|
||
if (__this->run) {
|
||
__this->ticks = JL_TIMER4->CNT;
|
||
JL_TIMER4->CON = 0;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
static void timer4_resume(void) //定时器继续
|
||
{
|
||
if (__this->run == 0) {
|
||
return;
|
||
}
|
||
u32 prd_cnt;
|
||
u8 index;
|
||
//precesion = PRD * index / CLK
|
||
for (index = 0; index < (sizeof(timer_div) / sizeof(timer_div[0])); index++) {
|
||
prd_cnt = __this->precesion * (APP_TIMER_CLK / 1000) / timer_div[index];
|
||
if (prd_cnt > MIN_TIME_CNT && prd_cnt < MAX_TIME_CNT) {
|
||
break;
|
||
}
|
||
}
|
||
|
||
__this->index = index;
|
||
__this->prd = prd_cnt;
|
||
JL_TIMER4->CNT = __this->ticks;
|
||
JL_TIMER4->PRD = prd_cnt; //2ms
|
||
JL_TIMER4->CON = (index << 4) | BIT(0) | BIT(3);
|
||
}
|
||
|
||
void timer4_stop(void) //定时器停止
|
||
{
|
||
printf("--->Stop");
|
||
JL_TIMER4->CON = BIT(14);
|
||
__this->run = 0;
|
||
__this->precesion = 0;
|
||
}
|
||
|
||
|
||
|
||
void timer4_run(u32 precesion) //定时器开始
|
||
|
||
{
|
||
precesion = 2;//br23 br25 周期不变化 为减少占用cpu资源,固定收集2ms内的计数值 可去掉
|
||
if (__this->precesion == precesion) {
|
||
return;
|
||
}
|
||
printf("-->Run %d", precesion);
|
||
JL_TIMER4->CON = BIT(14);
|
||
__this->precesion = precesion;
|
||
__this->run = 1;
|
||
__this->ticks = 0;
|
||
timer4_resume();
|
||
}
|
||
|
||
//////输入捕获
|
||
static bool isr_flag = false; //设立中断标志位
|
||
enum edge_mode {
|
||
RISE_EDGE = 0,
|
||
FALL_EDGE,
|
||
};
|
||
|
||
bool timer5_interrupt(void)
|
||
{
|
||
return isr_flag;
|
||
}
|
||
|
||
|
||
void timer5_start(void) //定时器5开始,清空计数器和标志位
|
||
{
|
||
JL_TIMER5->CNT = 0;
|
||
isr_flag = false;
|
||
|
||
}
|
||
|
||
___interrupt
|
||
static void timer5_isr(void)
|
||
{
|
||
JL_TIMER5->CON |= BIT(14);
|
||
isr_flag = true;
|
||
}
|
||
|
||
int timer5_get_cnt(void) //10us
|
||
{
|
||
u32 a = JL_TIMER5->PRD;
|
||
u32 b = a * 96 / 100; //53Mhz/512k 再转化为10us
|
||
|
||
return b ;
|
||
}
|
||
|
||
void timer5_init(int mode) //定时器5初始化
|
||
{
|
||
JL_TIMER5->CNT = 0;
|
||
#if CPU_CORE_NUM > 1
|
||
request_irq(IRQ_TIMER5_IDX, 1, timer5_isr, 1);
|
||
#else
|
||
request_irq(IRQ_TIMER5_IDX, 1, timer5_isr, 0);
|
||
#endif
|
||
JL_TIMER5->CON = BIT(7) | BIT(6);//lsb_clk的512分频
|
||
if (mode == FALL_EDGE) {
|
||
JL_TIMER5->CON |= BIT(0) | BIT(1);//下降沿捕获
|
||
gpio_direction_input(IO_PORTC_08);//输入引脚为PC8
|
||
gpio_set_pull_up(IO_PORTC_08, 1);
|
||
} else {
|
||
JL_TIMER5->CON |= BIT(1);//上升沿捕获
|
||
gpio_direction_input(IO_PORTC_08);
|
||
gpio_set_pull_down(IO_PORTC_08, 1);
|
||
}
|
||
}
|
||
|
||
void timer5_uninit(void)
|
||
{
|
||
JL_TIMER5->CON = 0;
|
||
}
|
||
void test(void)
|
||
{
|
||
extern bool timer5_interrupt(void);
|
||
extern void timer5_start(void);
|
||
extern void timer5_init(int mode); //mode: 0 上升沿 1 下降沿
|
||
extern void timer5_uninit(void);
|
||
extern int timer5_get_cnt(void);
|
||
|
||
|
||
timer5_init(1);
|
||
printf("-------%s-------%d\r\n", __func__, __LINE__);
|
||
|
||
while (1) {
|
||
timer5_start(); //先清空下数据
|
||
printf("-------%s-------%d\r\n", __func__, __LINE__);
|
||
|
||
while (!timer5_interrupt()) { //检测到有下降沿则为true,采用轮询方式每200ms检测一次
|
||
os_time_dly(20);
|
||
}
|
||
printf("-------%s-------%d get cnt = %d\r\n", __func__, __LINE__, timer5_get_cnt()); //返回出来的是单位是10us 的cnt 就是 cnt* 100 000就是秒
|
||
/* timer5_get_cnt(); */
|
||
|
||
|
||
}
|
||
timer5_uninit(); //用完就释放
|
||
}
|
||
late_initcall(c_main);
|
||
|
||
|
||
#endif
|