linux设备驱动 spi详解6-spi驱动实例

linux内核给了一个spi驱动的实例。

driver/spi/spidev.c 

1 spi_driver.c

  1 #include <linux/init.h>
  2 #include <linux/module.h>
  3 #include <linux/ioctl.h>
  4 #include <linux/fs.h>
  5 #include <linux/device.h>
  6 #include <linux/err.h>
  7 #include <linux/list.h>
  8 #include <linux/errno.h>
  9 #include <linux/mutex.h>
 10 #include <linux/slab.h>
 11 #include <linux/compat.h>
 12 #include <linux/of.h>
 13 #include <linux/of_device.h>
 14 
 15 #include <linux/spi/spi.h>
 16 #include <linux/spi/spidev.h>
 17 
 18 #include <asm/uaccess.h>  
 19   
 20 #define SPIDEV_MAJOR            153 //spidev主设备号  
 21 #define N_SPI_MINORS            32  /* ... up to 256 */  
 22 static DECLARE_BITMAP(minors, N_SPI_MINORS);    //声明次设备位图  
 23 #define SPI_MODE_MASK (SPI_CPHA|SPI_CPOL|SPI_CS_HIGH|SPI_LSB_FIRST|SPI_3WIRE|SPI_LOOP|SPI_NO_CS|SPI_READY)  
 24   
 25 struct spidev_data {  
 26     dev_t   devt;               //设备号  
 27     spinlock_t  spi_lock;       //自旋锁  
 28     struct spi_device   *spi;   //spi设备结构体  
 29     struct list_head    device_entry;  
 30     struct mutex    buf_lock;   //互斥锁  
 31     unsigned        users;      //使用者计数  
 32     u8          *buffer;        //缓冲区  
 33 };  
 34   
 35 static LIST_HEAD(device_list);  //声明spi设备链表  
 36 static DEFINE_MUTEX(device_list_lock);  //定义互斥锁  
 37 static unsigned bufsiz = 4096;  //最大传输缓冲区大小  
 38 module_param(bufsiz, uint, S_IRUGO);  
 39 MODULE_PARM_DESC(bufsiz, "data bytes in biggest supported SPI message");  
 40   
 41 static void spidev_complete(void *arg)  
 42 {  
 43     complete(arg);  //调用complete  
 44 }  
 45   
 46 static ssize_t spidev_sync(struct spidev_data *spidev, struct spi_message *message)  
 47 {  
 48     DECLARE_COMPLETION_ONSTACK(done);  
 49     int status;  
 50   
 51     message->complete = spidev_complete; //设置spi消息的complete方法 回调函数  
 52     message->context = &done;  
 53   
 54     spin_lock_irq(&spidev->spi_lock);  
 55     if (spidev->spi == NULL) //判断是否有指定对应的spi设备  
 56         status = -ESHUTDOWN;  
 57     else  
 58         status = spi_async(spidev->spi, message);    //spi异步同步  
 59     spin_unlock_irq(&spidev->spi_lock);  
 60   
 61     if (status == 0) {  
 62         wait_for_completion(&done); //等待传输完成  
 63         status = message->status;    //获取spi消息传输事务状态  
 64         if (status == 0)  
 65             status = message->actual_length; //status等于传输的实际长度  
 66     }  
 67     return status;  //返回实际传输长度  
 68 }  
 69   
 70 static inline ssize_t spidev_sync_write(struct spidev_data *spidev, size_t len)  
 71 {  
 72     struct spi_transfer t = {  
 73             .tx_buf     = spidev->buffer,    //发送缓冲区  
 74             .len        = len,  //发送数据长度  
 75         };  
 76     struct spi_message  m;  
 77   
 78     spi_message_init(&m);   //初始化spi消息(初始化spi传递事务队列)  
 79     spi_message_add_tail(&t, &m);   //添加spr传递到该队列  
 80     return spidev_sync(spidev, &m); //同步读写  
 81 }  
 82   
 83 static inline ssize_t spidev_sync_read(struct spidev_data *spidev, size_t len)  
 84 {  
 85     struct spi_transfer t = {  
 86             .rx_buf     = spidev->buffer,    //接收缓冲区  
 87             .len        = len,  //接收数据长度  
 88         };  
 89     struct spi_message  m;  
 90   
 91     spi_message_init(&m);   //初始化spi消息(初始化spi传递事务队列)  
 92     spi_message_add_tail(&t, &m);   //添加spr传递到该队列  
 93     return spidev_sync(spidev, &m); //同步读写  
 94 }  
 95   
 96 static ssize_t spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)  
 97 {  
 98     struct spidev_data  *spidev;  
 99     ssize_t status = 0;  
100   
101     if (count > bufsiz)  //传输数据大于缓冲区容量  
102         return -EMSGSIZE;  
103     spidev = filp->private_data; //从文件私有数据指针获取spidev_data  
104     mutex_lock(&spidev->buf_lock);   //上互斥锁  
105     status = spidev_sync_read(spidev, count);   //同步读,返回传输数据长度  
106     if (status > 0) {  
107         unsigned long   missing;    //丢失的数据个数  
108         missing = copy_to_user(buf, spidev->buffer, status); //内核空间复制到用户空间  
109         if (missing == status)      //丢失的数据个数等于要传输的数据个数  
110             status = -EFAULT;  
111         else  
112             status = status - missing;  //传输成功的数据个数  
113     }  
114     mutex_unlock(&spidev->buf_lock);//解互斥锁  
115     return status;  //返回读取成功的数据个数  
116 }  
117   
118 static ssize_t spidev_write(struct file *filp, const char __user *buf,size_t count, loff_t *f_pos)  
119 {  
120     struct spidev_data  *spidev;  
121     ssize_t         status = 0;  
122     unsigned long       missing;  
123   
124     if (count > bufsiz)  //传输数据大于缓冲区容量  
125         return -EMSGSIZE;  
126     spidev = filp->private_data; //从文件私有数据指针获取spidev_data  
127     mutex_lock(&spidev->buf_lock);   //上互斥锁  
128     missing = copy_from_user(spidev->buffer, buf, count);    //用户空间复制到内核空间  
129     if (missing == 0) { //传输失败个数为0  
130         status = spidev_sync_write(spidev, count);  //同步写,返回传输数据长度  
131     }   
132     else  
133         status = -EFAULT;  
134     mutex_unlock(&spidev->buf_lock);//解互斥锁  
135     return status;  //返回写数据的实际个数  
136 }  
137   
138 static int spidev_message(struct spidev_data *spidev,struct spi_ioc_transfer *u_xfers, unsigned n_xfers)  
139 {  
140     struct spi_message  msg;  
141     struct spi_transfer *k_xfers;  
142     struct spi_transfer *k_tmp;  
143     struct spi_ioc_transfer *u_tmp;  
144     unsigned    n, total;  
145     u8  *buf;  
146     int status = -EFAULT;  
147   
148     spi_message_init(&msg); //初始化spi消息(初始化spi传递事务队列)  
149     k_xfers = kcalloc(n_xfers, sizeof(*k_tmp), GFP_KERNEL); //分配spi传输指针内存  
150     if (k_xfers == NULL)  
151         return -ENOMEM;  
152     buf = spidev->buffer;    //获取spidev_data的缓冲区  
153     total = 0;  
154     //n=xfers为spi_ioc_transfer个数,u_tmp = u_xfers为要处理的spi_ioc_transfer指针  
155     for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers;n;n--, k_tmp++, u_tmp++) {  
156         k_tmp->len = u_tmp->len;  //设置传输信息的长度  
157         total += k_tmp->len; //累加传输信息的总长度  
158         if (total > bufsiz) {    //信息量超过bufsiz缓冲区最大容量  
159             status = -EMSGSIZE;  
160             goto done;  
161         }  
162         if (u_tmp->rx_buf) { //接收缓冲区指针不为空  
163             k_tmp->rx_buf = buf; //缓冲区指向buf  
164             if (!access_ok(VERIFY_WRITE, (u8 __user *)(uintptr_t) u_tmp->rx_buf,u_tmp->len))  
165                 goto done;  
166         }  
167         if (u_tmp->tx_buf) { //发送缓冲区指针不为空  
168             k_tmp->tx_buf = buf; //缓冲区指针指向buf  
169             if (copy_from_user(buf, (const u8 __user *)(uintptr_t) u_tmp->tx_buf,u_tmp->len)) //用户空间复制数据到buf  
170                 goto done;  
171         }  
172         buf += k_tmp->len;   //缓冲区指针移动一个传输信息的长度  
173         k_tmp->cs_change = !!u_tmp->cs_change;    //设置cs_change  
174         k_tmp->bits_per_word = u_tmp->bits_per_word;  //设置bits_per_word 一个字多少位  
175         k_tmp->delay_usecs = u_tmp->delay_usecs;  //设置delay_usecs 毫秒级延时  
176         k_tmp->speed_hz = u_tmp->speed_hz;    //设置speed_hz 速率  
177 #ifdef VERBOSE  
178         dev_dbg(&spidev->spi->dev,"  xfer len %zd %s%s%s%dbits %u usec %uHz\n",  
179             u_tmp->len,u_tmp->rx_buf ? "rx " : "",u_tmp->tx_buf ? "tx " : "",u_tmp->cs_change ? "cs " : "",  
180             u_tmp->bits_per_word ? : spidev->spi->bits_per_word,u_tmp->delay_usecs,u_tmp->speed_hz ? : spidev->spi->max_speed_hz);  
181 #endif  
182         spi_message_add_tail(k_tmp, &msg);  //添加spr传递到该队列  
183     }  
184     //for循环的作用是将spi_ioc_transfer批量转换为spi传递结构体spi_transfer,然后添加进spi传递事务队列  
185     status = spidev_sync(spidev, &msg);     //同步读写  
186     if (status < 0)  
187         goto done;  
188     buf = spidev->buffer;    //获取spidev_data缓冲区指针  
189     for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) {   //批量从内核空间复制spi_ioc_transfer到用户空间  
190         if (u_tmp->rx_buf) { //判断是否存在接收缓冲区  
191             if (__copy_to_user((u8 __user *)(uintptr_t) u_tmp->rx_buf, buf,u_tmp->len)) {  
192                 status = -EFAULT;  
193                 goto done;  
194             }  
195         }  
196         buf += u_tmp->len;   //buf指针位置调整指向下一个spi_ioc_transfer  
197     }  
198     status = total; //status等于实际传输的数据长度  
199 done:  
200     kfree(k_xfers); //释放k_xfers  
201     return status;  //返回实际传输的数据长度  
202 }  
203   
204 static long spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  
205 {  
206     int err = 0;  
207     int retval = 0;  
208     struct spidev_data  *spidev;  
209     struct spi_device   *spi;  
210     u32 tmp;  
211     unsigned    n_ioc;  
212     struct spi_ioc_transfer *ioc;  
213   
214     if (_IOC_TYPE(cmd) != SPI_IOC_MAGIC)    //判断控制命令的类型  
215         return -ENOTTY;  
216     if (_IOC_DIR(cmd) & _IOC_READ)  //判断控制命令的方向是否为读read  
217         err = !access_ok(VERIFY_WRITE,(void __user *)arg, _IOC_SIZE(cmd));  //判断传输数据大小  
218     if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE) //判断控制命令的方向是否为写write  
219         err = !access_ok(VERIFY_READ,(void __user *)arg, _IOC_SIZE(cmd));   //判断传输数据大小  
220     if (err)  
221         return -EFAULT;  
222   
223     spidev = filp->private_data; //从文件私有数据中获取spidev_data  
224     spin_lock_irq(&spidev->spi_lock);    //上自旋锁  
225     spi = spi_dev_get(spidev->spi);          //获取spi设备  
226     spin_unlock_irq(&spidev->spi_lock);  //解自旋锁  
227     if (spi == NULL)    //获取spi设备失败  
228         return -ESHUTDOWN;  //则返回错误  
229     mutex_lock(&spidev->buf_lock);   //上互斥锁  
230       
231     switch (cmd) {  
232     case SPI_IOC_RD_MODE:   //设置spi读模式  (此处原作者的理解与我不同,这里应该是应用程序获取数据)
233         retval = __put_user(spi->mode & SPI_MODE_MASK,(__u8 __user *)arg);  
234         break;  
235     case SPI_IOC_RD_LSB_FIRST:  //设置spi读最低有效位  (此处原作者的理解与我不同,这里应该是应用程序获取数据)
236         retval = __put_user((spi->mode & SPI_LSB_FIRST) ?  1 : 0,(__u8 __user *)arg);  
237         break;  
238     case SPI_IOC_RD_BITS_PER_WORD:  //设置spi读每个字含多个个位  (此处原作者的理解与我不同,这里应该是应用程序获取数据)
239         retval = __put_user(spi->bits_per_word, (__u8 __user *)arg);  
240         break;  
241     case SPI_IOC_RD_MAX_SPEED_HZ:   //设置spi读最大速率  (此处原作者的理解与我不同,这里应该是应用程序获取数据)
242         retval = __put_user(spi->max_speed_hz, (__u32 __user *)arg);  
243         break;  
244     case SPI_IOC_WR_MODE:   //设置spi写模式  
245         retval = __get_user(tmp, (u8 __user *)arg);  
246         if (retval == 0) {  
247             u8  save = spi->mode;    //获取spi设备模式  
248   
249             if (tmp & ~SPI_MODE_MASK) {  
250                 retval = -EINVAL;  
251                 break;  
252             }  
253   
254             tmp |= spi->mode & ~SPI_MODE_MASK;  
255             spi->mode = (u8)tmp;  
256             retval = spi_setup(spi);    //配置spi设备  
257             if (retval < 0)  
258                 spi->mode = save;  
259             else  
260                 dev_dbg(&spi->dev, "spi mode %02x\n", tmp);  
261         }  
262         break;  
263     case SPI_IOC_WR_LSB_FIRST:  //设置spi写最低有效位  
264         retval = __get_user(tmp, (__u8 __user *)arg);  
265         if (retval == 0) {  
266             u8  save = spi->mode;    //获取spi设备模式  
267   
268             if (tmp)  
269                 spi->mode |= SPI_LSB_FIRST;  
270             else  
271                 spi->mode &= ~SPI_LSB_FIRST;  
272             retval = spi_setup(spi);    //配置spi设备  
273             if (retval < 0)  
274                 spi->mode = save;  
275             else  
276                 dev_dbg(&spi->dev, "%csb first\n",tmp ? 'l' : 'm');  
277         }  
278         break;  
279     case SPI_IOC_WR_BITS_PER_WORD:  //设置spi写每个字含多个个位  
280         retval = __get_user(tmp, (__u8 __user *)arg);   //用户空间获取数据  
281         if (retval == 0) {  
282             u8  save = spi->bits_per_word;   //获取spi设备 每个字含多少位  
283   
284             spi->bits_per_word = tmp;    //更新新的spi设备 每个字含多少位  
285             retval = spi_setup(spi);    //配置spi设备  
286             if (retval < 0)  //配置失败  
287                 spi->bits_per_word = save;   //还原spi设备 每个字含多少位  
288             else  
289                 dev_dbg(&spi->dev, "%d bits per word\n", tmp);  
290         }  
291         break;  
292     case SPI_IOC_WR_MAX_SPEED_HZ:       //设置spi写最大速率  
293         retval = __get_user(tmp, (__u32 __user *)arg);  //用户空间获取数据  
294         if (retval == 0) {  
295             u32 save = spi->max_speed_hz;    //获取spi设备最大速率  
296   
297             spi->max_speed_hz = tmp; //更新新的spi设备最大速率  
298             retval = spi_setup(spi);    //配置spi设备  
299             if (retval < 0)  //配置失败  
300                 spi->max_speed_hz = save;    //还原spi设备最大速率  
301             else  
302                 dev_dbg(&spi->dev, "%d Hz (max)\n", tmp);  
303         }  
304         break;  
305   
306     default:  
307         //命令必须为写方向的命令,且传输数据必须是SPI_IOC_MESSAGE()修饰的命令  
308         if (_IOC_NR(cmd) != _IOC_NR(SPI_IOC_MESSAGE(0))|| _IOC_DIR(cmd) != _IOC_WRITE) {  
309             retval = -ENOTTY;  
310             break;  
311         }  
312   
313         tmp = _IOC_SIZE(cmd);   //计算传输数据大小  
314         if ((tmp % sizeof(struct spi_ioc_transfer)) != 0) { //判断是否为spi_ioc_transfer对齐  
315             retval = -EINVAL;  
316             break;  
317         }  
318         n_ioc = tmp / sizeof(struct spi_ioc_transfer);  //计算出spi_ioc_transfer数据的个数  
319         if (n_ioc == 0)  
320             break;  
321   
322         ioc = kmalloc(tmp, GFP_KERNEL); //分配spi_ioc_transfer指针ioc内存  
323         if (!ioc) {  
324             retval = -ENOMEM;  
325             break;  
326         }  
327         if (__copy_from_user(ioc, (void __user *)arg, tmp)) {   //从用户空间复制到内核空间  
328             kfree(ioc); //复制失败则释放ioc内存  
329             retval = -EFAULT;  
330             break;  
331         }  
332   
333         retval = spidev_message(spidev, ioc, n_ioc);    //spidev消息处理  
334         kfree(ioc); //释放ioc内存  
335         break;  
336     }  
337   
338     mutex_unlock(&spidev->buf_lock); //解互斥锁  
339     spi_dev_put(spi);   //增加spi设备的引用计数  
340     return retval;  
341 }  
342   
343 static int spidev_open(struct inode *inode, struct file *filp)  
344 {  
345     struct spidev_data  *spidev;  
346     int status = -ENXIO;  
347   
348     mutex_lock(&device_list_lock);  //上互斥锁  
349     list_for_each_entry(spidev, &device_list, device_entry) {   //遍历device_list  
350         if (spidev->devt == inode->i_rdev) {  //判断设备号找到对应的设备  
351             status = 0; //设置状态为0  
352             break;  
353         }  
354     }  
355     if (status == 0) {  //找得到对应的设备  
356         if (!spidev->buffer) {   //spidev_data缓冲区为空  
357             spidev->buffer = kmalloc(bufsiz, GFP_KERNEL);    //则分配内存  
358             if (!spidev->buffer) {   //还空  
359                 dev_dbg(&spidev->spi->dev, "open/ENOMEM\n");  //申请内存失败  
360                 status = -ENOMEM;  
361             }  
362         }  
363         if (status == 0) {  //找得到对应的设备  
364             spidev->users++; //spidev_data使用者计数++  
365             filp->private_data = spidev; //spidev_data放在文件的私有数据里  
366             nonseekable_open(inode, filp);  //设置文件的打开模式(文件读写指针不会跟随读写操作移动)  
367         }  
368     }   
369     else  
370         pr_debug("spidev: nothing for minor %d\n", iminor(inode));  
371     mutex_unlock(&device_list_lock);    //接互斥锁  
372     return status;  
373 }  
374   
375 static int spidev_release(struct inode *inode, struct file *filp)  
376 {  
377     struct spidev_data  *spidev;  
378     int status = 0;  
379   
380     mutex_lock(&device_list_lock);  
381     spidev = filp->private_data; //获取spidev_data  
382     filp->private_data = NULL;       //清除文件的私有数据指针  
383     spidev->users--;             //使用者个数--  
384     if (!spidev->users) {    //如果使用者个数为0  
385         int     dofree;  
386         kfree(spidev->buffer);   //释放spidev_data的缓冲区内存  
387         spidev->buffer = NULL;   //清除spidev_data缓冲区指针  
388         spin_lock_irq(&spidev->spi_lock);    //上自旋锁  
389         dofree = (spidev->spi == NULL);  //判断spi设备是否与spidev_data解绑了  
390         spin_unlock_irq(&spidev->spi_lock);  //解自旋锁  
391         if (dofree)         //没有捆绑的spi设备  
392             kfree(spidev);  //则是否spidev_data内存  
393     }  
394     mutex_unlock(&device_list_lock);  
395     return status;  
396 }  
397   
398 static const struct file_operations spidev_fops = {     //文件操作函数集  
399     .owner =    THIS_MODULE,  
400     .write =    spidev_write,       //写write  
401     .read =     spidev_read,        //读read  
402     .unlocked_ioctl = spidev_ioctl, //控制ioctl  
403     .open =     spidev_open,        //打开open  
404     .release =  spidev_release,     //释放release  
405     .llseek =   no_llseek,          //文件指针移动 no_llseek表示没有移动  
406 };  
407   
408 static struct class *spidev_class;  
409   
410 static int __devinit spidev_probe(struct spi_device *spi)  
411 {  
412     struct spidev_data  *spidev;  
413     int status;  
414     unsigned long   minor;  
415   
416     spidev = kzalloc(sizeof(*spidev), GFP_KERNEL);  //分配spidev_data内存  
417     if (!spidev)  
418         return -ENOMEM;  
419     spidev->spi = spi;   //设置spidev_data->spi(spi设备)  
420     spin_lock_init(&spidev->spi_lock);  
421     mutex_init(&spidev->buf_lock);  
422     INIT_LIST_HEAD(&spidev->device_entry);   //初始化spidev_data入口链表  
423     mutex_lock(&device_list_lock);  
424     minor = find_first_zero_bit(minors, N_SPI_MINORS);  //查找次设备位图分配次设备号  
425     if (minor < N_SPI_MINORS) {  
426         struct device *dev;  
427         spidev->devt = MKDEV(SPIDEV_MAJOR, minor);   //计算出设备号  
428         //创建设备/dev/spidev%d.%d(spidev总线号.片选号)  
429         dev = device_create(spidev_class, &spi->dev, spidev->devt,spidev, "spidev%d.%d",spi->master->bus_num, spi->chip_select);  
430         status = IS_ERR(dev) ? PTR_ERR(dev) : 0;  
431     }   
432     else {  
433         dev_dbg(&spi->dev, "no minor number available!\n");  
434         status = -ENODEV;  
435     }  
436     if (status == 0) {  //分配设备号成功  
437         set_bit(minor, minors); //更新次设备位图  
438         list_add(&spidev->device_entry, &device_list);   //添加进设备链表  
439     }  
440     mutex_unlock(&device_list_lock);  
441   
442     if (status == 0)  
443         spi_set_drvdata(spi, spidev);   //spi->dev->p->driver_data=spidev   
444     else  
445         kfree(spidev);  
446   
447     return status;  
448 }  
449   
450 static int __devexit spidev_remove(struct spi_device *spi)  
451 {  
452     struct spidev_data  *spidev = spi_get_drvdata(spi);     //根据spi设备获取spidev_data  
453     spin_lock_irq(&spidev->spi_lock);            //上自旋锁  
454     spidev->spi = NULL;                              //清空spidev_data->spi指针  
455     spi_set_drvdata(spi, NULL);                     //spi->dev->p->driver_data=NULL  
456     spin_unlock_irq(&spidev->spi_lock);          //解自旋锁  
457     mutex_lock(&device_list_lock);              //上互斥锁  
458     list_del(&spidev->device_entry);             //删除spidev_data入口链表  
459     device_destroy(spidev_class, spidev->devt);      //销毁/dev/spidev%d.%d  
460     clear_bit(MINOR(spidev->devt), minors);          //清除次设备位图对应位  
461     if (spidev->users == 0)                          //使用者个数为0  
462         kfree(spidev);                              //释放spidev_data内存  
463     mutex_unlock(&device_list_lock);            //解互斥锁  
464     return 0;  
465 }  
466   
467 static struct spi_driver spidev_spi_driver = {  //spi设备驱动  
468     .driver = {  
469         .name =     "spidev",  
470         .owner =    THIS_MODULE,  
471     },  
472     .probe =    spidev_probe,   //spidev的probe方法(当注册了modalias域为"spidev"的spi设备或板级设备,则会调用probe方法)  
473     .remove =   __devexit_p(spidev_remove), //spidev的remove方法  
474 };  
475   
476 static int __init spidev_init(void)     //spidev接口初始化  
477 {  
478     int status;  
479     BUILD_BUG_ON(N_SPI_MINORS > 256);  
480     //注册字符设备,主设备号SPIDEV_MAJOR=153,捆绑的设备操作函数集为spidev_fops  
481     status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops);  
482     if (status < 0)  
483         return status;  
484     spidev_class = class_create(THIS_MODULE, "spidev"); //创建设备类spidev_class  
485     if (IS_ERR(spidev_class)) {  
486         unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);  
487         return PTR_ERR(spidev_class);  
488     }  
489     status = spi_register_driver(&spidev_spi_driver);   //注册spi设备驱动spidev_spi_driver  
490     if (status < 0) {  
491         class_destroy(spidev_class);  
492         unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);  
493     }  
494     return status;  
495 }  
496 module_init(spidev_init);   //声明初始化入口  
497   
498 static void __exit spidev_exit(void)            //spidev接口销毁  
499 {  
500     spi_unregister_driver(&spidev_spi_driver);  //注销spi设备驱动spidev_spi_driver  
501     class_destroy(spidev_class);                //注销设备类spidev_class  
502     unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name); //注销字符设备  
503 }  
504 module_exit(spidev_exit);   //声明初始化出口  
505   
506 MODULE_AUTHOR("Andrea Paterniani, ");  
507 MODULE_DESCRIPTION("User mode SPI device interface");  
508 MODULE_LICENSE("GPL");  
509 MODULE_ALIAS("spi:spidev");

 2 spi_test.c

  1 #include   
  2 #include   
  3 #include   
  4 #include   
  5 #include   
  6 #include   
  7 #include   
  8 #include   
  9 #include   
 10   
 11 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))  
 12   
 13 static void pabort(const char *s)  
 14 {  
 15     perror(s);  
 16     abort();  
 17 }  
 18   
 19 static const char *device = "/dev/spidev1.1";  
 20 static uint8_t mode;  
 21 static uint8_t bits = 8;  
 22 static uint32_t speed = 500000;  
 23 static uint16_t delay;  
 24   
 25 static void transfer(int fd)  
 26 {  
 27     int ret;  
 28     uint8_t tx[] = {    //要发送的数据数组  
 29         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  
 30         0x40, 0x00, 0x00, 0x00, 0x00, 0x95,  
 31         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  
 32         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  
 33         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  
 34         0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD,  
 35         0xF0, 0x0D,  
 36     };  
 37     uint8_t rx[ARRAY_SIZE(tx)] = {0, }; //接收的数据数据  
 38     struct spi_ioc_transfer tr = {  //声明并初始化spi_ioc_transfer结构体  
 39         .tx_buf = (unsigned long)tx,  
 40         .rx_buf = (unsigned long)rx,  
 41         .len = ARRAY_SIZE(tx),  
 42         .delay_usecs = delay,  
 43         .speed_hz = speed,  
 44         .bits_per_word = bits,  
 45     };  
 46     //SPI_IOC_MESSAGE(1)的1表示spi_ioc_transfer的数量  
 47     ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);   //ioctl默认操作,传输数据  
 48     if (ret < 1)  
 49         pabort("can't send spi message");  
 50   
 51     for (ret = 0; ret < ARRAY_SIZE(tx); ret++) { //打印接收缓冲区  
 52         if (!(ret % 6))     //6个数据为一簇打印  
 53             puts("");  
 54         printf("%.2X ", rx[ret]);  
 55     }  
 56     puts("");  
 57 }  
 58   
 59 static void print_usage(const char *prog)   //参数错误则打印帮助信息  
 60 {  
 61     printf("Usage: %s [-DsbdlHOLC3]\n", prog);  
 62     puts("  -D --device   device to use (default /dev/spidev1.1)\n"  
 63          "  -s --speed    max speed (Hz)\n"  
 64          "  -d --delay    delay (usec)\n"  
 65          "  -b --bpw      bits per word \n"  
 66          "  -l --loop     loopback\n"  
 67          "  -H --cpha     clock phase\n"  
 68          "  -O --cpol     clock polarity\n"  
 69          "  -L --lsb      least significant bit first\n"  
 70          "  -C --cs-high  chip select active high\n"  
 71          "  -3 --3wire    SI/SO signals shared\n");  
 72     exit(1);  
 73 }  
 74   
 75 static void parse_opts(int argc, char *argv[])  
 76 {  
 77     while (1) {  
 78         static const struct option lopts[] = {  //参数命令表  
 79             { "device",  1, 0, 'D' },  
 80             { "speed",   1, 0, 's' },  
 81             { "delay",   1, 0, 'd' },  
 82             { "bpw",     1, 0, 'b' },  
 83             { "loop",    0, 0, 'l' },  
 84             { "cpha",    0, 0, 'H' },  
 85             { "cpol",    0, 0, 'O' },  
 86             { "lsb",     0, 0, 'L' },  
 87             { "cs-high", 0, 0, 'C' },  
 88             { "3wire",   0, 0, '3' },  
 89             { "no-cs",   0, 0, 'N' },  
 90             { "ready",   0, 0, 'R' },  
 91             { NULL, 0, 0, 0 },  
 92         };  
 93         int c;  
 94   
 95         c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts, NULL);  
 96   
 97         if (c == -1)  
 98             break;  
 99   
100         switch (c) {  
101         case 'D':   //设备名  
102             device = optarg;  
103             break;  
104         case 's':   //速率  
105             speed = atoi(optarg);  
106             break;  
107         case 'd':   //延时时间  
108             delay = atoi(optarg);  
109             break;  
110         case 'b':   //每字含多少位  
111             bits = atoi(optarg);  
112             break;  
113         case 'l':   //回送模式  
114             mode |= SPI_LOOP;  
115             break;  
116         case 'H':   //时钟相位  
117             mode |= SPI_CPHA;  
118             break;  
119         case 'O':   //时钟极性  
120             mode |= SPI_CPOL;  
121             break;  
122         case 'L':   //lsb 最低有效位  
123             mode |= SPI_LSB_FIRST;  
124             break;  
125         case 'C':   //片选高电平  
126             mode |= SPI_CS_HIGH;  
127             break;  
128         case '3':   //3线传输模式  
129             mode |= SPI_3WIRE;  
130             break;  
131         case 'N':   //没片选  
132             mode |= SPI_NO_CS;  
133             break;  
134         case 'R':   //从机拉低电平停止数据传输  
135             mode |= SPI_READY;  
136             break;  
137         default:    //错误的参数  
138             print_usage(argv[0]);  
139             break;  
140         }  
141     }  
142 }  
143   
144 int main(int argc, char *argv[])  
145 {  
146     int ret = 0;  
147     int fd;  
148   
149     parse_opts(argc, argv); //解析传递进来的参数  
150   
151     fd = open(device, O_RDWR);  //打开设备文件  
152     if (fd < 0)  
153         pabort("can't open device");  
154   
155     /* 
156      * spi mode //设置spi设备模式 
157      */  
158     ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);    //写模式  
159     if (ret == -1)  
160         pabort("can't set spi mode");  
161   
162     ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);    //读模式  
163     if (ret == -1)  
164         pabort("can't get spi mode");  
165   
166     /* 
167      * bits per word    //设置每个字含多少位 
168      */  
169     ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);   //写 每个字含多少位  
170     if (ret == -1)  
171         pabort("can't set bits per word");  
172   
173     ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);   //读 每个字含多少位  
174     if (ret == -1)  
175         pabort("can't get bits per word");  
176   
177     /* 
178      * max speed hz     //设置速率 
179      */  
180     ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);   //写速率  
181     if (ret == -1)  
182         pabort("can't set max speed hz");  
183   
184     ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);   //读速率  
185     if (ret == -1)  
186         pabort("can't get max speed hz");  
187     //打印模式,每字多少位和速率信息  
188     printf("spi mode: %d\n", mode);  
189     printf("bits per word: %d\n", bits);  
190     printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);  
191   
192     transfer(fd);   //传输测试  
193   
194     close(fd);  //关闭设备  
195   
196     return ret;  
197 }  

 3  ioctl的命令:

SPI_IOC_RD_MODE     //读 模式  
SPI_IOC_RD_LSB_FIRST    //读 LSB  
SPI_IOC_RD_BITS_PER_WORD    //读 每字多少位  
SPI_IOC_RD_MAX_SPEED_HZ //读 最大速率  
SPI_IOC_WR_MODE     //写 模式  
SPI_IOC_WR_LSB_FIRST    //写 LSB  
SPI_IOC_WR_BITS_PER_WORD    //写 每字多少位  
SPI_IOC_WR_MAX_SPEED_HZ //写 最大速率  
SPI_IOC_MESSAGE(n)      //传输n个数据包

 参考博文:http://dainh.blog.chinaunix.net/uid-26765074-id-3510490.html

posted @ 2020-06-04 22:50  Action_er  阅读(3694)  评论(0编辑  收藏  举报