|
发表于 2022-6-20 16:26:18
浏览:5073
|
回复:3
打印
只看该作者
[复制链接]
楼主
SPI用户层操作
spidev.c是linux为用户写的spi驱动及接口,下面以ITX-3588J与XM25QU128C为例,讲一下如何使用spidev
sdk: firefly_rk3588_android12.0_git_20220311
在kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588-firefly-itx-3588j.dtsi配置节点信息
- &spi1{
- status = "okay";
- pinctrl-0 = <&spi1m2_cs0 &spi1m2_pins>;
- num-cs = <1>;
- max-freq = <50000000>;
- spidev1: spidev@00{
- compatible = "rockchip,spidev";
- status = "okay";
- reg = <0x0>;
- spi-max-frequency = <1000000>;
- };
- };
复制代码 同时在`kernel-5.10/drivers/spi/spidev.c`中添加节点信息
- static const struct of_device_id spidev_dt_ids[] = {
- { .compatible = "rockchip,spidev" },
- {},
- };
复制代码 系统运行起来后会在`/dev/`目录下生成名为`spidev1.0`的字符设备,该设备可以用open、close、write、read、ioctl去操作。
一次读写大小测试
spidev 一次可读写4096个字节
测试程序: - char buf_t1[5000] = {};
- char buf_r1[5000] = {};
- for (int i = 0; i < 5000; i++)
- buf_t1[i] = 0xff;
- printf("--------------------------------读写大小测试-----------------------------------\n");
- printf("开始写入数据\n");
- printf("写入4906字节数据\n");
- ret = write(fd, buf_t1, 4096);
- printf("buf_t1 write %d byte\n", ret);
- printf("写入4097字节数据\n");
- ret = write(fd, buf_t1, 4097);
- printf("buf_t1 write %d byte\n", ret);
- printf("开始读取数据\n");
- printf("读取4096字节数据\n");
- ret = read(fd, buf_r1, 4096);
- printf("buf_r2 read %d byte\n", ret);
- printf("读取4097字节数据\n");
- ret = read(fd, buf_r1, 4097);
- printf("buf_r2 read %d byte\n", ret);
复制代码 测试结果
- --------------------------------读写大小测试-----------------------------------
- 开始写入数据
- 写入4906字节数据
- buf_t1 write 4096 byte
- 写入4097字节数据
- buf_t1 write -1 byte
- 开始读取数据
- 读取4096字节数据
- buf_r2 read 4096 byte
- 读取4097字节数据
- buf_r2 read -1 byte
复制代码
连续读写测试
read和write是单独的操作
测试程序:
- printf("-------------------------------连续读写测试-----------------------------------\n");
- printf("使用普通读写\n");
- write(fd, buf_t, 1);
- read(fd, buf_r, 4);
- printf("xm25qu128c id : %x %x %x %x \n", buf_r[0], buf_r[1], buf_r[2], buf_r[3]);
- printf("使用复杂读写\n");
- read_xm25qu128c_id();
复制代码- int read_xm25qu128c_id(void)
- {
- int ret = ioctl(fd, SPI_IOC_MESSAGE(1), &xfer);
- if (ret < 0)
- {
- printf("error in spi_exchange(): ioctl(SPI_IOC_MESSAGE(1)) return %d \n", ret);
- return -1;
- }
- printf("xm25qu128c flash id : %x %x %x %x \n", buf_r[0], buf_r[1], buf_r[2], buf_r[3]);
- memset(buf_r, 0, 4);
- return 0;
- }
复制代码 测试结果
- -------------------------------连续读写测试-----------------------------------
- 使用普通读写
- xm25qu128c id : ff ff ff ff
- 使用复杂读写
- xm25qu128c flash id : ff 20 41 18
复制代码 通过示波器进行测量
发现普通读写流程如下
片选线拉低->write->片选线拉高->片选线拉低->read->片选线拉高
使用复杂读写流程如下
mosi: ---- 0x9f ---- ---- ---- ----
miso: ---- 0xff 0x20 0x41 0x18 ----
cs: 高电平 低电平-------------------------- 高电平
spi模式设置
使用ioctl可以设置spi模式
`SPI_IOC_RD_MODE`读取模式
`SPI_IOC_WR_MODE`设置模式
测试程序:
- printf("--------------------------------模式测试-----------------------------------\n");
- ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
- printf("ioctl(fd, SPI_IOC_RD_MODE , &mode) 第一次读取模式 return %d(-1则ioctl失败) ,mode:%d\n", ret, mode & (SPI_CPOL | SPI_CPHA));
- read_xm25qu128c_id();
- mode = 0;
- mode = mode | (0x00 & SPI_CPOL) | (0xff & SPI_CPHA);
- ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
- printf("设置模式1 return %d(-1则ioctl失败) \n", ret);
- ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
- printf("ioctl(fd, SPI_IOC_RD_MODE , &mode) 第二次读取模式 return %d(-1则ioctl失败) ,mode:%d\n", ret, mode & (SPI_CPOL | SPI_CPHA));
- read_xm25qu128c_id();
- mode = 0;
- mode = mode | (0xff & SPI_CPOL) | (0x00 & SPI_CPHA);
- ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
- printf("设置模式2 return %d(-1则ioctl失败) \n", ret);
- ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
- printf("ioctl(fd, SPI_IOC_RD_MODE , &mode) 第三次读取模式 return %d(-1则ioctl失败) ,mode:%d\n", ret, mode & (SPI_CPOL | SPI_CPHA));
- read_xm25qu128c_id();
- mode = 0;
- mode = mode | (0xff & SPI_CPOL) | (0xff & SPI_CPHA);
- ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
- printf("设置模式3 return %d(-1则ioctl失败) \n", ret);
- ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
- printf("ioctl(fd, SPI_IOC_RD_MODE , &mode) 第四次读取模式 return %d(-1则ioctl失败) ,mode:%d\n", ret, mode & (SPI_CPOL | SPI_CPHA));
- read_xm25qu128c_id();
- mode = 0;
- mode = mode | (0x00 & SPI_CPOL) | (0x00 & SPI_CPHA);
- ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
- printf("设置模式0 return %d(-1则ioctl失败) \n", ret);
- ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
- printf("ioctl(fd, SPI_IOC_RD_MODE , &mode) 第五次读取模式 return %d(-1则ioctl失败) ,mode:%d\n", ret, mode & (SPI_CPOL | SPI_CPHA));
- read_xm25qu128c_id();
复制代码 测试结果
- --------------------------------模式测试-----------------------------------
- ioctl(fd, SPI_IOC_RD_MODE , &mode) 第一次读取模式 return 0(-1则ioctl失败) ,mode:0
- xm25qu128c flash id : ff 20 41 18
- 设置模式1 return 0(-1则ioctl失败)
- ioctl(fd, SPI_IOC_RD_MODE , &mode) 第二次读取模式 return 0(-1则ioctl失败) ,mode:1
- xm25qu128c flash id : ff ff ff ff
- 设置模式2 return 0(-1则ioctl失败)
- ioctl(fd, SPI_IOC_RD_MODE , &mode) 第三次读取模式 return 0(-1则ioctl失败) ,mode:2
- xm25qu128c flash id : ff 90 20 8c
- 设置模式3 return 0(-1则ioctl失败)
- ioctl(fd, SPI_IOC_RD_MODE , &mode) 第嬡读取模式 return 0(-1则ioctl失败) ,mode:3
- xm25qu128c flash id : ff 20 41 18
- 设置模式0 return 0(-1则ioctl失败)
- ioctl(fd, SPI_IOC_RD_MODE , &mode) 第五次读取模式 return 0(-1则ioctl失败) ,mode:0
- xm25qu128c flash id : ff 20 41 18
复制代码 可以看出xm25qu128c支持模式0、3
设置spi通信速率
使用ioctl可以设置spi速率
`SPI_IOC_RD_MAX_SPEED_HZ`读取速率
`SPI_IOC_WR_MAX_SPEED_HZ`设置速率
测试程序:
- printf("--------------------------------频率测试-----------------------------------\n");
- int max_speed_hz;
- ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &max_speed_hz);
- printf("ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ , &max_speed_hz) 第一次读取频率 return %d (-1则ioctl失败), speed:%d Hz\n", ret, max_speed_hz);
- max_speed_hz = 33000000;
- ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &max_speed_hz);
- printf("设置频率为33MHz return %d (-1则ioctl失败)\n", ret);
- ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &max_speed_hz);
- printf("ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ , &max_speed_hz) 第二次读取频率 return %d (-1则ioctl失败), speed:%d Hz\n", ret, max_speed_hz);
- max_speed_hz = 50000000;
- ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &max_speed_hz);
- printf("设置频率为50MHz return %d (-1则ioctl失败)\n", ret);
- ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &max_speed_hz);
- printf("ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ , &max_speed_hz) 第三次读取频率 return %d (-1则ioctl失败), speed:%d Hz\n", ret, max_speed_hz);
复制代码 测试结果
- --------------------------------频率测试-----------------------------------
- ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ , &max_speed_hz) 第一次读取频率 return 0 (-1则ioctl失败), speed:1000000 Hz
- 设置频率为33MHz return 0 (-1则ioctl失败)
- ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ , &max_speed_hz) 第二次读取频率 return 0 (-1则ioctl失败), speed:33000000 Hz
- 设置频率为50MHz return 0 (-1则ioctl失败)
- ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ , &max_speed_hz) 第三次读取频率 return 0 (-1则ioctl失败), speed:50000000 Hz
复制代码
设置spi数据高/低位先出
使用ioctl可以设置spi数据高/低位先出
`SPI_IOC_RD_LSB_FIRST`读取是否低位先出,是返回1,不是返回0
`SPI_IOC_WR_LSB_FIRST`设置是否低位先出,是写1,不是写0
测试程序:
- ret = ioctl(fd, SPI_IOC_RD_LSB_FIRST, &mode);
- printf("ioctl(fd, SPI_IOC_RD_LSB_FIRST , &mode) 第一次读取是否低位先出 1:LSB 0:MSB return %d(-1则ioctl失败),LSB/MSB: %d\n", ret, mode );
- read_xm25qu128c_id();
- mode = 1;
- ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &mode);
- printf("设置低位先出 return %d (-1则ioctl失败)\n", ret);
- ret = ioctl(fd, SPI_IOC_RD_LSB_FIRST, &mode);
- printf("ioctl(fd, SPI_IOC_RD_LSB_FIRST , &mode) 第二次读取是否低位先出 1:LSB 0:MSB return %d(-1则ioctl失败),LSB/MSB: %d\n", ret, mode );
- read_xm25qu128c_id();
- mode = 0;
- ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &mode);
- printf("设置高位先出 return %d (-1则ioctl失败)\n", ret);
- ret = ioctl(fd, SPI_IOC_RD_LSB_FIRST, &mode);
- printf("ioctl(fd, SPI_IOC_RD_LSB_FIRST , &mode) 第三次读取是否低位先出 1:LSB 0:MSB return %d(-1则ioctl失败),LSB/MSB: %d\n", ret, mode );
- read_xm25qu128c_id();
复制代码 测试结果
- --------------------------------高低位数据先出测试-----------------------------------
- ioctl(fd, SPI_IOC_RD_LSB_FIRST , &mode) 第一次读取是否低位先出 1:LSB 0:MSB return 0(-1则ioctl失败),LSB/MSB: 0
- xm25qu128c flash id : ff 20 41 18
- 设置低位先出 return 0 (-1则ioctl失败)
- ioctl(fd, SPI_IOC_RD_LSB_FIRST , &mode) 第二次读取是否低位先出 1:LSB 0:MSB return 0(-1则ioctl失败),LSB/MSB: 1
- xm25qu128c flash id : ff ff ff ff
- 设置高位先出 return 0 (-1则ioctl失败)
- ioctl(fd, SPI_IOC_RD_LSB_FIRST , &mode) 第三次读取是否低位先出 1:LSB 0:MSB return 0(-1则ioctl失败),LSB/MSB: 0
- xm25qu128c flash id : ff 20 41 18
复制代码
|
-
-
xm25x.c
6.06 KB, 下载次数: 17, 下载积分: 灯泡 -1 , 经验 -1
spidev测试程序
|