zoukankan      html  css  js  c++  java
  • 和菜鸟一起学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的数据传输就到这里了。

  • 相关阅读:
    一分钟搞懂列式与行式数据库(转)
    docker daemon 配置文件
    Docker-删除untagged docker images
    全栈JavaScript之路(十三)了解 ElementTraversal 规范
    static, readonly, const
    Timer与AlarmManager的差别
    计算客 (人人都有极客精神)爆力
    nginx 配置web 虚拟文件夹 而且codeIgniter,thinkphp 重定向url 地址
    单例模式之 懒汉模式普通版
    POJ 3468 A Simple Problem with Integers 【树状数组】
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/5736638.html
Copyright © 2011-2022 走看看