当前位置:文档之家› linux驱动学习笔记LED

linux驱动学习笔记LED

LED驱动学习:是一个char字符类型的驱动//配置模式为输出端口static unsigned int led_cfg_table [] = {S3C2410_GPB5_OUTP,S3C2410_GPB6_OUTP,S3C2410_GPB7_OUTP,S3C2410_GPB8_OUTP,};s3c2410_gpio_cfgpin(S3C2410_GPB5, S3C2410_GPB5_OUTP);s3c2410_gpio_cfgpin(37, 0x01 << 10);这个在\arch\arm\mach-s3c2410\include\mach\regs-gpio.h中定义#define S3C2410_GPB5 S3C2410_GPIONO(S3C2410_GPIO_BANKB, 5) #define S3C2410_GPB5_INP (0x00 << 10)#define S3C2410_GPB5_OUTP (0x01 << 10)#define S3C2410_GPB5_nXBACK (0x02 << 10)S3C2410_GPIONO(S3C2410_GPIO_BANKB, 5)#define S3C2410_GPIONO(bank,offset) ((bank) + (offset))#define S3C2410_GPIO_BANKA (32*0)#define S3C2410_GPIO_BANKB(32*1)static int __init dev_init(void){int ret;int i;for (i = 0; i < 4; i++) {s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);s3c2410_gpio_setpin(led_table[i], 0);}在驱动的初始化函数中经常看到,__init 前缀,这个在下面文件中定义file:/include/linux/init.h• /* These macros are used to mark some functions or•* initialized data (doesn't apply to uninitialized data)•* as `initialization' functions. The kernel can take this•* as hint that the function is used only during the initialization •* phase and free up used memory resources after•*•* Usage:•* For functions:•*•* You should add __init immediately before the function name, like: •*•* static void __init initme(int x, int y)•* {•* extern int z; z = x * y;•* }主要是将这个函数放在init段section中,这样可以在执行完成后,释放内存。

void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function){void __iomem *base = S3C24XX_GPIO_BASE(pin);unsigned long mask;unsigned long con;unsigned long flags;if (pin < S3C2410_GPIO_BANKB) {mask = 1 << S3C2410_GPIO_OFFSET(pin);} else {mask = 3 << S3C2410_GPIO_OFFSET(pin)*2; //3<<(37*2) }switch (function) {case S3C2410_GPIO_LEA VE:mask = 0;function = 0;break;case S3C2410_GPIO_INPUT:case S3C2410_GPIO_OUTPUT:case S3C2410_GPIO_SFN2:case S3C2410_GPIO_SFN3:if (pin < S3C2410_GPIO_BANKB) {function -= 1;function &= 1;function <<= S3C2410_GPIO_OFFSET(pin);} else {function &= 3;function <<= S3C2410_GPIO_OFFSET(pin)*2;}}/* modify the specified register wwith IRQs off */local_irq_save(flags);con = __raw_readl(base + 0x00);con &= ~mask;con |= function;__raw_writel(con, base + 0x00);local_irq_restore(flags);}#define S3C24XX_GPIO_BASE(x) S3C2410_GPIO_BASE(x)#define S3C2410_GPIO_BASE(pin) ((((pin) & ~31) >> 1) + S3C24XX_V A_GPIO)S3C24XX_V A_GPIO这个在\arch\arm\plat-s3c24xx\include\plat\map.h中定义,这个是Memory Map的定义:#define S3C2410_PA_GPIO (0x)#define S3C24XX_V A_GPIO ((S3C24XX_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_V A_UART)#define S3C24XX_SZ_GPIO SZ_1M其中PA表示Physical Address,V A表示Virtual Address由pdf中的GPIO的定义可以看出是一致的。

/* UARTs */#define S3C24XX_V A_UART S3C_V A_UART#define S3C2410_PA_UART (0x)#define S3C_V A_UART S3C_ADDR(0x01000000) /* UART */#define S3C_ADDR(x) (S3C_ADDR_BASE + (x))#define S3C_ADDR_BASE(0xF4000000)__iomem是I/O空间的表示可能不同。

当使用__iomem时,compiler会忽略对变量的检查(因为用的是void __iomem)。

但sparse会对它进行检查,当__iomem的指针和正常的指针混用时,就会发出一些warnings 有个地方讲不通:(这个地方应该是都不满足switch的条件,所以,function不改变)#define S3C2410_GPIO_LEA VE (0xFFFFFFFF)#define S3C2410_GPIO_INPUT (0xFFFFFFF0) /* not available on A */#define S3C2410_GPIO_OUTPUT (0xFFFFFFF1)#define S3C2410_GPIO_IRQ (0xFFFFFFF2) /* not available for all */#define S3C2410_GPIO_SFN2 (0xFFFFFFF2) /* bank A => addr/cs/nand */#define S3C2410_GPIO_SFN3 (0xFFFFFFF3) /* not available on A */而#define S3C2410_GPB5_OUTP (0x01 << 10)所以,s3c2410_gpio_cfgpin(S3C2410_GPB5, S3C2410_GPB5_OUTP);switch (function)根本对不上号?#define __raw_readl(p) (*(unsigned long *)(p))#define __raw_writel(v,p) (*(unsigned long *)(p) = (v))*******************************static struct miscdevice misc = {.minor = MISC_DYNAMIC_MINOR,.name = DEVICE_NAME,.fops = &dev_fops,};驱动注册时,如果次号指定MISC_DYNAMIC_MINOR,则进行动态分配。

#define DEVICE_NAME "leds"include\linux在这个头文件中主要是misc(混合)设备注册和注销:其它类型---不能严格划分的设备类型,也叫混合类型有:1.结构体:struct miscdevice {int minor;const char *name;const struct file_operations *fops;struct list_head list;struct device *parent;struct device *this_device;};2.misc设备注册:extern int misc_register(struct miscdevice * misc);misc设备注销:extern int misc_deregister(struct miscdevice * misc);说明:上面的结构体是注册混合设备所需要的参数。

主要有:minor:次设备号,所有的misc设备共用一个主设备号,所以注册misc设备时只要次设备号就可以了。

利用次设备号来区分设备的。

name:misc设备名。

*fops:misc设备文件操作结构体。

其它三个参数很少用。

杂项设备(misc device)杂项设备也是在嵌入式系统中用得比较多的一种设备驱动。

在 Linux 内核的include\linux目录下有Miscdevice.h文件,要把自己定义的misc device从设备定义在这里。

其实是因为这些字符设备不符合预先确定的字符设备范畴,所有这些设备采用主编号10,一起归于misc device,其实misc_register就是用主标号10调用register_chrdev()的。

相关主题