一、spi管脚定义的查找

1、硬件的连接

2、根据硬件的连接从芯片手册中查找管脚的定义

根据控制寄存器跳转到相应的管脚定义,查看管脚的复用功能

二、设备树修改

在dra7.dtsi中添加spi的设备地址

mcspi2: spi@4809a000 {
            compatible = "ti,omap4-mcspi";
            reg = <0x4809a000 0x200>;
            interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
            #address-cells = <1>;
            #size-cells = <0>;
            ti,hwmods = "mcspi2";
            ti,spi-num-cs = <2>;
            dmas = <&sdma_xbar 43>,
                   <&sdma_xbar 44>,
                   <&sdma_xbar 45>,
                   <&sdma_xbar 46>;
            dma-names = "tx0", "rx0", "tx1", "rx1";
            status = "disabled";
        };

在am57xx-beagle-x15-common.dtsi 和am57xx-evm-common.dtsi中对spi端口进行描述,理论是在某一个文件描述即可,这里没太多验证,两个都添加了

&mcspi2 {
        status = "okay";
        pinctrl-names = "default";
        pinctrl-0 = <&spi2_pins>;
    spidev0:spi@0 {
        compatible = "spidev";
        reg = <0>;            //  CS0 
        spi-max-frequency = <4000000>;
    };
};

spi2_pins: spi2_pins {
        pinctrl-single,pins = <
            DRA7XX_CORE_IOPAD(0x37c0, (INPUT_EN | MUX_MODE0))          /* spi2_sclk.spi2_sclk (A26) */
            DRA7XX_CORE_IOPAD(0x37c4, (INPUT_EN | MUX_MODE0))          /* spi2_d1.spi2_d1 (B22) */
            DRA7XX_CORE_IOPAD(0x37c8, (INPUT_EN | MUX_MODE0))          /* spi2_d0.spi2_d0 (G17) */
            DRA7XX_CORE_IOPAD(0x37cc, (PIN_OUTPUT_PULLUP | MUX_MODE0)) /* spi2_cs0.spi2_cs0 (B24) */
        >;
    };

然后编译设备树dtb文件和内核zImage

内核中选中spidev

Device Drivers --->
    [*] SPI support --->
        <*> User Mode SPI device driver support

三、测试应用程序 使用内存代码中的测试程序即可 路径Documentation/spi下的spidev_test.c

/*
 * SPI testing utility (using spidev driver)
 *
 * Copyright (c) 2007  MontaVista Software, Inc.
 * Copyright (c) 2007  Anton Vorontsov <avorontsov@ru.mvista.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License.
 *
 * Cross-compile with cross-gcc -I/path/to/cross-kernel/include
 */

#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

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

static const char *device = "/dev/spidev1.1";
static uint32_t mode;
static uint8_t bits = 8;
static uint32_t speed = 500000;
static uint16_t delay;
static int verbose;

uint8_t default_tx[] = {
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0x40, 0x00, 0x00, 0x00, 0x00, 0x95,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xF0, 0x0D,
};

uint8_t default_rx[ARRAY_SIZE(default_tx)] = {0, };
char *input_tx;

static void hex_dump(const void *src, size_t length, size_t line_size, char *prefix)
{
    int i = 0;
    const unsigned char *address = src;
    const unsigned char *line = address;
    unsigned char c;

printf("%s | ", prefix);
    while (length-- > 0) {
        printf("%02X ", *address++);
        if (!(++i % line_size) || (length == 0 && i % line_size)) {
            if (length == 0) {
                while (i++ % line_size)
                    printf("__ ");
            }
            printf(" | ");  /* right close */
            while (line < address) {
                c = *line++;
                printf("%c", (c < 33 || c == 255) ? 0x2E : c);
            }
            printf("\n");
            if (length > 0)
                printf("%s | ", prefix);
        }
    }
}

/*
 *  Unescape - process hexadecimal escape character
 *      converts shell input "\x23" -> 0x23
 */
static int unescape(char *_dst, char *_src, size_t len)
{
    int ret = 0;
    char *src = _src;
    char *dst = _dst;
    unsigned int ch;

while (*src) {
        if (*src == '\\' && *(src+1) == 'x') {
            sscanf(src + 2, "%2x", &ch);
            src += 4;
            *dst++ = (unsigned char)ch;
        } else {
            *dst++ = *src++;
        }
        ret++;
    }
    return ret;
}

static void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len)
{
    int ret;

struct spi_ioc_transfer tr = {
        .tx_buf = (unsigned long)tx,
        .rx_buf = (unsigned long)rx,
        .len = len,
        .delay_usecs = delay,
        .speed_hz = speed,
        .bits_per_word = bits,
    };

if (mode & SPI_TX_QUAD)
        tr.tx_nbits = 4;
    else if (mode & SPI_TX_DUAL)
        tr.tx_nbits = 2;
    if (mode & SPI_RX_QUAD)
        tr.rx_nbits = 4;
    else if (mode & SPI_RX_DUAL)
        tr.rx_nbits = 2;
    if (!(mode & SPI_LOOP)) {
        if (mode & (SPI_TX_QUAD | SPI_TX_DUAL))
            tr.rx_buf = 0;
        else if (mode & (SPI_RX_QUAD | SPI_RX_DUAL))
            tr.tx_buf = 0;
    }

ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
    if (ret < 1)
        pabort("can't send spi message");

if (verbose)
        hex_dump(tx, len, 32, "TX");
    hex_dump(rx, len, 32, "RX");
}

static void print_usage(const char *prog)
{
    printf("Usage: %s [-DsbdlHOLC3]\n", prog);
    puts("  -D --device   device to use (default /dev/spidev1.1)\n"
         "  -s --speed    max speed (Hz)\n"
         "  -d --delay    delay (usec)\n"
         "  -b --bpw      bits per word \n"
         "  -l --loop     loopback\n"
         "  -H --cpha     clock phase\n"
         "  -O --cpol     clock polarity\n"
         "  -L --lsb      least significant bit first\n"
         "  -C --cs-high  chip select active high\n"
         "  -3 --3wire    SI/SO signals shared\n"
         "  -v --verbose  Verbose (show tx buffer)\n"
         "  -p            Send data (e.g. \"1234\\xde\\xad\")\n"
         "  -N --no-cs    no chip select\n"
         "  -R --ready    slave pulls low to pause\n"
         "  -2 --dual     dual transfer\n"
         "  -4 --quad     quad transfer\n");
    exit(1);
}

static void parse_opts(int argc, char *argv[])
{
    while (1) {
        static const struct option lopts[] = {
            { "device",  1, 0, 'D' },
            { "speed",   1, 0, 's' },
            { "delay",   1, 0, 'd' },
            { "bpw",     1, 0, 'b' },
            { "loop",    0, 0, 'l' },
            { "cpha",    0, 0, 'H' },
            { "cpol",    0, 0, 'O' },
            { "lsb",     0, 0, 'L' },
            { "cs-high", 0, 0, 'C' },
            { "3wire",   0, 0, '3' },
            { "no-cs",   0, 0, 'N' },
            { "ready",   0, 0, 'R' },
            { "dual",    0, 0, '2' },
            { "verbose", 0, 0, 'v' },
            { "quad",    0, 0, '4' },
            { NULL, 0, 0, 0 },
        };
        int c;

c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR24p:v", lopts, NULL);

if (c == -1)
            break;

switch (c) {
        case 'D':
            device = optarg;
            break;
        case 's':
            speed = atoi(optarg);
            break;
        case 'd':
            delay = atoi(optarg);
            break;
        case 'b':
            bits = atoi(optarg);
            break;
        case 'l':
            mode |= SPI_LOOP;
            break;
        case 'H':
            mode |= SPI_CPHA;
            break;
        case 'O':
            mode |= SPI_CPOL;
            break;
        case 'L':
            mode |= SPI_LSB_FIRST;
            break;
        case 'C':
            mode |= SPI_CS_HIGH;
            break;
        case '3':
            mode |= SPI_3WIRE;
            break;
        case 'N':
            mode |= SPI_NO_CS;
            break;
        case 'v':
            verbose = 1;
            break;
        case 'R':
            mode |= SPI_READY;
            break;
        case 'p':
            input_tx = optarg;
            break;
        case '2':
            mode |= SPI_TX_DUAL;
            break;
        case '4':
            mode |= SPI_TX_QUAD;
            break;
        default:
            print_usage(argv[0]);
            break;
        }
    }
    if (mode & SPI_LOOP) {
        if (mode & SPI_TX_DUAL)
            mode |= SPI_RX_DUAL;
        if (mode & SPI_TX_QUAD)
            mode |= SPI_RX_QUAD;
    }
}

int main(int argc, char *argv[])
{
    int ret = 0;
    int fd;
    uint8_t *tx;
    uint8_t *rx;
    int size;

parse_opts(argc, argv);

fd = open(device, O_RDWR);
    if (fd < 0)
        pabort("can't open device");

/*
     * spi mode
     */
    ret = ioctl(fd, SPI_IOC_WR_MODE32, &mode);
    if (ret == -1)
        pabort("can't set spi mode");

ret = ioctl(fd, SPI_IOC_RD_MODE32, &mode);
    if (ret == -1)
        pabort("can't get spi mode");

/*
     * bits per word
     */
    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");

/*
     * max speed hz
     */
    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: 0x%x\n", mode);
    printf("bits per word: %d\n", bits);
    printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);

if (input_tx) {
        size = strlen(input_tx+1);
        tx = malloc(size);
        rx = malloc(size);
        size = unescape((char *)tx, input_tx, size);
        transfer(fd, tx, rx, size);
        free(rx);
        free(tx);
    } else {
        transfer(fd, default_tx, default_rx, sizeof(default_tx));
    }

close(fd);

return ret;
}

四、测试方法

将D0与D1短接

在 /dev下查看到spidev1.0设备

然后在系统终端输入spidev_test -D /dev/spidev1.0

AM5728 arm端 spi调试 设备树方式相关推荐

  1. A40i使用笔记:GPIO操作方式(用于测试设备io驱动性能)(传统方式、设备树方式、寄存器方式操作GPIO)

    一.前言 前文介绍了文件io的驱动方式,可以用于led点灯灭灯或者一些简单的不需求时序控制的ic操作,但是用于功能类ic,如AD采集芯片等时序控制需求高的,就不行了,这时候就需求高速io去实现指定的芯 ...

  2. TI AM5728 SDK升级之 linux设备树解析,以网口cpsw为例

    如果一个结点描述的设备有地址,则应该给出@unit-address.多个相同类型设备结点的name可以一样,只要unit-address不同即可,如本例中含有cpu@0.cpu@1以及serial@1 ...

  3. 【ZYNQ实战】利用AXI Quad SPI快速打通Linux至PL端SPI从设备

    关注.星标嵌入式客栈,精彩及时送达 [导读] 前面写过篇介绍ZYNQ基本情况的文章,今天来肝一篇实战文章介绍AXI quad SPI 使用方法,如果你正使用ZYNQ的这个IP,希望对你有所帮助. 初识 ...

  4. linux3.x 驱动程序,Arm Linux3.x的设备树 - 龙芯开源社区

    1. ARM Device Tree起源 Linus Torvalds在2011年3月17日的ARM Linux邮件列表宣称"this whole ARM thing is a f*ckin ...

  5. 2021-06-22 hi3516ev200 按键输入 gpio_key input 驱动 device tree 设备树方式

    Linux device tree 基础知识不补充,自行查找...... root@yex-Ubuntu:/home/work/hiSDK/hi3516ev200/hi3516/linux-4.9.y ...

  6. ARM Linux设备树

    1.ARM设备树起源 在过去的ARM Linux中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥着大量的垃圾代码,很多代码只是在描述板级细节,而这些板级细节对于内核来讲 ...

  7. SPI设备树处理过程

    一.spi_device结构体 /*** struct spi_device - Controller side proxy for an SPI slave device* @dev: Driver ...

  8. 【正点原子MP157连载】第二十三章 Linux设备树-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7

    1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...

  9. imx6平台设备树详解

    设备树详解 在Linux3.x版本后,arch/arm/plat-xxx和arch/arm/mach-xxx中,描述板级细节的代码(比如platform_device.i2c_board_info等) ...

最新文章

  1. 用意念就能控制的操作系统?这家华人团队做的脑机接口,3个电极实现脑波成像...
  2. Java时间操作工具类
  3. C#人爱学不学9[C#5.0异步实例+WPF自己的MVVM Async应用 1/12]
  4. 你竟然没用 Nuget 构建项目?
  5. 论文浅尝 | 基于知识图谱中图卷积神经网络的推荐系统
  6. Android 学习心得(2)——Android内置数据库SQLite
  7. 怎样在word文档画虚线_班级工作小技巧——怎样在word里画出美观正式的四线三格?...
  8. [翻译].NET委托:一个C#睡前故事 [转]
  9. LNMP环境下搭建wordpress
  10. win10下安装SQLServer2005
  11. 怎么关闭计算机139端口,win10系统关闭139端口的处理教程
  12. 怎么用dos系统进入服务器,进入纯DOS系统的步骤分享
  13. jpg图片转换成pdf文件,方法步骤
  14. 我们该如何设计数据库:“普通——文艺——二逼”的区别
  15. HTTP 请求头中的 Remote_Addr,X-Forwarded-For,X-Real-IP | Spring Cloud 13
  16. linux kernel —— kernel.ko 移至 kernel.ko.xz
  17. [HDU 3234] Exclusive-OR
  18. 电视音频输出怎么连接数字功放机
  19. 图像效果评估学习----图像基础知识(一)
  20. 数字电路基础与Quartus-II入门

热门文章

  1. 最牛的远程开发来了!不用配置向日葵,直接上车vscode Remote Tunnels,轻松实现跨网远程,局域网穿透
  2. linux系统英伟达gpu驱动卸载_在Linux系统中卸载手动安装的Nvidia驱动程序
  3. 电商项目之电商数据库建表
  4. 北斗中小渔船安全动态监控信息解决方案
  5. 4.1.2 计算机网络之(电路交换、报文交换、分组交换--数据报--虚电路)
  6. CS61A Proj 2
  7. Matlab实现频域滤波——二维傅里叶变换、低通、高通
  8. Blinker 天气时钟 esp8266+SH1106 OLCD屏显示
  9. 施耐德电气:以服务和数字化推动可持续落地
  10. HyperDock优化Mac的Dock栏