当前位置:   article > 正文

petalinux驱动实践:起步篇_petalinux 添加驱动

petalinux 添加驱动

 一 添加驱动

petalinux-create -t modules --name ps-led --enable
  1. lkmao@ubuntu:~/peta_prj/linuxPsBase/petalinux_bsp$ petalinux-create -t modules --name ps-led --enable
  2. INFO: Create modules: ps-led
  3. INFO: New modules successfully created in /home/lkmao/peta_prj/linuxPsBase/petalinux_bsp/project-spec/meta-user/recipes-modules/ps-led
  4. INFO: Enabling created component...
  5. INFO: sourcing build environment
  6. INFO: silentconfig rootfs
  7. INFO: ps-led has been enabled
  8. lkmao@ubuntu:~/peta_prj/linuxPsBase/petalinux_bsp$
 cd project-spec/meta-user/recipes-modules/
  1. lkmao@ubuntu:~/peta_prj/linuxPsBase/petalinux_bsp$ cd project-spec/meta-user/recipes-modules/
  2. lkmao@ubuntu:~/peta_prj/linuxPsBase/petalinux_bsp/project-spec/meta-user/recipes-modules$ tree
  3. .
  4. └── ps-led
  5. ├── files
  6. │   ├── COPYING
  7. │   ├── Makefile
  8. │   └── ps-led.c
  9. ├── ps-led.bb
  10. └── README
  11. 2 directories, 5 files
  12. lkmao@ubuntu:~/peta_prj/linuxPsBase/petalinux_bsp/project-spec/meta-user/recipes-modules$

当前ps-led.c的代码如下:

  1. /* ps-led.c - The simplest kernel module.
  2. * Copyright (C) 2013 - 2016 Xilinx, Inc
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License along
  14. * with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include <linux/kernel.h>
  17. #include <linux/init.h>
  18. #include <linux/module.h>
  19. #include <linux/slab.h>
  20. #include <linux/io.h>
  21. #include <linux/interrupt.h>
  22. #include <linux/of_address.h>
  23. #include <linux/of_device.h>
  24. #include <linux/of_platform.h>
  25. /* Standard module information, edit as appropriate */
  26. MODULE_LICENSE("GPL");
  27. MODULE_AUTHOR
  28. ("Xilinx Inc.");
  29. MODULE_DESCRIPTION
  30. ("ps-led - loadable module template generated by petalinux-create -t modules");
  31. #define DRIVER_NAME "ps-led"
  32. /* Simple example of how to receive command line parameters to your module.
  33. Delete if you don't need them */
  34. unsigned myint = 0xdeadbeef;
  35. char *mystr = "default";
  36. module_param(myint, int, S_IRUGO);
  37. module_param(mystr, charp, S_IRUGO);
  38. struct ps_led_local {
  39. int irq;
  40. unsigned long mem_start;
  41. unsigned long mem_end;
  42. void __iomem *base_addr;
  43. };
  44. static irqreturn_t ps_led_irq(int irq, void *lp)
  45. {
  46. printk("ps-led interrupt\n");
  47. return IRQ_HANDLED;
  48. }
  49. static int ps_led_probe(struct platform_device *pdev)
  50. {
  51. struct resource *r_irq; /* Interrupt resources */
  52. struct resource *r_mem; /* IO mem resources */
  53. struct device *dev = &pdev->dev;
  54. struct ps_led_local *lp = NULL;
  55. int rc = 0;
  56. dev_info(dev, "Device Tree Probing\n");
  57. /* Get iospace for the device */
  58. r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  59. if (!r_mem) {
  60. dev_err(dev, "invalid address\n");
  61. return -ENODEV;
  62. }
  63. lp = (struct ps_led_local *) kmalloc(sizeof(struct ps_led_local), GFP_KERNEL);
  64. if (!lp) {
  65. dev_err(dev, "Cound not allocate ps-led device\n");
  66. return -ENOMEM;
  67. }
  68. dev_set_drvdata(dev, lp);
  69. lp->mem_start = r_mem->start;
  70. lp->mem_end = r_mem->end;
  71. if (!request_mem_region(lp->mem_start,
  72. lp->mem_end - lp->mem_start + 1,
  73. DRIVER_NAME)) {
  74. dev_err(dev, "Couldn't lock memory region at %p\n",
  75. (void *)lp->mem_start);
  76. rc = -EBUSY;
  77. goto error1;
  78. }
  79. lp->base_addr = ioremap(lp->mem_start, lp->mem_end - lp->mem_start + 1);
  80. if (!lp->base_addr) {
  81. dev_err(dev, "ps-led: Could not allocate iomem\n");
  82. rc = -EIO;
  83. goto error2;
  84. }
  85. /* Get IRQ for the device */
  86. r_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
  87. if (!r_irq) {
  88. dev_info(dev, "no IRQ found\n");
  89. dev_info(dev, "ps-led at 0x%08x mapped to 0x%08x\n",
  90. (unsigned int __force)lp->mem_start,
  91. (unsigned int __force)lp->base_addr);
  92. return 0;
  93. }
  94. lp->irq = r_irq->start;
  95. rc = request_irq(lp->irq, &ps_led_irq, 0, DRIVER_NAME, lp);
  96. if (rc) {
  97. dev_err(dev, "testmodule: Could not allocate interrupt %d.\n",
  98. lp->irq);
  99. goto error3;
  100. }
  101. dev_info(dev,"ps-led at 0x%08x mapped to 0x%08x, irq=%d\n",
  102. (unsigned int __force)lp->mem_start,
  103. (unsigned int __force)lp->base_addr,
  104. lp->irq);
  105. return 0;
  106. error3:
  107. free_irq(lp->irq, lp);
  108. error2:
  109. release_mem_region(lp->mem_start, lp->mem_end - lp->mem_start + 1);
  110. error1:
  111. kfree(lp);
  112. dev_set_drvdata(dev, NULL);
  113. return rc;
  114. }
  115. static int ps_led_remove(struct platform_device *pdev)
  116. {
  117. struct device *dev = &pdev->dev;
  118. struct ps_led_local *lp = dev_get_drvdata(dev);
  119. free_irq(lp->irq, lp);
  120. iounmap(lp->base_addr);
  121. release_mem_region(lp->mem_start, lp->mem_end - lp->mem_start + 1);
  122. kfree(lp);
  123. dev_set_drvdata(dev, NULL);
  124. return 0;
  125. }
  126. #ifdef CONFIG_OF
  127. static struct of_device_id ps_led_of_match[] = {
  128. { .compatible = "vendor,ps-led", },
  129. { /* end of list */ },
  130. };
  131. MODULE_DEVICE_TABLE(of, ps_led_of_match);
  132. #else
  133. # define ps_led_of_match
  134. #endif
  135. static struct platform_driver ps_led_driver = {
  136. .driver = {
  137. .name = DRIVER_NAME,
  138. .owner = THIS_MODULE,
  139. .of_match_table = ps_led_of_match,
  140. },
  141. .probe = ps_led_probe,
  142. .remove = ps_led_remove,
  143. };
  144. static int __init ps_led_init(void)
  145. {
  146. printk("<1>Hello module world.\n");
  147. printk("<1>Module parameters were (0x%08x) and \"%s\"\n", myint,
  148. mystr);
  149. return platform_driver_register(&ps_led_driver);
  150. }
  151. static void __exit ps_led_exit(void)
  152. {
  153. platform_driver_unregister(&ps_led_driver);
  154. printk(KERN_ALERT "Goodbye module world.\n");
  155. }
  156. module_init(ps_led_init);
  157. module_exit(ps_led_exit);

Makefile的代码:

  1. obj-m := ps-led.o
  2. MY_CFLAGS += -g -DDEBUG
  3. ccflags-y += ${MY_CFLAGS}
  4. SRC := $(shell pwd)
  5. all:
  6. $(MAKE) -C $(KERNEL_SRC) M=$(SRC)
  7. modules_install:
  8. $(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install
  9. clean:
  10. rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c
  11. rm -f Module.markers Module.symvers modules.order
  12. rm -rf .tmp_versions Modules.symvers

修改ps-led.c文件的代码如下:这是一个最简单的驱动代码,且是平台无关的。

  1. #include <linux/module.h>
  2. #include <linux/init.h>
  3. #define DEBUG_INFO(format,...) printk(KERN_ERR"%s:%d"format"\n",\
  4. __func__,__LINE__,##__VA_ARGS__)
  5. static int __init ps_led_init(void)
  6. {
  7. DEBUG_INFO("init");
  8. printk(KERN_NOTICE"KERN_NOTICE\n");
  9. printk(KERN_WARNING"KERN_WARNING\n");
  10. return 0;
  11. }
  12. static int __exit ps_led_exit(void)
  13. {
  14. DEBUG_INFO("init");
  15. }
  16. module_init(ps_led_init);
  17. module_exit(ps_led_exit);
  18. MODULE_LICENSE("GPL");

在工程目录执行petalinux-build:

  1. lkmao@ubuntu:~/peta_prj/linuxPsBase/petalinux_bsp$ petalinux-build
  2. INFO: sourcing build tools
  3. [INFO] building project
  4. [INFO] sourcing build environment
  5. [INFO] generating user layers
  6. [INFO] generating workspace directory
  7. INFO: bitbake petalinux-image-minimal
  8. Loading cache: 100% |#############################################################################################| Time: 0:00:00
  9. Loaded 4228 entries from dependency cache.
  10. Parsing recipes: 100% |###########################################################################################| Time: 0:00:04
  11. Parsing of 2962 .bb files complete (2959 cached, 3 parsed). 4231 targets, 168 skipped, 0 masked, 0 errors.
  12. NOTE: Resolving any missing task queue dependencies
  13. Initialising tasks: 100% |########################################################################################| Time: 0:00:04
  14. Checking sstate mirror object availability: 100% |################################################################| Time: 0:00:00
  15. Sstate summary: Wanted 149 Found 9 Missed 140 Current 864 (6% match, 86% complete)
  16. NOTE: Executing Tasks
  17. NOTE: Setscene tasks completed
  18. WARNING: device-tree-xilinx-v2020.1+gitAUTOINC+bc84458333-r0 do_package: device-tree: NOT adding alternative provide /boot/device-tree.dtb: /boot/device-tree-999.dtb does not exist
  19. NOTE: u-boot-xlnx: compiling from external source tree /home/lkmao/Downloads/petalinux_offline_pkg/u-boot-xlnx-xilinx-v2020.1
  20. NOTE: Tasks Summary: Attempted 3640 tasks of which 3427 didn't need to be rerun and all succeeded.
  21. Summary: There was 1 WARNING message shown.
  22. INFO: Failed to copy built images to tftp dir: /tftpboot
  23. [INFO] successfully built project
  24. lkmao@ubuntu:~/peta_prj/linuxPsBase/petalinux_bsp$

编译完成后搜索ps-led.ko文件

  1. lkmao@ubuntu:~/peta_prj/linuxPsBase/petalinux_bsp$ find . -name "ps-led.ko"
  2. ./build/tmp/sysroots-components/zynqmp_generic/ps-led/lib/modules/5.4.0/extra/ps-led.ko
  3. lkmao@ubuntu:~/peta_prj/linuxPsBase/petalinux_bsp$

使用 makefile 单独编译驱动

使用petalinux-build编译驱动,很慢,效率很低,常规操作,使用Makefile单独编译驱动:
单独创建一个drivers目录,其中创建ps-led目录,将ps-led.c文件放进去,添加新的Makefile文件,内容如下
  1. modname:=ps-led
  2. obj-m:=$(modname).o
  3. PWD :=$(shell pwd)
  4. MAKE :=make
  5. KERNELDIR = /home/lkmao/peta_prj/linuxPsBase/petalinux_bsp/build/tmp/work-shared/zynqmp-generic/kernel-build-artifacts
  6. CROSS_COMPILE=aarch64-linux-gnu-
  7. ARCH=arm64
  8. all:
  9. $(MAKE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERNELDIR) M=$(PWD) modules
  10. clean:
  11. rm -rf $(modname).ko *.o *mod* \.*cmd *odule* .tmp_versions
  12. .PHONY: all clean

然后使用make编译:

  1. lkmao@ubuntu:~/peta_prj/linuxPsBase/drivers/ps-led$ make
  2. make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -C /home/lkmao/peta_prj/linuxPsBase/petalinux_bsp/build/tmp/work-shared/zynqmp-generic/kernel-build-artifacts M=/home/lkmao/peta_prj/linuxPsBase/drivers/ps-led modules
  3. make[1]: Entering directory '/home/lkmao/peta_prj/linuxPsBase/petalinux_bsp/build/tmp/work-shared/zynqmp-generic/kernel-build-artifacts'
  4. CC [M] /home/lkmao/peta_prj/linuxPsBase/drivers/ps-led/ps-led.o
  5. Building modules, stage 2.
  6. MODPOST 1 modules
  7. CC [M] /home/lkmao/peta_prj/linuxPsBase/drivers/ps-led/ps-led.mod.o
  8. LD [M] /home/lkmao/peta_prj/linuxPsBase/drivers/ps-led/ps-led.ko
  9. make[1]: Leaving directory '/home/lkmao/peta_prj/linuxPsBase/petalinux_bsp/build/tmp/work-shared/zynqmp-generic/kernel-build-artifacts'
  10. lkmao@ubuntu:~/peta_prj/linuxPsBase/drivers/ps-led$ ls
  11. Makefile modules.order Module.symvers ps-led.c ps-led.ko ps-led.mod ps-led.mod.c ps-led.mod.o ps-led.o
  12. lkmao@ubuntu:~/peta_prj/linuxPsBase/drivers/ps-led$

编译后,看到生成了ps-led.ko文件。

 确定内核路径

如何确定内核的路径:petalinux工程中创建一个驱动模块:

petalinux-create -t modules --name ps-led --enable

然后生成的ps-led.c中添加一些错误。使用petalinux-build编译工程,查看报错信息,如下所示,

测试驱动

创建本地挂载目录,配置IP地址,测试网络,挂载NFS服务。

  1. root@petalinux:~# mkdir server
  2. root@petalinux:~# ifconfig eth0 192.168.0.3
  3. root@petalinux:~# ping 192.168.0.111
  4. PING 192.168.0.111 (192.168.0.111): 56 data bytes
  5. 64 bytes from 192.168.0.111: seq=0 ttl=64 time=1.028 ms
  6. 64 bytes from 192.168.0.111: seq=1 ttl=64 time=0.399 ms
  7. ^C
  8. --- 192.168.0.111 ping statistics ---
  9. 2 packets transmitted, 2 packets received, 0% packet loss
  10. round-trip min/avg/max = 0.399/0.713/1.028 ms
  11. root@petalinux:~#
  12. root@petalinux:~# mount -t nfs -o nolock 192.168.0.111:/home/lkmao/work/nfsroot ./server
  13. root@petalinux:~#

 在虚拟机中,将ko文件复制到nfs目录

  1. lkmao@ubuntu:~/peta_prj/linuxPsBase/drivers/ps-led$ cp ps-led.ko ~/work/nfsroot/
  2. lkmao@ubuntu:~/peta_prj/linuxPsBase/drivers/ps-led$

复制完毕后,开发板中就可以看到ko文件了:

  1. root@petalinux:~/server# ls
  2. hello.txt ps-led.ko
  3. root@petalinux:~/server#

insmod加载模块:

  1. root@petalinux:~/server# insmod ps-led.ko
  2. [ 8549.734998] ps_led: loading out-of-tree module taints kernel.
  3. [ 8549.741658] ps_led_init:9init
  4. [ 8549.744631] KERN_NOTICE
  5. [ 8549.747074] KERN_WARNING
  6. root@petalinux:~/server#

lsmod查看模块:

  1. root@petalinux:~/server# lsmod
  2. Tainted: G
  3. ps_led 16384 0 - Live 0xffffffc008b75000 (O)
  4. uio_pdrv_genirq 16384 0 - Live 0xffffffc008b70000
  5. root@petalinux:~/server#

卸载模块:

  1. root@petalinux:~/server# rmmod ps-led.ko
  2. [ 8674.676105] ps_led_exit:17init
  3. root@petalinux:~/server#

小结

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/172247
推荐阅读
相关标签
  

闽ICP备14008679号