uClinux+S3C44B0X驱动编写总结

 

uClinux 驱动开发总结

弄了几天,终于成功实现了uClinux 下的驱动,喜悦中……

有收获了就应该总结一下,以便能给日后的工作提供一个参考,并且和想要写uClinux 驱动的朋友们分享一下。

     使用uClinux-2.4 S3C44B0X ARM7 ,在redhat9 上编译,交叉编译工具使用arm-elf-tools

uClinux 版本:uClinux-dist-20060311.tar.gz

arm-elf-tools 版本:arm-elf-tools-20040427.sh

第一天,原来的资料消失了,只能上网搜,根据印象找到了一些有用的。以前有接触过这块板,但是对板上的资源基本没印象了,所以只能结合S3C44B0X 的资料重温一下。今天用汇编写裸机程序,验证了个别引脚的功能和对应的寄存器,下面是第一天做的笔记:

 

LCD 控制 :板子上标有LCD 的插槽, 一共20 根针, 下面是图解:

18

16

14

12

10

8

6

4

2

0

19

17

15

13

11

9

7

5

3

1

 

 

 

VD[7:0] 对应图中07 号引脚,9 号接地

rPCOND[7:0]0x55(output) 时,可以通过rPDATD[3:0] 控制VD[3:0]

rPCONC[7:4]0x55(output) 时,可以通过rPDATC[7:4] 控制VD[7:4]

LED 控制 :当rPCONC[7:2]0x54(0xFC) 时,rPDATC[3:1] 控制3LED

 

有了这些信息,接下来只要把驱动写出来就OK 了。

 

 

第二天,开始写驱动。遇到了一些问题,都记下来了(小菜才会遇到的东西,高手略过吧):

 

今天编译驱动,好久不接触,搞了一个下午才能开始。

出现@led_driver,c,231,0 说明led_driver 驱动没有注册成功

后来发现驱动名不能有字母以外的字符,把led_driver 改成leddriver 后驱动注册成功,相应的文件名也要改成leddriver.c

make menuconfig make dep 只是第一次编译的时候需要执行。

今天未能成功实现驱动。

 

搞了一天,驱动还是没能成功,但是确定了问题出在ioctl

 

 

第三天,几天终于搞定驱动了,写下了ioctl 失败的原因:


昨天编译的驱动没问题,问题在于用户程序调用ioctl 的时候没有使用_IO 宏,就像windows 驱动一样,同样需要一个IOCTL_CODE ,这个参数就不只是一个整数而已,下面是它的结构:

| dir | size | type | nr |

dir: 2bit,命令指示,表示命令类型
size: 14bit,数据大小,通常和第四个参数有关
type: 8bit,类型,又称之为幻数,表示设备的类型
nr: 8bit,命令序号。

各个字段的顺序和位宽可能在不同版本、不同平台的内核中是不同的,写内核模块时应使用内核提供的宏来作处理,而不直接设定。

当然这个cmd的规定对驱动程序来说并不是严格的,也可另起炉灶,但是这不好。

摘至:http://www.yuanma.org/data/2008/1022/article_3252.htm

 

以下是ioctl 的详解:

相对于驱动程序中的ioctl就是应用程序中的ioctl,其原型是:
ioctl (int __fd, unsigned long int __request, ...)

其中int __fd 是已经打开的文件描述符。
int __request 是请求命令字,这是与设备相关的,也就是对应驱动程序ioctl中的cmd
第三个参数依赖于第二个参数,通常是一个指针,或有或无。

同样对应用程序的request的设定也应使用相应的宏来处理,参看 /asm-generic/ioctl.h

下面以ldd3中提供的scull设备为对象,在应用程序中调用ioctl对其进行控制。

int main(void)
{
 int fd = open("/dev/scull",O_RDONLY);
 int qset_size = 2000;

 if(fd<0){
  printf("error/n");
  return 0;
 }

 ioctl(fd, _IO('k',0) ); // 其中k是scull设备的类型
 // 这条命令是复位scull设备中量子和量子集的大小。

 printf("%d/n", ioctl(fd,_IO('k',8) ) ); // 获取默认量子集大小

 ioctl(fd, _IOW('k',2,int), &qset_size ); // 更改量子集大小

 printf("%d/n", ioctl(fd,_IO('k',8) ) );

 close(fd);
 return 0;
}

实际上,这里调用宏函数来设定request,只是为了更清晰的了解如何设定request( 也就是设定驱动程序中的 cmd),
而在应用程序中通常是直接给出其值。比如ioctl(sock, SIOCGIFNAME, &ifr)来获取接口名.

摘至: http://www.yuanma.org/data/2008/1022/article_3252.htm

 

OK ,用了宏之后成功点亮LED ,各个引脚都可以随心所欲地驱动了!

 

 

 

 

 

 

 

我的驱动控制11 个引脚,3LEDVD[7:0] ,其中2LEDuClinux 里面的某个功能冲突了,状态老是被覆盖,解决方法就是去掉该功能。

下面是完整的代码:

 

ioctl头文件:

 

 

驱动代码:

 

 

用户程序代码:

 

 

修改驱动编译配置:

1) 把led_ioctl.h和leddriver.c 丢到目录uClinux-dist/linux-2.4.x/drivers/char中
2) 修改文件  
uClinux-dist/linux-2.4.x/drivers/char/Makefile
----------------------------------------------
obj-$(CONFIG_C5471_WDT) += wdt_c5471.o之后加
obj-$(CONFIG_LED_DRIVER) += leddriver.o
3) 修改文件
uClinux-dist/linux-2.4.x/drivers/char/Config.in
-----------------------------------------
if [ "$CONFIG_CPU_S3C44B0X" = "y" ]; then
   bool 'Samsung S3C44B0X serial ports support' CONFIG_SERIAL_S3C44B0X之后加
   bool 'LED Driver' CONFIG_LED_DRIVER
4) 修改文件
uClinux-dist/linux-2.4.x/drivers/char/mem.c
-----------------------------------------
开头的地方扎堆加
#ifdef CONFIG_LED_DRIVER
extern void led_init(void);
#endif

int __init chr_dev_init(void)之后加
#ifdef CONFIG_LED_DRIVER
led_init();
#endif

5) 继续修改文件
uClinux-dist/vendors/Samsung/44B0/Makefile
-----------------------------------------
ttypc,c,3,12 ttypd,c,3,13 ttype,c,3,14 ttypf,c,3,15/之后加
/
leddriver,c,231,0 /



修改用户程序编译配置:
1) 把use_led.c和led_ioctl.h丢入自己建立的目录uClinux-dist/user/use_led
2) 修改文件
uClinux-dist/user/Makefile
-----------------------------------------
扎堆加个下面
dir_$(CONFIG_USER_USE_LED)   += use_led
3) 修改文件
uClinux-dist/config/Configure.help
-----------------------------------------
扎堆加个下面
CONFIG_USER_USE_LED 
  USE LED
4) 修改文件,就是在最后加上一段
uClinux-dist/config/Configure.in
-----------------------------------------
##############################
mainmenu_option next_comment
comment 'USE LED'

bool 'USE LED' CONFIG_USER_USE_LED
endmenu

###############################


编译
1) make menuconfig  
要选中Kernel和User那两个选项,在kernel中的能找到“LED Driver”选项,勾上,在user中能找到“USE LED”选项,进去后把“USE LED”选上,保存退出。
2) make clean
3) make lib_only
4) make user_only
5) make romfs
6) make image
7) make
我的leddriver.c刚开始有不少问题,make会提示是多少行有问题,然后再回去改,还蛮不错的

# ls uClinux-dist/images/
romfs.img  uclinux_ram.bin.gz  uclinux_rom.bin


烧写
只是我的板子的地址,但基本上差不多,配置好U-BOOT的环境变量之后按照下面步骤:
1) tftp 0x0c008000 uclinux_rom.bin
2) 下载uclinux_rom.bin
3) erase 0x50000 0x1fffff
4) cp 0x0c008000 0x50000 48774
  //48774根据自己载入文件的大小除以4再加2,我是121dcf/4+1的
5) save
6) reset

如果没问题,应该能看到uClinux的界面了,下面在板子中运行
1)cd /dev
2)ls
看见里面有个leddriver了吧?
3)cd /proc
4)cat devices
看见驱动列表吧?
leddriver 231也应该在里面
5)use_led,输入1所有灯亮,输入0所有灯灭

 

 (注:以上过程部分参考网上其他教程)

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值