先记录下Linux GPIO模拟串口笔记。
串口协议:
起始位 + 8位数据 + 结束位 【不考虑校验位】
波特率:9600 【先实现9600】
串口发送: 按9600波特率对应的时间间隔,将10位bit数据发送出去。
0,x,x,x,x,x,x,x,x,1. x对应数据的8位。
不打算去兼容系统uart框架,太麻烦了。
网上整理的实现:
中断实现发送:实现对应9600的定时器,在定时器内发送对应Bit位。
一般高精度hrtimer实现,移植性强。
延时实现 :udelay(~~9600~~),发送对应bit位,耗cpu。
考虑cpu性能较弱,我这边用硬件定时器timer2来做定时器。
理论上:精度高于前两种,对cpu性能影响最小。
测试平台新唐N32926 主频240M ARM9, 性能太弱鸡。
对应定时器示例Code:
测试及验证精度:
查看系统时间中断的次数,
cat /proc/interrupts | grep timer
对比系统timer中断次数的,算倍数关系。
#define DEF_BPS 9600
static irqreturn_t w55fa92_timer2_irq(int irq, void *dev_id);
static void w55fa92_clockevent_setmode(void)
{
unsigned int val;
val = __raw_readl(REG_TCSR2);
val &= ~(0x03 << 27);
__raw_writel(CLOCK_TICK_RATE / DEF_BPS/3, REG_TICR2); //采样3次
val |= (TMR_PERIOD | TMR_COUNTEN | TMR_INTEN);
__raw_writel(val, REG_TCSR2);
}
/*IRQ handler for the timer*/
static irqreturn_t w55fa92_timer2_irq(int irq, void *dev_id)
{
__raw_writel(0x01, REG_TISR2); /* clear TIF2 */
/* 添加串口收发处理函数 */
return IRQ_HANDLED;
}
static void __init w55fa92_clockevents_init(void)
{
struct clk *clk = clk_get(NULL, "timer2");
BUG_ON(IS_ERR(clk));
clk_enable(clk);
__raw_writel(0x00, REG_TCSR2);
__raw_writel(0x01, REG_TISR2);
if (request_irq
(IRQ_TIMER2, w55fa92_timer2_irq, IRQF_TIMER, "timer2",
NULL) != 0) {
printk("register the keypad_irq failed!\n");
return -1;
}
}
后续添加其他部分code
Linux GPIO模拟串口之硬件定时器
最新推荐文章于 2022-06-07 11:01:43 发布