Здравствуйте!
В процессе разработки возникла необходимость создания собственного протокола обмена данными, для чего используются GPIO.
Для установки уровней GPIO тестировалось несколько вариантов:
1) Вариант 1. На уровне приложения с помощью /dev/mem
// CONSTANTS
#define MAP_SIZE 4096
#define UINT unsigned long int
#define GPIO *(volatile UINT *)
#define GPIO_BASE 0x40E00000
#define GPLR0 0x0000
#define GPDR0 0x000C
#define GPSR0 0x0018
#define GPCR0 0x0024
…
// MEMORY
//open /dev/mem with read and write mode
fd = open ("/dev/mem", O_RDWR|O_SYNC);
//map physical memory
start = (char *)mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED , fd, GPIO_BASE);
// CONFIGURING
//GPIO 9, 13, 21, 22 are configured as OUTPUTs
GPIO(start+GPDR0)|= ((1<<9)|(1<<13)|(1<<21)|(1<<22));
//GPIO 90, 91, 93, 94 are configured as INPUTs
GPIO(start+GPDR2)&= ~((1<<26)|(1<<27)|(1<<29)|(1<<30));
// WRITING/READING
//Writing 0
GPIO(start + GPCR0) = (1<<9)|(1<<13)|(1<<21);
//Writing 1
GPIO(start + GPSR0) = (1<<22);
//Reading
UINT DeviceReady = GPIO(start + GPLR0)
На выходе генерировался меандр с периодом 8 мкс, по битам получается 2,5 МГц или 305 кБайт/с.
2) Вариант 2. На уровне драйвера с использованием заголовочного файла с функциями и макросами.
#include <asm/gpio.h>
int pin=9;
gpio_direction_input(26);
gpio_direction_output(pin, 1);
gpio_set_value(pin, 0);
gpio_set_value(pin, 1);
По скорости получился такой же результат.
Быстрее выставлять значения не получается, загрузка процессора под 100%. Итого с 512МГц процессором на выставление уровня одного GPIO (?= регистру из 32 GPIO) уходит 200 машинных тактов. Результат вызывает некоторые сомнения в достоверности. Подскажите, можно ли работать с единичным значением GPIO (или регистром) быстрее?
Пробовал на уровне пользовательского загружаемого модуля (отдельная менюшка в menuconfig'е — компилится, отладочные сообщения при загрузке и выключении модуля выдает) "достучаться" напрямую по адресам с использованием макросов GPCR, GPSR, GPDR, GPLR из linux-kernel/include/asm-arm/arch-pxa/pxa-regs.h — не получилось: Segmentation fault, хотя в linux-kernel/arch/arm/mach-pxa/tion270.c такие конструкции используются и работают. В чем заключаются мои ошибки?