编写测试APP
编写测试APP就是编写Linux应用,需要用到C语言库和上节编写的操作函数。
首先介绍打开函数:
int open(const char *pathname, int flags) |
- pathname:要打开的设备。就是装载驱动后,创建的节点文件,形如 /dev/XXX。
- flags:文件打开方式。O_RDONLY(仅读);O_WRONLY(仅写);O_RDWR(读写)。
- 返回值:文件打开成功就返回文件的描述符。
读写函数:
ssize_t read(int fd, void *buf, size_t count)
ssize_t write(int fd, const void *buf, size_t count);
- fd:要读取的描述符,就是上一个函数的int类型返回值。
- buf:数据存放到这个buf里,让驱动读取此buf。
- count:要读取的数据长度,字节数。
- 返回值:读取成功就返回读取的字节数,返回0就读到文件末尾,返回负值就读取失败。
注意:上一节的XXX_read()和XXX_write()函数是和这里的函数对应的,但是上节的函数传入参数多一个offt参数,表示相对于文件首地址的偏移。这里的函数没有此参数,应该说明不偏移,默认偏移是0。
关闭函数:
int close(int fd);
- fd:要读取的描述符,就是上一个函数的int类型返回值。
int main (int argc, char *argv[])//输入两个参数,argc表示参数个数,argv数组存放每个参数。
{
int fd, value;
char *filename;
if(argc != 3)
return -1; //argv[0]是要运行的此APP,形如 ./xxxAPP
filename = argv[1]; //表示要操作的驱动设备,形如 /dev/XXX
fd = open(filename, O_RDWR);
if(atoi(argv[2]) == 1) //argv[3]是写入的数据
value = read(fd, readbuf, 50);
if(atoi(argv[2]) == 2) //atoi 将字符类型转化为整形
value = write(fd, writebuf, 50);
value = close(fd);
return 0;
}
编译和加载
首先makefile文件的内核源码目录写成自己的,我这里是/home/zch/Linux/uboot/linux-imx。然后obj-m := XXX.o,将自己的c文件编译为ko驱动模块,用于稍后的安装。其他暂时不管。然后终端输入make -j4(4核)就可以编译了!
编译测试APP,这里直接输入命令进行交叉编译。arm-linux-funeabihf-gcc XXXAPP.c -o XXXAPP。机会生成XXXAPP的可执行文件。
此命令详解:
- arm指基于ARM架构。
- inux指ARM架构的Linux系统。如果跑裸机就省略这个,不带操作系统。
- guneabihf可拆解为三项:GUN指自由的操作系统,以GPL发布。上一节最后的LICENSE就是写的GPL。EABI指嵌入式ABI;ABI:二进制应用程序接口(Application Binary Interface (ABI) for the ARM Architecture)。hf表示 armhf架构,用fpu(Float Point Unit,浮点运算单元)计算,传参数也用fpu中的浮点寄存器传,省去转换效率高性能好,但中断负荷高。不加hf是armel架构,用普通寄存器传,中断负荷小,但参数需要转换成浮点型再计算。具体参见arm交叉编译器gnueabi、none-eabi、arm-eabi、gnueabihf等的区别 - 涛少& - 博客园
编译完成后需要把两个文件传入开发板上。这里要挂载nfs,在上位机输入:mount -t nfs -o nolock,vers=3 192.168.10.100:/home/zch/Linux/nfs /home/root/get。即可把nfs文件夹和get文件夹关联,文件放入nfs,get也会有。
驱动文件的操作:
- insmod XXX.ko:可以加载驱动文件。
- modprode XXX.ko:一样。
- lsmod:可查看当前系统中存在的模块。
- cat /proc/devices:查看当前系统中有没有这个设备。
- mknod /dev/XXX c 200 0:创建设备节点文件。mknod命令;/dev/XXX文件;c字符设备;200主设备号;0次设备号。
- ls /dev/XXX -l:查看节点信息。
- rmmod XXX.ko:卸载驱动。