转载的文章只为个人学习与分享,若文章有侵权之处,麻烦与本人联系,本人将及时删除。
嵌入式Linux之我行,主要讲述和总结了本人在学习嵌入式linux中的每个步骤。一为总结经验,二希望能给想入门嵌入式Linux的朋友提供方便。如有错误之处,谢请指正。
·共享资源,欢迎转载:http://hbhuanggang.cublog.cn
一、开发环境
·主 机:VMWare--Fedora 9
·开发板:Mini2440--64MB Nand
·编译器:arm-linux-gcc-4.3.2
二、实现步骤
1. 硬件原理图分析。由原理图得知LED电路是共阳极的,并分别由2440的GPB5、GPB6、GPB7、GPB8口控制的
2. 去掉内核已有的LED驱动设置,因为IO口与mini2440开发板的不一致,根本就不能控制板上的LED。
#gedit arch/arm/plat-s3c24xx/common-smdk.c // 注释掉以下内容
/* LED devices */ /* static struct s3c24xx_led_platdata smdk_pdata_led4 = { .gpio = S3C2410_GPF4, .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE, .name = "led4", .def_trigger = "timer", }; static struct s3c24xx_led_platdata smdk_pdata_led5 = { .gpio = S3C2410_GPF5, .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE, .name = "led5", .def_trigger = "nand-disk", }; static struct s3c24xx_led_platdata smdk_pdata_led6 = { .gpio = S3C2410_GPF6, .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE, .name = "led6", }; static struct s3c24xx_led_platdata smdk_pdata_led7 = { .gpio = S3C2410_GPF7, .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE, .name = "led7", }; static struct platform_device smdk_led4 = { .name = "s3c24xx_led", .id = 0, .dev = { .platform_data = &smdk_pdata_led4, }, }; static struct platform_device smdk_led5 = { .name = "s3c24xx_led", .id = 1, .dev = { .platform_data = &smdk_pdata_led5, }, }; static struct platform_device smdk_led6 = { .name = "s3c24xx_led", .id = 2, .dev = { .platform_data = &smdk_pdata_led6, }, }; static struct platform_device smdk_led7 = { .name = "s3c24xx_led", .id = 3, .dev = { .platform_data = &smdk_pdata_led7, }, };*/
static struct platform_device __initdata * smdk_devs [] = { & s3c_device_nand , /*&smdk_led4, &smdk_led5, &smdk_led6, &smdk_led7,*/ };
void __init smdk_machine_init ( void ) { /* Configure the LEDs (even if we have no LED support)*/ /* s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP); s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP); s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP); s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP); s3c2410_gpio_setpin(S3C2410_GPF4, 1); s3c2410_gpio_setpin(S3C2410_GPF5, 1); s3c2410_gpio_setpin(S3C2410_GPF6, 1); s3c2410_gpio_setpin(S3C2410_GPF7, 1);*/ if ( machine_is_smdk2443 ()) smdk_nand_info . twrph0 = 50 ; s3c_device_nand . dev . platform_data = & smdk_nand_info ; platform_add_devices ( smdk_devs , ARRAY_SIZE ( smdk_devs )); s3c_pm_init (); }
3. 编写适合mini2440开发板的LED驱动,代码如下,文件名称:my2440_leds.c
/* ============================================== Name : my2440_leds.c Author : Huang Gang Date : 05/11/2009 Copyright : GPL Description : my2440 leds driver ============================================== */ # include < linux / kernel . h > # include < linux / module . h > # include < linux / init . h > # include < linux / fs . h > # include < linux / errno . h > # include < mach / hardware . h > # include < mach / regs - gpio . h > # define DEVICE_NAME "my2440_leds" // 设备名称 # define LED_MAJOR 231 // 主设备号 # define LED_ON 1 //LED 亮状态 # define LED_OFF 0 //LED 灭状态 static unsigned long led_table [] = // 控制LED 的IO口 { S3C2410_GPB5 , S3C2410_GPB6 , S3C2410_GPB7 , S3C2410_GPB8 , }; static unsigned int led_cfg_table [] = //LED IO 口的模式 { S3C2410_GPB5_OUTP , S3C2410_GPB6_OUTP , S3C2410_GPB7_OUTP , S3C2410_GPB8_OUTP , }; static int leds_open ( struct inode * inode , struct file * file ) { return 0 ; } static int leds_ioctl ( struct inode * inode , struct file * file , unsigned int cmd , unsigned long arg ) { // 检测是第几个LED ,因开发板上只有4个,索引从0开始 if ( arg < 0 || arg > 3 ) { return - EINVAL ; } // 判断LED 要执行哪种状态 switch ( cmd ) { case LED_ON : { s3c2410_gpio_setpin ( led_table [ arg ], ~( LED_ON )); break ; } case LED_OFF : { s3c2410_gpio_setpin ( led_table [ arg ], ~( LED_OFF )); break ; } default : { return - EINVAL ; } } return 0 ; } static struct file_operations leds_fops = { . owner = THIS_MODULE , . open = leds_open , . ioctl = leds_ioctl , }; static int __init led_init ( void ) { int ret , i ; for ( i = 0 ; i < 4 ; i ++) { // 初始化各IO 口为输出模式 s3c2410_gpio_cfgpin ( led_table [ i ], led_cfg_table [ i ]); // 由原理图可知LED 电路是共阳极的(即各IO口输出低电平0才会点亮) // 这里初始化为1 ,不让LED点亮 s3c2410_gpio_setpin ( led_table [ i ], ~( LED_OFF )); } // 注册LED 设备为字符设备 ret = register_chrdev ( LED_MAJOR , DEVICE_NAME , & leds_fops ); if ( ret < 0 ) { printk ( DEVICE_NAME " register falid!/n" ); return ret ; } } static void __exit led_exit ( void ) { // 注销设备 unregister_chrdev ( LED_MAJOR , DEVICE_NAME ); } module_init ( led_init ); module_exit ( led_exit ); MODULE_LICENSE ( "GPL" ); MODULE_AUTHOR ( "Huang Gang" ); MODULE_DESCRIPTION ( "My2440 led driver" );
4. 把LED驱动代码部署到内核中去
#cp -f my2440_leds.c /linux-2.6.30.4/drivers/char // 把驱动源码复制到内核驱动的字符设备下
#gedit /linux-2.6.30.4/drivers/char/Kconfig // 添加 LED 设备配置
config MY2440_LEDS tristate "My2440 Leds Device" depends on ARCH_S3C2440 default y ---help--- My2440 User Leds
#gedit /linux-2.6.30.4/drivers/char/Makefile // 添加 LED 设备配置
obj-$(CONFIG_MY2440_LEDS) += my2440_leds.o
5. 配置内核,选择LED设备选项
Device Drivers ---> Character devices ---> <*> My2440 Leds Device (NEW)
6. 编译内核并下载到开发板上,查看已加载的设备:#cat /proc/devices,可以看到my2440_leds的主设备号为231
7. 编写应用程序测试LED驱动,文件名:leds_test.c
/* ============================================== Name : leds_test.c Author : Huang Gang Date : 06/11/2009 Copyright : GPL Description : my2440 leds driver test ============================================== */ # include < stdio . h > # include < stdlib . h > # include < fcntl . h > # include < sys / ioctl . h > int main ( int argc , char ** argv ) { int turn , index , fd ; // 检测输入的参数合法性 if ( argc != 3 || sscanf ( argv [ 2 ], "%d" , & index ) != 1 || index < 1 || index > 4 ) { printf ( "Usage: leds_test on|off 1|2|3|4/n" ); exit ( 1 ); } if ( strcmp ( argv [ 1 ], "on" ) == 0 ) { turn = 1 ; } else if ( strcmp ( argv [ 1 ], "off" ) == 0 ) { turn = 0 ; } else { printf ( "Usage: leds_test on|off 1|2|3|4/n" ); exit ( 1 ); } // 打开LED 设备 fd = open ( "/dev/my2440_leds" , 0 ); if ( fd < 0 ) { printf ( "Open Led Device Faild!/n" ); exit ( 1 ); } //IO 控制 ioctl ( fd , turn , index - 1 ); // 关闭LED 设备 close ( fd ); return 0 ; }
8. 在开发主机上交叉编译测试应用程序,并复制到文件系统的/usr/sbin目录下,然后重新编译文件系统下载到开发板上
#arm-linux-gcc -o leds_test leds_test.c
9. 在开发板上的文件系统中创建一个LED设备的节点,然后运行测试程序,效果图如下,观测开发板上的LED灯,可以看到每一步的操作对应的LED会点亮或者熄灭