linux下am335x點亮LED
![](http://i2.51cto.com/images/blog/201807/28/ce7cdc22c42c5b93bd5604c0ba1878db.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
與裸機程序不同,linux下的應用開發並不直接訪問硬件,而是由應用程序調用驅動來訪問硬件,這是linux的系統結構,具體可參考《嵌入式linux應用開發完全手冊》。
回到am335x,已經在uboot實現LED的操作,基本原理一致,設置GPIO輸出,低電平點亮LED。如果想通過內核空間操作文件的方式訪問GPIO,可參考[BeagleBone的GPIO控制 ](http://blog.sina.com.cn/s/blog_9e16dc4d01012x7z.html)
![](http://i2.51cto.com/images/blog/201807/25/3169db826031c0f7bf0be54f26ac0d91.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
linux3.2中driver/leds目錄下存放有led相關文件,在此編寫led驅動模塊。代碼參照[Am335x 下GPIO控制實例](https://blog.csdn.net/hudaweikevin/article/details/16826995)
添加文件leds-run.c
```
#include <linux/gpio.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/moduleparam.h> #include <linux/delay.h> #include <linux/types.h> #include <linux/miscdevice.h> #include <linux/device.h> #include <linux/fs.h> #include <linux/init.h> #define TEST_IO_NUM 89 #define NAME_MISC "GpioTest" #define NAME_MOUDULE "GpioTest1" #define USE_MISC_MODE 1 static int major = 251; void GpioTest(void); static long GpioIOctl(struct file *filp, unsigned cmd, unsigned long arg) { GpioTest(); return 1; } void GpioTest(void) { int iCount = 0; for(iCount = 0; iCount <=20; iCount++ ) { if(iCount%2 == 0) { gpio_direction_output(TEST_IO_NUM, 1); printk(KERN_INFO"#######LED statu is high.\r\n"); } else { gpio_direction_output(TEST_IO_NUM, 0); printk(KERN_INFO"#######LED statu is low.\r\n"); } mdelay(3000); } printk(KERN_INFO"#######App run over!"); } static int GpioOpen(struct inode *inode, struct file *file) { int iRen = -1; iRen = gpio_request(TEST_IO_NUM, "LED"); if(iRen < 0) { printk(KERN_INFO"#######Failed to request the LED!"); }else { printk(KERN_INFO"#######Success to request the LED"); } return iRen; } static int GpioClose(struct inode *inode, struct file *file) { printk(KERN_INFO"#######Free the LED"); gpio_free(TEST_IO_NUM); return 1; } //****entry point for TEST GPIO module static const struct file_operations gpio_test_driver = { .owner = THIS_MODULE, .unlocked_ioctl= GpioIOctl, .llseek = no_llseek, .open = GpioOpen, .release = GpioClose, }; #if USE_MISC_MODE static struct miscdevice gpiotest_misc_device = { .minor = MISC_DYNAMIC_MINOR, .name = NAME_MISC, .fops = &gpio_test_driver, }; #endif static int __init GpioTestInit(void) { int iRet; printk(KERN_INFO"#######GpioTest modules is install!\r\n"); #if USE_MISC_MODE iRet = misc_register(&gpiotest_misc_device); if (iRet) { printk(KERN_INFO"#######unable to register a misc device\r\n"); return iRet; } #else iRet = register_chrdev(major, NAME_MOUDULE, &gpio_test_driver); if (iRet < 0) { printk(KERN_INFO"#######unable to register a chr device\r\n"); return iRet; } #endif return iRet; } static void __exit GpioTestExit(void) { #if USE_MISC_MODE misc_deregister(&gpiotest_misc_device); #else unregister_chrdev(major, NAME_MOUDULE); #endif printk(KERN_INFO"#######GpioTest modules is exit!\r\n"); } module_init(GpioTestInit); module_exit(GpioTestExit); MODULE_AUTHOR("XXXXXXXXXXXX"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("System status led");
```
driver/leds目錄下修改Kconfig,添加一項:
config GPIO_LED bool "Gpio LED test" help Just test the Gpio LED status
同目錄下Makefile文件修改:
obj-$(CONFIG_INPUT_obj-$(CONFIG_GPIO_LED)+=leds-run.o
通過make menuconfig,將驅動模塊GPIO_LED編譯進內核。
應用程序app.c
#include <stdio.h> #include <stdio.h> #include <sys/types.h> #include <sys/ioctl.h> #include <unistd.h> #include <sys/stat.h> #include <linux/input.h> #include <fcntl.h> int main(int argc, char *argv) { int fd; fd = open("/dev/GpioTest", O_RDWR); if(fd < 0) { printf("***Can't open the gpiotest!\r\n"); return -1; } ioctl(fd, 0, 0); close(fd); printf("***App run over!\r\n"); return 1; }
燒寫內核,內核啟動後打印“#######GpioTest modules is install!”,運行app,可以正常運行,可led沒有按照程序進行亮滅操作。
細想整個過程發現,am335x的IO口是復用的,需要先完成mux設置。
再回到linux內核,需要明確linux的運行流程,此次參考了 linux內核代碼分析1 TI am335x:
Board-am335xevm.c(./arch/arm/mach-omap2)中開始執行,
MACHINE_START(AM335XEVM, "am335xevm") /* Maintainer: Texas Instruments */ .atag_offset= 0x100, .map_io= am335x_evm_map_io, .init_early= am33xx_init_early, .init_irq= ti81xx_init_irq, .handle_irq = omap3_intc_handle_irq, .timer= &omap3_am33xx_timer, .init_machine= am335x_evm_init, MACHINE_END
轉到啟動程序am335x_evm_init:
linux下am335x點亮LED