您的位置:首页 > 运维架构 > Linux

在linux源码树下,编译arm驱动

2017-12-29 09:27 162 查看
kernel版本:linux3.2.0

关于app调试,驱动调试使用nfs挂载目标板是个不错的选择。

1、编写驱动模块

/*

 * linux/arch/arm/mach-omap2/gpmc-bus.c

 *

 * Copyright (C) 2017 WLS 

 * Contact: ranruoyu

 * Version: 1.0

 * 

 * 2017.11.29

 *

 */

#include <linux/init.h>

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/platform_device.h>

#include <linux/gpio.h>

#include <linux/delay.h>

#include <linux/interrupt.h>

#include <linux/io.h>

#include <linux/cdev.h>

#include <linux/semaphore.h>

#include <linux/slab.h>

#include <linux/fs.h>

#include <asm/uaccess.h>

#include <plat/board.h>

#include <plat/gpmc.h>

#define USER_BUFF_SIZE 128

struct extgpmc_dev {

dev_t devt; //device id

struct cdev icdev; // char device

struct semaphore sem;

struct class *class; //??

char *user_buff;

};

static struct extgpmc_dev extgpmc_dev;

unsigned long mem_base;

static void __iomem *extgpmc_base;

//static void __iomem *gpmc_base;

/* GPMC register offsets */

#define GPMC_REVISION 0x00

#define GPMC_SYSCONFIG 0x10

#define GPMC_SYSSTATUS 0x14

#define GPMC_IRQSTATUS 0x18

#define GPMC_IRQENABLE 0x1c

#define GPMC_TIMEOUT_CONTROL 0x40

#define GPMC_ERR_ADDRESS 0x44

#define GPMC_ERR_TYPE 0x48

#define GPMC_CONFIG 0x50

#define GPMC_STATUS 0x54

#define GPMC_PREFETCH_CONFIG1 0x1e0

#define GPMC_PREFETCH_CONFIG2 0x1e4

#define GPMC_PREFETCH_CONTROL 0x1ec

#define GPMC_PREFETCH_STATUS 0x1f0

#define GPMC_ECC_CONFIG 0x1f4

#define GPMC_ECC_CONTROL 0x1f8

#define GPMC_ECC_SIZE_CONFIG 0x1fc

#define GPMC_ECC1_RESULT 0x200

#define GPMC_ECC_BCH_RESULT_0 0x240

#define GPMC_BASE_ADDR 0x50000000

#define GPMC_CS 2

#define GPMC_CS0 0x60

#define GPMC_CS_SIZE 0x30

#define STNOR_GPMC_CONFIG1 0x28601000

#define STNOR_GPMC_CONFIG2 0x00011001

#define STNOR_GPMC_CONFIG3 0x00020201

#define STNOR_GPMC_CONFIG4 0x08031003

#define STNOR_GPMC_CONFIG5 0x000f1111

#define STNOR_GPMC_CONFIG6 0x0f030080

static const u32 gpmc_nor[7] = {

STNOR_GPMC_CONFIG1,

STNOR_GPMC_CONFIG2,

STNOR_GPMC_CONFIG3,

STNOR_GPMC_CONFIG4,

STNOR_GPMC_CONFIG5,

STNOR_GPMC_CONFIG6, 0

};

static ssize_t extgpmc_write(struct file *filp, const char __user *buff,

size_t count, loff_t *f_pos)

{
ssize_t status;
size_t len = USER_BUFF_SIZE - 1;
int i,tmp;
printk(KERN_ALERT "extgpmc_write\n");
if (count == 0)
return 0;
printk(KERN_ALERT "check down_interruptible(&extgpmc_dev.sem) extgpmc_write\n");
if (down_interruptible(&extgpmc_dev.sem))
return -ERESTARTSYS;

if (len > count)
len = count;

memset(extgpmc_dev.user_buff, 0, USER_BUFF_SIZE);

if (copy_from_user(extgpmc_dev.user_buff, buff, len)) {
status = -EFAULT;
printk(KERN_ALERT "status = -EFAULT extgpmc_write\n");
goto extgpmc_write_done;
}

/* do something with the user data */

printk("extgpmc_write \n");

/*write 8 bit once mode ,test io out ;CPLD is 16bit */
//for (i = 0; i < len; i++) {
// tmp = extgpmc_dev.user_buff | (extgpmc_dev.user_buff[i+1]<<8); 
// writew(tmp,extgpmc_base+i);
//}

//for (i = 0; i < len; i++) {
// printk("0x%x ",extgpmc_dev.user_buff); 
//}

tmp = extgpmc_dev.user_buff;
writeb(tmp,extgpmc_base);

printk("0x%x ",tmp); 

printk("\n");

extgpmc_write_done:

up(&extgpmc_dev.sem);

return status;

}

static ssize_t extgpmc_read(struct file *filp, char __user *buff, 

size_t count, loff_t *offp)

{
ssize_t status;
size_t len;

// int i,tmp;

/* 

Generic user progs like cat will continue calling until we 

return zero. So if *offp != 0, we know this is at least the

second call.

*/
printk(KERN_ALERT "extgpmc_read\n");
if (*offp > 0)
return 0;

printk(KERN_ALERT "check down_interruptible(&extgpmc_dev.sem)..\n");
if (down_interruptible(&extgpmc_dev.sem)) 
return -ERESTARTSYS;

strcpy(extgpmc_dev.user_buff, "extgpmc driver data goes here\n");

len = strlen(extgpmc_dev.user_buff);

if (len > count)
len = count;

if (copy_to_user(buff, extgpmc_dev.user_buff, len)) {
status = -EFAULT;
printk(KERN_ALERT "status = -EFAULT..\n");
goto extgpmc_read_done;
}
printk(KERN_ALERT "read ok\n");

extgpmc_read_done:

up(&extgpmc_dev.sem);

return status;

}

static int extgpmc_open(struct inode *inode, struct file *filp)

{
int status = 0;
printk(KERN_ALERT "extgpmc_open(struct inode *inode, struct file *filp)");

if (down_interruptible(&extgpmc_dev.sem)) 
return -ERESTARTSYS;

if (!extgpmc_dev.user_buff) {
extgpmc_dev.user_buff = kmalloc(USER_BUFF_SIZE, GFP_KERNEL);
//kzalloc
if (!extgpmc_dev.user_buff) {
printk(KERN_ALERT "extgpmc_open: user_buff alloc failed\n");
status = -ENOMEM;
}else
printk(KERN_ALERT "extgpmc_dev.user_buff kmalloc OK \n");
}else
printk(KERN_ALERT "extgpmc_dev.user_buff is true \n");

up(&extgpmc_dev.sem);

return status;

}

static const struct file_operations extgpmc_fops = {
.owner = THIS_MODULE,
.open =
extgpmc_open,
.read =
extgpmc_read,
.write = extgpmc_write,

};

static int __init extgpmc_init_cdev(void)

{
int error;
u32 val;
printk(KERN_ALERT "extgpmc_init_cdev");
extgpmc_dev.devt = MKDEV(0, 0);

error = alloc_chrdev_region(&extgpmc_dev.devt, 0, 1, "extgpmc");
if (error) {
printk(KERN_ALERT "extgpmc alloc_chrdev_region() failed: %d\n", error);
return error;
}

cdev_init(&extgpmc_dev.icdev, &extgpmc_fops);
extgpmc_dev.icdev.owner = THIS_MODULE;

error = cdev_add(&extgpmc_dev.icdev, extgpmc_dev.devt, 1);
if (error) {
printk(KERN_ALERT "extgpmc cdev_add() failed: %d\n", error);
unregister_chrdev_region(extgpmc_dev.devt, 1);
return error;
}

printk("extgpmc Getting Chip Select\n");

// val = 0xf64;

// gpmc_cs_write_reg(GPMC_CS, GPMC_CS_CONFIG7, val);

//gpmc_base = ioremap(GPMC_BASE_ADDR, SZ_4K);
val = gpmc_read_reg(GPMC_REVISION);
printk("extgpmc GPMC revision %d.%d\n", (val >> 4) & 0x0f, val & 0x0f);

gpmc_write_reg(GPMC_IRQENABLE, 0);
gpmc_write_reg(GPMC_TIMEOUT_CONTROL, 0);

gpmc_cs_write_reg(GPMC_CS, GPMC_CS_CONFIG1, gpmc_nor[0]);
gpmc_cs_write_reg(GPMC_CS, GPMC_CS_CONFIG2, gpmc_nor[1]);
gpmc_cs_write_reg(GPMC_CS, GPMC_CS_CONFIG3, gpmc_nor[2]);
gpmc_cs_write_reg(GPMC_CS, GPMC_CS_CONFIG4, gpmc_nor[3]);
gpmc_cs_write_reg(GPMC_CS, GPMC_CS_CONFIG5, gpmc_nor[4]);
gpmc_cs_write_reg(GPMC_CS, GPMC_CS_CONFIG6, gpmc_nor[5]);

val = gpmc_cs_read_reg(GPMC_CS, GPMC_CS_CONFIG7);
printk("Gextgpmc PMC_CS_CONFIG7 value 0x%x\n", val);

if (gpmc_cs_request(GPMC_CS, SZ_2K, (unsigned long *)&mem_base) < 0){
printk(KERN_ERR "extgpmc Failed request for GPMC mem for usrp_e\n");
return -1;
}
printk("extgpmc Got CS0, address = %lx\n", mem_base);

if (!request_mem_region(mem_base, SZ_2K, "mem_extgpmc")) {
printk(KERN_ERR "extgpmc Request_mem_region failed.\n");
gpmc_cs_free(GPMC_CS);
return -1;
}
printk(KERN_ERR "extgpmc Request_mem_region OK.\n");
extgpmc_base = ioremap(mem_base, SZ_2K);

return 0;

}

static int __init extgpmc_init_class(void)

{
struct device *device;

extgpmc_dev.class = class_create(THIS_MODULE, "extgpmc");

if (IS_ERR(extgpmc_dev.class)) {
printk(KERN_ALERT "extgpmc class_create(extgpmc) failed\n");
return PTR_ERR(extgpmc_dev.class);
}

device = device_create(extgpmc_dev.class, NULL, extgpmc_dev.devt, NULL, "extgpmc");

if (IS_ERR(device)) {
class_destroy(extgpmc_dev.class);
printk(KERN_ALERT "extgpmc class_create(extgpmc) IS_ERR(device)\n");
return PTR_ERR(device);
}

printk(KERN_ALERT "extgpmc class_create(extgpmc) OK \n");

return 0;

}

static int __init extgpmc_init(void)

{
printk(KERN_INFO "extgpmc_init()\n");

memset(&extgpmc_dev, 0, sizeof(struct extgpmc_dev));

sema_init(&extgpmc_dev.sem, 1);

if (extgpmc_init_cdev())
goto init_fail_1;

if (extgpmc_init_class())
goto init_fail_2;

printk(KERN_INFO "extgpmc_init() OK \n");

return 0;

init_fail_2:
cdev_del(&extgpmc_dev.icdev);
unregister_chrdev_region(extgpmc_dev.devt, 1);
printk(KERN_INFO "extgpmc_init() init_fail_2 \n");

init_fail_1:
printk(KERN_INFO "extgpmc_init() init_fail_1 \n");
return -1;

}

module_init(extgpmc_init);

static void __exit extgpmc_exit(void)

{
printk(KERN_INFO "extgpmc_exit()\n");

device_destroy(extgpmc_dev.class, extgpmc_dev.devt);
class_destroy(extgpmc_dev.class);

cdev_del(&extgpmc_dev.icdev);
unregister_chrdev_region(extgpmc_dev.devt, 1);

release_mem_region(mem_base, SZ_2K);
gpmc_cs_free(GPMC_CS);
iounmap(extgpmc_base);

if (extgpmc_dev.user_buff)
kfree(extgpmc_dev.user_buff);

}

module_exit(extgpmc_exit);

MODULE_AUTHOR("ranruoyu");

MODULE_DESCRIPTION("extgpmc driver");

MODULE_LICENSE("Dual BSD/GPL");

MODULE_VERSION("0.1");

2、编写Makefile

ARCH=arm

obj-m += extgpmc.o

KDIR := /opt/EmbedSky/TQ3358/Kernel_3.2_TQ3358_for_Linux_v2.0  

PWD = $(shell pwd)

all:
make -C $(KDIR) M=$(PWD) modules

clean:
rm -rf *.o

3、make 并查看

4、将文件拷贝到nfs挂载文件系统下,再测试

[root@EmbedSky /opt]# chmod 777 extgpmc.ko

[root@EmbedSky /opt]# insmod extgpmc.ko 

extgpmc_init()

extgpmc_init_cdevextgpmc Getting Chip Select

extgpmc GPMC revision 6.0

Gextgpmc PMC_CS_CONFIG7 value 0xf00

extgpmc Got CS0, address = 1000000

extgpmc Request_mem_region OK.

extgpmc class_create(extgpmc) OK 

extgpmc_init() OK 

[root@EmbedSky /opt]# rmmod extgpmc.ko 

[root@EmbedSky /opt]# dmesg | tail -3

extgpmc Request_mem_region OK.

extgpmc class_create(extgpmc) OK 

extgpmc_init() OK 

[root@EmbedSky /opt]# 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  驱动编译 335 gpmc