hwdelay_task.h
#ifndef _HWDELAY_TASK_H_
#define _HWDELAY_TASK_H_
#include <rtthread.h>
#include <stdint.h>
#define DELAY_MAILBOX_MAX 5
/*
* 值为10us, 那么该延时任务的误差就有10us, 该值设置要大量测试
* 10us 出现了发送一次指令, 执行两次的情况(一次)
* 20us 小幅度测试没出现异样
*/
#define DELAY_HWTIMER_INTERVAL_US 20
/*
* 这个结果值要大于0
*/
#define HWDELAYTASK_CALC_DELAY_COUNT(us) (us < DELAY_HWTIMER_INTERVAL_US ? 1 : us/DELAY_HWTIMER_INTERVAL_US)
/*
* 这个 s 值不能超过 2147.483647; 因为 int 所能表示的最大范围为 2147483647
*/
#define HWDELAYTASK_CALC_DELAY_COUNT2(s, us) (((s*1000000)+us)/DELAY_HWTIMER_INTERVAL_US)
struct DelayMailbox{
volatile uint32_t count;//延时计数, 做减法, 减到0时,将数据发送到邮箱
rt_mailbox_t send_mb;//任务到达后被发送到的邮箱
void* data;
};
extern rt_mailbox_t MbGuidDataDelayHandle;
int8_t delaytask_init();
int8_t delaytask_add(struct DelayMailbox* dmb);
#endif
hwdelay_task.c
#include "hwdelay_task.h"
#include "bsp_gpt.h"
#define DELAY_HWTIMER_DEV_NAME "gpt2" /* 定时器名称 */
static struct imxrt_gpt* dev_hwtimer_hwdelay;
static int8_t state;
static volatile struct DelayMailbox DelayMbs[DELAY_MAILBOX_MAX] = {0};
static volatile uint8_t DelayMbsFront = 0; //队首
static volatile uint8_t DelayMbsRear = 0; //队尾,最后一个元素的索引+1
rt_mailbox_t MbGuidDataDelayHandle;
static void ht_timeout_cb(void* dev, uint32_t size){
//这里要测验定时器超时回调中的代码执行时长, 其执行时长要小于定时器的超时时间
uint8_t i = DelayMbsFront;
while(i != DelayMbsRear){
//printf("DelayMbs[%u].count: %u\r\n", i, DelayMbs[i].count);
DelayMbs[i].count--;
if(DelayMbs[i].count == 0){
rt_mb_send(DelayMbs[i].send_mb, (rt_ubase_t)DelayMbs[i].data);
DelayMbsFront = (DelayMbsFront+1)%DELAY_MAILBOX_MAX;
return;
}
i = (i+1)%DELAY_MAILBOX_MAX;
}
return;
}
int8_t delaytask_init(){
rt_err_t res;
MbGuidDataDelayHandle = rt_mb_create("_MGDDH", DELAY_MAILBOX_MAX, RT_IPC_FLAG_FIFO);
dev_hwtimer_hwdelay = bsp_gpt_init(DELAY_HWTIMER_DEV_NAME, ht_timeout_cb);
if (dev_hwtimer_hwdelay == RT_NULL) {
printf("hwtimer sample run failed! can't find %s device!\r\n", DELAY_HWTIMER_DEV_NAME);
return -1;
}
hwtimerval_t timerval = {0, DELAY_HWTIMER_INTERVAL_US};
bsp_gpt_start(dev_hwtimer_hwdelay, &timerval, HWTIMER_MODE_PERIOD);
return 0;
}
int8_t delaytask_add(struct DelayMailbox* dmb){
if((DelayMbsRear+1)%DELAY_MAILBOX_MAX == DelayMbsFront){
return -1;
}
DelayMbs[DelayMbsRear].count = dmb->count;
DelayMbs[DelayMbsRear].data = dmb->data;
DelayMbs[DelayMbsRear].send_mb = dmb->send_mb;
DelayMbsRear = (DelayMbsRear+1)%DELAY_MAILBOX_MAX;
//printf("DelayMbsRear: %d\r\n", DelayMbsRear);
return 0;
}