IMX257 LED驱动程序实现

发布时间:2024-08-15  

由于昨天对IMX257的地址分配不了解,所以前面只能用s3c24xx的驱动程序来了解ioremap等对IO端口的工作原理。

但是经过昨晚对IMX257芯片的细细梳理,今天早上起来又把IMX257的芯片资料看了一遍,终于成功看懂了,下面意义给大家道来。

我们此处使用ERR_LED 也就是GPIO3_23引脚

 

一、IMX257 芯片资料分析

1.确定相关寄存器基址

 

确定IOMUX地址

 

GPIO3的地址

 

2.确定相关寄存器的偏移地址

IOMUX的相关的模式配置寄存器,配置为ALT5模式

偏移地址:

寄存器描述:

 

接下来就是配置GPIO的相关信息,上拉,CMOS输入输出,等信息

偏移地址:

寄存器描述:

 

这个是有关ERR_LED的引脚的一些信息

 

GPIO寄存器的偏移地址

因为每个GPIO上最大只有32位,刚刚好上面的DR寄存器每一位就是表示单独一个引脚的电平

 

二、IMX257 代码分析

1.定义一些寄存器

//寄存器基址;

static unsigned long mem_iomux;

static unsigned long mem_gpio3;

static unsigned long base_iomux;     //iomux基址 0X 43FA C000 - 0X 43FA FFFF

static unsigned long base_gpio3;    //gpio3     0X 53FA 4000 - 0X 53FA 7FFF

// MUX_CTL模式选择 配置寄存器

#define MUX_CTL (*(volatile unsigned long *)(base_iomux + 0x0060))

// PAD_CTL GPIO常用功能设置

#define PAD_CTL (*(volatile unsigned long *)(base_iomux + 0x0270))

// GPIO DR 数据寄存器 DR

#define DR_GPIO3 (*(volatile unsigned long *)(base_gpio3 + 0x0000))

// GPIO GDIR 方向控制寄存器 GDIR

#define GDIR_GPIO3 (*(volatile unsigned long *)(base_gpio3 + 0x0004))

如图所示:

 

2.在init函数中初始化寄存器,及做相应的配置

 

IO端口申请:

配置引脚为ALT5 GPIO模式

 

配置引脚的电平,1.8v, CMOS输出,都是配置为0

 

配置为端口引脚为输出模式,并且初始化电平

 

打印各个寄存器的地址信息

 

将LED灯1秒间隔闪烁

 

 

3.在exit函数中释放IO端口

 

 

4.编译测试

 

硬件:

如图所示ERR_LED灯点亮

 

ERR_LED等熄灭

好了,大功告成:


附上驱动程序代码:


  1 #include

  2 #include

  3 #include

  4 #include

  5 #include

  6 #include

  7 #include

  8 #include

  9 #include

 10 #include

 11 #include

 12 #include

 13 #include

 14 

 15 #define Driver_NAME 'err_led_dev'

 16 #define DEVICE_NAME 'err_led_dev'

 17 

 18 static int major = 0;

 19 

 20 //auto to create device node

 21 static struct class *drv_class = NULL;

 22 static struct class_device *drv_class_dev = NULL;

 23 

 24 //寄存器基址;

 25 static unsigned long mem_iomux;

 26 static unsigned long mem_gpio3;

 27 static unsigned long base_iomux;      //iomux基址 0X 43FA C000 -  0X 43FA FFFF

 28 static unsigned long base_gpio3;    //gpio3      0X 53FA 4000 -  0X 53FA 7FFF

 29 // MUX_CTL模式选择  配置寄存器

 30 #define MUX_CTL  (*(volatile unsigned long *)(base_iomux + 0x0060))

 31 // PAD_CTL GPIO常用功能设置

 32 #define PAD_CTL  (*(volatile unsigned long *)(base_iomux + 0x0270))

 33 // GPIO DR   数据寄存器  DR

 34 #define DR_GPIO3 (*(volatile unsigned long *)(base_gpio3 + 0x0000))

 35 // GPIO GDIR 方向控制寄存器  GDIR

 36 #define GDIR_GPIO3 (*(volatile unsigned long *)(base_gpio3 + 0x0004))

 37 

 38 

 39 static int key_open(struct inode *inode, struct file *file)

 40 {

 41     printk('<0>function open!nn');

 42     return 0;

 43 }

 44 

 45 static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)

 46 {

 47     return 0;

 48 }

 49 

 50 static ssize_t key_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)

 51 {

 52     printk('<0>function write!nn');

 53     return 1;

 54 }

 55 

 56 static int  key_release(struct inode *inode, struct file *filp)

 57 {

 58     printk('<0>function write!nn');

 59     return 0;

 60 }

 61 

 62 static int key_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)

 63 {

 64     printk('<0>function ioctl!nn');

 65     return 0;

 66 }

 67 static struct file_operations key_fops = {

 68     .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */

 69     .open   =   key_open,

 70     .read   =   key_read,

 71     .write  =   key_write,

 72     .release=   key_release,

 73     .ioctl  =   key_ioctl,

 74 };

 75 

 76 void gpio_addr(void){

 77     printk('<0>addr base_iomux : %x n',base_iomux);

 78     printk('<0>addr base_gpio3 : %x n',base_gpio3);

 79     printk('<0>addr MUX_CTL : %x n',&MUX_CTL);

 80     printk('<0>addr PAD_CTL : %x n',&PAD_CTL);

 81     printk('<0>addr GDIR_GPIO3 : %x n',&GDIR_GPIO3);

 82     printk('<0>addr DR_GPIO3 : %x n',&DR_GPIO3);

 83 }

 84 

 85 void led_on_off(void){

 86     ssleep(1);

 87     DR_GPIO3 |= (0x01 << 23);        //将GPIO2_23置1

 88     ssleep(1);

 89     DR_GPIO3 &= ~(0x01 << 23);        //将GPIO2_23清零

 90     ssleep(1);

 91     DR_GPIO3 |= (0x01 << 23);        //将GPIO2_23置1

 92     ssleep(1);

 93     DR_GPIO3 &= ~(0x01 << 23);        //将GPIO2_23清零

 94     ssleep(1);

 95     DR_GPIO3 |= (0x01 << 23);        //将GPIO2_23置1

 96     ssleep(1);

 97     DR_GPIO3 &= ~(0x01 << 23);        //将GPIO2_23清零

 98     ssleep(1);

 99     DR_GPIO3 |= (0x01 << 23);        //将GPIO2_23置1

100     ssleep(1);

101     DR_GPIO3 &= ~(0x01 << 23);        //将GPIO2_23清零

102     ssleep(1);

103     DR_GPIO3 |= (0x01 << 23);        //将GPIO2_23置1

104 }

105 

106 static int __init  key_irq_init(void)

107 {

108     printk('<0>nHello,this is %s module!nn',Driver_NAME);

109     //register and mknod

110     major = register_chrdev(0,Driver_NAME,&key_fops);

111     drv_class = class_create(THIS_MODULE,Driver_NAME);

112     drv_class_dev = device_create(drv_class,NULL,MKDEV(major,0),NULL,DEVICE_NAME);  /*/dev/key_query*/

113     

114     //IO端口申请 ioremap  可以直接通过指针来访问这些地址

115     base_iomux = ioremap(0x43FAC000,0xFFF);

116     base_gpio3 = ioremap(0x53FA4000,0xFFF);

117 

118     //MUX_CTL

119     MUX_CTL &= ~(0x07 << 0);    

120     MUX_CTL |= (0X05 << 0);    //设置为ALT5  GPIO3_23 ERR_LED

121     //PAD_CTL

122     PAD_CTL &= ~(0x01<<13 | 0x01<<3 | 0x03<<1 | 0x01<<0);   //1.8v 不需要上拉下拉  CMOS输出 slew rate

123     //GDIR_GPIO3    配置为输出模式

124     GDIR_GPIO3 &= ~(0x01 << 23);    

125     GDIR_GPIO3 |= (0x01 << 23);    //配置为输出模式    

126 

127     //DR_GPIO3        配置为输出0 点亮ERR_LED

128     DR_GPIO3 &= ~(0x01 << 23);        //将GPIO2_23清零

129     DR_GPIO3 &= ~(0x01 << 23);        //将GPIO2_23清零

130     gpio_addr();

131     led_on_off();

132     return 0; 

133 }

134                      

135 static void __exit key_irq_exit(void)

136 {

137     gpio_addr();

138     printk('<0>nGoodbye,%s!nn',Driver_NAME);

139     led_on_off();

140 

141        unregister_chrdev(major,Driver_NAME);

142     device_unregister(drv_class_dev);

143     class_destroy(drv_class);

144     

145     //释放IO端口

146     iounmap(base_iomux);

147     iounmap(base_gpio3);

148 }

149 

150 

151 /* 这两行指定驱动程序的初始化函数和卸载函数 */

152 module_init(key_irq_init);

153 module_exit(key_irq_exit);

154 

155 /* 描述驱动程序的一些信息,不是必须的 */

156 MODULE_AUTHOR('Lover雪儿');

157 MODULE_VERSION('0.1.0');

158 MODULE_DESCRIPTION('IMX257 key Driver');

159 MODULE_LICENSE('GPL');


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>