基于I.MX6UL平台的ADS1256驱动开发三.基础驱动框架

我们通过前两章的内容完成了驱动移植和重构的准备工作,下面我们就开始处理驱动代码了。

驱动的基础架构我们采用和前面学习的platform框架一样,并且通过GPIO子系统对GPIO实现初始化的配置。

  1 /**
  2  * @file ads1256_base1.c
  3  * @author your name (you@domain.com)
  4  * @brief platform基础框架
  5  * @version 0.1
  6  * @date 2022-12-05
  7  * 
  8  * @copyright Copyright (c) 2022
  9  * 
 10  */
 11 #include <linux/module.h>
 12 #include <linux/kernel.h>
 13 #include <linux/init.h>
 14 #include <linux/fs.h>
 15 #include <linux/uaccess.h>
 16 #include <linux/io.h>
 17 #include <linux/types.h>
 18 #include <linux/cdev.h>
 19 #include <linux/device.h>
 20 #include <linux/of.h>
 21 #include <linux/of_address.h>
 22 #include <linux/of_irq.h>
 23 #include <linux/gpio.h>
 24 #include <linux/of_gpio.h>
 25 #include <linux/irq.h>
 26 #include <linux/interrupt.h>
 27 #include <linux/input.h>
 28 #include <linux/spi/spi.h>
 29 #include <linux/delay.h>
 30 #include <linux/platform_device.h>
 31 
 32 #include "ads1256.h"
 33 #include "ads1256reg.h"
 34 /*
 35     ADS1256模块       开发板
 36       +5V   <------  5.0V      5V供电
 37       GND   -------  GND       地
 38       PDWN  <------  PC8       掉电控制 常高
 39       RST   <------  PC13      复位信号 常高
 40 
 41       DRDY  ------>  GPIO1_IO24(8)       准备就绪
 42       DIN   <------  GPIO1_IO22(9)       SPI_MOSI
 43       DOUT  ------>  GPIO1_IO23(10)      SPI_MISO
 44       SCLK  <------  GPIO1_IO21(11)      SPI时钟
 45       CS    <------  GPIO1_IO03(15)      SPI_CS
 46 
 47       NC   空脚
 48       NC   空脚
 49 */
 50 
 51 #define ads1256_CNT            1
 52 #define ads1256_NAME           "ads1256"
 53 
 54 struct ads1256_device ads1256_dev;
 55 
 56 #define CS_0()        gpio_set_value(ads1256_dev.cs_gpio, 0)
 57 #define CS_1()        gpio_set_value(ads1256_dev.cs_gpio, 1)
 58 
 59 #define SCK_0()       gpio_set_value(ads1256_dev.clk_gpio, 0)
 60 #define SCK_1()       gpio_set_value(ads1256_dev.clk_gpio, 1)
 61 
 62 #define DI_0()        gpio_set_value(ads1256_dev.mosi_gpio, 0)
 63 #define DI_1()        gpio_set_value(ads1256_dev.mosi_gpio, 1)
 64 
 65 #define DO_IS_HIGH()  gpio_get_value(ads1256_dev.miso_gpio)==1
 66 #define DRDY_IS_LOW() gpio_get_value(ads1256_dev.drdy_gpio)==0
 67 
 68 
 69 static int ads1256_open(struct inode *inode, struct file *file)
 70 {
 71     int ret = 0;
 72     printk("file open!\r\n");
 73     return ret;
 74 }
 75 
 76 ssize_t ads1256_read(struct file *file, char __user *buf, size_t cnt, loff_t *off)
 77 {
 78     int ret = 0;
 79     return ret;
 80 }
 81 static int ads1256_release(struct inode *inode, struct file *file)
 82 {
 83     int ret = 0;
 84     return ret;
 85 }
 86 
 87 struct file_operations ads1256_fops = {
 88     .owner = THIS_MODULE,
 89     .open = ads1256_open,
 90     .read = ads1256_read,
 91     .release = ads1256_release,
 92 };
 93 
 94 
 95 static int ads1256_probe(struct platform_device *dev)
 96 {   
 97     int ret = 0;
 98     printk("ads1256 probe\r\n");
 99 
100     /*注册字符设备号*/
101     ads1256_dev.major = 0;
102     if(ads1256_dev.major){
103         ads1256_dev.dev_id = MKDEV(ads1256_dev.major,0);
104         ret = register_chrdev_region(ads1256_dev.dev_id,ads1256_CNT,ads1256_NAME);
105     }
106     else{
107         ret = alloc_chrdev_region(&ads1256_dev.dev_id,0,ads1256_CNT,ads1256_NAME);
108         ads1256_dev.major = MAJOR(ads1256_dev.dev_id);
109         ads1256_dev.minor = MINOR(ads1256_dev.dev_id);
110     }
111     printk("major\r\n");
112 
113     if(ret<0)
114     {
115         printk("ads1256 chrdev_region err\r\n");
116         goto fail_devid;
117     }
118 
119     /*添加字符设备*/
120     ads1256_dev.cdev.owner = THIS_MODULE;
121     cdev_init(&ads1256_dev.cdev,&ads1256_fops);
122     ret = cdev_add(&ads1256_dev.cdev,ads1256_dev.dev_id,ads1256_CNT);
123     if(ret<0)
124     {
125         goto fail_cdev;
126     }
127 
128     ads1256_dev.class = class_create(THIS_MODULE,ads1256_NAME);
129     if(IS_ERR(ads1256_dev.class))
130     {
131         ret = PTR_ERR(ads1256_dev.class);
132         goto fail_class;
133     }
134 
135     ads1256_dev.device = device_create(ads1256_dev.class,NULL,
136                                         ads1256_dev.dev_id,NULL,ads1256_NAME);
137     if(IS_ERR(ads1256_dev.device))
138     {
139         ret = PTR_ERR(ads1256_dev.device);
140         goto fail_device;
141     }
142 
143     /*gpio初始化*/
144     ads1256_dev.node =of_find_node_by_path("/ads1256");                          //获取节点
145     /*片选引脚*/
146     ads1256_dev.cs_gpio = of_get_named_gpio(ads1256_dev.node,"ads1256-gpios",0);
147     if(ads1256_dev.cs_gpio < 0 ){
148         printk("can't get gpio cs\r\n");
149         goto fail_gpio;
150     }
151 
152     ret = gpio_request(ads1256_dev.cs_gpio,"cs");            //这里省略判定
153     ret = gpio_direction_output(ads1256_dev.cs_gpio,1);      //默认高电平
154 
155     /*时钟引脚*/
156     ads1256_dev.clk_gpio = of_get_named_gpio(ads1256_dev.node,"ads1256-gpios",1);
157     if(ads1256_dev.clk_gpio < 0 ){
158         printk("can't get gpio clk\r\n");
159         goto fail_gpio;
160     }
161     
162     ret = gpio_request(ads1256_dev.clk_gpio,"clk");            //这里省略判定
163     ret = gpio_direction_output(ads1256_dev.clk_gpio,0);      //默认低
164     if(ret<0){
165         printk("clk_gpio request faild\r\n");
166         goto fail_gpio;
167     }
168 
169     /*MOSI引脚*/
170     ads1256_dev.mosi_gpio = of_get_named_gpio(ads1256_dev.node,"ads1256-gpios",2);
171     if(ads1256_dev.mosi_gpio < 0 ){
172         printk("can't get gpio mosi\r\n");
173         goto fail_gpio;
174     }
175     
176     ret = gpio_request(ads1256_dev.mosi_gpio,"mosi");            //这里省略判定
177     ret = gpio_direction_output(ads1256_dev.mosi_gpio,0);        //默认低电平
178     if(ret<0){
179         printk("mosi_gpio request faild\r\n");
180         goto fail_gpio;
181     }
182 
183     /*MISO引脚*/
184     ads1256_dev.miso_gpio = of_get_named_gpio(ads1256_dev.node,"ads1256-gpios",3);
185     if(ads1256_dev.miso_gpio < 0 ){
186         printk("can't get gpio miso\r\n");
187         goto fail_gpio;
188     }
189     
190     ret = gpio_request(ads1256_dev.miso_gpio,"miso");       
191     if(ret<0){
192         printk("miso_gpio request faild\r\n");
193         goto fail_gpio;
194     }
195 
196     /*DRDY引脚*/
197     ads1256_dev.drdy_gpio = of_get_named_gpio(ads1256_dev.node,"ads1256-gpios",4);
198     if(ads1256_dev.drdy_gpio<0){
199         printk("can't get gpio drdy");
200         goto fail_gpio;
201     }
202 
203     ret = gpio_request(ads1256_dev.drdy_gpio,"drdy");
204     if(ret<0){
205         printk("drdy_gpio request faild\r\n");
206         goto fail_gpio;
207     }
208 
209     return 0;
210 
211 fail_gpio:
212 fail_device:
213     class_destroy(ads1256_dev.class);
214 fail_class:
215     cdev_del(&ads1256_dev.cdev);
216 fail_cdev:
217     unregister_chrdev_region(ads1256_dev.dev_id,ads1256_CNT);
218 fail_devid:
219     return 0;
220 }
221 
222 
223 static int ads1256_remove(struct platform_device *dev)
224 {
225     int ret = 0;
226 
227     cdev_del(&ads1256_dev.cdev);
228     unregister_chrdev_region(ads1256_dev.dev_id,ads1256_CNT);
229     device_destroy(ads1256_dev.class,ads1256_dev.dev_id);
230     class_destroy(ads1256_dev.class);        
231     gpio_free(ads1256_dev.cs_gpio);
232     gpio_free(ads1256_dev.clk_gpio);
233     gpio_free(ads1256_dev.mosi_gpio);
234     gpio_free(ads1256_dev.miso_gpio);
235     gpio_free(ads1256_dev.drdy_gpio);
236 
237     printk("device remove\r\n");
238 
239     return 0;
240 }
241 
242 static const struct of_device_id ads1256_of_match[] = {
243     {.compatible = "ads1256"},
244     {}
245 };
246 
247 
248 struct platform_driver ads1256_driver = {
249     .driver = {
250         .name = "ads1256",
251         .of_match_table = ads1256_of_match,
252     },
253     .probe = ads1256_probe,
254     .remove = ads1256_remove,
255 };
256 
257 static int __init ads1256_init(void)
258 {
259     int ret = 0;
260     printk("__init\r\n");
261     ret =  platform_driver_register(&ads1256_driver);
262     return ret;
263 }
264 
265 static void __exit ads1256_exit(void)
266 {
267     platform_driver_unregister(&ads1256_driver);
268 }
269 
270 module_init(ads1256_init);
271 module_exit(ads1256_exit);
272 MODULE_LICENSE("GPL");
273 MODULE_AUTHOR("AC");

整个框架的流程很清楚了!倒着看比较合适

257~263行是驱动的入口,用来匹配ads1256的驱动,加载的过程

248~255行是定义的platform_driver结构体,通过242~245行的结构体进行匹配,在设备树下匹配到一致名称的device,就可以驱动设备,执行第253行probe指向的函数(ads1256_probe)。

ads1256_probe是驱动的主体,主要完成了字符串设备的注册,然后是GPIO的初始化。整个流程在前面写字符设备驱动的流程是完全一致的。没什么可说的。

ads1256_remove函数是驱动卸载时执行的函数,里面就是所用资源的释放。

架构完成以后,可以make生成对应的ko文件,复制到rootfs下加载一下看看效果

 一定要重复加载和卸载驱动模块的过程,防止在卸载过程中有哪些资源没有完全释放,导致驱动重新加载失败。(这一章节我把文件名设置为ads1256_base1,表示为驱动基础框架)

上面的内容完成以后,说明GPIO已经可以供我们使用了,我们可以测试一下CS、CLK和MOSI的输出

CS_0();
int i = 0;
for(i=0; i<10;i++)
{
    printk("%d\r\n",i);
    if(i%2==0){
        
        DI_0();
        SCK_0();
    }
    else{
        DI_1();
        SCK_1();
    }
    mdelay(5);
}
CS_1();

代码直接放在gpio初始化后面,其中DI_0。SCK_1等是前面定义的宏, 直接操作CPIO输出对应的高低电平。

用逻辑分析仪看一下

 

 CS信号应该是一直拉低的,但是会跟着其他两个信号跳变。调整一下代码会发现是时钟信号导致的,不操作时钟的时候就没问题了。

 

不过这个状态对实际使用时没有影响的,不知道是不是硬件上有什么问题。

下面就需要按照前面的资料完成IC的相关操作了!

posted @ 2022-12-11 23:11  银色的音色  阅读(191)  评论(0编辑  收藏  举报