文章目录
实验环境准备
实验材料:GEC6818实验箱、电脑、
实验环境:VMware下Linux系统、arm-linux-交叉编译环境,windows系统、secureCRT平台
步骤简要说明:
因为需要用到Linux系统环境,所以在Windows下装了个虚拟机,使用虚拟机的环境来开发驱动,并编写了测试驱动的程序,然后把驱动与测试驱动的两个文件传送到实验箱中,接着在实验箱上测试驱动是否可用
第一步:测试三个系统是否连通
- 禁用pc机无线网卡、关闭所有防火墙、使用网线连接PC机与实验箱
- 设置pc机的IP地址(192.168.1.160)、子网掩码(255.255.255.0)
- 设置虚拟机IP地址,在终端下输入:
ifconfig eth0 192.168.1.170
- 设置实验箱IP地址,在secureCRT下,输入:
ifconfig eth0 192.168.1.180
- 然后三个系统之间互相ping一下,看是否能ping通,注意,一定要ping通才能做接下来的实验
第二步:编写并编译好驱动程序和测试驱动的程序
编写直流电机驱动程序dc_motor.c
/*---------------------------------------
*功能描述: 直流电机驱动
*创建者: 粤嵌技术部
*创建时间: 2017,01,01
---------------------------------------
*修改日志:
*修改内容:
*修改人:
*修改时间:
----------------------------------------*/
/*************************************************
*头文件
*************************************************/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <mach/platform.h>
#include <asm/gpio.h>
#define DEVICE_NAME "dc_motor" //设备名字
//电机管脚
static int motor_gpios[] = {
(PAD_GPIO_C + 24),
(PAD_GPIO_C + 25),
};
#define MOTOR_NUM ARRAY_SIZE(motor_gpios) //电机的数量
/*************************************************
*电机初始化
*************************************************/
static void motor_init(void)
{
gpio_set_value(motor_gpios[0], 0);
gpio_set_value(motor_gpios[1], 0);
}
/*************************************************
*电机正传
*************************************************/
static void motor_foreward(void)
{
gpio_set_value(motor_gpios[0], 1);
gpio_set_value(motor_gpios[1], 0);
}
/*************************************************
*电机反转
*************************************************/
static void motor_rollback(void)
{
gpio_set_value(motor_gpios[1], 1);
gpio_set_value(motor_gpios[0], 0);
}
/*************************************************
*电机设备打开
*************************************************/
static int gec6818_motor_open(struct inode *inode, struct file *filp)
{
printk(DEVICE_NAME ":open\n");
motor_init();
return 0;
}
/*************************************************
*电机控制程序
*************************************************/
static long gec6818_motor_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
switch(cmd) {
case 0:
if (arg > MOTOR_NUM) {
return -EINVAL;
}
motor_init();
printk("Motor Stop.\n");
break;
case 1:
if (arg > MOTOR_NUM) {
return -EINVAL;
}
motor_rollback();
printk("Motor Rollback.\n");
break;
case 4:
if (arg > MOTOR_NUM) {
return -EINVAL;
}
motor_foreward();
printk("Motor Foreward.\n");
break;
default:
return -EINVAL;
}
return 0;
}
/*************************************************
*文件操作集
*************************************************/
static struct file_operations gec6818_motor_dev_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = gec6818_motor_ioctl,
.open = gec6818_motor_open
};
/*************************************************
*杂项设备
*************************************************/
static struct miscdevice gec6818_motor_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &gec6818_motor_dev_fops,
};
/********************************************************************
*驱动的初始化函数--->从内核中申请资源(内核、中断、设备号、锁....)
********************************************************************/
static int __init gec6818_motor_dev_init(void)
{
int ret;
int i;
for (i = 0; i < MOTOR_NUM; i++) {
ret = gpio_request(motor_gpios[i], "MOTOR");
if (ret) {
printk("%s: request GPIO %d for MOTOR failed, ret = %d\n", DEVICE_NAME,
motor_gpios[i], ret);
return ret;
}
gpio_direction_output(motor_gpios[i], 0);
}
gpio_set_value(motor_gpios[0], 0);
gpio_set_value(motor_gpios[1], 0);
ret = misc_register(&gec6818_motor_dev);
printk(DEVICE_NAME"\tinitialized\n");
return ret;
}
/*****************************************************************
*驱动退出函数 --->将申请的资源还给内核
*****************************************************************/
static void __exit gec6818_motor_dev_exit(void)
{
int i;
for (i = 0; i < MOTOR_NUM; i++) {
gpio_free(motor_gpios[i]);
}
misc_deregister(&gec6818_motor_dev);
}
module_init(gec6818_motor_dev_init); //驱动的入口函数会调用一个用户的初始化函数
module_exit(gec6818_motor_dev_exit); //驱动的出口函数会调用一个用户的退出函数
//驱动的描述信息: #modinfo *.ko , 驱动的描述信息并不是必需的。
MODULE_AUTHOR("kaoyangou"); //驱动的作者
MODULE_DESCRIPTION("Dc_Motor of driver"); //驱动的描述
MODULE_LICENSE("GPL"); //遵循的协议
编写驱动程序的Makefile文件
INSTALLDIR = /home/Hello
ifneq ($(KERNELRELEASE),)
obj-m:=dc_motor.o
else
KERNELDIR:=/home/Hello/demo/6818GEC/kernel
CROSS_COMPILE:=/home/Hello/demo/6818GEC/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi-
PWD:=$(shell pwd)
default:
mkdir -p $(INSTALLDIR)
$(MAKE) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERNELDIR) M=$(PWD) modules
cp --target-dir=$(INSTALLDIR) dc_motor.ko
clean:
rm -rf *.o *.order .*.cmd *.ko *.mod.c *.symvers
endif
编写驱动测试程序dcMotor_test.c
/*---------------------------------------
*功能描述: 直流电机测试程序
*创建者: 粤嵌技术部
*创建时间: 2015,01,01
---------------------------------------
*修改日志:
*修改内容:
*修改人:
*修改时间:
----------------------------------------*/
/*************************************************
*头文件
*************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PATH "/dev/dc_motor" //绝对路径
/*************************************************
*主函数
*************************************************/
int main(void)
{
int fd;
unsigned int val;
fd = open(PATH, O_RDWR); //打开设备,成功返回0
if (fd < 0) {
perror("Failed to open!\n");
exit(1);
}
do{
printf(" Please select how to operate the DC motor.\n");
printf("0 ->Stop\n");
printf("1 -> Rollback\n");
printf("4 -> Foreward\n");
printf("9 -> Exit!\n");
scanf("%d", &val);
if(val == 9)
break;
ioctl(fd, val, 0);
}while(1);
close(fd);
return 0;
}
编写测试驱动程序的Makefile文件
#
# Makefile for Linux application test example.
#
#---------------------------------------------------------------
# Linux application Makefile sample
# make -- the optical output without debug info
# make clean -- clean the object file(s)
# make install -- install the execute file(s) to INSTALLDIR
#---------------------------------------------------------------
# History:
#
INSTALLDIR = /home/Hello
#--------------------------------- /* execute file(s) */
TESTFILE = dcMotor_test
#--------------------------------- /* object file(s) */
SRCFILE = dcMotor_test.c
#--------------------------------- /* header file(s) */
TESTFILE_H =
CROSS = arm-none-linux-gnueabi-
CC = $(CROSS)gcc
AS = $(CROSS)as
LD = $(CROSS)ld
CFLAGS += -O2 -Wall
all: $(TESTFILE)
$(TESTFILE): $(SRCFILE) $(TESTFILE_H) Makefile
mkdir -p $(INSTALLDIR)
$(CC) $(CFLAGS) -o $@ $@.c
cp --target-dir=$(INSTALLDIR) $(TESTFILE)
clean:
rm -f $(TESTFILE)
第三步:编译生成dc_motor.ko与dcMotor_test二进制执行文件
- 将驱动程序dc_motor.c与其对应Makefile文件放在同一目录下,然后在该目录下执行命令make,生成目标文件dc_motor.ko
注意:Makefile中可能制定了生成的二进制执行文件安装路径:INSTALLDIR = 某某某- 将驱动程序dcMotor_test.c与其对应Makefile文件放在同一目录下,然后在该目录下执行命令make,生成目标文件dcMotor_test
注意:Makefile中可能制定了生成的二进制执行文件安装路径:INSTALLDIR = 某某某
需要知道的是,以上的编译属于交叉编译,Makefile文件中已指定相应的交叉编译器
第四步:将dc_motor.ko文件与dcMotor_test文件挂载到实验箱板子
- 将dc_motor.ko文件与dcMotor_test文件统一放在虚拟机的nfs_share目录上
- 在secureCRT命令框使用mount命令进行挂载,命令中的ip地址是虚拟机的ip地址
mount -o nolock,tcp 192.168.1.170:/home/Hello/nfs_share /mnt
第五步:在实验箱装载驱动并使用程序进行测试
- 在secureCRT中输入命令lsmod,然后回车,在返回的消息中如果找到有dc_motor字眼的一行,则使用rmmod dc_motor进行卸载原有驱动,确保实验箱系统不存在直流电机的驱动程序
lsmod //查看已存在驱动
rmmod dc_motor //卸载dc_motor直流电机的驱动
- 进入到目录 /mnt,然后插入驱动dc_motor.ko,因为刚才把自己制作的驱动挂载到了/mnt目录下
insmod dc_motor.ko
- 测试,输入命令打开直流电机
./dcMotor_test
然后,选择1或4选项,发现直流电机转动,实验成功!