代码示例_陀螺仪_SPI

 

陀螺仪_SPI


 

基于内核spi驱动修改移植

 

   1 /*
   2  * Simple synchronous userspace interface to SPI devices
   3  *
   4  * Copyright (C) 2006 SWAPP
   5  *    Andrea Paterniani <a.paterniani@swapp-eng.it>
   6  * Copyright (C) 2007 David Brownell (simplification, cleanup)
   7  *
   8  * This program is free software; you can redistribute it and/or modify
   9  * it under the terms of the GNU General Public License as published by
  10  * the Free Software Foundation; either version 2 of the License, or
  11  * (at your option) any later version.
  12  *
  13  * This program is distributed in the hope that it will be useful,
  14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16  * GNU General Public License for more details.
  17  *
  18  * You should have received a copy of the GNU General Public License
  19  * along with this program; if not, write to the Free Software
  20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21  */
  22 
  23 #include <linux/init.h>
  24 #include <linux/module.h>
  25 #include <linux/ioctl.h>
  26 #include <linux/fs.h>
  27 #include <linux/device.h>
  28 #include <linux/err.h>
  29 #include <linux/list.h>
  30 #include <linux/errno.h>
  31 #include <linux/mutex.h>
  32 #include <linux/slab.h>
  33 #include <linux/compat.h>
  34 
  35 #include <linux/spi/spi.h>
  36 #include <linux/spi/spidev.h>
  37 #include <asm/uaccess.h>
  38 #include <linux/delay.h>
  39 
  40 //struct spidev_data    spidev0;
  41 
  42 
  43 /*********************************    mpu6500    *********************************************/
  44 
  45 
  46 #define MPU6500_MAGIC 'K'
  47 
  48 //用于读取数据的存储
  49 
  50 union mpu6500_data
  51 {
  52     struct {
  53         short x;
  54         short y;
  55         short z;
  56     }accel;
  57     struct {
  58         short x;
  59         short y;
  60         short z;
  61     }gyro;
  62     unsigned short temp;
  63 };
  64 
  65 
  66 
  67 #define GET_ACCEL _IOR(MPU6500_MAGIC, 0, union mpu6500_data)
  68 #define GET_GYRO  _IOR(MPU6500_MAGIC, 1, union mpu6500_data) 
  69 #define GET_TEMP  _IOR(MPU6500_MAGIC, 2, union mpu6500_data)
  70 
  71 
  72 #define SMPLRT_DIV       0x19   //陀螺仪采样率,典型值:0x07(125Hz)   
  73 #define CONFIG           0x1A   //低通滤波频率,典型值:0x06(5Hz)
  74 #define GYRO_CONFIG      0x1B   //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
  75 #define ACCEL_CONFIG     0x1C   //加速计自检、测量范围及高通滤波,典型值:0x18(不自检,2G,5Hz)
  76 
  77 
  78 //    注册59到64 -加速度计测量值
  79 #define ACCEL_XOUT_H   0x3B        //加速度计x轴数据的高字节
  80 #define ACCEL_XOUT_L   0x3C        //加速度计x轴数据的低字节
  81 #define ACCEL_YOUT_H   0x3D        //加速度计y轴数据的高字节
  82 #define ACCEL_YOUT_L   0x3E        //加速度计y轴数据的低字节
  83 #define ACCEL_ZOUT_H   0x3F        //加速度计z轴数据的高字节
  84 #define ACCEL_ZOUT_L   0x40        //加速度计z轴数据的低字节
  85 
  86 
  87 //    寄存器65和66 -温度测量
  88 #define TEMP_OUT_H     0x41        //温度传感器输出的高字节
  89 #define TEMP_OUT_L     0x42        //温度传感器输出的低字节
  90 
  91 
  92 //    注册67至72 -陀螺仪测量
  93 #define GYRO_XOUT_H    0x43        //高字节的x轴陀螺仪输出
  94 #define GYRO_XOUT_L    0x44        //低字节的x轴陀螺仪输出
  95 #define GYRO_YOUT_H    0x45        //高字节的y轴陀螺仪输出
  96 #define GYRO_YOUT_L    0x46        //低字节的y轴陀螺仪输出
  97 #define GYRO_ZOUT_H    0x47        //高字节的z轴陀螺仪输出
  98 #define GYRO_ZOUT_L    0x48        //低字节的z轴陀螺仪输出
  99 
 100 
 101 #define PWR_MGMT_1      0x6B    //电源管理,典型值:0x00(正常启用)      
 102 #define WHO_AM_I        0x75    //IIC地址寄存器(默认数值0x68,只读)
 103 #define SlaveAddress    0x68    //MPU6050-I2C地址寄存器
 104 
 105 
 106 /*********************************    mpu6500    *********************************************/
 107 
 108 
 109 
 110 /*
 111  * This supports access to SPI devices using normal userspace I/O calls.
 112  * Note that while traditional UNIX/POSIX I/O semantics are half duplex,
 113  * and often mask message boundaries, full SPI support requires full duplex
 114  * transfers.  There are several kinds of internal message boundaries to
 115  * handle chipselect management and other protocol options.
 116  *
 117  * SPI has a character major number assigned.  We allocate minor numbers
 118  * dynamically using a bitmask.  You must use hotplug tools, such as udev
 119  * (or mdev with busybox) to create and destroy the /dev/spidevB.C device
 120  * nodes, since there is no fixed association of minor numbers with any
 121  * particular SPI bus or device.
 122  */
 123 #define SPIDEV_MAJOR            153    /* assigned */
 124 #define N_SPI_MINORS            32    /* ... up to 256 */
 125 
 126 static DECLARE_BITMAP(minors, N_SPI_MINORS);
 127 
 128 
 129 /* Bit masks for spi_device.mode management.  Note that incorrect
 130  * settings for some settings can cause *lots* of trouble for other
 131  * devices on a shared bus:
 132  *
 133  *  - CS_HIGH ... this device will be active when it shouldn't be
 134  *  - 3WIRE ... when active, it won't behave as it should
 135  *  - NO_CS ... there will be no explicit message boundaries; this
 136  *    is completely incompatible with the shared bus model
 137  *  - READY ... transfers may proceed when they shouldn't.
 138  *
 139  * REVISIT should changing those flags be privileged?
 140  */
 141 #define SPI_MODE_MASK        (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \
 142                 | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \
 143                 | SPI_NO_CS | SPI_READY)
 144 
 145 struct spidev_data {
 146     dev_t            devt;
 147     spinlock_t        spi_lock;
 148     struct spi_device    *spi;
 149     struct list_head    device_entry;
 150 
 151     /* buffer is NULL unless this device is open (users > 0) */
 152     struct mutex        buf_lock;
 153     unsigned        users;
 154     u8            *buffer;
 155 };
 156 
 157 static LIST_HEAD(device_list);
 158 static DEFINE_MUTEX(device_list_lock);
 159 
 160 static unsigned bufsiz = 4096;
 161 module_param(bufsiz, uint, S_IRUGO);
 162 MODULE_PARM_DESC(bufsiz, "data bytes in biggest supported SPI message");
 163 
 164 /*-------------------------------------------------------------------------*/
 165 
 166 /*
 167  * We can't use the standard synchronous wrappers for file I/O; we
 168  * need to protect against async removal of the underlying spi_device.
 169  */
 170  
 171  
 172 //驱动数据sync发送
 173 static void spidev_complete(void *arg)
 174 {
 175     complete(arg);
 176 }
 177 
 178 static ssize_t
 179 spidev_sync(struct spidev_data *spidev, struct spi_message *message)
 180 {
 181     DECLARE_COMPLETION_ONSTACK(done);
 182     int status;
 183 
 184     message->complete = spidev_complete;
 185     message->context = &done;
 186 
 187     spin_lock_irq(&spidev->spi_lock);
 188     if (spidev->spi == NULL)
 189         status = -ESHUTDOWN;
 190     else
 191         status = spi_async(spidev->spi, message);
 192     spin_unlock_irq(&spidev->spi_lock);
 193 
 194     if (status == 0) {
 195         wait_for_completion(&done);
 196         status = message->status;
 197         if (status == 0)
 198             status = message->actual_length;
 199     }
 200     return status;
 201 }
 202 
 203 
 204 //驱动写操作
 205 static inline ssize_t
 206 spidev_sync_write(struct spidev_data *spidev, size_t len)
 207 {
 208     struct spi_transfer    t = {
 209             .tx_buf        = spidev->buffer,
 210             .len        = len,
 211         };
 212     struct spi_message    m;
 213 
 214     spi_message_init(&m);
 215     spi_message_add_tail(&t, &m);
 216     return spidev_sync(spidev, &m);
 217 }
 218 
 219 //驱动读操作
 220 static inline ssize_t
 221 spidev_sync_read(struct spidev_data *spidev, size_t len)
 222 {
 223     struct spi_transfer    t = {
 224             .rx_buf        = spidev->buffer,
 225             .len        = len,
 226         };
 227     struct spi_message    m;
 228 
 229     spi_message_init(&m);
 230     spi_message_add_tail(&t, &m);
 231     return spidev_sync(spidev, &m);
 232 }
 233 
 234 
 235 /*-------------------------------------------------------------------------*/
 236 
 237 
 238 /* Read-only message with current device setup */
 239 
 240 //驱动读接口
 241 static ssize_t
 242 spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
 243 {
 244     struct spidev_data    *spidev;
 245     ssize_t            status = 0;
 246 
 247     /* chipselect only toggles at start or end of operation */
 248     if (count > bufsiz)
 249         return -EMSGSIZE;
 250 
 251     spidev = filp->private_data;
 252 
 253     mutex_lock(&spidev->buf_lock);
 254     status = spidev_sync_read(spidev, count);
 255     if (status > 0) {
 256         unsigned long    missing;
 257 
 258         missing = copy_to_user(buf, spidev->buffer, status);
 259         if (missing == status)
 260             status = -EFAULT;
 261         else
 262             status = status - missing;
 263     }
 264     mutex_unlock(&spidev->buf_lock);
 265 
 266     return status;
 267 }
 268 
 269 
 270 /* Write-only message with current device setup */
 271 
 272 //驱动写接口
 273 static ssize_t
 274 spidev_write(struct file *filp, const char __user *buf,
 275         size_t count, loff_t *f_pos)
 276 {
 277     struct spidev_data    *spidev;
 278     ssize_t            status = 0;
 279     unsigned long        missing;
 280 
 281     /* chipselect only toggles at start or end of operation */
 282     if (count > bufsiz)
 283         return -EMSGSIZE;
 284 
 285     spidev = filp->private_data;
 286 
 287     mutex_lock(&spidev->buf_lock);
 288     missing = copy_from_user(spidev->buffer, buf, count);
 289     if (missing == 0) {
 290         status = spidev_sync_write(spidev, count);
 291     } else
 292         status = -EFAULT;
 293     mutex_unlock(&spidev->buf_lock);
 294 
 295     return status;
 296 }
 297 
 298 
 299 //驱动信息队列message
 300 static int spidev_message(struct spidev_data *spidev,
 301         struct spi_ioc_transfer *u_xfers, unsigned n_xfers)
 302 {
 303     struct spi_message    msg;
 304     struct spi_transfer    *k_xfers;
 305     struct spi_transfer    *k_tmp;
 306     struct spi_ioc_transfer *u_tmp;
 307     unsigned        n, total;
 308     u8            *buf;
 309     int            status = -EFAULT;
 310 
 311     spi_message_init(&msg);
 312     k_xfers = kcalloc(n_xfers, sizeof(*k_tmp), GFP_KERNEL);
 313     if (k_xfers == NULL)
 314         return -ENOMEM;
 315 
 316     /* Construct spi_message, copying any tx data to bounce buffer.
 317      * We walk the array of user-provided transfers, using each one
 318      * to initialize a kernel version of the same transfer.
 319      */
 320     buf = spidev->buffer;
 321     total = 0;
 322     for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers;
 323             n;
 324             n--, k_tmp++, u_tmp++) {
 325         k_tmp->len = u_tmp->len;
 326 
 327         total += k_tmp->len;
 328         if (total > bufsiz) {
 329             status = -EMSGSIZE;
 330             goto done;
 331         }
 332 
 333         if (u_tmp->rx_buf) {
 334             k_tmp->rx_buf = buf;
 335             if (!access_ok(VERIFY_WRITE, (u8 __user *)
 336                         (uintptr_t) u_tmp->rx_buf,
 337                         u_tmp->len))
 338                 goto done;
 339         }
 340         if (u_tmp->tx_buf) {
 341             k_tmp->tx_buf = buf;
 342             if (copy_from_user(buf, (const u8 __user *)
 343                         (uintptr_t) u_tmp->tx_buf,
 344                     u_tmp->len))
 345                 goto done;
 346         }
 347         buf += k_tmp->len;
 348 
 349         k_tmp->cs_change = !!u_tmp->cs_change;
 350         k_tmp->bits_per_word = u_tmp->bits_per_word;
 351         k_tmp->delay_usecs = u_tmp->delay_usecs;
 352         k_tmp->speed_hz = u_tmp->speed_hz;
 353 #ifdef VERBOSE
 354         dev_dbg(&spidev->spi->dev,
 355             "  xfer len %zd %s%s%s%dbits %u usec %uHz\n",
 356             u_tmp->len,
 357             u_tmp->rx_buf ? "rx " : "",
 358             u_tmp->tx_buf ? "tx " : "",
 359             u_tmp->cs_change ? "cs " : "",
 360             u_tmp->bits_per_word ? : spidev->spi->bits_per_word,
 361             u_tmp->delay_usecs,
 362             u_tmp->speed_hz ? : spidev->spi->max_speed_hz);
 363 #endif
 364         spi_message_add_tail(k_tmp, &msg);
 365     }
 366 
 367     status = spidev_sync(spidev, &msg);
 368     if (status < 0)
 369         goto done;
 370 
 371     /* copy any rx data out of bounce buffer */
 372     buf = spidev->buffer;
 373     for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) {
 374         if (u_tmp->rx_buf) {
 375             if (__copy_to_user((u8 __user *)
 376                     (uintptr_t) u_tmp->rx_buf, buf,
 377                     u_tmp->len)) {
 378                 status = -EFAULT;
 379                 goto done;
 380             }
 381         }
 382         buf += u_tmp->len;
 383     }
 384     status = total;
 385 
 386 done:
 387     kfree(k_xfers);
 388     return status;
 389 }
 390 
 391 #if 0
 392 
 393 //驱动ioctl接口
 394 static long
 395 spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 396 {
 397     int            err = 0;
 398     int            retval = 0;
 399     struct spidev_data    *spidev;
 400     struct spi_device    *spi;
 401     u32            tmp;
 402     unsigned        n_ioc;
 403     struct spi_ioc_transfer    *ioc;
 404 
 405     /* Check type and command number */
 406     if (_IOC_TYPE(cmd) != SPI_IOC_MAGIC)
 407         return -ENOTTY;
 408 
 409     /* Check access direction once here; don't repeat below.
 410      * IOC_DIR is from the user perspective, while access_ok is
 411      * from the kernel perspective; so they look reversed.
 412      */
 413     if (_IOC_DIR(cmd) & _IOC_READ)
 414         err = !access_ok(VERIFY_WRITE,
 415                 (void __user *)arg, _IOC_SIZE(cmd));
 416     if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE)
 417         err = !access_ok(VERIFY_READ,
 418                 (void __user *)arg, _IOC_SIZE(cmd));
 419     if (err)
 420         return -EFAULT;
 421 
 422     /* guard against device removal before, or while,
 423      * we issue this ioctl.
 424      */
 425     spidev = filp->private_data;
 426     spin_lock_irq(&spidev->spi_lock);
 427     spi = spi_dev_get(spidev->spi);
 428     spin_unlock_irq(&spidev->spi_lock);
 429 
 430     if (spi == NULL)
 431         return -ESHUTDOWN;
 432 
 433     /* use the buffer lock here for triple duty:
 434      *  - prevent I/O (from us) so calling spi_setup() is safe;
 435      *  - prevent concurrent SPI_IOC_WR_* from morphing
 436      *    data fields while SPI_IOC_RD_* reads them;
 437      *  - SPI_IOC_MESSAGE needs the buffer locked "normally".
 438      */
 439     mutex_lock(&spidev->buf_lock);
 440 
 441     switch (cmd) {
 442     /* read requests */
 443     case SPI_IOC_RD_MODE:
 444         retval = __put_user(spi->mode & SPI_MODE_MASK,
 445                     (__u8 __user *)arg);
 446         break;
 447     case SPI_IOC_RD_LSB_FIRST:
 448         retval = __put_user((spi->mode & SPI_LSB_FIRST) ?  1 : 0,
 449                     (__u8 __user *)arg);
 450         break;
 451     case SPI_IOC_RD_BITS_PER_WORD:
 452         retval = __put_user(spi->bits_per_word, (__u8 __user *)arg);
 453         break;
 454     case SPI_IOC_RD_MAX_SPEED_HZ:
 455         retval = __put_user(spi->max_speed_hz, (__u32 __user *)arg);
 456         break;
 457 
 458     /* write requests */
 459     case SPI_IOC_WR_MODE:
 460         retval = __get_user(tmp, (u8 __user *)arg);
 461         if (retval == 0) {
 462             u8    save = spi->mode;
 463 
 464             if (tmp & ~SPI_MODE_MASK) {
 465                 retval = -EINVAL;
 466                 break;
 467             }
 468 
 469             tmp |= spi->mode & ~SPI_MODE_MASK;
 470             spi->mode = (u8)tmp;
 471             retval = spi_setup(spi);
 472             if (retval < 0)
 473                 spi->mode = save;
 474             else
 475                 dev_dbg(&spi->dev, "spi mode %02x\n", tmp);
 476         }
 477         break;
 478     case SPI_IOC_WR_LSB_FIRST:
 479         retval = __get_user(tmp, (__u8 __user *)arg);
 480         if (retval == 0) {
 481             u8    save = spi->mode;
 482 
 483             if (tmp)
 484                 spi->mode |= SPI_LSB_FIRST;
 485             else
 486                 spi->mode &= ~SPI_LSB_FIRST;
 487             retval = spi_setup(spi);
 488             if (retval < 0)
 489                 spi->mode = save;
 490             else
 491                 dev_dbg(&spi->dev, "%csb first\n",
 492                         tmp ? 'l' : 'm');
 493         }
 494         break;
 495     case SPI_IOC_WR_BITS_PER_WORD:
 496         retval = __get_user(tmp, (__u8 __user *)arg);
 497         if (retval == 0) {
 498             u8    save = spi->bits_per_word;
 499 
 500             spi->bits_per_word = tmp;
 501             retval = spi_setup(spi);
 502             if (retval < 0)
 503                 spi->bits_per_word = save;
 504             else
 505                 dev_dbg(&spi->dev, "%d bits per word\n", tmp);
 506         }
 507         break;
 508     case SPI_IOC_WR_MAX_SPEED_HZ:
 509         retval = __get_user(tmp, (__u32 __user *)arg);
 510         if (retval == 0) {
 511             u32    save = spi->max_speed_hz;
 512 
 513             spi->max_speed_hz = tmp;
 514             retval = spi_setup(spi);
 515             if (retval < 0)
 516                 spi->max_speed_hz = save;
 517             else
 518                 dev_dbg(&spi->dev, "%d Hz (max)\n", tmp);
 519         }
 520         break;
 521 
 522     default:
 523         /* segmented and/or full-duplex I/O request */
 524         if (_IOC_NR(cmd) != _IOC_NR(SPI_IOC_MESSAGE(0))
 525                 || _IOC_DIR(cmd) != _IOC_WRITE) {
 526             retval = -ENOTTY;
 527             break;
 528         }
 529 
 530         tmp = _IOC_SIZE(cmd);
 531         if ((tmp % sizeof(struct spi_ioc_transfer)) != 0) {
 532             retval = -EINVAL;
 533             break;
 534         }
 535         n_ioc = tmp / sizeof(struct spi_ioc_transfer);
 536         if (n_ioc == 0)
 537             break;
 538 
 539         /* copy into scratch area */
 540         ioc = kmalloc(tmp, GFP_KERNEL);
 541         if (!ioc) {
 542             retval = -ENOMEM;
 543             break;
 544         }
 545         if (__copy_from_user(ioc, (void __user *)arg, tmp)) {
 546             kfree(ioc);
 547             retval = -EFAULT;
 548             break;
 549         }
 550 
 551         /* translate to spi_message, execute */
 552         retval = spidev_message(spidev, ioc, n_ioc);
 553         kfree(ioc);
 554         break;
 555     }
 556 
 557     mutex_unlock(&spidev->buf_lock);
 558     spi_dev_put(spi);
 559     return retval;
 560 }
 561 
 562 #endif 
 563 
 564 #ifdef CONFIG_COMPAT
 565 //static long
 566 //spidev_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 567 //{
 568 //    return spidev_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
 569 //}
 570 #else
 571 #define spidev_compat_ioctl NULL
 572 #endif /* CONFIG_COMPAT */
 573 
 574 
 575 //驱动open接口
 576 static int spidev_open(struct inode *inode, struct file *filp)
 577 {
 578     struct spidev_data    *spidev;
 579     int            status = -ENXIO;
 580 
 581     mutex_lock(&device_list_lock);
 582 
 583     list_for_each_entry(spidev, &device_list, device_entry) {
 584         if (spidev->devt == inode->i_rdev) {
 585             status = 0;
 586             break;
 587         }
 588     }
 589     if (status == 0) {
 590         if (!spidev->buffer) {
 591             spidev->buffer = kmalloc(bufsiz, GFP_KERNEL);
 592             if (!spidev->buffer) {
 593                 dev_dbg(&spidev->spi->dev, "open/ENOMEM\n");
 594                 status = -ENOMEM;
 595             }
 596         }
 597         if (status == 0) {
 598             spidev->users++;
 599             filp->private_data = spidev;
 600             nonseekable_open(inode, filp);
 601         }
 602     } else
 603         pr_debug("spidev: nothing for minor %d\n", iminor(inode));
 604 
 605     mutex_unlock(&device_list_lock);
 606     return status;
 607 }
 608 
 609 
 610 // 驱动release接口
 611 static int spidev_release(struct inode *inode, struct file *filp)
 612 {
 613     struct spidev_data    *spidev;
 614     int            status = 0;
 615 
 616     mutex_lock(&device_list_lock);
 617     spidev = filp->private_data;
 618     filp->private_data = NULL;
 619 
 620     /* last close? */
 621     spidev->users--;
 622     if (!spidev->users) {
 623         int        dofree;
 624 
 625         kfree(spidev->buffer);
 626         spidev->buffer = NULL;
 627 
 628         /* ... after we unbound from the underlying device? */
 629         spin_lock_irq(&spidev->spi_lock);
 630         dofree = (spidev->spi == NULL);
 631         spin_unlock_irq(&spidev->spi_lock);
 632 
 633         if (dofree)
 634             kfree(spidev);
 635     }
 636     mutex_unlock(&device_list_lock);
 637 
 638     return status;
 639 }
 640 
 641 
 642 /*-------------------------------------------------------------------------*/
 643 
 644 /* The main reason to have this class is to make mdev/udev create the
 645  * /dev/spidevB.C character device nodes exposing our userspace API.
 646  * It also simplifies memory management.
 647  */
 648 
 649 static struct class *spidev_class;
 650 
 651 /*-------------------------------------------------------------------------*/
 652 
 653 
 654 
 655 /*******************************    device  inint    ***********************************/
 656  
 657  
 658  
 659 /*****封装一个写操作*****/ 
 660 static inline ssize_t mysync_write(struct spidev_data *spidev, unsigned char addr, unsigned char tx_buff)  
 661 { 
 662 
 663     u8  tx[2] ;
 664         
 665     tx[0] = addr ;
 666     tx[1] =tx_buff;
 667         
 668     struct spi_transfer    t = {
 669         .tx_buf        = tx,
 670         .len        = 2,
 671         
 672     };
 673     
 674     struct spi_message    m;
 675     
 676     spi_message_init(&m);
 677     spi_message_add_tail(&t, &m);
 678     
 679     return spidev_sync(spidev, &m);    
 680 
 681 }
 682 
 683 
 684 
 685 /*****封装一个读操作*****/ 
 686 static inline ssize_t    mysync_read(struct spidev_data *spidev, unsigned char addr)
 687 {
 688     
 689     // 先发一个地址  读模式
 690     u8 tx[2] ;     
 691     tx[0] =  addr | 0x80;  // 先写寄存器地址   读模式
 692     tx[1] =  0x88;           // 再写数据    
 693     u8 rx[2] = {0};        // 再读出数据
 694                     
 695     struct spi_transfer    t[2] =  {    
 696     [0] = {
 697         .tx_buf        = tx,  
 698         .rx_buf        = rx,
 699         .len        = 2,
 700         },
 701 
 702     [1] = {
 703         .rx_buf        = rx,
 704         .len        = 2,
 705         }, 
 706     };
 707     
 708     struct spi_message    m;
 709     spi_message_init(&m);
 710     spi_message_add_tail(&t, &m);
 711     spidev_sync(spidev, &m);    
 712 
 713 //    printk("read = %0x\n",rx[0]);    
 714 //    printk("read = %0x\n",rx[1]);
 715   
 716     return  rx[1];
 717     
 718 }
 719 
 720 
 721 /*
 722 
 723 static ssize_t
 724 spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
 725 {
 726 
 727 
 728 
 729 }
 730 
 731 */
 732 
 733 
 734 /*****自己封装一个ioctl接口*****/
 735 static long dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 736 {
 737         
 738     printk("kernel  ioctl  success ! \n");
 739         
 740     struct spidev_data    *spidev;
 741     struct spi_device    *spi;
 742 
 743     spidev = filp->private_data;
 744     spin_lock_irq(&spidev->spi_lock);
 745     spi = spi_dev_get(spidev->spi);
 746     spin_unlock_irq(&spidev->spi_lock);
 747     
 748 //    struct spidev_data *spidev = NULL;
 749     int res = 0;
 750     union mpu6500_data data = {{0}};
 751     switch(cmd){
 752     case GET_ACCEL:
 753         data.accel.x = mysync_read(spidev,ACCEL_XOUT_L);
 754         udelay(1);
 755         data.accel.x|= mysync_read(spidev,ACCEL_XOUT_H)<<8;
 756         udelay(1);
 757         data.accel.y = mysync_read(spidev,ACCEL_YOUT_L);
 758         udelay(1);
 759         data.accel.y|= mysync_read(spidev,ACCEL_YOUT_H)<<8;
 760         udelay(1);
 761         data.accel.z = mysync_read(spidev,ACCEL_ZOUT_L);
 762         udelay(1);
 763         data.accel.z|= mysync_read(spidev,ACCEL_ZOUT_H)<<8;
 764         udelay(1);
 765         break;
 766     case GET_GYRO:
 767         data.gyro.x = mysync_read(spidev,GYRO_XOUT_L);
 768         udelay(1);
 769         data.gyro.x|= mysync_read(spidev,GYRO_XOUT_H)<<8;
 770         udelay(1);
 771         data.gyro.y = mysync_read(spidev,GYRO_YOUT_L);
 772         udelay(1);
 773         data.gyro.y|= mysync_read(spidev,GYRO_YOUT_H)<<8;
 774         udelay(1);
 775         data.gyro.z = mysync_read(spidev,GYRO_ZOUT_L);
 776         udelay(1);
 777         data.gyro.z|= mysync_read(spidev,GYRO_ZOUT_H)<<8;
 778         udelay(1);
 779         printk("gyro:x %d, y:%d, z:%d\n",data.gyro.x,data.gyro.y,data.gyro.z);
 780         break;
 781     case GET_TEMP:
 782         data.temp = mysync_read(spidev,TEMP_OUT_L);
 783         udelay(1);
 784         data.temp|= mysync_read(spidev,TEMP_OUT_H)<<8;
 785         udelay(1);
 786         printk("temp: %d\n",data.temp);
 787         break;
 788     default:
 789         printk(KERN_INFO "invalid cmd");
 790         break;
 791     }
 792     printk("acc:x %d, y:%d, z:%d\n",data.accel.x,data.accel.y,data.accel.z);
 793     
 794     res = copy_to_user((void *)arg,&data,sizeof(data));
 795     
 796     return sizeof(data);
 797 }
 798 
 799 
 800 //驱动实现FOPS
 801 static const struct file_operations spidev_fops = {
 802     .owner =    THIS_MODULE,
 803     /* REVISIT switch to aio primitives, so that userspace
 804      * gets more complete API coverage.  It'll simplify things
 805      * too, except for the locking.
 806      */
 807     .write =    spidev_write,
 808     .read =        spi_read,
 809     
 810 //  .read =        spidev_read,
 811 //  .unlocked_ioctl = spidev_ioctl,
 812     
 813     .unlocked_ioctl = dev_ioctl, 
 814     
 815 //    .compat_ioctl = spidev_compat_ioctl,
 816     .open =        spidev_open,
 817     .release =    spidev_release,
 818     .llseek =    no_llseek,
 819 };
 820 
 821 
 822 /*****硬件初始化*****/
 823 void  mpu6500_init(struct spidev_data *spidev)
 824 {
 825     
 826     udelay(1);
 827 
 828 //    printk("kernel  mpu6500_init  success ! \n");    
 829     mysync_write(spidev,PWR_MGMT_1,0x00);    //电源管理,解除休眠    
 830     udelay(1);
 831 
 832 //    printk("kernel  dianyuan  success ! \n");    
 833     mysync_write(spidev,SMPLRT_DIV,0x07);    //设置陀螺仪采样率
 834     udelay(1);
 835     
 836 //    printk("kernel  caiyang  success ! \n");    
 837     mysync_write(spidev,CONFIG,0x06);        //设置低通滤波频率
 838     udelay(1);
 839     
 840 //    printk("kernel  lvbo  success ! \n");    
 841     mysync_write(spidev,GYRO_CONFIG,0x18);    //设置陀螺仪自检
 842     udelay(1);
 843     
 844 //    printk("kernel  zijian  success ! \n");    
 845     mysync_write(spidev,ACCEL_CONFIG,0x00);    //设置加速计自检
 846     udelay(1);
 847 
 848 //    printk("kernel  jiasu  success ! \n");    
 849     
 850     
 851     mysync_read(spidev,ACCEL_XOUT_L);
 852     mysync_read(spidev,ACCEL_XOUT_H);
 853 
 854         
 855     return 0;    
 856 }
 857 
 858 
 859 /*******************************    device  inint    ***********************************/
 860 
 861 
 862 static int  spidev_probe(struct spi_device *spi)
 863 {
 864     
 865     printk("probe ok !\n");
 866     
 867     struct spidev_data    *spidev;
 868     int            status;
 869     unsigned long        minor;
 870 
 871     /* Allocate driver data */
 872     spidev = kzalloc(sizeof(*spidev), GFP_KERNEL);
 873     if (!spidev)
 874         return -ENOMEM;
 875 
 876     /* Initialize the driver data */
 877     
 878     
 879     spidev->spi = spi;
 880     spin_lock_init(&spidev->spi_lock);
 881     mutex_init(&spidev->buf_lock);
 882 
 883     INIT_LIST_HEAD(&spidev->device_entry);
 884 
 885     /* If we can allocate a minor number, hook up this device.
 886      * Reusing minors is fine so long as udev or mdev is working.
 887      */
 888     mutex_lock(&device_list_lock);
 889     minor = find_first_zero_bit(minors, N_SPI_MINORS);
 890     if (minor < N_SPI_MINORS) {
 891         struct device *dev;
 892 
 893         spidev->devt = MKDEV(SPIDEV_MAJOR, minor);
 894         dev = device_create(spidev_class, &spi->dev, spidev->devt,
 895                     spidev, "spidev%d.%d",
 896                     spi->master->bus_num, spi->chip_select);
 897         status = IS_ERR(dev) ? PTR_ERR(dev) : 0;
 898     } else {
 899         dev_dbg(&spi->dev, "no minor number available!\n");
 900         status = -ENODEV;
 901     }
 902     if (status == 0) {
 903         set_bit(minor, minors);
 904         list_add(&spidev->device_entry, &device_list);
 905     }
 906     mutex_unlock(&device_list_lock);
 907 
 908     if (status == 0)
 909         spi_set_drvdata(spi, spidev);
 910     else
 911         kfree(spidev);
 912 
 913 
 914 /*****硬件初始化*****/
 915     mpu6500_init(spidev);
 916 
 917 
 918     return status;
 919 }
 920 
 921 static int  spidev_remove(struct spi_device *spi)
 922 {
 923     struct spidev_data    *spidev = spi_get_drvdata(spi);
 924 
 925     /* make sure ops on existing fds can abort cleanly */
 926     spin_lock_irq(&spidev->spi_lock);
 927     spidev->spi = NULL;
 928     spi_set_drvdata(spi, NULL);
 929     spin_unlock_irq(&spidev->spi_lock);
 930 
 931     /* prevent new opens */
 932     mutex_lock(&device_list_lock);
 933     list_del(&spidev->device_entry);
 934     device_destroy(spidev_class, spidev->devt);
 935     clear_bit(MINOR(spidev->devt), minors);
 936     if (spidev->users == 0)
 937         kfree(spidev);
 938     mutex_unlock(&device_list_lock);
 939 
 940     printk("remove  ok !\n");
 941 
 942     return 0;
 943 }
 944 
 945 static struct spi_driver spidev_spi_driver = {
 946     .driver = {
 947         .name =        "spidev",
 948         .owner =    THIS_MODULE,
 949     },
 950     .probe =    spidev_probe,
 951     .remove =    spidev_remove,
 952 
 953     /* NOTE:  suspend/resume methods are not necessary here.
 954      * We don't do anything except pass the requests to/from
 955      * the underlying controller.  The refrigerator handles
 956      * most issues; the controller driver handles the rest.
 957      */
 958 };
 959 
 960 /*-------------------------------------------------------------------------*/
 961 
 962 static int __init spidev_init(void)
 963 {
 964     
 965     printk("init ok !\n");
 966     
 967     int status;
 968 
 969     /* Claim our 256 reserved device numbers.  Then register a class
 970      * that will key udev/mdev to add/remove /dev nodes.  Last, register
 971      * the driver which manages those device numbers.
 972      */
 973     BUILD_BUG_ON(N_SPI_MINORS > 256);
 974     status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops);
 975     if (status < 0)
 976         return status;
 977 
 978     spidev_class = class_create(THIS_MODULE, "spidev");
 979     if (IS_ERR(spidev_class)) {
 980         unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
 981         return PTR_ERR(spidev_class);
 982     }
 983 
 984     status = spi_register_driver(&spidev_spi_driver);
 985     if (status < 0) {
 986         class_destroy(spidev_class);
 987         unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
 988     }
 989     return status;
 990 }
 991 module_init(spidev_init);
 992 
 993 static void __exit spidev_exit(void)
 994 {
 995     
 996     printk("exit ok !\n");
 997     
 998     spi_unregister_driver(&spidev_spi_driver);
 999     class_destroy(spidev_class);
1000     unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
1001 }
1002 module_exit(spidev_exit);
1003 
1004 MODULE_AUTHOR("Andrea Paterniani, <a.paterniani@swapp-eng.it>");
1005 MODULE_DESCRIPTION("User mode SPI device interface");
1006 MODULE_LICENSE("GPL");
1007 MODULE_ALIAS("spi:spidev");

 

 

 

 

笔记


 

posted @ 2019-09-05 10:14  panda_w  阅读(1621)  评论(0编辑  收藏  举报