представлять SPI Модуль метода изиспользовать,удобныйоткрытьразработчикииспользовать。
Разработчик/сопровождающий драйвера для модуля SPI.
Таблица 1-1: Список применимой продукции
Версия ядра | файл драйвера |
---|---|
Linux-4.9 | spi-sunxi.c |
Linux-5.4 | spi-sunxi.c |
SPI — это высокоскоростная и высокоэффективная технология последовательного интерфейса. Обычно он состоит из ведущего модуля и одного или нескольких ведомых модулей. Главный модуль выбирает ведомый модуль для синхронной связи для завершения обмена данными. Он широко используется между АЦП, ЖК-дисплеем и другим оборудованием и MCU. Spi-контроллер Allwinner поддерживает следующие функции:
• Полнодуплексный синхронный последовательный интерфейс.
• поддерживать 5 выбор источника синхронизации.
• поддерживать master и slave Две конфигурации.
• четыре cs Выбор фильмаподдерживать。
• 8bit Ширина и 64 байт fifo глубина.
• cs и clk Из полярности и фазы можно Конфигурация.
• поддерживатьиспользовать DMA。
• поддерживатьчетыре вида общениямодель.
• Массовое производство поддерживаетMAXиз io ставка 100MHz。
• поддерживать 3 Линия, 4 Проволока SPI модель.
• Поддерживает длину кадра данных программируемой последовательной линии: 0~32 бита.
• поддерживать Standard SPI/Dual-Output/Dual-input SPI/Dual i/O SPI/ и Quad-Output/Quad Input SPI。
Таблица 2-1: Аппаратная терминология
термин | Объяснение |
---|---|
SPI | Последовательный периферийный интерфейс, синхронный последовательный периферийный интерфейс |
поверхность 2-2: программное обеспечениетермин
термин | Объяснение |
---|---|
Sunxi | Относится к серии аппаратных платформ SOC компании Allwinner. |
SPI Master | SPI-мастер |
SPI Device | Относится к внешнему устройству SPI. |
безразличный Sunxi В аппаратной платформе SPI Количество контроллеров также варьируется, но для каждого SPI Для контроллера параметры конфигурации середина дерева устройств существования аналогичны, файл дерева устройств платформы имеет путь для: kernel/Версия ядра/arch/arm64(32 рычаг битовой платформы)/boot/dts/sunxi/CHIP.dtsi(CHIP — это кодовое название НИОКР, например sun50iw10p1 и т. д.), для настройки Для SPI1 это выглядит следующим образом:
spi1: spi@05011000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "allwinner,sun50i-spi"; //Специально для устройства, используется для привязки драйвера и устройства
device_type = "spi1"; //Имя узла устройства
reg = <0x0 0x05011000 0x0 0x1000>; // Конфигурация всех проводных регистров
interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;//общий Проволокасередина Номер перерыва、тип разрыва середина
clocks = <&clk_pll_periph0>, <&clk_spi1>; //Устройствоиспользования часов
clock-frequency = <100000000>; //Контроллер тактовой частоты
pinctrl-names = "default", "sleep"; //ControlleruseizPin name
pinctrl-0 = <&spi1_pins_a &spi1_pins_b>; //контроллериспользоватьизpinступня Конфигурация pinctrl-1 = <&spi1_pins_c>; //контроллериспользоватьизpinступня Конфигурация spi1_cs_number = <1>; //Количество контактов контроллера cs
spi1_cs_bitmap = <1>; /* cs0- 0x1; cs1-0x2, cs0&cs1-0x3. */
status = "disabled"; //Включен ли контроллер
};
существовать Linux-5.4 версия ядра, с Linux-4.9 Конфигурация ядра немного другая, в основном существует clock и dma По конфигурации:
spi1: spi@4026000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "allwinner,sun20i-spi"; //Специально для устройства, используется для привязки драйвера и устройства
reg = <0x0 0x04026000 0x0 0x1000>; //Имя узла устройства
interrupts-extended = <&plic0 32 IRQ_TYPE_LEVEL_HIGH>;//общий Проволокасередина Номер перерыва、тип разрыва середина
clocks = <&ccu CLK_PLL_PERIPH0>, <&ccu CLK_SPI1>, <&ccu CLK_BUS_SPI1>;//оборудованиеиспользовать изчас clock-names = "pll", "mod", "bus"; //Устройствоиспользования часовимя
resets = <&ccu RST_BUS_SPI1>; //Устройство сбрасывает часы
clock-frequency = <100000000>; //Контроллер тактовой частоты
spi1_cs_number = <1>; //Количество контактов контроллера cs
spi1_cs_bitmap = <1>; /* cs0- 0x1; cs1-0x2, cs0&cs1-0x3. */
dmas = <&dma 23>, <&dma 23>; //Контроллериспользуетиздмс номер канала
dma-names = "tx", "rx"; //Номер канала использования контроллера соответствует названию
status = "disabled"; //Включен ли контроллер
};
для Понятносуществовать SPI Общий код драйвера Проволока середина отличает каждого человека SPI Контроллер, необходимый для существования Device Tree в aliases для каждого узла SPI Указанный псевдоним узла:
aliases {
soc_spi0 = &spi0;
soc_spi1 = &spi1;
...
};
Форма псевдонима представляет собой строку “spi” Сложите последовательные числа из цифр, существуют SPI Драйвер Total Profila середина доступен через of_alias_get_id() Функция получает соответствующее SPI Контроллер имеет цифровой номер, что позволяет различать каждый SPI контроллер.
в Версия ядрадля Linux-4.9 из spi1_pins_a, spi1_pins_b из Конфигурацияпуть к файлудля kernel/linux-4.9/arch/arm64(32 Битовая платформа Arm)/boot/dts/sunxi/xxx-pinctrl.dtsi, конкретная конфигурация выглядит следующим образом:
spi1_pins_a: spi1@0 {
allwinner,pins = "PH4", "PH5", "PH6";
allwinner,pname = "spi1_sclk", "spi1_mosi",
"spi1_miso";
allwinner,function = "spi1";
allwinner,muxsel = <2>;
allwinner,drive = <1>;
allwinner,pull = <0>;
};
spi1_pins_b: spi1@1 {
allwinner,pins = "PH3";
allwinner,pname = "spi1_cs0";
allwinner,function = "spi1";
allwinner,muxsel = <2>;
allwinner,drive = <1>;
allwinner,pull = <1>; // only CS should be pulled up
};
spi1_pins_c: spi1@2 {
allwinner,pins = "PH3", "PH4", "PH5", "PH6";
allwinner,function = "io_disabled";
allwinner,muxsel = <7>;
allwinner,drive = <1>;
allwinner,pull = <0>;
};
Версия ядра для Linux-5.4 из spi1_pins_a, spi1_pins_b из конкретной конфигурации следующим образом:
spi1_pins_a: spi1@0 {
pins = "PD11", "PD12", "PD13";
function = "spi1";
drive-strength = <10>;
};
spi1_pins_b: spi1@1 {
pins = "PD10";
function = "spi1";
drive-strength = <10>;
bias-pull-up; /* only CS should be pulled up */
};
spi1_pins_c: spi1@2 {
pins = "PD10", "PD11", "PD12", "PD13";
function = "gpio_in";
};
board.dts Используется для сохранения различий между устройствами платформы на уровне платы из информации и дополнений (например, demo Доска, демо2.0 Доска, версия 1 доска и т. д.), на нее будет наложена находящаяся внутри информация. device tree Информация о конфигурации по умолчанию.
board.dts из Путь для/device/config/chips/{IC}/configs/{BOARD}/board.dts, в SPI1 из Конкретная конфигурация следующая:
иллюстрировать
существовать Linux-5.4 Версия ядросерединапара board.dts Грамматика была изменена таким образом, что узлы с одинаковым именем больше не подпадают под действие и поддерживаются. “&” Узел ссылки на символ.
&spi1 {
clock-frequency = <100000000>;
pinctrl-0 = <&spi1_pins_a &spi1_pins_b>;
pinctrl-1 = <&spi1_pins_c>;
pinctrl-names = "default", "sleep";
spi_slave_mode = <0>;
status = "disabled";
spi_board1@0 {
device_type = "spi_board1";
compatible = "rohm,dh2228fv";
spi-max-frequency = <0x5f5e100>;
reg = <0x0>;
spi-rx-bus-width = <0x4>;
spi-tx-bus-width = <0x4>;
status = "disabled";
};
};
Обратите внимание: если вы хотите использовать spi slave режим, пожалуйста, поставьте spi_slave_mode = <0> Изменить на: spi_slave_mode = <1>。
spi_board1 также имеет некоторые настраиваемые параметры, такие как:
• spi-cpha и spi-cpol: конфигурация spi из Четыре вида модели передачи.
• spi-cs-high: конфигурация cs Когда вывод находится в допустимом состоянии, он находится на уровне «из».
spi1_pins_a, spi1_pins_b, spi1_pins_c Конкретная конфигурация следующая:
spi1_pins_a: spi1@0 {
pins = "PD11", "PD12", "PD13","PD14", "PD15"; /*clk mosi miso hold wp*/
function = "spi1";
drive-strength = <10>;
};
spi1_pins_b: spi1@1 {
pins = "PD10";
function = "spi1";
drive-strength = <10>;
bias-pull-up; // only CS should be pulled up
};
spi1_pins_c: spi1@2 {
allwinner,pins = "PD10", "PD11", "PD12", "PD13","PD14", "PD15";
allwinner,function = "gpio_in";
allwinner,muxsel = <0>;
drive-strength = <10>;
};
существует командная строка середина для входа в ядро linux каталог, выполнить make ARCH=arm64 menuconfig(32 Битовая система make ARCH=arm menuconfig) Войдите в основной интерфейс конфигурации (Linux-5.4 Версия выполнение ядра: ./build.sh Menuconfig) и выполните следующие действия.
Выберите опцию «Драйверы устройств», чтобы перейти на следующий уровень конфигурации, как показано на рисунке ниже.
Рисунок 2-1: Параметры конфигурации драйверов устройств
Выберите опцию поддержки SPI, чтобы перейти на следующий уровень конфигурации, как показано на рисунке ниже.
Рисунок 2-2: Параметры конфигурации поддержки SPI
Выберите опцию SUNXI SPI Controller, и вы сможете скомпилировать его непосредственно в ядро или скомпилировать в модуль. Как показано ниже.
Рисунок 2-3: Параметры конфигурации контроллера SUNXI SPI
Если ты хочешь отпустить spi из Некоторые отладочные отпечатки, которые можно выбрать Debug support for SPI drivers。
SPI Полный драйвер Проволока из исходного кода находится в ядре. drivers/spi В каталоге:
drivers/spi/
├── spi-sunxi.c // Код драйвера контроллера SPI платформы Sunxi
├── spi-sunxi.h // Драйвер контроллера SPI для платформыSunxi определяет некоторые макросы и структуры данных.
Архитектура SPI в Linux разделена на три уровня, как показано на рисунке ниже.
Рисунок 2-4: Схема архитектуры Linux SPI
включить всеиспользовать SPI Устройство из приложения, существующее. Этот уровень пользователей может действовать в соответствии со своими реальными потребностями. spi Устройство выполняет некоторую специальную обработку, которая в данный момент неизвестна драйверу контроллера. Специфические функции устройства, SPI Конкретные функции устройства дополняются программами пользовательского уровня. Например, и MTD взаимодействие слоев, чтобы SPI ловитьиз устройства хранения данных для индивидуальной файловой системы, иTTY Дескриптор взаимодействия с подсистемой SPI Устройство реализовано как TTY Взаимодействие устройства и сетевой подсистемы поставит индивидуальное SPI Устройство реализовано как сетевое оборудование и т.д. Конечно, если это индивидуальная собственность. SPI Для оборудования мы также можем реализовать собственный драйвер протокола в соответствии с требованиями протокола оборудования. При этом мы не используем эту часть фокуса на。
пространство ядра мы также разделим на три части:
Учитывая дажеловитьсуществовать SPI Из-за изменчивости устройства на контроллере, существующее ядро не оснащено соответствующим драйвером протокола, для В этом случае ядро для мы подготовили универсальный из SPI драйвер устройства, универсальный драйвер устройства, который обеспечивает контроль над пользовательским пространством SPI Управление по управлению ловить портом, конкретная работа по управлению протоколом и передаче данных передается пользователю. Пространство комплектуется в соответствии со спецификой существующего оборудования, таким образом середина может использоваться только в синхронном методе. SPI устройства обмениваются данными, поэтому к обычно используется для некоторого простого SPI с небольшим объемом данных. оборудование.
Этот слой соответствует нашему ядру. spidev.c этотиндивидуальныйстандартныйиз spi Драйвер устройства, или наша компания из spi–nand.c,поддерживать spi Соглашение из nand Водитель и т. д. Для конкретного из SPI Оборудование для реализации конкретных функций, в том числе read,write а также ioctl Подождите, пока пользовательский уровень изловит порт. СПИ Общий драйвер Проволока в основном реализован для конкретных SPI Контроллер из всех методов чтения и записи Проволока и зарегистрируйтесь Linux Ядро из SPI Архитектура,СПИ Периферийные устройства могут пройти SPI Архитектура дополняет оборудование и полную адаптацию Проволокаиз. Однако сам общий драйвер Проволока не осуществляет никакой связи. Он только обеспечивает реализацию связи и ждет, пока драйвер устройства вызовет свои функции. СПИ Core из Руководство просто заблокировало это SPI Общий драйвер Проволока из разницы, которая составляет SPI Драйвер устройства может игнорировать различные общие различия контроллера и не должен учитывать, как они работают. обеспечение Устройство связииз Подробнее.
Чтобы упростить SPI Программирование драйверов также снижает степень связи между драйвером протокола и драйвером контроллера. Ядро инкапсулирует некоторые общие операции драйвера контроллера и драйвера протокола в стандартные интерфейсы, а также некоторые общие логические операции обработки. SPI Универсальный ловить изоляционный слой рта. Преимущество этого заключается в том, что драйверу контроллера достаточно реализовать стандартные обратные вызовы порта. API и поместите его на общий уровень порта без необходимости напрямую взаимодействовать с драйвером уровня протокола. Что касается драйвера уровня протокола, его необходимо предоставить только через общий уровень интерфейса ловить. API Вы можете завершить регистрацию драйвера устройства и передать уровень универсального порта ловить из API. Полная передача данных без каких-либо усилий на SPI Подробности реализации драйвера контроллера. Этот слой соответствует драйверу spi.c Файл является собственным файлом ядра.
Чтобы упростить SPI Программирование драйверов также снижает степень связи между драйвером протокола и драйвером контроллера. Ядро инкапсулирует некоторые общие операции драйвера контроллера и драйвера протокола в стандартные интерфейсы, а также некоторые общие логические операции обработки. SPI Универсальный ловить изоляционный слой рта. Преимущество этого заключается в том, что драйверу контроллера достаточно реализовать стандартные обратные вызовы порта. API и поместите его на общий уровень порта без необходимости напрямую взаимодействовать с драйвером уровня протокола. Что касается драйвера уровня протокола, его необходимо предоставить только через общий уровень интерфейса ловить. API Вы можете завершить устройство и драйвер из-за регистрации и пройти универсальный уровень ловить порт из API Полная передача данных без каких-либо усилий на SPI Подробности реализации драйвера контроллера.
Этот слой является предметом нашего внимания, существование которого будет подробно описано в следующей статье.
Этот уровень представляет собой реальное физическое устройство, включая нас. spi Контроллер Также контроллер подключается индивидуально для каждого spi суб-устройство, через spi Всего Проволока может и cpu Выполните взаимодействие с данными.
ловитьопределение ртасуществовать include/linux/spi/spi.h, в основном включает spi_register_driver и spi_unregister_driver ловитьрот,в Даватьвне Понятнобыстрыйзарегистрироватьсяиз SPI Драйвер устройства и макрос модуль_spi_driver(), определенный следующим образом:
#define module_spi_driver(__spi_driveSPI \
module_driver(__spi_driver, spi_register_driver, \
spi_unregister_driver)
• Прототип функции: int spi_register_driver(struct spi_driver *sdrv)
• Описание функции: Зарегистрируйте SPI Драйвер устройства.
• параметриллюстрировать:
• sdrv,spi_driver типизобратитесь игла, в комплекте SPI Название оборудования, зонд и другая информация об интерфейсе.
• Возвращаемое значение: возврат 0 поверхность указывает на успех, возврат других значений указывает на неудачу.
• Прототип функции: void spi_unregister_driver(struct spi_driver *sdrv)
• Описание функции: выйти из системы SPI Драйвер устройства.
• параметриллюстрировать:
• sdrv,spi_driver типизобратитесь игла, в комплекте SPI Название оборудования, зонд и другая информация об интерфейсе.
• Возвращаемое значение: Нет
SPI Драйвер устройстваиспользовать “struct spi_message” К SPI Общий запрос Проволока на чтение и запись ввод/вывод. один spi_message содержит последовательность операций, каждая операция называется spi_transfer, так удобно SPI Полный серединный серийный драйвер Проволоки выполняет индивидуальную атомарную последовательность. Очередь процесса Проволока ядра реализует асинхронную передачу из функции для той же индивидуальной передачи данных из инициатора. Поскольку асинхронному методу не нужно ждать завершения передачи данных, прежде чем он сможет вернуться, после возврата инициатор может это сделать. немедленно инициировать еще одного человека сообщение, а в это время предыдущее message Еще не закончено. для другого индивидуального другого инициатора, также возможно инициировать его одновременно message Запрос на трансфер.
Рисунок 3-1: Процесс передачи данных Linux SPI
struct spi_transfer {
const void *tx_buf;
void *rx_buf;
unsigned len;
dma_addr_t tx_dma;
dma_addr_t rx_dma;
unsigned cs_change:1;
u8 bits_per_word;
u16 delay_usecs;
u32 speed_hz;
struct list_head transfer_list;
};
struct spi_message {
struct list_head transfers;
struct spi_device *spi;
unsigned is_dma_mapped:1;
void (*complete)(void *context);
void *context;
unsigned actual_length;
int status;
struct list_head queue;
void *state;
};
• Прототип функции: void spi_message_init(struct spi_message *m)
• Описание функции: Инициализация SPI message Структура, в основном очистка и инициализация transfer очередь.
• параметриллюстрировать:
• m:spi_message типизобратитесь игла.
• Возвращаемое значение: Нет
• Прототип функции: void spi_message_add_tail(struct spi_transfer *t, struct spi_message *m)
• Описание функции: К SPI message Добавьте один в transfer。
• параметриллюстрировать:
• t: обратитесь к КДобавить в SPI transfer структура;
• m:spi_message типизобратитесь игла.
• Возвращаемое значение: Нет
• Прототип функции: int spi_sync(struct spi_device *spi, struct spi_message *message)
• Описание функции: запуск и ожидание SPI общий Проволока Законченныйобратитесь к Конечноиз SPI message。
• параметриллюстрировать:
• spi,обратитесь к Ктекущийиз SPI оборудование;
• m,spi_message типизобратитесь к Игла, в ожидании из SPI transfer очередь.
• Возвращаемое значение: 0, успех меньше; 0, не удалось.
файл драйверасуществовать driver/spi/spidev.c, этот драйвер Linux Ядро поставляется с индивидуальным spidev Универсальный драйвер. в вызове spi_register_driver() зарегистрироваться SPI Драйвер, удобный для использования в реализации SPI message Данные чтения и записи.
static int __init spidev_init(void)
{
int status;
/* Claim our 256 reserved device numbers. Then register a class
* that will key udev/mdev to add/remove /dev nodes. Last, register
* the driver which manages those device numbers.
*/
BUILD_BUG_ON(N_SPI_MINORS > 256);
status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops);
if (status < 0)
return status;
spidev_class = class_create(THIS_MODULE, "spidev");
if (IS_ERR(spidev_class)) {
unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
return PTR_ERR(spidev_class);
}
status = spi_register_driver(&spidev_spi_driver);
if (status < 0) {
class_destroy(spidev_class);
unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
}
return status;
}
module_init(spidev_init);
static void __exit spidev_exit(void)
{
spi_unregister_driver(&spidev_spi_driver);
class_destroy(spidev_class);
unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
}
module_exit(spidev_exit);
Также необходимо соответствующее существование из spi Контроллер dts плюс ниже spi Описание информации о субустройстве, конкретная информация о конфигурации следующая:
&spi1 {
clock-frequency = <100000000>;
pinctrl-0 = <&spi1_pins_a &spi1_pins_b>;
pinctrl-1 = <&spi1_pins_c>;
pinctrl-names = "default", "sleep";
spi_slave_mode = <0>;
status = "disabled";
spi_board1@0 {
device_type = "spi_board1";
compatible = "rohm,dh2228fv";
spi-max-frequency = <0x5f5e100>;
reg = <0x0>;
spi-rx-bus-width = <0x4>;
spi-tx-bus-width = <0x4>;
status = "disabled";
};
};
для spi Контроллерописыватьсуществоватьэтотвнутри Нетповтори еще разиззаявление,этотвнутрииз spi_board1@0 Это наш виртуальный индивидуальный spi подчиненное устройство,
• device_type : поверхность Указывает тип оборудования из;
• compatible : Информация о соответствии драйвера;
• spi-max-frequency : Максимальная частота ведомого устройства;
• reg : Ведомое устройство по адресу регистра;
• spi-rx-bus-width: При чтении данных с ведомого устройстваиспользоватьиз data данные Проволокаиндивидуальныйчисло;
• spi-tx-bus-width : При записи данных на ведомое устройствоиспользоватьиз data данные Проволокаиндивидуальныйчисло;
• status :Состояние ведомого устройства;
существовать menuconfig(Device Drivers->SPI Настройте в поддержке) User mode SPI device driver support параметры.
Рисунок 4-1: Спайдев
После компиляции и записи прошивки файловая система маленького компьютера будет /dev. Найдено в каталоге spidevX.0(X=0~2) оборудование, может spidevX.0 Выполнять операции чтения и записи. Или сипользовать Linux Принесите свой собственный spi инструмент:существовать tina/lichee/linux-5.4/tools в каталоге, Выполните следующую команду:
make spi
Тогда он будет существовать в исполняемом файле tina/lichee/linux-5.4/tools/spi/spidev_test.,Скопируйте в корневую файловую систему мини-машины середина.,Для проверки выполните следующую команду:
/spidev_test -D /dev/spidevX.0
нуждатьсясуществовать board.dts серединасоответствующийиз SPI Конфигурация узла узла spi_slave_mode = <1>。
Если взять в качестве примера устройство spidev1.0, оно отправляет десять данных от 0 до 9:
#define DEVICE_NAME "/dev/spidev1.0"
#define HEAD_LEN 5
#define PKT_MAX_LEN 0x40
#define STATUS_LEN 0x01
#define SUNXI_OP_WRITE 0x01
#define SUNXI_OP_READ 0x03
#define STATUS_WRITABLE 0x02
#define STATUS_READABLE 0x04
#define WRITE_DELAY 200
#define READ_DELAY 100000
void dump_data(unsigned char *buf, unsigned int len)
{
unsigned int i;
unsigned char tmp[len*2], cnt = 0;
for (i = 0; i < len; i++) {
if (i%0x10== 0)
cnt += sprintf(tmp + cnt, "0x%08x: ", i);
cnt += sprintf(tmp + cnt, "%02x ", buf[i]);
if ( (i%0x10== 0x0f) || (i == (len -1)) ) {
printf("%s\n", tmp);
cnt = 0;
}
}
}
void batch_rand(char *buf, unsigned int length)
{
unsigned int i;
srand(time(0));
for(i = 0; i < length; i++) {
*(buf + i) = rand() % 256;
}
}
int main(int argc, const char *argv[])
{
unsigned int length = 0, test_len;
char wbuf_head[HEAD_LEN] = {SUNXI_OP_WRITE, 0x00, 0x00, 0x00, 0x00};
char rbuf_head[HEAD_LEN] = {SUNXI_OP_READ, 0x00, 0x00, 0x00, 0x00};
char wbuf[PKT_MAX_LEN], rbuf[PKT_MAX_LEN], i, time;
int fd, ret;
test_len = 10;//send 10 numbers
if (test_len > PKT_MAX_LEN) {
printf("invalid argument, numbers must less 64B\n");
return -1;
}
wbuf_head[4] = test_len;
rbuf_head[4] = test_len;
for (i = 0; i < test_len; i++)
wbuf[i] = i;
printf("wbuf:\n");
dump_data(wbuf, test_len);
fd = open(DEVICE_NAME, O_RDWR);
if (fd <= 0) {
printf("Fail to to open %s\n", DEVICE_NAME);
ret = -1;
return ret;
}
{//write
if (write(fd, wbuf_head, HEAD_LEN) != HEAD_LEN) {
printf("W Fail to write head\n");
ret = -1;
goto err;
} else
printf("W write head successful\n");
usleep(WRITE_DELAY);
if (write(fd, wbuf, test_len) != test_len) {
printf("W Fail to write data\n");
ret = -1;
goto err;
} else
printf("W write data successful\n");
usleep(READ_DELAY);
}
err:
if (fd > 0)
close(fd);
return ret;
}
На примере устройства spidev1.0 прочитайте десять данных:
#define DEVICE_NAME "/dev/spidev1.0"
#define HEAD_LEN 5
#define PKT_MAX_LEN 0x40
#define STATUS_LEN 0x01
#define SUNXI_OP_WRITE 0x01
#define SUNXI_OP_READ 0x03
#define STATUS_WRITABLE 0x02
#define STATUS_READABLE 0x04
#define WRITE_DELAY 200
#define READ_DELAY 100000
void dump_data(unsigned char *buf, unsigned int len)
{
unsigned int i;
unsigned char tmp[len*2], cnt = 0;
for (i = 0; i < len; i++) {
if (i%0x10== 0)
cnt += sprintf(tmp + cnt, "0x%08x: ", i);
cnt += sprintf(tmp + cnt, "%02x ", buf[i]);
if ( (i%0x10== 0x0f) || (i == (len -1)) ) {
printf("%s\n", tmp);
cnt = 0;
}
}
}
void batch_rand(char *buf, unsigned int length)
{
unsigned int i;
srand(time(0));
for(i = 0; i < length; i++) {
*(buf + i) = rand() % 256;
}
}
int main(int argc, const char *argv[])
{
unsigned int length = 0, test_len;
char wbuf_head[HEAD_LEN] = {SUNXI_OP_WRITE, 0x00, 0x00, 0x00, 0x00};
char rbuf_head[HEAD_LEN] = {SUNXI_OP_READ, 0x00, 0x00, 0x00, 0x00};
char wbuf[PKT_MAX_LEN], rbuf[PKT_MAX_LEN], i, time;
int fd, ret;
test_len = 10;
if (test_len > PKT_MAX_LEN) {
printf("inval argument, numbers must less 64B\n");
return -1;
}
wbuf_head[4] = test_len;
rbuf_head[4] = test_len;
fd = open(DEVICE_NAME, O_RDWR);
if (fd <= 0) {
printf("Fail to to open %s\n", DEVICE_NAME);
ret = -1;
return ret;
}
{//read
if (write(fd, rbuf_head, HEAD_LEN) != HEAD_LEN) {
printf("R Fail to write head\n");
ret = -1;
goto err;
} else
printf("R write head successful\n");
usleep(READ_DELAY);
if (read(fd, rbuf, test_len) != test_len) {
printf("R Fail to read data\n");
ret = -1;
goto err;
} else
printf("R read data successful\n");
usleep(READ_DELAY);
}
printf("rbuf:\n");
dump_data(rbuf, test_len);
err:
if (fd > 0)
close(fd);
return ret;
}
Этот тестиспользовать две открытые доски для волос, чтобы построить окружающую среду, одну, чтобы сделать хозяина рабом.
Воля MASTER и SLAVE из SPI1 из CS、CLK Соедините их по имени, МАСТЕР. из MOSI забрать РАБ из MOSI,MASTER из MISO ловить SLAVE из MISO,Волядве частиоткрытьобщая основа доски для волос。
бить открыть menuconfig из CONFIG_SPI_SUNXI и CONFIG_SPI_SPIDEV, как показано на рисунке ниже.
Рисунок 4-2: конфигурация меню
4.2.3.1.3 DTS
Путь в дереве устройств: device/config/chips/xxx(t507)/configs/xxx(demo2.0)/board.dts, добавьте следующие узлы:
spi1: spi@05011000 {
pinctrl-0 = <&spi1_pins_a &spi1_pins_b>;
pinctrl-1 = <&spi1_pins_c>;
spi_slave_mode = <0>;
status = "okay";
spi_board1 {
device_type = "spi_board1";
compatible = "rohm,dh2228fv";
spi-max-frequency = <30000000>;
reg = <0x0>;
spi-rx-bus-width = <0x1>;
spi-tx-bus-width = <0x1>;
};
};
Примечание: spi_slave_mode = <0> для Master Конфигурация spi_slave_mode; = <1>,для Slave Конфигурация
Установить отдельно Master и Salve из DTS, скомпилируйте соответствующую прошивку и запишите прошивку.
Slave Выполните на терминале следующую команду: битьоткрыть Slave отладочная печать, чтобы вы могли видеть данные чтения и записи.
Исходные данные Maset и целевые данные бьют данные печати согласованными, то есть проверка поверхности прошла успешно.
--------------------------------------------
n test
--------------------------------------------
W write head successful
W write data successful
source data:
0x00000000: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a
0x00000010: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a
R write head successful
R read data successful
target data:
0x00000000: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a
0x00000010: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a
slave function [PASS]
Пользователи могут настраивать функции подчиненного устройства для работы в подчиненном режиме. устройство, нужно отправить 5 индивидуальный byte из запроса на операцию, иллюстрируем следующим образом:
Нет. 1 индивидуальный Байт: код операции
SUNXI_OP_WRITE 0x01
SUNXI_OP_READ 0x03
//Чтение и запись относятся к мастеру
Нет. 2~4 индивидуальный Байт: адрес (2 это адрес старшего порядка)
Нет. 5 Давать Байт: длина (длина должна быть меньше 64Byte)
Сейчас существуют только операции чтения и записи.,Саморазвитие пользователя,существоватьdrivers/spi/spi-sunxi.c функция issunxi_spi_slave_handle_head середина добавляет команду, соответствующую функции операции
if (head->op_code == SUNXI_OP_WRITE) {
sunxi_spi_slave_cpu_rx_config(sspi);
} else if (head->op_code == SUNXI_OP_READ) {
sunxi_spi_slave_cpu_tx_config(sspi);
} else {
dprintk(DEBUG_INFO, "[spi%d] pkt head opcode err\n", sspi->master->bus_num);
ret = -1;
goto err1;
}
Нет. 2~4 индивидуальный Byte из адреса следует обратиться к Определены данные кэша чтения и записи, макрос размера кэша существуетdrivers/spi/spi-slave-protocol.hсередина определен, пользователь задает его сам, единица измерения Byte
#define STORAGE_SIZE 128
4.2.3.4.3 длина
Читать и записывать каждый раз длины данных требуется менее 64 байта, из-за SPI RX/TX из FIFO Размер кэшадля 64Byte, для того, чтобы один конец устройства не забирал данные вовремя во время чтения и записи. buf Переполнение, для одной передачи требуется длина меньше 64 байта, если вы хотите читать и писать больше, чем 64Byte Данные могут передаваться несколькими пакетами, и проблем не будет, если смещение адреса хорошее.
По умолчанию debug для 1,Нетбитьоткрытьотладочная информация。
echo 255 > /sys/module/spi_sunxi/parameters/debug
Вы можете битьоткрыть отладочную информацию.
Этот файл узла может распечатать текущий SPI1 канал какое-то аппаратное предоставление информации о ресурсах.
cat /sys/devices/platform/soc/spi1/info
Этот файл узла может распечатать текущий SPI1 рядиз Некоторая информация о рабочем состоянии,включать Контроллер Каждое значение регистра。
cat /sys/devices/platform/soc/spi1/status
Проблемное явление:существовать board.dts середина Конфигурация spi из statue состояниедля "окей", но в придачу Linux Ядро найдено Спи-контроллер не включен. Анализ проблемы: Возможно, статус «Конфигурация» неправильный или возникла ошибка «Используйте другие контроллеры, такие как spi0。
Действия по устранению неполадок:
• шаг 1: Проблема такого рода обычно возникает из-за того, что ваше устройство зависит от другого устройства в существующем дереве устройств, но это отдельное устройство выходит из строя. probe Успех, в результате чего ваше устройство не сможет зонд. Рекомендуется spi Зависимость dma Устраните неполадки модуля и проверьте dma существовать menuconfig середина Будь тобитьоткрыть;
• шаг 2:существовать Найдите .sunxi.dts в каталоге out/. И битьоткрыть:
find -name ".sunxi.dts"
Найдите соответствующий из узла в существующем файле и проверьте, успешен ли соответствующий из spi.
• шаг 3:существоватьмаленький письменный стол uboot Консоль проходит fdt list spi* Представление команд dts, включен ли SPI Успех (статус = "окей"), если еще отключить, это возможно spi существовать uboot Этап disable Выпало (нормально spi0 Сохраню Дават flash использовать,spi0 встречасуществовать uboot сцена закрыта).
Признак: данные записи и чтения несовместимы.
• шаг 1: Проведите проверку совместимости. к nor flash дляпример,Некоторые материалы несовместимы,Вызовет ошибки чтения и записи. В это время вы можете сначала подтвердить, указаны ли в списке материалы следующего элемента. Если не существовать,Попробуйте изменить материал и сделать это снова.
• шаг 2: Отладка драйверов. Масштаб проблем этого типа относительно велик, но их можно отслеживать и устранять с помощью базовых методов отладки. Общая идея состоит в том, чтобы распечатать данные битьоткрыть и посмотреть, перенесётся ли записанное из значения в SPI Общая обработка драйвера Проволока, внешний вид тот же SPI Общий драйвер Проволока только что прочитал данные и проверил, согласованы ли ранее записанные и распечатанные данные, чтобы определить, какое соединение вызвало ошибку чтения и записи. Этот метод можно распространить на другие уровни. Убедитесь, что это уровень файловой системы или уровень. МТД Слой, ИПИ Всегда возникают проблемы с чтением или записью на уровне драйвера Проволоки.