和菜鸟一起学linux总线驱动之初识spi驱动数据传输流程【转】

转自:http://blog.csdn.net/eastmoon502136/article/details/7921846

对于SPI的一些结构体都有所了解之后呢,那么再去瞧瞧SPI的那些长见的操作的函数了。

首先看一下本人画的比较挫的数据流了,仅供参考,如有不对,不吝赐教

 

 

 

接下来看看各个函数吧还是:

 

SPI write

 

[html] view plain copy

 

  1. /**  
  2.  * spi_write - SPI synchronous write  
  3.  * @spi: device to which data will be written  
  4.  * @buf: data buffer  
  5.  * @len: data buffer size  
  6.  * Context: can sleep  
  7.  *  
  8.  * This writes the buffer and returns zero or a negative error code.  
  9.  * Callable only from contexts that can sleep.  
  10.  */  
  11. static inline int  
  12. spi_write(struct spi_device *spi, const void *buf, size_t len)  
  13. {  
  14.        struct spi_transfer   t = {  
  15.                      .tx_buf           = buf,  
  16.                      .len         = len,  
  17.               };  
  18.        struct spi_message  m;  
  19.    
  20.        spi_message_init(&m);  
  21.        spi_message_add_tail(&t, &m);  
  22.        return spi_sync(spi, &m);  
  23.   
  24. }  

SPI发送函数,数据放在buf中,然后把要发送的数据放在工作队列中

 

SPI  read

 

[html] view plain copy

 

  1. /**  
  2.  * spi_read - SPI synchronous read  
  3.  * @spi: device from which data will be read  
  4.  * @buf: data buffer  
  5.  * @len: data buffer size  
  6.  * Context: can sleep  
  7.  *  
  8.  * This reads the buffer and returns zero or a negative error code.  
  9.  * Callable only from contexts that can sleep.  
  10.  */  
  11. static inline int  
  12. spi_read(struct spi_device *spi, void *buf, size_t len)  
  13. {  
  14.        struct spi_transfer   t = {  
  15.                      .rx_buf           = buf,  
  16.                      .len         = len,  
  17.               };  
  18.        struct spi_message  m;  
  19.   
  20.        spi_message_init(&m);  
  21.        spi_message_add_tail(&t, &m);  
  22.        return spi_sync(spi, &m);  
  23. }  

SPI接收函数,数据放在buf中,然后把要发送的数据放在工作队列中,发送出去

 

SPI write 8 bits read 8 bits

 

[html] view plain copy

 

  1. /* this copies txbuf and rxbuf data; for small transfers only! */  
  2. extern int spi_write_then_read(struct spi_device *spi,  
  3.               const void *txbuf, unsigned n_tx,  
  4.               void *rxbuf, unsigned n_rx);  
  5. /**  
  6.  * spi_w8r8 - SPI synchronous 8 bit write followed by 8 bit read  
  7.  * @spi: device with which data will be exchanged  
  8.  * @cmd: command to be written before data is read back  
  9.  * Context: can sleep  
  10.  *  
  11.  * This returns the (unsigned) eight bit number returned by the  
  12.  * device, or else a negative error code.  Callable only from  
  13.  * contexts that can sleep.  
  14.  */  
  15. static inline ssize_t spi_w8r8(struct spi_device *spi, u8 cmd)  
  16. {  
  17.        ssize_t                   status;  
  18.        u8                  result;   
  19.        status = spi_write_then_read(spi, &cmd, 1, &result, 1);  
  20.   
  21.        /* return negative errno or unsigned value */  
  22.        return (status < 0) ? status : result;  
  23. }  

 

 

SPI write 8 bit read 16 bits

 

[html] view plain copy

 

  1. /**  
  2.  * spi_w8r16 - SPI synchronous 8 bit write followed by 16 bit read  
  3.  * @spi: device with which data will be exchanged  
  4.  * @cmd: command to be written before data is read back  
  5.  * Context: can sleep  
  6.  *  
  7.  * This returns the (unsigned) sixteen bit number returned by the  
  8.  * device, or else a negative error code.  Callable only from  
  9.  * contexts that can sleep.  
  10.  *  
  11.  * The number is returned in wire-order, which is at least sometimes  
  12.  * big-endian.  
  13.  */  
  14. static inline ssize_t spi_w8r16(struct spi_device *spi, u8 cmd)  
  15. {  
  16.        ssize_t                   status;  
  17.        u16                result;  
  18.    
  19.        status = spi_write_then_read(spi, &cmd, 1, (u8 *) &result, 2);  
  20.    
  21.        /* return negative errno or unsigned value */  
  22.        return (status < 0) ? status : result;  
  23. }  

 

[html] view plain copy

 

  1. int spi_write_then_read(struct spi_device *spi,  
  2.               const void *txbuf, unsigned n_tx,  
  3.               void *rxbuf, unsigned n_rx)  
  4. {  
  5.        static DEFINE_MUTEX(lock);  
  6.    
  7.        int                 status;  
  8.        struct spi_message  message;  
  9.        struct spi_transfer   x[2];  
  10.        u8                  *local_buf;  
  11.    
  12.        /* Use preallocated DMA-safe buffer.  We can't avoid copying here,  
  13.         * (as a pure convenience thing), but we can keep heap costs  
  14.         * out of the hot path ...  
  15.         */  
  16.        if ((n_tx + n_rx) > SPI_BUFSIZ)  
  17.               return -EINVAL;  
  18.    
  19.        spi_message_init(&message);  
  20.        memset(x, 0, sizeof x);  
  21.        if (n_tx) {  
  22.               x[0].len = n_tx;  
  23.               spi_message_add_tail(&x[0], &message);  
  24.        }  
  25.        if (n_rx) {  
  26.               x[1].len = n_rx;  
  27.               spi_message_add_tail(&x[1], &message);  
  28.        }  
  29.    
  30.        /* ... unless someone else is using the pre-allocated buffer */  
  31.        if (!mutex_trylock(&lock)) {  
  32.               local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);  
  33.               if (!local_buf)  
  34.                      return -ENOMEM;  
  35.        } else  
  36.               local_buf = buf;  
  37.    
  38.        memcpy(local_buf, txbuf, n_tx);  
  39.        x[0].tx_buf = local_buf;  
  40.        x[1].rx_buf = local_buf + n_tx;   
  41.        /* do the i/o */  
  42.        status = spi_sync(spi, &message);  
  43.        if (status == 0)  
  44.               memcpy(rxbuf, x[1].rx_buf, n_rx);  
  45.    
  46.        if (x[0].tx_buf == buf)  
  47.               mutex_unlock(&lock);  
  48.        else  
  49.               kfree(local_buf);  
  50.    
  51.        return status;  
  52. }  

 

 

SPI sync

读写都会调用到spi_sync

[html] view plain copy

 

  1. int spi_sync(struct spi_device *spi, struct spi_message *message)  
  2. {  
  3.        return __spi_sync(spi, message, 0);  
  4. }  

 

接着调用了__spi_sync

 

[html] view plain copy

 

  1. static int __spi_sync(struct spi_device *spi, struct spi_message *message,  
  2.                     int bus_locked)  
  3. {  
  4.        DECLARE_COMPLETION_ONSTACK(done);  
  5.        int status;  
  6.        struct spi_master *master = spi->master;  
  7.    
  8.        message->complete = spi_complete;  
  9.        message->context = &done;  
  10.    
  11.        if (!bus_locked)  
  12.               mutex_lock(&master->bus_lock_mutex);  
  13.         status = spi_async_locked(spi, message);  
  14.    
  15.        if (!bus_locked)  
  16.               mutex_unlock(&master->bus_lock_mutex);  
  17.    
  18.        if (status == 0) {  
  19.               wait_for_completion(&done);  
  20.               status = message->status;  
  21.        }  
  22.        message->context = NULL;  
  23.        return status;  
  24. }  

 

 

然后就是spi_async

[html] view plain copy

 

  1. int spi_async(struct spi_device *spi, struct spi_message *message)  
  2. {  
  3.        struct spi_master *master = spi->master;  
  4.        int ret;  
  5.        unsigned long flags;  
  6.    
  7.        spin_lock_irqsave(&master->bus_lock_spinlock, flags);  
  8.    
  9.        if (master->bus_lock_flag)  
  10.               ret = -EBUSY;  
  11.        else  
  12.               ret = __spi_async(spi, message);  
  13.    
  14.        spin_unlock_irqrestore(&master->bus_lock_spinlock, flags);  
  15.    
  16.        return ret;  
  17. }  

 

最后调用__spi_async

[html] view plain copy

 

  1. static int __spi_async(struct spi_device *spi, struct spi_message *message)  
  2. {  
  3.        struct spi_master *master = spi->master;  
  4.    
  5.        /* Half-duplex links include original MicroWire, and ones with  
  6.         * only one data pin like SPI_3WIRE (switches direction) or where  
  7.         * either MOSI or MISO is missing.  They can also be caused by  
  8.         * software limitations.  
  9.         */  
  10.        if ((master->flags & SPI_MASTER_HALF_DUPLEX)  
  11.                      || (spi->mode & SPI_3WIRE)) {  
  12.               struct spi_transfer *xfer;  
  13.               unsigned flags = master->flags;  
  14.    
  15.               list_for_each_entry(xfer, &message->transfers, transfer_list) {  
  16.                      if (xfer->rx_buf && xfer->tx_buf)  
  17.                             return -EINVAL;  
  18.                      if ((flags & SPI_MASTER_NO_TX) && xfer->tx_buf)  
  19.                             return -EINVAL;  
  20.                      if ((flags & SPI_MASTER_NO_RX) && xfer->rx_buf)  
  21.                             return -EINVAL;  
  22.               }  
  23.        }  
  24.   
  25.        message->spi = spi;  
  26.        message->status = -EINPROGRESS;  
  27.        return master->transfer(spi, message);  
  28. }  

 

返回了master->transfer(spi, message);那么就是控制器里去工作了。

 

我用的是gpio模拟的spi,所以那用gpio模拟的那个控制器去看控制器的处理了。

先还是看一下probe函数

 

[html] view plain copy

 

  1. static int __init spi_gpio_probe(struct platform_device *pdev)  
  2.   
  3. {  
  4.   
  5.        int                        status;  
  6.   
  7.        struct spi_master           *master;  
  8.   
  9.        struct spi_gpio                     *spi_gpio;  
  10.   
  11.        struct spi_gpio_platform_data       *pdata;  
  12.   
  13.        u16 master_flags = 0;  
  14.   
  15.    
  16.   
  17.        pdata = pdev->dev.platform_data;  
  18.   
  19. #ifdef GENERIC_BITBANG  
  20.   
  21.        if (!pdata || !pdata->num_chipselect)  
  22.   
  23.               return -ENODEV;  
  24.   
  25. #endif  
  26.   
  27.    
  28.   
  29.        status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags);  
  30.   
  31.        if (status < 0)  
  32.   
  33.               return status;  
  34.   
  35.    
  36.   
  37.        master = spi_alloc_master(&pdev->dev, sizeof *spi_gpio);  
  38.   
  39.        if (!master) {  
  40.   
  41.               status = -ENOMEM;  
  42.   
  43.               goto gpio_free;  
  44.   
  45.        }  
  46.   
  47.        spi_gpio = spi_master_get_devdata(master);  
  48.   
  49.        platform_set_drvdata(pdev, spi_gpio);  
  50.   
  51.    
  52.   
  53.        spi_gpio->pdev = pdev;  
  54.   
  55.        if (pdata)  
  56.   
  57.               spi_gpio->pdata = *pdata;  
  58.   
  59.    
  60.   
  61.        master->flags = master_flags;  
  62.   
  63.        master->bus_num = pdev->id;  
  64.   
  65.        master->num_chipselect = SPI_N_CHIPSEL;  
  66.   
  67.        master->setup = spi_gpio_setup;  
  68.   
  69.        master->cleanup = spi_gpio_cleanup;  
  70.   
  71.    
  72.   
  73.        spi_gpio->bitbang.master = spi_master_get(master);  
  74.   
  75.        spi_gpio->bitbang.chipselect = spi_gpio_chipselect;  
  76.   
  77.    
  78.   
  79.        if ((master_flags & (SPI_MASTER_NO_TX | SPI_MASTER_NO_RX)) == 0) {  
  80.   
  81.               spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0;  
  82.   
  83.               spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1;  
  84.   
  85.               spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2;  
  86.   
  87.               spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3;  
  88.   
  89.        } else {  
  90.   
  91.               spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_spec_txrx_word_mode0;  
  92.   
  93.               spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_spec_txrx_word_mode1;  
  94.   
  95.               spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_spec_txrx_word_mode2;  
  96.   
  97.               spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_spec_txrx_word_mode3;  
  98.   
  99.        }  
  100.   
  101.        spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer;  
  102.   
  103.        spi_gpio->bitbang.flags = SPI_CS_HIGH;  
  104.   
  105.    
  106.   
  107.        status = spi_bitbang_start(&spi_gpio->bitbang);  
  108.   
  109.        if (status < 0) {  
  110.   
  111.               spi_master_put(spi_gpio->bitbang.master);  
  112.   
  113. gpio_free:  
  114.   
  115.               if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)  
  116.   
  117.                      gpio_free(SPI_MISO_GPIO);  
  118.   
  119.               if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)  
  120.   
  121.                      gpio_free(SPI_MOSI_GPIO);  
  122.   
  123.               gpio_free(SPI_SCK_GPIO);  
  124.   
  125.               spi_master_put(master);  
  126.   
  127.        }  
  128.   
  129.    
  130.   
  131.        return status;  
  132.   
  133. }  

 

主要看下下面三个函数

[html] view plain copy

 

  1. spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0;  
  2.   
  3. spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer;  
  4.   
  5. status = spi_bitbang_start(&spi_gpio->bitbang);   

 

spi_gpio_txrx_word_mode0;就是最后调用到的先放一边,spi_bitbang_start,看一下这个函数

 

[html] view plain copy

 

  1. int spi_bitbang_start(struct spi_bitbang *bitbang)  
  2.   
  3. {  
  4.   
  5.        int   status;  
  6.   
  7.    
  8.   
  9.        if (!bitbang->master || !bitbang->chipselect)  
  10.   
  11.               return -EINVAL;  
  12.   
  13.    
  14.   
  15.        INIT_WORK(&bitbang->work, bitbang_work);  
  16.   
  17.        spin_lock_init(&bitbang->lock);  
  18.   
  19.        INIT_LIST_HEAD(&bitbang->queue);  
  20.   
  21.    
  22.   
  23.        if (!bitbang->master->mode_bits)  
  24.   
  25.               bitbang->master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags;  
  26.   
  27.    
  28.   
  29.        if (!bitbang->master->transfer)  
  30.   
  31.               bitbang->master->transfer = spi_bitbang_transfer;  
  32.   
  33.        if (!bitbang->txrx_bufs) {  
  34.   
  35.               bitbang->use_dma = 0;  
  36.   
  37.               bitbang->txrx_bufs = spi_bitbang_bufs;  
  38.   
  39.               if (!bitbang->master->setup) {  
  40.   
  41.                      if (!bitbang->setup_transfer)  
  42.   
  43.                             bitbang->setup_transfer =  
  44.   
  45.                                     spi_bitbang_setup_transfer;  
  46.   
  47.                      bitbang->master->setup = spi_bitbang_setup;  
  48.   
  49.                      bitbang->master->cleanup = spi_bitbang_cleanup;  
  50.   
  51.               }  
  52.   
  53.        } else if (!bitbang->master->setup)  
  54.   
  55.               return -EINVAL;  
  56.   
  57.        if (bitbang->master->transfer == spi_bitbang_transfer &&  
  58.   
  59.                      !bitbang->setup_transfer)  
  60.   
  61.               return -EINVAL;  
  62.   
  63.    
  64.   
  65.        /* this task is the only thing to touch the SPI bits */  
  66.   
  67.        bitbang->busy = 0;  
  68.   
  69.        bitbang->workqueue = create_singlethread_workqueue(  
  70.   
  71.                      dev_name(bitbang->master->dev.parent));  
  72.   
  73.        if (bitbang->workqueue == NULL) {  
  74.   
  75.               status = -EBUSY;  
  76.   
  77.               goto err1;  
  78.   
  79.        }  
  80.   
  81.    
  82.   
  83.        /* driver may get busy before register() returns, especially  
  84.   
  85.         * if someone registered boardinfo for devices  
  86.   
  87.         */  
  88.   
  89.        status = spi_register_master(bitbang->master);  
  90.   
  91.        if (status < 0)  
  92.   
  93.               goto err2;  
  94.   
  95.    
  96.   
  97.        return status;  
  98.   
  99.    
  100.   
  101. err2:  
  102.   
  103.        destroy_workqueue(bitbang->workqueue);  
  104.   
  105. err1:  
  106.   
  107.        return status;  
  108.   
  109. }  

 

看到这个函数指针了吧:

[html] view plain copy

 

  1. if (!bitbang->master->transfer)  
  2.   
  3.               bitbang->master->transfer = spi_bitbang_transfer;  

那么设备驱动调用的master->transfer(spi, message);就是调用到了spi_bitbang_transfer了,

 

[html] view plain copy

 

  1. /**  
  2.   
  3.  * spi_bitbang_transfer - default submit to transfer queue  
  4.   
  5.  */  
  6.   
  7. int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m)  
  8.   
  9. {  
  10.   
  11.        struct spi_bitbang   *bitbang;  
  12.   
  13.        unsigned long        flags;  
  14.   
  15.        int                 status = 0;  
  16.   
  17.    
  18.   
  19.        m->actual_length = 0;  
  20.   
  21.        m->status = -EINPROGRESS;  
  22.   
  23.    
  24.   
  25.        bitbang = spi_master_get_devdata(spi->master);  
  26.   
  27.    
  28.   
  29.        spin_lock_irqsave(&bitbang->lock, flags);  
  30.   
  31.        if (!spi->max_speed_hz)  
  32.   
  33.               status = -ENETDOWN;  
  34.   
  35.        else {  
  36.   
  37.               list_add_tail(&m->queue, &bitbang->queue);  
  38.   
  39.               queue_work(bitbang->workqueue, &bitbang->work);  
  40.   
  41.        }  
  42.   
  43.        spin_unlock_irqrestore(&bitbang->lock, flags);  
  44.   
  45.    
  46.   
  47.        return status;  
  48.   
  49. }  

这里是把信息加到了bitbang->workqueue,然后在bitbang->work里处理

 

再来看下bitbang->work做了什么

[html] view plain copy

 

  1. static void bitbang_work(struct work_struct *work)  
  2.   
  3. {  
  4.   
  5.        struct spi_bitbang   *bitbang =  
  6.   
  7.               container_of(work, struct spi_bitbang, work);  
  8.   
  9.        unsigned long        flags;  
  10.   
  11.    
  12.   
  13.        spin_lock_irqsave(&bitbang->lock, flags);  
  14.   
  15.        bitbang->busy = 1;  
  16.   
  17.        while (!list_empty(&bitbang->queue)) {  
  18.   
  19.               struct spi_message  *m;  
  20.   
  21.               struct spi_device     *spi;  
  22.   
  23.               unsigned         nsecs;  
  24.   
  25.               struct spi_transfer   *t = NULL;  
  26.   
  27.               unsigned         tmp;  
  28.   
  29.               unsigned         cs_change;  
  30.   
  31.               int                 status;  
  32.   
  33.               int                 do_setup = -1;  
  34.   
  35.    
  36.   
  37.               m = container_of(bitbang->queue.next, struct spi_message,  
  38.   
  39.                             queue);  
  40.   
  41.               list_del_init(&m->queue);  
  42.   
  43.               spin_unlock_irqrestore(&bitbang->lock, flags);  
  44.   
  45.    
  46.   
  47.               /* FIXME this is made-up ... the correct value is known to  
  48.   
  49.                * word-at-a-time bitbang code, and presumably chipselect()  
  50.   
  51.                * should enforce these requirements too?  
  52.   
  53.                */  
  54.   
  55.               nsecs = 100;  
  56.   
  57.    
  58.   
  59.               spi = m->spi;  
  60.   
  61.               tmp = 0;  
  62.   
  63.               cs_change = 1;  
  64.   
  65.               status = 0;  
  66.   
  67.    
  68.   
  69.               list_for_each_entry (t, &m->transfers, transfer_list) {  
  70.   
  71.    
  72.   
  73.                      /* override speed or wordsize? */  
  74.   
  75.                      if (t->speed_hz || t->bits_per_word)  
  76.   
  77.                             do_setup = 1;  
  78.   
  79.    
  80.   
  81.                      /* init (-1) or override (1) transfer params */  
  82.   
  83.                      if (do_setup != 0) {  
  84.   
  85.                             status = bitbang->setup_transfer(spi, t);  
  86.   
  87.                             if (status < 0)  
  88.   
  89.                                    break;  
  90.   
  91.                             if (do_setup == -1)  
  92.   
  93.                                    do_setup = 0;  
  94.   
  95.                      }  
  96.   
  97.    
  98.   
  99.                      /* set up default clock polarity, and activate chip;  
  100.   
  101.                       * this implicitly updates clock and spi modes as  
  102.   
  103.                       * previously recorded for this device via setup().  
  104.   
  105.                       * (and also deselects any other chip that might be  
  106.   
  107.                       * selected ...)  
  108.   
  109.                       */  
  110.   
  111.                      if (cs_change) {  
  112.   
  113.                             bitbang->chipselect(spi, BITBANG_CS_ACTIVE);  
  114.   
  115.                             ndelay(nsecs);  
  116.   
  117.                      }  
  118.   
  119.                      cs_change = t->cs_change;  
  120.   
  121.                      if (!t->tx_buf && !t->rx_buf && t->len) {  
  122.   
  123.                             status = -EINVAL;  
  124.   
  125.                             break;  
  126.   
  127.                      }  
  128.   
  129.    
  130.   
  131.                      /* transfer data.  the lower level code handles any  
  132.   
  133.                       * new dma mappings it needs. our caller always gave  
  134.   
  135.                       * us dma-safe buffers.  
  136.   
  137.                       */  
  138.   
  139.                      if (t->len) {  
  140.   
  141.                             /* REVISIT dma API still needs a designated  
  142.   
  143.                              * DMA_ADDR_INVALID; ~0 might be better.  
  144.   
  145.                              */  
  146.   
  147.                             if (!m->is_dma_mapped)  
  148.   
  149.                                    t->rx_dma = t->tx_dma = 0;  
  150.   
  151.                             status = bitbang->txrx_bufs(spi, t);  
  152.   
  153.                      }  
  154.   
  155.                      if (status > 0)  
  156.   
  157.                             m->actual_length += status;  
  158.   
  159.                      if (status != t->len) {  
  160.   
  161.                             /* always report some kind of error */  
  162.   
  163.                             if (status >= 0)  
  164.   
  165.                                    status = -EREMOTEIO;  
  166.   
  167.                             break;  
  168.   
  169.                      }  
  170.   
  171.                      status = 0;  
  172.   
  173.    
  174.   
  175.                      /* protocol tweaks before next transfer */  
  176.   
  177.                      if (t->delay_usecs)  
  178.   
  179.                             udelay(t->delay_usecs);  
  180.   
  181.    
  182.   
  183.                      if (!cs_change)  
  184.   
  185.                             continue;  
  186.   
  187.                      if (t->transfer_list.next == &m->transfers)  
  188.   
  189.                             break;  
  190.   
  191.    
  192.   
  193.                      /* sometimes a short mid-message deselect of the chip  
  194.   
  195.                       * may be needed to terminate a mode or command  
  196.   
  197.                       */  
  198.   
  199.                      ndelay(nsecs);  
  200.   
  201.                      bitbang->chipselect(spi, BITBANG_CS_INACTIVE);  
  202.   
  203.                      ndelay(nsecs);  
  204.   
  205.               }  
  206.   
  207.    
  208.   
  209.               m->status = status;  
  210.   
  211.               m->complete(m->context);  
  212.   
  213.    
  214.   
  215.               /* normally deactivate chipselect ... unless no error and  
  216.   
  217.                * cs_change has hinted that the next message will probably  
  218.   
  219.                * be for this chip too.  
  220.   
  221.                */  
  222.   
  223.               if (!(status == 0 && cs_change)) {  
  224.   
  225.                      ndelay(nsecs);  
  226.   
  227.                      bitbang->chipselect(spi, BITBANG_CS_INACTIVE);  
  228.   
  229.                      ndelay(nsecs);  
  230.   
  231.               }  
  232.   
  233.    
  234.   
  235.               spin_lock_irqsave(&bitbang->lock, flags);  
  236.   
  237.        }  
  238.   
  239.        bitbang->busy = 0;  
  240.   
  241.        spin_unlock_irqrestore(&bitbang->lock, flags);  
  242.   
  243. }  

 

当队列非空的时候就一直去取队列的数据,然后会执行到

[html] view plain copy

 

  1. status = bitbang->setup_transfer(spi, t);  

这个函数,因为在spi_bitbang_start中

[html] view plain copy

 

  1. if (!bitbang->txrx_bufs) {  
  2.   
  3.               bitbang->use_dma = 0;  
  4.   
  5.               bitbang->txrx_bufs = spi_bitbang_bufs;  
  6.   
  7.               if (!bitbang->master->setup) {  
  8.   
  9.                      if (!bitbang->setup_transfer)  
  10.   
  11.                             bitbang->setup_transfer =  
  12.   
  13.                                     spi_bitbang_setup_transfer;  
  14.   
  15.                      bitbang->master->setup = spi_bitbang_setup;  
  16.   
  17.                      bitbang->master->cleanup = spi_bitbang_cleanup;  
  18.   
  19.               }  
  20.   
  21.        }  

所以就调用了spi_bitbang_setup_transfer;

 

 

[html] view plain copy

 

  1. int spi_bitbang_setup_transfer(struct spi_device *spi, struct spi_transfer *t)  
  2.   
  3. {  
  4.   
  5.        struct spi_bitbang_cs      *cs = spi->controller_state;  
  6.   
  7.        u8                  bits_per_word;  
  8.   
  9.        u32                hz;  
  10.   
  11.    
  12.   
  13.        if (t) {  
  14.   
  15.               bits_per_word = t->bits_per_word;  
  16.   
  17.               hz = t->speed_hz;  
  18.   
  19.        } else {  
  20.   
  21.               bits_per_word = 0;  
  22.   
  23.               hz = 0;  
  24.   
  25.        }  
  26.   
  27.    
  28.   
  29.        /* spi_transfer level calls that work per-word */  
  30.   
  31.        if (!bits_per_word)  
  32.   
  33.               bits_per_word = spi->bits_per_word;  
  34.   
  35.        if (bits_per_word <= 8)  
  36.   
  37.               cs->txrx_bufs = bitbang_txrx_8;  
  38.   
  39.        else if (bits_per_word <= 16)  
  40.   
  41.               cs->txrx_bufs = bitbang_txrx_16;  
  42.   
  43.        else if (bits_per_word <= 32)  
  44.   
  45.               cs->txrx_bufs = bitbang_txrx_32;  
  46.   
  47.        else  
  48.   
  49.               return -EINVAL;  
  50.   
  51.    
  52.   
  53.        /* nsecs = (clock period)/2 */  
  54.   
  55.        if (!hz)  
  56.   
  57.               hz = spi->max_speed_hz;  
  58.   
  59.        if (hz) {  
  60.   
  61.               cs->nsecs = (1000000000/2) / hz;  
  62.   
  63.               if (cs->nsecs > (MAX_UDELAY_MS * 1000 * 1000))  
  64.   
  65.                      return -EINVAL;  
  66.   
  67.        }  
  68.   
  69.    
  70.   
  71.        return 0;  
  72.   
  73. }  

 

这里主要是根据bits_per_word选择传输的方式,分8、16,、32三种模式,ads7843touchscreen是用bits_per_word默认没有,选择bitbang_txrx_8的。

 

[html] view plain copy

 

  1. static unsigned bitbang_txrx_8(  
  2.   
  3.        struct spi_device     *spi,  
  4.   
  5.        u32                (*txrx_word)(struct spi_device *spi,  
  6.   
  7.                                    unsigned nsecs,  
  8.   
  9.                                    u32 word, u8 bits),  
  10.   
  11.        unsigned         ns,  
  12.   
  13.        struct spi_transfer   *t  
  14.   
  15. ) {  
  16.   
  17.        unsigned         bits = t->bits_per_word ? : spi->bits_per_word;  
  18.   
  19.        unsigned         count = t->len;  
  20.   
  21.        const u8         *tx = t->tx_buf;  
  22.   
  23.        u8                  *rx = t->rx_buf;  
  24.   
  25.    
  26.   
  27.        while (likely(count > 0)) {  
  28.   
  29.               u8           word = 0;  
  30.   
  31.    
  32.   
  33.               if (tx)  
  34.   
  35.                      word = *tx++;  
  36.   
  37.               word = txrx_word(spi, ns, word, bits);  
  38.   
  39.               if (rx)  
  40.   
  41.                      *rx++ = word;  
  42.   
  43.               count -= 1;  
  44.   
  45.        }  
  46.   
  47.        return t->len - count;  
  48.   
  49. }  
  50.   
  51.    

这里word = txrx_word(spi, ns, word, bits);会调用到哪里呢?,首先看下这个函数的指针指向哪里。

在spi_bitbang_start中,bitbang->master->setup = spi_bitbang_setup;

然后在spi_bitbang_setup 中有

[html] view plain copy

 

  1. cs->txrx_word = bitbang->txrx_word[spi->mode & (SPI_CPOL|SPI_CPHA)];  

所以,这个最终还是调用到了spi_gpio.c文件中的spi_gpio_spec_txrx_word_mode0

[html] view plain copy

 

  1. static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi,  
  2.   
  3.               unsigned nsecs, u32 word, u8 bits)  
  4.   
  5. {  
  6.   
  7.        unsigned flags = spi->master->flags;  
  8.   
  9.        return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);  
  10.   
  11. }  

然后这个函数就调用了bitbang_txrx_be_cpha0,这个函数在spi-bitbang-txrx.h中

 

[html] view plain copy

 

  1. static inline u32  
  2.   
  3. bitbang_txrx_be_cpha0(struct spi_device *spi,  
  4.   
  5.               unsigned nsecs, unsigned cpol, unsigned flags,  
  6.   
  7.               u32 word, u8 bits)  
  8.   
  9. {  
  10.   
  11.        /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */  
  12.   
  13.    
  14.   
  15.        /* clock starts at inactive polarity */  
  16.   
  17.        for (word <<= (32 - bits); likely(bits); bits--) {  
  18.   
  19.    
  20.   
  21.               /* setup MSB (to slave) on trailing edge */  
  22.   
  23.               if ((flags & SPI_MASTER_NO_TX) == 0)  
  24.   
  25.                      setmosi(spi, word & (1 << 31));  
  26.   
  27.               spidelay(nsecs);      /* T(setup) */  
  28.   
  29.    
  30.   
  31.               setsck(spi, !cpol);  
  32.   
  33.               spidelay(nsecs);  
  34.   
  35.    
  36.   
  37.               /* sample MSB (from slave) on leading edge */  
  38.   
  39.               word <<= 1;  
  40.   
  41.               if ((flags & SPI_MASTER_NO_RX) == 0)  
  42.   
  43.                      word |= getmiso(spi);  
  44.   
  45.               setsck(spi, cpol);  
  46.   
  47.        }  
  48.   
  49.        return word;  
  50.   
  51. }  

这里就是gpio模拟的spi总线的协议过程了。这样,从最上面设备程序调用到控制器的整个数据流就结束了。

 

注:这里有一个很恶心的东东,就是在bitbang_txrx_16,bitbang_txrx_32中的

[html] view plain copy

 

  1. const u8         *tx = t->tx_buf;  
  2.   
  3. u8                  *rx = t->rx_buf;  

这里是强制转换的,由于大小端的问题,可能导致数据相反,从而传输会出现问题的,如果是8bit的,那么就没有任何问题了。

一段小插曲,也是用逻辑分析仪抓到的数据才发现的,如果没有这玩意儿,估计现在还纠结着。

OK,至此,linux的SPI的数据传输就到这里了。

时间: 2024-10-05 16:08:55

和菜鸟一起学linux总线驱动之初识spi驱动数据传输流程【转】的相关文章

linux网络编程-linux方面遇到的一个难题,希望大哥大姐帮忙解决下,小弟是菜鸟,刚学linux编程

问题描述 linux方面遇到的一个难题,希望大哥大姐帮忙解决下,小弟是菜鸟,刚学linux编程 /proc/进程号/statm包含了进程使用内存的信息,如[root@cs 9519]# more statm 18095 2094 1468 7 0 605 0 [root@cs 9519]# ps 9519PID TTY STAT TIME COMMAND9519 ? S 0:00 /usr/libexec/notification-daemonmore statm 18095 2094 1468

十天学Linux内核之第四天---如何处理输入输出操作

原文:十天学Linux内核之第四天---如何处理输入输出操作 真的是悲喜交加呀,本来这个寒假早上8点都去练车,两个小时之后再来实验室陪伴Linux内核,但是今天教练说没名额考试了,好纠结,不过想想就可以睡懒觉了,哈哈,自从大三寒假以来还没睡过懒觉呢,现在也有更多的时间来分享自己学习Linux内核的感受,前几天觉得就是自己也有些不懂的,相信大家看了也是很模糊,以后我会标志出来自己不懂的,希望大神们指教,也希望大家多多指点,共同攻克Linux内核,今天将讲到处理器是如何与其它设备进行交互的,内核又是

十天学Linux内核之第六天---调度和内核同步

原文:十天学Linux内核之第六天---调度和内核同步 心情大好,昨晚我们实验室老大和我们聊了好久,作为已经在实验室待了快两年的大三工科男来说,老师让我们不要成为那种技术狗,代码工,说多了都是泪啊,,不过我们的激情依旧不变,老师帮我们组好了队伍,着手参加明年的全国大赛,说起来我们学校历史上也就又一次拿国一的,去了一次人民大会堂领奖,可以说老大是对我们寄予厚望,以后我会专攻仪器仪表类的题目,激情不灭,梦想不息,不过最近一段时间还是会继续更新Linux内核,总之,继续加油~ Linux2.6版本中的

十天学Linux内核之第九天---向内核添加代码

原文:十天学Linux内核之第九天---向内核添加代码 睡了个好觉,很晚才起,好久没有这么舒服过了,今天的任务不重,所以压力不大,呵呵,现在的天气真的好冷,不过实验室有空调,我还是喜欢待在这里,有一种不一样的感觉,在写了这么多天之后,自己有些不懂的页渐渐的豁然开朗了吗,而且也交到了一些朋友,真是相当开心啊.今天将介绍一下向内核中添加代码,一起来看看吧~ 先来熟悉一下文件系统,通过/dev可以访问Linux的设备,我们以men设备驱动程序为例来看看随机数是如何产生的,源代码在dirvers/cha

十天学Linux内核之第十天---总结篇(kconfig和Makefile &amp; 讲不出再见)

原文:十天学Linux内核之第十天---总结篇(kconfig和Makefile & 讲不出再见) 非常开心能够和大家一起分享这些,让我受益匪浅,感激之情也溢于言表,,code monkey的话少,没办法煽情了,,,,,,,冬天的风,吹得伤怀,倒叙往事,褪成空白~学校的人越来越少了,就像那年我们小年之后再回家的场景一样,到处荒芜,然而我们的激情却不褪去,依然狂躁在实验室凌晨两点半的星空里,也许今天又会是这样的一年,不一样的是身边的人变成学弟学妹了,而我们几个大三老家伙依然在,为自己喜欢的事情,为

linux 实时时钟(RTC)驱动【转】

转自:http://blog.csdn.net/yaozhenguo2006/article/details/6820218 这个是linux内核文档关于rtc实时时钟部分的说明,此文档主要描述了rtc实时时钟的作用和编程接口,分别介绍了老的rtc接口和新的rtc类架构.并给出了一个测试rtc驱动的程序.     linux 实时时钟(RTC)驱动                                                                         翻译

Linux驱动修炼之道-SPI驱动框架源码分析(上)【转】

转自:http://blog.csdn.net/lanmanck/article/details/6895318 SPI驱动架构,以前用过,不过没这个详细,跟各位一起分享: 来自:http://blog.csdn.net/woshixingaaa/article/details/6574215     SPI协议是一种同步的串行数据连接标准,由摩托罗拉公司命名,可工作于全双工模式.相关通讯设备可工作于m/s模式.主设备发起数据帧,允许多个从设备的存在.每个从设备 有独立的片选信号,SPI一般来说

Linux芯片级移植与底层驱动(基于3.7.4内核) 中断控制器

3.中断控制器驱动 在Linux内核中,各个设备驱动可以简单地调用request_irq().enable_irq().disable_irq().local_irq_disable().local_irq_enable()等通用API完成中断申请.使能.禁止等功能.在将Linux移植到新的SoC时,芯片供应商需要提供该部分API的底层支持. local_irq_disable().local_irq_enable()的实现与具体中断控制器无关,对于ARMv6以上的体系架构而言,是直接调用CPS

如何获得Linux系统的内置模块和设备驱动列表

  提问:我想要知道Linux系统中内核内置的模块,以及每个模块有哪些参数.有什么方法可以得到内置模块和设备驱动的列表,以及它们的详细信息呢? 现代Linux内核正在随着时间变化而迅速增长,以支持大量的硬件.文件系统和网络功能.在此期间,"可加载模块(loadable kernel modules,[LKM])"的引入防止内核变得越来越臃肿,以及在不同的环境中灵活地扩展功能及硬件支持,而不必重新构建内核. 最新的Linux发行版的内核只带了相对较小的"内置模块(built-i