zoukankan      html  css  js  c++  java
  • 代码示例_陀螺仪_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
    ",
     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
    ", 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
    ",
     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
    ", 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)
    ", 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
    ");
     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
    ", 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
    ",rx[0]);    
     714 //    printk("read = %0x
    ",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 ! 
    ");
     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
    ",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
    ",data.temp);
     787         break;
     788     default:
     789         printk(KERN_INFO "invalid cmd");
     790         break;
     791     }
     792     printk("acc:x %d, y:%d, z:%d
    ",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 ! 
    ");    
     829     mysync_write(spidev,PWR_MGMT_1,0x00);    //电源管理,解除休眠    
     830     udelay(1);
     831 
     832 //    printk("kernel  dianyuan  success ! 
    ");    
     833     mysync_write(spidev,SMPLRT_DIV,0x07);    //设置陀螺仪采样率
     834     udelay(1);
     835     
     836 //    printk("kernel  caiyang  success ! 
    ");    
     837     mysync_write(spidev,CONFIG,0x06);        //设置低通滤波频率
     838     udelay(1);
     839     
     840 //    printk("kernel  lvbo  success ! 
    ");    
     841     mysync_write(spidev,GYRO_CONFIG,0x18);    //设置陀螺仪自检
     842     udelay(1);
     843     
     844 //    printk("kernel  zijian  success ! 
    ");    
     845     mysync_write(spidev,ACCEL_CONFIG,0x00);    //设置加速计自检
     846     udelay(1);
     847 
     848 //    printk("kernel  jiasu  success ! 
    ");    
     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 !
    ");
     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!
    ");
     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 !
    ");
     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 !
    ");
     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 !
    ");
     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");

    笔记


  • 相关阅读:
    [Codeup 25482]选美
    [Codeup 25481] swan
    暑假集训D12总结
    [技术]浅谈重载操作符
    2020年寒假第6次学*进度记录
    2020年寒假第5次学*进度记录
    2020年寒假第4次学*进度记录
    “家庭记账本”软件开发(1)
    阅读《梦断代码》随笔(1)
    2020年寒假第三次学*进度记录
  • 原文地址:https://www.cnblogs.com/panda-w/p/11137887.html
Copyright © 2011-2022 走看看