AM5728 arm端 spi调试 设备树方式
一、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调试 设备树方式相关推荐
- A40i使用笔记:GPIO操作方式(用于测试设备io驱动性能)(传统方式、设备树方式、寄存器方式操作GPIO)
一.前言 前文介绍了文件io的驱动方式,可以用于led点灯灭灯或者一些简单的不需求时序控制的ic操作,但是用于功能类ic,如AD采集芯片等时序控制需求高的,就不行了,这时候就需求高速io去实现指定的芯 ...
- TI AM5728 SDK升级之 linux设备树解析,以网口cpsw为例
如果一个结点描述的设备有地址,则应该给出@unit-address.多个相同类型设备结点的name可以一样,只要unit-address不同即可,如本例中含有cpu@0.cpu@1以及serial@1 ...
- 【ZYNQ实战】利用AXI Quad SPI快速打通Linux至PL端SPI从设备
关注.星标嵌入式客栈,精彩及时送达 [导读] 前面写过篇介绍ZYNQ基本情况的文章,今天来肝一篇实战文章介绍AXI quad SPI 使用方法,如果你正使用ZYNQ的这个IP,希望对你有所帮助. 初识 ...
- linux3.x 驱动程序,Arm Linux3.x的设备树 - 龙芯开源社区
1. ARM Device Tree起源 Linus Torvalds在2011年3月17日的ARM Linux邮件列表宣称"this whole ARM thing is a f*ckin ...
- 2021-06-22 hi3516ev200 按键输入 gpio_key input 驱动 device tree 设备树方式
Linux device tree 基础知识不补充,自行查找...... root@yex-Ubuntu:/home/work/hiSDK/hi3516ev200/hi3516/linux-4.9.y ...
- ARM Linux设备树
1.ARM设备树起源 在过去的ARM Linux中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥着大量的垃圾代码,很多代码只是在描述板级细节,而这些板级细节对于内核来讲 ...
- SPI设备树处理过程
一.spi_device结构体 /*** struct spi_device - Controller side proxy for an SPI slave device* @dev: Driver ...
- 【正点原子MP157连载】第二十三章 Linux设备树-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7
1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...
- imx6平台设备树详解
设备树详解 在Linux3.x版本后,arch/arm/plat-xxx和arch/arm/mach-xxx中,描述板级细节的代码(比如platform_device.i2c_board_info等) ...
最新文章
- 用意念就能控制的操作系统?这家华人团队做的脑机接口,3个电极实现脑波成像...
- Java时间操作工具类
- C#人爱学不学9[C#5.0异步实例+WPF自己的MVVM Async应用 1/12]
- 你竟然没用 Nuget 构建项目?
- 论文浅尝 | 基于知识图谱中图卷积神经网络的推荐系统
- Android 学习心得(2)——Android内置数据库SQLite
- 怎样在word文档画虚线_班级工作小技巧——怎样在word里画出美观正式的四线三格?...
- [翻译].NET委托:一个C#睡前故事 [转]
- LNMP环境下搭建wordpress
- win10下安装SQLServer2005
- 怎么关闭计算机139端口,win10系统关闭139端口的处理教程
- 怎么用dos系统进入服务器,进入纯DOS系统的步骤分享
- jpg图片转换成pdf文件,方法步骤
- 我们该如何设计数据库:“普通——文艺——二逼”的区别
- HTTP 请求头中的 Remote_Addr,X-Forwarded-For,X-Real-IP | Spring Cloud 13
- linux kernel —— kernel.ko 移至 kernel.ko.xz
- [HDU 3234] Exclusive-OR
- 电视音频输出怎么连接数字功放机
- 图像效果评估学习----图像基础知识(一)
- 数字电路基础与Quartus-II入门
热门文章
- 最牛的远程开发来了!不用配置向日葵,直接上车vscode Remote Tunnels,轻松实现跨网远程,局域网穿透
- linux系统英伟达gpu驱动卸载_在Linux系统中卸载手动安装的Nvidia驱动程序
- 电商项目之电商数据库建表
- 北斗中小渔船安全动态监控信息解决方案
- 4.1.2 计算机网络之(电路交换、报文交换、分组交换--数据报--虚电路)
- CS61A Proj 2
- Matlab实现频域滤波——二维傅里叶变换、低通、高通
- Blinker 天气时钟 esp8266+SH1106 OLCD屏显示
- 施耐德电气:以服务和数字化推动可持续落地
- HyperDock优化Mac的Dock栏