SPI message 基础 Part 2

SPI message基础

Contents

        .Part 1 - Linux SPI系统概览

        .Part 2 - SPI message 基础

        .Part 3 - 异步写

LinuxSPI 通信基础

SPI总线上是通过封装一系列的spi_transfer到一个spi_message中,然后将spi_message提交到SPI子系统去。

下面是spi_transfer结构:

struct spi_transfer {
    const void*tx_buf;	//驱动提供的发送缓冲区dma,
    void *rx_buf;	 //接收缓冲区
    unsigned len;
    dma_addr_ttx_dma;	//发送dma,controller使用
    dma_addr_t rx_dma;	//接收dma
    unsigned cs_change:1;	//片选位 
    u8 bits_per_word;	//每字长度
    u16 delay_usecs;	//延迟
    u32 speed_hz;	 //速度
    struct list_headtransfer_list;	//transfer 链表
};

len is always the # of 8-bitbytes to clock, could be send ,receive or both.

tx_dmarx_dma可通过dma_map_single()来初始化或者让controller来填充这些域。如果你手动的映射这些dma,就必须将spi_message.is_dma_mappped置为1,来告知controller你已经做好映射了。既然手动的做映射也必须手的unmapped掉。并不是所有的transfer都会使用dma,比如,有的控制器在transfer小于8字节时会使用PIO(ProgrammingI/O,cpu执行I/O端口指令进行读写,大数据交换是会提高cpu占有率)模式。

cs_change1会引起CS线在spi_message序列中transfers间变高。通常,CS会在第一个transfer前变低并一直保持直至spi_message序列中最后一个transfer到来(这是本次spi_message中最后一个)。这种反转在和某些设备通信时会非常有用。

bit_per_word对于单个spi_transfer可用来覆盖spi_device.bits_per_word域。清零不做覆盖。

delay_usecs会在spi_message序列中一个transfer之后,CS状态改变前或者下一个transfer修正延迟。

speed_hz允许这个transfer可以有高于spi_device.max_speed_hz的速率。清零不作变化。

transfer_listspi_message序列中用于维护transfer的链表。

spi_transfer中时常更改的域也许只有lentx_bufrx_buf。剩下的当以0来初始化。

单个spi_transfer可表示一次读,一次写或者是一次读写。在SPIcontroller驱动下,所有操作常是全双工的。向spi_transferrx_buf传递一个NULL,这就是一次只写操作,会丢弃MISO线上的数据。同样向tx_buf传递一个NULL,这就是一次只读操作了。spi_transferlen域代表(已经多少字节数据流过总线了)howmany bytes to clock the bus

spi_message结构:

struct spi_message {
        struct list_head transfers;
        struct spi_device *spi;
        unsigned is_dma_mapped:1;
        void (*complete)(void*context);
        void *context;
        unsigned actual_length;
        int status;
        struct list_head queue;
        void *state;
};

transfer这个spi_message所包含有的spi_transfer链表头。

is_dma_mappedspi_transfertx_dmarx_dma是否已经mapped

complete回调函数

context 提供给complete的可选参数

actual_lengthspi_message已经传输了的字节数

status 出错与否,错误时返回errorcode

queue state controller驱动内部使用

在每次使用spi_message可以使用函数:

void spi_message_init(structspi_message *m);

来初始化。

spi_message添加transfers可以使用spi_message_add_tail()函数:

void spi_message_add_tail(structspi_transfer *t, struct spi_message *m);

一旦你准备好了spi_message,就可以使用spi_async()来向SPI系统提交了:

int spi_async(struct spi_device *spi,struct spi_message *message);

因为是异步的,一提交就立马返回了,这也就是说需要同步机制(complete就是了)。他确保不会睡眠,可安全的在中断handler或其他不可休眠的代码中调用。稍后会念念他的好的。

使用spi_async()需要注意的是,在complete()未返回前不要轻易访问你一提交的spi_transfer中的buffer。也不能释放SPI系统正在使用的buffer。一旦你的complete返回了,这些buffer就又是你的了。

使用完成回调机制稍显复杂,可以使用SPI系统提供的另一个同步版本:spi_sync():

int spi_sync(struct spi_device *spi,struct spi_message *message);

因为是同步的,spi_sync提交完spi_message后不会立即返回,会一直等待其被处理。一旦返回就可以重新使用buffer了。spi_sync()drivers/spi/spi.c中实现,其调用了spi_async(),并休眠直至complete返回。

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值