Вот пример управления пином к которому подключен светодиод с помощью системного вызова mmap
Код
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#define PC22 (1 << 22)
#define MAP_SIZE 4096Ul
#define MAP_MASK (MAP_SIZE - 1)
#define PIOA_BASE 0xFFFFF400
#define PIOB_BASE 0xFFFFF600
#define PIOC_BASE 0xFFFFF800
#define PIOD_BASE 0xFFFFFA00
typedef volatile unsigned int AT91_REG;
typedef struct _AT91S_PIO {
AT91_REG PIO_PER; /* PIO Enable Register */
...
AT91_REG PIO_OWSR; /* Output Write Status Register */
} AT91S_PIO, *AT91PS_PIO;
AT91S_PIO *pio_map(unsigned int piobase)
{
int fd; //дискриптор файла-псевдоустройства /dev/mem
void *base; //начальный адрес области памяти,
//в которую отображен /dev/mem
AT91S_PIO *pio; //структура регистров порта GPIO
off_t addr = piobase; //базовый адрес порта GPIO
if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1)
{
fprintf(stderr, "Cannot open /dev/mem.\n");
exit(EXIT_FAILURE);
}
fprintf(stderr, "/dev/mem opened.\n");
base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
fd, addr & ~MAP_MASK);
if (base == (void *) -1)
{
fprintf(stderr, "Cannot open /dev/mem.\n");
exit(EXIT_FAILURE);
}
fprintf(stderr, "Memory mapped at address %p.\n", base);
pio = base + (addr & MAP_MASK); //«корректировка» адреса
//порта GPIO
return pio;
}
void pio_enable(AT91S_PIO * pio, int mask)
{
pio->PIO_PER = mask; /* Enable PIO */
}
void pio_output_enable(AT91S_PIO * pio, int mask)
{
pio->PIO_OER = mask;
}
void pio_out(AT91S_PIO * pio, int mask, int val)
{
if (val == 0)
pio->PIO_CODR = mask;
else
pio->PIO_SODR = mask;
}
int pio_in(AT91S_PIO * pio, int mask)
{
return (pio->PIO_PDSR & mask);
}
int main(void)
{
int state = 0;
unsigned int mask = PC22;
AT91S_PIO *pioc;
pioc = pio_map(PIOC_BASE);
pio_enable(pioc, mask);
pio_output_enable(pioc, mask);
while (1)
{
pio_out(pioc, PC22, state);
state = !state;
usleep(1 * 1000 * 1000);
}
return 0;
}
А вот пример обработки нажатия кнопки через драйвер:
Код
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <mach/gpio.h>
#define LED AT91_PIN_PB7
static irqreturn_t btn_int(int irq, void *dev_id)
{
if (at91_get_gpio_value(AT91_PIN_PA24) == 1)
{
printk(KERN_ALERT "111");
at91_set_gpio_value(LED, 0);
}
else
{
at91_set_gpio_value(LED, 1);
}
return IRQ_HANDLED;
}
static __init int driver_init(void)
{
printk(KERN_ALERT "driver init start...\n");
at91_set_gpio_output(LED, 1);
at91_set_gpio_value(LED, 0);
at91_set_gpio_input(AT91_PIN_PA24, 1);
at91_set_deglitch(AT91_PIN_PA24, 1);
if (request_irq(AT91_PIN_PA24, btn_int, 0, "btn_int", NULL))
{
printk(KERN_ALERT "request_irq error\n");
return -EBUSY;
}
return 0;
}
static __exit void driver_exit(void)
{
free_irq(AT91_PIN_PA24, NULL);
printk(KERN_ALERT "driver exit\n");
}
module_init(driver_init);
module_exit(driver_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("External Interrupt driver");