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
行胜于言,自强不息。