Paso 6: Escribir el módulo del núcleo
Crear un archivo de C llamado alcance-drv.c que contiene el código siguiente
#include < linux/kernel.h > #include < linux/module.h > #include < linux/fs.h > #include < asm/uaccess.h > < linux/time.h > del #include #include < linux/io.h > #include < linux/vmalloc.h > int init_module(void); void cleanup_module(void); Static int device_open (struct nodo *, struct file *); Static int device_release (struct nodo *, struct file *); ssize_t estática device_read (struct file *, char *, size_t, loff_t *); ssize_t estática device_write (struct file *, char const *, size_t, loff_t *); #define éxito 0 #define nombre_dispositivo "chardev" #define BUF_LEN 80 / * ajuste y macros para las conexiones de GPIO * / #define BCM2708_PERI_BASE 0 x 20000000 #define GPIO_BASE (BCM2708_PERI_BASE + 0 x 20000000) #define INP_GPIO(g) * (gpio.addr + ((g) / 10)) & = ~ (7 << (((g) % 10) * 3)) #define SET_GPIO_ALT(g,a) * (gpio.addr + (((g) / 10))) | = (((a) < = 3? () un) + 4:(a)==4?3:2) << (((g) % 10) * 3)) / * reloj GPIO * / #define CLOCK_BASE (BCM2708_PERI_BASE + 0x00101000) #define GZ_CLK_BUSY (1 << 7) / * número de muestras para capturar * / #define SAMPLE_SIZE 10000 / * pines GPIO definir * / / * ADC 1 * / #define BIT0_PIN 7 #define BIT1_PIN 8 #define BIT2_PIN 9 #define BIT3_PIN 10 #define BIT4_PIN 11 #define BIT5_PIN 25 / * ADC 2 * / #define BIT0_PIN2 17 #define BIT1_PIN2 18 #define BIT2_PIN2 22 #define BIT3_PIN2 23 #define BIT4_PIN2 24 #define BIT5_PIN2 27 struct bcm2835_peripheral {unsigned largo addr_p; int mem_fd; void * mapa; volátil unsigned int * addr;}; Static int map_peripheral (struct bcm2835_peripheral * p); Static void unmap_peripheral (struct bcm2835_peripheral * p); Static void readScope(void); Static int mayor; Static int Device_Open = 0; Static char mensaje [BUF_LEN]; Static char * msg_Ptr; Static unsigned char * buf_p; Static struct file_operations fops = {leer = device_read, .escriben = device_write, abrir = device_open, .release = device_release}; Static struct bcm2835_peripheral myclock = {CLOCK_BASE}; Static struct bcm2835_peripheral gpio = {GPIO_BASE}; struct DataStruct {uint32_t Buffer [SAMPLE_SIZE]; tiempo de uint32_t;}; struct DataStruct dataStruct; Static unsigned char * ScopeBufferStart; Static unsigned char * ScopeBufferStop; Static int map_peripheral (struct bcm2835_peripheral * p) {p -> addr =(uint32_t *) ioremap (GPIO_BASE, 41 * 4); return 0;} static void unmap_peripheral (struct bcm2835_peripheral * p) {iounmap (p -> addr);} static void readScope() {int contador = 0; estructura timespec ts_start, ts_stop; local_irq_disable(); local_fiq_disable(); getnstimeofday(&ts_start); while(counter<SAMPLE_SIZE) {dataStruct.Buffer[counter++]= * (gpio.addr + 13);} getnstimeofday(&ts_stop); local_fiq_enable(); local_irq_enable(); dataStruct.time = timespec_to_ns (& ts_stop) - timespec_to_ns(&ts_start); buf_p = (unsigned char *) & dataStruct; ScopeBufferStart = (unsigned char *) & dataStruct; ScopeBufferStop = ScopeBufferStart + sizeof (struct DataStruct); } int init_module(void) {struct bcm2835_peripheral * p = & myclock; int speed_id = 6; Principales = register_chrdev (0, nombre_dispositivo, & fops); Si (importante < 0) {han (KERN_ALERT "reg dev char fail %d\n",Major); return mayor;} ficheros (KERN_INFO "Importante número %d.\n", mayor); ficheros (KERN_INFO "creado un dev archivo con\n"); ficheros (KERN_INFO "'mknod /dev/%s % c d 0'. \n", nombre_dispositivo, mayor); Si (map_peripheral(&gpio) == -1) {han (KERN_ALERT "Error de mapa GPIO\n"); vuelta -1;} INP_GPIO(BIT0_PIN); INP_GPIO(BIT1_PIN); INP_GPIO(BIT2_PIN); INP_GPIO(BIT3_PIN); INP_GPIO(BIT4_PIN); INP_GPIO(BIT5_PIN); INP_GPIO(BIT0_PIN2); INP_GPIO(BIT1_PIN2); INP_GPIO(BIT2_PIN2); INP_GPIO(BIT3_PIN2); INP_GPIO(BIT4_PIN2); INP_GPIO(BIT5_PIN2); / * reloj señal al pin 4 * / p -> addr =(uint32_t *) ioremap (CLOCK_BASE, 41 * 4); INP_GPIO(4); SET_GPIO_ALT(4,0); *(myclock.addr+28)=0x5A000000 | speed_id; while(*(myclock.addr+28) & GZ_CLK_BUSY) {}; *(myclock.addr+29)= 0x5A000000 | (0x32 << 12) | 0; *(myclock.addr+28)=0x5A000000 | speed_id; devolver el éxito; } void cleanup_module(void) {unregister_chrdev (Major, nombre_dispositivo); unmap_peripheral (& gpio); unmap_peripheral(&myclock);} static int device_open (struct inode * inodo, struct file * archivo) {static int contador = 0; if(Device_Open) volver - EBUSY; Device_Open ++; sprintf (msg, "Llamado device_open %d times\n", contador ++); msg_Ptr = msg; readScope(); try_module_get(THIS_MODULE); devolver el éxito; } static int device_release (struct inode * inodo, struct file * archivo) {Device_Open-; module_put(THIS_MODULE); return 0;} ssize_t estática device_read (struct file * filp, char * buffer, size_t longitud, loff_t * offset) {int bytes_read = 0; si (* msg_Ptr == 0) return 0; mientras que (longitud & & buf_p < ScopeBufferStop) {si (0! = put_user(*(buf_p++) buffer ++)) han (KERN_INFO "Problema con copy\n"); longitud--; bytes_read ++; } volver bytes_read; } device_write ssize_t estática (struct file * filp, const char * buff, size_t len, loff_t * off) {han (KERN_ALERT "esta operación no es compatible. \n"); volver - EINVAL;}
El programa contiene algunas funciones importantes. Para lograr un módulo del núcleo. el módulo necesita algunas funciones de entrada especial. Una de estas funciones es el init_module(), que se llama cuando se carga el módulo del kernel. Se llama a la función device_open() cuando se abre el archivo de dispositivo asociado con el módulo del kernel. Abrir el archivo de dispositivo hace que el ADC que leer 10.000 veces, donde los resultados se guardan en la memoria. La función device_release() es llamada cuando el dispositivo está cerrado. La función device_read() se llama cuando un proceso lee el archivo de dispositivo. Esta función devuelve las mediciones que se hicieron cuando se abrió el archivo de dispositivo. La última función device_write() es necesario para manejar el caso cuando un proceso intenta escribir en el fichero de dispositivo.
Más sobre el módulo de kernel: http://www.tldp.org/LDP/lkmpg/2.6/html/lkmpg.html
Se adjunta el programa completo, puedes subirlo utilizando FileZilla.