S3C2410——LED灯实验

博客 动态
0 204
羽尘
羽尘 2022-05-07 16:58:54
悬赏:0 积分 收藏

S3C2410——LED灯实验

写在最前面:嵌入式实验,ping不通时一定要先看看网线有没有接通,一般接通都是会有黄绿色色闪烁。

一、S3C2410输入/输出的原理

Linux主要有字符设备、块设备和网络设备3类驱动程序,我们一般编写的驱动都是字符设备驱动程序。

二、程序部分

编写程序控制3个LED灯,代码分为2个部分:控制LED的驱动程序、调用驱动程序的应用程序

1. 控制LED的驱动程序

(1) 常量和结构体的定义:

//定义设备名字,分配设备号时使用#define DEVICE_NAME "UP-LED"//定义次设备号#define LEDRAW_MINOR 0//定义端口C配置寄存器#define GPCCON (*(volatile unsigned int *)S3C2410_GPCCON)//定义端口C数据寄存器#define GPCDAT (*(volatile unsigned int *)S3C2410_GPCDAT)//定义字符设备结构体struct cdev *mycdev;//定义设备号变量,由主设备号和次设备号组成dev_t devno;//文件操作结构体定义使用设备的文件操作static struct file_operations led_fops = {    owner: THIS_MODULE,    ioctl: led_ioctl, //只定义ioctl一个};

(2) 驱动加载时的代码:

//定义加载驱动时执行的函数module_init(led_init);static int __init led_init(void){    int result,err;    //分配字符设备号    result=alloc_chrdev_region(&devno,LEDRAW_MINOR,1,DEVICE_NAME);    if(result < 0)        printk(KERN_ERR "can't get device number \n");    else        printk("get device number\n");    //设置GPC5、GPC6、GPC7为输出状态    GPCCON=(GPCCON|0x5400)&0xffff57ff;    //分配字符设备结构体    mycdev = cdev_alloc();    //初始化结构体,关联文件操作    cdev_init(mycdev,&led_fops);    //将字符设备驱动注册到内核    err=cdev_add(mycdev,devno,1);    if (err < 0)        printk(KERN_ERR "can't add led device");    return 0;}

(3) 定义控制LED的文件操作:

static int led_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){    switch(cmd){        case 1:            if(arg==1) GPCDAT=GPCDAT&0xffffffdf;//第一个led亮            if(arg==0) GPCDAT=GPCDAT|0x20;      //第一个led灭            break;        case 2:            if(arg==1) GPCDAT=GPCDAT&0xffffffbf;//第二个led亮            if(arg==0) GPCDAT=GPCDAT|0x40;      //第二个led灭            break;        case 3:            if(arg==1) GPCDAT=GPCDAT&0xffffff7f;//第三个led亮            if(arg==0) GPCDAT=GPCDAT|0x80;      //第三个led灭            break;        default:            printk("error cmd number\n");break;      }      return 0;}

2. 调用驱动程序的应用程序

//相关头文件的引用#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/ioctl.h>int main(int argc, char **argv){   //相关常量变量定义    int on;    int led_number;    int fd;    //读入命令行参数    sscanf(argv[1], “%d”, &led_number);    sscanf(argv[2],"%d", &on);    //打开设备文件    fd = open("/dev/leds", 0);    if (fd < 0) {         perror("open device /dev/leds");        exit(1);    }    //根据参数操作设备    ioctl(fd, led_number, on);    usleep(1000);    //关闭设备文件    close(fd);    return 0;}

3. makefile文件

ARGET = test_ledCROSS_COMPILE = arm-linuxCC            = $(CROSS_COMPILE)gccifeq ($(KERNELRELEASE),)  KERNELDIR ?= /root/kernel/linux-2.6.24.4  PWD := $(shell pwd)all:   $(TARGET) modules$(TARGET):      $(CC) -o $(TARGET) $(TARGET).cmodules:      $(MAKE) -C $(KERNELDIR) M=$(PWD) modulesclean:      rm -rf *.o *~ *.ko Module.symvers *.mod.c $(TARGET).PHONY:modules cleanelseobj-m := led.oendif

三、实验过程

在主机(虚拟机)上进行交叉编译:

根据makefile编译得到可执行文件test_led。

在主机上输入下面两行代码,将下面的两个文件上传到tftp服务器

cp led.ko /tftpboot/cp test_led /tftpboot/

利用xshell超级终端,在目标机上接收led.ko和test_led文件,并且加载驱动程序

手动创建led设备节点,并给test_led文件可执行权限

实验现象:


posted @ 2022-05-07 16:41 静候佳茵 阅读(8) 评论(0) 编辑 收藏 举报
回帖
    羽尘

    羽尘 (王者 段位)

    2335 积分 (2)粉丝 (11)源码

     

    温馨提示

    亦奇源码

    最新会员