This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

beaglebone black的GPIO的寄存器驱动



beaglebone black使用的是Angstrom系统,现使用下面的驱动控制GPIO,但编译进内核后,系统启动不了,是什么原因?

#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <asm/io.h>


//#define GPIO0 0x44E07000
//#define GPIO1 0x4804C000
//#define GPIO2 0x481AC000
#define GPIO3 0x481AE000
#define GPIO_OE 0x134
//#define GPIO_DATAIN 0x138
#define GPIO_DATAOUT 0x13c
#define GPIO_CLEARDATAOUT 0x190
#define GPIO_SETDATAOUT 0x194
#define GPIO_CTRL 0x130


#define CONTROL_MODULE 0x44E10000
//#define SPIO_CS1 0x960 //gpio0_6
//#define ECAP0_IN 0x964
#define MCASP0_ACLKH 0x990 //gpio3_17
#define MCASP0_FSX 0x994 //gpio3_15


static struct class *leds_class;
static struct device *leds_class_dev;

int majors;

//struct LEDS{
//volatile unsigned long *gpio_oe;
//volatile unsigned long *gpio_datain;
//volatile unsigned long *gpio_dataout;
//volatile unsigned long *gpio_setdataout;
//volatile unsigned long *gpio_cleardataout;
//volatile unsigned long *gpio_ctrl;
//volatile unsigned long *spio_cs1;
//volatile unsigned long *ecap0_in;
 
//}_leds;

struct LEDS{
volatile unsigned long *gpio_oe;
volatile unsigned long *gpio_datain;
volatile unsigned long *gpio_dataout;
volatile unsigned long *gpio_setdataout;
volatile unsigned long *gpio_cleardataout;
volatile unsigned long *gpio_ctrl;
volatile unsigned long *mcasp0_aclkh;
volatile unsigned long *mcasp0_fsx;

}_leds;
struct LEDS *leds = &_leds;

static int led_open(struct inode *inode , struct file *file)
{
 printk("this is open!\n");
 return 0;
}

static int led_close(struct inode *inode , struct file *file)
{
 printk("this is close!\n");
 return 0;
}

static long led_ioctl(struct file *file , unsigned int cmd , 
 unsigned long arg)
{
 printk("cmd is : %d\n" , cmd);

// switch (cmd)
// {
 
// default:
// break;
// }
 return 0; 
}

static ssize_t led_read(struct file *file , char __user *buf , size_t count , loff_t *pos)
{
 printk("count is : %d\n" , count);
 return 0;
}

static ssize_t led_write(struct file *file , const char __user *buf , size_t count , loff_t *pos)
{

 int val;
 copy_from_user(&val,buf,count);
 printk("val is =%d\n",val);
 if (val==1)
 {
 *(leds->gpio_dataout)&=~((0x1<<6)|(0x1<<7));//设置gpio输出高/低电平

 }
 else
 {
 *(leds->gpio_dataout)|=((0x1<<6)|(0x1<<7));

 }

 return 0;
}

static struct file_operations fops = {
 .owner = THIS_MODULE,
 .open = led_open,
 .release = led_close,
 .unlocked_ioctl = led_ioctl,
 .read = led_read,
 .write = led_write,
};


static int __init test_init(void)
{

 majors = register_chrdev(0, "leds_drvS", &fops); // 注册, 告诉内核
 leds_class = class_create(THIS_MODULE, "ledsdrvS"); //自动创建设备节点
 leds_class_dev= device_create(leds_class, NULL, MKDEV(majors, 0), NULL, "ledsS");


 leds->gpio_oe = (volatile unsigned long *)ioremap(GPIO3 + GPIO_OE , sizeof(volatile unsigned long ));
 //leds->gpio_datain = (volatile unsigned long *)ioremap(GPIO3 + GPIO_DATAIN, sizeof(volatile unsigned long ));
 //leds->gpio_dataout = (volatile unsigned long *)ioremap_nocache(GPIO3 + GPIO_DATAOUT, sizeof(volatile unsigned long ));
 leds->gpio_dataout = (volatile unsigned long *)ioremap(GPIO3 + GPIO_DATAOUT, sizeof(volatile unsigned long ));
 leds->gpio_setdataout =( volatile unsigned long *)ioremap(GPIO3 + GPIO_SETDATAOUT, sizeof(volatile unsigned long ));
 leds->gpio_cleardataout = (volatile unsigned long *)ioremap(GPIO3 + GPIO_CLEARDATAOUT , sizeof(volatile unsigned long ));
 leds->gpio_ctrl=(volatile unsigned long *)ioremap(GPIO3+GPIO_CTRL,sizeof(volatile unsigned long ));
 leds->mcasp0_aclkh=(volatile unsigned long *)ioremap(CONTROL_MODULE+MCASP0_ACLKH,sizeof(volatile unsigned long ));
 leds->mcasp0_fsx=(volatile unsigned long *)ioremap(CONTROL_MODULE+MCASP0_FSX,sizeof(volatile unsigned long ));
 printk("insmod the leds module!\n");

 /*
 *配置相关引脚的pin_mux模式;
 *配置相关寄存器;
 *首先是寄存器OE,输出使能;设置0为输出使能;
 *其次是寄存器SETDATAOUT,设置允许输出位;设置1为允许;
 *最后是寄存器DATAOUT,设置输出高低电平;
 */

 *(leds->mcasp0_aclkh)|=(0x7);
 *(leds->mcasp0_fsx)|=(0x7);
 *(leds->gpio_ctrl)&=~(0x1);
 
 
 *(leds->gpio_oe) &= ~((0x1<<6)|(0x1<<7));
 *(leds->gpio_setdataout) |= ((0x1<<6)|(0x1<<7));

// *(leds->gpio_datain) |= ((0x1<<6)|(0x1<<7));
// *(leds->gpio_datain) &= ~((0x1<<6)|(0x1<<7));
 
 *(leds->gpio_dataout) |= ((0x1<<6)|(0x1<<7));
 *(leds->gpio_dataout) &= ~((0x1<<6)|(0x1<<7));

 return 0;
}

static void __exit test_exit(void)
{
 unregister_chrdev(majors, "leds_drvS"); // 卸载
 device_unregister(leds_class_dev);
 class_destroy(leds_class);
// *(leds->gpio_cleardataout) |= 0xffffffff;

 iounmap(leds->gpio_oe);
 //iounmap(leds->gpio_datain);
 iounmap(leds->gpio_dataout);
 iounmap(leds->gpio_setdataout);
 iounmap(leds->gpio_cleardataout);
 iounmap(leds->mcasp0_aclkh);
 iounmap(leds->gpio_ctrl);
 iounmap(leds->mcasp0_fsx);

}

module_init(test_init);
module_exit(test_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("xiaogao");
MODULE_DESCRIPTION("Class test");

  • 用insmode试过么?加载会出问题么?

  • 用insmod 时出现Segmentation fault,用dmesg查看,多了以下信息:

    [ 96.695288] insmod the leds module!
     [ 96.695310] Unhandled fault: external abort on non-linefetch (0x1028) at 0xfa1ae130
     [ 96.703349] Internal error: : 1028 [#1] SMP THUMB2
     [ 96.708387] Modules linked in: gpio(O+)
     [ 96.712423] CPU: 0 Tainted: G W O (3.8.13 #10)
     [ 96.718200] PC is at test_init+0xbf/0x133 [gpio]
     [ 96.723052] LR is at test_init+0xa2/0x133 [gpio]
     [ 96.727900] pc : [<bf8020c0>] lr : [<bf8020a3>] psr: 60000033
     sp : dcf07e58 ip : 00000021 fp : bf800294
     [ 96.739948] r10: 00000000 r9 : bf802001 r8 : bf8002d0
     [ 96.745441] r7 : 00000001 r6 : 00000000 r5 : bf8003e4 r4 : bf800218
     [ 96.752290] r3 : fa1ae130 r2 : 00000027 r1 : 00000001 r0 : 00000000
     [ 96.759144] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA Thumb Segment user
     [ 96.766815] Control: 50c5387d Table: 9c9e0019 DAC: 00000015
     [ 96.772855] Process insmod (pid: 618, stack limit = 0xdcf06240)
     [ 96.779077] Stack: (0xdcf07e58 to 0xdcf08000)
     [ 96.783648] 7e40: bf8001d2 00000000
     [ 96.792231] 7e60: 00000000 bf800288 dcf07f58 c000868d bf802001 00000000 00000001 bf800288
     [ 96.800819] 7e80: bf800288 dcf07f58 00000000 00000001 bf8002d0 dca77780 00000001 c005b553
     [ 96.809422] 7ea0: bf800294 00007fff c0059379 00000000 fa2000d8 0000001c 0000002c c065eacc
     [ 96.818006] 7ec0: bf8003c4 c0398f80 e09f4530 dcf07eec b6f34cc4 20000033 ffffffff c05c6870
     [ 96.826593] 7ee0: 00180011 c000c1b5 e09f6000 b6f4a000 00000248 00000000 00000000 00000000
     [ 96.835176] 7f00: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
     [ 96.843758] 7f20: 00000000 00000000 00000000 00000000 20000033 00000000 b6f44000 b6f34cc4
     [ 96.852365] 7f40: 00000080 c000c824 dcf06000 00000000 00000000 c005b7d7 e09f0000 000062c8
     [ 96.860959] 7f60: e09f3e78 e09f3cb4 e09f60a8 00000404 00000644 00000000 00000000 00000000
     [ 96.869542] 7f80: 0000002b 0000002c 00000015 00000012 00000010 00000000 00000000 00000000
     [ 96.878123] 7fa0: 000210a0 c000c681 00000000 00000000 b6f44000 000062c8 b6f34cc4 00000002
     [ 96.886708] 7fc0: 00000000 00000000 000210a0 00000080 00021088 000062c8 b6f34cc4 00000000
     [ 96.895295] 7fe0: b6e9a890 bea64b98 b6f2d734 b6e9a8a0 60000010 b6f44000 9fefe821 9fefec21
     [ 96.903914] [<bf8020c0>] (test_init+0xbf/0x133 [gpio]) from [<c000868d>] (do_one_initcall+0x61/0xec)
     [ 96.913527] [<c000868d>] (do_one_initcall+0x61/0xec) from [<c005b553>] (load_module+0x10ff/0x1308)
     [ 96.922931] [<c005b553>] (load_module+0x10ff/0x1308) from [<c005b7d7>] (sys_init_module+0x7b/0x8e)
     [ 96.932342] [<c005b7d7>] (sys_init_module+0x7b/0x8e) from [<c000c681>] (ret_fast_syscall+0x1/0x46)
     [ 96.941749] Code: 0207 601a 6823 695b (681a) f022
     [ 96.946775] ---[ end trace 09c7d93bcbc542ab ]---
  • 如果是GPIO控制LED的驱动,可以参考SDK06或者SDK07源代码目录下的\drivers\leds\leds-gpio.c来写,你的驱动感觉上有些问题。

  • 当把以下注释掉,insmod接没问题,那要怎样才能操作这些寄存器呢?

    //*(leds->mcasp0_aclkh)|=(0x7);
    // *(leds->mcasp0_fsx)|=(0x7);
    // *(leds->gpio_ctrl)&=~(0x1);
     
     
    // *(leds->gpio_oe) &= ~((0x1<<6)|(0x1<<7));
    // *(leds->gpio_setdataout) |= ((0x1<<6)|(0x1<<7));
    
    
    //// *(leds->gpio_datain) |= ((0x1<<6)|(0x1<<7));
    //// *(leds->gpio_datain) &= ~((0x1<<6)|(0x1<<7));
     
    // *(leds->gpio_dataout) |= ((0x1<<6)|(0x1<<7));
     //*(leds->gpio_dataout) &= ~((0x1<<6)|(0x1<<7));
  • 可能是地址操作的问题

    gpio的配置,使能,以及赋值,最好用系统自带的函数

    gpio_set_value();

    gpio_request();

    等等‘

    可参考http://bbs.eeworld.com.cn/thread-327156-1-1.html