SPI子系统之驱动SSD1306 OLED(5)

/* override or restore speed and wordsize */
            /* [cgw]: 如果驱动指定了spi速度,和位数,重新调用spi_bitbang_setup_transfer
            * 更改默认设置
            */
            if (t->speed_hz || t->bits_per_word) {
                setup_transfer = bitbang->setup_transfer;
                if (!setup_transfer) {
                    status = -ENOPROTOOPT;
                    break;
                }
            }
            if (setup_transfer) {
                status = setup_transfer(spi, t);
                if (status < 0)
                    break;
            }

/* set up default clock polarity, and activate chip;
            * this implicitly updates clock and spi modes as
            * previously recorded for this device via setup().
            * (and also deselects any other chip that might be
            * selected ...)
            */
            /* [cgw]: 激活spi */
            if (cs_change) {
                bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
                ndelay(nsecs);
            }
            /* [cgw]: 驱动指定收发完一帧数据要不要改变恢复CS为空闲 */
            cs_change = t->cs_change;
            /* [cgw]: 收发包为空,则无效 */
            if (!t->tx_buf && !t->rx_buf && t->len) {
                status = -EINVAL;
                break;
            }

/* transfer data.  the lower level code handles any
            * new dma mappings it needs. our caller always gave
            * us dma-safe buffers.
            */
            if (t->len) {
                /* REVISIT dma API still needs a designated
                * DMA_ADDR_INVALID; ~0 might be better.
                */
                if (!m->is_dma_mapped)
                    t->rx_dma = t->tx_dma = 0;
                /* [cgw]: 这里才是真正的实现spi收发时序 */
                status = bitbang->txrx_bufs(spi, t);
            }
            if (status != t->len) {
                if (status > 0)
                    status = -EMSGSIZE;
                break;
            }
            m->actual_length += status;
            status = 0;

/* protocol tweaks before next transfer */
            if (t->delay_usecs)
                udelay(t->delay_usecs);
           
            /* [cgw]: 收发完一帧,不改变CS状态 */
            if (!cs_change)
                continue;
           
            /* [cgw]: 收发列表已经没有数据,结束 */
            if (t->transfer_list.next == &m->transfers)
                break;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/f06f37a19007f6f04167f392c9581460.html