千家信息网

linux下am335x点亮LED

发表于:2024-11-11 作者:千家信息网编辑
千家信息网最后更新 2024年11月11日,首先借用一张图说明linux应用程序和内核的关系与裸机程序不同,linux下的应用开发并不直接访问硬件,而是由应用程序调用驱动来访问硬件,这是linux的系统结构,具体可参考《嵌入式linux应用开发
千家信息网最后更新 2024年11月11日linux下am335x点亮LED

首先借用一张图说明linux应用程序和内核的关系

与裸机程序不同,linux下的应用开发并不直接访问硬件,而是由应用程序调用驱动来访问硬件,这是linux的系统结构,具体可参考《嵌入式linux应用开发完全手册》。


回到am335x,已经在uboot实现LED的操作,基本原理一致,设置GPIO输出,低电平点亮LED。如果想通过内核空间操作文件的方式访问GPIO,可参考 BeagleBone的GPIO控制


linux3.2中driver/leds目录下存放有led相关文件,在此编写led驱动模块。代码参照 Am335x 下GPIO控制实例

添加文件leds-run.c

```

#include #include #include #include #include #include #include #include #include #include #define TEST_IO_NUM 89#define NAME_MISC "GpioTest"#define NAME_MOUDULE "GpioTest1"#define USE_MISC_MODE 1static 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 modulestatic const struct file_operations gpio_test_driver = {.owner = THIS_MODULE,.unlocked_ioctl= GpioIOctl,.llseek = no_llseek,.open = GpioOpen,.release = GpioClose,};#if USE_MISC_MODEstatic struct miscdevice gpiotest_misc_device = {.minor = MISC_DYNAMIC_MINOR,.name = NAME_MISC,.fops = &gpio_test_driver,};#endifstatic int __init GpioTestInit(void){int iRet;printk(KERN_INFO"#######GpioTest modules is install!\r\n");#if USE_MISC_MODEiRet = misc_register(&gpiotest_misc_device);if (iRet) {printk(KERN_INFO"#######unable to register a misc device\r\n");return iRet;}#elseiRet = register_chrdev(major, NAME_MOUDULE, &gpio_test_driver);if (iRet < 0) {printk(KERN_INFO"#######unable to register a chr device\r\n");return iRet;}#endifreturn iRet;}static void __exit GpioTestExit(void){#if USE_MISC_MODEmisc_deregister(&gpiotest_misc_device);#elseunregister_chrdev(major, NAME_MOUDULE);#endifprintk(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_LEDbool "Gpio LED test"helpJust test the Gpio LED status

同目录下Makefile文件修改:

obj-$(CONFIG_GPIO_LED)+=leds-run.o

通过make menuconfig,将驱动模块GPIO_LED编译进内核。


应用程序app.c

#include #include #include #include #include #include #include #include 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:

am33xx_cpuidle_init();am33xx_mux_init(board_mux);omap_serial_init();am335x_evm_i2c_init();am335x_evm_setup();omap_sdrc_init(NULL, NULL);usb_musb_init(&musb_board_data);


 static void am335x_evm_setup(){    setup_general_purpose_evm();}


static void setup_general_purpose_evm(void){     _configure_device(boardid,invt_evm_dev_cfg, -1); }

所以初始化开发板的设置,重点就是invt_evm_dev_cfg


static struct evm_dev_cfginvt_evm_dev_cfg[] = {         {enable_ecap0,        DEV_ON_BASEBOARD, PROFILE_NONE},         {lcdc_init,          DEV_ON_BASEBOARD, PROFILE_NONE},         {mfd_tscadc_init,    DEV_ON_BASEBOARD, PROFILE_NONE},         {rmii1_init,       DEV_ON_BASEBOARD, PROFILE_NONE},         {rmii2_init,       DEV_ON_BASEBOARD, PROFILE_NONE},         {usb0_init,        DEV_ON_BASEBOARD, PROFILE_NONE},         {usb1_init,        DEV_ON_BASEBOARD, PROFILE_NONE},         {evm_nand_init,DEV_ON_BASEBOARD,PROFILE_NONE},         {mmc0_init,     DEV_ON_BASEBOARD, PROFILE_NONE},         {spi0_init,         DEV_ON_BASEBOARD, PROFILE_NONE},         {led_init,   DEV_ON_BASEBOARD, PROFILE_NONE},   //添加led操作};


static void led_init(int evm_id, int profile){    int err;    setup_pin_mux(gpio_led_mux);    err = platform_device_register(&leds_gpio);    if (err)    pr_err("failed to register gpio led device\n");}


static struct pinmux_config gpio_led_mux[] = {{"lcd_ac_bias_en.gpio2_25", OMAP_MUX_MODE7 | AM33XX_PIN_OUTPUT},    //LED GPIO 配置{NULL, 0},};

修改完成后,重新编译内核,烧写内核,运行程序,成功实现LED的操作。

0