最近搞了一个NVIDIA tx2上的spi接口控制电机的东西,被搞了好几天写下一点心得,下面是jetson4.3以下版本的spi接口使用方法,NVIDIA jetson4.3以上版本做了优化,本身就带有/dev/spidev*.0,不需要做什么工作,直接使用sudo /opt/nvidia/jetson-io/jetson-io.py启用引脚使能就可以了。
NVIDIA tx2 jetson4.2 中的添加spi:
内核构建SPIDev模块:
配置内核
编辑tegra18_defconfig文件:
$ cd /usr/src
$ cd /kernel/kernel-4.4/
$ cd /arch/arm64/configs/
$ sudo gedit tegra18_defconfig
在下面添加以下内容 CONFIG_SPI_TEGRA114_SPI=y
CONFIG_SPI=y
CONFIG_SPI_TEGRA114=y
CONFIG_SPI_SPIDEV=m
CONFIG_QSPI_TEGRA186=y
构建内核
.conf更改为后生成新文件tegra18_defconfig
$ cd ~/buildJetsonTX2Kernel
$ sudo ./makeKernel.sh
确保将SPIDev内核模块复制到 /lib/modules
$ sudo cp /usr/src/kernel/kernel-4.4/drivers/spi/spidev.ko /lib/modules/$(uname -r)/kernel/drivers/
更新模块依赖性和内核映像:
$ sudo depmod
$ sudo ./copyImage.sh
重新启动到新配置:
$ sudo reboot
验证SPIDev模块
要验证启用了我们构建的SPIDev内核模块,请导航至 /lib/modules/$(uname -r)
$ cd /lib/modules/$(uname -r)
$ cat modules.dep
# print the contents of modules.dep to the screen, and ensure spidev.ko is in there
# e.g. @line 23
# kernel/drivers/spi/spidev.ko
修改设备树:
1,安装DTC工具
首先我们需要 device-tree-compiler
$sudo apt-get update
$sudo apt-get install device-tree-complier
2,反编译设备树
为了获得我们将要编辑的设备树源(DTS),首先我们需要将当前的设备树二进制(DTB)反编译回源:
$cd /boot/dtb/
$sudo dtc -I fs -O dts -o extract_proc.dts /proc/device-tree
3,更新设备树
使用您选择的文本编辑器更新我们上面反编译的DTS:
$sudo gedit extract_proc.dts
Or
$sudo vim extract_proc.dts
制作以下补丁:
spi@3240000{ //根据设备挂载的spi位置确定
compatible = "nvidia,tegra186-spi";
reg = <0x0 0x3240000 0x0 0x10000>;
....
....
....
linux,phandle = <0x80>;
spi@0 {
compatible = "spidev";
reg = <0x0>;
spi-max-frequency = <0x1312D00>;
nvidia,enable-hw-based-cs;
nvidia,cs-setup-clk-count = <0x1e>;
nvidia,cs-hold-clk-count = <0x1e>;
nvidia,rx-clk-tap-delay = <0x1f>;
nvidia,tx-clk-tap-delay = <0x0>;
};
};
4,重新编译设备树
再次使用DTC将修改后的DTS重新编译回新的DTB:
$ cd /boot/dtb/
$ sudo dtc -I dts -O dtb -o tegra186-quill-p3310-1000-c03-00-base.dtb extract_proc.dts
5,启用新的DTB
r28,r32版本必须通过以下命令更新dtb。(需要在本地电脑上进行烧录)
$sudo ./flash.sh -r -k kernel-dtb jetson-tx2 mmcblk0p1
重新启动以使更改生效:
$sudo reboot
6,验证SPIDev设备
要确认SPIDev模块已加载并创建了SPI设备,请检查/dev文件夹中是否有SPIdev :
$ls /dev/spi*
显示:
$/dev/spidev.3.0
7,修改Pinmux配置
启用SPI总线的最后一步是确保SoC上的接口引脚已正确配置为路由SPI信号。该信号路由由SoC上称为pinmux的功能控制。如果未正确配置pinmux,则驱动程序将加载,并且将能够在SoC上操作SPI控制器,但是SPI控制器将不会与外部SPI引脚电气连接。
启用了SPI4(SoC内部名称,外部称为SPI1)信号的R28.3之前的Nvidia L4T版本。从L4T 28.3开始,某些板卡和SoC配置的pinmux配置文件必须更新才能重新启用SPI4。
第一步:查找Pinmux配置文件
pinmux配置是引导加载程序的一部分,并且特定于SoC型号和载板。特定于主板和SoC的pinmux配置文件可在<L4T dir> / bootloader / t186ref / BCT / tegra186-mb1-bct-pinmux-*。cfg中找到。
第二步:验证正确的Pinmux设置
通常,此文件不应在适当位置进行编辑,而应使用SoC pinmux电子表格生成,并转换为pinavix配置(如Xavier此处所述),但是手动更新pinmux值可能是一个相对简单的过程。
Pinmux配置文件包含一系列寄存器偏移量和值。启用SPI4的正确偏移量和值是:
pinmux.0x02430038 = 0x00000401; # gpio_cam4_pn3: spi4, tristate-disable, input-disable
pinmux.0x02430040 = 0x00000455; # gpio_cam5_pn4: spi4, pull-down, tristate-enable, input-enable
pinmux.0x02430048 = 0x00000401; # gpio_cam6_pn5: spi4, tristate-disable, input-disable
pinmux.0x02430050 = 0x00000409; # gpio_cam7_pn6: spi4, pull-up, tristate-disable, input-disable
禁用SPI4的条目示例:
pinmux.0x02430038 = 0x00000445; # gpio_cam4_pn3: spi4, pull-down, tristate-disable, input-enable
pinmux.0x02430040 = 0x00000445; # gpio_cam5_pn4: spi4, pull-down, tristate-disable, input-enable
pinmux.0x02430048 = 0x00000445; # gpio_cam6_pn5: spi4, pull-down, tristate-disable, input-enable
pinmux.0x02430050 = 0x00000449; # gpio_cam7_pn6: spi4, pull-up, tristate-disable, input-enable
第三步:在芯片上更新Pinmux配置
如果需要更改pinmux配置文件,则需要将更新的配置写入目标,以便生效:
$ cd <L4T_dir>
$ sudo ./flash.sh jetson-tx2 mmcblk0p1
方法二:NVIDIA tx2 kernel中的设备树添加spi:
内核构建SPIDev模块:
1,配置内核
先获取NVIDIA tx2内核,到内核文件夹下
$cd public_sources/kernel/kernel-4.9
$./scripts/extract-ikconfig /boot/Image >> current_config
$vim current_config
CONFIG_SPI=y
CONFIG_SPI_TEGRA114=y
CONFIG_SPI_SPIDEV=m
CONFIG_QSPI_TEGRA186=y
$make menuconfig ARCH=arm64 config=current_config
Device Drivers ->
<*>SPI support ->
<*>User mode SPI device driver support
2,无需修改spidev.c文件
/*-------------------------------------------------------------------------*/
/* The main reason to have this class is to make mdev/udev create the
* /dev/spidevB.C character device nodes exposing our userspace API.
* It also simplifies memory management.
*/
static struct class *spidev_class;
#ifdef CONFIG_OF
static const struct of_device_id spidev_dt_ids[] = {
{ .compatible = "spidev" },
{ .compatible = "rohm,dh2228fv" },
{ .compatible = "lineartechnology,ltc2488" },
{},
};
MODULE_DEVICE_TABLE(of, spidev_dt_ids);
#endif
#ifdef CONFIG_ACPI
需要使能spi1引脚
在jetson4.3以上版本中,可以使用sudo /opt/nvidia/jetson/jetsin-io.py控制台打开spi引脚使能。之前的版本需要手动修改,在Linux_for_Tegra/bootloader/t186ref/BCT/中可以找到 *.cfg文件,修改其中spi
Tx2:
pinmux.0x02430038 = 0x00000445; # gpio_cam4_pn3: spi4, pull-down, tristate-disable, input-enable
pinmux.0x02430040 = 0x00000445; # gpio_cam5_pn4: spi4, pull-down, tristate-disable, input-enable
pinmux.0x02430048 = 0x00000445; # gpio_cam6_pn5: spi4, pull-down, tristate-disable, input-enable
pinmux.0x02430050 = 0x00000449; # gpio_cam7_pn6: spi4, pull-up, tristate-disable, input-enable
Agx:
pinmux.0x0243d040 = 0x00000400; # spi1_sck_pz3: rsvd1, pull-down, tristate-enable, input-enable, lpdr-disable
pinmux.0x0243d020 = 0x00000450; # spi1_miso_pz4: rsvd1, pull-down, tristate-enable, input-enable, lpdr-disable
pinmux.0x0243d058 = 0x00000400; # spi1_mosi_pz5: rsvd1, pull-down, tristate-enable, input-enable, lpdr-disable
pinmux.0x0243d010 = 0x00000400; # spi1_cs0_pz6: rsvd1, pull-up, tristate-enable, input-enable, lpdr-disable
pinmux.0x0243d050 = 0x00000400; # spi1_cs1_pz7: rsvd1, pull-up, tristate-enable, input-enable, lpdr-disable
使用命令烧录(会重刷内核,记得保存):
$sudo ./flash.sh jetson-tx2 mmcblk0p1
3,编译内核
使用make命令编译内核,注意编译环境,可以使用ARCH直接指定。
$make ARCH=arm64 config=current_config
$cd public_sources/kernel/kernel-4.9/arch/arm64/boot
$ls
dts Image Image.gz install.sh Makefile zImage
4,烧录内核
$sudo ./flash.sh -k kernel jetson-tx2 mmcblk0p1
修改设备树:
1,更新设备树
下载NVIDIA tx2内核,找到spi的设备树声明位置:
$cd public_sources/hardware/nvidia/soc/t18x/kernel-dts/tegra186-soc/ tegra186-soc-spi.dtsi
确认挂载的spi位置,需要根据原理图查找spi接口,添加spi节点。
spi1: spi@c260000 {
compatible = "nvidia,tegra186-spi";//(必需)通用名称后的SPI设备名称
reg = <0x0 0x0c260000 0x0 0x10000>;//(必需)设备的片选地址
interrupts = <0 37 0x04>;//指定它所依附的中断控制器
#address-cells = <1>; //定义芯片选择所需的单元数SPI总线上的地址。
#size-cells = <0>; //应该为零
iommus = <&smmu TEGRA_SID_GPCDMA_0>;
dmas = <&gpcdma 16>, <&gpcdma 16>;//一个或多个DMA描述符,每个节点有两个选项,1 dma控制器描述符,2 一个包含DMA控制器特定信息的phandle引用的节点中的属性。
dma-names = "rx", "tx";//为dmas属性中的每个DMA说明符包含一个标识符字符串。
nvidia,clk-parents = "pll_p", "osc";
spi-max-frequency = <25000000>;//(必需)设备的最大SPI时钟速度,单位为Hz
clocks = <&tegra_car TEGRA186_CLK_SPI2>,
<&tegra_car TEGRA186_CLK_PLLP_OUT0>,
<&tegra_car TEGRA186_CLK_OSC>;
clock-names = "spi", "pll_p", "osc";
resets = <&tegra_car TEGRA186_RESET_SPI2>;
reset-names = "spi";
status = "okay";
lens_dev@0{
compatible = "spidev"; //与spidev.c中的compatible = "spidev"一致
reg = <0x1>;
spi-max-frequency = <0xf4240>;
#address-cells = <0x1>;
#size-cells = <0x1>;
status = "okay";
};
};
- 编译设备树
在public_sources/kernel/kernel-4.9下运行:
$make dtbs ARCH=arm64
3,烧录设备树
将编译好的dtbs拷贝到Linux_for_Tegra/kernel/dtb中,在Linux_for_Tegra中运行命令:
$sudo ./flash.sh -k kernel-dtb jetson-tx2 mmcblk0p1
4,验证设备节点
在dev下查看是否查找spidev的节点。
可以使用spidev_test验证miso与mosi是否可以使用,只需将两个引脚连接在一起,使用命令:
sudo ./spidev_test -D /dev/spidev*.0 -v -p sss
验证即可。