Arm开发板(什么是arm开发板)
打开盒子,里面有一张全家福。
包装盒内包含开发板(背板+核心板)、12V2A电源适配器、micro u *** Android数据线、type-c安装数据线和显示线。
开发板的另一个特写视图。
这个开发板有两个版本,一个是内存容量为512MB+512MB的NAND版本,一个是内存容量为512MB+8GB的eMMC版本。我有NAND版,NAND和eMMC开发的程序除了U-boot之外都是一样的,很容易切换。Wildfire i.MX6ULL处理器的主频为800MHz,包含两个 *** 端口,因此很容易对 *** 进行编程。
开发板的配置如上图所示。板载一个HDMI高清视频接口,可以直接连接电脑屏幕,不需要屏幕。内容拆包到此为止。
NFS的环境建设
本文在win10虚拟机上安装ubuntu18.04进行开发,所有的坑和解决方案都是基于这个系统。在ubuntu的终端输入。
sudoapt-getupdatesudoaptinstallnet-toolssudoaptinstallmakegcc-arm-linux-gnueabihfgccbisonflexlibssl-devdpkg-devlzop将ubuntu和开发板连接到同一个路由器上,确保它们的ip在同一个网段上。进入Ubuntu
sudoaptinstallnfs-kernel-server在home/user下设置nfs文件夹,通过以下命令授予权限(我的用户目录是hasee)
sudochmod-R777nfs使用vim命令打开/etc/exports并更改以下内容
保存并重启虚拟机。使用ifconfig查询ubuntu下的原生ip
我的IP: 192.168.2.217通过串口终端连接win10电脑和开发板。我分享一个我经常用的工具,mobxterm _ personal _ 20.6,很强大。谁用谁知道。打开MobaXterm,按照下图操作。
这样就可以操作开发板的终端了。首先,在根目录下的mnt目录中设置nfs文件夹,然后输入pwd返回到以下路径
进入开发板
sudomount-tnfs192.168.2.217:/home/user/nfs/mnt/nfs注意:192.168.2.217这个IP是电脑虚拟机ubuntu的ip/home/user/nfs,虚拟机ubuntu的nfs文件夹路径,/mnt/nfs是开发板中nfs的路径,只要不出现以下提示就表示成功:
编写之一个测试程序。
用ubuntu编写一个简单的测试程序,名为helloworld.c,源代码如下
#include"stdio.h"intmain(intargc,char**argv){printf("helloworld!\n");return0;}执行以下命令进行编译。这里必须使用交叉编译工具,否则无法在开发板上运行:
gcc-arm-linux-gnueabihf-gcchelloworld.c-ohelloworldhelloworld文件将在相同的路径中生成,如下所示
通过cp命令将新的helloworld文件复制到ubuntu的home/user/nfs路径。在win10上用MobaXterm工具操作开发板终端,进入/mnt/nfs路径,找到里面的helloworld文件,执行命令。
./helloworld这意味着程序成功执行,构建的环境可用。前面我们实现了最简单的驱动模板,这次继续探索驱动的编写。驱动代码核心的两个句子是注册模块加载函数module_init()和注册模块卸载函数module_exit()。这次要提的是设备号的申请,角色设备的注册,节点的创建。
应用设备号
申请设备号通常有两种方式:静态申请和动态申请。
静态应用设备号
静态应用设备号的功能原型
intregister_chrdev_region(dev_tfrom,unsignedcount,constchar*name)//参数dev_tfrom:dev_t类型的变量,用于指定字符设备的起始设备号,如果要注册的设备号已经被其他的设备注册了,那么就会导致注册失败。//参数unsignedcount:指定要申请的设备号个数,count的值不可以太大,否则会与下一个主设备号重叠。//参数constchar*name:表示设备名称,我们可以在/proc/devices中看到该设备。//返回值0表示申请成功,返回其它表示失败,并且失败的原因可以通过错误码获取。当使用静态应用程序设备号时,您需要检查使用了内核中的哪些设备号。一旦有重复,设备号申请就会失败,对应的设备注册也不会成功,使用起来非常不方便。
动态应用设备号
动态申请设备号的功能原型
intalloc_chrdev_region(dev_t*dev,unsignedbaseminor,unsignedcount,constchar*name)//参数dev_t*dev:指向dev_t类型数据的指针变量,用于存放分配到的设备编号的起始值;//参数unsignedbaseminor:次设备号的起始值,通常情况下,设置为0;//参数unsignedcount:同register_chrdev_region类型,用于指定需要分配的设备编号的个数以及设备的名称。//返回值0表示申请成功,返回其它表示失败,并且失败的原因可以通过错误码获取。这个函数,内核会自动给我们分配一个未使用的主设备号。不要以为操作起来比静态方便很多。广泛应用于驱动程序开发,尤其是3.x的内核中。
发布设备编号
无论是上面哪种方式申请设备号,都需要使用unregister_chrdev_region()函数来释放设备号。删除设备时调用释放设备号的函数,以便在设备重新注册时提供可用的设备号。如果删除时没有释放,重新添加设备时会报错,导致新设备不可用,从而影响驱动的稳定性。功能原型
voidunregister_chrdev_region(dev_tfrom,unsignedcount)//参数dev_tfrom:指定需要注销的字符设备的设备编号起始值,我们一般将定义的dev_t变量作为实参。//参数unsignedcount:指定需要注销的字符设备编号的个数,该值应与申请函数的count值相等,通常采用宏定义进行管理。以动态和静态综合的方式申请设备编号。
内核中提供了一个函数,可以用于动态应用,也可以用于静态应用。原型如下
staticinlineintregister_chrdev(unsignedintmajor,constchar*name,conststructfile_operations*fops){return__register_chrdev(major,0,256,name,fops);}//参数unsignedintmajor:该参数用于指定要申请的主设备号,相当于静态申请,当该值设为0时,由系统自动分配,相当于动态申请。//参数constchar*name:指定设备的名称。//参数conststructfile_operations*fops:设备的函数接口指针。该函数的发布设备编号函数的原型如下
该函数的释放设备号函数原型如下staticinlinevoidunregister_chrdev(unsignedintmajor,constchar*name){__unregister_chrdev(major,0,256,name);}至于这部分,贴上我的代码。
printk(KERN_EMERG"[KERN_EMERG]HelloModuleInit\n");ret=alloc_chrdev_region(&devno,0,1,"HelloWorld");if(ret==0)printk(KERN_EMERG"[KERN_EMERG]baseminorok\n");elsereturn0;major=MAJOR(devno);minor=MINOR(devno);Cdev操作
初始化
我们用驱动API来关联系统的API,主要是实现file_operations结构,需要cdev_init()函数来操作。
voidcdev_init(structcdev*cdev,conststructfile_operations*fops)//友优资源网cdev:structcdev类型的指针变量,指向需要关联的字符设备结构体;//fops:file_operations类型的结构体指针变量,一般将实现操作该设备的结构体file_operations结构体作为实参。注册
使用以下函数进行注册
intcdev_add(structcdev*p,dev_tdev,unsignedcount)//p:structcdev类型的指针,用于指定需要添加的字符设备;//dev:dev_t类型变量,用于指定设备的起始编号;//count:指定注册多少个设备。只有在注册之后,才能通过后续操作创建设备节点。
取消
voidcdev_del(structcdev*p)//p:structcdev类型的指针,用于指定需要添加的字符设备。//注册和注销是配对的,注销函数实在删除设备时执行的。我的代码的一部分。
cdev_init(&cdev,&fops);ret=cdev_add(&cdev,devno,1);if(ret本文地址:百科常识频道 https://www.neebe.cn/changshi/936623.html,易企推百科一个免费的知识分享平台,本站部分文章来网络分享,本着互联网分享的精神,如有涉及到您的权益,请联系我们删除,谢谢!