Введение

Как правило, при покупке материнской платы для микрокомпьютера типа Raspberry или Jetson в документации есть распиновка. Распиновка показывает как связаны физические пины платы с пинами процессора. Однако, мало в какой документации найдётся описание связи между виртуальными пинами системы и физическими пинами платы. Постараемся в этом разобраться на примере микрокомпьютера Jetson Nano от Nvidia.

Матрица с выводами (PGA)

Если дело касается пинов процессора, то придётся познакомиться с понятием PGA (pin grid array) - стандарт упаковки интегральных схем, используемый в большинстве процессоров второго-пятого поколения. Грубо говоря, стандарт предписывает располагать пины в виде матрицы. На рисунке 1 представлен упрощённый пример такой матрицы.

Рис. 1: Упрощённый пример PGA.

Обратим внимание на нумерацию. Столбцы нумеруются буквами, а строки цифрами (точно как в Excel). Это очень удобно, поскольку конкретный пин можно позиционировать выра-жением типа A5. Если букв не хватает, то столбец индексируют двумя буквами, например АА5. То есть нумерация осуществляется в точности как в Excel.

Виртуальные пины системы

Ранее упоминалось понятие «виртуальные пины системы». Под виртуальными пинами системы будем понимать GPIO (General Purpose Input Output) интерфейса sysfs. Каждый контакт GPIO имеет уникальный номер в Linux, который, как правило, не соответствует наименованию пинов на чипе. Однако, существует правило пересчёта, по которому определяется нумерация в системе. Для Jetson это правило определено в исходниках ядра, в файле tegra-gpio.h:

#ifndef _DT_BINDINGS_GPIO_TEGRA_GPIO_H
#define _DT_BINDINGS_GPIO_TEGRA_GPIO_H

#include <dt-bindings/gpio/gpio.h>

#define TEGRA_GPIO_PORT_A 0
#define TEGRA_GPIO_PORT_B 1
#define TEGRA_GPIO_PORT_C 2
#define TEGRA_GPIO_PORT_D 3
#define TEGRA_GPIO_PORT_E 4
#define TEGRA_GPIO_PORT_F 5
#define TEGRA_GPIO_PORT_G 6
#define TEGRA_GPIO_PORT_H 7
#define TEGRA_GPIO_PORT_I 8
#define TEGRA_GPIO_PORT_J 9
#define TEGRA_GPIO_PORT_K 10
#define TEGRA_GPIO_PORT_L 11
#define TEGRA_GPIO_PORT_M 12
#define TEGRA_GPIO_PORT_N 13
#define TEGRA_GPIO_PORT_O 14
#define TEGRA_GPIO_PORT_P 15
#define TEGRA_GPIO_PORT_Q 16
#define TEGRA_GPIO_PORT_R 17
#define TEGRA_GPIO_PORT_S 18
#define TEGRA_GPIO_PORT_T 19
#define TEGRA_GPIO_PORT_U 20
#define TEGRA_GPIO_PORT_V 21
#define TEGRA_GPIO_PORT_W 22
#define TEGRA_GPIO_PORT_X 23
#define TEGRA_GPIO_PORT_Y 24
#define TEGRA_GPIO_PORT_Z 25
#define TEGRA_GPIO_PORT_AA 26
#define TEGRA_GPIO_PORT_BB 27
#define TEGRA_GPIO_PORT_CC 28
#define TEGRA_GPIO_PORT_DD 29
#define TEGRA_GPIO_PORT_EE 30 
#define TEGRA_GPIO_PORT_FF 31

#define TEGRA_GPIO(port, offset) \
((TEGRA_GPIO_PORT_##port * 8) + offset)
#endif

В приведённой формуле port соответствует столбцу, а offset строке. К счастью для пользователя, высчитывать соответствия не придётся. Их так же можно получить выполнив:

sudo cat /sys/kernel/debug/pinctrl/2430000.pinmux/pinmux-pins

Типичный результат выполнения:

Pinmux settings per pin
Format: pin (name): mux_owner gpio_owner hog?
pin 0 (PEX_L0_RST_N_PA0): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 1 (PEX_L0_CLKREQ_N_PA1): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 2 (PEX_WAKE_N_PA2): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 3 (PEX_L1_RST_N_PA3): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 4 (PEX_L1_CLKREQ_N_PA4): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 5 (PEX_L2_RST_N_PA5): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 6 (PEX_L2_CLKREQ_N_PA6): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 8 (UART4_TX_PB0): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 9 (UART4_RX_PB1): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 10 (UART4_RTS_PB2): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 11 (UART4_CTS_PB3): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 12 (GPIO_WAN1_PB4): (MUX UNCLAIMED) tegra-gpio:332
pin 13 (GPIO_WAN2_PB5): (MUX UNCLAIMED) (GPIO UNCLAIMED)
......

Выражение «pin 32 (PB0)» означает, что системному пину номер 32 соответствует пин процессора «B0». Префикс «P» убирается, поскольку он просто означает «пин» и не относится к наименованию пина процессора. Итак, связь пина процессора с виртуальным пином системы установлена. Далее необходимо установить соответствие пина процессора и пина на материнской плате. Если такое соответствие есть в datasheet, то дело сделано, однако в случае, если используется малоизвестная материнская плата или она была сделана под заказ, то в случае с Jetson придётся совершить ещё один шаг.

Связь пина процессора с пином на материнской плате

Тут всё очень индивидуально. Между пином процессора и пином на материнской плате может быть большое количество промежуточных подключений. В нашем примере рассматривается Jetson Nano, у которого имеется такое промежуточное подключение. Дело в том, что Jetson Nano – это устройство с разъёмом SO-DIMM, на который выведены, в том числе и пины процессора. Как правило, этот разъём подключают к материнской плате и интересующие пользователя пины находятся именно там. Установить соответствие позволит документация на Jetson Nano, которую можно скачать здесь: pinmux_config. Скачиваем файл «Jetson Nano Pinmux» (рисунок 2).

Рис.2: Файл распиновки для Jetson Nano в Download центре сайта компании Nvidia.

В этом файле есть вся необходимая информация для того, чтобы связать виртуальный пин системы и физический пин на разъёме SO-DIMM. На рисунке 3 зелёным выделен номер пина на разъёме SO-DIMM, а синим ножка процессора (GPIO3_PE.06). В названии заложено наименование пина процессора – PE6. Красным выделено наименование функции данного пина на процессоре.

Рис.3: Соответствие пинов на Jetson Nano.

Теперь, если у нас есть документация на плату, на которую подключается Jetson Nano, мы можем связать виртуальный пин с физическим.