C语言 事件驱动程序的排序



我正在尝试在Raspberry pi 3中制作一个Linux内核驱动程序,当操纵杆中的按钮按下时打开LED(将GPIO设置为输出,然后将其设置为输出(,并且还读取该GPIO端口的状态。

我打开 LED 的驱动程序是:

#include<linux/init.h>
#include<linux/module.h>
#include<linux/fs.h>
#include<linux/cdev.h>
#include<linux/slab.h>
#include<asm/uaccess.h>
#include<asm/io.h>
#define ioaddress_SIE_BASE 0x3F200000
#define ioaddress_SIZE 0x38
#define address_LED_on 0x1C
#define address_LED_off 0x28
#define address_LED_estado 0x34
MODULE_LICENSE("Dual BSD/GPL");
static char *nombre="4led";
static unsigned int PrimerMenor=0;
static unsigned int cuenta=1;
static dev_t led_dev_numero;
char *buffer;
int on_off=0;
int leido=0;
static void __iomem *ioaddress_SIE;
struct led_dev *led_dev_puntero;
struct led_dev {
struct cdev led_cdev;
};
int led_open (struct inode *puntero_inode, struct file *puntero_file)
{
struct led_dev *led_dev_puntero;
printk (KERN_INFO "led_SIE: se ha abierto el dispositivo n" );
led_dev_puntero=container_of(puntero_inode->i_cdev, struct led_dev, led_cdev);
puntero_file->private_data=led_dev_puntero;
return 0;
}
int led_release (struct inode *puntero_inode , struct file *puntero_file)
{
printk (KERN_INFO "led_SIE: se ha liberado el dispositivo n" );
return 0;
}
static ssize_t led_read (struct file *puntero_file , char *buffer_user, size_t tamano, loff_t *puntero_offset)
{
unsigned int estado;
unsigned long prueba;
printk (KERN_INFO "led_SIE: leyendo el dispositivo n" );
iowrite32(0x00000000, ioaddress_SIE);
estado=ioread32(ioaddress_SIE + address_LED_estado);
printk("led_SIE: GPIOs 9 to 0 --> 0x%X n", estado);
*buffer=(char ) (estado >> leido );
prueba=copy_to_user(buffer_user, buffer, 1);
printk("led_SIE: GPIOs 9 to 0 --> 0x%X n", *buffer);
if(leido>23){
leido=0;}
else
leido=leido+8;
return 1;
}

static ssize_t led_write (struct file *puntero_file , const char *buffer_user, size_t tamano, loff_t *puntero_offset)
{
unsigned long prueba;
/*printk(KERN_INFO "led_SIE: escribiendo en el dispositivo n");
if(buffer_user[0]!='1'){
if(buffer_user[0]!='0'){
printk(KERN_INFO "led_SIE: Ha ingresado una orden incorrecta! n");
printk(KERN_INFO "led_SIE: Las ordenes son: 1 para encender, 0 para apagar n");
return tamano;
}
}*/
prueba=copy_from_user(buffer, buffer_user, tamano);
printk(KERN_INFO "led_SIE: SE escribió %c en el dispositivo n", buffer);
/*ibuffer_user=(int)buffer_user;*/
/*printk(ibuffer_user);
int    ibuffer = (int) buffer;*/
/*if(buffer_user=='1'){
printk(KERN_INFO "Lee maldita sea n");
}*/
switch(buffer[0]){
case '1':
if(on_off==1){
printk(KERN_INFO "led_SIE: El led ya se encuentra encendido n");
return tamano;
}
on_off=1;
iowrite32(0x00009240, ioaddress_SIE);
iowrite32(0x00000004, ioaddress_SIE + address_LED_on);
iowrite32(0x00000038, ioaddress_SIE + address_LED_off);
break;
case '2':
if(on_off==2){
printk(KERN_INFO "led_SIE: El led ya se encuentra encendido n");
return tamano;
}
on_off=2;
iowrite32(0x00009240, ioaddress_SIE);
iowrite32(0x00000008, ioaddress_SIE + address_LED_on);
iowrite32(0x00000034, ioaddress_SIE + address_LED_off);
break;
case '3':
if(on_off==3){
printk(KERN_INFO "led_SIE: El led ya se encuentra encendido n");
return tamano;
}
on_off=3;
iowrite32(0x00009240, ioaddress_SIE);
iowrite32(0x00000010, ioaddress_SIE + address_LED_on);
iowrite32(0x0000002C, ioaddress_SIE + address_LED_off);
break;
case '4':
if(on_off==4){
printk(KERN_INFO "led_SIE: El led ya se encuentra encendido n");
return tamano;
}
on_off=4;
iowrite32(0x00009240, ioaddress_SIE);
iowrite32(0x00000020, ioaddress_SIE + address_LED_on);
iowrite32(0x0000001C, ioaddress_SIE + address_LED_off);
break;
case '0':
if(on_off==0){
printk(KERN_INFO "led_SIE: El led ya se encuentra apagado n");
return tamano;
}
on_off=0;
iowrite32(0x00009240, ioaddress_SIE);
iowrite32(0x0000003C, ioaddress_SIE + address_LED_off);
break;
default:
return tamano;
}
return tamano;
}

struct file_operations led_fops = {
.owner = THIS_MODULE,
.read = led_read,
.write = led_write,
.open = led_open,
.release = led_release
};
static int hello_init(void)
{
int resultado, error;
printk(KERN_ALERT "Hola, mundon");
resultado=alloc_chrdev_region(&led_dev_numero, PrimerMenor, cuenta, nombre);
if (resultado ==0)
printk(KERN_INFO "Se reservaron los siguientes numeros n Mayor:  %dn Menor: %dn", MAJOR(led_dev_numero), MINOR(led_dev_numero));
else
printk(KERN_INFO "Hubo un error y los numeros no se reservaron. Error:  %dn", resultado);
led_dev_puntero = kmalloc (sizeof(struct led_dev), GFP_ATOMIC);
buffer=kmalloc(8,GFP_ATOMIC);//GFP_KERNEL---Difícil
cdev_init(&led_dev_puntero->led_cdev, &led_fops);
led_dev_puntero->led_cdev.owner=THIS_MODULE;
led_dev_puntero->led_cdev.ops=&led_fops;
error=cdev_add(&led_dev_puntero->led_cdev, led_dev_numero, cuenta);
if(error)
printk (KERN_INFO "error $d al anadir led_dev");
ioaddress_SIE=ioremap(ioaddress_SIE_BASE, ioaddress_SIZE);
printk(KERN_ALERT "ioadress_SIE_BASE fue mapeado a: %p n", ioaddress_SIE);
return 0;
}
module_init(hello_init);
static void hello_exit(void)
{
printk(KERN_ALERT "Adios, mundo crueln");
unregister_chrdev_region(led_dev_numero,cuenta);
cdev_del(&led_dev_puntero->led_cdev);
kfree(led_dev_puntero);
kfree(buffer);
if(on_off==1){
iowrite32(0xFFFFFFFF, ioaddress_SIE + address_LED_off);
}
iounmap(ioaddress_SIE);
}
module_exit(hello_exit);

与驱动程序和操纵杆交互的应用程序是:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
struct js_event {
unsigned int time;      /* event timestamp in milliseconds */
short value;   /* value */
unsigned char type;     /* event type */
unsigned char number;   /* axis/button number */
};
#define JS_EVENT_BUTTON         0x01    /* button pressed/released */
#define JS_EVENT_AXIS           0x02    /* joystick moved */
#define JS_EVENT_INIT           0x80    /* initial state of device */
int main(int argc, char **argv)
{   //Acceso al driver Xdriv
int fd = open ("/dev/input/js0", O_RDONLY);
FILE *archivo;
int  tamano;
int a;int b;
/*Acceso al driver 4_leds
system("sudo chmod 777 /dev/4leds");
archivo=fopen("/dev/4leds" ,"w");
if (archivo==NULL){fputs("No existe el archivo" ,stderr); exit(1);}
*/
if( fd < 0 )
printf( "cannot open devn" );
else
printf( "opened success...:)n" );
struct js_event e;
while( 1 ) //event loop
{
read( fd, &e, sizeof(e) );
//printf( "%d %d %d %dn", e.time, e.value, e.type, e.number );
if( e.type == JS_EVENT_BUTTON || e.type == JS_EVENT_AXIS )
{
if( e.type == JS_EVENT_BUTTON ){
printf( "button#%d value:%dn", (int) e.number, e.value );
switch((int) e.number) {
case 0  ://Btn A, Motor 1---Atrás
if ((int) e.value == 1){
printf("Hola esto es 0n Btn A, Motor 1---Atrás");
char escribe[1] = "1";
//Acceso al driver 4_leds
system("sudo chmod 777 /dev/4leds");
archivo=fopen("/dev/4leds" ,"w");
if (archivo==NULL){fputs("No existe el archivo" ,stderr); exit(1);}
//
fwrite(escribe ,sizeof(char) ,tamano , archivo);//Escribe 1 en driver
fclose(archivo);
sleep(3);               
printf("Este es escribe :%c ",*escribe);}
else{
printf("Hola esto es 0 pero no presionadon");
}
break; 
case 1  ://Btn B, Motor 1---Adelante
if ((int) e.value == 1){
printf("Hola esto es 1n Btn B, Motor 1---Adelante");
char escribe[1] = "2";
//Acceso al driver 4_leds
system("sudo chmod 777 /dev/4leds");
archivo=fopen("/dev/4leds" ,"w");
if (archivo==NULL){fputs("No existe el archivo" ,stderr); exit(1);}
//
fwrite(escribe ,sizeof(char) ,tamano , archivo);//Escribe 2 en driver
fclose(archivo);
sleep(3);               
printf("Este es escribe :%c n",*escribe);}
else{
printf("Hola esto es 1 pero no presionadon");
}
break; 
case 2  ://Btn X, Motor 2---Abajo
if ((int) e.value == 1){
printf("Hola esto es 2 n Btn X, Motor 2---Abajo");
char escribe[1] = "3";
//Acceso al driver 4_leds
system("sudo chmod 777 /dev/4leds");
archivo=fopen("/dev/4leds" ,"w");
if (archivo==NULL){fputs("No existe el archivo" ,stderr); exit(1);}
//
fwrite(escribe ,sizeof(char) ,tamano , archivo);//Escribe 3 en driver
fclose(archivo);
sleep(3);               
printf("Este es escribe :%c n",*escribe);}
else{
printf("Hola esto es 2 pero no presionadon");
}
break; 
case 3  ://Btn Y, Motor 2---Arriba
if ((int) e.value == 1){
printf("Hola esto es 3 n Btn Y, Motor 2---Arriba");
char escribe[1] = "4";
//Acceso al driver 4_leds
system("sudo chmod 777 /dev/4leds");
archivo=fopen("/dev/4leds" ,"w");
if (archivo==NULL){fputs("No existe el archivo" ,stderr); exit(1);}
//
fwrite(escribe ,sizeof(char) ,tamano , archivo);//Escribe 4 en driver
fclose(archivo);
sleep(3);               
printf("Este es escribe :%c n",*escribe);}
else{
printf("Hola esto es 3 pero no presionadon");
}
break; 
case 7  ://Detener
if ((int) e.value == 1){
printf("Hola esto es Start/Stop n");
char escribe[1] = "0";
//Acceso al driver 4_leds
system("sudo chmod 777 /dev/4leds");
archivo=fopen("/dev/4leds" ,"w");
if (archivo==NULL){fputs("No existe el archivo" ,stderr); exit(1);}
//
fwrite(escribe ,sizeof(char) ,tamano , archivo);//Escribe 0 en driver
fclose(archivo);
sleep(3);
printf("Este es escribe :%c n",*escribe);}
else{
printf("Hola esto es 7 pero no presionadon");
}
break; 
default : /* Optional */
printf("Hola esto es default también sirve como stopn");
char escribe[1] = "0";
//Acceso al driver 4_leds
system("sudo chmod 777 /dev/4leds");
archivo=fopen("/dev/4leds" ,"w");
if (archivo==NULL){fputs("No existe el archivo" ,stderr); exit(1);}
//
fwrite(escribe ,sizeof(char) ,tamano , archivo);//Escribe 0 en driver
fclose(archivo);
sleep(3);               
printf("Este es escribe :%c n",*escribe);
}
printf("El último presionado fue: %X n",(char) e.number);}
else{
printf( "axis#%d value:%d n", (int) e.number, e.value );}
}
else
{
printf( "Init Eventsn" );
}
}
return 0;
}

我遇到了分段错误,所以我认为这可能是copy_from_user缓冲区中的内存分配问题......但我现在不知道如何解决它。

我试过在一段时间之前打开文件,然后在每个开关案例中写入它,也打开文件并在开关案例中写入它......等等。

驱动程序与另一个非事件应用程序配合使用时工作正常。

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main(int argc, char **argv){
FILE *archivo;
char escribe[1];
char lee[1];
int  tamano, i;
int registro=0;
int registro2=0;
tamano=1;
printf("introduzca el numero que quiere escribir: ");
scanf("%c" ,escribe);
printf("%c ",*escribe);
system("sudo chmod 777 /dev/4leds");
archivo=fopen("/dev/4leds" ,"w");
if (archivo==NULL){fputs("No existe el archivo" ,stderr); exit(1);}
fwrite(escribe ,sizeof(char) ,tamano , archivo);
printf("El valor escrito fue: %c n" , *escribe);
fclose(archivo);
sleep(3);
/*archivo=fopen("/dev/4leds", "r");
if (archivo==NULL){fputs("No existe el archivo" ,stderr); exit(1);}
for (i=0;i<4;i++)
{
registro=registro << 8;
fread(lee ,tamano*sizeof(char),1,archivo);
registro=registro | *lee;
}
registro2=registro2 | (registro << 24 & 0xFF000000);
registro2=registro2 | (registro << 8  & 0x00FF0000);
registro2=registro2 | (registro >> 8  & 0x0000FF00);
registro2=registro2 | (registro >> 24 & 0x000000FF);
printf("El valor leido es: 0x%X n" , registro2);
fclose(archivo);*/
return 0;
}

感谢您的帮助和建议。很抱歉注释的代码,但我正在测试驱动程序的所有部分。

声明了tamano或元素数量,但从未在main()中定义。

fwrite(escribe ,sizeof(char) ,tamano , archivo);

最新更新