linux-kernel - GPIO和SPI有什么关系?

标签 linux-kernel raspberry-pi driver gpio spi

我发现内核中的 GPIO 驱动离开 /sys/class/gpio 来控制 gpio,但我发现 GPIO 也可以通过 /dev/mem 来控制,我发现这个映射可能在 spi-bcm2708 中完成(它调用 __ioremap 作为平台驱动程序),但我不明白 spi 和 GPIO 之间的关系,它们如何在 linux 中协同工作?

最佳答案

据我了解,您说的是 this驱动程序(例如,在 Raspberry Pi 中使用)。首先来看BCM2835 datasheet .查看接下来的部分:

  • 1.1 概述
  • 6.0 通用 I/O (GPIO)
  • 6.2 替代函数赋值(见表6-31)

从驱动程序代码(见bcm2708_init_pinmode()函数)和数据表(表6-31),我们可以看出SPI管脚实际上是GPIO7..11管脚。这些引脚实际上可以连接到不同的 hardware modules (在本例中为 SPI 或 SD)。

Alternative Functions Assignment

这样的选择是使用 pin muxing 完成的.所以基本上你需要将 GPIO7..GPIO11 引脚连接到 SPI 模块。为此,您需要为每个 GPIO7..GPIO11 引脚选择 ALT0 功能。这可以通过将相应的值写入 GPFSEL0GPFSEL1 寄存器来完成(参见数据表中的表 6-1..6-3):

GPFSEL0 address

GPFSELn register description

这就是驱动程序实际执行此操作的方式:

/*
 * This function sets the ALT mode on the SPI pins so that we can use them with
 * the SPI hardware.
 *
 * FIXME: This is a hack. Use pinmux / pinctrl.
 */
static void bcm2708_init_pinmode(void)
{
#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define SET_GPIO_ALT(g, a) *(gpio+(((g)/10))) |= (((a) <= 3 ? (a)+4 : (a) == 4 ? 3 : 2)<<(((g)%10)*3))

    int pin;
    u32 *gpio = ioremap(GPIO_BASE, SZ_16K);

    /* SPI is on GPIO 7..11 */
    for (pin = 7; pin <= 11; pin++) {
        INP_GPIO(pin);      /* set mode to GPIO input first */
        SET_GPIO_ALT(pin, 0);   /* set mode to ALT 0 */
    }

    iounmap(gpio);

#undef INP_GPIO
#undef SET_GPIO_ALT
}

这对我来说看起来像是快速破解,他们实际上提到了它:正确的方法是使用称为 pinctrl 的内核机制。 .

结论:BCM2708 驱动程序实际上不会触发任何 GPIO 引脚,它只是在进行引脚复用,以便将 GPIO7..GPIO11 引脚连接到 SPI 模块。为此,该驱动程序写入 GPFSELn 寄存器,而这些寄存器恰好是 GPIO 寄存器。这几乎就是该驱动程序中 SPI 和 GPIO 之间的所有关系。

附言:如果您对 SPI 和 GPIO 之间的可能关系感到好奇,请阅读 bit banging .参见示例 spi-bitbang.c Linux 内核中的驱动程序。

关于linux-kernel - GPIO和SPI有什么关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31635576/

相关文章:

asynchronous - Linux 中的 async_schedule 与工作队列

python - 从 Raspberry Pi 捕获 jpeg 图像并将其发送到 PC socket python?

c# - 将元素插入到MongoDB中的嵌套数组中

c++ - 无法通过 CreateFile 打开设备,ERROR_INVALID_FUNCTION

c - C语言中如何获取某个进程的进程ID

linux - 为什么 strace 会根据环境/内核(随机)忽略某些系统调用?

linux-kernel - 如何使用 copy_to_user

sockets - 套接字对和成对的未命名管道之间有什么区别吗?

java - Android WebView不显示本地IP地址

python - 在 RaspberryPi 中安装 OpenCV 以与 Python 一起使用的正确方法