我正在尝试在 Odroid-C1 板上使用 UBlox NEO-7M GPS 接收器。
默认情况下,GPS 模块工作在 SPI 的第一种模式。这就是为什么我使用这个用户空间代码片段来选择正确的 SPI 模式。
int mode = SPI_MODE_0;
ret = ioctl(spi_fd, SPI_IOC_WR_MODE, &mode);
if (ret < 0) {
perror("can't set spi mode");
exit(1);
}
之后,我尝试一次读取一个字节并将其发送到标准输出。不过,这行不通。
经过一番思考,我插入了我的 Salaea 逻辑分析仪并得到了这张照片
这似乎根本不对。如果我没记错的话,SCL 应该在交易之间被拉低。
我试图通过在 spicc.ko 内核模块中拉下 SCL 行来解决这个问题(我使用这个内核和一个 RT-patch 来编译模块。RT-patch 并没有真正的区别。这个问题在 vanilla 上遇到过内核也是如此)。
因此,主要问题是:将这个引脚拉下来是正确的做法吗?
当我进一步查看代码时,我注意到 spicc_set_mode() 确实按照Amlogic S805 数据表中的描述设置模式(第 15.5.3 节描述了 CONREG 寄存器布局)。也许这还不够?
无论哪种方式,使用 Linux 的 pinctrl 接口下拉引脚的预期方法是什么?
我也在尝试理解 spicc 的代码。它用
ret = of_property_read_string(pdev->dev.of_node, "pinctrl-names", &prop_name);
if(ret || IS_ERR(prop_name)) {
dev_err(&pdev->dev, "match pinctrl-names failed!\n");
return -ENODEV;
}
pdata->pinctrl = devm_pinctrl_get_select(&pdev->dev, prop_name);
if(IS_ERR(pdata->pinctrl)) {
dev_err(&pdev->dev, "pinmux error\n");
return -ENODEV;
}
dev_info(&pdev->dev, "pinctrl_name = %s\n", prop_name);
从设备树 Blob 中获取 pinctrl 句柄,不是吗?我应该编辑 .dts 文件以拉下引脚还是可以在运行时完成?
起初我试图通过愚蠢的野蛮强制代码来使用它,但它不起作用(pinctrl 已经在使用这个引脚,如 spicc 部分的 .dts 文件中所声明的那样)。
static void spicc_sclk_init(void)
{
int ret;
int gpio;
char *owner = "spicc_sclk";
char *pin_name = "GPIOX_8";
gpio = amlogic_gpio_name_map_num(pin_name);
if (gpio < 0) {
printk(KERN_ERR "amlogic_gpio_name_map_num() failed. gpio: %d\n", gpio);
goto out_map;
}
ret = amlogic_gpio_request(gpio, owner);
if (ret < 0) {
printk(KERN_ERR "amlogic_gpio_request_one() failed. ret: %d\n", ret);
goto out_request;
}
ret = amlogic_set_pull_up_down(gpio, 0, owner);
if (ret < 0) {
printk(KERN_ERR "amlogic_set_pull_up_down() failed. ret: %d\n", ret);
goto out_pull_up_down;
}
out_pull_up_down:
out_request:
out_map:
;
}
有人对如何解决此问题有任何建议吗?
PS:我在具有相同 UBlox 的 RPi 上使用相同的用户空间代码,并且代码确实有效,并且模式按预期切换。
我尝试将另一个 SPI 驱动的设备连接到 Odroid-C1(它是 Invensense 的 MPU9260,如果这很重要的话。)并且成功了。我猜它只是更能容忍 SPI 模式。