Linux 字符设备驱动开发基础(二)—— 编写简单 PWM 设备驱动【转】

本文介绍了Linux环境下如何编写字符设备驱动,用于控制PWM蜂鸣器。首先分析原理图确定控制I/O口和寄存器,接着使用ioremap等函数进行地址映射和寄存器操作,实现蜂鸣器的开关和频率控制。然后展示了驱动程序的结构,包括open、release、ioctl等函数的实现,并提供了测试程序以验证驱动功能。
摘要由CSDN通过智能技术生成

本文转载自:https://blog.csdn.net/zqixiao_09/article/details/50858776

版权声明:本文为博主原创文章,未经博主允许不得转载。    https://blog.csdn.net/zqixiao_09/article/details/50858776
       编写驱动的第一步仍是看原理图:
       可以看到,该蜂鸣器由 GPD0_0 来控制 ,查手册可知该I/O口由Time0 来控制,找到相应的寄存器:
a -- I/O口寄存器及地址
      GPD0CON  0x114000a0
b -- Time0 寄存器及地址
      基地址为:TIMER_BASE 0x139D0000
      这些物理寄存器地址都是相邻的,我们这里用偏移量来表示:
      寄存器名      地址偏移量            所需配置
        TCFG0          0x0000              [7-0]     0XFF
        TCFG1          0x0004              [3-0]     0X2              
        TCON            0x0008              [3-0]     0X2       0X9   0X0
        TCNTB0        0x000C             500
        TCMPB0       0x0010              250
       前面已经知道,驱动是无法直接操纵物理地址的,所以这里仍需物理地址向虚拟地址的转换,用到 ioremap() 函数、writel()函数、readl()函数:
1、地址映射操作
unsigned int   *gpd0con;
void *timer_base;<span style="white-space:pre">    </span>//之所以是void类型,偏移量为4时,只是移动4个字节,方便理解
gpd0con = ioremap(GPD0CON,4);
timer_base = ioremap(TIMER_BASE , 0x14);
2、Time0初始化操作(这里使用的已经是虚拟地址)
       这里现将数据从寄存器中读出,修改后再写回寄存器,具体寄存器操作可以移步Exynos4412裸机开发——PWM定时器:   
writel((readl(gpd0con)&~(0xf<<0)) | (0x2<<0),gpd0con);
writel ((readl(timer_base +TCFG0  )&~(0xff<<0)) | (0xff <<0),timer_base +TCFG0);
writel ((readl(timer_base +TCFG1 )&~(0xf<<0)) | (0x2 <<0),timer_base +TCFG1 );
3、装载数据,配置占空比
writel(500, timer_base +TCNTB0  );
writel(250, timer_base +TCMPB0 );
writel ((readl(timer_base +TCON )&~(0xf<<0)) | (0x2 <<0),timer_base +TCON );
4、相关控制函数
void beep_on(void)
{
    writel ((readl(timer_base +TCON )&~(0xf<<0)) | (0x9 <<0),timer_base +TCON );
}
void beep_off(void)
{
    writel ((readl(timer_base +TCON )&~(0xf<<0)) | (0x0 <<0),timer_base +TCON );
}
下面是驱动程序,这里我们用到了 write() read() ioctl() 函数,具体解析移步:
驱动程序:beep.c
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <asm/io.h>
#include <asm/uaccess.h>
static int major = 250;
static int minor=0;
static dev_t devno;
static struct class *cls;
static struct device *test_device;
#define GPD0CON       0x114000a0
#define TIMER_BASE    0x139D0000           
#define TCFG0         0x0000               
#define TCFG1         0x0004                            
#define TCON          0x0008             
#define TCNTB0        0x000C          
#define TCMPB0        0x0010           
static unsigned int *gpd0con;
static void *timer_base;
#define  MAGIC_NUMBER    'k'
#define  BEEP_ON    _IO(MAGIC_NUMBER    ,0)
#define  BEEP_OFF   _IO(MAGIC_NUMBER   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式小庄老师

要是觉得不错,就给我点支持吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值