SPI

从数据手册中可以了解到,SSD20X有2个SPI接口,一个已经用于SPIFlash,因此供开发者使用的只有一个SPI接口。

如果需要开启SPI接口,则需要将DTS中的status改为ok:

vi kernel/arch/arm/boot/dts/infinity2m-doublenet.dtsi

接着将对应的引脚配置为SPI_MODE:

vi kernel/arch/arm/boot/dts/infinity2m-ssc011a-s01a-padmux-rgb565-rmii-doublenet.dtsi
<PAD_GPIO8         PINMUX_FOR_SPI0_MODE_5        MDRV_PUSE_SPI0_CZ>,
<PAD_GPIO9         PINMUX_FOR_SPI0_MODE_5        MDRV_PUSE_SPI0_CK >,
<PAD_GPIO10        PINMUX_FOR_SPI0_MODE_5        MDRV_PUSE_SPI0_DI >,
<PAD_GPIO11        PINMUX_FOR_SPI0_MODE_5        MDRV_PUSE_SPI0_DO >,

这里由于默认已经设置为SPI_MODE,因此只需要保证不被配置为其他功能即可。最后加载MSPI驱动:

# cd kernel && ARCH=arm make menuconfig

配置完后,保存到默认配置中:

# cp .config ./arch/arm/configs/infinity2m_spinand_ssc011a_s01a_minigui_doublenet_defconfig -f

编译后,查看spi节点

# ls /dev/spi*

spi节点已经出来了。

使用spi_test.c做回环(短接MISO和MOSI)测试。

短接GPIO10–GPIO11

编译spi_test.c得到spi_test,将spi_test拷贝到开发板并执行。

# ./spi_test


spi测试ok

spi_test.c源码

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <strings.h>
#include <string.h>
#include "../../project/kbuild/4.9.84/i2m/include/uapi/linux/spi/spidev.h"


static const char *device = "/dev/spidev0.0";
static uint8_t mode = 0; /* SPI 通信使用全双工,设置 CPOL=0,CPHA=0。 */
static uint8_t bits = 8; /* 8bits读写,MSB first。*/
static uint32_t speed = 12*1000*1000;/* 设置传输速度 */
static uint16_t delay = 0;
static int g_SPI_Fd = 0;

#define SPI_DEBUG 1

static void pabort(const char *s)
{
    perror(s);
    abort();
}

int SPI_Transfer(const uint8_t *TxBuf, uint8_t *RxBuf, int len)
{
    int ret;
    int fd = g_SPI_Fd;
    struct spi_ioc_transfer tr ={
        .tx_buf = (unsigned long) TxBuf,
        .rx_buf = (unsigned long) RxBuf,
        .len =len,
        .delay_usecs = delay,
    };
    ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
    if (ret < 1)
        perror("can't send spi message\n");
    else
    {
#if SPI_DEBUG
        int i;
        printf("nsend spi message Succeed\n");
        printf("nSPI Send [Len:%d]: \n", len);
        for (i = 0; i < len; i++)
        {
            if (i % 8 == 0)
                printf("nt\n");
            printf("0x%02X \n", TxBuf[i]);
        }
        printf("n");
        printf("SPI Receive [len:%d]:\n", len);
        for (i = 0; i < len; i++)
        {
            if (i % 8 == 0)
                printf("nt\n");
            printf("0x%02X \n", RxBuf[i]);
        }
#endif
    }
    return ret;
}

int SPI_Write(uint8_t *TxBuf, int len)
{
    int ret;
    int fd = g_SPI_Fd;
    ret = write(fd, TxBuf, len);
    if (ret < 0)
        perror("SPI Write error\n");
    else
    {
#if SPI_DEBUG
        int i;
        printf("SPI Write [Len:%d]: \n", len);
        for (i = 0; i < len; i++)
        {
            if (i % 8 == 0)
                printf("\n\t");
            printf("0x%02X \n", TxBuf[i]);
        }
        printf("\n");
#endif
    }
    return ret;
}

int SPI_Read(uint8_t *RxBuf, int len)
{
    int ret;
    int fd = g_SPI_Fd;
    ret = read(fd, RxBuf, len);
    if (ret < 0)
        printf("SPI Read error\n");
    else
    {
#if SPI_DEBUG
        int i;
        printf("SPI Read [len:%d]:\n", len);
        for (i = 0; i < len; i++)
        {
            if (i % 8 == 0)
                printf("\n\t");
            printf("0x%02X \n", RxBuf[i]);
        }
        printf("\n");
#endif
    }
    return ret;
}

int SPI_Open(void)
{
    int fd;
    int ret = 0;
    if (g_SPI_Fd != 0) /* 设备已打开 */
        return 0xF1;
    fd = open(device, O_RDWR);
    if (fd < 0)
        pabort("can't open device\n");
    else
        printf("SPI - Open Succeed. Start Init SPI...\n");
    g_SPI_Fd = fd;

    ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
    if (ret == -1)
        pabort("can't set spi mode\n");
    ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
    if (ret == -1)
        pabort("can't get spi mode\n");
    /*
     * bits per word
     */
    ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
    if (ret == -1)
        pabort("can't set bits per word\n");
    ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
    if (ret == -1)
        pabort("can't get bits per word\n");
    /*
     * max speed hz
     */
    ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
    if (ret == -1)
        pabort("can't set max speed hz\n");
    ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
    if (ret == -1)
        pabort("can't get max speed hz\n");
    printf("spi mode: %d\n", mode);
    printf("bits per word: %d\n", bits);
    printf("max speed: %d KHz (%d MHz)\n", speed / 1000, speed / 1000 / 1000);
    return ret;
}

int SPI_Close(void)
{
    int fd = g_SPI_Fd;
    if (fd == 0) /* SPI 是否已经打开*/
        return 0;
    close(fd);
    g_SPI_Fd = 0;
    return 0;
}

int SPI_LookBackTest(void)
{
    int ret, i;
    const int BufSize = 16;
    uint8_t tx[BufSize], rx[BufSize];
    bzero(rx, sizeof(rx));
    for (i = 0; i < BufSize; i++)
        tx[i] = i;
    printf("nSPI - LookBack Mode Test...\n");
    ret = SPI_Transfer(tx, rx, BufSize);
    if (ret > 1)
    {
        ret = memcmp(tx, rx, BufSize);
        if (ret != 0)
        {
            printf("tx:\n");
            for (i = 0; i < BufSize; i++)
            {
                printf("%d ", tx[i]);
            }
            printf("\n");
            printf("rx:\n");
            for (i = 0; i < BufSize; i++)
            {
                printf("%d ", rx[i]);
            }
            printf("\n");
            perror("LookBack Mode Test error\n");
        }
        else
            printf("SPI - LookBack Mode OK\n");
    }
    return ret;
}


int main(void)
{
    int ret;

    ret = SPI_Open();
    printf("************************* ret = %d***********************\n", ret);

    //unsigned char buf[3] = {0xf3, 0x76, 0x59};
    //SPI_Write(buf, 3);

    SPI_LookBackTest();

    SPI_Close();

    return 0;
}

文档更新时间: 2022-04-22 10:19   作者:Aeeditor