• 在freescale mx6q平台上添加spi资源


    1:配置管脚为SPI功能

    在board-mx6q_sabresd.h的最后添加,复制被重定义

    (以添加SPI2为例)

           

    [cpp] view plaincopy
     
    1. <span style="font-size:18px;">        MX6Q_PAD_EIM_CS0__ECSPI2_SCLK,  
    2.         MX6Q_PAD_EIM_CS1__ECSPI2_MOSI,  
    3.         MX6Q_PAD_EIM_OE__ECSPI2_MISO,  
    4.         MX6Q_PAD_CSI0_DAT11__ECSPI2_SS0 ,  
    5. </span>  


    之后再板级文件board-mx6q_sabresd.c中将有相关函数对管脚进行统一初始化。

    完成寄存器配置的工作。

    [cpp] view plaincopy
     
    1. <span style="font-size:18px;">  mxc_iomux_v3_setup_multiple_pads(mx6q_sabresd_pads,  
    2.         ARRAY_SIZE(mx6q_sabresd_pads));  
    3.   
    4.     mxc_iomux_v3_setup_multiple_pads(mx6q_sabresd_cstm_tq_pads,  
    5.         ARRAY_SIZE(mx6q_sabresd_cstm_tq_pads));</span>  

    2:在板级文件board-mx6q_sabresd.c中添加以下代码

    将匹配到driver/spi/spidev.c文件中的驱动源码

    2.1完成SPI master的注册

    SPI2片选管脚宏定义:

    [cpp] view plaincopy
     
    1. <span style="font-size:14px;">#define SABRESD_ECSPI2_CS0 IMX_GPIO_NR(5, 29)</span>  


    添加相关结构体

    [cpp] view plaincopy
     
    1. <span style="font-size:14px;">static int mx6q_marsboard_spi1_cs[] = {  
    2.         SABRESD_ECSPI2_CS0,  
    3. };  
    4. </span>  


     

    [cpp] view plaincopy
     
    1. <span style="font-size:14px;">static const struct spi_imx_master mx6q_sabresd_spi2_data __initconst = {  
    2.         .chipselect = mx6q_marsboard_spi2_cs,  
    3.         .num_chipselect = ARRAY_SIZE(mx6q_marsboard_spi1_cs),  
    4. };  
    5. </span>  


     

    2.2在spi 总线上匹配spi2的驱动文件

    mx6q平台有2路spi资源,0/1,其中的bus_num则为挂载驱动的总线选择。

    [cpp] view plaincopy
     
    1. <span style="font-size:18px;"><span style="font-size:14px;">static struct mtd_partition imx6_sabrelite_spi_nor_partitions[] = {  
    2.  {  
    3.   .name = "bootloader",  
    4.   .offset = 0,  
    5.   .size = 0x00100000,  
    6.  },  
    7.  {  
    8.   .name = "kernel",  
    9.   .offset = MTDPART_OFS_APPEND,  
    10.   .size = MTDPART_SIZ_FULL,  
    11.  },  
    12. };  
    13.   
    14.   
    15. static struct flash_platform_data imx6_sabrelite__spi_flash_data = {  
    16.  .name = "spidev",  / /匹配原则。  
    17.  .parts = imx6_sabrelite_spi_nor_partitions,  
    18.  .nr_parts = ARRAY_SIZE(imx6_sabrelite_spi_nor_partitions),  
    19.  .type = "sst25vf016b",  
    20. };  
    21.   
    22.   
    23.   
    24.   
    25. static struct spi_board_info imx6_sabrelite_spi_nor_device[] __initdata = {  
    26.  {  
    27.   .modalias = "spidev",  
    28.   .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */  
    29.   .bus_num = 1,    //设备挂载第几号spi总线上  
    30.   .chip_select = 0,  
    31.   .platform_data = &imx6_sabrelite__spi_flash_data,  
    32.  },  
    33. };  
    34.   
    35.   
    36. spi_register_board_info(imx6_sabrelite_spi_nor_device,  
    37. ARRAY_SIZE(imx6_sabrelite_spi_nor_device));  
    38.   
    39. imx6q_add_ecspi(0, &mx6q_sabrelite_spi2_data);  
    40.   
    41.   
    42.   
    43.   
    44.   
    45.   
    46. </span>   
    47. </span>  

    3:内核配置

    查看spidev.c文件目录下的Kconfig以及Makefile得知内核驱动的添加方法

    选择蓝色部分选项,将spidev.c文件添加到内核中。

    4:查看开发板/sys/bus/spi/drivers/spidev目录

    在/dev下生成设备文件/dev/spidev1.0

    5:使用freescale官方的bsp包中的spi测试程序对接口进行测试

    [cpp] view plaincopy
     
    1. <span style="font-size:12px;">/* 
    2.  * SPI testing utility (using spidev driver) 
    3.  * 
    4.  * Copyright (c) 2007  MontaVista Software, Inc. 
    5.  * Copyright (c) 2007  Anton Vorontsov <avorontsov@ru.mvista.com> 
    6.  * 
    7.  * This program is free software; you can redistribute it and/or modify 
    8.  * it under the terms of the GNU General Public License as published by 
    9.  * the Free Software Foundation; either version 2 of the License. 
    10.  * 
    11.  * Cross-compile with cross-gcc -I/path/to/cross-kernel/include 
    12.  */  
    13.   
    14. #include <stdint.h>  
    15. #include <unistd.h>  
    16. #include <stdio.h>  
    17. #include <stdlib.h>  
    18. #include <getopt.h>  
    19. #include <fcntl.h>  
    20. #include <sys/ioctl.h>  
    21. #include <linux/types.h>  
    22. #include <linux/spi/spidev.h>  
    23.   
    24. #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))  
    25.   
    26. static void pabort(const char *s)  
    27. {  
    28.     perror(s);  
    29.     abort();  
    30. }  
    31.   
    32. static const char *device = "/dev/spidev1.0";  
    33. static uint8_t mode;  
    34. static uint8_t bits = 8;  
    35. static uint32_t speed = 500000;  
    36. static uint16_t delay;  
    37.   
    38. static void transfer(int fd)  
    39. {  
    40.     int ret;  
    41.     uint8_t tx[] = {  
    42.         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  
    43.         0x40, 0x00, 0x00, 0x00, 0x00, 0x95,  
    44.         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  
    45.         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  
    46.         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  
    47.         0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD,  
    48.         0xF0, 0x0D,  
    49.     };  
    50.     uint8_t rx[ARRAY_SIZE(tx)] = {0, };  
    51.     struct spi_ioc_transfer tr = {  
    52.         .tx_buf = (unsigned long)tx,  
    53.         .rx_buf = (unsigned long)rx,  
    54.         .len = ARRAY_SIZE(tx),  
    55.         .delay_usecs = delay,  
    56.         .speed_hz = speed,  
    57.         .bits_per_word = bits,  
    58.     };  
    59.   
    60.     ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);  
    61.     if (ret < 1)  
    62.         pabort("can't send spi message");  
    63.   
    64.     for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {  
    65.         if (!(ret % 6))  
    66.             puts("");  
    67.         printf("%.2X ", rx[ret]);  
    68.     }  
    69.     puts("");  
    70. }  
    71.   
    72.   
    73. int main(int argc, char *argv[])  
    74. {  
    75.     int ret = 0;  
    76.     int fd;  
    77.   
    78.     //parse_opts(argc, argv); /* for what ,unknow*/  
    79.   
    80.     fd = open(device, O_RDWR);  
    81.     if (fd < 0)  
    82.         pabort("can't open device");  
    83.   
    84.     /* 
    85.      * spi mode 
    86.      */  
    87.     ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);  
    88.     if (ret == -1)  
    89.         pabort("can't set spi mode");  
    90.   
    91.     ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);  
    92.     if (ret == -1)  
    93.         pabort("can't get spi mode");  
    94.   
    95.     /* 
    96.      * bits per word 
    97.      */  
    98.     ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);  
    99.     if (ret == -1)  
    100.         pabort("can't set bits per word");  
    101.   
    102.     ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);  
    103.     if (ret == -1)  
    104.         pabort("can't get bits per word");  
    105.   
    106.     /* 
    107.      * max speed hz 
    108.      */  
    109.     ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);  
    110.     if (ret == -1)  
    111.         pabort("can't set max speed hz");  
    112.   
    113.     ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);  
    114.     if (ret == -1)  
    115.         pabort("can't get max speed hz");  
    116.   
    117.     printf("spi mode: %d ", mode);  
    118.     printf("bits per word: %d ", bits);  
    119.     printf("max speed: %d Hz (%d KHz) ", speed, speed/1000);  
    120.   
    121.     transfer(fd);  
    122.   
    123.     close(fd);  
    124.   
    125.     return ret;  
    126. }  
    127. </span>  


     

    执行应用程序,可以看到时序模式(spi 4种时序模式第0种),时钟频率等参数。

    7    /*
    8     * SPI testing utility (using spidev driver)
    9     *
    10     * Copyright (c) 2007  MontaVista Software, Inc.
    11     * Copyright (c) 2007  Anton Vorontsov <avorontsov@ru.mvista.com>
    12     *
    13     * This program is free software; you can redistribute it and/or modify
    14     * it under the terms of the GNU General Public License as published by
    15     * the Free Software Foundation; either version 2 of the License.
    16     *
    17     * Cross-compile with cross-gcc -I/path/to/cross-kernel/include
    18     */
    19    
    20    #include <stdint.h>
    21    #include <unistd.h>
    22    #include <stdio.h>
    23    #include <stdlib.h>
    24    #include <getopt.h>
    25    #include <fcntl.h>
    26    #include <sys/ioctl.h>
    27    #include <linux/types.h>
    28    #include <linux/spi/spidev.h>
    29    
    30    #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
    31    
    32    static void pabort(const char *s)
    33    {
    34        perror(s);
    35        abort();
    36    }
    37    
    38    static const char *device = "/dev/spidev1.0";
    39    static uint8_t mode;
    40    static uint8_t bits = 8;
    41    static uint32_t speed = 9000000;
    42    static uint16_t delay=0;
    43    
    44    static void transfer(int fd)
    45    {
    46        int ret;
    47        uint8_t tx[] = {
    48            0x11, 0x12, 0x18, 0x78, 0x24, 0xa2,
    49            0x40, 0x00, 0x13, 0x00, 0x00, 0x95,
    50            0x23, 0x56, 0x54, 0x34, 0x45, 0x65,
    51            0x69, 0x78, 0x98, 0xFF, 0xFF, 0x36,
    52        };
    53        uint8_t rx[ARRAY_SIZE(tx)] = {0, };
    54        struct spi_ioc_transfer tr = {
    55            .tx_buf = (unsigned long)tx,
    56            .rx_buf = (unsigned long)rx,
    57            .len = ARRAY_SIZE(tx),
    58            .delay_usecs = delay,
    59            .speed_hz = speed,
    60            .bits_per_word = bits,
    61            .cs_change=1
    62        };
    63    
    64        ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
    65        if (ret < 1)
    66            pabort("can't send spi message");
    67    
    68        for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {
    69            if (!(ret % 6))
    70                puts("");
    71            printf("%.2X ", rx[ret]);
    72        }
    73        puts("");
    74    }
    75    
    76    static void print_usage(const char *prog)
    77    {
    78        printf("Usage: %s [-DsbdlHOLC3]
    ", prog);
    79        puts("  -D --device   device to use (default /dev/spidev1.0)
    "
    80             "  -s --speed    max speed (Hz)
    "
    81             "  -d --delay    delay (usec)
    "
    82             "  -b --bpw      bits per word 
    "
    83             "  -l --loop     loopback
    "
    84             "  -H --cpha     clock phase
    "
    85             "  -O --cpol     clock polarity
    "
    86             "  -L --lsb      least significant bit first
    "
    87             "  -C --cs-high  chip select active high
    "
    88             "  -3 --3wire    SI/SO signals shared
    ");
    89        exit(1);
    90    }
    91    
    92    static void parse_opts(int argc, char *argv[])
    93    {
    94        while (1) {
    95            static const struct option lopts[] = {
    96                { "device",  1, 0, 'D' },
    97                { "speed",   1, 0, 's' },
    98                { "delay",   1, 0, 'd' },
    99                { "bpw",     1, 0, 'b' },
    100                { "loop",    0, 0, 'l' },
    101                { "cpha",    0, 0, 'H' },
    102                { "cpol",    0, 0, 'O' },
    103                { "lsb",     0, 0, 'L' },
    104                { "cs-high", 0, 0, 'C' },
    105                { "3wire",   0, 0, '3' },
    106                { "no-cs",   0, 0, 'N' },
    107                { "ready",   0, 0, 'R' },
    108                { NULL, 0, 0, 0 },
    109            };
    110            int c;
    111    
    112            c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts, NULL);
    113    
    114            if (c == -1)
    115                break;
    116    
    117            switch (c) {
    118            case 'D':
    119                device = optarg;
    120                break;
    121            case 's':
    122                speed = atoi(optarg);
    123                break;
    124            case 'd':
    125                delay = atoi(optarg);
    126                break;
    127            case 'b':
    128                bits = atoi(optarg);
    129                break;
    130            case 'l':
    131                mode |= SPI_LOOP;
    132                break;
    133            case 'H':
    134                mode |= SPI_CPHA;
    135                break;
    136            case 'O':
    137                mode |= SPI_CPOL;
    138                break;
    139            case 'L':
    140                mode |= SPI_LSB_FIRST;
    141                break;
    142            case 'C':
    143                mode |= SPI_CS_HIGH;
    144                break;
    145            case '3':
    146                mode |= SPI_3WIRE;
    147                break;
    148            case 'N':
    149                mode |= SPI_NO_CS;
    150                break;
    151            case 'R':
    152                mode |= SPI_READY;
    153                break;
    154            default:
    155                print_usage(argv[0]);
    156                break;
    157            }
    158        }
    159    }
    160    
    161    int main(int argc, char *argv[])
    162    {
    163        int ret = 0;
    164        int fd;
    165    
    166        parse_opts(argc, argv);
    167    
    168        fd = open(device, O_RDWR);
    169        if (fd < 0)
    170            pabort("can't open device");
    171    
    172        /*
    173         * spi mode
    174         */
    175        ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
    176        if (ret == -1)
    177            pabort("can't set spi mode");
    178    
    179        ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
    180        if (ret == -1)
    181            pabort("can't get spi mode");
    182    
    183        /*
    184         * bits per word
    185         */
    186        ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
    187        if (ret == -1)
    188            pabort("can't set bits per word");
    189    
    190        ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
    191        if (ret == -1)
    192            pabort("can't get bits per word");
    193    
    194        /*
    195         * max speed hz
    196         */
    197        ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
    198        if (ret == -1)
    199            pabort("can't set max speed hz");
    200    
    201        ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
    202        if (ret == -1)
    203            pabort("can't get max speed hz");
    204    
    205        printf("spi mode: %d
    ", mode);
    206        printf("bits per word: %d
    ", bits);
    207        printf("max speed: %d Hz (%d KHz)
    ", speed, speed/1000);
    208    
    209        transfer(fd);
    210    
    211        close(fd);
    212    
    213        return ret;
    214    }
  • 相关阅读:
    oracle常用命令
    批量导出docker镜像
    python中的xpath
    __call__, __str__
    闭包
    ORM操作
    nginx跨域请求
    docker-compose命令
    nginx 之 websocket长连接
    nginx--proxy_set_header
  • 原文地址:https://www.cnblogs.com/subo_peng/p/4837372.html
Copyright © 2020-2023  润新知