英创信息技术EM9280 Linux SPI驱动简介

描述

1、简述

SPI(Synchronous Peripheral Interface)是一种同步串行数据通讯总线接口,常用于连接ADCs、EPROMs、Sensors或者是其他一些微控制器,SPI具有两种工作模式:master和slave模式,其中master模式提供时钟信号。

EM9280提供的SPI驱动支持master模式,该SPI接口为四线制SPI,包括:时钟CLK、数据MISO (master in, slave out)、数据 MOSI (master out, slave in)、片选CS。SPI管脚和GPIO28-GPIO31复用。具体的管脚定义请参见《EM9280工控主板数据手册》相关章节。

本文将介绍EM9280如何实现SPI设备驱动(spi-dev)以及如何使用spi-dev。

2、Linux内核配置

内核配置中增加以下选项(make menuconfig):

Device Drivers ---> SPI
        Device Drivers ---> SPI ---> Freescale MXS SPI/SSP Controller
        Device Drivers ---> SPI ---> User mode SPI device driver support

增加对SPI板卡一级的支持,在arch/arm/mach-mx28/board-em9280.c定义:

static struct spi_board_info spi_board_info[] __initdata = {
                {
                        .modalias = 'spidev',
                        .chip_select = 0,
                        .max_speed_hz = 12 * 1000 * 1000,
                        .bus_num = 1,
                        .mode = SPI_MODE_3,
                },
        };

spi_register_board_info( spi_board_info, ARRAY_SIZE(spi_board_info)); )); 注册spi_board_info。这个代码会把spi_board_info注册要链表board_list上, 然后spi_master的注册会在spi_register_board_info之后,spi_master注册的过程中会调用scan_boardinfo扫描board_list,找到挂接在它上面的spi设备,然后创建并注册spi_device。这样EM9280在系统启动完成后SPI所对应的设备节点为:“/dev/spidev1.0”。

3、spi-dev的使用

SPI常用四种数据传输模式,主要差别在于:输出串行同步时钟极性(CPOL)和相位(CPHA)可以进行配置。如果CPOL= 0,串行同步时钟的空闲状态为低电平;如果CPOL= 1,串行同步时钟的空闲状态为高电平。如果CPHA= 0,在串行同步时钟的前沿(上升或下降)数据被采样;如果CPHA = 1,在串行同步时钟的后沿(上升或下降)数据被采样。对于SPI模式的定义如下表1:

SPI Mode CPOL CPHA
0 0 0
1 0 1
2 1 0
3 1 1

应用程序可以通过read()、write()、ioctl()函数使用spi-dev驱动,在EM9280中SPI是半双工模式,最高波特率为12Mbps, 所以选择调用read/write函数进行数据通讯,而ioctl()函数仅仅用于对于SPI通讯参数的设置。如:

static const char *device = '/dev/spidev1.0';
        static uint8_t mode = 3;
        static uint8_t bits = 8;
        static uint32_t speed = 1000000;
        int main( int argc, char *argv[] )
        {
                int i, fd;
                int ret = 0;
                char wr_buf[]={ 0xff,0x00,0x1f,0x0f,0xff,0x00,0x1f,0x0f, 0xff,0x00 };
                char rd_buf[10];
                fd = open(device, O_RDWR);
                if (fd < 0)
                        pabort('can't open device');
                // 设置 spi mode,其定义参见表1 
                ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
                if (ret == -1)
                        pabort('can't set spi mode');
                ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
                if (ret == -1)
                        pabort('can't get spi mode');
                // 设置数据bit位
                ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); 
                if (ret == -1) 
                        pabort('can't set bits per word');
                ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
                if (ret == -1)
                        pabort('can't get bits per word');
                // 设置SPI通讯波特率
                ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
                if (ret == -1)
                        pabort('can't set max speed hz');
                ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
                if (ret == -1)
                        pabort('can't get max speed hz');
                printf('spi mode: %d\n', mode);
                printf('bits per word: %d\n', bits);
                printf('max speed: %d Hz (%d KHz)\n', speed, speed/1000);
                if( write(fd, wr_buf, ARRAY_SIZE(wr_buf)) != ARRAY_SIZE(wr_buf)) 
                        perror('Write Error'); 
                if( read(fd, rd_buf, ARRAY_SIZE(rd_buf)) != ARRAY_SIZE(rd_buf) )
                        perror('Read Error');
                else
                {
                        for (i=0; i<(int)ARRAY_SIZE(rd_buf);i++) 
                        {
                                printf('0x%02X ', rd_buf[i]);
                                if (i%2)
                                        printf('\n'); 
                        }
                }
                close(fd);

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分