Files
obsidian-vault-/Linux/Programm/GPIO Userspace control.md
T

3.4 KiB
Raw Blame History

#include // вывод сообщений
#include <fcntl.h> // открытие файлов #include <sys/mman.h> // mmap и munmap #include <unistd.h> // usleep и close #include // perror #include // для uint32_t

/*

  1. Userspace драйвер GPIO. Управление GPIO Raspberry Pi через mmap обеспечивает прямой доступ к регистрам периферии, минуя медленные системные вызовы. Это реализуется через открытие /dev/mem, мапирование базового адреса GPIO */

#define GPIO_BASE 0x3F200000 // физический адрес начала блока регистров GPIO на SoC BCM2835 #define BLOCK_SIZE 4096 // Размер отображ. памяти Регистры GPIO занимают 41 байт, но мы отображаем целую страницу для простоты. #define TIME_SLEEP 500000 // Время задержки в микросекундах

int main() { // открытие спец.файла физической памяти. Флаги - чтение и запись + отключение кэширования int mem_fd = open("/dev/mem", O_RDWR | O_SYNC); // Если не удалось открыть - вывод ошибки if (mem_fd < 0) { perror("open"); return 1; }

/*
Отображение памяти регистров в виртуальное адресное пространство
mmap создаёт отображение физической памяти, начиная с адреса GPIO_BASE, размером BLOCK_SIZE, в виртуальную память процесса.
NULL – ядро само выбирает адрес для отображения.
BLOCK_SIZE – количество байт.
PROT_READ | PROT_WRITE – разрешено чтение и запись.
MAP_SHARED – изменения видны другим процессам и синхронизируются с файлом (важно для доступа к реальной памяти).
mem_fd – файловый дескриптор /dev/mem.
GPIO_BASE – смещение в файле (физический адрес).
*/  
void* gpio_map = mmap(
    NULL,
    BLOCK_SIZE,
    PROT_READ | PROT_WRITE,
    MAP_SHARED,
    mem_fd,
    GPIO_BASE
);

if (gpio_map == MAP_FAILED) {
    perror("mmap");
    return 1;
}

// Указатель приводится к типу volatile uint32_t*, чтобы:
// Обращаться к памяти 32-битными словами.
// volatile запрещает компилятору оптимизировать обращения, т.к. значения регистров могут меняться аппаратно.
volatile uint32_t* gpio = (volatile uint32_t*)gpio_map;

// GPIO17 = бит 21 в GPFSEL1
gpio[1] &= ~(7 << 21);   // очистить
gpio[1] |=  (1 << 21);   // output

while (true) {
    gpio[7] = (1 << 17);  // set
    usleep(TIME_SLEEP);
    gpio[10] = (1 << 17); // clear
    usleep(TIME_SLEEP);
}
// освобождение ресурсов, при выходе 
munmap(gpio_map, BLOCK_SIZE);
close(mem_fd);

}